diff options
author | Robert Hak <adiamas@rockbox.org> | 2003-02-24 09:32:09 +0000 |
---|---|---|
committer | Robert Hak <adiamas@rockbox.org> | 2003-02-24 09:32:09 +0000 |
commit | 820e3ae746ae5be6baa533b552fb06e8f64a9d94 (patch) | |
tree | f6694be990ad46c1a552569e73bbff7b3de4a204 /apps | |
parent | 8d672afdebb54b1bdc3abb8e45311e7843ae7163 (diff) | |
download | rockbox-820e3ae746ae5be6baa533b552fb06e8f64a9d94.tar.gz rockbox-820e3ae746ae5be6baa533b552fb06e8f64a9d94.zip |
rewrite/cleanup, addition of multilevel undo (limit is 5 right now)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@3327 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r-- | apps/recorder/sokoban.c | 1018 |
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 | ||
45 | static void load_level(int); | 50 | #define ROWS 16 |
51 | #define COLS 20 | ||
52 | #define MAX_UNDOS 5 | ||
53 | |||
54 | static void init_undo(); | ||
55 | static void undo(); | ||
56 | static void add_undo(int button); | ||
57 | |||
58 | static void init_boards(); | ||
59 | static void load_level(short level); | ||
60 | static void draw_level(short level); | ||
46 | static void update_screen(void); | 61 | static void update_screen(void); |
47 | static bool sokoban_loop(void); | 62 | static bool sokoban_loop(void); |
48 | static void copy_current_state_to_undo(void); | 63 | |
49 | static 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, | |
51 | static char board[16][20]; | 66 | * but the overall data layout becomes more manageable. */ |
52 | static char undo_board[16][20]; | 67 | |
53 | static int current_level=0; | 68 | /* We use the same three values in 2 structs. Makeing them a struct |
54 | static int undo_current_level=0; | 69 | * hopefully ensures that if you change things in one, the other changes |
55 | static int moves=0; | 70 | * as well. */ |
56 | static int undo_moves=0; | 71 | struct LevelInfo { |
57 | static int row=0; | 72 | short level; |
58 | static int undo_row=0; | 73 | short moves; |
59 | static int col=0; | 74 | short boxes_to_go; |
60 | static int undo_col=0; | 75 | }; |
61 | static int boxes_to_go=0; | 76 | |
62 | static int undo_boxes_to_go=0; | 77 | /* What a given location on the board looks like at a given time */ |
63 | static char current_spot= ' '; | 78 | struct Location { |
64 | static char undo_current_spot=' '; | 79 | char spot; |
65 | 80 | short row; | |
66 | 81 | short col; | |
67 | static 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 */ | ||
86 | struct Undo { | ||
87 | struct LevelInfo level; | ||
88 | struct Location location[3]; | ||
89 | }; | ||
90 | |||
91 | /* Our full undo history */ | ||
92 | static 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 */ | ||
99 | static struct BoardInfo { | ||
100 | char board[ROWS][COLS]; | ||
101 | struct LevelInfo level; | ||
102 | struct Location player; | ||
103 | } current_info; | ||
104 | |||
105 | |||
106 | static void init_undo() | ||
107 | { | ||
108 | undo_info.count = 0; | ||
109 | undo_info.current = 0; | ||
110 | } | ||
111 | |||
112 | static 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 | ||
86 | static void copy_current_undo_to_state(void) { | 154 | static 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 | ||
104 | static void load_level (int level_to_load) { | 233 | static 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 | |
245 | static 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 | ||
128 | static void update_screen(void) { | 271 | static 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 | 342 | static void draw_level(short level) | |
343 | { | ||
344 | load_level(level); | ||
345 | lcd_clear_display(); | ||
346 | update_screen(); | ||
347 | } | ||
192 | 348 | ||
193 | static bool sokoban_loop(void) | 349 | static 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 | |||