sokoban 0.0.18 → 0.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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