diff options
Diffstat (limited to 'apps/plugins/puzzles/src/inertia.c')
-rw-r--r-- | apps/plugins/puzzles/src/inertia.c | 88 |
1 files changed, 34 insertions, 54 deletions
diff --git a/apps/plugins/puzzles/src/inertia.c b/apps/plugins/puzzles/src/inertia.c index 726c89c7dd..fe174f3b56 100644 --- a/apps/plugins/puzzles/src/inertia.c +++ b/apps/plugins/puzzles/src/inertia.c | |||
@@ -11,7 +11,12 @@ | |||
11 | #include <string.h> | 11 | #include <string.h> |
12 | #include <assert.h> | 12 | #include <assert.h> |
13 | #include <ctype.h> | 13 | #include <ctype.h> |
14 | #include <math.h> | 14 | #include <limits.h> |
15 | #ifdef NO_TGMATH_H | ||
16 | # include <math.h> | ||
17 | #else | ||
18 | # include <tgmath.h> | ||
19 | #endif | ||
15 | 20 | ||
16 | #include "puzzles.h" | 21 | #include "puzzles.h" |
17 | 22 | ||
@@ -202,6 +207,8 @@ static const char *validate_params(const game_params *params, bool full) | |||
202 | */ | 207 | */ |
203 | if (params->w < 2 || params->h < 2) | 208 | if (params->w < 2 || params->h < 2) |
204 | return "Width and height must both be at least two"; | 209 | return "Width and height must both be at least two"; |
210 | if (params->w > INT_MAX / params->h) | ||
211 | return "Width times height must not be unreasonably large"; | ||
205 | 212 | ||
206 | /* | 213 | /* |
207 | * The grid construction algorithm creates 1/5 as many gems as | 214 | * The grid construction algorithm creates 1/5 as many gems as |
@@ -715,18 +722,6 @@ static int move_goes_to(int w, int h, char *grid, int x, int y, int d) | |||
715 | return (y*w+x)*DP1+dr; | 722 | return (y*w+x)*DP1+dr; |
716 | } | 723 | } |
717 | 724 | ||
718 | static int compare_integers(const void *av, const void *bv) | ||
719 | { | ||
720 | const int *a = (const int *)av; | ||
721 | const int *b = (const int *)bv; | ||
722 | if (*a < *b) | ||
723 | return -1; | ||
724 | else if (*a > *b) | ||
725 | return +1; | ||
726 | else | ||
727 | return 0; | ||
728 | } | ||
729 | |||
730 | static char *solve_game(const game_state *state, const game_state *currstate, | 725 | static char *solve_game(const game_state *state, const game_state *currstate, |
731 | const char *aux, const char **error) | 726 | const char *aux, const char **error) |
732 | { | 727 | { |
@@ -1520,7 +1515,8 @@ static char *encode_ui(const game_ui *ui) | |||
1520 | return dupstr(buf); | 1515 | return dupstr(buf); |
1521 | } | 1516 | } |
1522 | 1517 | ||
1523 | static void decode_ui(game_ui *ui, const char *encoding) | 1518 | static void decode_ui(game_ui *ui, const char *encoding, |
1519 | const game_state *state) | ||
1524 | { | 1520 | { |
1525 | int p = 0; | 1521 | int p = 0; |
1526 | sscanf(encoding, "D%d%n", &ui->deaths, &p); | 1522 | sscanf(encoding, "D%d%n", &ui->deaths, &p); |
@@ -1545,6 +1541,15 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, | |||
1545 | ui->just_made_move = false; | 1541 | ui->just_made_move = false; |
1546 | } | 1542 | } |
1547 | 1543 | ||
1544 | static const char *current_key_label(const game_ui *ui, | ||
1545 | const game_state *state, int button) | ||
1546 | { | ||
1547 | if (IS_CURSOR_SELECT(button) && | ||
1548 | state->soln && state->solnpos < state->soln->len) | ||
1549 | return "Advance"; | ||
1550 | return ""; | ||
1551 | } | ||
1552 | |||
1548 | struct game_drawstate { | 1553 | struct game_drawstate { |
1549 | game_params p; | 1554 | game_params p; |
1550 | int tilesize; | 1555 | int tilesize; |
@@ -1593,7 +1598,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, | |||
1593 | * end up the right way round. */ | 1598 | * end up the right way round. */ |
1594 | angle = atan2(dx, -dy); | 1599 | angle = atan2(dx, -dy); |
1595 | 1600 | ||
1596 | angle = (angle + (PI/8)) / (PI/4); | 1601 | angle = (angle + (float)(PI/8)) / (float)(PI/4); |
1597 | assert(angle > -16.0F); | 1602 | assert(angle > -16.0F); |
1598 | dir = (int)(angle + 16.0F) & 7; | 1603 | dir = (int)(angle + 16.0F) & 7; |
1599 | } | 1604 | } |
@@ -1618,20 +1623,20 @@ static char *interpret_move(const game_state *state, game_ui *ui, | |||
1618 | dir = state->soln->list[state->solnpos]; | 1623 | dir = state->soln->list[state->solnpos]; |
1619 | 1624 | ||
1620 | if (dir < 0) | 1625 | if (dir < 0) |
1621 | return NULL; | 1626 | return MOVE_UNUSED; |
1622 | 1627 | ||
1623 | /* | 1628 | /* |
1624 | * Reject the move if we can't make it at all due to a wall | 1629 | * Reject the move if we can't make it at all due to a wall |
1625 | * being in the way. | 1630 | * being in the way. |
1626 | */ | 1631 | */ |
1627 | if (AT(w, h, state->grid, state->px+DX(dir), state->py+DY(dir)) == WALL) | 1632 | if (AT(w, h, state->grid, state->px+DX(dir), state->py+DY(dir)) == WALL) |
1628 | return NULL; | 1633 | return MOVE_NO_EFFECT; |
1629 | 1634 | ||
1630 | /* | 1635 | /* |
1631 | * Reject the move if we're dead! | 1636 | * Reject the move if we're dead! |
1632 | */ | 1637 | */ |
1633 | if (state->dead) | 1638 | if (state->dead) |
1634 | return NULL; | 1639 | return MOVE_NO_EFFECT; |
1635 | 1640 | ||
1636 | /* | 1641 | /* |
1637 | * Otherwise, we can make the move. All we need to specify is | 1642 | * Otherwise, we can make the move. All we need to specify is |
@@ -1685,6 +1690,7 @@ static game_state *execute_move(const game_state *state, const char *move) | |||
1685 | * This is a solve move, so we don't actually _change_ the | 1690 | * This is a solve move, so we don't actually _change_ the |
1686 | * grid but merely set up a stored solution path. | 1691 | * grid but merely set up a stored solution path. |
1687 | */ | 1692 | */ |
1693 | if (move[1] == '\0') return NULL; /* Solution must be non-empty. */ | ||
1688 | ret = dup_game(state); | 1694 | ret = dup_game(state); |
1689 | install_new_solution(ret, move); | 1695 | install_new_solution(ret, move); |
1690 | return ret; | 1696 | return ret; |
@@ -1729,11 +1735,10 @@ static game_state *execute_move(const game_state *state, const char *move) | |||
1729 | if (ret->soln) { | 1735 | if (ret->soln) { |
1730 | if (ret->dead || ret->gems == 0) | 1736 | if (ret->dead || ret->gems == 0) |
1731 | discard_solution(ret); | 1737 | discard_solution(ret); |
1732 | else if (ret->soln->list[ret->solnpos] == dir) { | 1738 | else if (ret->soln->list[ret->solnpos] == dir && |
1739 | ret->solnpos+1 < ret->soln->len) | ||
1733 | ++ret->solnpos; | 1740 | ++ret->solnpos; |
1734 | assert(ret->solnpos < ret->soln->len); /* or gems == 0 */ | 1741 | else { |
1735 | assert(!ret->dead); /* or not a solution */ | ||
1736 | } else { | ||
1737 | const char *error = NULL; | 1742 | const char *error = NULL; |
1738 | char *soln = solve_game(NULL, ret, NULL, &error); | 1743 | char *soln = solve_game(NULL, ret, NULL, &error); |
1739 | if (!error) { | 1744 | if (!error) { |
@@ -1751,7 +1756,7 @@ static game_state *execute_move(const game_state *state, const char *move) | |||
1751 | */ | 1756 | */ |
1752 | 1757 | ||
1753 | static void game_compute_size(const game_params *params, int tilesize, | 1758 | static void game_compute_size(const game_params *params, int tilesize, |
1754 | int *x, int *y) | 1759 | const game_ui *ui, int *x, int *y) |
1755 | { | 1760 | { |
1756 | /* Ick: fake up `ds->tilesize' for macro expansion purposes */ | 1761 | /* Ick: fake up `ds->tilesize' for macro expansion purposes */ |
1757 | struct { int tilesize; } ads, *ds = &ads; | 1762 | struct { int tilesize; } ads, *ds = &ads; |
@@ -1869,11 +1874,6 @@ static void draw_player(drawing *dr, game_drawstate *ds, int x, int y, | |||
1869 | coords[d*4+2] = x + TILESIZE/2 + (int)((TILESIZE*3/7) * x2); | 1874 | coords[d*4+2] = x + TILESIZE/2 + (int)((TILESIZE*3/7) * x2); |
1870 | coords[d*4+3] = y + TILESIZE/2 + (int)((TILESIZE*3/7) * y2); | 1875 | coords[d*4+3] = y + TILESIZE/2 + (int)((TILESIZE*3/7) * y2); |
1871 | } | 1876 | } |
1872 | /* rockbox hack */ | ||
1873 | int tmp[2] = { coords[0], coords[1] }; | ||
1874 | memmove(coords, coords + 2, sizeof(int) * DIRECTIONS * 4 - 2); | ||
1875 | memcpy(coords + DIRECTIONS * 4 - 2, tmp, 2 * sizeof(int)); | ||
1876 | |||
1877 | draw_polygon(dr, coords, DIRECTIONS*2, COL_DEAD_PLAYER, COL_OUTLINE); | 1877 | draw_polygon(dr, coords, DIRECTIONS*2, COL_DEAD_PLAYER, COL_OUTLINE); |
1878 | } else { | 1878 | } else { |
1879 | draw_circle(dr, x + TILESIZE/2, y + TILESIZE/2, | 1879 | draw_circle(dr, x + TILESIZE/2, y + TILESIZE/2, |
@@ -1889,6 +1889,8 @@ static void draw_player(drawing *dr, game_drawstate *ds, int x, int y, | |||
1889 | int coords[14], *c; | 1889 | int coords[14], *c; |
1890 | 1890 | ||
1891 | c = coords; | 1891 | c = coords; |
1892 | *c++ = ox + px/9; | ||
1893 | *c++ = oy + py/9; | ||
1892 | *c++ = ox + px/9 + ax*2/3; | 1894 | *c++ = ox + px/9 + ax*2/3; |
1893 | *c++ = oy + py/9 + ay*2/3; | 1895 | *c++ = oy + py/9 + ay*2/3; |
1894 | *c++ = ox + px/3 + ax*2/3; | 1896 | *c++ = ox + px/3 + ax*2/3; |
@@ -1901,8 +1903,6 @@ static void draw_player(drawing *dr, game_drawstate *ds, int x, int y, | |||
1901 | *c++ = oy - py/9 + ay*2/3; | 1903 | *c++ = oy - py/9 + ay*2/3; |
1902 | *c++ = ox - px/9; | 1904 | *c++ = ox - px/9; |
1903 | *c++ = oy - py/9; | 1905 | *c++ = oy - py/9; |
1904 | *c++ = ox + px/9; | ||
1905 | *c++ = oy + py/9; | ||
1906 | draw_polygon(dr, coords, 7, COL_HINT, COL_OUTLINE); | 1906 | draw_polygon(dr, coords, 7, COL_HINT, COL_OUTLINE); |
1907 | } | 1907 | } |
1908 | 1908 | ||
@@ -2013,15 +2013,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, | |||
2013 | * Initialise a fresh drawstate. | 2013 | * Initialise a fresh drawstate. |
2014 | */ | 2014 | */ |
2015 | if (!ds->started) { | 2015 | if (!ds->started) { |
2016 | int wid, ht; | ||
2017 | |||
2018 | /* | ||
2019 | * Blank out the window initially. | ||
2020 | */ | ||
2021 | game_compute_size(&ds->p, TILESIZE, &wid, &ht); | ||
2022 | draw_rect(dr, 0, 0, wid, ht, COL_BACKGROUND); | ||
2023 | draw_update(dr, 0, 0, wid, ht); | ||
2024 | |||
2025 | /* | 2016 | /* |
2026 | * Draw the grid lines. | 2017 | * Draw the grid lines. |
2027 | */ | 2018 | */ |
@@ -2207,19 +2198,6 @@ static int game_status(const game_state *state) | |||
2207 | return state->gems == 0 ? +1 : 0; | 2198 | return state->gems == 0 ? +1 : 0; |
2208 | } | 2199 | } |
2209 | 2200 | ||
2210 | static bool game_timing_state(const game_state *state, game_ui *ui) | ||
2211 | { | ||
2212 | return true; | ||
2213 | } | ||
2214 | |||
2215 | static void game_print_size(const game_params *params, float *x, float *y) | ||
2216 | { | ||
2217 | } | ||
2218 | |||
2219 | static void game_print(drawing *dr, const game_state *state, int tilesize) | ||
2220 | { | ||
2221 | } | ||
2222 | |||
2223 | #ifdef COMBINED | 2201 | #ifdef COMBINED |
2224 | #define thegame inertia | 2202 | #define thegame inertia |
2225 | #endif | 2203 | #endif |
@@ -2241,12 +2219,14 @@ const struct game thegame = { | |||
2241 | free_game, | 2219 | free_game, |
2242 | true, solve_game, | 2220 | true, solve_game, |
2243 | true, game_can_format_as_text_now, game_text_format, | 2221 | true, game_can_format_as_text_now, game_text_format, |
2222 | NULL, NULL, /* get_prefs, set_prefs */ | ||
2244 | new_ui, | 2223 | new_ui, |
2245 | free_ui, | 2224 | free_ui, |
2246 | encode_ui, | 2225 | encode_ui, |
2247 | decode_ui, | 2226 | decode_ui, |
2248 | NULL, /* game_request_keys */ | 2227 | NULL, /* game_request_keys */ |
2249 | game_changed_state, | 2228 | game_changed_state, |
2229 | current_key_label, | ||
2250 | interpret_move, | 2230 | interpret_move, |
2251 | execute_move, | 2231 | execute_move, |
2252 | PREFERRED_TILESIZE, game_compute_size, game_set_size, | 2232 | PREFERRED_TILESIZE, game_compute_size, game_set_size, |
@@ -2258,8 +2238,8 @@ const struct game thegame = { | |||
2258 | game_flash_length, | 2238 | game_flash_length, |
2259 | game_get_cursor_location, | 2239 | game_get_cursor_location, |
2260 | game_status, | 2240 | game_status, |
2261 | false, false, game_print_size, game_print, | 2241 | false, false, NULL, NULL, /* print_size, print */ |
2262 | true, /* wants_statusbar */ | 2242 | true, /* wants_statusbar */ |
2263 | false, game_timing_state, | 2243 | false, NULL, /* timing_state */ |
2264 | 0, /* flags */ | 2244 | 0, /* flags */ |
2265 | }; | 2245 | }; |