1
0
Fork 0
forked from len0rd/rockbox

code cleanup and remote support for maze plugin

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13996 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Kevin Ferrare 2007-07-26 11:25:24 +00:00
parent 31cf7e95b4
commit bc597e4aa5
2 changed files with 223 additions and 154 deletions

View file

@ -92,232 +92,266 @@ const struct button_mapping *plugin_contexts[]
#define MAZE_HEIGHT 24 #define MAZE_HEIGHT 24
#endif #endif
unsigned short maze[MAZE_WIDTH][MAZE_HEIGHT]; struct coord_stack{
unsigned short solved_maze[MAZE_WIDTH][MAZE_HEIGHT]; int data[MAZE_WIDTH*MAZE_HEIGHT];
int stp;
};
int stack[MAZE_WIDTH*MAZE_HEIGHT]; void coord_stack_init(struct coord_stack* stack){
int solved = false; stack->stp=0;
char buf[30]; }
int sy = 0; void coord_stack_push(struct coord_stack* stack, int x, int y){
int sx = 0; stack->data[stack->stp] = ((x<<8)|y);
stack->stp++;
}
void coord_stack_get(struct coord_stack* stack, int index, int* x, int* y){
*y = stack->data[index];
*y &= 0xff;
*x = (stack->data[index])>>8;
}
void init_maze(void){ void coord_stack_pop(struct coord_stack* stack, int* x, int* y){
stack->stp--;
coord_stack_get(stack, stack->stp, x, y);
}
int coord_stack_count(struct coord_stack* stack){
return(stack->stp);
}
struct maze{
unsigned short maze[MAZE_WIDTH][MAZE_HEIGHT];
int solved;
int player_x;
int player_y;
};
void maze_init(struct maze* maze){
int x, y; int x, y;
rb->memset(maze->maze, 0, sizeof(maze->maze));
rb->memset(maze, 0, sizeof(maze)); maze->solved = false;
sx = 0; maze->player_x = 0;
sy = 0; maze->player_y = 0;
for(y=0; y<MAZE_HEIGHT; y++){ for(y=0; y<MAZE_HEIGHT; y++){
for(x=0; x<MAZE_WIDTH; x++){ for(x=0; x<MAZE_WIDTH; x++){
/* all walls are up */ /* all walls are up */
maze[x][y] |= WALL_ALL | PATH; maze->maze[x][y] |= WALL_ALL | PATH;
/* setup borders */ /* setup borders */
if(x == 0) if(x == 0)
maze[x][y]|= BORDER_W; maze->maze[x][y]|= BORDER_W;
if(y == 0) if(y == 0)
maze[x][y]|= BORDER_N; maze->maze[x][y]|= BORDER_N;
if(x == MAZE_WIDTH-1) if(x == MAZE_WIDTH-1)
maze[x][y]|= BORDER_E; maze->maze[x][y]|= BORDER_E;
if(y == MAZE_HEIGHT-1) if(y == MAZE_HEIGHT-1)
maze[x][y]|= BORDER_S; maze->maze[x][y]|= BORDER_S;
} }
} }
} }
void show_maze(void){ void maze_draw(struct maze* maze, struct screen* display){
int x, y; int x, y;
int wx, wy; int wx, wy;
int point_width, point_height, point_offset_x, point_offset_y;
unsigned short cell; unsigned short cell;
wx = (int) LCD_WIDTH / MAZE_WIDTH; wx = (int) display->width / MAZE_WIDTH;
wy = (int) LCD_HEIGHT / MAZE_HEIGHT; wy = (int) display->height / MAZE_HEIGHT;
rb->lcd_clear_display(); if(wx>3){
point_width=wx-3;
point_offset_x=2;
}else{
point_width=1;
point_offset_x=1;
}
if(wy>3){
point_height=wy-3;
point_offset_y=2;
}else{
point_height=1;
point_offset_y=1;
}
display->clear_display();
for(y=0; y<MAZE_HEIGHT; y++){ for(y=0; y<MAZE_HEIGHT; y++){
for(x=0; x<MAZE_WIDTH; x++){ for(x=0; x<MAZE_WIDTH; x++){
cell = maze[x][y]; cell = maze->maze[x][y];
/* draw walls */ /* draw walls */
if(cell & WALL_N) if(cell & WALL_N)
rb->lcd_drawline(x*wx, y*wy, x*wx+wx, y*wy); display->drawline(x*wx, y*wy, x*wx+wx, y*wy);
if(cell & WALL_E) if(cell & WALL_E)
rb->lcd_drawline(x*wx+wx, y*wy, x*wx+wx, y*wy+wy); display->drawline(x*wx+wx, y*wy, x*wx+wx, y*wy+wy);
if(cell & WALL_S) if(cell & WALL_S)
rb->lcd_drawline(x*wx, y*wy+wy, x*wx+wx, y*wy+wy); display->drawline(x*wx, y*wy+wy, x*wx+wx, y*wy+wy);
if(cell & WALL_W) if(cell & WALL_W)
rb->lcd_drawline(x*wx, y*wy, x*wx, y*wy+wy); display->drawline(x*wx, y*wy, x*wx, y*wy+wy);
if(cell & BORDER_N) if(cell & BORDER_N)
rb->lcd_drawline(x*wx, y*wy, x*wx+wx, y*wy); display->drawline(x*wx, y*wy, x*wx+wx, y*wy);
if(cell & BORDER_E) if(cell & BORDER_E)
rb->lcd_drawline(x*wx+wx, y*wy, x*wx+wx, y*wy+wy); display->drawline(x*wx+wx, y*wy, x*wx+wx, y*wy+wy);
if(cell & BORDER_S) if(cell & BORDER_S)
rb->lcd_drawline(x*wx, y*wy+wy, x*wx+wx, y*wy+wy); display->drawline(x*wx, y*wy+wy, x*wx+wx, y*wy+wy);
if(cell & BORDER_W) if(cell & BORDER_W)
rb->lcd_drawline(x*wx, y*wy, x*wx, y*wy+wy); display->drawline(x*wx, y*wy, x*wx, y*wy+wy);
}
if(solved){ }
if(cell & PATH){ #if (LCD_DEPTH > 1) || (defined(LCD_REMOTE_DEPTH) && (LCD_REMOTE_DEPTH > 1))
#if LCD_DEPTH >= 16 unsigned color;
rb->lcd_set_foreground( LCD_RGBPACK( 127, 127, 127 )); if(display->depth>1){
#elif LCD_DEPTH == 2 color=(display->depth>=16)?LCD_RGBPACK(127,127,127):1;
rb->lcd_set_foreground(1); display->set_foreground(color);
}
#endif #endif
rb->lcd_fillrect(x*wx+2, y*wy+2, wx-3, wy-3); if(maze->solved){
#if LCD_DEPTH >= 16 for(y=0; y<MAZE_HEIGHT; y++){
rb->lcd_set_foreground( LCD_RGBPACK( 0, 0, 0)); for(x=0; x<MAZE_WIDTH; x++){
#elif LCD_DEPTH == 2 cell = maze->maze[x][y];
rb->lcd_set_foreground(0); if(cell & PATH)
#endif display->fillrect(x*wx+point_offset_x,
} y*wy+point_offset_y,
point_width, point_height);
} }
} }
} }
#if (LCD_DEPTH > 1) || (defined(LCD_REMOTE_DEPTH) && (LCD_REMOTE_DEPTH > 1))
if(display->depth>1){
color=(display->depth>=16)?LCD_RGBPACK(0,0,0):0;
display->set_foreground(color);
}
#endif
/* mark start and end */ /* mark start and end */
rb->lcd_drawline(0, 0, wx, wy); display->drawline(0, 0, wx, wy);
rb->lcd_drawline(0, wy, wx, 0); display->drawline(0, wy, wx, 0);
rb->lcd_drawline((MAZE_WIDTH-1)*wx,(MAZE_HEIGHT-1)*wy, display->drawline((MAZE_WIDTH-1)*wx,(MAZE_HEIGHT-1)*wy,
(MAZE_WIDTH-1)*wx+wx, (MAZE_HEIGHT-1)*wy+wy); (MAZE_WIDTH-1)*wx+wx, (MAZE_HEIGHT-1)*wy+wy);
rb->lcd_drawline((MAZE_WIDTH-1)*wx,(MAZE_HEIGHT-1)*wy+wy, display->drawline((MAZE_WIDTH-1)*wx,(MAZE_HEIGHT-1)*wy+wy,
(MAZE_WIDTH-1)*wx+wx, (MAZE_HEIGHT-1)*wy); (MAZE_WIDTH-1)*wx+wx, (MAZE_HEIGHT-1)*wy);
/* draw current position */ /* draw current position */
rb->lcd_fillrect(sx*wx+2, sy*wy+2, wx-3, wy-3); display->fillrect(maze->player_x*wx+point_offset_x,
maze->player_y*wy+point_offset_y,
point_width, point_height);
rb->lcd_update(); display->update();
} }
int random_neighbour_cell_with_walls(int *px, int *py, int *pnx, int *pny){ int maze_pick_random_neighbour_cell_with_walls(struct maze* maze,
int x, int y, int *pnx, int *pny){
int ncount = 0; int ncount = 0;
int neighbours[4]; struct coord_stack neighbours;
int found_cell; unsigned short current_cell=maze->maze[x][y];
coord_stack_init(&neighbours);
/* look for neighbour cells with walls */ /* look for neighbour cells with walls */
/* north */ /* north */
if(!(maze[*px][*py] & BORDER_N)){ if(!(current_cell & BORDER_N)){
if((maze[*px][*py-1] & WALL_ALL) == WALL_ALL){ if((maze->maze[x][y-1] & WALL_ALL) == WALL_ALL){
/* save found cell coordinates */ coord_stack_push(&neighbours, x, y-1);
neighbours[ncount]=(*px<<8)|((*py)-1);
ncount++;
} }
} }
/* west */ /* west */
if(!(maze[*px][*py] & BORDER_W)){ if(!(current_cell & BORDER_W)){
if((maze[*px-1][*py] & WALL_ALL) == WALL_ALL){ if((maze->maze[x-1][y] & WALL_ALL) == WALL_ALL){
/* save found cell coordinates */ coord_stack_push(&neighbours, x-1, y);
neighbours[ncount]=((*px-1)<<8)|(*py);
ncount++;
} }
} }
/* east */ /* east */
if(!(maze[*px][*py] & BORDER_E)){ if(!(current_cell & BORDER_E)){
if((maze[*px+1][*py] & WALL_ALL) == WALL_ALL){ if((maze->maze[x+1][y] & WALL_ALL) == WALL_ALL){
/* save found cell coordinates */ coord_stack_push(&neighbours, x+1, y);
neighbours[ncount]=((*px+1)<<8)|(*py);
ncount++;
} }
} }
/* south */ /* south */
if(!(maze[*px][*py] & BORDER_S)){ if(!(current_cell & BORDER_S)){
if((maze[*px][*py+1] & WALL_ALL) == WALL_ALL){ if((maze->maze[x][y+1] & WALL_ALL) == WALL_ALL){
/* save found cell coordinates */ coord_stack_push(&neighbours, x, y+1);
neighbours[ncount]=(*px<<8)|((*py)+1);
ncount++;
} }
} }
/* randomly select neighbour cell with walls */ /* randomly select neighbour cell with walls */
if(ncount!=0){ ncount=coord_stack_count(&neighbours);
found_cell = neighbours[rb->rand()%ncount]; if(ncount!=0)
*pny = found_cell &0x000000ff; coord_stack_get(&neighbours, rb->rand()%ncount, pnx, pny);
*pnx = (unsigned int) found_cell >> 8;
}
return ncount; return ncount;
} }
void remove_walls(int *px, int *py, int *pnx, int *pny){ /* Removes the wall between the cell (x,y) and the cell (nx,ny) */
void maze_remove_wall(struct maze* maze, int x, int y, int nx, int ny){
/* where is our neighbour? */ /* where is our neighbour? */
/* north or south */ /* north or south */
if(*px==*pnx){ if(x==nx){
if(*py<*pny){ if(y<ny){
/*south*/ /*south*/
maze[*px][*py] &= ~WALL_S; maze->maze[x][y] &= ~WALL_S;
maze[*pnx][*pny] &= ~WALL_N; maze->maze[nx][ny] &= ~WALL_N;
} else { } else {
/*north*/ /*north*/
maze[*px][*py] &= ~WALL_N; maze->maze[x][y] &= ~WALL_N;
maze[*pnx][*pny] &= ~WALL_S; maze->maze[nx][ny] &= ~WALL_S;
} }
} else { } else {
/* east or west */ /* east or west */
if(*py==*pny){ if(y==ny){
if(*px<*pnx){ if(x<nx){
/* east */ /* east */
maze[*px][*py] &= ~WALL_E; maze->maze[x][y] &= ~WALL_E;
maze[*pnx][*pny] &= ~WALL_W; maze->maze[nx][ny] &= ~WALL_W;
} else { } else {
/*west*/ /*west*/
maze[*px][*py] &= ~WALL_W; maze->maze[x][y] &= ~WALL_W;
maze[*pnx][*pny] &= ~WALL_E; maze->maze[nx][ny] &= ~WALL_E;
} }
} }
} }
} }
void maze_generate(struct maze* maze){
void generate_maze(void){
int stp = 0;
int total_cells = MAZE_WIDTH * MAZE_HEIGHT; int total_cells = MAZE_WIDTH * MAZE_HEIGHT;
int visited_cells; int visited_cells;
int neighbour_cell; int available_neighbours;
int x, y; int x, y;
int nx = 0; int nx = 0;
int ny = 0; int ny = 0;
int *px, *py, *pnx, *pny; struct coord_stack done_cells;
px = &x; coord_stack_init(&done_cells);
py = &y;
pnx = &nx;
pny = &ny;
x = rb->rand()%MAZE_WIDTH; x = rb->rand()%MAZE_WIDTH;
y = rb->rand()%MAZE_HEIGHT; y = rb->rand()%MAZE_HEIGHT;
visited_cells = 1; visited_cells = 1;
while (visited_cells < total_cells){ while (visited_cells < total_cells){
neighbour_cell = random_neighbour_cell_with_walls(px, py, pnx, pny); available_neighbours =
if(neighbour_cell == 0){ maze_pick_random_neighbour_cell_with_walls(maze, x, y, &nx, &ny);
if(available_neighbours == 0){
/* pop from stack */ /* pop from stack */
stp--; coord_stack_pop(&done_cells, &x, &y);
*py = stack[stp];
*py &= 0xff;
*px = (stack[stp])>>8;
} else { } else {
remove_walls(px, py, pnx, pny); maze_remove_wall(maze, x, y, nx, ny);
/* save position on the stack */ /* save position on the stack */
stack[stp] = ((*px<<8)|*py); coord_stack_push(&done_cells, x, y);
stp++;
/* current cell = neighbour cell */ /* current cell = neighbour cell */
x=nx; x=nx;
y=ny; y=ny;
@ -328,16 +362,17 @@ void generate_maze(void){
} }
void solve_maze(void){ void maze_solve(struct maze* maze){
int x, y; int x, y;
unsigned short cell; unsigned short cell;
unsigned short w; unsigned short w;
int dead_ends = 1; int dead_ends = 1;
unsigned short solved_maze[MAZE_WIDTH][MAZE_HEIGHT];
/* dead end filler*/ maze->solved = ~(maze->solved);
/* copy maze for solving */ /* copy maze for solving */
rb->memcpy(solved_maze, maze, (MAZE_HEIGHT*MAZE_WIDTH*sizeof(maze[0][0]))); rb->memcpy(solved_maze, maze->maze, (MAZE_HEIGHT*MAZE_WIDTH*sizeof(maze->maze[0][0])));
/* remove some borders and walls on start and end point */ /* remove some borders and walls on start and end point */
@ -357,7 +392,7 @@ void solve_maze(void){
w == WALL_S || w == WALL_S ||
w == WALL_W){ w == WALL_W){
/* found dead end, clear path bit and fill it up */ /* found dead end, clear path bit and fill it up */
maze[x][y] &= ~PATH; maze->maze[x][y] &= ~PATH;
solved_maze[x][y] |= WALL_ALL; solved_maze[x][y] |= WALL_ALL;
/* don't forget the neighbours */ /* don't forget the neighbours */
if(!(cell & BORDER_N)) if(!(cell & BORDER_N))
@ -375,31 +410,66 @@ void solve_maze(void){
} }
} }
void maze_move_player_down(struct maze* maze){
unsigned short cell=maze->maze[maze->player_x][maze->player_y];
if( !(cell & WALL_S) &&
!(cell & BORDER_S)){
maze->player_y++;
}
}
void maze_move_player_up(struct maze* maze){
unsigned short cell=maze->maze[maze->player_x][maze->player_y];
if( !(cell & WALL_N) &&
!(cell & BORDER_N)){
maze->player_y--;
}
}
void maze_move_player_left(struct maze* maze){
unsigned short cell=maze->maze[maze->player_x][maze->player_y];
if( !(cell & WALL_W) &&
!(cell & BORDER_W)){
maze->player_x--;
}
}
void maze_move_player_right(struct maze* maze){
unsigned short cell=maze->maze[maze->player_x][maze->player_y];
if( !(cell & WALL_E) &&
!(cell & BORDER_E)){
maze->player_x++;
}
}
/**********************************/ /**********************************/
/* this is the plugin entry point */ /* this is the plugin entry point */
/**********************************/ /**********************************/
enum plugin_status plugin_start(struct plugin_api* api, void* parameter) enum plugin_status plugin_start(struct plugin_api* api, void* parameter){
{
int button, lastbutton = BUTTON_NONE; int button, lastbutton = BUTTON_NONE;
int quit = 0; int quit = 0;
int i;
struct maze maze;
(void)parameter; (void)parameter;
rb = api; rb = api;
rb->backlight_set_timeout(1); rb->backlight_set_timeout(1);
#if LCD_DEPTH > 1 #if LCD_DEPTH > 1
rb->lcd_set_backdrop(NULL); rb->lcd_set_backdrop(NULL);
rb->lcd_set_background(LCD_DEFAULT_BG); FOR_NB_SCREENS(i){
#if LCD_DEPTH >= 16 if(rb->screens[i]->depth>1){
rb->lcd_set_foreground( LCD_RGBPACK( 0, 0, 0)); rb->screens[i]->set_background(LCD_DEFAULT_BG);
#elif LCD_DEPTH == 2 if(rb->screens[i]->depth>=16)
rb->lcd_set_foreground(0); rb->screens[i]->set_foreground( LCD_RGBPACK( 0, 0, 0));
#endif else if(rb->screens[i]->depth==2)
rb->screens[i]->set_foreground(0);
}
}
#endif #endif
init_maze(); maze_init(&maze);
generate_maze(); maze_generate(&maze);
show_maze(); FOR_NB_SCREENS(i)
maze_draw(&maze, rb->screens[i]);
while(!quit) { while(!quit) {
#ifdef __PLUGINLIB_ACTIONS_H__ #ifdef __PLUGINLIB_ACTIONS_H__
@ -413,45 +483,40 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
if(lastbutton != MAZE_NEW_PRE) if(lastbutton != MAZE_NEW_PRE)
break; break;
#endif #endif
solved = false; maze_init(&maze);
init_maze(); maze_generate(&maze);
generate_maze(); FOR_NB_SCREENS(i)
show_maze(); maze_draw(&maze, rb->screens[i]);
break; break;
case MAZE_SOLVE: case MAZE_SOLVE:
solved = ~solved; maze_solve(&maze);
solve_maze(); FOR_NB_SCREENS(i)
show_maze(); maze_draw(&maze, rb->screens[i]);
break; break;
case MAZE_RIGHT: case MAZE_RIGHT:
case MAZE_RRIGHT: case MAZE_RRIGHT:
if( !(maze[sx][sy] & WALL_E) && !(maze[sx][sy] & BORDER_E)){ maze_move_player_right(&maze);
sx++; FOR_NB_SCREENS(i)
show_maze(); maze_draw(&maze, rb->screens[i]);
}
break; break;
case MAZE_LEFT: case MAZE_LEFT:
case MAZE_RLEFT: case MAZE_RLEFT:
if( !(maze[sx][sy] & WALL_W) && !(maze[sx][sy] & BORDER_W)){ maze_move_player_left(&maze);
sx--; FOR_NB_SCREENS(i)
show_maze(); maze_draw(&maze, rb->screens[i]);
}
break; break;
case MAZE_UP: case MAZE_UP:
case MAZE_RUP: case MAZE_RUP:
if( !(maze[sx][sy] & WALL_N) && !(maze[sx][sy] & BORDER_N)){ maze_move_player_up(&maze);
sy--; FOR_NB_SCREENS(i)
show_maze(); maze_draw(&maze, rb->screens[i]);
}
break; break;
case MAZE_DOWN: case MAZE_DOWN:
case MAZE_RDOWN: case MAZE_RDOWN:
if( !(maze[sx][sy] & WALL_S) && !(maze[sx][sy] & BORDER_S)){ maze_move_player_down(&maze);
sy++; FOR_NB_SCREENS(i)
show_maze(); maze_draw(&maze, rb->screens[i]);
}
break; break;
case MAZE_QUIT: case MAZE_QUIT:
/* quit plugin */ /* quit plugin */
quit=true; quit=true;

View file

@ -84,6 +84,7 @@ A: Fonts and Unicode
A: Replaygain A: Replaygain
A: Profiling A: Profiling
A: Screens API and GUI widgets A: Screens API and GUI widgets
M: Kévin Ferrare
A: Settings API A: Settings API
A: Language API A: Language API
A: Menu API A: Menu API
@ -149,12 +150,14 @@ A: clock
A: credits A: credits
A: cube A: cube
A: demystify A: demystify
M: Kévin Ferrare
A: dice A: dice
A: dict A: dict
A: disktidy A: disktidy
A: doom A: doom
A: euroconverter A: euroconverter
A: fire A: fire
M: Kévin Ferrare
A: fireworks A: fireworks
A: firmware_flash A: firmware_flash
A: flipit A: flipit
@ -205,6 +208,7 @@ A: spacerocks
A: splitedit A: splitedit
A: star A: star
A: starfield A: starfield
M: Kévin Ferrare
A: stats A: stats
A: stopwatch A: stopwatch
@ -332,5 +336,5 @@ Web site stuff
A: web site scripts and server-side admin A: web site scripts and server-side admin
M: Daniel Stenberg M: Daniel Stenberg
M: Björn Stenberg M: Bj<EFBFBD>rn Stenberg
M: Linus Nielsen Feltzing M: Linus Nielsen Feltzing