diff options
Diffstat (limited to 'apps/plugins/puzzles/src/rect.c')
-rw-r--r-- | apps/plugins/puzzles/src/rect.c | 82 |
1 files changed, 44 insertions, 38 deletions
diff --git a/apps/plugins/puzzles/src/rect.c b/apps/plugins/puzzles/src/rect.c index b13de75fd4..c3ee1ab478 100644 --- a/apps/plugins/puzzles/src/rect.c +++ b/apps/plugins/puzzles/src/rect.c | |||
@@ -26,7 +26,11 @@ | |||
26 | #include <string.h> | 26 | #include <string.h> |
27 | #include <assert.h> | 27 | #include <assert.h> |
28 | #include <ctype.h> | 28 | #include <ctype.h> |
29 | #include <math.h> | 29 | #ifdef NO_TGMATH_H |
30 | # include <math.h> | ||
31 | #else | ||
32 | # include <tgmath.h> | ||
33 | #endif | ||
30 | 34 | ||
31 | #include "puzzles.h" | 35 | #include "puzzles.h" |
32 | 36 | ||
@@ -163,10 +167,7 @@ static char *encode_params(const game_params *params, bool full) | |||
163 | 167 | ||
164 | sprintf(data, "%dx%d", params->w, params->h); | 168 | sprintf(data, "%dx%d", params->w, params->h); |
165 | if (full && params->expandfactor) | 169 | if (full && params->expandfactor) |
166 | { | 170 | sprintf(data + strlen(data), "e%g", params->expandfactor); |
167 | sprintf(data + strlen(data), "e"); | ||
168 | ftoa(data + strlen(data), params->expandfactor); | ||
169 | } | ||
170 | if (full && !params->unique) | 171 | if (full && !params->unique) |
171 | strcat(data, "a"); | 172 | strcat(data, "a"); |
172 | 173 | ||
@@ -192,7 +193,7 @@ static config_item *game_configure(const game_params *params) | |||
192 | 193 | ||
193 | ret[2].name = "Expansion factor"; | 194 | ret[2].name = "Expansion factor"; |
194 | ret[2].type = C_STRING; | 195 | ret[2].type = C_STRING; |
195 | ftoa(buf, params->expandfactor); | 196 | sprintf(buf, "%g", params->expandfactor); |
196 | ret[2].u.string.sval = dupstr(buf); | 197 | ret[2].u.string.sval = dupstr(buf); |
197 | 198 | ||
198 | ret[3].name = "Ensure unique solution"; | 199 | ret[3].name = "Ensure unique solution"; |
@@ -221,6 +222,8 @@ static const char *validate_params(const game_params *params, bool full) | |||
221 | { | 222 | { |
222 | if (params->w <= 0 || params->h <= 0) | 223 | if (params->w <= 0 || params->h <= 0) |
223 | return "Width and height must both be greater than zero"; | 224 | return "Width and height must both be greater than zero"; |
225 | if (params->w > INT_MAX / params->h) | ||
226 | return "Width times height must not be unreasonably large"; | ||
224 | if (params->w*params->h < 2) | 227 | if (params->w*params->h < 2) |
225 | return "Grid area must be greater than one"; | 228 | return "Grid area must be greater than one"; |
226 | if (params->expandfactor < 0.0F) | 229 | if (params->expandfactor < 0.0F) |
@@ -2207,7 +2210,7 @@ static game_ui *new_ui(const game_state *state) | |||
2207 | reset_ui(ui); | 2210 | reset_ui(ui); |
2208 | ui->erasing = false; | 2211 | ui->erasing = false; |
2209 | ui->cur_x = ui->cur_y = 0; | 2212 | ui->cur_x = ui->cur_y = 0; |
2210 | ui->cur_visible = false; | 2213 | ui->cur_visible = getenv_bool("PUZZLES_SHOW_CURSOR", false); |
2211 | ui->cur_dragging = false; | 2214 | ui->cur_dragging = false; |
2212 | return ui; | 2215 | return ui; |
2213 | } | 2216 | } |
@@ -2217,15 +2220,6 @@ static void free_ui(game_ui *ui) | |||
2217 | sfree(ui); | 2220 | sfree(ui); |
2218 | } | 2221 | } |
2219 | 2222 | ||
2220 | static char *encode_ui(const game_ui *ui) | ||
2221 | { | ||
2222 | return NULL; | ||
2223 | } | ||
2224 | |||
2225 | static void decode_ui(game_ui *ui, const char *encoding) | ||
2226 | { | ||
2227 | } | ||
2228 | |||
2229 | static void coord_round(float x, float y, int *xr, int *yr) | 2223 | static void coord_round(float x, float y, int *xr, int *yr) |
2230 | { | 2224 | { |
2231 | float xs, ys, xv, yv, dx, dy, dist; | 2225 | float xs, ys, xv, yv, dx, dy, dist; |
@@ -2377,6 +2371,21 @@ struct game_drawstate { | |||
2377 | unsigned long *visible; | 2371 | unsigned long *visible; |
2378 | }; | 2372 | }; |
2379 | 2373 | ||
2374 | static const char *current_key_label(const game_ui *ui, | ||
2375 | const game_state *state, int button) | ||
2376 | { | ||
2377 | if (IS_CURSOR_SELECT(button) && ui->cur_visible && | ||
2378 | !(ui->drag_start_x >= 0 && !ui->cur_dragging)) { | ||
2379 | if (ui->cur_dragging) { | ||
2380 | if (!ui->dragged) return "Cancel"; | ||
2381 | if ((button == CURSOR_SELECT2) == ui->erasing) return "Done"; | ||
2382 | return "Cancel"; | ||
2383 | } | ||
2384 | return button == CURSOR_SELECT ? "Mark" : "Erase"; | ||
2385 | } | ||
2386 | return ""; | ||
2387 | } | ||
2388 | |||
2380 | static char *interpret_move(const game_state *from, game_ui *ui, | 2389 | static char *interpret_move(const game_state *from, game_ui *ui, |
2381 | const game_drawstate *ds, | 2390 | const game_drawstate *ds, |
2382 | int x, int y, int button) | 2391 | int x, int y, int button) |
@@ -2385,7 +2394,7 @@ static char *interpret_move(const game_state *from, game_ui *ui, | |||
2385 | bool startdrag = false, enddrag = false, active = false, erasing = false; | 2394 | bool startdrag = false, enddrag = false, active = false, erasing = false; |
2386 | char buf[80], *ret; | 2395 | char buf[80], *ret; |
2387 | 2396 | ||
2388 | button &= ~MOD_MASK; | 2397 | button = STRIP_BUTTON_MODIFIERS(button); |
2389 | 2398 | ||
2390 | coord_round(FROMCOORD((float)x), FROMCOORD((float)y), &xc, &yc); | 2399 | coord_round(FROMCOORD((float)x), FROMCOORD((float)y), &xc, &yc); |
2391 | 2400 | ||
@@ -2406,10 +2415,11 @@ static char *interpret_move(const game_state *from, game_ui *ui, | |||
2406 | enddrag = true; | 2415 | enddrag = true; |
2407 | erasing = (button == RIGHT_RELEASE); | 2416 | erasing = (button == RIGHT_RELEASE); |
2408 | } else if (IS_CURSOR_MOVE(button)) { | 2417 | } else if (IS_CURSOR_MOVE(button)) { |
2409 | move_cursor(button, &ui->cur_x, &ui->cur_y, from->w, from->h, false); | 2418 | char *ret; |
2410 | ui->cur_visible = true; | 2419 | ret = move_cursor(button, &ui->cur_x, &ui->cur_y, from->w, from->h, |
2420 | false, &ui->cur_visible); | ||
2411 | active = true; | 2421 | active = true; |
2412 | if (!ui->cur_dragging) return UI_UPDATE; | 2422 | if (!ui->cur_dragging || ret != MOVE_UI_UPDATE) return ret; |
2413 | coord_round((float)ui->cur_x + 0.5F, (float)ui->cur_y + 0.5F, &xc, &yc); | 2423 | coord_round((float)ui->cur_x + 0.5F, (float)ui->cur_y + 0.5F, &xc, &yc); |
2414 | } else if (IS_CURSOR_SELECT(button)) { | 2424 | } else if (IS_CURSOR_SELECT(button)) { |
2415 | if (ui->drag_start_x >= 0 && !ui->cur_dragging) { | 2425 | if (ui->drag_start_x >= 0 && !ui->cur_dragging) { |
@@ -2422,7 +2432,7 @@ static char *interpret_move(const game_state *from, game_ui *ui, | |||
2422 | if (!ui->cur_visible) { | 2432 | if (!ui->cur_visible) { |
2423 | assert(!ui->cur_dragging); | 2433 | assert(!ui->cur_dragging); |
2424 | ui->cur_visible = true; | 2434 | ui->cur_visible = true; |
2425 | return UI_UPDATE; | 2435 | return MOVE_UI_UPDATE; |
2426 | } | 2436 | } |
2427 | coord_round((float)ui->cur_x + 0.5F, (float)ui->cur_y + 0.5F, &xc, &yc); | 2437 | coord_round((float)ui->cur_x + 0.5F, (float)ui->cur_y + 0.5F, &xc, &yc); |
2428 | erasing = (button == CURSOR_SELECT2); | 2438 | erasing = (button == CURSOR_SELECT2); |
@@ -2443,7 +2453,7 @@ static char *interpret_move(const game_state *from, game_ui *ui, | |||
2443 | reset_ui(ui); /* cancel keyboard dragging */ | 2453 | reset_ui(ui); /* cancel keyboard dragging */ |
2444 | ui->cur_dragging = false; | 2454 | ui->cur_dragging = false; |
2445 | } | 2455 | } |
2446 | return UI_UPDATE; | 2456 | return MOVE_UI_UPDATE; |
2447 | } else if (button != LEFT_DRAG && button != RIGHT_DRAG) { | 2457 | } else if (button != LEFT_DRAG && button != RIGHT_DRAG) { |
2448 | return NULL; | 2458 | return NULL; |
2449 | } | 2459 | } |
@@ -2527,7 +2537,7 @@ static char *interpret_move(const game_state *from, game_ui *ui, | |||
2527 | if (ret) | 2537 | if (ret) |
2528 | return ret; /* a move has been made */ | 2538 | return ret; /* a move has been made */ |
2529 | else if (active) | 2539 | else if (active) |
2530 | return UI_UPDATE; | 2540 | return MOVE_UI_UPDATE; |
2531 | else | 2541 | else |
2532 | return NULL; | 2542 | return NULL; |
2533 | } | 2543 | } |
@@ -2621,7 +2631,7 @@ static game_state *execute_move(const game_state *from, const char *move) | |||
2621 | #define MAX4(x,y,z,w) ( max(max(x,y),max(z,w)) ) | 2631 | #define MAX4(x,y,z,w) ( max(max(x,y),max(z,w)) ) |
2622 | 2632 | ||
2623 | static void game_compute_size(const game_params *params, int tilesize, | 2633 | static void game_compute_size(const game_params *params, int tilesize, |
2624 | int *x, int *y) | 2634 | const game_ui *ui, int *x, int *y) |
2625 | { | 2635 | { |
2626 | /* Ick: fake up `ds->tilesize' for macro expansion purposes */ | 2636 | /* Ick: fake up `ds->tilesize' for macro expansion purposes */ |
2627 | struct { int tilesize; } ads, *ds = &ads; | 2637 | struct { int tilesize; } ads, *ds = &ads; |
@@ -2796,9 +2806,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, | |||
2796 | } | 2806 | } |
2797 | 2807 | ||
2798 | if (!ds->started) { | 2808 | if (!ds->started) { |
2799 | draw_rect(dr, 0, 0, | ||
2800 | state->w * TILE_SIZE + 2*BORDER + 1, | ||
2801 | state->h * TILE_SIZE + 2*BORDER + 1, COL_BACKGROUND); | ||
2802 | draw_rect(dr, COORD(0)-1, COORD(0)-1, | 2809 | draw_rect(dr, COORD(0)-1, COORD(0)-1, |
2803 | ds->w*TILE_SIZE+3, ds->h*TILE_SIZE+3, COL_LINE); | 2810 | ds->w*TILE_SIZE+3, ds->h*TILE_SIZE+3, COL_LINE); |
2804 | ds->started = true; | 2811 | ds->started = true; |
@@ -2901,24 +2908,21 @@ static int game_status(const game_state *state) | |||
2901 | return state->completed ? +1 : 0; | 2908 | return state->completed ? +1 : 0; |
2902 | } | 2909 | } |
2903 | 2910 | ||
2904 | static bool game_timing_state(const game_state *state, game_ui *ui) | 2911 | static void game_print_size(const game_params *params, const game_ui *ui, |
2905 | { | 2912 | float *x, float *y) |
2906 | return true; | ||
2907 | } | ||
2908 | |||
2909 | static void game_print_size(const game_params *params, float *x, float *y) | ||
2910 | { | 2913 | { |
2911 | int pw, ph; | 2914 | int pw, ph; |
2912 | 2915 | ||
2913 | /* | 2916 | /* |
2914 | * I'll use 5mm squares by default. | 2917 | * I'll use 5mm squares by default. |
2915 | */ | 2918 | */ |
2916 | game_compute_size(params, 500, &pw, &ph); | 2919 | game_compute_size(params, 500, ui, &pw, &ph); |
2917 | *x = pw / 100.0F; | 2920 | *x = pw / 100.0F; |
2918 | *y = ph / 100.0F; | 2921 | *y = ph / 100.0F; |
2919 | } | 2922 | } |
2920 | 2923 | ||
2921 | static void game_print(drawing *dr, const game_state *state, int tilesize) | 2924 | static void game_print(drawing *dr, const game_state *state, const game_ui *ui, |
2925 | int tilesize) | ||
2922 | { | 2926 | { |
2923 | int w = state->w, h = state->h; | 2927 | int w = state->w, h = state->h; |
2924 | int ink = print_mono_colour(dr, 0); | 2928 | int ink = print_mono_colour(dr, 0); |
@@ -2992,12 +2996,14 @@ const struct game thegame = { | |||
2992 | free_game, | 2996 | free_game, |
2993 | true, solve_game, | 2997 | true, solve_game, |
2994 | true, game_can_format_as_text_now, game_text_format, | 2998 | true, game_can_format_as_text_now, game_text_format, |
2999 | NULL, NULL, /* get_prefs, set_prefs */ | ||
2995 | new_ui, | 3000 | new_ui, |
2996 | free_ui, | 3001 | free_ui, |
2997 | encode_ui, | 3002 | NULL, /* encode_ui */ |
2998 | decode_ui, | 3003 | NULL, /* decode_ui */ |
2999 | NULL, /* game_request_keys */ | 3004 | NULL, /* game_request_keys */ |
3000 | game_changed_state, | 3005 | game_changed_state, |
3006 | current_key_label, | ||
3001 | interpret_move, | 3007 | interpret_move, |
3002 | execute_move, | 3008 | execute_move, |
3003 | PREFERRED_TILE_SIZE, game_compute_size, game_set_size, | 3009 | PREFERRED_TILE_SIZE, game_compute_size, game_set_size, |
@@ -3011,7 +3017,7 @@ const struct game thegame = { | |||
3011 | game_status, | 3017 | game_status, |
3012 | true, false, game_print_size, game_print, | 3018 | true, false, game_print_size, game_print, |
3013 | true, /* wants_statusbar */ | 3019 | true, /* wants_statusbar */ |
3014 | false, game_timing_state, | 3020 | false, NULL, /* timing_state */ |
3015 | 0, /* flags */ | 3021 | 0, /* flags */ |
3016 | }; | 3022 | }; |
3017 | 3023 | ||