ale_ruby_interface 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/ale_ruby_interface.rb +92 -12
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7d5774428a94d5e51002236d6baaeef5c7042d52
|
4
|
+
data.tar.gz: f076b50123171066497e1698ab90d7801cada3bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4eea742eaf9a6bdd04612cd0d50635b255267beef11f355c982be4b17595223c43b25b48ea8756e674dfbb96a213cbb5250632924ce481960822303e9f09506f
|
7
|
+
data.tar.gz: d4eac2d449b0f52a1d6ca68b7d03de446f6c4047fd943a3a116291405f4a1ff51ba72adc409efd90f7d5a82f957f2586ff44e60d5c3b56ca29252e3baefdf2d8
|
data/lib/ale_ruby_interface.rb
CHANGED
@@ -2,11 +2,10 @@ require 'ffi'
|
|
2
2
|
require 'nmatrix'
|
3
3
|
require 'fileutils'
|
4
4
|
|
5
|
+
##
|
6
|
+
# Module for connecting to libale_c.so
|
5
7
|
module ALELib
|
6
8
|
extend FFI::Library
|
7
|
-
# ffi_lib '/Users/happybai/Arcade-Learning-Environment/ale_python_interface/libale_c.so'
|
8
|
-
# ffi_lib File.expand_path(File.join(File.dirname(__FILE__), "lib", "libale_c.so"))
|
9
|
-
# ffi_lib './lib/libale_c.so'
|
10
9
|
ffi_lib File.join(File.dirname(__FILE__), "libale_c.so")
|
11
10
|
attach_function :ALE_new, [], :pointer
|
12
11
|
attach_function :ALE_del, [:pointer], :pointer
|
@@ -56,12 +55,15 @@ module ALELib
|
|
56
55
|
attach_function :setLoggerMode, [:int], :pointer
|
57
56
|
end
|
58
57
|
|
58
|
+
##
|
59
|
+
# This is the main class
|
60
|
+
|
59
61
|
class ALEInterface
|
62
|
+
|
63
|
+
##
|
64
|
+
# initialize method
|
60
65
|
def initialize
|
61
|
-
#
|
62
|
-
# ale_path = ENV['ale_path'] || '/Users/happybai/Arcade-Learning-Environment'
|
63
|
-
# base_path = "#{Dir.pwd}/lib"
|
64
|
-
# Dir.chdir base_path
|
66
|
+
# if ale.cfg doesn't exist, will create one.
|
65
67
|
src = File.join(File.dirname(__FILE__), "ale.cfg")
|
66
68
|
dest = './ale.cfg'
|
67
69
|
if !File.exist?('./ale.cfg')
|
@@ -69,57 +71,84 @@ class ALEInterface
|
|
69
71
|
puts "Created ale.cfg successfully"
|
70
72
|
end
|
71
73
|
@obj = ALELib.ALE_new
|
72
|
-
# Dir.chdir base_path
|
73
74
|
end
|
74
75
|
|
76
|
+
##
|
77
|
+
# Gets the value of any flag passed as parameter that has a string value
|
75
78
|
def get_string(key)
|
76
79
|
ALELib.getString(@obj, key)
|
77
80
|
end
|
78
81
|
|
82
|
+
##
|
83
|
+
# Gets the value of any flag passed as parameter that has an integer value
|
79
84
|
def get_int(key)
|
80
85
|
ALELib.getInt(@obj, key)
|
81
86
|
end
|
82
87
|
|
88
|
+
##
|
89
|
+
# Gets the value of any flag passed as parameter that has a boolean value
|
83
90
|
def get_bool(key)
|
84
91
|
ALELib.getBool(@obj, key)
|
85
92
|
end
|
86
93
|
|
94
|
+
##
|
95
|
+
# Gets the value of any flag passed as parameter that has a float value
|
87
96
|
def get_float(key)
|
88
97
|
ALELib.getFloat(@obj, key)
|
89
98
|
end
|
90
99
|
|
100
|
+
##
|
101
|
+
# Sets the value of any flag that has a string type
|
91
102
|
def set_string(key, value)
|
92
103
|
ALELib.setString(@obj, key, value)
|
93
104
|
end
|
94
105
|
|
106
|
+
##
|
107
|
+
# Sets the value of any flag that has an integer type
|
95
108
|
def set_int(key, value)
|
96
109
|
ALELib.setInt(@obj, key, value)
|
97
110
|
end
|
98
111
|
|
112
|
+
##
|
113
|
+
# Sets the value of any flag that has a boolean type
|
99
114
|
def set_bool(key, value)
|
100
115
|
ALELib.setBool(@obj, key, value)
|
101
116
|
end
|
102
117
|
|
118
|
+
##
|
119
|
+
# Sets the value of any flag that has a float type
|
103
120
|
def set_float(key, value)
|
104
121
|
ALELib.setFloat(@obj, key, value)
|
105
122
|
end
|
106
123
|
|
124
|
+
##
|
125
|
+
# TODO: load_ROM method
|
107
126
|
def load_ROM(rom_file)
|
108
127
|
ALELib.loadROM(@obj, rom_file)
|
109
128
|
end
|
110
129
|
|
130
|
+
##
|
131
|
+
# Applies an action to the game and returns the reward.
|
132
|
+
# It is the user’s responsibility to check if the game has ended and to reset it when necessary (this method will keep pressing buttons on the game over screen).
|
111
133
|
def act(action)
|
112
134
|
ALELib.act(@obj, action.to_i)
|
113
135
|
end
|
114
136
|
|
137
|
+
##
|
138
|
+
# Indicates if the game has ended.
|
115
139
|
def game_over
|
116
140
|
ALELib.game_over(@obj)
|
117
141
|
end
|
118
142
|
|
143
|
+
##
|
144
|
+
# Resets the game, but not the full system (it is not “equivalent” to un- plugging the console from electricity).
|
119
145
|
def reset_game
|
120
146
|
ALELib.game_over(@obj)
|
121
147
|
end
|
122
148
|
|
149
|
+
##
|
150
|
+
# Returns the vector of legal actions (all the 18 actions).
|
151
|
+
# This should be called only after the ROM is loaded.
|
123
152
|
def get_legal_action_set
|
124
153
|
act_size = ALELib.getLegalActionSize(@obj)
|
125
154
|
act = NMatrix.zeros [act_size]
|
@@ -130,6 +159,9 @@ class ALEInterface
|
|
130
159
|
end
|
131
160
|
end
|
132
161
|
|
162
|
+
##
|
163
|
+
# Returns the vector of the minimal set of actions needed to play the game (all actions that have some effect on the game).
|
164
|
+
# This should be called only after the ROM is loaded.
|
133
165
|
def get_minimal_action_set
|
134
166
|
act_size = ALELib.getMinimalActionSize(@obj)
|
135
167
|
act = NMatrix.zeros [act_size]
|
@@ -140,6 +172,9 @@ class ALEInterface
|
|
140
172
|
end
|
141
173
|
end
|
142
174
|
|
175
|
+
##
|
176
|
+
# Returns the vector of modes available for the current game.
|
177
|
+
# This should be called only after the ROM is loaded.
|
143
178
|
def get_available_modes
|
144
179
|
modes_size = ALELib.getAvailableModesSize(@obj)
|
145
180
|
modes = NMatrix.zeros [modes_size]
|
@@ -150,10 +185,16 @@ class ALEInterface
|
|
150
185
|
end
|
151
186
|
end
|
152
187
|
|
188
|
+
##
|
189
|
+
# Sets the mode of the game. The mode must be an available mode (otherwise it throws an exception).
|
190
|
+
# This should be called only after the ROM is loaded.
|
153
191
|
def set_mode(mode)
|
154
192
|
ALELib.set_mode(@obj, mode)
|
155
193
|
end
|
156
194
|
|
195
|
+
##
|
196
|
+
# Returns the vector of difficulties available for the current game.
|
197
|
+
# This should be called only after the ROM is loaded.
|
157
198
|
def get_available_difficulties
|
158
199
|
difficulties_size = ALELib.getAvailableDifficultiesSize(@obj)
|
159
200
|
difficulties = NMatrix.zeros [difficulties_size]
|
@@ -164,28 +205,41 @@ class ALEInterface
|
|
164
205
|
end
|
165
206
|
end
|
166
207
|
|
208
|
+
##
|
209
|
+
# Sets the difficulty of the game. The difficulty must be an available mode (otherwise it throws an exception).
|
210
|
+
# This should be called only after the ROM is loaded.
|
167
211
|
def set_difficulty(difficulty)
|
168
212
|
ALELib.set_mode(@obj, difficulty)
|
169
213
|
end
|
170
214
|
|
215
|
+
##
|
216
|
+
# Returns the current frame number since the loading of the ROM.
|
171
217
|
def get_frame_number
|
172
218
|
ALELib.getFrameNumber(@obj)
|
173
219
|
end
|
174
220
|
|
221
|
+
##
|
222
|
+
# Returns the agent’s remaining number of lives. If the game does not have the concept of lives (e.g. Freeway), this function returns 0.
|
175
223
|
def lives
|
176
224
|
ALELib.lives(@obj)
|
177
225
|
end
|
178
226
|
|
227
|
+
##
|
228
|
+
# Returns the current frame number since the start of the cur- rent episode.
|
179
229
|
def get_episode_frame_number
|
180
230
|
ALELib.getEpisodeFrameNumber(@obj)
|
181
231
|
end
|
182
232
|
|
233
|
+
##
|
234
|
+
# get_screen_dims method
|
183
235
|
def get_screen_dims
|
184
236
|
width = ALELib.getScreenWidth(@obj)
|
185
237
|
height = ALELib.getScreenHeight(@obj)
|
186
238
|
{ width: width, height: height }
|
187
239
|
end
|
188
240
|
|
241
|
+
##
|
242
|
+
# Returns a matrix containing the current game screen.
|
189
243
|
def get_screen(screen_data = nil)
|
190
244
|
# This function fills screen_data with the RAW Pixel data
|
191
245
|
width = ALELib.getScreenWidth(@obj)
|
@@ -201,6 +255,8 @@ class ALEInterface
|
|
201
255
|
end
|
202
256
|
end
|
203
257
|
|
258
|
+
##
|
259
|
+
# This method fills the given vector with a RGB version of the current screen, provided in row, column, then colour channel order (typically yielding 210 × 160 × 3 = 100, 800 entries). The colour channels themselves are, in order: R, G, B. For example, output_rgb_buffer[(160 * 3) * 1 + 52 * 3 + 1] corresponds to the 2nd row, 53rd column pixel’s green value. The vector is resized as needed. Still, for efficiency it is recommended to initialize the vector beforehand, to make sure an allocation is not performed at each time step.
|
204
260
|
def get_screen_RGB()
|
205
261
|
# This function fills screen_data with the data in RGB format
|
206
262
|
width = ALELib.getScreenWidth(@obj)
|
@@ -216,6 +272,8 @@ class ALEInterface
|
|
216
272
|
end
|
217
273
|
end
|
218
274
|
|
275
|
+
##
|
276
|
+
# This method fills the given vector with a grayscale version of the current screen, provided in row- major order (typically yielding 210 × 160 = 33, 600 entries). The vector is resized as needed. For efficiency it is recommended to initialize the vector beforehand, to make sure an allocation is not performed at each time step. Note that the grayscale value corresponds to the pixel’s luminance; for more details, consult the web.
|
219
277
|
def get_screen_grayscale(screen_data = nil)
|
220
278
|
width = ALELib.getScreenWidth(@obj)
|
221
279
|
height = ALELib.getScreenHeight(@obj)
|
@@ -230,10 +288,14 @@ class ALEInterface
|
|
230
288
|
end
|
231
289
|
end
|
232
290
|
|
291
|
+
##
|
292
|
+
# get_RAM_size method
|
233
293
|
def get_RAM_size
|
234
294
|
ALELib.getRAMSize(@obj)
|
235
295
|
end
|
236
296
|
|
297
|
+
##
|
298
|
+
# Returns a vector containing current RAM content (byte-level).
|
237
299
|
def get_RAM()
|
238
300
|
ram_size = ALELib.getRAMSize(@obj)
|
239
301
|
FFI::MemoryPointer.new(:uint64, ram_size) do |p|
|
@@ -246,48 +308,66 @@ class ALEInterface
|
|
246
308
|
end
|
247
309
|
end
|
248
310
|
|
311
|
+
##
|
312
|
+
# Saves the current screen as a png file.
|
249
313
|
def save_screen_PNG(filename)
|
250
314
|
return ALELib.saveScreenPNG(@obj, filename)
|
251
315
|
end
|
252
316
|
|
317
|
+
##
|
318
|
+
# Saves the current state of the system if one wants to be able to recover a state in the future; e.g. in search algorithms.
|
253
319
|
def save_state
|
254
320
|
return ALELib.saveState(@obj)
|
255
321
|
end
|
256
322
|
|
323
|
+
##
|
324
|
+
# Loads a previous saved state of the system once we have a state saved.
|
257
325
|
def load_state
|
258
326
|
return ALELib.loadState(@obj)
|
259
327
|
end
|
260
328
|
|
329
|
+
##
|
330
|
+
# Makes a copy of the environment state. This copy does not include pseudo-randomness, making it suitable for planning purposes. By contrast, see cloneSystemState.
|
261
331
|
def clone_state
|
262
|
-
# This makes a copy of the environment state. This copy does *not*
|
263
|
-
# include pseudorandomness, making it suitable for planning
|
264
|
-
# purposes. By contrast, see cloneSystemState.
|
265
332
|
return ALELib.cloneState(@obj)
|
266
333
|
end
|
267
334
|
|
335
|
+
##
|
336
|
+
# Reverse operation of cloneState(). This does not restore pseudo-randomness, so that repeated calls to restoreState() in the stochastic controls setting will not lead to the same outcomes. By contrast, see restoreSystemState.
|
268
337
|
def restore_state(state)
|
269
338
|
ALELib.restoreState(@obj, state)
|
270
339
|
end
|
271
340
|
|
341
|
+
##
|
342
|
+
# This makes a copy of the system and environment state, suitable for serialization. This includes pseudo-randomness and so is not suitable for planning purposes.
|
272
343
|
def clone_system_state
|
273
344
|
return ALELib.cloneSystemState(@obj)
|
274
345
|
end
|
275
346
|
|
347
|
+
##
|
348
|
+
# Reverse operation of cloneSystemState.
|
276
349
|
def restore_system_state
|
277
350
|
ALELib.restoreSystemState(@obj)
|
278
351
|
end
|
279
352
|
|
353
|
+
##
|
354
|
+
# delete_state method
|
280
355
|
def delete_state(state)
|
281
356
|
ALELib.deleteState(state)
|
282
357
|
end
|
283
358
|
|
359
|
+
##
|
360
|
+
# encode_state_len method
|
284
361
|
def encode_state_len(state)
|
285
362
|
return ALELib.encodeStateLen(state)
|
286
363
|
end
|
287
364
|
|
288
|
-
|
365
|
+
##
|
366
|
+
# encode_staten method
|
289
367
|
def encode_state; end
|
290
368
|
|
369
|
+
##
|
370
|
+
# encode_staten method
|
291
371
|
def decode_state; end
|
292
372
|
|
293
373
|
private
|