sokoban.rb 0.0.1
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.
- data/.README.swp +0 -0
- data/.gitignore +5 -0
- data/.rvmrc +3 -0
- data/Gemfile +4 -0
- data/README +39 -0
- data/Rakefile +1 -0
- data/bin/.gears3.rb.swp +0 -0
- data/bin/.opengl_sokoban.rb.swp +0 -0
- data/bin/.sokoban.swp +0 -0
- data/bin/ignore_me_unix_term_sokoban.rb +266 -0
- data/bin/original_opengl_sokoban.rb +236 -0
- data/bin/run +11 -0
- data/bin/sokoban +485 -0
- data/lib/sokoban/config.rb +22 -0
- data/lib/sokoban/game_engine.rb +215 -0
- data/lib/sokoban/render.rb +401 -0
- data/lib/sokoban/sokoban_levels.txt +760 -0
- data/lib/sokoban/sokoban_saved_game.yaml +1821 -0
- data/lib/sokoban.rb +10 -0
- data/sokoban.gemspec +33 -0
- data/spec/sokoban/board_spec.rb +477 -0
- data/spec/spec_helper.rb +10 -0
- data/test/sokoban/board_test.rb +38 -0
- data/test/sokoban/tc_moveable.rb +41 -0
- data/test/test_helper.rb +28 -0
- metadata +108 -0
data/bin/sokoban
ADDED
@@ -0,0 +1,485 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
|
4
|
+
#######################################
|
5
|
+
#about switching SHOW_FFI :
|
6
|
+
#if working with ruby 1.9.1-p376 + gem: ruby-opengl :
|
7
|
+
#read: http://rubygamedev.wordpress.com/2010/04/16/ruby-opengl-on-ruby-1-9/
|
8
|
+
#
|
9
|
+
#if working with ruby 1.9.2 + gem: ffi-opengl + stil buggy(for me..)
|
10
|
+
|
11
|
+
########################################
|
12
|
+
|
13
|
+
SHOW_GEARS = false #to show the original ffi-opengl gears example OR the sokoban game
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
# some undeleted notes from original creator of the original sokoban project:
|
20
|
+
##########################################################################
|
21
|
+
# 3-D gear wheels. This program is in the public domain.
|
22
|
+
#
|
23
|
+
# Command line options:
|
24
|
+
# -info print GL implementation information
|
25
|
+
# -exit automatically exit after 30 seconds
|
26
|
+
#
|
27
|
+
# 2005-05-01 Ruby version by Arto Bendiken based on gears.c rev 1.8.
|
28
|
+
# 2005-01-09 Original C version (gears.c) by Brian Paul et al.
|
29
|
+
# http://cvs.freedesktop.org/mesa/Mesa/progs/demos/gears.c?rev=1.8
|
30
|
+
###########################################################################
|
31
|
+
|
32
|
+
|
33
|
+
#$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")))
|
34
|
+
#require 'ffi-opengl'
|
35
|
+
|
36
|
+
#require './render'
|
37
|
+
|
38
|
+
|
39
|
+
def convertf args
|
40
|
+
if SHOW_FFI
|
41
|
+
MemoryPointer.new(:float, 4).put_array_of_float(0,args )
|
42
|
+
else
|
43
|
+
args
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class Gears
|
48
|
+
attr_accessor :mPOS , :mRED , :mGREEN , :mBLUE
|
49
|
+
#include FFI, GL, GLU, GLUT, Math
|
50
|
+
|
51
|
+
#include Render
|
52
|
+
#unless SHOW_GEARS
|
53
|
+
|
54
|
+
|
55
|
+
|
56
|
+
#end
|
57
|
+
|
58
|
+
#puts 'create Constants for color with ffi pointer array'
|
59
|
+
#POS = MemoryPointer.new(:float, 4).put_array_of_float(0, [5.0, 5.0, 10.0, 0.0])
|
60
|
+
#RED = MemoryPointer.new(:float, 4).put_array_of_float(0, [0.8, 0.1, 0.0, 1.0])
|
61
|
+
#GREEN = MemoryPointer.new(:float, 4).put_array_of_float(0, [0.0, 0.8, 0.2, 1.0])
|
62
|
+
#BLUE = MemoryPointer.new(:float, 4).put_array_of_float(0, [0.2, 0.2, 1.0, 1.0])
|
63
|
+
|
64
|
+
|
65
|
+
#puts self.POS
|
66
|
+
#include Math
|
67
|
+
|
68
|
+
# Draw a gear wheel. You'll probably want to call this function when
|
69
|
+
# building a display list since we do a lot of trig here.
|
70
|
+
#
|
71
|
+
# Input: inner_radius - radius of hole at center
|
72
|
+
# outer_radius - radius at center of teeth
|
73
|
+
# width - width of gear
|
74
|
+
# teeth - number of teeth
|
75
|
+
# tooth_depth - depth of tooth
|
76
|
+
def gear(inner_radius, outer_radius, width, teeth, tooth_depth)
|
77
|
+
r0 = inner_radius
|
78
|
+
r1 = outer_radius - tooth_depth / 2.0
|
79
|
+
r2 = outer_radius + tooth_depth / 2.0
|
80
|
+
|
81
|
+
da = 2.0 * PI / teeth / 4.0
|
82
|
+
|
83
|
+
glShadeModel(GL_FLAT)
|
84
|
+
|
85
|
+
glNormal3f(0.0, 0.0, 1.0)
|
86
|
+
|
87
|
+
# Draw front face
|
88
|
+
glBegin(GL_QUAD_STRIP)
|
89
|
+
for i in 0..teeth
|
90
|
+
angle = i * 2.0 * PI / teeth
|
91
|
+
glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5)
|
92
|
+
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5)
|
93
|
+
if i < teeth
|
94
|
+
glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5)
|
95
|
+
glVertex3f(r1 * cos(angle + 3 * da),
|
96
|
+
r1 * sin(angle + 3 * da), width * 0.5)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
glEnd()
|
100
|
+
|
101
|
+
# Draw front sides of teeth
|
102
|
+
glBegin(GL_QUADS)
|
103
|
+
for i in 0...teeth
|
104
|
+
angle = i * 2.0 * PI / teeth
|
105
|
+
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5)
|
106
|
+
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5)
|
107
|
+
glVertex3f(r2 * cos(angle + 2 * da),
|
108
|
+
r2 * sin(angle + 2 * da), width * 0.5)
|
109
|
+
glVertex3f(r1 * cos(angle + 3 * da),
|
110
|
+
r1 * sin(angle + 3 * da), width * 0.5)
|
111
|
+
end
|
112
|
+
glEnd()
|
113
|
+
|
114
|
+
glNormal3f(0.0, 0.0, -1.0)
|
115
|
+
|
116
|
+
# Draw back face
|
117
|
+
glBegin(GL_QUAD_STRIP)
|
118
|
+
for i in 0..teeth
|
119
|
+
angle = i * 2.0 * PI / teeth
|
120
|
+
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5)
|
121
|
+
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5)
|
122
|
+
if i < teeth
|
123
|
+
glVertex3f(r1 * cos(angle + 3 * da),
|
124
|
+
r1 * sin(angle + 3 * da), -width * 0.5)
|
125
|
+
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
glEnd()
|
129
|
+
|
130
|
+
# Draw back sides of teeth
|
131
|
+
glBegin(GL_QUADS)
|
132
|
+
for i in 0...teeth
|
133
|
+
angle = i * 2.0 * PI / teeth
|
134
|
+
glVertex3f(r1 * cos(angle + 3 * da),
|
135
|
+
r1 * sin(angle + 3 * da), -width * 0.5)
|
136
|
+
glVertex3f(r2 * cos(angle + 2 * da),
|
137
|
+
r2 * sin(angle + 2 * da), -width * 0.5)
|
138
|
+
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5)
|
139
|
+
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5)
|
140
|
+
end
|
141
|
+
glEnd()
|
142
|
+
|
143
|
+
# Draw outward faces of teeth
|
144
|
+
glBegin(GL_QUAD_STRIP)
|
145
|
+
for i in 0...teeth
|
146
|
+
angle = i * 2.0 * PI / teeth
|
147
|
+
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5)
|
148
|
+
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5)
|
149
|
+
u = r2 * cos(angle + da) - r1 * cos(angle)
|
150
|
+
v = r2 * sin(angle + da) - r1 * sin(angle)
|
151
|
+
len = sqrt(u * u + v * v)
|
152
|
+
u /= len
|
153
|
+
v /= len
|
154
|
+
glNormal3f(v, -u, 0.0)
|
155
|
+
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5)
|
156
|
+
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5)
|
157
|
+
glNormal3f(cos(angle), sin(angle), 0.0)
|
158
|
+
glVertex3f(r2 * cos(angle + 2 * da),
|
159
|
+
r2 * sin(angle + 2 * da), width * 0.5)
|
160
|
+
glVertex3f(r2 * cos(angle + 2 * da),
|
161
|
+
r2 * sin(angle + 2 * da), -width * 0.5)
|
162
|
+
u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da)
|
163
|
+
v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da)
|
164
|
+
glNormal3f(v, -u, 0.0)
|
165
|
+
glVertex3f(r1 * cos(angle + 3 * da),
|
166
|
+
r1 * sin(angle + 3 * da), width * 0.5)
|
167
|
+
glVertex3f(r1 * cos(angle + 3 * da),
|
168
|
+
r1 * sin(angle + 3 * da), -width * 0.5)
|
169
|
+
glNormal3f(cos(angle), sin(angle), 0.0)
|
170
|
+
end
|
171
|
+
glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5)
|
172
|
+
glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5)
|
173
|
+
glEnd()
|
174
|
+
|
175
|
+
glShadeModel(GL_SMOOTH)
|
176
|
+
|
177
|
+
# Draw inside radius cylinder
|
178
|
+
glBegin(GL_QUAD_STRIP)
|
179
|
+
for i in 0..teeth
|
180
|
+
angle = i * 2.0 * PI / teeth
|
181
|
+
glNormal3f(-cos(angle), -sin(angle), 0.0)
|
182
|
+
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5)
|
183
|
+
glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5)
|
184
|
+
end
|
185
|
+
glEnd()
|
186
|
+
end
|
187
|
+
|
188
|
+
def draw_gears
|
189
|
+
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
190
|
+
|
191
|
+
glPushMatrix()
|
192
|
+
glRotatef(@view_rotx, 1.0, 0.0, 0.0)
|
193
|
+
glRotatef(@view_roty, 0.0, 1.0, 0.0)
|
194
|
+
glRotatef(@view_rotz, 0.0, 0.0, 1.0)
|
195
|
+
|
196
|
+
glPushMatrix()
|
197
|
+
glTranslatef(-3.0, -2.0, 0.0)
|
198
|
+
glRotatef(@angle, 0.0, 0.0, 1.0)
|
199
|
+
glCallList(@gear1)
|
200
|
+
glPopMatrix()
|
201
|
+
|
202
|
+
glPushMatrix()
|
203
|
+
glTranslatef(3.1, -2.0, 0.0)
|
204
|
+
glRotatef(-2.0 * @angle - 9.0, 0.0, 0.0, 1.0)
|
205
|
+
glCallList(@gear2)
|
206
|
+
glPopMatrix()
|
207
|
+
|
208
|
+
glPushMatrix()
|
209
|
+
glTranslatef(-3.1, 4.2, 0.0)
|
210
|
+
glRotatef(-2.0 * @angle - 25.0, 0.0, 0.0, 1.0)
|
211
|
+
glCallList(@gear3)
|
212
|
+
glPopMatrix()
|
213
|
+
|
214
|
+
glPopMatrix()
|
215
|
+
|
216
|
+
glutSwapBuffers()
|
217
|
+
|
218
|
+
@frames = 0 if not defined? @frames
|
219
|
+
@t0 = 0 if not defined? @t0
|
220
|
+
|
221
|
+
@frames += 1
|
222
|
+
t = glutGet(GLUT_ELAPSED_TIME)
|
223
|
+
if t - @t0 >= 5000
|
224
|
+
seconds = (t - @t0) / 1000.0
|
225
|
+
fps = @frames / seconds
|
226
|
+
printf("%d frames in %6.3f seconds = %6.3f FPS\n",
|
227
|
+
@frames, seconds, fps)
|
228
|
+
@t0, @frames = t, 0
|
229
|
+
exit if defined? @autoexit and t >= 999.0 * @autoexit
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def idle
|
234
|
+
t = glutGet(GLUT_ELAPSED_TIME) / 1000.0
|
235
|
+
@t0_idle = t if !defined? @t0_idle
|
236
|
+
# 90 degrees per second
|
237
|
+
@angle += 70.0 * (t - @t0_idle)
|
238
|
+
@t0_idle = t
|
239
|
+
glutPostRedisplay()
|
240
|
+
end
|
241
|
+
|
242
|
+
# Change view angle, exit upon ESC
|
243
|
+
def key(k, x, y)
|
244
|
+
case k
|
245
|
+
when ?z
|
246
|
+
@view_rotz += 5.0
|
247
|
+
when ?Z
|
248
|
+
@view_rotz -= 5.0
|
249
|
+
when 27 # Escape
|
250
|
+
exit
|
251
|
+
end
|
252
|
+
glutPostRedisplay()
|
253
|
+
end
|
254
|
+
|
255
|
+
# Change view angle
|
256
|
+
def special(k, x, y)
|
257
|
+
case k
|
258
|
+
when GLUT_KEY_UP
|
259
|
+
@view_rotx += 5.0
|
260
|
+
when GLUT_KEY_DOWN
|
261
|
+
@view_rotx -= 5.0
|
262
|
+
when GLUT_KEY_LEFT
|
263
|
+
@view_roty += 5.0
|
264
|
+
when GLUT_KEY_RIGHT
|
265
|
+
@view_roty -= 5.0
|
266
|
+
end
|
267
|
+
glutPostRedisplay()
|
268
|
+
end
|
269
|
+
|
270
|
+
# New window size or exposure
|
271
|
+
def reshape_gears(width, height)
|
272
|
+
|
273
|
+
h = height.to_f / width.to_f
|
274
|
+
glViewport(0, 0, width, height)
|
275
|
+
glMatrixMode(GL_PROJECTION)
|
276
|
+
glLoadIdentity()
|
277
|
+
glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0)
|
278
|
+
glMatrixMode(GL_MODELVIEW)
|
279
|
+
glLoadIdentity()
|
280
|
+
glTranslatef(0.0, 0.0, -40.0)
|
281
|
+
end
|
282
|
+
def enable_light_for_gears
|
283
|
+
puts '@mPOS'
|
284
|
+
puts @mPOS
|
285
|
+
|
286
|
+
glLightfv(GL_LIGHT0, GL_POSITION, @mPOS)
|
287
|
+
glEnable(GL_CULL_FACE)
|
288
|
+
glEnable(GL_LIGHTING)
|
289
|
+
glEnable(GL_LIGHT0)
|
290
|
+
glEnable(GL_DEPTH_TEST)
|
291
|
+
|
292
|
+
end
|
293
|
+
def init_gears
|
294
|
+
|
295
|
+
@angle = 0.0
|
296
|
+
@view_rotx, @view_roty, @view_rotz = 20.0, 30.0, 0.0
|
297
|
+
|
298
|
+
|
299
|
+
# Make the gears
|
300
|
+
@gear1 = glGenLists(1)
|
301
|
+
glNewList(@gear1, GL_COMPILE)
|
302
|
+
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE,@mRED)
|
303
|
+
gear(1.0, 4.0, 1.0, 20, 0.7)
|
304
|
+
glEndList()
|
305
|
+
|
306
|
+
@gear2 = glGenLists(1)
|
307
|
+
glNewList(@gear2, GL_COMPILE)
|
308
|
+
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, @mGREEN)
|
309
|
+
gear(0.5, 2.0, 2.0, 10, 0.7)
|
310
|
+
glEndList()
|
311
|
+
|
312
|
+
@gear3 = glGenLists(1)
|
313
|
+
glNewList(@gear3, GL_COMPILE)
|
314
|
+
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, @mBLUE)
|
315
|
+
gear(1.3, 2.0, 0.5, 10, 0.7)
|
316
|
+
glEndList()
|
317
|
+
|
318
|
+
glEnable(GL_NORMALIZE)
|
319
|
+
|
320
|
+
ARGV.each do |arg|
|
321
|
+
case arg
|
322
|
+
when '-info'
|
323
|
+
printf("GL_RENDERER = %s\n", glGetString(GL_RENDERER))
|
324
|
+
printf("GL_VERSION = %s\n", glGetString(GL_VERSION))
|
325
|
+
printf("GL_VENDOR = %s\n", glGetString(GL_VENDOR))
|
326
|
+
printf("GL_EXTENSIONS = %s\n", glGetString(GL_EXTENSIONS))
|
327
|
+
when '-exit'
|
328
|
+
@autoexit = 30
|
329
|
+
printf("Auto Exit after %i seconds.\n", @autoexit);
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
def visible(vis)
|
335
|
+
glutIdleFunc((vis == GLUT_VISIBLE ? method(:idle).to_proc : nil))
|
336
|
+
end
|
337
|
+
|
338
|
+
def mouse(button, state, x, y)
|
339
|
+
@mouse = state
|
340
|
+
@x0, @y0 = x, y
|
341
|
+
end
|
342
|
+
|
343
|
+
def motion(x, y)
|
344
|
+
if @mouse == GLUT_DOWN then
|
345
|
+
@view_roty += @x0 - x
|
346
|
+
@view_rotx += @y0 - y
|
347
|
+
end
|
348
|
+
@x0, @y0 = x, y
|
349
|
+
end
|
350
|
+
|
351
|
+
|
352
|
+
def glut_init
|
353
|
+
if SHOW_FFI
|
354
|
+
glutInit(MemoryPointer.new(:int, 1).put_int(0, 0),
|
355
|
+
MemoryPointer.new(:pointer, 1).put_pointer(0, nil))
|
356
|
+
else
|
357
|
+
glutInit
|
358
|
+
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
|
363
|
+
def initialize
|
364
|
+
#POS = @mPOS
|
365
|
+
#RED = @mRED
|
366
|
+
#GREEN = @mGREEN
|
367
|
+
#BLUE = @mBLUE
|
368
|
+
|
369
|
+
puts 'initialize() call glut_init :: init_soko|no gears equivalent '
|
370
|
+
glut_init
|
371
|
+
# argc, argv parameters
|
372
|
+
|
373
|
+
puts 'initialize() set DisplayMode'
|
374
|
+
if SHOW_GEARS
|
375
|
+
|
376
|
+
|
377
|
+
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE)
|
378
|
+
else
|
379
|
+
|
380
|
+
glutInitDisplayMode GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH
|
381
|
+
|
382
|
+
#glutInitDisplayMode GLUT_DOUBLE | GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH
|
383
|
+
Sokoban1::Render.init_soko
|
384
|
+
end
|
385
|
+
|
386
|
+
|
387
|
+
|
388
|
+
glutInitWindowPosition(0, 0)
|
389
|
+
glutInitWindowSize(300, 300)
|
390
|
+
|
391
|
+
|
392
|
+
|
393
|
+
|
394
|
+
end
|
395
|
+
|
396
|
+
def register_glut_with_gears
|
397
|
+
glutDisplayFunc(method(:draw_gears).to_proc)
|
398
|
+
|
399
|
+
glutReshapeFunc(method(:reshape_gears).to_proc)
|
400
|
+
glutKeyboardFunc(method(:key).to_proc)
|
401
|
+
glutSpecialFunc(method(:special).to_proc)
|
402
|
+
glutVisibilityFunc(method(:visible).to_proc)
|
403
|
+
glutMouseFunc(method(:mouse).to_proc)
|
404
|
+
glutMotionFunc(method(:motion).to_proc)
|
405
|
+
end
|
406
|
+
def start
|
407
|
+
|
408
|
+
|
409
|
+
puts 'start() enable lights'
|
410
|
+
puts 'start() register glut with methods'
|
411
|
+
if SHOW_GEARS
|
412
|
+
|
413
|
+
glutCreateWindow('Gears')
|
414
|
+
enable_light_for_gears
|
415
|
+
init_gears
|
416
|
+
|
417
|
+
register_glut_with_gears
|
418
|
+
else
|
419
|
+
init_gears
|
420
|
+
glutCreateWindow('SokoBan')
|
421
|
+
Sokoban1::Render.enable_light_soko
|
422
|
+
Sokoban1::Render.register_glut_with_soko
|
423
|
+
end
|
424
|
+
glutMainLoop()
|
425
|
+
end
|
426
|
+
|
427
|
+
end
|
428
|
+
|
429
|
+
#Gears.new.start
|
430
|
+
|
431
|
+
#puts 'initialize() call init_soko , glut_init'
|
432
|
+
#puts 'start() set DisplayMode'
|
433
|
+
#puts 'start() enable lights'
|
434
|
+
#puts 'start() register glut with methods'
|
435
|
+
if __FILE__ == $0
|
436
|
+
|
437
|
+
|
438
|
+
|
439
|
+
require File.dirname(__FILE__) + '/../lib/sokoban'
|
440
|
+
#include Config1
|
441
|
+
puts 'SHOW FFI?'
|
442
|
+
Sokoban1::Config.detect
|
443
|
+
|
444
|
+
if Sokoban1::Config.show_ffi
|
445
|
+
#$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")))
|
446
|
+
SHOW_FFI = true
|
447
|
+
gem 'ffi-opengl'
|
448
|
+
require 'ffi-opengl'
|
449
|
+
include FFI
|
450
|
+
puts true
|
451
|
+
else
|
452
|
+
SHOW_FFI = false
|
453
|
+
require 'opengl'
|
454
|
+
puts false
|
455
|
+
end
|
456
|
+
|
457
|
+
|
458
|
+
|
459
|
+
|
460
|
+
|
461
|
+
|
462
|
+
|
463
|
+
|
464
|
+
include GL, GLU, GLUT
|
465
|
+
include Math
|
466
|
+
#include Render
|
467
|
+
|
468
|
+
|
469
|
+
app = Gears.new
|
470
|
+
|
471
|
+
#app = Soko.new
|
472
|
+
#app.light_diffuse = MemoryPointer.new(:float, 4).put_array_of_float(0, [1.0, 1.0, 1.0, 1.0])
|
473
|
+
#app.light_position = MemoryPointer.new(:float, 4).put_array_of_float(0, [1.0, 1.0, 1.0, 0.0])
|
474
|
+
|
475
|
+
puts 'create Constants for color with ffi pointer array'
|
476
|
+
app.mPOS = convertf( [5.0, 5.0, 10.0, 0.0] )
|
477
|
+
app.mRED = convertf( [0.8, 0.1, 0.0, 1.0] )
|
478
|
+
app.mGREEN = convertf( [0.0, 0.8, 0.2, 1.0])
|
479
|
+
app.mBLUE = convertf ([0.2, 0.2, 1.0, 1.0])
|
480
|
+
|
481
|
+
|
482
|
+
#app.init_ffi
|
483
|
+
app.start
|
484
|
+
end
|
485
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Sokoban1
|
2
|
+
class Config
|
3
|
+
class << self
|
4
|
+
attr_accessor :show_ffi
|
5
|
+
def detect
|
6
|
+
puts 'ruby in use:'
|
7
|
+
rubyv = RUBY_VERSION
|
8
|
+
if rubyv == "1.9.1"
|
9
|
+
puts "1.9.1"
|
10
|
+
@show_ffi = false
|
11
|
+
elsif rubyv == "1.9.2"
|
12
|
+
puts "1.9.2"
|
13
|
+
|
14
|
+
@show_ffi = true
|
15
|
+
else
|
16
|
+
exit
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
@@ -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
|