summaryrefslogtreecommitdiff
path: root/apps/plugins/puzzles/src/flip.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/puzzles/src/flip.c')
-rw-r--r--apps/plugins/puzzles/src/flip.c89
1 files changed, 36 insertions, 53 deletions
diff --git a/apps/plugins/puzzles/src/flip.c b/apps/plugins/puzzles/src/flip.c
index 5d4f2250aa..044d6c30c3 100644
--- a/apps/plugins/puzzles/src/flip.c
+++ b/apps/plugins/puzzles/src/flip.c
@@ -8,7 +8,12 @@
8#include <string.h> 8#include <string.h>
9#include <assert.h> 9#include <assert.h>
10#include <ctype.h> 10#include <ctype.h>
11#include <math.h> 11#include <limits.h>
12#ifdef NO_TGMATH_H
13# include <math.h>
14#else
15# include <tgmath.h>
16#endif
12 17
13#include "puzzles.h" 18#include "puzzles.h"
14#include "tree234.h" 19#include "tree234.h"
@@ -181,9 +186,16 @@ static game_params *custom_params(const config_item *cfg)
181 186
182static const char *validate_params(const game_params *params, bool full) 187static const char *validate_params(const game_params *params, bool full)
183{ 188{
189 int wh;
190
184 if (params->w <= 0 || params->h <= 0) 191 if (params->w <= 0 || params->h <= 0)
185 return "Width and height must both be greater than zero"; 192 return "Width and height must both be greater than zero";
186 return NULL; 193 if (params->w > (INT_MAX - 3) / params->h)
194 return "Width times height must not be unreasonably large";
195 wh = params->w * params->h;
196 if (wh > (INT_MAX - 3) / wh)
197 return "Width times height is too large";
198 return NULL;
187} 199}
188 200
189static char *encode_bitmap(unsigned char *bmp, int len) 201static char *encode_bitmap(unsigned char *bmp, int len)
@@ -905,7 +917,7 @@ static game_ui *new_ui(const game_state *state)
905{ 917{
906 game_ui *ui = snew(game_ui); 918 game_ui *ui = snew(game_ui);
907 ui->cx = ui->cy = 0; 919 ui->cx = ui->cy = 0;
908 ui->cdraw = false; 920 ui->cdraw = getenv_bool("PUZZLES_SHOW_CURSOR", false);
909 return ui; 921 return ui;
910} 922}
911 923
@@ -914,18 +926,16 @@ static void free_ui(game_ui *ui)
914 sfree(ui); 926 sfree(ui);
915} 927}
916 928
917static char *encode_ui(const game_ui *ui) 929static void game_changed_state(game_ui *ui, const game_state *oldstate,
918{ 930 const game_state *newstate)
919 return NULL;
920}
921
922static void decode_ui(game_ui *ui, const char *encoding)
923{ 931{
924} 932}
925 933
926static void game_changed_state(game_ui *ui, const game_state *oldstate, 934static const char *current_key_label(const game_ui *ui,
927 const game_state *newstate) 935 const game_state *state, int button)
928{ 936{
937 if (IS_CURSOR_SELECT(button)) return "Flip";
938 return "";
929} 939}
930 940
931struct game_drawstate { 941struct game_drawstate {
@@ -940,7 +950,7 @@ static char *interpret_move(const game_state *state, game_ui *ui,
940 int x, int y, int button) 950 int x, int y, int button)
941{ 951{
942 int w = state->w, h = state->h, wh = w * h; 952 int w = state->w, h = state->h, wh = w * h;
943 char buf[80], *nullret = NULL; 953 char buf[80], *nullret = MOVE_UNUSED;
944 954
945 if (button == LEFT_BUTTON || IS_CURSOR_SELECT(button)) { 955 if (button == LEFT_BUTTON || IS_CURSOR_SELECT(button)) {
946 int tx, ty; 956 int tx, ty;
@@ -951,7 +961,7 @@ static char *interpret_move(const game_state *state, game_ui *ui,
951 tx = ui->cx; ty = ui->cy; 961 tx = ui->cx; ty = ui->cy;
952 ui->cdraw = true; 962 ui->cdraw = true;
953 } 963 }
954 nullret = UI_UPDATE; 964 nullret = MOVE_UI_UPDATE;
955 965
956 if (tx >= 0 && tx < w && ty >= 0 && ty < h) { 966 if (tx >= 0 && tx < w && ty >= 0 && ty < h) {
957 /* 967 /*
@@ -969,25 +979,12 @@ static char *interpret_move(const game_state *state, game_ui *ui,
969 sprintf(buf, "M%d,%d", tx, ty); 979 sprintf(buf, "M%d,%d", tx, ty);
970 return dupstr(buf); 980 return dupstr(buf);
971 } else { 981 } else {
972 return NULL; 982 return MOVE_NO_EFFECT;
973 } 983 }
974 } 984 }
975 } 985 } else if (IS_CURSOR_MOVE(button))
976 else if (IS_CURSOR_MOVE(button)) { 986 nullret = move_cursor(button, &ui->cx, &ui->cy, state->w, state->h,
977 int dx = 0, dy = 0; 987 false, &ui->cdraw);
978 switch (button) {
979 case CURSOR_UP: dy = -1; break;
980 case CURSOR_DOWN: dy = 1; break;
981 case CURSOR_RIGHT: dx = 1; break;
982 case CURSOR_LEFT: dx = -1; break;
983 default: assert(!"shouldn't get here");
984 }
985 ui->cx += dx; ui->cy += dy;
986 ui->cx = min(max(ui->cx, 0), state->w - 1);
987 ui->cy = min(max(ui->cy, 0), state->h - 1);
988 ui->cdraw = true;
989 nullret = UI_UPDATE;
990 }
991 988
992 return nullret; 989 return nullret;
993} 990}
@@ -1045,7 +1042,7 @@ static game_state *execute_move(const game_state *from, const char *move)
1045 */ 1042 */
1046 1043
1047static void game_compute_size(const game_params *params, int tilesize, 1044static void game_compute_size(const game_params *params, int tilesize,
1048 int *x, int *y) 1045 const game_ui *ui, int *x, int *y)
1049{ 1046{
1050 /* Ick: fake up `ds->tilesize' for macro expansion purposes */ 1047 /* Ick: fake up `ds->tilesize' for macro expansion purposes */
1051 struct { int tilesize; } ads, *ds = &ads; 1048 struct { int tilesize; } ads, *ds = &ads;
@@ -1145,7 +1142,7 @@ static void draw_tile(drawing *dr, game_drawstate *ds, const game_state *state,
1145 coords[7] = by + TILE_SIZE - (int)((float)TILE_SIZE * animtime); 1142 coords[7] = by + TILE_SIZE - (int)((float)TILE_SIZE * animtime);
1146 1143
1147 colour = (tile & 1 ? COL_WRONG : COL_RIGHT); 1144 colour = (tile & 1 ? COL_WRONG : COL_RIGHT);
1148 if (animtime < 0.5) 1145 if (animtime < 0.5F)
1149 colour = COL_WRONG + COL_RIGHT - colour; 1146 colour = COL_WRONG + COL_RIGHT - colour;
1150 1147
1151 draw_polygon(dr, coords, 4, colour, COL_GRID); 1148 draw_polygon(dr, coords, 4, colour, COL_GRID);
@@ -1159,7 +1156,7 @@ static void draw_tile(drawing *dr, game_drawstate *ds, const game_state *state,
1159 for (j = 0; j < w; j++) 1156 for (j = 0; j < w; j++)
1160 if (state->matrix->matrix[(y*w+x)*wh + i*w+j]) { 1157 if (state->matrix->matrix[(y*w+x)*wh + i*w+j]) {
1161 int ox = j - x, oy = i - y; 1158 int ox = j - x, oy = i - y;
1162 int td = TILE_SIZE / 16; 1159 int td = TILE_SIZE / 16 ? TILE_SIZE / 16 : 1;
1163 int cx = (bx + TILE_SIZE/2) + (2 * ox - 1) * td; 1160 int cx = (bx + TILE_SIZE/2) + (2 * ox - 1) * td;
1164 int cy = (by + TILE_SIZE/2) + (2 * oy - 1) * td; 1161 int cy = (by + TILE_SIZE/2) + (2 * oy - 1) * td;
1165 if (ox == 0 && oy == 0) 1162 if (ox == 0 && oy == 0)
@@ -1202,9 +1199,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds,
1202 int i, flashframe; 1199 int i, flashframe;
1203 1200
1204 if (!ds->started) { 1201 if (!ds->started) {
1205 draw_rect(dr, 0, 0, TILE_SIZE * w + 2 * BORDER,
1206 TILE_SIZE * h + 2 * BORDER, COL_BACKGROUND);
1207
1208 /* 1202 /*
1209 * Draw the grid lines. 1203 * Draw the grid lines.
1210 */ 1204 */
@@ -1309,19 +1303,6 @@ static int game_status(const game_state *state)
1309 return state->completed ? +1 : 0; 1303 return state->completed ? +1 : 0;
1310} 1304}
1311 1305
1312static bool game_timing_state(const game_state *state, game_ui *ui)
1313{
1314 return true;
1315}
1316
1317static void game_print_size(const game_params *params, float *x, float *y)
1318{
1319}
1320
1321static void game_print(drawing *dr, const game_state *state, int tilesize)
1322{
1323}
1324
1325#ifdef COMBINED 1306#ifdef COMBINED
1326#define thegame flip 1307#define thegame flip
1327#endif 1308#endif
@@ -1343,12 +1324,14 @@ const struct game thegame = {
1343 free_game, 1324 free_game,
1344 true, solve_game, 1325 true, solve_game,
1345 true, game_can_format_as_text_now, game_text_format, 1326 true, game_can_format_as_text_now, game_text_format,
1327 NULL, NULL, /* get_prefs, set_prefs */
1346 new_ui, 1328 new_ui,
1347 free_ui, 1329 free_ui,
1348 encode_ui, 1330 NULL, /* encode_ui */
1349 decode_ui, 1331 NULL, /* decode_ui */
1350 NULL, /* game_request_keys */ 1332 NULL, /* game_request_keys */
1351 game_changed_state, 1333 game_changed_state,
1334 current_key_label,
1352 interpret_move, 1335 interpret_move,
1353 execute_move, 1336 execute_move,
1354 PREFERRED_TILE_SIZE, game_compute_size, game_set_size, 1337 PREFERRED_TILE_SIZE, game_compute_size, game_set_size,
@@ -1360,8 +1343,8 @@ const struct game thegame = {
1360 game_flash_length, 1343 game_flash_length,
1361 game_get_cursor_location, 1344 game_get_cursor_location,
1362 game_status, 1345 game_status,
1363 false, false, game_print_size, game_print, 1346 false, false, NULL, NULL, /* print_size, print */
1364 true, /* wants_statusbar */ 1347 true, /* wants_statusbar */
1365 false, game_timing_state, 1348 false, NULL, /* timing_state */
1366 0, /* flags */ 1349 0, /* flags */
1367}; 1350};