-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathale_interface.hpp
246 lines (206 loc) · 7.86 KB
/
ale_interface.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
/* *****************************************************************************
* A.L.E (Arcade Learning Environment)
* Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare,
* Matthew Hausknecht, and the Reinforcement Learning and Artificial Intelligence
* Laboratory
* Released under the GNU General Public License; see License.txt for details.
*
* Based on: Stella -- "An Atari 2600 VCS Emulator"
* Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team
*
* *****************************************************************************
* ale_interface.hpp
*
* The shared library interface.
**************************************************************************** */
#ifndef __ALE_INTERFACE_HPP__
#define __ALE_INTERFACE_HPP__
#include "emucore/FSNode.hxx"
#include "emucore/OSystem.hxx"
#include "os_dependent/SettingsWin32.hxx"
#include "os_dependent/OSystemWin32.hxx"
#include "os_dependent/SettingsUNIX.hxx"
#include "os_dependent/OSystemUNIX.hxx"
#include "games/Roms.hpp"
#include "common/Defaults.hpp"
#include "common/display_screen.h"
#include "environment/stella_environment.hpp"
// @todo
static const std::string Version = "0.4";
// Display welcome message
static std::string welcomeMessage() {
// ALE welcome message
std::ostringstream oss;
oss << "A.L.E: Arcade Learning Environment (version "
<< Version << ")\n"
<< "[Powered by Stella]\n"
<< "Use -help for help screen.";
return oss.str();
}
static void disableBufferedIO() {
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stdin, NULL, _IONBF, 0);
cin.rdbuf()->pubsetbuf(0,0);
cout.rdbuf()->pubsetbuf(0,0);
cin.sync_with_stdio();
cout.sync_with_stdio();
}
static void createOSystem(int argc, char* argv[],
std::auto_ptr<OSystem> &theOSystem,
std::auto_ptr<Settings> &theSettings) {
#ifdef WIN32
theOSystem.reset(new OSystemWin32());
theSettings.reset(new SettingsWin32(theOSystem.get()));
#else
theOSystem.reset(new OSystemUNIX());
theSettings.reset(new SettingsUNIX(theOSystem.get()));
#endif
setDefaultSettings(theOSystem->settings());
theOSystem->settings().loadConfig();
// process commandline arguments, which over-ride all possible config file settings
string romfile = theOSystem->settings().loadCommandLine(argc, argv);
// Load the configuration from a config file (passed on the command
// line), if provided
string configFile = theOSystem->settings().getString("config", false);
if (!configFile.empty())
theOSystem->settings().loadConfig(configFile.c_str());
theOSystem->settings().validate();
theOSystem->create();
string outputFile = theOSystem->settings().getString("output_file", false);
if (!outputFile.empty()) {
cerr << "Redirecting ... " << outputFile << endl;
freopen(outputFile.c_str(), "w", stdout);
}
// attempt to load the ROM
if (argc == 1 || romfile == "" || !FilesystemNode::fileExists(romfile)) {
std::cerr << "No ROM File specified or the ROM file was not found." << std::endl;
exit(1);
} else if (theOSystem->createConsole(romfile)) {
std::cerr << "Running ROM file..." << std::endl;
theOSystem->settings().setString("rom_file", romfile);
} else {
exit(1);
}
// seed random number generator
if (theOSystem->settings().getString("random_seed") == "time") {
cerr << "Random Seed: Time" << endl;
srand((unsigned)time(0));
//srand48((unsigned)time(0));
} else {
int seed = theOSystem->settings().getInt("random_seed");
assert(seed >= 0);
cerr << "Random Seed: " << seed << endl;
srand((unsigned)seed);
//srand48((unsigned)seed);
}
theOSystem->console().setPalette("standard");
}
/**
This class interfaces ALE with external code for controlling agents.
*/
class ALEInterface
{
public:
std::auto_ptr<OSystem> theOSystem;
std::auto_ptr<Settings> theSettings;
std::auto_ptr<RomSettings> settings;
std::auto_ptr<StellaEnvironment> environment;
protected:
reward_t episode_score; // Score accumulated throughout the course of an episode
bool display_active; // Should the screen be displayed or not
int max_num_frames; // Maximum number of frames for each episode
public:
ALEInterface(bool display_screen=false): episode_score(0), display_active(display_screen) {
#ifndef __USE_SDL
if (display_active) {
cout << "Screen display requires directive __USE_SDL to be defined." << endl;
cout << "Please recompile this code with flag '-D__USE_SDL'." << endl;
cout << "Also ensure ALE has been compiled with USE_SDL active (see ALE makefile)." << endl;
exit(0);
}
#endif
disableBufferedIO();
std::cerr << welcomeMessage() << endl;
}
~ALEInterface() {}
// Loads and initializes a game. After this call the game should be ready to play.
void loadROM(string rom_file) {
int argc = 6;
char** argv = new char*[argc];
for (int i=0; i<=argc; i++) {
argv[i] = new char[200];
}
strcpy(argv[0],"./ale");
strcpy(argv[1],"-player_agent");
strcpy(argv[2],"random_agent");
strcpy(argv[3],"-display_screen");
if (display_active) strcpy(argv[4],"true");
else strcpy(argv[4],"false");
strcpy(argv[5],rom_file.c_str());
createOSystem(argc, argv, theOSystem, theSettings);
settings.reset(buildRomRLWrapper(rom_file));
environment.reset(new StellaEnvironment(theOSystem.get(), settings.get()));
max_num_frames = theOSystem->settings().getInt("max_num_frames_per_episode");
reset_game();
}
// Resets the game
void reset_game() {
environment->reset();
}
// Indicates if the game has ended
bool game_over() {
return (environment->isTerminal() || (max_num_frames > 0 && getEpisodeFrameNumber() >= max_num_frames));
}
// Applies an action to the game and returns the reward. It is the user's responsibility
// to check if the game has ended and reset when necessary - this method will keep pressing
// buttons on the game over screen.
reward_t act(Action action) {
reward_t reward = environment->act(action, PLAYER_B_NOOP);
if (display_active)
theOSystem->p_display_screen->display_screen(theOSystem->console().mediaSource());
return reward;
}
// Returns the vector of legal actions. This should be called only after the rom is loaded.
ActionVect getLegalActionSet() {
return settings->getAllActions();
}
// Returns the vector of the minimal set of actions needed to play the game.
ActionVect getMinimalActionSet() {
return settings->getMinimalActionSet();
}
// Returns the frame number since the loading of the ROM
int getFrameNumber() {
return environment->getFrameNumber();
}
// Returns the frame number since the start of the current episode
int getEpisodeFrameNumber() {
return environment->getEpisodeFrameNumber();
}
// Sets the episodic frame limit
void setMaxNumFrames(int newMax) {
max_num_frames = newMax;
}
// Returns the current game screen
const ALEScreen &getScreen() {
return environment->getScreen();
}
// Returns the current RAM content
const ALERAM &getRAM() {
return environment->getRAM();
}
// Saves the state of the system
void saveState() {
environment->save();
}
// Loads the state of the system
void loadState() {
environment->load();
}
ALEState cloneState() {
return environment->cloneState();
}
void restoreState(const ALEState& state) {
return environment->restoreState(state);
}
};
#endif