summaryrefslogtreecommitdiff
path: root/apps/plugins/puzzles/src/inertia.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/puzzles/src/inertia.c')
-rw-r--r--apps/plugins/puzzles/src/inertia.c88
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
718static 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
730static char *solve_game(const game_state *state, const game_state *currstate, 725static 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
1523static void decode_ui(game_ui *ui, const char *encoding) 1518static 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
1544static 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
1548struct game_drawstate { 1553struct 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
1753static void game_compute_size(const game_params *params, int tilesize, 1758static 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
2210static bool game_timing_state(const game_state *state, game_ui *ui)
2211{
2212 return true;
2213}
2214
2215static void game_print_size(const game_params *params, float *x, float *y)
2216{
2217}
2218
2219static 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};