diff options
Diffstat (limited to 'apps/plugins/puzzles/src/cube.c')
-rw-r--r-- | apps/plugins/puzzles/src/cube.c | 110 |
1 files changed, 52 insertions, 58 deletions
diff --git a/apps/plugins/puzzles/src/cube.c b/apps/plugins/puzzles/src/cube.c index 8c8c46faed..08788cbd65 100644 --- a/apps/plugins/puzzles/src/cube.c +++ b/apps/plugins/puzzles/src/cube.c | |||
@@ -7,7 +7,11 @@ | |||
7 | #include <string.h> | 7 | #include <string.h> |
8 | #include <assert.h> | 8 | #include <assert.h> |
9 | #include <ctype.h> | 9 | #include <ctype.h> |
10 | #include <math.h> | 10 | #ifdef NO_TGMATH_H |
11 | # include <math.h> | ||
12 | #else | ||
13 | # include <tgmath.h> | ||
14 | #endif | ||
11 | 15 | ||
12 | #include "puzzles.h" | 16 | #include "puzzles.h" |
13 | 17 | ||
@@ -171,7 +175,7 @@ enum { LEFT, RIGHT, UP, DOWN, UP_LEFT, UP_RIGHT, DOWN_LEFT, DOWN_RIGHT }; | |||
171 | (ra)[0] = rx; (ra)[1] = ry; (ra)[2] = rz; \ | 175 | (ra)[0] = rx; (ra)[1] = ry; (ra)[2] = rz; \ |
172 | } while (0) | 176 | } while (0) |
173 | 177 | ||
174 | #define APPROXEQ(x,y) ( SQ(x-y) < 0.1 ) | 178 | #define APPROXEQ(x,y) ( SQ(x-y) < 0.1F ) |
175 | 179 | ||
176 | struct grid_square { | 180 | struct grid_square { |
177 | float x, y; | 181 | float x, y; |
@@ -202,8 +206,8 @@ struct game_grid { | |||
202 | }; | 206 | }; |
203 | 207 | ||
204 | #define SET_SQUARE(state, i, val) \ | 208 | #define SET_SQUARE(state, i, val) \ |
205 | ((state)->bluemask[(i)/32] &= ~(1 << ((i)%32)), \ | 209 | ((state)->bluemask[(i)/32] &= ~(1UL << ((i)%32)), \ |
206 | (state)->bluemask[(i)/32] |= ((!!val) << ((i)%32))) | 210 | (state)->bluemask[(i)/32] |= ((unsigned long)(!!val) << ((i)%32))) |
207 | #define GET_SQUARE(state, i) \ | 211 | #define GET_SQUARE(state, i) \ |
208 | (((state)->bluemask[(i)/32] >> ((i)%32)) & 1) | 212 | (((state)->bluemask[(i)/32] >> ((i)%32)) & 1) |
209 | 213 | ||
@@ -542,12 +546,38 @@ static const char *validate_params(const game_params *params, bool full) | |||
542 | if (params->solid < 0 || params->solid >= lenof(solids)) | 546 | if (params->solid < 0 || params->solid >= lenof(solids)) |
543 | return "Unrecognised solid type"; | 547 | return "Unrecognised solid type"; |
544 | 548 | ||
549 | if (params->d1 < 0 || params->d2 < 0) | ||
550 | return "Grid dimensions may not be negative"; | ||
551 | |||
545 | if (solids[params->solid]->order == 4) { | 552 | if (solids[params->solid]->order == 4) { |
546 | if (params->d1 <= 1 || params->d2 <= 1) | 553 | if (params->d1 <= 1 || params->d2 <= 1) |
547 | return "Both grid dimensions must be greater than one"; | 554 | return "Both grid dimensions must be greater than one"; |
555 | if (params->d2 > INT_MAX / params->d1) | ||
556 | return "Grid area must not be unreasonably large"; | ||
548 | } else { | 557 | } else { |
549 | if (params->d1 <= 0 && params->d2 <= 0) | 558 | if (params->d1 <= 0 && params->d2 <= 0) |
550 | return "At least one grid dimension must be greater than zero"; | 559 | return "At least one grid dimension must be greater than zero"; |
560 | |||
561 | /* | ||
562 | * Check whether d1^2 + d2^2 + 4 d1 d2 > INT_MAX, without overflow: | ||
563 | * | ||
564 | * First check d1^2 doesn't overflow by itself. | ||
565 | * | ||
566 | * Then check d2^2 doesn't exceed the remaining space between | ||
567 | * d1^2 and INT_MAX. | ||
568 | * | ||
569 | * If that's all OK then we know both d1 and d2 are | ||
570 | * individually less than the square root of INT_MAX, so we | ||
571 | * can safely multiply them and compare against the | ||
572 | * _remaining_ space. | ||
573 | */ | ||
574 | if ((params->d1 > 0 && params->d1 > INT_MAX / params->d1) || | ||
575 | (params->d2 > 0 && | ||
576 | params->d2 > (INT_MAX - params->d1*params->d1) / params->d2) || | ||
577 | (params->d2 > 0 && | ||
578 | params->d1*params->d2 > (INT_MAX - params->d1*params->d1 - | ||
579 | params->d2*params->d2) / params->d2)) | ||
580 | return "Grid area must not be unreasonably large"; | ||
551 | } | 581 | } |
552 | 582 | ||
553 | for (i = 0; i < 4; i++) | 583 | for (i = 0; i < 4; i++) |
@@ -761,7 +791,7 @@ static bool align_poly(const struct solid *solid, struct grid_square *sq, | |||
761 | dist += SQ(solid->vertices[i*3+1] * flip - sq->points[j*2+1] + sq->y); | 791 | dist += SQ(solid->vertices[i*3+1] * flip - sq->points[j*2+1] + sq->y); |
762 | dist += SQ(solid->vertices[i*3+2] - zmin); | 792 | dist += SQ(solid->vertices[i*3+2] - zmin); |
763 | 793 | ||
764 | if (dist < 0.1) { | 794 | if (dist < 0.1F) { |
765 | matches++; | 795 | matches++; |
766 | index = i; | 796 | index = i; |
767 | } | 797 | } |
@@ -811,7 +841,7 @@ static struct solid *transform_poly(const struct solid *solid, bool flip, | |||
811 | */ | 841 | */ |
812 | vx = ret->vertices[key1*3+0] - ret->vertices[key0*3+0]; | 842 | vx = ret->vertices[key1*3+0] - ret->vertices[key0*3+0]; |
813 | vy = ret->vertices[key1*3+1] - ret->vertices[key0*3+1]; | 843 | vy = ret->vertices[key1*3+1] - ret->vertices[key0*3+1]; |
814 | assert(APPROXEQ(vx*vx + vy*vy, 1.0)); | 844 | assert(APPROXEQ(vx*vx + vy*vy, 1.0F)); |
815 | 845 | ||
816 | vmatrix[0] = vx; vmatrix[3] = vy; vmatrix[6] = 0; | 846 | vmatrix[0] = vx; vmatrix[3] = vy; vmatrix[6] = 0; |
817 | vmatrix[1] = -vy; vmatrix[4] = vx; vmatrix[7] = 0; | 847 | vmatrix[1] = -vy; vmatrix[4] = vx; vmatrix[7] = 0; |
@@ -999,22 +1029,6 @@ static void free_game(game_state *state) | |||
999 | sfree(state); | 1029 | sfree(state); |
1000 | } | 1030 | } |
1001 | 1031 | ||
1002 | static char *solve_game(const game_state *state, const game_state *currstate, | ||
1003 | const char *aux, const char **error) | ||
1004 | { | ||
1005 | return NULL; | ||
1006 | } | ||
1007 | |||
1008 | static bool game_can_format_as_text_now(const game_params *params) | ||
1009 | { | ||
1010 | return true; | ||
1011 | } | ||
1012 | |||
1013 | static char *game_text_format(const game_state *state) | ||
1014 | { | ||
1015 | return NULL; | ||
1016 | } | ||
1017 | |||
1018 | static game_ui *new_ui(const game_state *state) | 1032 | static game_ui *new_ui(const game_state *state) |
1019 | { | 1033 | { |
1020 | return NULL; | 1034 | return NULL; |
@@ -1024,15 +1038,6 @@ static void free_ui(game_ui *ui) | |||
1024 | { | 1038 | { |
1025 | } | 1039 | } |
1026 | 1040 | ||
1027 | static char *encode_ui(const game_ui *ui) | ||
1028 | { | ||
1029 | return NULL; | ||
1030 | } | ||
1031 | |||
1032 | static void decode_ui(game_ui *ui, const char *encoding) | ||
1033 | { | ||
1034 | } | ||
1035 | |||
1036 | static void game_changed_state(game_ui *ui, const game_state *oldstate, | 1041 | static void game_changed_state(game_ui *ui, const game_state *oldstate, |
1037 | const game_state *newstate) | 1042 | const game_state *newstate) |
1038 | { | 1043 | { |
@@ -1081,11 +1086,11 @@ static int find_move_dest(const game_state *from, int direction, | |||
1081 | for (j = 0; j < from->grid->squares[i].npoints; j++) { | 1086 | for (j = 0; j < from->grid->squares[i].npoints; j++) { |
1082 | dist = (SQ(from->grid->squares[i].points[j*2] - points[0]) + | 1087 | dist = (SQ(from->grid->squares[i].points[j*2] - points[0]) + |
1083 | SQ(from->grid->squares[i].points[j*2+1] - points[1])); | 1088 | SQ(from->grid->squares[i].points[j*2+1] - points[1])); |
1084 | if (dist < 0.1) | 1089 | if (dist < 0.1F) |
1085 | dkey[match++] = j; | 1090 | dkey[match++] = j; |
1086 | dist = (SQ(from->grid->squares[i].points[j*2] - points[2]) + | 1091 | dist = (SQ(from->grid->squares[i].points[j*2] - points[2]) + |
1087 | SQ(from->grid->squares[i].points[j*2+1] - points[3])); | 1092 | SQ(from->grid->squares[i].points[j*2+1] - points[3])); |
1088 | if (dist < 0.1) | 1093 | if (dist < 0.1F) |
1089 | dkey[match++] = j; | 1094 | dkey[match++] = j; |
1090 | } | 1095 | } |
1091 | 1096 | ||
@@ -1140,7 +1145,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, | |||
1140 | cy = (int)(state->grid->squares[state->current].y * GRID_SCALE) + ds->oy; | 1145 | cy = (int)(state->grid->squares[state->current].y * GRID_SCALE) + ds->oy; |
1141 | 1146 | ||
1142 | if (x == cx && y == cy) | 1147 | if (x == cx && y == cy) |
1143 | return NULL; /* clicked in exact centre! */ | 1148 | return MOVE_NO_EFFECT; /* clicked in exact centre! */ |
1144 | angle = atan2(y - cy, x - cx); | 1149 | angle = atan2(y - cy, x - cx); |
1145 | 1150 | ||
1146 | /* | 1151 | /* |
@@ -1191,11 +1196,11 @@ static char *interpret_move(const game_state *state, game_ui *ui, | |||
1191 | direction = RIGHT; | 1196 | direction = RIGHT; |
1192 | } | 1197 | } |
1193 | } else | 1198 | } else |
1194 | return NULL; | 1199 | return MOVE_UNUSED; |
1195 | 1200 | ||
1196 | mask = state->grid->squares[state->current].directions[direction]; | 1201 | mask = state->grid->squares[state->current].directions[direction]; |
1197 | if (mask == 0) | 1202 | if (mask == 0) |
1198 | return NULL; | 1203 | return MOVE_NO_EFFECT; |
1199 | 1204 | ||
1200 | /* | 1205 | /* |
1201 | * Translate diagonal directions into orthogonal ones. | 1206 | * Translate diagonal directions into orthogonal ones. |
@@ -1210,14 +1215,14 @@ static char *interpret_move(const game_state *state, game_ui *ui, | |||
1210 | } | 1215 | } |
1211 | 1216 | ||
1212 | if (find_move_dest(state, direction, skey, dkey) < 0) | 1217 | if (find_move_dest(state, direction, skey, dkey) < 0) |
1213 | return NULL; | 1218 | return MOVE_NO_EFFECT; |
1214 | 1219 | ||
1215 | if (direction == LEFT) return dupstr("L"); | 1220 | if (direction == LEFT) return dupstr("L"); |
1216 | if (direction == RIGHT) return dupstr("R"); | 1221 | if (direction == RIGHT) return dupstr("R"); |
1217 | if (direction == UP) return dupstr("U"); | 1222 | if (direction == UP) return dupstr("U"); |
1218 | if (direction == DOWN) return dupstr("D"); | 1223 | if (direction == DOWN) return dupstr("D"); |
1219 | 1224 | ||
1220 | return NULL; /* should never happen */ | 1225 | return MOVE_NO_EFFECT; /* should never happen */ |
1221 | } | 1226 | } |
1222 | 1227 | ||
1223 | static game_state *execute_move(const game_state *from, const char *move) | 1228 | static game_state *execute_move(const game_state *from, const char *move) |
@@ -1484,7 +1489,7 @@ static struct bbox find_bbox(const game_params *params) | |||
1484 | ((int)(((bb).d - (bb).u + 2*(solid)->border) * gs)) | 1489 | ((int)(((bb).d - (bb).u + 2*(solid)->border) * gs)) |
1485 | 1490 | ||
1486 | static void game_compute_size(const game_params *params, int tilesize, | 1491 | static void game_compute_size(const game_params *params, int tilesize, |
1487 | int *x, int *y) | 1492 | const game_ui *ui, int *x, int *y) |
1488 | { | 1493 | { |
1489 | struct bbox bb = find_bbox(params); | 1494 | struct bbox bb = find_bbox(params); |
1490 | 1495 | ||
@@ -1734,19 +1739,6 @@ static int game_status(const game_state *state) | |||
1734 | return state->completed ? +1 : 0; | 1739 | return state->completed ? +1 : 0; |
1735 | } | 1740 | } |
1736 | 1741 | ||
1737 | static bool game_timing_state(const game_state *state, game_ui *ui) | ||
1738 | { | ||
1739 | return true; | ||
1740 | } | ||
1741 | |||
1742 | static void game_print_size(const game_params *params, float *x, float *y) | ||
1743 | { | ||
1744 | } | ||
1745 | |||
1746 | static void game_print(drawing *dr, const game_state *state, int tilesize) | ||
1747 | { | ||
1748 | } | ||
1749 | |||
1750 | #ifdef COMBINED | 1742 | #ifdef COMBINED |
1751 | #define thegame cube | 1743 | #define thegame cube |
1752 | #endif | 1744 | #endif |
@@ -1766,14 +1758,16 @@ const struct game thegame = { | |||
1766 | new_game, | 1758 | new_game, |
1767 | dup_game, | 1759 | dup_game, |
1768 | free_game, | 1760 | free_game, |
1769 | false, solve_game, | 1761 | false, NULL, /* solve */ |
1770 | false, game_can_format_as_text_now, game_text_format, | 1762 | false, NULL, NULL, /* can_format_as_text_now, text_format */ |
1763 | NULL, NULL, /* get_prefs, set_prefs */ | ||
1771 | new_ui, | 1764 | new_ui, |
1772 | free_ui, | 1765 | free_ui, |
1773 | encode_ui, | 1766 | NULL, /* encode_ui */ |
1774 | decode_ui, | 1767 | NULL, /* decode_ui */ |
1775 | NULL, /* game_request_keys */ | 1768 | NULL, /* game_request_keys */ |
1776 | game_changed_state, | 1769 | game_changed_state, |
1770 | NULL, /* current_key_label */ | ||
1777 | interpret_move, | 1771 | interpret_move, |
1778 | execute_move, | 1772 | execute_move, |
1779 | PREFERRED_GRID_SCALE, game_compute_size, game_set_size, | 1773 | PREFERRED_GRID_SCALE, game_compute_size, game_set_size, |
@@ -1785,8 +1779,8 @@ const struct game thegame = { | |||
1785 | game_flash_length, | 1779 | game_flash_length, |
1786 | game_get_cursor_location, | 1780 | game_get_cursor_location, |
1787 | game_status, | 1781 | game_status, |
1788 | false, false, game_print_size, game_print, | 1782 | false, false, NULL, NULL, /* print_size, print */ |
1789 | true, /* wants_statusbar */ | 1783 | true, /* wants_statusbar */ |
1790 | false, game_timing_state, | 1784 | false, NULL, /* timing_state */ |
1791 | 0, /* flags */ | 1785 | 0, /* flags */ |
1792 | }; | 1786 | }; |