summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/recorder/sokoban.c1018
1 files changed, 590 insertions, 428 deletions
diff --git a/apps/recorder/sokoban.c b/apps/recorder/sokoban.c
index 0f0b90f1ed..b192ea1922 100644
--- a/apps/recorder/sokoban.c
+++ b/apps/recorder/sokoban.c
@@ -8,6 +8,8 @@
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2002 Eric Linenberg 10 * Copyright (C) 2002 Eric Linenberg
11 * February 2003: Robert Hak performs a cleanup/rewrite/feature addition.
12 * Eric smiles. Bjorn cris. Linus say 'huh?'.
11 * 13 *
12 * All files in this archive are subject to the GNU General Public License. 14 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement. 15 * See the file COPYING in the source tree root for full license agreement.
@@ -30,7 +32,9 @@
30#include "menu.h" 32#include "menu.h"
31#include "screens.h" 33#include "screens.h"
32#include "font.h" 34#include "font.h"
35#include "file.h"
33 36
37#include "debug.h"
34#include "sokoban_levels.h" 38#include "sokoban_levels.h"
35 39
36#ifdef SIMULATOR 40#ifdef SIMULATOR
@@ -38,524 +42,676 @@
38#endif 42#endif
39#include <string.h> 43#include <string.h>
40#include "lang.h" 44#include "lang.h"
41#define SOKOBAN_TITLE "Sokoban" 45#define SOKOBAN_TITLE "Sokoban"
42#define SOKOBAN_TITLE_FONT 2 46#define SOKOBAN_TITLE_FONT 2
43#define NUM_LEVELS sizeof(levels)/320 47#define LEVELS_FILE "/sokoban.levels"
48#define NUM_LEVELS sizeof(levels)/320
44 49
45static void load_level(int); 50#define ROWS 16
51#define COLS 20
52#define MAX_UNDOS 5
53
54static void init_undo();
55static void undo();
56static void add_undo(int button);
57
58static void init_boards();
59static void load_level(short level);
60static void draw_level(short level);
46static void update_screen(void); 61static void update_screen(void);
47static bool sokoban_loop(void); 62static bool sokoban_loop(void);
48static void copy_current_state_to_undo(void); 63
49static void copy_current_undo_to_state(void); 64/* The Location, Undo and LevelInfo structs are OO-flavored.
50 65 * (oooh!-flavored as Schnueff puts it.) It makes more you have to know,
51static char board[16][20]; 66 * but the overall data layout becomes more manageable. */
52static char undo_board[16][20]; 67
53static int current_level=0; 68/* We use the same three values in 2 structs. Makeing them a struct
54static int undo_current_level=0; 69 * hopefully ensures that if you change things in one, the other changes
55static int moves=0; 70 * as well. */
56static int undo_moves=0; 71struct LevelInfo {
57static int row=0; 72 short level;
58static int undo_row=0; 73 short moves;
59static int col=0; 74 short boxes_to_go;
60static int undo_col=0; 75};
61static int boxes_to_go=0; 76
62static int undo_boxes_to_go=0; 77/* What a given location on the board looks like at a given time */
63static char current_spot= ' '; 78struct Location {
64static char undo_current_spot=' '; 79 char spot;
65 80 short row;
66 81 short col;
67static void copy_current_state_to_undo(void) { 82};
68 int a = 0; 83
69 int b = 0; 84/* A single level of undo. Each undo move can affect upto,
85 * but not more then, 3 spots on the board */
86struct Undo {
87 struct LevelInfo level;
88 struct Location location[3];
89};
90
91/* Our full undo history */
92static struct UndoInfo {
93 short count; /* How many undos are there in history */
94 short current; /* Which history is the current undo */
95 struct Undo history[MAX_UNDOS];
96} undo_info;
97
98/* Our playing board */
99static struct BoardInfo {
100 char board[ROWS][COLS];
101 struct LevelInfo level;
102 struct Location player;
103} current_info;
104
105
106static void init_undo()
107{
108 undo_info.count = 0;
109 undo_info.current = 0;
110}
111
112static void undo()
113{
114 struct Undo *undo;
115 int i = 0;
116 short row, col;
117
118 if (undo_info.count == 0)
119 return;
120
121 /* Update board info */
122 undo = &undo_info.history[undo_info.current];
70 123
71 for (a=0 ; a<16 ; a++) { 124 current_info.level = undo->level;
72 for (b=0; b<16 ; b++) { 125 current_info.player = undo->location[0];
73 undo_board[a][b] = board[a][b]; 126
127 row = undo->location[0].row;
128 col = undo->location[0].col;
129 current_info.board[row][col] = '@';
130
131 /* Update the two other possible spots */
132 for (i = 1; i < 3; i++) {
133 if (undo->location[i].spot != '\0') {
134 row = undo->location[i].row;
135 col = undo->location[i].col;
136 current_info.board[row][col] = undo->location[i].spot;
137 undo->location[i].spot = '\0';
74 } 138 }
75 } 139 }
76 undo_current_level = current_level; 140
77 undo_moves = moves; 141 /* Remove this undo from the list */
78 undo_row = row; 142 if (undo_info.current == 0) {
79 undo_col = col; 143 if (undo_info.count > 1)
80 undo_boxes_to_go = boxes_to_go; 144 undo_info.current = MAX_UNDOS - 1;
81 undo_current_spot = current_spot; 145 } else {
146 undo_info.current--;
147 }
148
149 undo_info.count--;
82 150
83 return; 151 return;
84} 152}
85 153
86static void copy_current_undo_to_state(void) { 154static void add_undo(int button)
87 int a = 0; 155{
88 int b = 0; 156 struct Undo *undo;
89 157 int row, col, i;
90 for (a=0 ; a<16 ; a++) { 158 bool storable;
91 for (b=0; b<16 ; b++) { 159
92 board[a][b] = undo_board[a][b]; 160 if ((button != BUTTON_LEFT) && (button != BUTTON_RIGHT) &&
161 (button != BUTTON_UP) && (button != BUTTON_DOWN))
162 return;
163
164 if (undo_info.count != 0) {
165 if (undo_info.current < (MAX_UNDOS - 1))
166 undo_info.current++;
167 else
168 undo_info.current = 0;
169 }
170
171 /* Make what follows more readable */
172 undo = &undo_info.history[undo_info.current];
173
174 /* Store our level info */
175 undo->level = current_info.level;
176
177 /* Store our player info */
178 undo->location[0] = current_info.player;
179
180 /* Now we need to store upto 2 blocks that may be affected.
181 * If player.spot is NULL, then there is no info stored
182 * for that block */
183
184 row = current_info.player.row;
185 col = current_info.player.col;
186
187 /* This must stay as _1_ because the first block (0) is the player */
188 for (i = 1; i < 3; i++) {
189 storable = true;
190
191 switch (button) {
192 case BUTTON_LEFT:
193 col--;
194 if (col < 0)
195 storable = false;
196 break;
197
198 case BUTTON_RIGHT:
199 col++;
200 if (col >= COLS)
201 storable = false;
202 break;
203
204 case BUTTON_UP:
205 row--;
206 if (row < 0)
207 storable = false;
208 break;
209
210 case BUTTON_DOWN:
211 row++;
212 if (row >= ROWS)
213 storable = false;
214 break;
215
216 default:
217 return;
218 }
219
220 if (storable) {
221 undo->location[i].col = col;
222 undo->location[i].row = row;
223 undo->location[i].spot = current_info.board[row][col];
224 } else {
225 undo->location[i].spot = '\0';
93 } 226 }
94 } 227 }
95 current_level = undo_current_level; 228
96 moves = undo_moves-1; 229 if (undo_info.count < MAX_UNDOS)
97 row = undo_row; 230 undo_info.count++;
98 col = undo_col;
99 boxes_to_go = undo_boxes_to_go;
100 current_spot = undo_current_spot;
101 return;
102} 231}
103 232
104static void load_level (int level_to_load) { 233static void init_boards()
105 int a = 0; 234{
106 int b = 0; 235 current_info.level.level = 0;
107 int c = 0; 236 current_info.level.moves = 0;
108 current_spot=' '; 237 current_info.level.boxes_to_go = 0;
109 boxes_to_go = 0; 238 current_info.player.row = 0;
110 /* load level into board */ 239 current_info.player.col = 0;
111 /* get to the current level in the level array */ 240 current_info.player.spot = ' ';
112 241
113 for(b=0 ; b<16 ; b++) { 242 init_undo();
114 for (c=0 ; c<20 ; c++) { 243}
115 board[b][c] = levels[level_to_load][a]/* - '0'*/; 244
245static void load_level(short level_to_load)
246{
247 short a = 0, b = 0, c = 0;
248
249 current_info.player.spot=' ';
250 current_info.level.boxes_to_go = 0;
251 current_info.level.moves = 0;
252
253 for (b = 0; b < ROWS; b++) {
254 for (c = 0; c < COLS; c++) {
255 current_info.board[b][c] = levels[level_to_load][a];
116 a++; 256 a++;
117 if (board[b][c]=='@') { 257
118 row = b; 258 if (current_info.board[b][c] == '@') {
119 col = c; 259 current_info.player.row = b;
260 current_info.player.col = c;
120 } 261 }
121 if (board[b][c]=='.') 262
122 boxes_to_go++; 263 if (current_info.board[b][c] == '.')
264 current_info.level.boxes_to_go++;
123 } 265 }
124 } 266 }
267
125 return; 268 return;
126} 269}
127 270
128static void update_screen(void) { 271static void update_screen(void)
129 int b = 0; 272{
130 int c = 0; 273 short b = 0, c = 0;
274 short rows = 0, cols = 0;
131 char s[25]; 275 char s[25];
276
277 short magnify = 4;
132 278
133 /* load the board to the screen */ 279 /* load the board to the screen */
134 for(b=0 ; b<16 ; b++) { 280 for (rows=0 ; rows < ROWS ; rows++) {
135 for (c=0 ; c<20 ; c++) { 281 for (cols = 0 ; cols < COLS ; cols++) {
136 switch ( board[b][c] ) { 282 c = cols * magnify;
137 case 'X': /* this is a black space */ 283 b = rows * magnify;
138 lcd_drawrect (c*4, b*4, 4, 4); 284
139 lcd_drawrect (c*4+1, b*4+1, 2, 2); 285 switch(current_info.board[rows][cols]) {
140 break; 286 case 'X': /* black space */
287 lcd_drawrect(c, b, magnify, magnify);
288 lcd_drawrect(c+1, b+1, 2, 2);
289 break;
290
291 case '#': /* this is a wall */
292 lcd_drawpixel(c, b);
293 lcd_drawpixel(c+2, b);
294 lcd_drawpixel(c+1, b+1);
295 lcd_drawpixel(c+3, b+1);
296 lcd_drawpixel(c, b+2);
297 lcd_drawpixel(c+2, b+2);
298 lcd_drawpixel(c+1, b+3);
299 lcd_drawpixel(c+3, b+3);
300 break;
141 301
142 case '#': /* this is a wall */ 302 case '.': /* this is a home location */
143 lcd_drawpixel (c*4, b*4); 303 lcd_drawrect(c+1, b+1, 2, 2);
144 lcd_drawpixel (c*4+2, b*4); 304 break;
145 lcd_drawpixel (c*4+1, b*4+1);
146 lcd_drawpixel (c*4+3, b*4+1);
147 lcd_drawpixel (c*4, b*4+2);
148 lcd_drawpixel (c*4+2, b*4+2);
149 lcd_drawpixel (c*4+1, b*4+3);
150 lcd_drawpixel (c*4+3, b*4+3);
151 break;
152 305
153 case '.': /* this is a home location */ 306 case '$': /* this is a box */
154 lcd_drawrect (c*4+1, b*4+1, 2, 2); 307 lcd_drawrect(c, b, magnify, magnify);
155 break; 308 break;
156 309
157 case '$': /* this is a box */ 310 case '@': /* this is you */
158 lcd_drawrect (c*4, b*4, 4, 4); 311 lcd_drawline(c+1, b, c+2, b);
159 break; 312 lcd_drawline(c, b+1, c+3, b+1);
313 lcd_drawline(c+1, b+2, c+2, b+2);
160 314
161 case '@': /* this is you */ 315 lcd_drawpixel(c, b+3);
162 lcd_drawline (c*4+1, b*4, c*4+2, b*4); 316 lcd_drawpixel(c+3, b+3);
163 lcd_drawline (c*4, b*4+1, c*4+3, b*4+1); 317 break;
164 lcd_drawline (c*4+1, b*4+2, c*4+2, b*4+2);
165 lcd_drawpixel (c*4, b*4+3);
166 lcd_drawpixel (c*4+3, b*4+3);
167 break;
168 318
169 case '%': /* this is a box on a home spot */ 319 case '%': /* this is a box on a home spot */
170 lcd_drawrect (c*4, b*4, 4, 4); 320 lcd_drawrect(c, b, magnify, magnify);
171 lcd_drawrect (c*4+1, b*4+1, 2, 2); 321 lcd_drawrect(c+1, b+1, 2, 2);
172 break; 322 break;
173 } 323 }
174 } 324 }
175 } 325 }
176 326
177 327
178 snprintf (s, sizeof(s), "%d", current_level+1); 328 snprintf(s, sizeof(s), "%d", current_info.level.level+1);
179 lcd_putsxy (86, 22, s); 329 lcd_putsxy(86, 22, s);
180 snprintf (s, sizeof(s), "%d", moves); 330 snprintf(s, sizeof(s), "%d", current_info.level.moves);
181 lcd_putsxy (86, 54, s); 331 lcd_putsxy(86, 54, s);
332
333 lcd_drawrect(80,0,32,32);
334 lcd_drawrect(80,32,32,64);
335 lcd_putsxy(81, 10, str(LANG_SOKOBAN_LEVEL));
336 lcd_putsxy(81, 42, str(LANG_SOKOBAN_MOVE));
182 337
183 lcd_drawrect (80,0,32,32);
184 lcd_drawrect (80,32,32,64);
185 lcd_putsxy (81, 10, str(LANG_SOKOBAN_LEVEL));
186 lcd_putsxy (81, 42, str(LANG_SOKOBAN_MOVE));
187 /* print out the screen */ 338 /* print out the screen */
188 lcd_update(); 339 lcd_update();
189} 340}
190 341
191 342static void draw_level(short level)
343{
344 load_level(level);
345 lcd_clear_display();
346 update_screen();
347}
192 348
193static bool sokoban_loop(void) 349static bool sokoban_loop(void)
194{ 350{
195 int ii = 0; 351 char new_spot;
196 moves = 0; 352 bool moved = true;
197 current_level = 0; 353 int i = 0, button = 0;
198 load_level(current_level); 354 short r = 0, c = 0;
199 update_screen();
200 355
201 while(1) { 356 current_info.level.level = 0;
202
203 bool idle = false;
204 switch ( button_get(true) ) {
205 case BUTTON_OFF:
206 /* get out of here */
207 return false;
208
209 case BUTTON_F3:
210 /* increase level */
211 boxes_to_go=0;
212 idle=true;
213 break;
214 357
215 case BUTTON_ON: 358 load_level(current_info.level.level);
216 /* this is UNDO */ 359 update_screen();
217 copy_current_undo_to_state(); 360
361 while (1) {
362 moved = true;
363
364 r = current_info.player.row;
365 c = current_info.player.col;
366
367 button = button_get(true);
368
369 add_undo(button);
370
371 switch(button)
372 {
373 case BUTTON_OFF:
374 /* get out of here */
375 return false;
376
377 case BUTTON_ON:
378 case BUTTON_ON | BUTTON_REPEAT:
379 /* this is UNDO */
380 undo();
381 lcd_clear_display();
382 update_screen();
383 moved = false;
384 break;
385
386 case BUTTON_F3:
387 case BUTTON_F3 | BUTTON_REPEAT:
388 /* increase level */
389 init_undo();
390 current_info.level.boxes_to_go=0;
391 moved = true;
392 break;
393
394 case BUTTON_F1:
395 case BUTTON_F1 | BUTTON_REPEAT:
396 /* previous level */
397 init_undo();
398 if (current_info.level.level)
399 current_info.level.level--;
400
401 draw_level(current_info.level.level);
402 moved = false;
403 break;
404
405 case BUTTON_F2:
406 case BUTTON_F2 | BUTTON_REPEAT:
407 /* same level */
408 init_undo();
409 draw_level(current_info.level.level);
410 moved = false;
411 break;
412
413 case BUTTON_LEFT:
414 switch(current_info.board[r][c-1])
415 {
416 case ' ': /* if it is a blank spot */
417 case '.': /* if it is a home spot */
418 new_spot = current_info.board[r][c-1];
419 current_info.board[r][c-1] = '@';
420 current_info.board[r][c] = current_info.player.spot;
421 current_info.player.spot = new_spot;
218 break; 422 break;
219 423
220 case BUTTON_F2: 424 case '$':
221 /* same level */ 425 switch(current_info.board[r][c-2])
222 load_level(current_level); 426 {
223 moves=0; 427 case ' ': /* going from blank to blank */
224 idle=true; 428 current_info.board[r][c-2] = current_info.board[r][c-1];
225 load_level(current_level); 429 current_info.board[r][c-1] = current_info.board[r][c];
226 lcd_clear_display(); 430 current_info.board[r][c] = current_info.player.spot;
227 update_screen(); 431 current_info.player.spot = ' ';
228 copy_current_state_to_undo(); 432 break;
229 copy_current_undo_to_state(); 433
434 case '.': /* going from a blank to home */
435 current_info.board[r][c-2] = '%';
436 current_info.board[r][c-1] = current_info.board[r][c];
437 current_info.board[r][c] = current_info.player.spot;
438 current_info.player.spot = ' ';
439 current_info.level.boxes_to_go--;
440 break;
441
442 default:
443 moved = false;
444 break;
445 }
230 break; 446 break;
231 447
232 case BUTTON_F1: 448 case '%':
233 449 switch(current_info.board[r][c-2]) {
234 /* previous level */ 450 case ' ': /* we are going from a home to a blank */
235 if (current_level) 451 current_info.board[r][c-2] = '$';
236 current_level--; 452 current_info.board[r][c-1] = current_info.board[r][c];
237 load_level(current_level); 453 current_info.board[r][c] = current_info.player.spot;
238 moves=0; 454 current_info.player.spot = '.';
239 idle=true; 455 current_info.level.boxes_to_go++;
240 load_level(current_level); 456 break;
241 lcd_clear_display(); 457
242 update_screen(); 458 case '.': /* if we are going from a home to home */
243 copy_current_state_to_undo(); 459 current_info.board[r][c-2] = '%';
244 copy_current_undo_to_state(); 460 current_info.board[r][c-1] = current_info.board[r][c];
461 current_info.board[r][c] = current_info.player.spot;
462 current_info.player.spot = '.';
463 break;
464
465 default:
466 moved = false;
467 break;
468 }
245 break; 469 break;
246 470
247 case BUTTON_LEFT: 471 default:
248 copy_current_state_to_undo(); 472 moved = false;
249 switch ( board[row][col-1] ) { 473 break;
250 case ' ': /* if it is a blank spot */ 474 }
251 board[row][col-1]='@';
252 board[row][col]=current_spot;
253 current_spot=' ';
254 break;
255 475
256 case '.': /* if it is a home spot */ 476 if (moved)
257 board[row][col-1]='@'; 477 current_info.player.col--;
258 board[row][col]=current_spot; 478 break;
259 current_spot='.'; 479
260 break; 480 case BUTTON_RIGHT: /* if it is a blank spot */
481 switch(current_info.board[r][c+1]) {
482 case ' ':
483 case '.': /* if it is a home spot */
484 new_spot = current_info.board[r][c+1];
485 current_info.board[r][c+1] = '@';
486 current_info.board[r][c] = current_info.player.spot;
487 current_info.player.spot = new_spot;
488 break;
261 489
262 case '$': 490 case '$':
263 switch ( board[row][col-2] ) { 491 switch(current_info.board[r][c+2]) {
264 case ' ': /* if we are going from blank to blank */ 492 case ' ': /* going from blank to blank */
265 board[row][col-2]=board[row][col-1]; 493 current_info.board[r][c+2] = current_info.board[r][c+1];
266 board[row][col-1]=board[row][col]; 494 current_info.board[r][c+1] = current_info.board[r][c];
267 board[row][col]=current_spot; 495 current_info.board[r][c] = current_info.player.spot;
268 current_spot=' '; 496 current_info.player.spot = ' ';
269 break; 497 break;
270
271 case '.': /* if we are going from a blank to home */
272 board[row][col-2]='%';
273 board[row][col-1]=board[row][col];
274 board[row][col]=current_spot;
275 current_spot=' ';
276 boxes_to_go--;
277 break;
278
279 default:
280 idle = true;
281 break;
282 }
283 break;
284 498
285 case '%': 499 case '.': /* going from a blank to home */
286 switch ( board[row][col-2] ) { 500 current_info.board[r][c+2] = '%';
287 case ' ': /* we are going from a home to a blank */ 501 current_info.board[r][c+1] = current_info.board[r][c];
288 board[row][col-2]='$'; 502 current_info.board[r][c] = current_info.player.spot;
289 board[row][col-1]=board[row][col]; 503 current_info.player.spot = ' ';
290 board[row][col]=current_spot; 504 current_info.level.boxes_to_go--;
291 current_spot='.'; 505 break;
292 boxes_to_go++;
293 break;
294
295 case '.': /* if we are going from a home to home */
296 board[row][col-2]='%';
297 board[row][col-1]=board[row][col];
298 board[row][col]=current_spot;
299 current_spot='.';
300 break;
301
302 default:
303 idle = true;
304 break;
305 }
306 break;
307 506
308 default: 507 default:
309 idle = true; 508 moved = false;
310 break; 509 break;
311 } 510 }
312 if (!idle)
313 col--;
314 break; 511 break;
315 512
316 case BUTTON_RIGHT: /* if it is a blank spot */ 513 case '%':
317 copy_current_state_to_undo(); 514 switch(current_info.board[r][c+2]) {
318 switch ( board[row][col+1] ) { 515 case ' ': /* going from a home to a blank */
319 case ' ': 516 current_info.board[r][c+2] = '$';
320 board[row][col+1]='@'; 517 current_info.board[r][c+1] = current_info.board[r][c];
321 board[row][col]=current_spot; 518 current_info.board[r][c] = current_info.player.spot;
322 current_spot=' '; 519 current_info.player.spot = '.';
323 break; 520 current_info.level.boxes_to_go++;
521 break;
324 522
325 case '.': /* if it is a home spot */ 523 case '.':
326 board[row][col+1]='@'; 524 current_info.board[r][c+2] = '%';
327 board[row][col]=current_spot; 525 current_info.board[r][c+1] = current_info.board[r][c];
328 current_spot='.'; 526 current_info.board[r][c] = current_info.player.spot;
329 break; 527 current_info.player.spot = '.';
528 break;
330 529
331 case '$': 530 default:
332 switch ( board[row][col+2] ) { 531 moved = false;
333 case ' ': /* if we are going from blank to blank */ 532 break;
334 board[row][col+2]=board[row][col+1]; 533 }
335 board[row][col+1]=board[row][col]; 534 break;
336 board[row][col]=current_spot;
337 current_spot=' ';
338 break;
339
340 case '.': /* if we are going from a blank to home */
341 board[row][col+2]='%';
342 board[row][col+1]=board[row][col];
343 board[row][col]=current_spot;
344 current_spot=' ';
345 boxes_to_go--;
346 break;
347
348 default:
349 idle = true;
350 break;
351 }
352 break;
353 535
354 case '%': 536 default:
355 switch ( board[row][col+2] ) { 537 moved = false;
356 case ' ': /* we are going from a home to a blank */ 538 break;
357 board[row][col+2]='$'; 539 }
358 board[row][col+1]=board[row][col];
359 board[row][col]=current_spot;
360 current_spot='.';
361 boxes_to_go++;
362 break;
363
364 case '.':
365 board[row][col+2]='%';
366 board[row][col+1]=board[row][col];
367 board[row][col]=current_spot;
368 current_spot='.';
369 break;
370
371 default:
372 idle = true;
373 break;
374 }
375 break;
376 540
377 default: 541 if (moved)
378 idle = true; 542 current_info.player.col++;
379 break; 543 break;
380 } 544
381 if (!idle) 545 case BUTTON_UP:
382 col++; 546 switch(current_info.board[r-1][c]) {
547 case ' ': /* if it is a blank spot */
548 case '.': /* if it is a home spot */
549 new_spot = current_info.board[r-1][c];
550 current_info.board[r-1][c] = '@';
551 current_info.board[r][c] = current_info.player.spot;
552 current_info.player.spot = new_spot;
383 break; 553 break;
384 554
385 case BUTTON_UP: 555 case '$':
386 copy_current_state_to_undo(); 556 switch(current_info.board[r-2][c]) {
387 switch ( board[row-1][col] ) { 557 case ' ': /* going from blank to blank */
388 case ' ': /* if it is a blank spot */ 558 current_info.board[r-2][c] = current_info.board[r-1][c];
389 board[row-1][col]='@'; 559 current_info.board[r-1][c] = current_info.board[r][c];
390 board[row][col]=current_spot; 560 current_info.board[r][c] = current_info.player.spot;
391 current_spot=' '; 561 current_info.player.spot = ' ';
392 break; 562 break;
393 563
394 case '.': /* if it is a home spot */ 564 case '.': /* going from a blank to home */
395 board[row-1][col]='@'; 565 current_info.board[r-2][c] = '%';
396 board[row][col]=current_spot; 566 current_info.board[r-1][c] = current_info.board[r][c];
397 current_spot='.'; 567 current_info.board[r][c] = current_info.player.spot;
398 break; 568 current_info.player.spot = ' ';
569 current_info.level.boxes_to_go--;
570 break;
399 571
400 case '$': 572 default:
401 switch ( board[row-2][col] ) { 573 moved = false;
402 case ' ': /* if we are going from blank to blank */ 574 break;
403 board[row-2][col]=board[row-1][col]; 575 }
404 board[row-1][col]=board[row][col]; 576 break;
405 board[row][col]=current_spot;
406 current_spot=' ';
407 break;
408
409 case '.': /* if we are going from a blank to home */
410 board[row-2][col]='%';
411 board[row-1][col]=board[row][col];
412 board[row][col]=current_spot;
413 current_spot=' ';
414 boxes_to_go--;
415 break;
416
417 default:
418 idle = true;
419 break;
420 }
421 break;
422 577
423 case '%': 578 case '%':
424 switch ( board[row-2][col] ) { 579 switch(current_info.board[r-2][c]) {
425 case ' ': /* we are going from a home to a blank */ 580 case ' ': /* we are going from a home to a blank */
426 board[row-2][col]='$'; 581 current_info.board[r-2][c] = '$';
427 board[row-1][col]=board[row][col]; 582 current_info.board[r-1][c] = current_info.board[r][c];
428 board[row][col]=current_spot; 583 current_info.board[r][c] = current_info.player.spot;
429 current_spot='.'; 584 current_info.player.spot = '.';
430 boxes_to_go++; 585 current_info.level.boxes_to_go++;
431 break; 586 break;
432
433 case '.': /* if we are going from a home to home */
434 board[row-2][col]='%';
435 board[row-1][col]=board[row][col];
436 board[row][col]=current_spot;
437 current_spot='.';
438 break;
439
440 default:
441 idle = true;
442 break;
443 }
444 break;
445 587
446 default: 588 case '.': /* if we are going from a home to home */
447 idle = true; 589 current_info.board[r-2][c] = '%';
448 break; 590 current_info.board[r-1][c] = current_info.board[r][c];
591 current_info.board[r][c] = current_info.player.spot;
592 current_info.player.spot = '.';
593 break;
594
595 default:
596 moved = false;
597 break;
449 } 598 }
450 if (!idle)
451 row--;
452 break; 599 break;
453 600
454 case BUTTON_DOWN: 601 default:
455 copy_current_state_to_undo(); 602 moved = false;
456 switch ( board[row+1][col] ) { 603 break;
457 case ' ': /* if it is a blank spot */ 604 }
458 board[row+1][col]='@';
459 board[row][col]=current_spot;
460 current_spot=' ';
461 break;
462 605
463 case '.': /* if it is a home spot */ 606 if (moved)
464 board[row+1][col]='@'; 607 current_info.player.row--;
465 board[row][col]=current_spot; 608 break;
466 current_spot='.'; 609
467 break; 610 case BUTTON_DOWN:
611 switch(current_info.board[r+1][c]) {
612 case ' ': /* if it is a blank spot */
613 case '.': /* if it is a home spot */
614 new_spot = current_info.board[r+1][c];
615 current_info.board[r+1][c] = '@';
616 current_info.board[r][c] = current_info.player.spot;
617 current_info.player.spot = new_spot;
618 break;
468 619
469 case '$': 620 case '$':
470 switch ( board[row+2][col] ) { 621 switch(current_info.board[r+2][c]) {
471 case ' ': /* if we are going from blank to blank */ 622 case ' ': /* going from blank to blank */
472 board[row+2][col]=board[row+1][col]; 623 current_info.board[r+2][c] = current_info.board[r+1][c];
473 board[row+1][col]=board[row][col]; 624 current_info.board[r+1][c] = current_info.board[r][c];
474 board[row][col]=current_spot; 625 current_info.board[r][c] = current_info.player.spot;
475 current_spot=' '; 626 current_info.player.spot = ' ';
476 break; 627 break;
477
478 case '.': /* if we are going from a blank to home */
479 board[row+2][col]='%';
480 board[row+1][col]=board[row][col];
481 board[row][col]=current_spot;
482 current_spot=' ';
483 boxes_to_go--;
484 break;
485
486 default:
487 idle = true;
488 break;
489 }
490 break;
491 628
492 case '%': 629 case '.': /* going from a blank to home */
493 switch ( board[row+2][col] ) { 630 current_info.board[r+2][c] = '%';
494 case ' ': /* we are going from a home to a blank */ 631 current_info.board[r+1][c] = current_info.board[r][c];
495 board[row+2][col]='$'; 632 current_info.board[r][c] = current_info.player.spot;
496 board[row+1][col]=board[row][col]; 633 current_info.player.spot = ' ';
497 board[row][col]=current_spot; 634 current_info.level.boxes_to_go--;
498 current_spot='.'; 635 break;
499 boxes_to_go++;
500 break;
501
502 case '.': /* if we are going from a home to home */
503 board[row+2][col]='%';
504 board[row+1][col]=board[row][col];
505 board[row][col]=current_spot;
506 current_spot='.';
507 break;
508
509 default:
510 idle = true;
511 break;
512 }
513 break;
514 636
515 default: 637 default:
516 idle = true; 638 moved = false;
517 break; 639 break;
518 } 640 }
519 if (!idle)
520 row++;
521 break; 641 break;
522 642
523 case SYS_USB_CONNECTED: 643 case '%':
524 usb_screen(); 644 switch(current_info.board[r+2][c]) {
525 return true; 645 case ' ': /* going from a home to a blank */
646 current_info.board[r+2][c] = '$';
647 current_info.board[r+1][c] = current_info.board[r][c];
648 current_info.board[r][c] = current_info.player.spot;
649 current_info.player.spot = '.';
650 current_info.level.boxes_to_go++;
651 break;
652
653 case '.': /* going from a home to home */
654 current_info.board[r+2][c] = '%';
655 current_info.board[r+1][c] = current_info.board[r][c];
656 current_info.board[r][c] = current_info.player.spot;
657 current_info.player.spot = '.';
658 break;
659
660 default:
661 moved = false;
662 break;
663 }
664 break;
526 665
527 default: 666 default:
528 idle = true; 667 moved = false;
529 break; 668 break;
669 }
670
671 if (moved)
672 current_info.player.row++;
673 break;
674
675 case SYS_USB_CONNECTED:
676 usb_screen();
677 return true;
678
679 default:
680 moved = false;
681 break;
530 } 682 }
531 683
532 if (!idle) { 684 if (moved) {
533 moves++; 685 current_info.level.moves++;
534 lcd_clear_display(); 686 lcd_clear_display();
535 update_screen(); 687 update_screen();
536 } 688 }
537 689
538 if (boxes_to_go==0) { 690 /* We have completed this level */
539 moves=0; 691 if (current_info.level.boxes_to_go == 0) {
540 current_level++; 692 current_info.level.level++;
541 if (current_level == NUM_LEVELS) { 693
542 lcd_clear_display(); 694 lcd_clear_display();
695
696 if (current_info.level.level == NUM_LEVELS) {
543 lcd_putsxy(10, 20, str(LANG_SOKOBAN_WIN)); 697 lcd_putsxy(10, 20, str(LANG_SOKOBAN_WIN));
544 for(ii=0; ii<30000 ; ii++) { 698
545 lcd_invertrect(0,0,111,63); 699 for (i = 0; i < 30000 ; i++) {
700 lcd_invertrect(0, 0, 111, 63);
546 lcd_update(); 701 lcd_update();
547 if ( button_get(false) ) 702
548 return false; 703 if (button_get(false))
704 break;
549 } 705 }
706
550 return false; 707 return false;
551 } 708 }
552 load_level(current_level); 709
553 lcd_clear_display(); 710 load_level(current_info.level.level);
554 update_screen(); 711 update_screen();
555 copy_current_state_to_undo();
556 copy_current_undo_to_state();
557 } 712 }
558 } 713
714 } /* end while */
559 715
560 return false; 716 return false;
561} 717}
@@ -574,7 +730,7 @@ bool sokoban(void)
574 /* Get horizontel centering for text */ 730 /* Get horizontel centering for text */
575 len = w; 731 len = w;
576 if (len%2 != 0) 732 if (len%2 != 0)
577 len = ((len+1)/2)+(w/2); 733 len =((len+1)/2)+(w/2);
578 else 734 else
579 len /= 2; 735 len /= 2;
580 736
@@ -584,7 +740,7 @@ bool sokoban(void)
584 h /= 2; 740 h /= 2;
585 741
586 lcd_clear_display(); 742 lcd_clear_display();
587 lcd_putsxy(LCD_WIDTH/2-len, (LCD_HEIGHT/2)-h, SOKOBAN_TITLE); 743 lcd_putsxy(LCD_WIDTH/2-len,(LCD_HEIGHT/2)-h, SOKOBAN_TITLE);
588 744
589 lcd_update(); 745 lcd_update();
590 sleep(HZ*2); 746 sleep(HZ*2);
@@ -600,6 +756,8 @@ bool sokoban(void)
600 lcd_update(); 756 lcd_update();
601 sleep(HZ*2); 757 sleep(HZ*2);
602 lcd_clear_display(); 758 lcd_clear_display();
759
760 init_boards();
603 result = sokoban_loop(); 761 result = sokoban_loop();
604 762
605 lcd_setfont(FONT_UI); 763 lcd_setfont(FONT_UI);
@@ -608,3 +766,7 @@ bool sokoban(void)
608} 766}
609 767
610#endif 768#endif
769
770
771
772