summaryrefslogtreecommitdiff
path: root/apps/plugins/puzzles/src/rect.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/puzzles/src/rect.c')
-rw-r--r--apps/plugins/puzzles/src/rect.c82
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
2220static char *encode_ui(const game_ui *ui)
2221{
2222 return NULL;
2223}
2224
2225static void decode_ui(game_ui *ui, const char *encoding)
2226{
2227}
2228
2229static void coord_round(float x, float y, int *xr, int *yr) 2223static 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
2374static 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
2380static char *interpret_move(const game_state *from, game_ui *ui, 2389static 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
2623static void game_compute_size(const game_params *params, int tilesize, 2633static 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
2904static bool game_timing_state(const game_state *state, game_ui *ui) 2911static void game_print_size(const game_params *params, const game_ui *ui,
2905{ 2912 float *x, float *y)
2906 return true;
2907}
2908
2909static 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
2921static void game_print(drawing *dr, const game_state *state, int tilesize) 2924static 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