diff options
-rw-r--r-- | apps/plugins/maze.c | 410 | ||||
-rw-r--r-- | docs/CREDITS | 1 |
2 files changed, 219 insertions, 192 deletions
diff --git a/apps/plugins/maze.c b/apps/plugins/maze.c index 7f0c058708..f7751ceb48 100644 --- a/apps/plugins/maze.c +++ b/apps/plugins/maze.c | |||
@@ -31,15 +31,15 @@ | |||
31 | */ | 31 | */ |
32 | 32 | ||
33 | #include "plugin.h" | 33 | #include "plugin.h" |
34 | #include "pluginlib_actions.h" | ||
35 | #include "helper.h" | 34 | #include "helper.h" |
36 | 35 | ||
37 | PLUGIN_HEADER | 36 | PLUGIN_HEADER |
38 | 37 | ||
38 | /* key assignments */ | ||
39 | |||
39 | #if (CONFIG_KEYPAD == IPOD_4G_PAD) || \ | 40 | #if (CONFIG_KEYPAD == IPOD_4G_PAD) || \ |
40 | (CONFIG_KEYPAD == IPOD_3G_PAD) || \ | 41 | (CONFIG_KEYPAD == IPOD_3G_PAD) || \ |
41 | (CONFIG_KEYPAD == IPOD_1G2G_PAD) | 42 | (CONFIG_KEYPAD == IPOD_1G2G_PAD) |
42 | # undef __PLUGINLIB_ACTIONS_H__ | ||
43 | # define MAZE_NEW (BUTTON_SELECT | BUTTON_REPEAT) | 43 | # define MAZE_NEW (BUTTON_SELECT | BUTTON_REPEAT) |
44 | # define MAZE_NEW_PRE BUTTON_SELECT | 44 | # define MAZE_NEW_PRE BUTTON_SELECT |
45 | # define MAZE_QUIT (BUTTON_SELECT | BUTTON_MENU) | 45 | # define MAZE_QUIT (BUTTON_SELECT | BUTTON_MENU) |
@@ -54,6 +54,7 @@ PLUGIN_HEADER | |||
54 | # define MAZE_RDOWN (BUTTON_PLAY | BUTTON_REPEAT) | 54 | # define MAZE_RDOWN (BUTTON_PLAY | BUTTON_REPEAT) |
55 | 55 | ||
56 | #else | 56 | #else |
57 | # include "pluginlib_actions.h" | ||
57 | # define MAZE_NEW PLA_START | 58 | # define MAZE_NEW PLA_START |
58 | # define MAZE_QUIT PLA_QUIT | 59 | # define MAZE_QUIT PLA_QUIT |
59 | # define MAZE_SOLVE PLA_FIRE | 60 | # define MAZE_SOLVE PLA_FIRE |
@@ -65,29 +66,29 @@ PLUGIN_HEADER | |||
65 | # define MAZE_RLEFT PLA_LEFT_REPEAT | 66 | # define MAZE_RLEFT PLA_LEFT_REPEAT |
66 | # define MAZE_RUP PLA_UP_REPEAT | 67 | # define MAZE_RUP PLA_UP_REPEAT |
67 | # define MAZE_RDOWN PLA_DOWN_REPEAT | 68 | # define MAZE_RDOWN PLA_DOWN_REPEAT |
69 | static const struct button_mapping *plugin_contexts[] | ||
70 | = {generic_directions, generic_actions}; | ||
68 | 71 | ||
69 | #endif | 72 | #endif |
70 | 73 | ||
71 | /* propertie bits of the cell */ | 74 | /* cell property bits */ |
72 | #define WALL_N 0x00000001 | 75 | #define WALL_N 0x0001 |
73 | #define WALL_E 0x00000002 | 76 | #define WALL_E 0x0002 |
74 | #define WALL_S 0x00000004 | 77 | #define WALL_S 0x0004 |
75 | #define WALL_W 0x00000008 | 78 | #define WALL_W 0x0008 |
76 | #define WALL_ALL 0x0000000F | 79 | #define WALL_ALL (WALL_N | WALL_E | WALL_S | WALL_W) |
77 | 80 | #define PATH 0x0010 | |
78 | #define BORDER_N 0x00000010 | 81 | |
79 | #define BORDER_E 0x00000020 | 82 | /* border tests */ |
80 | #define BORDER_S 0x00000040 | 83 | #define BORDER_N(y) ((y) == 0) |
81 | #define BORDER_W 0x00000080 | 84 | #define BORDER_E(x) ((x) == MAZE_WIDTH-1) |
82 | #define PATH 0x00000100 | 85 | #define BORDER_S(y) ((y) == MAZE_HEIGHT-1) |
83 | 86 | #define BORDER_W(x) ((x) == 0) | |
87 | |||
88 | /* the API */ | ||
84 | static const struct plugin_api* rb; | 89 | static const struct plugin_api* rb; |
85 | 90 | ||
86 | #ifdef __PLUGINLIB_ACTIONS_H__ | 91 | // we can and should change this to make square boxes |
87 | const struct button_mapping *plugin_contexts[] | ||
88 | = {generic_directions, generic_actions}; | ||
89 | #endif | ||
90 | |||
91 | #if ( LCD_WIDTH == 112 ) | 92 | #if ( LCD_WIDTH == 112 ) |
92 | #define MAZE_WIDTH 16 | 93 | #define MAZE_WIDTH 16 |
93 | #define MAZE_HEIGHT 12 | 94 | #define MAZE_HEIGHT 12 |
@@ -99,82 +100,41 @@ const struct button_mapping *plugin_contexts[] | |||
99 | #define MAZE_HEIGHT 24 | 100 | #define MAZE_HEIGHT 24 |
100 | #endif | 101 | #endif |
101 | 102 | ||
102 | struct coord_stack | ||
103 | { | ||
104 | int data[MAZE_WIDTH*MAZE_HEIGHT]; | ||
105 | int stp; | ||
106 | }; | ||
107 | |||
108 | void coord_stack_init(struct coord_stack* stack) | ||
109 | { | ||
110 | stack->stp=0; | ||
111 | } | ||
112 | |||
113 | void coord_stack_push(struct coord_stack* stack, int x, int y) | ||
114 | { | ||
115 | stack->data[stack->stp] = ((x<<8)|y); | ||
116 | stack->stp++; | ||
117 | } | ||
118 | |||
119 | void coord_stack_get(struct coord_stack* stack, int index, int* x, int* y) | ||
120 | { | ||
121 | *y = stack->data[index]; | ||
122 | *y &= 0xff; | ||
123 | *x = (stack->data[index])>>8; | ||
124 | } | ||
125 | |||
126 | void coord_stack_pop(struct coord_stack* stack, int* x, int* y) | ||
127 | { | ||
128 | stack->stp--; | ||
129 | coord_stack_get(stack, stack->stp, x, y); | ||
130 | } | ||
131 | |||
132 | int coord_stack_count(struct coord_stack* stack) | ||
133 | { | ||
134 | return(stack->stp); | ||
135 | } | ||
136 | |||
137 | struct maze | 103 | struct maze |
138 | { | 104 | { |
105 | int show_path; | ||
139 | int solved; | 106 | int solved; |
140 | int player_x; | 107 | int player_x; |
141 | int player_y; | 108 | int player_y; |
142 | unsigned short maze[MAZE_WIDTH][MAZE_HEIGHT]; | 109 | uint8_t maze[MAZE_WIDTH][MAZE_HEIGHT]; |
143 | }; | 110 | }; |
144 | 111 | ||
145 | void maze_init(struct maze* maze) | 112 | static void maze_init(struct maze* maze) |
146 | { | 113 | { |
147 | int x, y; | 114 | int x, y; |
148 | rb->memset(maze->maze, 0, sizeof(maze->maze)); | 115 | |
116 | /* initialize the properties */ | ||
117 | maze->show_path = false; | ||
149 | maze->solved = false; | 118 | maze->solved = false; |
150 | maze->player_x = 0; | 119 | maze->player_x = 0; |
151 | maze->player_y = 0; | 120 | maze->player_y = 0; |
152 | 121 | ||
122 | /* all walls are up */ | ||
153 | for(y=0; y<MAZE_HEIGHT; y++){ | 123 | for(y=0; y<MAZE_HEIGHT; y++){ |
154 | for(x=0; x<MAZE_WIDTH; x++){ | 124 | for(x=0; x<MAZE_WIDTH; x++){ |
155 | 125 | maze->maze[x][y] = WALL_ALL; | |
156 | /* all walls are up */ | ||
157 | maze->maze[x][y] |= WALL_ALL | PATH; | ||
158 | |||
159 | /* setup borders */ | ||
160 | if(x == 0) | ||
161 | maze->maze[x][y]|= BORDER_W; | ||
162 | if(y == 0) | ||
163 | maze->maze[x][y]|= BORDER_N; | ||
164 | if(x == MAZE_WIDTH-1) | ||
165 | maze->maze[x][y]|= BORDER_E; | ||
166 | if(y == MAZE_HEIGHT-1) | ||
167 | maze->maze[x][y]|= BORDER_S; | ||
168 | } | 126 | } |
169 | } | 127 | } |
170 | } | 128 | } |
171 | 129 | ||
172 | void maze_draw(struct maze* maze, struct screen* display) | 130 | static void maze_draw(struct maze* maze, struct screen* display) |
173 | { | 131 | { |
174 | int x, y; | 132 | int x, y; |
175 | int wx, wy; | 133 | int wx, wy; |
176 | int point_width, point_height, point_offset_x, point_offset_y; | 134 | int point_width, point_height, point_offset_x, point_offset_y; |
177 | unsigned short cell; | 135 | uint8_t cell; |
136 | |||
137 | /* calculate the size variables */ | ||
178 | 138 | ||
179 | wx = (int) display->lcdwidth / MAZE_WIDTH; | 139 | wx = (int) display->lcdwidth / MAZE_WIDTH; |
180 | wy = (int) display->lcdheight / MAZE_HEIGHT; | 140 | wy = (int) display->lcdheight / MAZE_HEIGHT; |
@@ -195,14 +155,14 @@ void maze_draw(struct maze* maze, struct screen* display) | |||
195 | point_offset_y=1; | 155 | point_offset_y=1; |
196 | } | 156 | } |
197 | 157 | ||
158 | /* start drawing */ | ||
159 | |||
198 | display->clear_display(); | 160 | display->clear_display(); |
199 | 161 | ||
162 | /* draw the walls */ | ||
200 | for(y=0; y<MAZE_HEIGHT; y++){ | 163 | for(y=0; y<MAZE_HEIGHT; y++){ |
201 | for(x=0; x<MAZE_WIDTH; x++){ | 164 | for(x=0; x<MAZE_WIDTH; x++){ |
202 | |||
203 | cell = maze->maze[x][y]; | 165 | cell = maze->maze[x][y]; |
204 | |||
205 | /* draw walls */ | ||
206 | if(cell & WALL_N) | 166 | if(cell & WALL_N) |
207 | display->hline(x*wx, x*wx+wx, y*wy); | 167 | display->hline(x*wx, x*wx+wx, y*wy); |
208 | if(cell & WALL_E) | 168 | if(cell & WALL_E) |
@@ -211,18 +171,11 @@ void maze_draw(struct maze* maze, struct screen* display) | |||
211 | display->hline(x*wx, x*wx+wx, y*wy+wy); | 171 | display->hline(x*wx, x*wx+wx, y*wy+wy); |
212 | if(cell & WALL_W) | 172 | if(cell & WALL_W) |
213 | display->vline(x*wx, y*wy, y*wy+wy); | 173 | display->vline(x*wx, y*wy, y*wy+wy); |
214 | |||
215 | if(cell & BORDER_N) | ||
216 | display->hline(x*wx, x*wx+wx, y*wy); | ||
217 | if(cell & BORDER_E) | ||
218 | display->vline(x*wx+wx, y*wy, y*wy+wy); | ||
219 | if(cell & BORDER_S) | ||
220 | display->hline(x*wx, x*wx+wx, y*wy+wy); | ||
221 | if(cell & BORDER_W) | ||
222 | display->vline(x*wx, y*wy, y*wy+wy); | ||
223 | } | 174 | } |
224 | } | 175 | } |
225 | if(maze->solved){ | 176 | |
177 | /* draw the path */ | ||
178 | if(maze->show_path){ | ||
226 | #if LCD_DEPTH >= 16 | 179 | #if LCD_DEPTH >= 16 |
227 | if(display->depth>=16) | 180 | if(display->depth>=16) |
228 | display->set_foreground(LCD_RGBPACK(127,127,127)); | 181 | display->set_foreground(LCD_RGBPACK(127,127,127)); |
@@ -231,6 +184,8 @@ void maze_draw(struct maze* maze, struct screen* display) | |||
231 | if(display->depth==2) | 184 | if(display->depth==2) |
232 | display->set_foreground(1); | 185 | display->set_foreground(1); |
233 | #endif | 186 | #endif |
187 | |||
188 | /* highlight the path */ | ||
234 | for(y=0; y<MAZE_HEIGHT; y++){ | 189 | for(y=0; y<MAZE_HEIGHT; y++){ |
235 | for(x=0; x<MAZE_WIDTH; x++){ | 190 | for(x=0; x<MAZE_WIDTH; x++){ |
236 | cell = maze->maze[x][y]; | 191 | cell = maze->maze[x][y]; |
@@ -240,6 +195,32 @@ void maze_draw(struct maze* maze, struct screen* display) | |||
240 | point_width, point_height); | 195 | point_width, point_height); |
241 | } | 196 | } |
242 | } | 197 | } |
198 | |||
199 | /* link the cells in the path together */ | ||
200 | for(y=0; y<MAZE_HEIGHT; y++){ | ||
201 | for(x=0; x<MAZE_WIDTH; x++){ | ||
202 | cell = maze->maze[x][y]; | ||
203 | if(cell & PATH){ | ||
204 | if(!(cell & WALL_N) && (maze->maze[x][y-1] & PATH)) | ||
205 | display->fillrect(x*wx+point_offset_x, | ||
206 | y*wy, | ||
207 | point_width, wy-point_height); | ||
208 | if(!(cell & WALL_E) && (maze->maze[x+1][y] & PATH)) | ||
209 | display->fillrect(x*wx+wx-point_offset_x, | ||
210 | y*wy+point_offset_y, | ||
211 | wx-point_width, point_height); | ||
212 | if(!(cell & WALL_S) && (maze->maze[x][y+1] & PATH)) | ||
213 | display->fillrect(x*wx+point_offset_x, | ||
214 | y*wy+wy-point_offset_y, | ||
215 | point_width, wy-point_height); | ||
216 | if(!(cell & WALL_W) && (maze->maze[x-1][y] & PATH)) | ||
217 | display->fillrect(x*wx, | ||
218 | y*wy+point_offset_y, | ||
219 | wx-point_width, point_height); | ||
220 | } | ||
221 | } | ||
222 | } | ||
223 | |||
243 | #if LCD_DEPTH >= 16 | 224 | #if LCD_DEPTH >= 16 |
244 | if(display->depth>=16) | 225 | if(display->depth>=16) |
245 | display->set_foreground(LCD_RGBPACK(0,0,0)); | 226 | display->set_foreground(LCD_RGBPACK(0,0,0)); |
@@ -258,64 +239,90 @@ void maze_draw(struct maze* maze, struct screen* display) | |||
258 | display->drawline((MAZE_WIDTH-1)*wx,(MAZE_HEIGHT-1)*wy+wy, | 239 | display->drawline((MAZE_WIDTH-1)*wx,(MAZE_HEIGHT-1)*wy+wy, |
259 | (MAZE_WIDTH-1)*wx+wx, (MAZE_HEIGHT-1)*wy); | 240 | (MAZE_WIDTH-1)*wx+wx, (MAZE_HEIGHT-1)*wy); |
260 | 241 | ||
261 | |||
262 | /* draw current position */ | 242 | /* draw current position */ |
263 | display->fillrect(maze->player_x*wx+point_offset_x, | 243 | display->fillrect(maze->player_x*wx+point_offset_x, |
264 | maze->player_y*wy+point_offset_y, | 244 | maze->player_y*wy+point_offset_y, |
265 | point_width, point_height); | 245 | point_width, point_height); |
266 | 246 | ||
247 | /* update the display */ | ||
267 | display->update(); | 248 | display->update(); |
268 | } | 249 | } |
269 | 250 | ||
270 | 251 | ||
271 | int maze_pick_random_neighbour_cell_with_walls(struct maze* maze, | 252 | struct coord_stack |
253 | { | ||
254 | uint8_t x[MAZE_WIDTH*MAZE_HEIGHT]; | ||
255 | uint8_t y[MAZE_WIDTH*MAZE_HEIGHT]; | ||
256 | int stp; | ||
257 | }; | ||
258 | |||
259 | static void coord_stack_init(struct coord_stack* stack) | ||
260 | { | ||
261 | rb->memset(stack->x, 0, sizeof(stack->x)); | ||
262 | rb->memset(stack->y, 0, sizeof(stack->y)); | ||
263 | stack->stp = 0; | ||
264 | } | ||
265 | |||
266 | static void coord_stack_push(struct coord_stack* stack, int x, int y) | ||
267 | { | ||
268 | stack->x[stack->stp] = x; | ||
269 | stack->y[stack->stp] = y; | ||
270 | stack->stp++; | ||
271 | } | ||
272 | |||
273 | static void coord_stack_pop(struct coord_stack* stack, int* x, int* y) | ||
274 | { | ||
275 | stack->stp--; | ||
276 | *x = stack->x[stack->stp]; | ||
277 | *y = stack->y[stack->stp]; | ||
278 | } | ||
279 | |||
280 | static int maze_pick_random_neighbour_cell_with_walls(struct maze* maze, | ||
272 | int x, int y, int *pnx, int *pny) | 281 | int x, int y, int *pnx, int *pny) |
273 | { | 282 | { |
283 | int n, i; | ||
284 | int px[4], py[4]; | ||
274 | 285 | ||
275 | int ncount = 0; | 286 | n = 0; |
276 | struct coord_stack neighbours; | ||
277 | unsigned short current_cell=maze->maze[x][y]; | ||
278 | 287 | ||
279 | coord_stack_init(&neighbours); | 288 | /* look for neighbours with all walls set up */ |
280 | /* look for neighbour cells with walls */ | ||
281 | 289 | ||
282 | /* north */ | 290 | if(!BORDER_N(y) && ((maze->maze[x][y-1] & WALL_ALL) == WALL_ALL)){ |
283 | if(!(current_cell & BORDER_N)){ | 291 | px[n] = x; |
284 | if((maze->maze[x][y-1] & WALL_ALL) == WALL_ALL){ | 292 | py[n] = y-1; |
285 | coord_stack_push(&neighbours, x, y-1); | 293 | n++; |
286 | } | ||
287 | } | 294 | } |
288 | 295 | ||
289 | /* west */ | 296 | if(!BORDER_E(x) && ((maze->maze[x+1][y] & WALL_ALL) == WALL_ALL)){ |
290 | if(!(current_cell & BORDER_W)){ | 297 | px[n] = x+1; |
291 | if((maze->maze[x-1][y] & WALL_ALL) == WALL_ALL){ | 298 | py[n] = y; |
292 | coord_stack_push(&neighbours, x-1, y); | 299 | n++; |
293 | } | ||
294 | } | 300 | } |
295 | 301 | ||
296 | /* east */ | 302 | if(!BORDER_S(y) && ((maze->maze[x][y+1] & WALL_ALL) == WALL_ALL)){ |
297 | if(!(current_cell & BORDER_E)){ | 303 | px[n] = x; |
298 | if((maze->maze[x+1][y] & WALL_ALL) == WALL_ALL){ | 304 | py[n] = y+1; |
299 | coord_stack_push(&neighbours, x+1, y); | 305 | n++; |
300 | } | ||
301 | } | 306 | } |
302 | 307 | ||
303 | /* south */ | 308 | if(!BORDER_W(x) && ((maze->maze[x-1][y] & WALL_ALL) == WALL_ALL)){ |
304 | if(!(current_cell & BORDER_S)){ | 309 | px[n] = x-1; |
305 | if((maze->maze[x][y+1] & WALL_ALL) == WALL_ALL){ | 310 | py[n] = y; |
306 | coord_stack_push(&neighbours, x, y+1); | 311 | n++; |
307 | } | 312 | } |
313 | |||
314 | /* then choose one */ | ||
315 | if (n > 0){ | ||
316 | i = rb->rand() % n; | ||
317 | *pnx = px[i]; | ||
318 | *pny = py[i]; | ||
308 | } | 319 | } |
309 | 320 | ||
310 | /* randomly select neighbour cell with walls */ | 321 | return n; |
311 | ncount=coord_stack_count(&neighbours); | ||
312 | if(ncount!=0) | ||
313 | coord_stack_get(&neighbours, rb->rand()%ncount, pnx, pny); | ||
314 | return ncount; | ||
315 | } | 322 | } |
316 | 323 | ||
317 | /* Removes the wall between the cell (x,y) and the cell (nx,ny) */ | 324 | /* Removes the wall between the cell (x,y) and the cell (nx,ny) */ |
318 | void maze_remove_wall(struct maze* maze, int x, int y, int nx, int ny) | 325 | static void maze_remove_wall(struct maze* maze, int x, int y, int nx, int ny) |
319 | { | 326 | { |
320 | /* where is our neighbour? */ | 327 | /* where is our neighbour? */ |
321 | 328 | ||
@@ -346,7 +353,7 @@ void maze_remove_wall(struct maze* maze, int x, int y, int nx, int ny) | |||
346 | } | 353 | } |
347 | } | 354 | } |
348 | 355 | ||
349 | void maze_generate(struct maze* maze) | 356 | static void maze_generate(struct maze* maze) |
350 | { | 357 | { |
351 | int total_cells = MAZE_WIDTH * MAZE_HEIGHT; | 358 | int total_cells = MAZE_WIDTH * MAZE_HEIGHT; |
352 | int visited_cells; | 359 | int visited_cells; |
@@ -369,106 +376,120 @@ void maze_generate(struct maze* maze) | |||
369 | /* pop from stack */ | 376 | /* pop from stack */ |
370 | coord_stack_pop(&done_cells, &x, &y); | 377 | coord_stack_pop(&done_cells, &x, &y); |
371 | } else { | 378 | } else { |
379 | /* remove the wall */ | ||
372 | maze_remove_wall(maze, x, y, nx, ny); | 380 | maze_remove_wall(maze, x, y, nx, ny); |
373 | 381 | /* save our position on the stack */ | |
374 | /* save position on the stack */ | ||
375 | coord_stack_push(&done_cells, x, y); | 382 | coord_stack_push(&done_cells, x, y); |
376 | 383 | /* move to the next cell */ | |
377 | /* current cell = neighbour cell */ | ||
378 | x=nx; | 384 | x=nx; |
379 | y=ny; | 385 | y=ny; |
380 | 386 | /* keep track of visited cells count */ | |
381 | visited_cells++; | 387 | visited_cells++; |
382 | } | 388 | } |
383 | } | 389 | } |
384 | } | 390 | } |
385 | 391 | ||
386 | 392 | ||
387 | void maze_solve(struct maze* maze) | 393 | static void maze_solve(struct maze* maze) |
388 | { | 394 | { |
389 | int x, y; | 395 | int x, y; |
390 | int dead_ends = 1; | 396 | int dead_ends = 1; |
391 | unsigned short cell; | 397 | uint8_t cell; |
392 | unsigned short w; | 398 | uint8_t wall; |
393 | unsigned short solved_maze[MAZE_WIDTH][MAZE_HEIGHT]; | 399 | uint8_t solved_maze[MAZE_WIDTH][MAZE_HEIGHT]; |
400 | |||
401 | /* toggle the visibility of the path */ | ||
402 | maze->show_path = ~(maze->show_path); | ||
394 | 403 | ||
395 | maze->solved = ~(maze->solved); | 404 | /* no need to solve the maze if already solved */ |
405 | if (maze->solved) | ||
406 | return; | ||
396 | 407 | ||
397 | /* copy maze for solving */ | 408 | /* work on a copy of the maze */ |
398 | rb->memcpy(solved_maze, maze->maze, | 409 | rb->memcpy(solved_maze, maze->maze, sizeof(maze->maze)); |
399 | (MAZE_HEIGHT*MAZE_WIDTH*sizeof(maze->maze[0][0]))); | ||
400 | 410 | ||
411 | /* remove walls on start and end point */ | ||
412 | solved_maze[0][0] &= ~WALL_N; | ||
413 | solved_maze[MAZE_WIDTH-1][MAZE_HEIGHT-1] &= ~WALL_S; | ||
401 | 414 | ||
402 | /* remove some borders and walls on start and end point */ | 415 | /* first, mark all the cells as reachable */ |
403 | solved_maze[0][0] &= ~(WALL_N|BORDER_N); | 416 | for(y=0; y<MAZE_HEIGHT; y++){ |
404 | solved_maze[MAZE_WIDTH-1][MAZE_HEIGHT-1] &= ~(WALL_S|BORDER_S); | 417 | for(x=0; x<MAZE_WIDTH; x++){ |
418 | solved_maze[x][y] |= PATH; | ||
419 | } | ||
420 | } | ||
405 | 421 | ||
422 | /* start solving */ | ||
406 | while(dead_ends){ | 423 | while(dead_ends){ |
424 | /* solve by blocking off dead ends -- backward approach */ | ||
407 | dead_ends = 0; | 425 | dead_ends = 0; |
408 | /* scan for dead ends */ | 426 | /* scan for dead ends */ |
409 | for(y=0; y<MAZE_HEIGHT; y++){ | 427 | for(y=0; y<MAZE_HEIGHT; y++){ |
410 | rb->yield(); | 428 | rb->yield(); |
411 | for(x=0; x<MAZE_WIDTH; x++){ | 429 | for(x=0; x<MAZE_WIDTH; x++){ |
412 | cell = solved_maze[x][y]; | 430 | cell = solved_maze[x][y]; |
413 | w = ~cell & 0x000f; | 431 | wall = cell & WALL_ALL; |
414 | if(w == WALL_N || | 432 | if((wall == (WALL_E | WALL_S | WALL_W)) || |
415 | w == WALL_E || | 433 | (wall == (WALL_N | WALL_S | WALL_W)) || |
416 | w == WALL_S || | 434 | (wall == (WALL_N | WALL_E | WALL_W)) || |
417 | w == WALL_W){ | 435 | (wall == (WALL_N | WALL_E | WALL_S))){ |
418 | /* found dead end, clear path bit and fill it up */ | 436 | /* found dead end, clear path bit and set all its walls */ |
419 | maze->maze[x][y] &= ~PATH; | 437 | solved_maze[x][y] &= ~PATH; |
420 | solved_maze[x][y] |= WALL_ALL; | 438 | solved_maze[x][y] |= WALL_ALL; |
421 | /* don't forget the neighbours */ | 439 | /* don't forget the neighbours */ |
422 | if(!(cell & BORDER_N)) | 440 | if(!BORDER_S(y)) |
423 | solved_maze[x][y-1]|=WALL_S; | 441 | solved_maze[x][y+1] |= WALL_N; |
424 | if(!(cell & BORDER_E)) | 442 | if(!BORDER_W(x)) |
425 | solved_maze[x+1][y]|=WALL_W; | 443 | solved_maze[x-1][y] |= WALL_E; |
426 | if(!(cell & BORDER_S)) | 444 | if(!BORDER_N(y)) |
427 | solved_maze[x][y+1]|=WALL_N; | 445 | solved_maze[x][y-1] |= WALL_S; |
428 | if(!(cell & BORDER_W)) | 446 | if(!BORDER_E(x)) |
429 | solved_maze[x-1][y]|=WALL_E; | 447 | solved_maze[x+1][y] |= WALL_W; |
430 | dead_ends++; | 448 | dead_ends++; |
431 | } | 449 | } |
432 | } | 450 | } |
433 | } | 451 | } |
434 | } | 452 | } |
435 | } | ||
436 | 453 | ||
437 | void maze_move_player_down(struct maze* maze) | 454 | /* copy all the path bits to the maze */ |
438 | { | 455 | for(y=0; y<MAZE_HEIGHT; y++){ |
439 | unsigned short cell=maze->maze[maze->player_x][maze->player_y]; | 456 | for(x=0; x<MAZE_WIDTH; x++){ |
440 | if( !(cell & WALL_S) && | 457 | maze->maze[x][y] |= solved_maze[x][y] & PATH; |
441 | !(cell & BORDER_S)){ | 458 | } |
442 | maze->player_y++; | ||
443 | } | 459 | } |
460 | |||
461 | /* mark the maze as solved */ | ||
462 | maze->solved = true; | ||
444 | } | 463 | } |
445 | 464 | ||
446 | void maze_move_player_up(struct maze* maze) | 465 | static void maze_move_player_up(struct maze* maze) |
447 | { | 466 | { |
448 | unsigned short cell=maze->maze[maze->player_x][maze->player_y]; | 467 | uint8_t cell = maze->maze[maze->player_x][maze->player_y]; |
449 | if( !(cell & WALL_N) && | 468 | if(!BORDER_N(maze->player_y) && !(cell & WALL_N)) |
450 | !(cell & BORDER_N)){ | ||
451 | maze->player_y--; | 469 | maze->player_y--; |
452 | } | ||
453 | } | 470 | } |
454 | 471 | ||
455 | void maze_move_player_left(struct maze* maze) | 472 | static void maze_move_player_right(struct maze* maze) |
456 | { | 473 | { |
457 | unsigned short cell=maze->maze[maze->player_x][maze->player_y]; | 474 | uint8_t cell = maze->maze[maze->player_x][maze->player_y]; |
458 | if( !(cell & WALL_W) && | 475 | if(!BORDER_E(maze->player_x) && !(cell & WALL_E)) |
459 | !(cell & BORDER_W)){ | 476 | maze->player_x++; |
460 | maze->player_x--; | ||
461 | } | ||
462 | } | 477 | } |
463 | 478 | ||
464 | void maze_move_player_right(struct maze* maze) | 479 | static void maze_move_player_down(struct maze* maze) |
465 | { | 480 | { |
466 | unsigned short cell=maze->maze[maze->player_x][maze->player_y]; | 481 | uint8_t cell = maze->maze[maze->player_x][maze->player_y]; |
467 | if( !(cell & WALL_E) && | 482 | if(!BORDER_S(maze->player_y) && !(cell & WALL_S)) |
468 | !(cell & BORDER_E)){ | 483 | maze->player_y++; |
469 | maze->player_x++; | ||
470 | } | ||
471 | } | 484 | } |
485 | |||
486 | static void maze_move_player_left(struct maze* maze) | ||
487 | { | ||
488 | uint8_t cell = maze->maze[maze->player_x][maze->player_y]; | ||
489 | if(!BORDER_W(maze->player_x) && !(cell & WALL_W)) | ||
490 | maze->player_x--; | ||
491 | } | ||
492 | |||
472 | /**********************************/ | 493 | /**********************************/ |
473 | /* this is the plugin entry point */ | 494 | /* this is the plugin entry point */ |
474 | /**********************************/ | 495 | /**********************************/ |
@@ -483,20 +504,26 @@ enum plugin_status plugin_start(const struct plugin_api* api, const void* parame | |||
483 | 504 | ||
484 | /* Turn off backlight timeout */ | 505 | /* Turn off backlight timeout */ |
485 | backlight_force_on(rb); /* backlight control in lib/helper.c */ | 506 | backlight_force_on(rb); /* backlight control in lib/helper.c */ |
486 | 507 | ||
508 | /* Seed the RNG */ | ||
509 | rb->srand(*rb->current_tick); | ||
510 | |||
487 | FOR_NB_SCREENS(i) | 511 | FOR_NB_SCREENS(i) |
488 | rb->screens[i]->set_viewport(NULL); | 512 | rb->screens[i]->set_viewport(NULL); |
489 | 513 | ||
514 | /* Draw the background */ | ||
490 | #if LCD_DEPTH > 1 | 515 | #if LCD_DEPTH > 1 |
491 | rb->lcd_set_backdrop(NULL); | 516 | rb->lcd_set_backdrop(NULL); |
492 | #if LCD_DEPTH >= 16 | 517 | #if LCD_DEPTH >= 16 |
493 | rb->lcd_set_foreground( LCD_RGBPACK( 0, 0, 0)); | 518 | rb->lcd_set_foreground(LCD_RGBPACK( 0, 0, 0)); |
494 | rb->lcd_set_background(LCD_RGBPACK(182, 198, 229)); /* rockbox blue */ | 519 | rb->lcd_set_background(LCD_RGBPACK(182, 198, 229)); /* rockbox blue */ |
495 | #elif LCD_DEPTH == 2 | 520 | #elif LCD_DEPTH == 2 |
496 | rb->lcd_set_foreground(0); | 521 | rb->lcd_set_foreground(0); |
497 | rb->lcd_set_background(LCD_DEFAULT_BG); | 522 | rb->lcd_set_background(LCD_DEFAULT_BG); |
498 | #endif | 523 | #endif |
499 | #endif | 524 | #endif |
525 | |||
526 | /* Initialize and draw the maze */ | ||
500 | maze_init(&maze); | 527 | maze_init(&maze); |
501 | maze_generate(&maze); | 528 | maze_generate(&maze); |
502 | FOR_NB_SCREENS(i) | 529 | FOR_NB_SCREENS(i) |
@@ -524,30 +551,30 @@ enum plugin_status plugin_start(const struct plugin_api* api, const void* parame | |||
524 | FOR_NB_SCREENS(i) | 551 | FOR_NB_SCREENS(i) |
525 | maze_draw(&maze, rb->screens[i]); | 552 | maze_draw(&maze, rb->screens[i]); |
526 | break; | 553 | break; |
527 | case MAZE_RIGHT: | ||
528 | case MAZE_RRIGHT: | ||
529 | maze_move_player_right(&maze); | ||
530 | FOR_NB_SCREENS(i) | ||
531 | maze_draw(&maze, rb->screens[i]); | ||
532 | break; | ||
533 | case MAZE_LEFT: | ||
534 | case MAZE_RLEFT: | ||
535 | maze_move_player_left(&maze); | ||
536 | FOR_NB_SCREENS(i) | ||
537 | maze_draw(&maze, rb->screens[i]); | ||
538 | break; | ||
539 | case MAZE_UP: | 554 | case MAZE_UP: |
540 | case MAZE_RUP: | 555 | case MAZE_RUP: |
541 | maze_move_player_up(&maze); | 556 | maze_move_player_up(&maze); |
542 | FOR_NB_SCREENS(i) | 557 | FOR_NB_SCREENS(i) |
543 | maze_draw(&maze, rb->screens[i]); | 558 | maze_draw(&maze, rb->screens[i]); |
544 | break; | 559 | break; |
560 | case MAZE_RIGHT: | ||
561 | case MAZE_RRIGHT: | ||
562 | maze_move_player_right(&maze); | ||
563 | FOR_NB_SCREENS(i) | ||
564 | maze_draw(&maze, rb->screens[i]); | ||
565 | break; | ||
545 | case MAZE_DOWN: | 566 | case MAZE_DOWN: |
546 | case MAZE_RDOWN: | 567 | case MAZE_RDOWN: |
547 | maze_move_player_down(&maze); | 568 | maze_move_player_down(&maze); |
548 | FOR_NB_SCREENS(i) | 569 | FOR_NB_SCREENS(i) |
549 | maze_draw(&maze, rb->screens[i]); | 570 | maze_draw(&maze, rb->screens[i]); |
550 | break; | 571 | break; |
572 | case MAZE_LEFT: | ||
573 | case MAZE_RLEFT: | ||
574 | maze_move_player_left(&maze); | ||
575 | FOR_NB_SCREENS(i) | ||
576 | maze_draw(&maze, rb->screens[i]); | ||
577 | break; | ||
551 | case MAZE_QUIT: | 578 | case MAZE_QUIT: |
552 | /* quit plugin */ | 579 | /* quit plugin */ |
553 | quit=1; | 580 | quit=1; |
@@ -561,8 +588,7 @@ enum plugin_status plugin_start(const struct plugin_api* api, const void* parame | |||
561 | } | 588 | } |
562 | if( button != BUTTON_NONE ) | 589 | if( button != BUTTON_NONE ) |
563 | lastbutton = button; | 590 | lastbutton = button; |
564 | if(!quit) | 591 | |
565 | rb->yield(); /* BUG alert: always yielding causes data abort */ | ||
566 | } | 592 | } |
567 | /* Turn on backlight timeout (revert to settings) */ | 593 | /* Turn on backlight timeout (revert to settings) */ |
568 | backlight_use_settings(rb); /* backlight control in lib/helper.c */ | 594 | backlight_use_settings(rb); /* backlight control in lib/helper.c */ |
diff --git a/docs/CREDITS b/docs/CREDITS index 08880ba4ac..aa8b5be059 100644 --- a/docs/CREDITS +++ b/docs/CREDITS | |||
@@ -399,6 +399,7 @@ Maciej Adamczak | |||
399 | Tomer Shalev | 399 | Tomer Shalev |
400 | Thibaut Girka | 400 | Thibaut Girka |
401 | Rasmus Ry | 401 | Rasmus Ry |
402 | William Poetra Yoga Hadisoeseno | ||
402 | 403 | ||
403 | The libmad team | 404 | The libmad team |
404 | The wavpack team | 405 | The wavpack team |