sokobanrb 0.0.3

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.
@@ -0,0 +1,215 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "yaml"
4
+
5
+ module Sokoban1
6
+ class Sokoban
7
+ WALL = "#"
8
+ OPEN_FLOOR = " "
9
+
10
+ MAN = "@"
11
+ CRATE = "o"
12
+
13
+ STORAGE = "."
14
+ MAN_ON_STORAGE = "+"
15
+ CRATE_ON_STORAGE = "*"
16
+
17
+ MAX_UNDO = 10
18
+
19
+ PATH = File.expand_path(File.dirname(__FILE__))
20
+
21
+ attr_reader :level, :moves
22
+
23
+ def self.load( file = File.join(PATH, "sokoban_saved_game.yaml") )
24
+ game = nil
25
+
26
+ File.open file do |f|
27
+ game = YAML.load(f)
28
+ end
29
+
30
+ game ||= Sokoban.new
31
+ game
32
+ end
33
+
34
+ def initialize( file = File.join(PATH, "sokoban_levels.txt") )
35
+ @level_file = file
36
+
37
+ @board = [ ]
38
+ @level = 0
39
+ @over = false
40
+
41
+ @undos = [ ]
42
+ @moves = 0
43
+
44
+ load_level
45
+ end
46
+
47
+ def can_move_down?( ) can_move? :down end
48
+ def can_move_left?( ) can_move? :left end
49
+ def can_move_right?( ) can_move? :right end
50
+ def can_move_up?( ) can_move? :up end
51
+
52
+ def display
53
+ @board.inject("") { |dis, row| dis + row.join + "\n" }
54
+ end
55
+
56
+ def level_solved?
57
+ @board.each_with_index do |row, y|
58
+ row.each_with_index do |cell, x|
59
+ return false if cell == CRATE
60
+ end
61
+ end
62
+ true
63
+ end
64
+
65
+ def load_level( level = @level += 1, file = @level_file )
66
+ loaded = false
67
+
68
+ File.open file do |f|
69
+ count = 0
70
+ while lvl = f.gets("")
71
+ count += 1
72
+ if count == level
73
+ @board = [ ]
74
+ lvl.chomp!
75
+ lvl.each_line { |e| @board << e.chomp.split("") }
76
+ loaded = true
77
+ break
78
+ end
79
+ end
80
+ end
81
+
82
+ if loaded
83
+ @undos = [ ]
84
+ @moves = 0
85
+ else
86
+ @over = true
87
+ end
88
+
89
+ loaded
90
+ end
91
+
92
+ def move_down( ) move :down end
93
+ def move_left( ) move :left end
94
+ def move_right( ) move :right end
95
+ def move_up( ) move :up end
96
+
97
+ def over?
98
+ @over
99
+ end
100
+
101
+ def restart_level
102
+ load_level @level
103
+ end
104
+
105
+ def save( file = File.join(PATH, "sokoban_saved_game.yaml") )
106
+ File.open(file, "w") do |f|
107
+ f << YAML.dump(self)
108
+ end
109
+ end
110
+
111
+ def undo
112
+ if @undos.size > 0
113
+ @board = @undos.pop
114
+ @moves -= 1
115
+ end
116
+ end
117
+
118
+ private
119
+
120
+ def can_move?( dir )
121
+ x, y = where_am_i
122
+ case dir
123
+ when :down
124
+ first = @board[y + 1][x]
125
+ second = y < @board.size - 2 ? @board[y + 2][x] : nil
126
+ when :left
127
+ first = @board[y][x - 1]
128
+ second = x >= 2 ? @board[y][x - 2] : nil
129
+ when :right
130
+ first = @board[y][x + 1]
131
+ second = x < @board[y].size - 2 ? @board[y][x + 2] : nil
132
+ when :up
133
+ first = @board[y - 1][x]
134
+ second = y >= 2 ? @board[y - 2][x] : nil
135
+ end
136
+
137
+ if first == OPEN_FLOOR or first == STORAGE
138
+ true
139
+ elsif not second.nil? and
140
+ (first == CRATE or first == CRATE_ON_STORAGE) and
141
+ (second == OPEN_FLOOR or second == STORAGE)
142
+ true
143
+ else
144
+ false
145
+ end
146
+ end
147
+
148
+ def move( dir )
149
+ return false unless can_move? dir
150
+
151
+ @undos << Marshal.load(Marshal.dump(@board))
152
+ @undos.shift if @undos.size > MAX_UNDO
153
+ @moves += 1
154
+
155
+ x, y = where_am_i
156
+ case dir
157
+ when :down
158
+ if @board[y + 1][x] == CRATE or @board[y + 1][x] == CRATE_ON_STORAGE
159
+ move_crate x, y + 1, x, y + 2
160
+ end
161
+ move_man x, y, x, y + 1
162
+ when :left
163
+ if @board[y][x - 1] == CRATE or @board[y][x - 1] == CRATE_ON_STORAGE
164
+ move_crate x - 1, y, x - 2, y
165
+ end
166
+ move_man x, y, x - 1, y
167
+ when :right
168
+ if @board[y][x + 1] == CRATE or @board[y][x + 1] == CRATE_ON_STORAGE
169
+ move_crate x + 1, y, x + 2, y
170
+ end
171
+ move_man x, y, x + 1, y
172
+ when :up
173
+ if @board[y - 1][x] == CRATE or @board[y - 1][x] == CRATE_ON_STORAGE
174
+ move_crate x, y - 1, x, y - 2
175
+ end
176
+ move_man x, y, x, y - 1
177
+ end
178
+ true
179
+ end
180
+
181
+ def move_crate( from_x, from_y, to_x, to_y )
182
+ if @board[to_y][to_x] == STORAGE
183
+ @board[to_y][to_x] = CRATE_ON_STORAGE
184
+ else
185
+ @board[to_y][to_x] = CRATE
186
+ end
187
+ if @board[from_y][from_x] == CRATE_ON_STORAGE
188
+ @board[from_y][from_x] = STORAGE
189
+ else
190
+ @board[from_y][from_x] = OPEN_FLOOR
191
+ end
192
+ end
193
+
194
+ def move_man( from_x, from_y, to_x, to_y )
195
+ if @board[to_y][to_x] == STORAGE
196
+ @board[to_y][to_x] = MAN_ON_STORAGE
197
+ else
198
+ @board[to_y][to_x] = MAN
199
+ end
200
+ if @board[from_y][from_x] == MAN_ON_STORAGE
201
+ @board[from_y][from_x] = STORAGE
202
+ else
203
+ @board[from_y][from_x] = OPEN_FLOOR
204
+ end
205
+ end
206
+
207
+ def where_am_i
208
+ @board.each_with_index do |row, y|
209
+ row.each_with_index do |cell, x|
210
+ return x, y if cell == MAN or cell == MAN_ON_STORAGE
211
+ end
212
+ end
213
+ end
214
+ end
215
+ end
@@ -0,0 +1,401 @@
1
+
2
+
3
+
4
+
5
+ module Sokoban1
6
+ class Render
7
+ class << self
8
+ attr_accessor :game
9
+
10
+ def render_man
11
+ unless @render_man
12
+ @render_man = glGenLists 1
13
+
14
+ glNewList(@render_man , GL_COMPILE)
15
+
16
+ glMaterialfv GL_FRONT, GL_AMBIENT,convert( [0.0, 0.0, 0.0, 1.0] )
17
+ glMaterialfv GL_FRONT, GL_DIFFUSE,convert( [0.5, 0.0, 0.0, 1.0] )
18
+ glMaterialfv GL_FRONT, GL_SPECULAR,convert( [0.7, 0.6, 0.6, 1.0] )
19
+ #glMaterialfv GL_FRONT, GL_SHININESS, 0.25 * 128.0 unless SHOW_FFI
20
+
21
+ glutSolidSphere 0.5, 16, 16
22
+ glEndList
23
+ end
24
+ glCallList @render_man
25
+ end
26
+
27
+ def render_crate
28
+ unless @render_crate
29
+ @render_crate = glGenLists 1
30
+
31
+ glNewList(@render_crate , GL_COMPILE)
32
+ glMaterialfv GL_FRONT, GL_AMBIENT,convert( [0.19125, 0.0735, 0.0225, 1.0] )
33
+ glMaterialfv GL_FRONT, GL_DIFFUSE,convert( [0.7038, 0.27048, 0.0828, 1.0] )
34
+ glMaterialfv GL_FRONT, GL_SPECULAR,convert( [0.256777, 0.137622, 0.086014, 1.0] )
35
+ #glMaterialfv GL_FRONT, GL_SHININESS, 0.1 * 128.0 unless SHOW_FFI
36
+
37
+ glPushMatrix
38
+ glScalef 0.9, 0.9, 0.9
39
+ glTranslatef 0.0, 0.0, 0.45
40
+
41
+ glutSolidCube 1.0
42
+ glPopMatrix
43
+ glEndList
44
+ end
45
+ glCallList @render_crate
46
+ end
47
+
48
+ def render_stored_crate
49
+ unless @render_stored_crate
50
+ @render_stored_crate = glGenLists 1
51
+
52
+ glNewList(@render_stored_crate , GL_COMPILE)
53
+
54
+ glMaterialfv GL_FRONT, GL_AMBIENT,convert( [0.25, 0.20725, 0.20725, 1.0] )
55
+ glMaterialfv GL_FRONT, GL_DIFFUSE,convert( [1.0, 0.829, 0.829, 1.0] )
56
+ glMaterialfv GL_FRONT, GL_SPECULAR,convert( [0.296648, 0.296648, 0.296648, 1.0] )
57
+ #glMaterialfv GL_FRONT, GL_SHININESS, 0.088 * 128.0 unless SHOW_FFI
58
+
59
+ glPushMatrix
60
+ glScalef 0.9, 0.9, 0.9
61
+ glTranslatef 0.0, 0.0, 0.45
62
+
63
+ glutSolidCube 1.0
64
+ glPopMatrix
65
+ glEndList
66
+ end
67
+ glCallList @render_stored_crate
68
+ end
69
+
70
+ def render_open_floor
71
+
72
+ unless @render_open_floor
73
+ @render_open_floor = glGenLists 1
74
+
75
+ glNewList(@render_open_floor, GL_COMPILE)
76
+
77
+ glMaterialfv GL_FRONT, GL_AMBIENT,convert( [0.05, 0.05, 0.05, 1.0] )
78
+ glMaterialfv GL_FRONT, GL_DIFFUSE,convert( [0.5, 0.5, 0.5, 1.0] )
79
+ glMaterialfv GL_FRONT, GL_SPECULAR,convert( [0.7, 0.7, 0.7, 1.0] )
80
+ #glMaterialfv GL_FRONT, GL_SHININESS, 0.078125 * 128.0
81
+
82
+
83
+
84
+ glPushMatrix
85
+ glScalef 0.9, 0.9, 0.1
86
+ glTranslatef 0.0, 0.0, -0.05
87
+
88
+ glutSolidCube 1.0
89
+ glPopMatrix
90
+
91
+ glMaterialfv GL_FRONT, GL_AMBIENT, convert( [0.05375, 0.05, 0.06625, 1.0] )
92
+ glMaterialfv GL_FRONT, GL_DIFFUSE, convert( [0.18275, 0.17, 0.22525, 1.0] )
93
+ glMaterialfv GL_FRONT, GL_SPECULAR, convert( [0.332741, 0.328634, 0.346435, 1.0] )
94
+ #glMaterialfv GL_FRONT, GL_SHININESS, 0.3 * 128.0 unless SHOW_FFI
95
+
96
+ glPushMatrix
97
+ glScalef 1.0, 1.0, 0.1
98
+ glTranslatef 0.0, 0.0, -0.1
99
+
100
+ glutSolidCube 1.0
101
+ glPopMatrix
102
+ glEndList
103
+ end
104
+ glCallList @render_open_floor
105
+ end
106
+
107
+ def render_storage
108
+
109
+ #glGenLists(1)
110
+ # Make the gears
111
+ unless @render_storage
112
+ puts 'REGISTER IN DISPLAY LIST'
113
+ @render_storage = glGenLists 1
114
+
115
+ glNewList(@render_storage, GL_COMPILE)
116
+ #glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE,@mRED)
117
+ #gear(1.0, 4.0, 1.0, 20, 0.7)
118
+
119
+
120
+ glMaterialfv GL_FRONT, GL_AMBIENT, convert( [0.05, 0.05, 0.0, 1.0] )
121
+ glMaterialfv GL_FRONT, GL_DIFFUSE, convert( [0.5, 0.5, 0.4, 1.0] )
122
+ glMaterialfv GL_FRONT, GL_SPECULAR, convert( [0.7, 0.7, 0.04, 1.0] )
123
+ #glMaterialfv GL_FRONT, GL_SHININESS, 0.078125 * 128.0 unless SHOW_FFI
124
+
125
+
126
+ glPushMatrix
127
+ glScalef 0.9, 0.9, 0.1
128
+ glTranslatef 0.0, 0.0, -0.05
129
+
130
+ glutSolidCube 1.0
131
+ glPopMatrix
132
+
133
+ glMaterialfv GL_FRONT, GL_AMBIENT, convert([0.05375, 0.05, 0.06625, 1.0])
134
+ glMaterialfv GL_FRONT, GL_DIFFUSE, convert([0.18275, 0.17, 0.22525, 1.0])
135
+ glMaterialfv GL_FRONT, GL_SPECULAR, convert([0.332741, 0.328634, 0.346435, 1.0])
136
+ #glMaterialfv GL_FRONT, GL_SHININESS, 0.3 * 128.0 unless SHOW_FFI
137
+
138
+ glPushMatrix
139
+ glScalef 1.0, 1.0, 0.1
140
+ glTranslatef 0.0, 0.0, -0.1
141
+
142
+ glutSolidCube 1.0
143
+ glPopMatrix
144
+
145
+ glEndList()
146
+ end
147
+ #glPushMatrix()
148
+ #glTranslatef(-3.0, -2.0, 0.0)
149
+ #glRotatef(@angle, 0.0, 0.0, 1.0)
150
+ glCallList(@render_storage)
151
+ #glPopMatrix()
152
+
153
+ end
154
+
155
+ def solid_cylinder(radius, height, slices, stacks)
156
+
157
+ glPushAttrib GL_POLYGON_BIT
158
+ glPolygonMode GL_FRONT_AND_BACK, GL_FILL
159
+ obj = gluNewQuadric
160
+ gluCylinder obj, radius, radius, height, slices, stacks
161
+ glPushMatrix
162
+ glTranslatef 0.0, 0.0, height
163
+ gluDisk obj, 0.0, radius, slices, stacks
164
+ glPopMatrix
165
+ gluDeleteQuadric obj
166
+ glPopAttrib
167
+
168
+ end
169
+
170
+ def convert args
171
+ #puts args.class
172
+ if SHOW_FFI
173
+ MemoryPointer.new(:float, 4).put_array_of_float(0, args)
174
+ else
175
+ args
176
+ end
177
+
178
+
179
+
180
+ end
181
+ def render_wall
182
+
183
+ unless @render_wall
184
+ @render_wall = glGenLists 1
185
+
186
+ glNewList(@render_wall , GL_COMPILE)
187
+
188
+ glMaterialfv GL_FRONT, GL_AMBIENT, convert( [0.0, 0.0, 0.0, 1.0])
189
+ glMaterialfv GL_FRONT, GL_DIFFUSE, convert( [0.1, 0.35, 0.1, 1.0])
190
+ glMaterialfv GL_FRONT, GL_SPECULAR, convert( [0.45, 0.55, 0.45, 1.0])
191
+ #glMaterialfv GL_FRONT, GL_SHININESS, 0.25 * 128.0 unless SHOW_FFI
192
+
193
+ glPushMatrix
194
+ glTranslatef 0.0, 0.0, 0.5
195
+
196
+ solid_cylinder 0.45, 1.0, 16, 4
197
+ glPopMatrix
198
+ glEndList
199
+ end
200
+ glCallList @render_wall
201
+ end
202
+
203
+ def keyboard_not_ffi key , x , y
204
+ #= lambda do |key, x, y|
205
+ puts key
206
+ puts x
207
+ puts y
208
+ case key
209
+ when ?c
210
+ exit 0
211
+ when ?s
212
+ @game.save
213
+ #when ?l
214
+ #if test ?e, File.join(PATH, "sokoban_saved_@game.yaml")
215
+ #@game = Sokoban.load
216
+ #end
217
+ when ?r
218
+ @game.restart_level
219
+ when ?n
220
+ @game.load_level
221
+ when ?u
222
+ @game.undo
223
+ when ?j
224
+ @game.move_left
225
+ when ?l
226
+ @game.move_right
227
+ when ?k
228
+ @game.move_down
229
+ when ?i
230
+ #?i, ?I
231
+ @game.move_up
232
+ #puts 'move up'
233
+ when ?q
234
+ exit
235
+ end
236
+
237
+ if @game.level_solved?
238
+ @game.load_level
239
+
240
+ exit 0 if @game.over?
241
+ end
242
+
243
+ glutPostRedisplay
244
+ end
245
+
246
+
247
+ def keyboard_ffi key , x , y
248
+ #= lambda do |key, x, y|
249
+ puts key
250
+ puts x
251
+ puts y
252
+ case key
253
+ when ?c
254
+ exit 0
255
+ when ?s
256
+ @game.save
257
+ #when ?l
258
+ #if test ?e, File.join(PATH, "sokoban_saved_@game.yaml")
259
+ #@game = Sokoban.load
260
+ #end
261
+ when ?r
262
+ @game.restart_level
263
+ when ?n
264
+ @game.load_level
265
+ when ?u
266
+ @game.undo
267
+ when 104
268
+ @game.move_left
269
+ when 107
270
+ @game.move_right
271
+ when 106
272
+ @game.move_down
273
+ when 117
274
+ #?i, ?I
275
+ @game.move_up
276
+ #puts 'move up'
277
+ when 27
278
+ exit
279
+ end
280
+
281
+ if @game.level_solved?
282
+ @game.load_level
283
+
284
+ exit 0 if @game.over?
285
+ end
286
+
287
+ glutPostRedisplay
288
+ end
289
+
290
+
291
+
292
+
293
+ def display2
294
+ #= lambda do
295
+ puts 'render::display2() glClear (..)'
296
+ glClear GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT
297
+
298
+ #GLUT.InitDisplayMode GLUT::SINGLE | GLUT::RGB | GLUT::DEPTH
299
+
300
+ screen = @game.display
301
+ #puts screen.class
302
+ screen = screen.split("\n")
303
+ #puts screen.class
304
+ puts screen
305
+ screen.each_with_index do |row, y|
306
+ row.chomp!
307
+ first = row =~ /^(\s+)/ ? $1.length : 0
308
+ (first...row.length).each do |x|
309
+ glPushMatrix
310
+ glTranslatef 1.0 + x, 17.5 - y, 0.0
311
+
312
+ if row[x, 1] == "." or row[x, 1] == "*" or row[x, 1] == "+"
313
+ render_storage
314
+ else
315
+ render_open_floor
316
+ end
317
+ if row[x, 1] == "@" or row[x, 1] == "+"
318
+ render_man
319
+ elsif row[x, 1] == "o"
320
+ render_crate
321
+ elsif row[x, 1] == "*"
322
+ render_stored_crate
323
+ elsif row[x, 1] == "#"
324
+ render_wall
325
+ end
326
+ glPopMatrix
327
+ end
328
+ end
329
+
330
+ glFlush
331
+ glutSwapBuffers
332
+ end
333
+ def register_glut_with_soko
334
+
335
+ glutDisplayFunc (method(:display2).to_proc)
336
+ #glutIdleFunc(method(:idle).to_proc)
337
+
338
+ glutReshapeFunc (method(:reshape_soko).to_proc)
339
+
340
+ if SHOW_FFI
341
+
342
+ glutKeyboardFunc(method(:keyboard_ffi).to_proc)
343
+ else
344
+
345
+ glutKeyboardFunc(method(:keyboard_not_ffi).to_proc)
346
+ end
347
+
348
+ end
349
+ def init_soko
350
+
351
+ puts 'render think: SHOW_FFI is:'
352
+ puts SHOW_FFI
353
+
354
+ @game = Sokoban.new
355
+ end
356
+ def enable_light_soko
357
+ unless SHOW_FFI
358
+ puts 'Render::senable_light_soko() how ffi'
359
+ glLight GL_LIGHT0, GL_AMBIENT, [0.0, 0.0, 0.0, 1.0]
360
+ glLight GL_LIGHT0, GL_DIFFUSE, [1.0, 1.0, 1.0, 1.0]
361
+ glLight GL_LIGHT0, GL_POSITION, [0.0, 3.0, 3.0, 0.0]
362
+ glLightModel GL_LIGHT_MODEL_AMBIENT, [0.2, 0.2, 0.2, 1.0]
363
+ glLightModel GL_LIGHT_MODEL_LOCAL_VIEWER, [0.0]
364
+ end
365
+
366
+ #GL.FrontFace GL::CW
367
+ #GL.Enable GL::LIGHTING
368
+ #GL.Enable GL::LIGHT0
369
+ #GL.Enable GL::AUTO_NORMAL
370
+ #GL.Enable GL::NORMALIZE
371
+ #GL.Enable GL::DEPTH_TEST
372
+ #GL.DepthFunc GL::LESS
373
+
374
+ glFrontFace GL_CW
375
+ glEnable GL_LIGHTING
376
+ glEnable GL_LIGHT0
377
+ glEnable GL_AUTO_NORMAL
378
+ glEnable GL_NORMALIZE
379
+ glEnable GL_DEPTH_TEST
380
+ glDepthFunc GL_LESS
381
+ end
382
+ # New window size or exposure
383
+ def reshape_soko(width, height)
384
+
385
+ h = height.to_f / width.to_f
386
+ glViewport(0, 0, width, height)
387
+ glMatrixMode(GL_PROJECTION)
388
+ glLoadIdentity()
389
+ glFrustum(-1.0, 1.0, -h, h, 1.5, 20.0)
390
+ glMatrixMode(GL_MODELVIEW)
391
+ glLoadIdentity()
392
+
393
+ gluLookAt 10.0, 10.0, 17.5, 10.0, 10.0, 0.0, 0.0, 1.0, 0.0
394
+ #glTranslatef(0.0, 0.0, -40.0)
395
+ #
396
+ glutPostRedisplay
397
+ end
398
+
399
+ end
400
+ end
401
+ end