summaryrefslogtreecommitdiff
path: root/apps/plugins
diff options
context:
space:
mode:
authorFranklin Wei <frankhwei536@gmail.com>2014-08-19 15:20:19 -0400
committerMichael Giacomelli <giac2000@hotmail.com>2014-08-19 22:37:54 +0200
commit7ac0056beb327d7f208deb7bb3de95e08dcb704f (patch)
tree575c5e55184e43f210c845e01bc27afaecd87993 /apps/plugins
parenta9713d89e76158c6b7be4d8873a921e30efe688f (diff)
downloadrockbox-7ac0056beb327d7f208deb7bb3de95e08dcb704f.tar.gz
rockbox-7ac0056beb327d7f208deb7bb3de95e08dcb704f.zip
2048: service pack 1 :)
- fixed some bugs - added 1-bit LCD support Change-Id: I7bb458d79d799dcd6b11d9d538773404f9a7f97c Reviewed-on: http://gerrit.rockbox.org/917 Reviewed-by: Michael Giacomelli <giac2000@hotmail.com>
Diffstat (limited to 'apps/plugins')
-rw-r--r--apps/plugins/2048.c232
1 files changed, 153 insertions, 79 deletions
diff --git a/apps/plugins/2048.c b/apps/plugins/2048.c
index 30f8899974..7c2fd85668 100644
--- a/apps/plugins/2048.c
+++ b/apps/plugins/2048.c
@@ -83,10 +83,10 @@
83#define SCORE_Y (max_numeral_height) 83#define SCORE_Y (max_numeral_height)
84#define BEST_SCORE_X 0 84#define BEST_SCORE_X 0
85#define BEST_SCORE_Y (2*max_numeral_height) 85#define BEST_SCORE_Y (2*max_numeral_height)
86#endif 86#endif /* LCD_WIDTH<LCD_HEIGHT */
87 87
88#define BACKGROUND_X (BASE_X-MIN_SPACE) 88#define BACKGROUND_X (int)(BASE_X-MIN_SPACE)
89#define BACKGROUND_Y (BASE_Y-MIN_SPACE) 89#define BACKGROUND_Y (int)(BASE_Y-MIN_SPACE)
90 90
91/* key mappings */ 91/* key mappings */
92 92
@@ -121,6 +121,9 @@ static struct game_ctx_t *ctx=&ctx_data;
121static bool merged_grid[GRID_SIZE][GRID_SIZE]; 121static bool merged_grid[GRID_SIZE][GRID_SIZE];
122static int old_grid[GRID_SIZE][GRID_SIZE]; 122static int old_grid[GRID_SIZE][GRID_SIZE];
123static int max_numeral_height=-1; 123static int max_numeral_height=-1;
124#if LCD_DEPTH <= 1
125static int max_numeral_width;
126#endif
124static bool loaded=false; 127static bool loaded=false;
125 128
126/* first init_game will set this, when it is exceeded, it will be updated in the slide functions */ 129/* first init_game will set this, when it is exceeded, it will be updated in the slide functions */
@@ -180,7 +183,8 @@ static bool do_help(void)
180static inline void slide_internal(int startx, int starty, 183static inline void slide_internal(int startx, int starty,
181 int stopx, int stopy, 184 int stopx, int stopy,
182 int dx, int dy, 185 int dx, int dy,
183 int lookx, int looky) 186 int lookx, int looky,
187 bool update_best)
184{ 188{
185 int best_score_before=best_score; 189 int best_score_before=best_score;
186 for(int y=starty;y!=stopy;y+=dy) 190 for(int y=starty;y!=stopy;y+=dy)
@@ -202,7 +206,7 @@ static inline void slide_internal(int startx, int starty,
202 } 206 }
203 } 207 }
204 } 208 }
205 if(ctx->score>best_score_before) 209 if(ctx->score>best_score_before && update_best)
206 best_score=ctx->score; 210 best_score=ctx->score;
207} 211}
208 212
@@ -215,12 +219,13 @@ static inline void slide_internal(int startx, int starty,
215 3 ^ ^ ^ ^ 219 3 ^ ^ ^ ^
216 0 1 2 3 220 0 1 2 3
217*/ 221*/
218static void up(void) 222static void up(bool update_best)
219{ 223{
220 slide_internal(0, 1, /* start values */ 224 slide_internal(0, 1, /* start values */
221 GRID_SIZE, GRID_SIZE, /* stop values */ 225 GRID_SIZE, GRID_SIZE, /* stop values */
222 1, 1, /* delta values */ 226 1, 1, /* delta values */
223 0, -1); /* lookahead values */ 227 0, -1, /* lookahead values */
228 update_best);
224} 229}
225/* Down 230/* Down
226 0 v v v v 231 0 v v v v
@@ -229,12 +234,13 @@ static void up(void)
229 3 234 3
230 0 1 2 3 235 0 1 2 3
231*/ 236*/
232static void down(void) 237static void down(bool update_best)
233{ 238{
234 slide_internal(0, GRID_SIZE-2, 239 slide_internal(0, GRID_SIZE-2,
235 GRID_SIZE, -1, 240 GRID_SIZE, -1,
236 1, -1, 241 1, -1,
237 0, 1); 242 0, 1,
243 update_best);
238} 244}
239/* Left 245/* Left
240 0 < < < 246 0 < < <
@@ -243,12 +249,13 @@ static void down(void)
243 3 < < < 249 3 < < <
244 0 1 2 3 250 0 1 2 3
245*/ 251*/
246static void left(void) 252static void left(bool update_best)
247{ 253{
248 slide_internal(1, 0, 254 slide_internal(1, 0,
249 GRID_SIZE, GRID_SIZE, 255 GRID_SIZE, GRID_SIZE,
250 1, 1, 256 1, 1,
251 -1, 0); 257 -1, 0,
258 update_best);
252} 259}
253/* Right 260/* Right
254 0 > > > 261 0 > > >
@@ -257,12 +264,13 @@ static void left(void)
257 3 > > > 264 3 > > >
258 0 1 2 3 265 0 1 2 3
259*/ 266*/
260static void right(void) 267static void right(bool update_best)
261{ 268{
262 slide_internal(GRID_SIZE-2, 0, /* start */ 269 slide_internal(GRID_SIZE-2, 0, /* start */
263 -1, GRID_SIZE, /* stop */ 270 -1, GRID_SIZE, /* stop */
264 -1, 1, /* delta */ 271 -1, 1, /* delta */
265 1, 0); /* lookahead */ 272 1, 0, /* lookahead */
273 update_best);
266} 274}
267 275
268/* slightly modified version of base 2 log, returns 1 when given zero, and log2(n)+1 for anything else */ 276/* slightly modified version of base 2 log, returns 1 when given zero, and log2(n)+1 for anything else */
@@ -279,6 +287,7 @@ static inline int ilog2(int n)
279 } 287 }
280 return log+1; 288 return log+1;
281} 289}
290#if LCD_DEPTH > 1
282static void draw(void) 291static void draw(void)
283{ 292{
284#ifdef HAVE_LCD_COLOR 293#ifdef HAVE_LCD_COLOR
@@ -318,13 +327,22 @@ static void draw(void)
318 int w, h; 327 int w, h;
319 rb->lcd_setfont(FONT_UI); 328 rb->lcd_setfont(FONT_UI);
320 rb->font_getstringsize(buf, &w, &h, FONT_UI); 329 rb->font_getstringsize(buf, &w, &h, FONT_UI);
330 bool draw_title=true;
321 if(w+TITLE_X>=BACKGROUND_X && h+TITLE_Y>=BACKGROUND_Y) 331 if(w+TITLE_X>=BACKGROUND_X && h+TITLE_Y>=BACKGROUND_Y)
322 { 332 {
323 /* if it goes into the grid, use the system font, which should be smaller */ 333 /* if it goes into the grid, use the system font, which should be smaller */
324 rb->lcd_setfont(FONT_SYSFIXED); 334 rb->lcd_setfont(FONT_SYSFIXED);
335 rb->font_getstringsize(buf, &w, &h, FONT_SYSFIXED);
336 if(w+TITLE_X>=BACKGROUND_X && h+TITLE_Y>=BACKGROUND_Y)
337 {
338 /* title can't fit, don't draw it */
339 draw_title=false;
340 h=0;
341 }
325 } 342 }
326 rb->lcd_putsxy(TITLE_X, TITLE_Y, buf); 343 if(draw_title)
327 344 rb->lcd_putsxy(TITLE_X, TITLE_Y, buf);
345 int score_y=TITLE_Y+h+VERT_SPACING;
328 /* draw the score */ 346 /* draw the score */
329 rb->snprintf(buf, 31, "Score: %d", ctx->score); 347 rb->snprintf(buf, 31, "Score: %d", ctx->score);
330#ifdef HAVE_LCD_COLOR 348#ifdef HAVE_LCD_COLOR
@@ -366,13 +384,18 @@ static void draw(void)
366 384
367 /* as a last resort, don't use Score: and use the system font */ 385 /* as a last resort, don't use Score: and use the system font */
368 rb->snprintf(buf, 31, "%d", ctx->score); 386 rb->snprintf(buf, 31, "%d", ctx->score);
387 rb->font_getstringsize(buf, &w, &h, FONT_SYSFIXED);
369 rb->lcd_setfont(FONT_SYSFIXED); 388 rb->lcd_setfont(FONT_SYSFIXED);
389 if(w+SCORE_X<BACKGROUND_X)
390 goto draw_lbl;
391 else
392 goto skip_draw_score;
370 } 393 }
371draw_lbl: 394draw_lbl:
372 rb->lcd_putsxy(SCORE_X, SCORE_Y, buf); 395 rb->lcd_putsxy(SCORE_X, score_y, buf);
373 396 score_y+=h+VERT_SPACING;
374 /* draw the best score */ 397 /* draw the best score */
375 398skip_draw_score:
376 rb->snprintf(buf, 31, "Best: %d", best_score); 399 rb->snprintf(buf, 31, "Best: %d", best_score);
377#ifdef HAVE_LCD_COLOR 400#ifdef HAVE_LCD_COLOR
378 rb->lcd_set_foreground(LCD_WHITE); 401 rb->lcd_set_foreground(LCD_WHITE);
@@ -413,16 +436,70 @@ draw_lbl:
413 436
414 /* as a last resort, don't use Score: and use the system font */ 437 /* as a last resort, don't use Score: and use the system font */
415 rb->snprintf(buf, 31, "%d", best_score); 438 rb->snprintf(buf, 31, "%d", best_score);
439 rb->font_getstringsize(buf, &w, &h, FONT_SYSFIXED);
416 rb->lcd_setfont(FONT_SYSFIXED); 440 rb->lcd_setfont(FONT_SYSFIXED);
441 if(w+BEST_SCORE_X<BACKGROUND_X)
442 goto draw_best;
443 else
444 goto skip_draw_best;
417 } 445 }
418draw_best: 446draw_best:
419 rb->lcd_putsxy(BEST_SCORE_X, BEST_SCORE_Y, buf); 447 rb->lcd_putsxy(BEST_SCORE_X, score_y, buf);
420 448skip_draw_best:
421 rb->lcd_update(); 449 rb->lcd_update();
422 /* revert the font back */ 450 /* revert the font back */
423 rb->lcd_setfont(WHAT_FONT); 451 rb->lcd_setfont(WHAT_FONT);
424} 452}
453#else /* LCD_DEPTH > 1 */
454/* 1-bit display :( */
455/* bitmaps are unreadable with these screens, so just resort to text */
456static void draw(void)
457{
458 rb->lcd_clear_display();
459 /* Draw the grid */
460 /* find the biggest tile */
461 int biggest_tile=-1;
462 for(int x=0;x<GRID_SIZE;++x)
463 {
464 for(int y=0;y<GRID_SIZE;++y)
465 if(ctx->grid[x][y]>biggest_tile)
466 biggest_tile=ctx->grid[x][y];
467 }
468 char str[32];
469 rb->snprintf(str, 31,"%d", biggest_tile);
470 int biggest_tile_width=rb->strlen(str)*rb->font_get_width(rb->font_get(WHAT_FONT), '0')+MIN_SPACE;
471 for(int y=0;y<GRID_SIZE;++y)
472 {
473 for(int x=0;x<GRID_SIZE;++x)
474 {
475 if(ctx->grid[x][y])
476 {
477 if(ctx->grid[x][y]>biggest_tile)
478 biggest_tile=ctx->grid[x][y];
479 rb->snprintf(str,31,"%d", ctx->grid[x][y]);
480 rb->lcd_putsxy(biggest_tile_width*x,y*max_numeral_height+max_numeral_height,str);
481 }
482 }
483 }
484 /* Now draw the score, and the game title */
485 rb->snprintf(str, 31, "Score: %d", ctx->score);
486 int str_width, str_height;
487 rb->font_getstringsize(str, &str_width, &str_height, WHAT_FONT);
488 int score_leftmost=LCD_WIDTH-str_width-1;
489 /* Check if there is enough space to display "Score: ", otherwise, only display the score */
490 if(score_leftmost>=0)
491 rb->lcd_putsxy(score_leftmost,0,str);
492 else
493 rb->lcd_putsxy(score_leftmost,0,str+rb->strlen("Score: "));
494 /* Reuse the same string for the title */
425 495
496 rb->snprintf(str, 31, "%d", WINNING_TILE);
497 rb->font_getstringsize(str, &str_width, &str_height, WHAT_FONT);
498 if(str_width<score_leftmost)
499 rb->lcd_putsxy(0,0,str);
500 rb->lcd_update();
501}
502#endif /* LCD_DEPTH > 1 */
426/* place a 2 or 4 in a random empty space */ 503/* place a 2 or 4 in a random empty space */
427static void place_random(void) 504static void place_random(void)
428{ 505{
@@ -455,74 +532,66 @@ static void restore_old_grid(void)
455/* checks for a win or loss */ 532/* checks for a win or loss */
456static bool check_gameover(void) 533static bool check_gameover(void)
457{ 534{
458 int numempty=0; 535 /* first, check for a loss */
536 int oldscore=ctx->score;
537 bool have_legal_move=false;
538 memset(&merged_grid,0,SPACES*sizeof(bool));
539 up(false);
540 if(memcmp(&old_grid, &ctx->grid, sizeof(int)*SPACES))
541 {
542 restore_old_grid();
543 ctx->score=oldscore;
544 have_legal_move=true;
545 }
546 restore_old_grid();
547 memset(&merged_grid,0,SPACES*sizeof(bool));
548 down(false);
549 if(memcmp(&old_grid, &ctx->grid, sizeof(int)*SPACES))
550 {
551 restore_old_grid();
552 ctx->score=oldscore;
553 have_legal_move=true;
554 }
555 restore_old_grid();
556 memset(&merged_grid,0,SPACES*sizeof(bool));
557 left(false);
558 if(memcmp(&old_grid, &ctx->grid, sizeof(int)*SPACES))
559 {
560 restore_old_grid();
561 ctx->score=oldscore;
562 have_legal_move=true;
563 }
564 restore_old_grid();
565 memset(&merged_grid,0,SPACES*sizeof(bool));
566 right(false);
567 if(memcmp(&old_grid, &ctx->grid, sizeof(int)*SPACES))
568 {
569 restore_old_grid();
570 ctx->score=oldscore;
571 have_legal_move=true;
572 }
573 ctx->score=oldscore;
574 if(!have_legal_move)
575 {
576 /* no more legal moves */
577 draw(); /* Shame the player :) */
578 rb->splash(HZ*2, "Game Over!");
579 return true;
580 }
459 for(int y=0;y<GRID_SIZE;++y) 581 for(int y=0;y<GRID_SIZE;++y)
460 { 582 {
461 for(int x=0;x<GRID_SIZE;++x) 583 for(int x=0;x<GRID_SIZE;++x)
462 { 584 {
463 if(ctx->grid[x][y]==0)
464 ++numempty;
465 if(ctx->grid[x][y]==WINNING_TILE && !ctx->already_won) 585 if(ctx->grid[x][y]==WINNING_TILE && !ctx->already_won)
466 { 586 {
467 /* Let the user see the tile in its full glory... */ 587 /* Let the user see the tile in its full glory... */
468 draw(); 588 draw();
469 ctx->already_won=true; 589 ctx->already_won=true;
470 rb->splash(HZ*2,"You win!"); 590 rb->splash(HZ*2,"You win!");
471 const struct text_message prompt={(const char*[]){"Keep going?"}, 1}; 591 /* don't let the user quit here :) */
472 enum yesno_res keepgoing=rb->gui_syncyesno_run(&prompt, NULL, NULL);
473 if(keepgoing==YESNO_NO)
474 return true;
475 else
476 return false;
477 } 592 }
478 } 593 }
479 } 594 }
480 if(!numempty)
481 {
482 /* No empty spaces, check for valid moves */
483 /* Then, get the current score */
484 int oldscore=ctx->score;
485 memset(&merged_grid,0,SPACES*sizeof(bool));
486 up();
487 if(memcmp(&old_grid, &ctx->grid, sizeof(int)*SPACES))
488 {
489 restore_old_grid();
490 ctx->score=oldscore;
491 return false;
492 }
493 restore_old_grid();
494 memset(&merged_grid,0,SPACES*sizeof(bool));
495 down();
496 if(memcmp(&old_grid, &ctx->grid, sizeof(int)*SPACES))
497 {
498 restore_old_grid();
499 ctx->score=oldscore;
500 return false;
501 }
502 restore_old_grid();
503 memset(&merged_grid,0,SPACES*sizeof(bool));
504 left();
505 if(memcmp(&old_grid, &ctx->grid, sizeof(int)*SPACES))
506 {
507 restore_old_grid();
508 ctx->score=oldscore;
509 return false;
510 }
511 restore_old_grid();
512 memset(&merged_grid,0,SPACES*sizeof(bool));
513 right();
514 if(memcmp(&old_grid, &ctx->grid, sizeof(int)*SPACES))
515 {
516 restore_old_grid();
517 ctx->score=oldscore;
518 return false;
519 }
520 /* no more legal moves */
521 ctx->score=oldscore;
522 draw(); /* Shame the player :) */
523 rb->splash(HZ*2, "Game Over!");
524 return true;
525 }
526 return false; 595 return false;
527} 596}
528 597
@@ -540,6 +609,8 @@ static void load_hs(void)
540static void init_game(bool newgame) 609static void init_game(bool newgame)
541{ 610{
542 best_score=highscores[0].score; 611 best_score=highscores[0].score;
612 if(loaded && ctx->score > best_score)
613 best_score=ctx->score;
543 if(newgame) 614 if(newgame)
544 { 615 {
545 /* initialize the game context */ 616 /* initialize the game context */
@@ -558,6 +629,9 @@ static void init_game(bool newgame)
558 /* Now get the height of the font */ 629 /* Now get the height of the font */
559 rb->font_getstringsize("0123456789", NULL, &max_numeral_height,WHAT_FONT); 630 rb->font_getstringsize("0123456789", NULL, &max_numeral_height,WHAT_FONT);
560 max_numeral_height+=VERT_SPACING; 631 max_numeral_height+=VERT_SPACING;
632#if LCD_DEPTH <= 1
633 max_numeral_width=rb->font_get_width(rb->font_get(WHAT_FONT), '0');
634#endif
561 backlight_ignore_timeout(); 635 backlight_ignore_timeout();
562 rb->lcd_clear_display(); 636 rb->lcd_clear_display();
563 draw(); 637 draw();
@@ -735,7 +809,7 @@ static enum plugin_status do_game(bool newgame)
735 for(int i=0;i<GRID_SIZE-1;++i) 809 for(int i=0;i<GRID_SIZE-1;++i)
736 { 810 {
737 memcpy(grid_before_anim_step, ctx->grid, sizeof(int)*SPACES); 811 memcpy(grid_before_anim_step, ctx->grid, sizeof(int)*SPACES);
738 up(); 812 up(true);
739 if(memcmp(grid_before_anim_step, ctx->grid, sizeof(int)*SPACES)) 813 if(memcmp(grid_before_anim_step, ctx->grid, sizeof(int)*SPACES))
740 { 814 {
741 rb->sleep(ANIM_SLEEPTIME); 815 rb->sleep(ANIM_SLEEPTIME);
@@ -748,7 +822,7 @@ static enum plugin_status do_game(bool newgame)
748 for(int i=0;i<GRID_SIZE-1;++i) 822 for(int i=0;i<GRID_SIZE-1;++i)
749 { 823 {
750 memcpy(grid_before_anim_step, ctx->grid, sizeof(int)*SPACES); 824 memcpy(grid_before_anim_step, ctx->grid, sizeof(int)*SPACES);
751 down(); 825 down(true);
752 if(memcmp(grid_before_anim_step, ctx->grid, sizeof(int)*SPACES)) 826 if(memcmp(grid_before_anim_step, ctx->grid, sizeof(int)*SPACES))
753 { 827 {
754 rb->sleep(ANIM_SLEEPTIME); 828 rb->sleep(ANIM_SLEEPTIME);
@@ -761,7 +835,7 @@ static enum plugin_status do_game(bool newgame)
761 for(int i=0;i<GRID_SIZE-1;++i) 835 for(int i=0;i<GRID_SIZE-1;++i)
762 { 836 {
763 memcpy(grid_before_anim_step, ctx->grid, sizeof(int)*SPACES); 837 memcpy(grid_before_anim_step, ctx->grid, sizeof(int)*SPACES);
764 left(); 838 left(true);
765 if(memcmp(grid_before_anim_step, ctx->grid, sizeof(int)*SPACES)) 839 if(memcmp(grid_before_anim_step, ctx->grid, sizeof(int)*SPACES))
766 { 840 {
767 rb->sleep(ANIM_SLEEPTIME); 841 rb->sleep(ANIM_SLEEPTIME);
@@ -774,7 +848,7 @@ static enum plugin_status do_game(bool newgame)
774 for(int i=0;i<GRID_SIZE-1;++i) 848 for(int i=0;i<GRID_SIZE-1;++i)
775 { 849 {
776 memcpy(grid_before_anim_step, ctx->grid, sizeof(int)*SPACES); 850 memcpy(grid_before_anim_step, ctx->grid, sizeof(int)*SPACES);
777 right(); 851 right(true);
778 if(memcmp(grid_before_anim_step, ctx->grid, sizeof(int)*SPACES)) 852 if(memcmp(grid_before_anim_step, ctx->grid, sizeof(int)*SPACES))
779 { 853 {
780 rb->sleep(ANIM_SLEEPTIME); 854 rb->sleep(ANIM_SLEEPTIME);