diff options
author | Franklin Wei <frankhwei536@gmail.com> | 2015-04-01 18:15:29 -0400 |
---|---|---|
committer | Gerrit Rockbox <gerrit@rockbox.org> | 2015-04-19 17:48:12 +0200 |
commit | d8ee5fcfc4282b4ed2cc002e3c11ce9bf5c44572 (patch) | |
tree | f711fee8773e9fea0a9ea409aeff5702990c4cef | |
parent | 24533635c0c47964db1e17d70655fa4161be5fba (diff) | |
download | rockbox-d8ee5fcfc4282b4ed2cc002e3c11ce9bf5c44572.tar.gz rockbox-d8ee5fcfc4282b4ed2cc002e3c11ce9bf5c44572.zip |
2048: Cleanup
- more whitespace to enhance readability
- better/fixed/more comments ;)
- some minor optimizations
- general code cleanup
Change-Id: I2b5f69aba0f83f989abb2c636920646e4315583f
-rw-r--r-- | apps/plugins/2048.c | 684 |
1 files changed, 391 insertions, 293 deletions
diff --git a/apps/plugins/2048.c b/apps/plugins/2048.c index 7c2fd85668..15d3f41191 100644 --- a/apps/plugins/2048.c +++ b/apps/plugins/2048.c | |||
@@ -46,50 +46,49 @@ | |||
46 | #include "pluginbitmaps/_2048_tiles.h" | 46 | #include "pluginbitmaps/_2048_tiles.h" |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | /* defines */ | 49 | /* some constants */ |
50 | 50 | ||
51 | #define ANIM_SLEEPTIME (HZ/20) | 51 | static const int ANIM_SLEEPTIME = (HZ/20); |
52 | static const int NUM_STARTING_TILES = 2; | ||
53 | static const int VERT_SPACING = 4; | ||
54 | static const int WHAT_FONT = FONT_UI; | ||
55 | static const unsigned int WINNING_TILE = 2048; | ||
56 | |||
57 | /* must use macros for these */ | ||
52 | #define GRID_SIZE 4 | 58 | #define GRID_SIZE 4 |
53 | #define HISCORES_FILE PLUGIN_GAMES_DATA_DIR "/2048.score" | 59 | #define HISCORES_FILE PLUGIN_GAMES_DATA_DIR "/2048.score" |
60 | #define MIN_SPACE (BMPHEIGHT__2048_tiles * 0.134) | ||
54 | #define NUM_SCORES 5 | 61 | #define NUM_SCORES 5 |
55 | #define NUM_STARTING_TILES 2 | ||
56 | #define RESUME_FILE PLUGIN_GAMES_DATA_DIR "/2048.save" | 62 | #define RESUME_FILE PLUGIN_GAMES_DATA_DIR "/2048.save" |
57 | #define WHAT_FONT FONT_UI | 63 | #define SPACES (GRID_SIZE * GRID_SIZE) |
58 | #define SPACES (GRID_SIZE*GRID_SIZE) | ||
59 | #define MIN_SPACE (BMPHEIGHT__2048_tiles*0.134) /* space between tiles */ | ||
60 | #define MAX_UNDOS 64 | ||
61 | #define VERT_SPACING 4 | ||
62 | #define WINNING_TILE 2048 | ||
63 | 64 | ||
64 | /* screen-specific configuration */ | 65 | /* screen-specific configuration */ |
65 | 66 | ||
66 | #if LCD_WIDTH<LCD_HEIGHT | 67 | #if (LCD_WIDTH < LCD_HEIGHT) /* tall screens */ |
67 | /* tall screens */ | 68 | # define TITLE_X 0 |
68 | #define TITLE_X 0 | 69 | # define TITLE_Y 0 |
69 | #define TITLE_Y 0 | 70 | # define BASE_Y (BMPHEIGHT__2048_tiles*1.5) |
70 | #define BASE_Y (BMPHEIGHT__2048_tiles*1.5) | 71 | # define BASE_X (BMPHEIGHT__2048_tiles*.5-MIN_SPACE) |
71 | #define BASE_X (BMPHEIGHT__2048_tiles*.5-MIN_SPACE) | 72 | # define SCORE_X 0 |
72 | #define SCORE_X 0 | 73 | # define SCORE_Y (max_numeral_height) |
73 | #define SCORE_Y (max_numeral_height) | 74 | # define BEST_SCORE_X 0 |
74 | #define BEST_SCORE_X 0 | 75 | # define BEST_SCORE_Y (2*max_numeral_height) |
75 | #define BEST_SCORE_Y (2*max_numeral_height) | 76 | #else /* wide or square screens */ |
76 | #else | 77 | # define TITLE_X 0 |
77 | /* wide screens or square screens*/ | 78 | # define TITLE_Y 0 |
78 | #define TITLE_X 0 | 79 | # define BASE_X (LCD_WIDTH-(GRID_SIZE*BMPHEIGHT__2048_tiles)-(((GRID_SIZE+1)*MIN_SPACE))) |
79 | #define TITLE_Y 0 | 80 | # define BASE_Y (BMPHEIGHT__2048_tiles*.5-MIN_SPACE) |
80 | #define BASE_X (LCD_WIDTH-(GRID_SIZE*BMPHEIGHT__2048_tiles)-(((GRID_SIZE+1)*MIN_SPACE))) | 81 | # define SCORE_X 0 |
81 | #define BASE_Y (BMPHEIGHT__2048_tiles*.5-MIN_SPACE) | 82 | # define SCORE_Y (max_numeral_height) |
82 | #define SCORE_X 0 | 83 | # define BEST_SCORE_X 0 |
83 | #define SCORE_Y (max_numeral_height) | 84 | # define BEST_SCORE_Y (2*max_numeral_height) |
84 | #define BEST_SCORE_X 0 | 85 | #endif /* LCD_WIDTH < LCD_HEIGHT */ |
85 | #define BEST_SCORE_Y (2*max_numeral_height) | ||
86 | #endif /* LCD_WIDTH<LCD_HEIGHT */ | ||
87 | |||
88 | #define BACKGROUND_X (int)(BASE_X-MIN_SPACE) | ||
89 | #define BACKGROUND_Y (int)(BASE_Y-MIN_SPACE) | ||
90 | 86 | ||
91 | /* key mappings */ | 87 | /* where to draw the background bitmap */ |
88 | static const int BACKGROUND_X = (BASE_X-MIN_SPACE); | ||
89 | static const int BACKGROUND_Y = (BASE_Y-MIN_SPACE); | ||
92 | 90 | ||
91 | /* key mappings */ | ||
93 | #define KEY_UP PLA_UP | 92 | #define KEY_UP PLA_UP |
94 | #define KEY_DOWN PLA_DOWN | 93 | #define KEY_DOWN PLA_DOWN |
95 | #define KEY_LEFT PLA_LEFT | 94 | #define KEY_LEFT PLA_LEFT |
@@ -97,48 +96,58 @@ | |||
97 | #define KEY_EXIT PLA_CANCEL | 96 | #define KEY_EXIT PLA_CANCEL |
98 | #define KEY_UNDO PLA_SELECT | 97 | #define KEY_UNDO PLA_SELECT |
99 | 98 | ||
99 | /* notice how "color" is spelled :P */ | ||
100 | #ifdef HAVE_LCD_COLOR | ||
101 | |||
100 | /* colors */ | 102 | /* colors */ |
101 | 103 | ||
102 | #define BACKGROUND (LCD_RGBPACK(0xfa, 0xf8, 0xef)) | 104 | static const unsigned BACKGROUND = LCD_RGBPACK(0xfa, 0xf8, 0xef); |
103 | #define BOARD_BACKGROUND (LCD_RGBPACK(0xbb, 0xad, 0xa0)) | 105 | static const unsigned BOARD_BACKGROUND = LCD_RGBPACK(0xbb, 0xad, 0xa0); |
104 | #define TEXT_COLOR (LCD_RGBPACK(0x77, 0x6e, 0x65)) | 106 | static const unsigned TEXT_COLOR = LCD_RGBPACK(0x77, 0x6e, 0x65); |
107 | |||
108 | #endif | ||
105 | 109 | ||
110 | /* PLA data */ | ||
106 | static const struct button_mapping *plugin_contexts[] = { pla_main_ctx }; | 111 | static const struct button_mapping *plugin_contexts[] = { pla_main_ctx }; |
107 | 112 | ||
108 | /* game data */ | 113 | /*** game data structures ***/ |
114 | |||
109 | struct game_ctx_t { | 115 | struct game_ctx_t { |
110 | int grid[GRID_SIZE][GRID_SIZE]; | 116 | unsigned int grid[GRID_SIZE][GRID_SIZE]; /* 0 = empty */ |
111 | int score; | 117 | unsigned int score; |
112 | int cksum; /* sum of grid, XORed by score */ | 118 | unsigned int cksum; /* sum of grid, XORed by score */ |
113 | bool already_won; | 119 | bool already_won; /* has the player gotten 2048 yet? */ |
114 | }; | 120 | } game_ctx; |
121 | |||
122 | static struct game_ctx_t *ctx = &game_ctx; | ||
115 | 123 | ||
116 | static struct game_ctx_t ctx_data; | 124 | /*** temporary data ***/ |
117 | /* use a pointer to make save/load easier */ | ||
118 | static struct game_ctx_t *ctx=&ctx_data; | ||
119 | 125 | ||
120 | /* temporary data */ | ||
121 | static bool merged_grid[GRID_SIZE][GRID_SIZE]; | 126 | static bool merged_grid[GRID_SIZE][GRID_SIZE]; |
122 | static int old_grid[GRID_SIZE][GRID_SIZE]; | 127 | static int old_grid[GRID_SIZE][GRID_SIZE]; |
123 | static int max_numeral_height=-1; | 128 | |
129 | static int max_numeral_height = -1; | ||
130 | |||
124 | #if LCD_DEPTH <= 1 | 131 | #if LCD_DEPTH <= 1 |
125 | static int max_numeral_width; | 132 | static int max_numeral_width; |
126 | #endif | 133 | #endif |
127 | static bool loaded=false; | ||
128 | 134 | ||
129 | /* first init_game will set this, when it is exceeded, it will be updated in the slide functions */ | 135 | static bool loaded = false; /* has a save been loaded? */ |
130 | static int best_score; | 136 | |
137 | /* the high score */ | ||
138 | static unsigned int best_score; | ||
131 | 139 | ||
132 | static bool abnormal_exit=true; | 140 | static bool abnormal_exit = true; |
133 | static struct highscore highscores[NUM_SCORES]; | 141 | static struct highscore highscores[NUM_SCORES]; |
134 | 142 | ||
135 | /* returns a random int between min and max */ | 143 | /***************************** UTILITY FUNCTIONS *****************************/ |
144 | |||
136 | static inline int rand_range(int min, int max) | 145 | static inline int rand_range(int min, int max) |
137 | { | 146 | { |
138 | return rb->rand()%(max-min+1)+min; | 147 | return rb->rand() % (max-min + 1) + min; |
139 | } | 148 | } |
140 | 149 | ||
141 | /* prepares to exit */ | 150 | /* prepares for exit */ |
142 | static void cleanup(void) | 151 | static void cleanup(void) |
143 | { | 152 | { |
144 | backlight_use_settings(); | 153 | backlight_use_settings(); |
@@ -148,66 +157,77 @@ static void cleanup(void) | |||
148 | static inline int rand_2_or_4(void) | 157 | static inline int rand_2_or_4(void) |
149 | { | 158 | { |
150 | /* 1 in 10 chance of a four */ | 159 | /* 1 in 10 chance of a four */ |
151 | if(rb->rand()%10==0) | 160 | if(rb->rand() % 10 == 0) |
152 | return 4; | 161 | return 4; |
153 | else | 162 | else |
154 | return 2; | 163 | return 2; |
155 | } | 164 | } |
156 | 165 | ||
157 | /* display the help text */ | 166 | /* displays the help text */ |
158 | static bool do_help(void) | 167 | static bool do_help(void) |
159 | { | 168 | { |
169 | |||
160 | #ifdef HAVE_LCD_COLOR | 170 | #ifdef HAVE_LCD_COLOR |
161 | rb->lcd_set_foreground(LCD_WHITE); | 171 | rb->lcd_set_foreground(LCD_WHITE); |
162 | rb->lcd_set_background(LCD_BLACK); | 172 | rb->lcd_set_background(LCD_BLACK); |
163 | #endif | 173 | #endif |
174 | |||
164 | rb->lcd_setfont(FONT_UI); | 175 | rb->lcd_setfont(FONT_UI); |
165 | char* help_text[]= {"2048", "", "Aim", | 176 | |
166 | "", "Join", "the", "numbers", "to", "get", "to", "the", "2048", "tile!", "", "", | 177 | static char* help_text[]= {"2048", "", "Aim", |
167 | "How", "to", "Play", "", | 178 | "", "Join", "the", "numbers", "to", "get", "to", "the", "2048", "tile!", "", "", |
168 | "", "Use", "the", "directional", "keys", "to", "move", "the", "tiles.", "When", | 179 | "How", "to", "Play", "", |
169 | "two", "tiles", "with", "the", "same", "number", "touch,", "they", "merge", "into", "one!"}; | 180 | "", "Use", "the", "directional", "keys", "to", "move", "the", "tiles.", "When", |
170 | struct style_text style[]={ | 181 | "two", "tiles", "with", "the", "same", "number", "touch,", "they", "merge", "into", "one!"}; |
171 | {0, TEXT_CENTER|TEXT_UNDERLINE}, | 182 | |
172 | {2, C_RED}, | 183 | struct style_text style[] = { |
173 | {15, C_RED}, {16, C_RED}, {17,C_RED}, | 184 | {0, TEXT_CENTER | TEXT_UNDERLINE}, |
185 | {2, C_RED}, | ||
186 | {15, C_RED}, | ||
187 | {16, C_RED}, | ||
188 | {17, C_RED}, | ||
174 | LAST_STYLE_ITEM | 189 | LAST_STYLE_ITEM |
175 | }; | 190 | }; |
176 | return display_text(ARRAYLEN(help_text), help_text, style,NULL,true); | ||
177 | } | ||
178 | 191 | ||
179 | /*** the logic for sliding ***/ | 192 | return display_text(ARRAYLEN(help_text), help_text, style, NULL, true); |
193 | } | ||
180 | 194 | ||
181 | /* this is the helper function that does the actual tile moving */ | 195 | /*** tile movement logic ***/ |
182 | 196 | ||
197 | /* this function performs the tile movement */ | ||
183 | static inline void slide_internal(int startx, int starty, | 198 | static inline void slide_internal(int startx, int starty, |
184 | int stopx, int stopy, | 199 | int stopx, int stopy, |
185 | int dx, int dy, | 200 | int dx, int dy, |
186 | int lookx, int looky, | 201 | int lookx, int looky, |
187 | bool update_best) | 202 | bool update_best) |
188 | { | 203 | { |
189 | int best_score_before=best_score; | 204 | unsigned int best_score_old = best_score; |
190 | for(int y=starty;y!=stopy;y+=dy) | 205 | |
206 | /* loop over the rows or columns, moving the tiles in the specified direction */ | ||
207 | for(int y = starty; y != stopy; y += dy) | ||
191 | { | 208 | { |
192 | for(int x=startx;x!=stopx;x+=dx) | 209 | for(int x = startx; x != stopx; x += dx) |
193 | { | 210 | { |
194 | if(ctx->grid[x+lookx][y+looky]==ctx->grid[x][y] && ctx->grid[x][y] && !merged_grid[x+lookx][y+looky] && !merged_grid[x][y]) /* Slide into */ | 211 | if(ctx->grid[x + lookx][y + looky] == ctx->grid[x][y] && |
212 | ctx->grid[x][y] && | ||
213 | !merged_grid[x + lookx][y + looky] && | ||
214 | !merged_grid[x][y]) /* merge these two tiles */ | ||
195 | { | 215 | { |
196 | /* Each merged tile cannot be merged again */ | 216 | /* Each merged tile cannot be merged again */ |
197 | merged_grid[x+lookx][y+looky]=true; | 217 | merged_grid[x + lookx][y + looky] = true; |
198 | ctx->grid[x+lookx][y+looky]=2*ctx->grid[x][y]; | 218 | ctx->grid[x + lookx][y + looky] = 2 * ctx->grid[x][y]; |
199 | ctx->score+=ctx->grid[x+lookx][y+looky]; | 219 | ctx->score += ctx->grid[x + lookx][y + looky]; |
200 | ctx->grid[x][y]=0; | 220 | ctx->grid[x][y] = 0; |
201 | } | 221 | } |
202 | else if(ctx->grid[x+lookx][y+looky]==0) /* Empty! */ | 222 | else if(ctx->grid[x + lookx][y + looky] == 0) /* Empty! */ |
203 | { | 223 | { |
204 | ctx->grid[x+lookx][y+looky]=ctx->grid[x][y]; | 224 | ctx->grid[x + lookx][y + looky] = ctx->grid[x][y]; |
205 | ctx->grid[x][y]=0; | 225 | ctx->grid[x][y] = 0; |
206 | } | 226 | } |
207 | } | 227 | } |
208 | } | 228 | } |
209 | if(ctx->score>best_score_before && update_best) | 229 | if(ctx->score > best_score_old && update_best) |
210 | best_score=ctx->score; | 230 | best_score = ctx->score; |
211 | } | 231 | } |
212 | 232 | ||
213 | /* these functions move each tile 1 space in the direction specified via calls to slide_internal */ | 233 | /* these functions move each tile 1 space in the direction specified via calls to slide_internal */ |
@@ -227,6 +247,7 @@ static void up(bool update_best) | |||
227 | 0, -1, /* lookahead values */ | 247 | 0, -1, /* lookahead values */ |
228 | update_best); | 248 | update_best); |
229 | } | 249 | } |
250 | |||
230 | /* Down | 251 | /* Down |
231 | 0 v v v v | 252 | 0 v v v v |
232 | 1 v v v v | 253 | 1 v v v v |
@@ -242,6 +263,7 @@ static void down(bool update_best) | |||
242 | 0, 1, | 263 | 0, 1, |
243 | update_best); | 264 | update_best); |
244 | } | 265 | } |
266 | |||
245 | /* Left | 267 | /* Left |
246 | 0 < < < | 268 | 0 < < < |
247 | 1 < < < | 269 | 1 < < < |
@@ -257,6 +279,7 @@ static void left(bool update_best) | |||
257 | -1, 0, | 279 | -1, 0, |
258 | update_best); | 280 | update_best); |
259 | } | 281 | } |
282 | |||
260 | /* Right | 283 | /* Right |
261 | 0 > > > | 284 | 0 > > > |
262 | 1 > > > | 285 | 1 > > > |
@@ -273,31 +296,44 @@ static void right(bool update_best) | |||
273 | update_best); | 296 | update_best); |
274 | } | 297 | } |
275 | 298 | ||
276 | /* slightly modified version of base 2 log, returns 1 when given zero, and log2(n)+1 for anything else */ | 299 | /* copies old_grid to ctx->grid */ |
300 | static inline void RESTORE_GRID(void) | ||
301 | { | ||
302 | memcpy(&ctx->grid, &old_grid, sizeof(ctx->grid)); | ||
303 | } | ||
277 | 304 | ||
305 | /* slightly modified base 2 logarithm, returns 1 when given zero, and log2(n) + 1 for anything else */ | ||
278 | static inline int ilog2(int n) | 306 | static inline int ilog2(int n) |
279 | { | 307 | { |
280 | if(n==0) | 308 | if(n == 0) |
281 | return 1; | 309 | return 1; |
282 | int log=0; | 310 | int log = 0; |
283 | while(n>1) | 311 | while(n > 1) |
284 | { | 312 | { |
285 | n>>=1; | 313 | n >>= 1; |
286 | ++log; | 314 | ++log; |
287 | } | 315 | } |
288 | return log+1; | 316 | return log + 1; |
289 | } | 317 | } |
318 | |||
319 | /* low-depth displays resort to text drawing, see the #else case below */ | ||
320 | |||
290 | #if LCD_DEPTH > 1 | 321 | #if LCD_DEPTH > 1 |
322 | |||
323 | /* draws game screen + updates LCD */ | ||
291 | static void draw(void) | 324 | static void draw(void) |
292 | { | 325 | { |
293 | #ifdef HAVE_LCD_COLOR | 326 | #ifdef HAVE_LCD_COLOR |
294 | rb->lcd_set_background(BACKGROUND); | 327 | rb->lcd_set_background(BACKGROUND); |
295 | #endif | 328 | #endif |
329 | |||
296 | rb->lcd_clear_display(); | 330 | rb->lcd_clear_display(); |
297 | 331 | ||
298 | /* draw the background */ | 332 | /* draw the background */ |
299 | 333 | ||
300 | rb->lcd_bitmap(_2048_background, BACKGROUND_X, BACKGROUND_Y, BMPWIDTH__2048_background, BMPWIDTH__2048_background); | 334 | rb->lcd_bitmap(_2048_background, |
335 | BACKGROUND_X, BACKGROUND_Y, | ||
336 | BMPWIDTH__2048_background, BMPWIDTH__2048_background); | ||
301 | 337 | ||
302 | /* | 338 | /* |
303 | grey_gray_bitmap(_2048_background, BACKGROUND_X, BACKGROUND_Y, BMPWIDTH__2048_background, BMPHEIGHT__2048_background); | 339 | grey_gray_bitmap(_2048_background, BACKGROUND_X, BACKGROUND_Y, BMPWIDTH__2048_background, BMPHEIGHT__2048_background); |
@@ -305,290 +341,316 @@ static void draw(void) | |||
305 | 341 | ||
306 | /* draw the grid */ | 342 | /* draw the grid */ |
307 | 343 | ||
308 | for(int y=0;y<GRID_SIZE;++y) | 344 | for(int y = 0; y < GRID_SIZE; ++y) |
309 | { | 345 | { |
310 | for(int x=0;x<GRID_SIZE;++x) | 346 | for(int x = 0; x < GRID_SIZE; ++x) |
311 | { | 347 | { |
312 | rb->lcd_bitmap_part(_2048_tiles, /* source */ | 348 | rb->lcd_bitmap_part(_2048_tiles, /* source */ |
313 | BMPWIDTH__2048_tiles-BMPHEIGHT__2048_tiles*ilog2(ctx->grid[x][y]), 0, /* source upper left corner */ | 349 | BMPWIDTH__2048_tiles - BMPHEIGHT__2048_tiles * ilog2(ctx->grid[x][y]), 0, /* source upper left corner */ |
314 | STRIDE(SCREEN_MAIN, BMPWIDTH__2048_tiles, BMPHEIGHT__2048_tiles), /* stride */ | 350 | STRIDE(SCREEN_MAIN, BMPWIDTH__2048_tiles, BMPHEIGHT__2048_tiles), /* stride */ |
315 | (BMPHEIGHT__2048_tiles+MIN_SPACE)*x+BASE_X, (BMPHEIGHT__2048_tiles+MIN_SPACE)*y+BASE_Y, /* dest upper-left corner */ | 351 | (BMPHEIGHT__2048_tiles + MIN_SPACE) * x + BASE_X, (BMPHEIGHT__2048_tiles + MIN_SPACE) * y + BASE_Y, /* dest upper-left corner */ |
316 | BMPHEIGHT__2048_tiles, BMPHEIGHT__2048_tiles); /* size of the cut section */ | 352 | BMPHEIGHT__2048_tiles, BMPHEIGHT__2048_tiles); /* size of the cut section */ |
317 | } | 353 | } |
318 | } | 354 | } |
355 | |||
319 | /* draw the title */ | 356 | /* draw the title */ |
320 | char buf[32]; | 357 | char buf[32]; |
358 | |||
321 | #ifdef HAVE_LCD_COLOR | 359 | #ifdef HAVE_LCD_COLOR |
322 | rb->lcd_set_foreground(TEXT_COLOR); | 360 | rb->lcd_set_foreground(TEXT_COLOR); |
323 | #endif | 361 | #endif |
324 | rb->snprintf(buf, 31, "%d", WINNING_TILE); | ||
325 | 362 | ||
326 | /* check if the title will go into the grid */ | 363 | rb->snprintf(buf, sizeof(buf), "%d", WINNING_TILE); |
364 | |||
365 | /* check if the title will overlap the grid */ | ||
327 | int w, h; | 366 | int w, h; |
328 | rb->lcd_setfont(FONT_UI); | 367 | rb->lcd_setfont(FONT_UI); |
329 | rb->font_getstringsize(buf, &w, &h, FONT_UI); | 368 | rb->font_getstringsize(buf, &w, &h, FONT_UI); |
330 | bool draw_title=true; | 369 | bool draw_title = true; |
331 | if(w+TITLE_X>=BACKGROUND_X && h+TITLE_Y>=BACKGROUND_Y) | 370 | if(w + TITLE_X >= BACKGROUND_X && h + TITLE_Y >= BACKGROUND_Y) |
332 | { | 371 | { |
333 | /* if it goes into the grid, use the system font, which should be smaller */ | 372 | /* if it goes into the grid, use the system font, which should be smaller */ |
334 | rb->lcd_setfont(FONT_SYSFIXED); | 373 | rb->lcd_setfont(FONT_SYSFIXED); |
335 | rb->font_getstringsize(buf, &w, &h, FONT_SYSFIXED); | 374 | rb->font_getstringsize(buf, &w, &h, FONT_SYSFIXED); |
336 | if(w+TITLE_X>=BACKGROUND_X && h+TITLE_Y>=BACKGROUND_Y) | 375 | if(w + TITLE_X >= BACKGROUND_X && h + TITLE_Y >= BACKGROUND_Y) |
337 | { | 376 | { |
338 | /* title can't fit, don't draw it */ | 377 | /* title can't fit, don't draw it */ |
339 | draw_title=false; | 378 | draw_title = false; |
340 | h=0; | 379 | h = 0; |
341 | } | 380 | } |
342 | } | 381 | } |
382 | |||
343 | if(draw_title) | 383 | if(draw_title) |
344 | rb->lcd_putsxy(TITLE_X, TITLE_Y, buf); | 384 | rb->lcd_putsxy(TITLE_X, TITLE_Y, buf); |
345 | int score_y=TITLE_Y+h+VERT_SPACING; | 385 | |
386 | int score_y = TITLE_Y + h + VERT_SPACING; | ||
387 | |||
346 | /* draw the score */ | 388 | /* draw the score */ |
347 | rb->snprintf(buf, 31, "Score: %d", ctx->score); | 389 | rb->snprintf(buf, sizeof(buf), "Score: %d", ctx->score); |
390 | |||
348 | #ifdef HAVE_LCD_COLOR | 391 | #ifdef HAVE_LCD_COLOR |
349 | rb->lcd_set_foreground(LCD_WHITE); | 392 | rb->lcd_set_foreground(LCD_WHITE); |
350 | rb->lcd_set_background(BOARD_BACKGROUND); | 393 | rb->lcd_set_background(BOARD_BACKGROUND); |
351 | #endif | 394 | #endif |
395 | |||
352 | rb->lcd_setfont(FONT_UI); | 396 | rb->lcd_setfont(FONT_UI); |
353 | rb->font_getstringsize(buf, &w, &h, FONT_UI); | 397 | rb->font_getstringsize(buf, &w, &h, FONT_UI); |
354 | if(w+SCORE_X>=BACKGROUND_X && h+SCORE_Y>=BACKGROUND_Y) | 398 | |
399 | /* try making the score fit */ | ||
400 | if(w + SCORE_X >= BACKGROUND_X && h + SCORE_Y >= BACKGROUND_Y) | ||
355 | { | 401 | { |
356 | /* score overflows */ | 402 | /* score overflows */ |
357 | /* first see if it fits with Score: and FONT_SYSFIXED */ | 403 | /* first see if it fits with Score: and FONT_SYSFIXED */ |
358 | rb->lcd_setfont(FONT_SYSFIXED); | 404 | rb->lcd_setfont(FONT_SYSFIXED); |
359 | rb->font_getstringsize(buf, &w, &h, FONT_SYSFIXED); | 405 | rb->font_getstringsize(buf, &w, &h, FONT_SYSFIXED); |
360 | if(w+SCORE_X < BACKGROUND_X) | 406 | if(w + SCORE_X < BACKGROUND_X) |
361 | /* it fits, go and draw it */ | 407 | /* it fits, go and draw it */ |
362 | goto draw_lbl; | 408 | goto draw_lbl; |
363 | 409 | ||
364 | /* now try with S: and FONT_UI */ | 410 | /* now try with S: and FONT_UI */ |
365 | rb->snprintf(buf, 31, "S: %d", ctx->score); | 411 | rb->snprintf(buf, sizeof(buf), "S: %d", ctx->score); |
366 | rb->font_getstringsize(buf, &w, &h, FONT_UI); | 412 | rb->font_getstringsize(buf, &w, &h, FONT_UI); |
367 | rb->lcd_setfont(FONT_UI); | 413 | rb->lcd_setfont(FONT_UI); |
368 | if(w+SCORE_X<BACKGROUND_X) | 414 | if(w + SCORE_X < BACKGROUND_X) |
369 | goto draw_lbl; | 415 | goto draw_lbl; |
370 | 416 | ||
371 | /* now try with S: and FONT_SYSFIXED */ | 417 | /* now try with S: and FONT_SYSFIXED */ |
372 | rb->snprintf(buf, 31, "S: %d", ctx->score); | 418 | rb->snprintf(buf, sizeof(buf), "S: %d", ctx->score); |
373 | rb->font_getstringsize(buf, &w, &h, FONT_SYSFIXED); | 419 | rb->font_getstringsize(buf, &w, &h, FONT_SYSFIXED); |
374 | rb->lcd_setfont(FONT_SYSFIXED); | 420 | rb->lcd_setfont(FONT_SYSFIXED); |
375 | if(w+SCORE_X<BACKGROUND_X) | 421 | if(w + SCORE_X < BACKGROUND_X) |
376 | goto draw_lbl; | 422 | goto draw_lbl; |
377 | 423 | ||
378 | /* then try without Score: and FONT_UI */ | 424 | /* then try without Score: and FONT_UI */ |
379 | rb->snprintf(buf, 31, "%d", ctx->score); | 425 | rb->snprintf(buf, sizeof(buf), "%d", ctx->score); |
380 | rb->font_getstringsize(buf, &w, &h, FONT_UI); | 426 | rb->font_getstringsize(buf, &w, &h, FONT_UI); |
381 | rb->lcd_setfont(FONT_UI); | 427 | rb->lcd_setfont(FONT_UI); |
382 | if(w+SCORE_X<BACKGROUND_X) | 428 | if(w + SCORE_X < BACKGROUND_X) |
383 | goto draw_lbl; | 429 | goto draw_lbl; |
384 | 430 | ||
385 | /* as a last resort, don't use Score: and use the system font */ | 431 | /* as a last resort, don't use Score: and use the system font */ |
386 | rb->snprintf(buf, 31, "%d", ctx->score); | 432 | rb->snprintf(buf, sizeof(buf), "%d", ctx->score); |
387 | rb->font_getstringsize(buf, &w, &h, FONT_SYSFIXED); | 433 | rb->font_getstringsize(buf, &w, &h, FONT_SYSFIXED); |
388 | rb->lcd_setfont(FONT_SYSFIXED); | 434 | rb->lcd_setfont(FONT_SYSFIXED); |
389 | if(w+SCORE_X<BACKGROUND_X) | 435 | if(w + SCORE_X < BACKGROUND_X) |
390 | goto draw_lbl; | 436 | goto draw_lbl; |
391 | else | 437 | else |
392 | goto skip_draw_score; | 438 | goto skip_draw_score; |
393 | } | 439 | } |
440 | |||
394 | draw_lbl: | 441 | draw_lbl: |
395 | rb->lcd_putsxy(SCORE_X, score_y, buf); | 442 | rb->lcd_putsxy(SCORE_X, score_y, buf); |
396 | score_y+=h+VERT_SPACING; | 443 | score_y += h + VERT_SPACING; |
444 | |||
397 | /* draw the best score */ | 445 | /* draw the best score */ |
398 | skip_draw_score: | 446 | skip_draw_score: |
399 | rb->snprintf(buf, 31, "Best: %d", best_score); | 447 | rb->snprintf(buf, sizeof(buf), "Best: %d", best_score); |
448 | |||
400 | #ifdef HAVE_LCD_COLOR | 449 | #ifdef HAVE_LCD_COLOR |
401 | rb->lcd_set_foreground(LCD_WHITE); | 450 | rb->lcd_set_foreground(LCD_WHITE); |
402 | rb->lcd_set_background(BOARD_BACKGROUND); | 451 | rb->lcd_set_background(BOARD_BACKGROUND); |
403 | #endif | 452 | #endif |
453 | |||
404 | rb->lcd_setfont(FONT_UI); | 454 | rb->lcd_setfont(FONT_UI); |
405 | rb->font_getstringsize(buf, &w, &h, FONT_UI); | 455 | rb->font_getstringsize(buf, &w, &h, FONT_UI); |
406 | if(w+BEST_SCORE_X>=BACKGROUND_X && h+BEST_SCORE_Y>=BACKGROUND_Y) | 456 | if(w + BEST_SCORE_X >= BACKGROUND_X && h + BEST_SCORE_Y >= BACKGROUND_Y) |
407 | { | 457 | { |
408 | /* score overflows */ | 458 | /* score overflows */ |
409 | /* first see if it fits with Score: and FONT_SYSFIXED */ | 459 | /* first see if it fits with Score: and FONT_SYSFIXED */ |
410 | rb->lcd_setfont(FONT_SYSFIXED); | 460 | rb->lcd_setfont(FONT_SYSFIXED); |
411 | rb->font_getstringsize(buf, &w, &h, FONT_SYSFIXED); | 461 | rb->font_getstringsize(buf, &w, &h, FONT_SYSFIXED); |
412 | if(w+BEST_SCORE_X < BACKGROUND_X) | 462 | if(w + BEST_SCORE_X < BACKGROUND_X) |
413 | /* it fits, go and draw it */ | 463 | /* it fits, go and draw it */ |
414 | goto draw_best; | 464 | goto draw_best; |
415 | 465 | ||
416 | /* now try with S: and FONT_UI */ | 466 | /* now try with S: and FONT_UI */ |
417 | rb->snprintf(buf, 31, "B: %d", best_score); | 467 | rb->snprintf(buf, sizeof(buf), "B: %d", best_score); |
418 | rb->font_getstringsize(buf, &w, &h, FONT_UI); | 468 | rb->font_getstringsize(buf, &w, &h, FONT_UI); |
419 | rb->lcd_setfont(FONT_UI); | 469 | rb->lcd_setfont(FONT_UI); |
420 | if(w+BEST_SCORE_X<BACKGROUND_X) | 470 | if(w + BEST_SCORE_X < BACKGROUND_X) |
421 | goto draw_best; | 471 | goto draw_best; |
422 | 472 | ||
423 | /* now try with S: and FONT_SYSFIXED */ | 473 | /* now try with S: and FONT_SYSFIXED */ |
424 | rb->snprintf(buf, 31, "B: %d", best_score); | 474 | rb->snprintf(buf, sizeof(buf), "B: %d", best_score); |
425 | rb->font_getstringsize(buf, &w, &h, FONT_SYSFIXED); | 475 | rb->font_getstringsize(buf, &w, &h, FONT_SYSFIXED); |
426 | rb->lcd_setfont(FONT_SYSFIXED); | 476 | rb->lcd_setfont(FONT_SYSFIXED); |
427 | if(w+BEST_SCORE_X<BACKGROUND_X) | 477 | if(w + BEST_SCORE_X < BACKGROUND_X) |
428 | goto draw_best; | 478 | goto draw_best; |
429 | 479 | ||
430 | /* then try without Score: and FONT_UI */ | 480 | /* then try without Score: and FONT_UI */ |
431 | rb->snprintf(buf, 31, "%d", best_score); | 481 | rb->snprintf(buf, sizeof(buf), "%d", best_score); |
432 | rb->font_getstringsize(buf, &w, &h, FONT_UI); | 482 | rb->font_getstringsize(buf, &w, &h, FONT_UI); |
433 | rb->lcd_setfont(FONT_UI); | 483 | rb->lcd_setfont(FONT_UI); |
434 | if(w+BEST_SCORE_X<BACKGROUND_X) | 484 | if(w + BEST_SCORE_X < BACKGROUND_X) |
435 | goto draw_best; | 485 | goto draw_best; |
436 | 486 | ||
437 | /* as a last resort, don't use Score: and use the system font */ | 487 | /* as a last resort, don't use Score: and use the system font */ |
438 | rb->snprintf(buf, 31, "%d", best_score); | 488 | rb->snprintf(buf, sizeof(buf), "%d", best_score); |
439 | rb->font_getstringsize(buf, &w, &h, FONT_SYSFIXED); | 489 | rb->font_getstringsize(buf, &w, &h, FONT_SYSFIXED); |
440 | rb->lcd_setfont(FONT_SYSFIXED); | 490 | rb->lcd_setfont(FONT_SYSFIXED); |
441 | if(w+BEST_SCORE_X<BACKGROUND_X) | 491 | if(w + BEST_SCORE_X < BACKGROUND_X) |
442 | goto draw_best; | 492 | goto draw_best; |
443 | else | 493 | else |
444 | goto skip_draw_best; | 494 | goto skip_draw_best; |
445 | } | 495 | } |
446 | draw_best: | 496 | draw_best: |
447 | rb->lcd_putsxy(BEST_SCORE_X, score_y, buf); | 497 | rb->lcd_putsxy(BEST_SCORE_X, score_y, buf); |
498 | |||
448 | skip_draw_best: | 499 | skip_draw_best: |
449 | rb->lcd_update(); | 500 | rb->lcd_update(); |
450 | /* revert the font back */ | 501 | |
502 | /* revert the font */ | ||
451 | rb->lcd_setfont(WHAT_FONT); | 503 | rb->lcd_setfont(WHAT_FONT); |
452 | } | 504 | } |
505 | |||
453 | #else /* LCD_DEPTH > 1 */ | 506 | #else /* LCD_DEPTH > 1 */ |
507 | |||
454 | /* 1-bit display :( */ | 508 | /* 1-bit display :( */ |
455 | /* bitmaps are unreadable with these screens, so just resort to text */ | 509 | /* bitmaps are unreadable on these screens, so just resort to text-based drawing */ |
456 | static void draw(void) | 510 | static void draw(void) |
457 | { | 511 | { |
458 | rb->lcd_clear_display(); | 512 | rb->lcd_clear_display(); |
513 | |||
459 | /* Draw the grid */ | 514 | /* Draw the grid */ |
460 | /* find the biggest tile */ | 515 | /* find the biggest tile */ |
461 | int biggest_tile=-1; | 516 | unsigned int biggest_tile = 0; |
462 | for(int x=0;x<GRID_SIZE;++x) | 517 | for(int x = 0; x < GRID_SIZE; ++x) |
463 | { | 518 | { |
464 | for(int y=0;y<GRID_SIZE;++y) | 519 | for(int y = 0; y < GRID_SIZE; ++y) |
465 | if(ctx->grid[x][y]>biggest_tile) | 520 | if(ctx->grid[x][y] > biggest_tile) |
466 | biggest_tile=ctx->grid[x][y]; | 521 | biggest_tile = ctx->grid[x][y]; |
467 | } | 522 | } |
468 | char str[32]; | 523 | |
469 | rb->snprintf(str, 31,"%d", biggest_tile); | 524 | char buf[32]; |
470 | int biggest_tile_width=rb->strlen(str)*rb->font_get_width(rb->font_get(WHAT_FONT), '0')+MIN_SPACE; | 525 | |
471 | for(int y=0;y<GRID_SIZE;++y) | 526 | rb->snprintf(buf, 32, "%d", biggest_tile); |
527 | |||
528 | int biggest_tile_width = rb->strlen(buf) * rb->font_get_width(rb->font_get(WHAT_FONT), '0') + MIN_SPACE; | ||
529 | |||
530 | for(int y = 0; y < GRID_SIZE; ++y) | ||
472 | { | 531 | { |
473 | for(int x=0;x<GRID_SIZE;++x) | 532 | for(int x = 0; x < GRID_SIZE; ++x) |
474 | { | 533 | { |
475 | if(ctx->grid[x][y]) | 534 | if(ctx->grid[x][y]) |
476 | { | 535 | { |
477 | if(ctx->grid[x][y]>biggest_tile) | 536 | if(ctx->grid[x][y] > biggest_tile) |
478 | biggest_tile=ctx->grid[x][y]; | 537 | biggest_tile = ctx->grid[x][y]; |
479 | rb->snprintf(str,31,"%d", ctx->grid[x][y]); | 538 | rb->snprintf(buf, 32, "%d", ctx->grid[x][y]); |
480 | rb->lcd_putsxy(biggest_tile_width*x,y*max_numeral_height+max_numeral_height,str); | 539 | rb->lcd_putsxy(biggest_tile_width * x, y * max_numeral_height + max_numeral_height, buf); |
481 | } | 540 | } |
482 | } | 541 | } |
483 | } | 542 | } |
543 | |||
484 | /* Now draw the score, and the game title */ | 544 | /* Now draw the score, and the game title */ |
485 | rb->snprintf(str, 31, "Score: %d", ctx->score); | 545 | rb->snprintf(buf, 32, "Score: %d", ctx->score); |
486 | int str_width, str_height; | 546 | int buf_width, buf_height; |
487 | rb->font_getstringsize(str, &str_width, &str_height, WHAT_FONT); | 547 | rb->font_getstringsize(buf, &buf_width, &buf_height, WHAT_FONT); |
488 | int score_leftmost=LCD_WIDTH-str_width-1; | 548 | |
549 | int score_leftmost = LCD_WIDTH - buf_width - 1; | ||
489 | /* Check if there is enough space to display "Score: ", otherwise, only display the score */ | 550 | /* Check if there is enough space to display "Score: ", otherwise, only display the score */ |
490 | if(score_leftmost>=0) | 551 | if(score_leftmost >= 0) |
491 | rb->lcd_putsxy(score_leftmost,0,str); | 552 | rb->lcd_putsxy(score_leftmost, 0, buf); |
492 | else | 553 | else |
493 | rb->lcd_putsxy(score_leftmost,0,str+rb->strlen("Score: ")); | 554 | rb->lcd_putsxy(score_leftmost, 0, buf + rb->strlen("Score: ")); |
494 | /* Reuse the same string for the title */ | 555 | |
556 | rb->snprintf(buf, 32, "%d", WINNING_TILE); | ||
557 | rb->font_getstringsize(buf, &buf_width, &buf_height, WHAT_FONT); | ||
558 | if(buf_width < score_leftmost) | ||
559 | rb->lcd_putsxy(0, 0, buf); | ||
495 | 560 | ||
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(); | 561 | rb->lcd_update(); |
501 | } | 562 | } |
563 | |||
502 | #endif /* LCD_DEPTH > 1 */ | 564 | #endif /* LCD_DEPTH > 1 */ |
565 | |||
503 | /* place a 2 or 4 in a random empty space */ | 566 | /* place a 2 or 4 in a random empty space */ |
504 | static void place_random(void) | 567 | static void place_random(void) |
505 | { | 568 | { |
506 | int xpos[SPACES],ypos[SPACES]; | 569 | int xpos[SPACES], ypos[SPACES]; |
507 | int back=0; | 570 | int back = 0; |
508 | /* get the indexes of empty spaces */ | 571 | /* get the indexes of empty spaces */ |
509 | for(int y=0;y<GRID_SIZE;++y) | 572 | for(int y = 0; y < GRID_SIZE; ++y) |
510 | for(int x=0;x<GRID_SIZE;++x) | 573 | for(int x = 0; x < GRID_SIZE; ++x) |
511 | { | 574 | { |
512 | if(!ctx->grid[x][y]) | 575 | if(!ctx->grid[x][y]) |
513 | { | 576 | { |
514 | xpos[back]=x; | 577 | xpos[back] = x; |
515 | ypos[back]=y; | 578 | ypos[back++] = y; |
516 | ++back; | ||
517 | } | 579 | } |
518 | } | 580 | } |
581 | |||
519 | if(!back) | 582 | if(!back) |
520 | /* no empty spaces */ | 583 | /* no empty spaces */ |
521 | return; | 584 | return; |
522 | int idx=rand_range(0,back-1); | ||
523 | ctx->grid[xpos[idx]][ypos[idx]]=rand_2_or_4(); | ||
524 | } | ||
525 | 585 | ||
526 | /* copies old_grid to ctx->grid */ | 586 | int idx = rand_range(0, back - 1); |
527 | static void restore_old_grid(void) | 587 | ctx->grid[ xpos[idx] ][ ypos[idx] ] = rand_2_or_4(); |
528 | { | ||
529 | memcpy(&ctx->grid, &old_grid, sizeof(int)*SPACES); | ||
530 | } | 588 | } |
531 | 589 | ||
532 | /* checks for a win or loss */ | 590 | /* checks for a win or loss */ |
533 | static bool check_gameover(void) | 591 | static bool check_gameover(void) |
534 | { | 592 | { |
535 | /* first, check for a loss */ | 593 | /* first, check for a loss */ |
536 | int oldscore=ctx->score; | 594 | int oldscore = ctx->score; |
537 | bool have_legal_move=false; | 595 | bool have_legal_move = false; |
538 | memset(&merged_grid,0,SPACES*sizeof(bool)); | 596 | |
597 | memset(&merged_grid, 0, SPACES * sizeof(bool)); | ||
539 | up(false); | 598 | up(false); |
540 | if(memcmp(&old_grid, &ctx->grid, sizeof(int)*SPACES)) | 599 | if(memcmp(&old_grid, &ctx->grid, sizeof(ctx->grid))) |
541 | { | 600 | { |
542 | restore_old_grid(); | 601 | RESTORE_GRID(); |
543 | ctx->score=oldscore; | 602 | ctx->score = oldscore; |
544 | have_legal_move=true; | 603 | have_legal_move = true; |
545 | } | 604 | } |
546 | restore_old_grid(); | 605 | RESTORE_GRID(); |
547 | memset(&merged_grid,0,SPACES*sizeof(bool)); | 606 | |
607 | memset(&merged_grid, 0, SPACES * sizeof(bool)); | ||
548 | down(false); | 608 | down(false); |
549 | if(memcmp(&old_grid, &ctx->grid, sizeof(int)*SPACES)) | 609 | if(memcmp(&old_grid, &ctx->grid, sizeof(ctx->grid))) |
550 | { | 610 | { |
551 | restore_old_grid(); | 611 | RESTORE_GRID(); |
552 | ctx->score=oldscore; | 612 | ctx->score = oldscore; |
553 | have_legal_move=true; | 613 | have_legal_move = true; |
554 | } | 614 | } |
555 | restore_old_grid(); | 615 | RESTORE_GRID(); |
556 | memset(&merged_grid,0,SPACES*sizeof(bool)); | 616 | |
617 | memset(&merged_grid, 0, SPACES * sizeof(bool)); | ||
557 | left(false); | 618 | left(false); |
558 | if(memcmp(&old_grid, &ctx->grid, sizeof(int)*SPACES)) | 619 | if(memcmp(&old_grid, &ctx->grid, sizeof(ctx->grid))) |
559 | { | 620 | { |
560 | restore_old_grid(); | 621 | RESTORE_GRID(); |
561 | ctx->score=oldscore; | 622 | ctx->score = oldscore; |
562 | have_legal_move=true; | 623 | have_legal_move = true; |
563 | } | 624 | } |
564 | restore_old_grid(); | 625 | RESTORE_GRID(); |
565 | memset(&merged_grid,0,SPACES*sizeof(bool)); | 626 | |
627 | memset(&merged_grid, 0, SPACES * sizeof(bool)); | ||
566 | right(false); | 628 | right(false); |
567 | if(memcmp(&old_grid, &ctx->grid, sizeof(int)*SPACES)) | 629 | if(memcmp(&old_grid, &ctx->grid, sizeof(ctx->grid))) |
568 | { | 630 | { |
569 | restore_old_grid(); | 631 | RESTORE_GRID(); |
570 | ctx->score=oldscore; | 632 | ctx->score = oldscore; |
571 | have_legal_move=true; | 633 | have_legal_move = true; |
572 | } | 634 | } |
573 | ctx->score=oldscore; | 635 | ctx->score = oldscore; |
574 | if(!have_legal_move) | 636 | if(!have_legal_move) |
575 | { | 637 | { |
576 | /* no more legal moves */ | 638 | /* no more legal moves */ |
577 | draw(); /* Shame the player :) */ | 639 | draw(); /* Shame the player */ |
578 | rb->splash(HZ*2, "Game Over!"); | 640 | rb->splash(HZ*2, "Game Over!"); |
579 | return true; | 641 | return true; |
580 | } | 642 | } |
581 | for(int y=0;y<GRID_SIZE;++y) | 643 | |
644 | for(int y = 0;y < GRID_SIZE; ++y) | ||
582 | { | 645 | { |
583 | for(int x=0;x<GRID_SIZE;++x) | 646 | for(int x = 0; x < GRID_SIZE; ++x) |
584 | { | 647 | { |
585 | if(ctx->grid[x][y]==WINNING_TILE && !ctx->already_won) | 648 | if(ctx->grid[x][y] == WINNING_TILE && !ctx->already_won) |
586 | { | 649 | { |
587 | /* Let the user see the tile in its full glory... */ | 650 | /* Let the user see the tile in its full glory... */ |
588 | draw(); | 651 | draw(); |
589 | ctx->already_won=true; | 652 | ctx->already_won = true; |
590 | rb->splash(HZ*2,"You win!"); | 653 | rb->splash(HZ*2,"You win!"); |
591 | /* don't let the user quit here :) */ | ||
592 | } | 654 | } |
593 | } | 655 | } |
594 | } | 656 | } |
@@ -602,38 +664,43 @@ static void load_hs(void) | |||
602 | if(rb->file_exists(HISCORES_FILE)) | 664 | if(rb->file_exists(HISCORES_FILE)) |
603 | highscore_load(HISCORES_FILE, highscores, NUM_SCORES); | 665 | highscore_load(HISCORES_FILE, highscores, NUM_SCORES); |
604 | else | 666 | else |
605 | memset(highscores, 0, sizeof(struct highscore)*NUM_SCORES); | 667 | memset(highscores, 0, sizeof(struct highscore) * NUM_SCORES); |
606 | } | 668 | } |
607 | 669 | ||
608 | /* initialize the data structures */ | 670 | /* initialize the data structures */ |
609 | static void init_game(bool newgame) | 671 | static void init_game(bool newgame) |
610 | { | 672 | { |
611 | best_score=highscores[0].score; | 673 | best_score = highscores[0].score; |
612 | if(loaded && ctx->score > best_score) | 674 | if(loaded && ctx->score > best_score) |
613 | best_score=ctx->score; | 675 | best_score = ctx->score; |
676 | |||
614 | if(newgame) | 677 | if(newgame) |
615 | { | 678 | { |
616 | /* initialize the game context */ | 679 | /* initialize the game context */ |
617 | memset(ctx->grid, 0, sizeof(int)*SPACES); | 680 | memset(ctx->grid, 0, sizeof(ctx->grid)); |
618 | for(int i=0;i<NUM_STARTING_TILES;++i) | 681 | for(int i = 0; i < NUM_STARTING_TILES; ++i) |
619 | { | 682 | { |
620 | place_random(); | 683 | place_random(); |
621 | } | 684 | } |
622 | ctx->score=0; | 685 | ctx->score = 0; |
623 | ctx->already_won=false; | 686 | ctx->already_won = false; |
624 | } | 687 | } |
688 | |||
625 | /* using the menu resets the font */ | 689 | /* using the menu resets the font */ |
626 | /* set it again here */ | 690 | /* set it again here */ |
691 | |||
627 | rb->lcd_setfont(WHAT_FONT); | 692 | rb->lcd_setfont(WHAT_FONT); |
693 | |||
628 | /* Now calculate font sizes */ | 694 | /* Now calculate font sizes */ |
629 | /* Now get the height of the font */ | 695 | /* Now get the height of the font */ |
630 | rb->font_getstringsize("0123456789", NULL, &max_numeral_height,WHAT_FONT); | 696 | rb->font_getstringsize("0123456789", NULL, &max_numeral_height, WHAT_FONT); |
631 | max_numeral_height+=VERT_SPACING; | 697 | max_numeral_height += VERT_SPACING; |
698 | |||
632 | #if LCD_DEPTH <= 1 | 699 | #if LCD_DEPTH <= 1 |
633 | max_numeral_width=rb->font_get_width(rb->font_get(WHAT_FONT), '0'); | 700 | max_numeral_width = rb->font_get_width(rb->font_get(WHAT_FONT), '0'); |
634 | #endif | 701 | #endif |
702 | |||
635 | backlight_ignore_timeout(); | 703 | backlight_ignore_timeout(); |
636 | rb->lcd_clear_display(); | ||
637 | draw(); | 704 | draw(); |
638 | } | 705 | } |
639 | 706 | ||
@@ -641,17 +708,22 @@ static void init_game(bool newgame) | |||
641 | static void save_game(void) | 708 | static void save_game(void) |
642 | { | 709 | { |
643 | rb->splash(0, "Saving..."); | 710 | rb->splash(0, "Saving..."); |
644 | int fd=rb->open(RESUME_FILE,O_WRONLY|O_CREAT, 0666); | 711 | int fd = rb->open(RESUME_FILE, O_WRONLY|O_CREAT, 0666); |
645 | if(fd<0) | 712 | if(fd < 0) |
646 | { | 713 | { |
647 | return; | 714 | return; |
648 | } | 715 | } |
649 | ctx->cksum=0; | 716 | |
650 | for(int x=0;x<GRID_SIZE;++x) | 717 | /* calculate checksum */ |
651 | for(int y=0;y<GRID_SIZE;++y) | 718 | ctx->cksum = 0; |
652 | ctx->cksum+=ctx->grid[x][y]; | 719 | |
653 | ctx->cksum^=ctx->score; | 720 | for(int x = 0; x < GRID_SIZE; ++x) |
654 | rb->write(fd, ctx,sizeof(struct game_ctx_t)); | 721 | for(int y = 0; y < GRID_SIZE; ++y) |
722 | ctx->cksum += ctx->grid[x][y]; | ||
723 | |||
724 | ctx->cksum ^= ctx->score; | ||
725 | |||
726 | rb->write(fd, ctx, sizeof(struct game_ctx_t)); | ||
655 | rb->close(fd); | 727 | rb->close(fd); |
656 | rb->lcd_update(); | 728 | rb->lcd_update(); |
657 | } | 729 | } |
@@ -659,59 +731,67 @@ static void save_game(void) | |||
659 | /* loads a saved game, returns true on success */ | 731 | /* loads a saved game, returns true on success */ |
660 | static bool load_game(void) | 732 | static bool load_game(void) |
661 | { | 733 | { |
662 | int success=0; | 734 | int success = 0; |
663 | int fd=rb->open(RESUME_FILE, O_RDONLY); | 735 | int fd = rb->open(RESUME_FILE, O_RDONLY); |
664 | if(fd<0) | 736 | if(fd < 0) |
665 | { | 737 | { |
666 | rb->remove(RESUME_FILE); | 738 | rb->remove(RESUME_FILE); |
667 | return false; | 739 | return false; |
668 | } | 740 | } |
669 | int numread=rb->read(fd, ctx, sizeof(struct game_ctx_t)); | 741 | |
670 | int calc=0; | 742 | int numread = rb->read(fd, ctx, sizeof(struct game_ctx_t)); |
671 | for(int x=0;x<GRID_SIZE;++x) | 743 | |
672 | for(int y=0;y<GRID_SIZE;++y) | 744 | /* verify checksum */ |
673 | calc+=ctx->grid[x][y]; | 745 | unsigned int calc = 0; |
674 | calc^=ctx->score; | 746 | for(int x = 0; x < GRID_SIZE; ++x) |
675 | if(numread==sizeof(struct game_ctx_t) && calc==ctx->cksum) | 747 | for(int y = 0; y < GRID_SIZE; ++y) |
748 | calc += ctx->grid[x][y]; | ||
749 | |||
750 | calc ^= ctx->score; | ||
751 | |||
752 | if(numread == sizeof(struct game_ctx_t) && calc == ctx->cksum) | ||
676 | ++success; | 753 | ++success; |
754 | |||
677 | rb->close(fd); | 755 | rb->close(fd); |
678 | rb->remove(RESUME_FILE); | 756 | rb->remove(RESUME_FILE); |
679 | return (success==1); | 757 | |
758 | return (success > 0); | ||
680 | } | 759 | } |
681 | 760 | ||
682 | /* update the highscores with ctx->score */ | 761 | /* update the highscores with ctx->score */ |
683 | static void hs_check_update(bool noshow) | 762 | static void hs_check_update(bool noshow) |
684 | { | 763 | { |
685 | /* first, find the biggest tile to show as the level */ | 764 | /* first, find the biggest tile to show as the level */ |
686 | int biggest=0; | 765 | unsigned int biggest = 0; |
687 | for(int x=0;x<GRID_SIZE;++x) | 766 | for(int x = 0; x < GRID_SIZE; ++x) |
688 | { | 767 | { |
689 | for(int y=0;y<GRID_SIZE;++y) | 768 | for(int y = 0; y < GRID_SIZE; ++y) |
690 | { | 769 | { |
691 | if(ctx->grid[x][y]>biggest) | 770 | if(ctx->grid[x][y] > biggest) |
692 | biggest=ctx->grid[x][y]; | 771 | biggest = ctx->grid[x][y]; |
693 | } | 772 | } |
694 | } | 773 | } |
695 | int hs_idx=highscore_update(ctx->score,biggest, "", highscores,NUM_SCORES); | 774 | |
775 | int hs_idx = highscore_update(ctx->score,biggest, "", highscores,NUM_SCORES); | ||
696 | if(!noshow) | 776 | if(!noshow) |
697 | { | 777 | { |
698 | /* show the scores if there is a new high score */ | 778 | /* show the scores if there is a new high score */ |
699 | if(hs_idx>=0) | 779 | if(hs_idx >= 0) |
700 | { | 780 | { |
701 | rb->splashf(HZ*2,"New High Score: %d", ctx->score); | 781 | rb->splashf(HZ*2, "New High Score: %d", ctx->score); |
702 | rb->lcd_clear_display(); | 782 | rb->lcd_clear_display(); |
703 | highscore_show(hs_idx,highscores,NUM_SCORES,true); | 783 | highscore_show(hs_idx, highscores, NUM_SCORES, true); |
704 | } | 784 | } |
705 | } | 785 | } |
706 | highscore_save(HISCORES_FILE,highscores,NUM_SCORES); | 786 | highscore_save(HISCORES_FILE, highscores, NUM_SCORES); |
707 | } | 787 | } |
708 | 788 | ||
709 | /* asks the user if they wish to quit */ | 789 | /* asks the user if they wish to quit */ |
710 | static bool confirm_quit(void) | 790 | static bool confirm_quit(void) |
711 | { | 791 | { |
712 | const struct text_message prompt={(const char*[]){"Are you sure?", "This will clear your current game."}, 2}; | 792 | const struct text_message prompt = { (const char*[]) {"Are you sure?", "This will clear your current game."}, 2}; |
713 | enum yesno_res response=rb->gui_syncyesno_run(&prompt, NULL, NULL); | 793 | enum yesno_res response = rb->gui_syncyesno_run(&prompt, NULL, NULL); |
714 | if(response==YESNO_NO) | 794 | if(response == YESNO_NO) |
715 | return false; | 795 | return false; |
716 | else | 796 | else |
717 | return true; | 797 | return true; |
@@ -720,7 +800,7 @@ static bool confirm_quit(void) | |||
720 | /* show the pause menu */ | 800 | /* show the pause menu */ |
721 | static int do_2048_pause_menu(void) | 801 | static int do_2048_pause_menu(void) |
722 | { | 802 | { |
723 | int sel=0; | 803 | int sel = 0; |
724 | MENUITEM_STRINGLIST(menu,"2048 Menu", NULL, | 804 | MENUITEM_STRINGLIST(menu,"2048 Menu", NULL, |
725 | "Resume Game", | 805 | "Resume Game", |
726 | "Start New Game", | 806 | "Start New Game", |
@@ -729,7 +809,7 @@ static int do_2048_pause_menu(void) | |||
729 | "Help", | 809 | "Help", |
730 | "Quit without Saving", | 810 | "Quit without Saving", |
731 | "Quit"); | 811 | "Quit"); |
732 | bool quit=false; | 812 | bool quit = false; |
733 | while(!quit) | 813 | while(!quit) |
734 | { | 814 | { |
735 | switch(rb->do_menu(&menu, &sel, NULL, false)) | 815 | switch(rb->do_menu(&menu, &sel, NULL, false)) |
@@ -748,7 +828,7 @@ static int do_2048_pause_menu(void) | |||
748 | } | 828 | } |
749 | } | 829 | } |
750 | case 2: | 830 | case 2: |
751 | highscore_show(-1,highscores, NUM_SCORES, true); | 831 | highscore_show(-1, highscores, NUM_SCORES, true); |
752 | break; | 832 | break; |
753 | case 3: | 833 | case 3: |
754 | playback_control(NULL); | 834 | playback_control(NULL); |
@@ -782,80 +862,85 @@ static void exit_handler(void) | |||
782 | #endif | 862 | #endif |
783 | return; | 863 | return; |
784 | } | 864 | } |
865 | |||
785 | static bool check_hs; | 866 | static bool check_hs; |
867 | |||
786 | /* main game loop */ | 868 | /* main game loop */ |
787 | static enum plugin_status do_game(bool newgame) | 869 | static enum plugin_status do_game(bool newgame) |
788 | { | 870 | { |
789 | init_game(newgame); | 871 | init_game(newgame); |
790 | rb_atexit(&exit_handler); | 872 | rb_atexit(exit_handler); |
791 | int made_move=0; | 873 | int made_move = 0; |
792 | while(1) | 874 | while(1) |
793 | { | 875 | { |
794 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | 876 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
795 | rb->cpu_boost(false); /* Save battery when idling */ | 877 | rb->cpu_boost(false); /* Save battery when idling */ |
796 | #endif | 878 | #endif |
797 | /* Wait for a button press */ | 879 | /* Wait for a button press */ |
798 | int button=pluginlib_getaction(-1, plugin_contexts, ARRAYLEN(plugin_contexts)); | 880 | int button = pluginlib_getaction(-1, plugin_contexts, ARRAYLEN(plugin_contexts)); |
799 | made_move=0; | 881 | made_move = 0; |
800 | memset(&merged_grid,0,SPACES*sizeof(bool)); | 882 | |
883 | memset(&merged_grid, 0, SPACES*sizeof(bool)); | ||
801 | memcpy(&old_grid, &ctx->grid, sizeof(int)*SPACES); | 884 | memcpy(&old_grid, &ctx->grid, sizeof(int)*SPACES); |
802 | int grid_before_anim_step[GRID_SIZE][GRID_SIZE]; | 885 | |
886 | unsigned int grid_before_anim_step[GRID_SIZE][GRID_SIZE]; | ||
887 | |||
803 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | 888 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
804 | rb->cpu_boost(true); /* doing work now... */ | 889 | rb->cpu_boost(true); /* doing work now... */ |
805 | #endif | 890 | #endif |
806 | switch(button) | 891 | switch(button) |
807 | { | 892 | { |
808 | case KEY_UP: | 893 | case KEY_UP: |
809 | for(int i=0;i<GRID_SIZE-1;++i) | 894 | for(int i = 0; i < GRID_SIZE - 1; ++i) |
810 | { | 895 | { |
811 | memcpy(grid_before_anim_step, ctx->grid, sizeof(int)*SPACES); | 896 | memcpy(grid_before_anim_step, ctx->grid, sizeof(ctx->grid)); |
812 | up(true); | 897 | up(true); |
813 | if(memcmp(grid_before_anim_step, ctx->grid, sizeof(int)*SPACES)) | 898 | if(memcmp(grid_before_anim_step, ctx->grid, sizeof(ctx->grid))) |
814 | { | 899 | { |
815 | rb->sleep(ANIM_SLEEPTIME); | 900 | rb->sleep(ANIM_SLEEPTIME); |
816 | draw(); | 901 | draw(); |
817 | } | 902 | } |
818 | } | 903 | } |
819 | made_move=1; | 904 | made_move = 1; |
820 | break; | 905 | break; |
821 | case KEY_DOWN: | 906 | case KEY_DOWN: |
822 | for(int i=0;i<GRID_SIZE-1;++i) | 907 | for(int i = 0; i < GRID_SIZE - 1; ++i) |
823 | { | 908 | { |
824 | memcpy(grid_before_anim_step, ctx->grid, sizeof(int)*SPACES); | 909 | memcpy(grid_before_anim_step, ctx->grid, sizeof(ctx->grid)); |
825 | down(true); | 910 | down(true); |
826 | if(memcmp(grid_before_anim_step, ctx->grid, sizeof(int)*SPACES)) | 911 | if(memcmp(grid_before_anim_step, ctx->grid, sizeof(ctx->grid))) |
827 | { | 912 | { |
828 | rb->sleep(ANIM_SLEEPTIME); | 913 | rb->sleep(ANIM_SLEEPTIME); |
829 | draw(); | 914 | draw(); |
830 | } | 915 | } |
831 | } | 916 | } |
832 | made_move=1; | 917 | made_move = 1; |
833 | break; | 918 | break; |
834 | case KEY_LEFT: | 919 | case KEY_LEFT: |
835 | for(int i=0;i<GRID_SIZE-1;++i) | 920 | for(int i = 0; i < GRID_SIZE - 1; ++i) |
836 | { | 921 | { |
837 | memcpy(grid_before_anim_step, ctx->grid, sizeof(int)*SPACES); | 922 | memcpy(grid_before_anim_step, ctx->grid, sizeof(ctx->grid)); |
838 | left(true); | 923 | left(true); |
839 | if(memcmp(grid_before_anim_step, ctx->grid, sizeof(int)*SPACES)) | 924 | if(memcmp(grid_before_anim_step, ctx->grid, sizeof(ctx->grid))) |
840 | { | 925 | { |
841 | rb->sleep(ANIM_SLEEPTIME); | 926 | rb->sleep(ANIM_SLEEPTIME); |
842 | draw(); | 927 | draw(); |
843 | } | 928 | } |
844 | } | 929 | } |
845 | made_move=1; | 930 | made_move = 1; |
846 | break; | 931 | break; |
847 | case KEY_RIGHT: | 932 | case KEY_RIGHT: |
848 | for(int i=0;i<GRID_SIZE-1;++i) | 933 | for(int i = 0; i < GRID_SIZE - 1; ++i) |
849 | { | 934 | { |
850 | memcpy(grid_before_anim_step, ctx->grid, sizeof(int)*SPACES); | 935 | memcpy(grid_before_anim_step, ctx->grid, sizeof(ctx->grid)); |
851 | right(true); | 936 | right(true); |
852 | if(memcmp(grid_before_anim_step, ctx->grid, sizeof(int)*SPACES)) | 937 | if(memcmp(grid_before_anim_step, ctx->grid, sizeof(ctx->grid))) |
853 | { | 938 | { |
854 | rb->sleep(ANIM_SLEEPTIME); | 939 | rb->sleep(ANIM_SLEEPTIME); |
855 | draw(); | 940 | draw(); |
856 | } | 941 | } |
857 | } | 942 | } |
858 | made_move=1; | 943 | made_move = 1; |
859 | break; | 944 | break; |
860 | case KEY_EXIT: | 945 | case KEY_EXIT: |
861 | switch(do_2048_pause_menu()) | 946 | switch(do_2048_pause_menu()) |
@@ -864,33 +949,33 @@ static enum plugin_status do_game(bool newgame) | |||
864 | break; | 949 | break; |
865 | case 1: /* new game */ | 950 | case 1: /* new game */ |
866 | init_game(true); | 951 | init_game(true); |
867 | made_move=1; | 952 | made_move = 1; |
868 | continue; | 953 | continue; |
869 | break; | ||
870 | case 2: /* quit without saving */ | 954 | case 2: /* quit without saving */ |
871 | check_hs=true; | 955 | check_hs = true; |
872 | rb->remove(RESUME_FILE); | 956 | rb->remove(RESUME_FILE); |
873 | return PLUGIN_ERROR; | 957 | return PLUGIN_ERROR; |
874 | case 3: /* save and quit */ | 958 | case 3: /* save and quit */ |
875 | check_hs=false; | 959 | check_hs = false; |
876 | save_game(); | 960 | save_game(); |
877 | return PLUGIN_ERROR; | 961 | return PLUGIN_ERROR; |
878 | } | 962 | } |
879 | break; | 963 | break; |
880 | default: | 964 | default: |
881 | { | 965 | { |
882 | exit_on_usb(button); /* handles poweroff and USB events */ | 966 | exit_on_usb(button); /* handle poweroff and USB events */ |
883 | break; | 967 | break; |
884 | } | 968 | } |
885 | } | 969 | } |
970 | |||
886 | if(made_move) | 971 | if(made_move) |
887 | { | 972 | { |
888 | /* Check if we actually moved, then add random */ | 973 | /* Check if any tiles moved, then add random */ |
889 | if(memcmp(&old_grid, ctx->grid, sizeof(int)*SPACES)) | 974 | if(memcmp(&old_grid, ctx->grid, sizeof(ctx->grid))) |
890 | { | 975 | { |
891 | place_random(); | 976 | place_random(); |
892 | } | 977 | } |
893 | memcpy(&old_grid, ctx->grid, sizeof(int)*SPACES); | 978 | memcpy(&old_grid, ctx->grid, sizeof(ctx->grid)); |
894 | if(check_gameover()) | 979 | if(check_gameover()) |
895 | return PLUGIN_OK; | 980 | return PLUGIN_OK; |
896 | draw(); | 981 | draw(); |
@@ -906,8 +991,8 @@ static enum plugin_status do_game(bool newgame) | |||
906 | /* used to hide resume option when there is no save */ | 991 | /* used to hide resume option when there is no save */ |
907 | static int mainmenu_cb(int action, const struct menu_item_ex *this_item) | 992 | static int mainmenu_cb(int action, const struct menu_item_ex *this_item) |
908 | { | 993 | { |
909 | int idx=((intptr_t)this_item); | 994 | int idx = ((intptr_t)this_item); |
910 | if(action==ACTION_REQUEST_MENUITEM && !loaded && (idx==0 || idx==5)) | 995 | if(action == ACTION_REQUEST_MENUITEM && !loaded && (idx == 0 || idx == 5)) |
911 | return ACTION_EXIT_MENUITEM; | 996 | return ACTION_EXIT_MENUITEM; |
912 | return action; | 997 | return action; |
913 | } | 998 | } |
@@ -915,29 +1000,37 @@ static int mainmenu_cb(int action, const struct menu_item_ex *this_item) | |||
915 | /* show the main menu */ | 1000 | /* show the main menu */ |
916 | static enum plugin_status do_2048_menu(void) | 1001 | static enum plugin_status do_2048_menu(void) |
917 | { | 1002 | { |
918 | int sel=0; | 1003 | int sel = 0; |
919 | loaded=load_game(); | 1004 | loaded = load_game(); |
920 | MENUITEM_STRINGLIST(menu,"2048 Menu", mainmenu_cb, "Resume Game", "Start New Game","High Scores","Playback Control", "Help", "Quit without Saving", "Quit"); | 1005 | MENUITEM_STRINGLIST(menu, |
921 | bool quit=false; | 1006 | "2048 Menu", |
1007 | mainmenu_cb, | ||
1008 | "Resume Game", | ||
1009 | "Start New Game", | ||
1010 | "High Scores", | ||
1011 | "Playback Control", | ||
1012 | "Help", | ||
1013 | "Quit without Saving", | ||
1014 | "Quit"); | ||
1015 | bool quit = false; | ||
922 | while(!quit) | 1016 | while(!quit) |
923 | { | 1017 | { |
924 | int item; | 1018 | switch(rb->do_menu(&menu, &sel, NULL, false)) |
925 | switch(item=rb->do_menu(&menu,&sel,NULL,false)) | ||
926 | { | 1019 | { |
927 | case 0: /* Start new game or resume a game */ | 1020 | case 0: /* Start new game or resume a game */ |
928 | case 1: | 1021 | case 1: |
929 | { | 1022 | { |
930 | if(item==1 && loaded) | 1023 | if(sel == 1 && loaded) |
931 | { | 1024 | { |
932 | if(!confirm_quit()) | 1025 | if(!confirm_quit()) |
933 | break; | 1026 | break; |
934 | } | 1027 | } |
935 | enum plugin_status ret=do_game(item==1); | 1028 | enum plugin_status ret = do_game(sel == 1); |
936 | switch(ret) | 1029 | switch(ret) |
937 | { | 1030 | { |
938 | case PLUGIN_OK: | 1031 | case PLUGIN_OK: |
939 | { | 1032 | { |
940 | loaded=false; | 1033 | loaded = false; |
941 | rb->remove(RESUME_FILE); | 1034 | rb->remove(RESUME_FILE); |
942 | hs_check_update(false); | 1035 | hs_check_update(false); |
943 | break; | 1036 | break; |
@@ -956,7 +1049,7 @@ static enum plugin_status do_2048_menu(void) | |||
956 | break; | 1049 | break; |
957 | } | 1050 | } |
958 | case 2: | 1051 | case 2: |
959 | highscore_show(-1,highscores, NUM_SCORES, true); | 1052 | highscore_show(-1, highscores, NUM_SCORES, true); |
960 | break; | 1053 | break; |
961 | case 3: | 1054 | case 3: |
962 | playback_control(NULL); | 1055 | playback_control(NULL); |
@@ -977,6 +1070,8 @@ static enum plugin_status do_2048_menu(void) | |||
977 | } | 1070 | } |
978 | return PLUGIN_OK; | 1071 | return PLUGIN_OK; |
979 | } | 1072 | } |
1073 | |||
1074 | /* plugin entry point */ | ||
980 | enum plugin_status plugin_start(const void* param) | 1075 | enum plugin_status plugin_start(const void* param) |
981 | { | 1076 | { |
982 | (void)param; | 1077 | (void)param; |
@@ -985,9 +1080,12 @@ enum plugin_status plugin_start(const void* param) | |||
985 | rb->lcd_setfont(WHAT_FONT); | 1080 | rb->lcd_setfont(WHAT_FONT); |
986 | 1081 | ||
987 | /* now start the game menu */ | 1082 | /* now start the game menu */ |
988 | enum plugin_status ret=do_2048_menu(); | 1083 | enum plugin_status ret = do_2048_menu(); |
989 | highscore_save(HISCORES_FILE,highscores,NUM_SCORES); | 1084 | |
1085 | highscore_save(HISCORES_FILE, highscores, NUM_SCORES); | ||
990 | cleanup(); | 1086 | cleanup(); |
991 | abnormal_exit=false; | 1087 | |
1088 | abnormal_exit = false; | ||
1089 | |||
992 | return ret; | 1090 | return ret; |
993 | } | 1091 | } |