sokoban 0.0.18 → 0.0.19
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/sokoban.rb +45 -74
- data/lib/sokoban/version.rb +1 -1
- 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: 80e6f6e337c1eebe994d0bdfced62f199935e06e
|
4
|
+
data.tar.gz: b6da9f42629f9bf123a33f5f9c44fd87cefaa145
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e01076920cdd1dd199223fff53f983bb07a74ac7fe8d8c8402e61c9f19af1b9fc376dc8f525dd88b95454551ef5ff63a1ee8cb86d55cf8745c7b0da5cd58c664
|
7
|
+
data.tar.gz: 6715b40491d31b37e8833046f4919ed3c843b908939eecb40d63b69343baaf267d87424353e79fc65a6a4bb58fdd2f79535a6d34f28c74e0f7b6b66b2feb3ec6
|
data/lib/sokoban.rb
CHANGED
@@ -26,26 +26,11 @@ module Sokoban
|
|
26
26
|
l.gsub(/\n/, '')
|
27
27
|
end
|
28
28
|
|
29
|
-
DIRECTIONS = {
|
30
|
-
W: { x: 0, y: -1 }, # 1
|
31
|
-
A: { x: -1, y: 0 }, # 2
|
32
|
-
S: { x: 0, y: 1 }, # 3
|
33
|
-
D: { x: 1, y: 0 } # 4
|
34
|
-
}
|
35
|
-
|
36
|
-
# Global variables to ease testing
|
37
|
-
# I still like to initialize them even though
|
38
|
-
# nil is the same as false in an if statement
|
39
|
-
$batch, $hax = false, false
|
40
|
-
|
41
|
-
# Game class separates logger and optparse from internal
|
42
|
-
# Level logic and handles level changes and win condition
|
43
29
|
class Game
|
44
30
|
def initialize
|
45
31
|
@level = Level.new
|
46
32
|
parse_opts
|
47
|
-
# --level and --resume may change lnum
|
48
|
-
# set @lnum after parse_opts
|
33
|
+
# --level and --resume opts may change lnum
|
49
34
|
@lnum = @level.lnum
|
50
35
|
play
|
51
36
|
end
|
@@ -115,7 +100,7 @@ module Sokoban
|
|
115
100
|
end
|
116
101
|
|
117
102
|
opts.on("-r", "--resume", "Resume saved game") do
|
118
|
-
@level.
|
103
|
+
@level.load_game
|
119
104
|
@options[:resume] = true
|
120
105
|
end
|
121
106
|
|
@@ -154,15 +139,6 @@ module Sokoban
|
|
154
139
|
@pushes = 0
|
155
140
|
end
|
156
141
|
|
157
|
-
def moves
|
158
|
-
@moves.size
|
159
|
-
end
|
160
|
-
|
161
|
-
# The public interface to initialize()
|
162
|
-
def restart(lnum)
|
163
|
-
initialize(lnum)
|
164
|
-
end
|
165
|
-
|
166
142
|
def play
|
167
143
|
while free_boxes > 0
|
168
144
|
print self
|
@@ -185,43 +161,15 @@ module Sokoban
|
|
185
161
|
STDIN.getch
|
186
162
|
end
|
187
163
|
|
188
|
-
def free_boxes
|
189
|
-
@level.scan(/o/).size
|
190
|
-
end
|
191
|
-
|
192
|
-
def inspect
|
193
|
-
s = "Level: #{@lnum} Moves: #{@moves.size} Pushes: #{@pushes} "
|
194
|
-
s << @moves.map {|m| DIRECTIONS.keys[m - 1].to_s }.join
|
195
|
-
end
|
196
|
-
|
197
|
-
def to_s
|
198
|
-
clear_screen
|
199
|
-
s = "Level: #{@lnum}\n\n"
|
200
|
-
s << (0...16).map {|i| @level[i * 19, 19] }.join("\n")
|
201
|
-
s << "\nMoves: #{@moves.size} Pushes: #{@pushes}\n> "
|
202
|
-
end
|
203
|
-
|
204
|
-
def load_saved_game
|
205
|
-
file = Zlib::GzipReader.open(SAV_FILE) {|f| f.read }
|
206
|
-
file = file.unpack('C' * file.size)
|
207
|
-
# Initialize Level with @lnum from file
|
208
|
-
@lnum = file.shift
|
209
|
-
initialize(@lnum)
|
210
|
-
# Rebuild @moves
|
211
|
-
moves = []
|
212
|
-
file.map {|c| moves << unpack_nibs(c) }
|
213
|
-
moves.flatten.map {|m| move(DIRECTIONS.keys[m - 1]) }
|
214
|
-
end
|
215
|
-
|
216
164
|
def parse_move(input)
|
217
165
|
# Handle multiple moves
|
218
166
|
input.each_char {|c| parse_move(c) } if input.size > 1
|
219
167
|
case input.downcase
|
220
168
|
when 'b'; $batch = ! $batch
|
221
|
-
when 'w', 'k', '8'; move(:W) #
|
222
|
-
when 'a', 'h', '4'; move(:A) #
|
223
|
-
when 's', 'j', '2'; move(:S) #
|
224
|
-
when 'd', 'l', '6'; move(:D) #
|
169
|
+
when 'w', 'k', '8'; move(:W) # up
|
170
|
+
when 'a', 'h', '4'; move(:A) # left
|
171
|
+
when 's', 'j', '2'; move(:S) # down
|
172
|
+
when 'd', 'l', '6'; move(:D) # right
|
225
173
|
when 'r'; initialize(@lnum)
|
226
174
|
when 'u'; undo
|
227
175
|
when 'q'; quit
|
@@ -229,29 +177,46 @@ module Sokoban
|
|
229
177
|
end
|
230
178
|
end
|
231
179
|
|
232
|
-
|
180
|
+
def free_boxes
|
181
|
+
@level.scan(/o/).size
|
182
|
+
end
|
233
183
|
|
234
|
-
def
|
235
|
-
|
184
|
+
def moves
|
185
|
+
@moves.size
|
186
|
+
end
|
187
|
+
|
188
|
+
# The public interface to initialize()
|
189
|
+
def restart(lnum)
|
190
|
+
initialize(lnum)
|
191
|
+
end
|
192
|
+
|
193
|
+
def inspect
|
194
|
+
s = "Level: #{@lnum} Moves: #{moves} Pushes: #{@pushes} "
|
195
|
+
s << @moves.join
|
236
196
|
end
|
237
197
|
|
238
|
-
def
|
239
|
-
|
198
|
+
def to_s
|
199
|
+
clear_screen
|
200
|
+
s = "Level: #{@lnum}\n\n"
|
201
|
+
s << (0...16).map {|i| @level[i * 19, 19] }.join("\n")
|
202
|
+
s << "\nMoves: #{moves} Pushes: #{@pushes}\n> "
|
240
203
|
end
|
241
204
|
|
242
|
-
def
|
243
|
-
|
244
|
-
|
205
|
+
def load_game
|
206
|
+
file = Zlib::GzipReader.open(SAV_FILE) {|f| f.read }
|
207
|
+
initialize(file.slice!(/\d+/).to_i) # Init @lnum
|
208
|
+
file.each_char {|c| move(c.to_sym) } # Rebuild @moves
|
245
209
|
end
|
246
210
|
|
211
|
+
private
|
212
|
+
|
247
213
|
def save_game
|
248
|
-
file = [@lnum]
|
249
|
-
# @moves are 1, 2, 3, or 4 to enable easy bit packing
|
250
|
-
@moves.each_slice(2) {|s| file << pack_nibs(s[0], s[1]) }
|
251
|
-
file = file.pack('C' * file.size)
|
252
|
-
# Gzip becomes space-efficient when @moves is ~99
|
214
|
+
file = ([@lnum] << @moves).flatten.join
|
253
215
|
Zlib::GzipWriter.open(SAV_FILE) {|f| f.write(file) }
|
254
|
-
|
216
|
+
end
|
217
|
+
|
218
|
+
def clear_screen
|
219
|
+
30.times { puts }
|
255
220
|
end
|
256
221
|
|
257
222
|
def undo
|
@@ -298,6 +263,13 @@ module Sokoban
|
|
298
263
|
@level[x + y * 19] = v
|
299
264
|
end
|
300
265
|
|
266
|
+
DIRECTIONS = {
|
267
|
+
W: { x: 0, y: -1 },
|
268
|
+
A: { x: -1, y: 0 },
|
269
|
+
S: { x: 0, y: 1 },
|
270
|
+
D: { x: 1, y: 0 }
|
271
|
+
}
|
272
|
+
|
301
273
|
def move(direction)
|
302
274
|
x, y = find_player
|
303
275
|
dx = DIRECTIONS[direction][:x]
|
@@ -326,8 +298,7 @@ module Sokoban
|
|
326
298
|
self[x + dx, y + dy] = (dest == ' ') ? '@' : '+'
|
327
299
|
# Update previous position
|
328
300
|
self[x, y] = (self[x, y] == '@') ? ' ' : '.'
|
329
|
-
|
330
|
-
@moves << DIRECTIONS.keys.index(direction) + 1
|
301
|
+
@moves << direction.to_s
|
331
302
|
# Save a copy of the level in case of undo
|
332
303
|
@state << @level.dup
|
333
304
|
end
|
data/lib/sokoban/version.rb
CHANGED