summaryrefslogtreecommitdiff
path: root/apps/plugins/puzzles/src/inertia.c
diff options
context:
space:
mode:
authorFranklin Wei <franklin@rockbox.org>2024-07-22 21:43:25 -0400
committerFranklin Wei <franklin@rockbox.org>2024-07-22 21:44:08 -0400
commit09aa8de52cb962f1ceebfb1fd44f2c54a924fc5c (patch)
tree182bd4efb2dc8ca4fcb369d8cccab0c0f290d054 /apps/plugins/puzzles/src/inertia.c
parentc72030f98c953a82ed6f5c7132ad000c3d5f4a16 (diff)
downloadrockbox-09aa8de52cb962f1ceebfb1fd44f2c54a924fc5c.tar.gz
rockbox-09aa8de52cb962f1ceebfb1fd44f2c54a924fc5c.zip
puzzles: resync with upstream
This brings the puzzles source in sync with Simon's branch, commit fd304c5 (from March 2024), with some added Rockbox-specific compatibility changes: https://www.franklinwei.com/git/puzzles/commit/?h=rockbox-devel&id=516830d9d76bdfe64fe5ccf2a9b59c33f5c7c078 There are quite a lot of backend changes, including a new "Mosaic" puzzle. In addition, some new frontend changes were necessary: - New "Preferences" menu to access the user preferences system. - Enabled spacebar input for several games. Change-Id: I94c7df674089c92f32d5f07025f6a1059068af1e
Diffstat (limited to 'apps/plugins/puzzles/src/inertia.c')
-rw-r--r--apps/plugins/puzzles/src/inertia.c76
1 files changed, 34 insertions, 42 deletions
diff --git a/apps/plugins/puzzles/src/inertia.c b/apps/plugins/puzzles/src/inertia.c
index 726c89c7dd..d120411f55 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
@@ -1520,7 +1527,8 @@ static char *encode_ui(const game_ui *ui)
1520 return dupstr(buf); 1527 return dupstr(buf);
1521} 1528}
1522 1529
1523static void decode_ui(game_ui *ui, const char *encoding) 1530static void decode_ui(game_ui *ui, const char *encoding,
1531 const game_state *state)
1524{ 1532{
1525 int p = 0; 1533 int p = 0;
1526 sscanf(encoding, "D%d%n", &ui->deaths, &p); 1534 sscanf(encoding, "D%d%n", &ui->deaths, &p);
@@ -1545,6 +1553,15 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate,
1545 ui->just_made_move = false; 1553 ui->just_made_move = false;
1546} 1554}
1547 1555
1556static const char *current_key_label(const game_ui *ui,
1557 const game_state *state, int button)
1558{
1559 if (IS_CURSOR_SELECT(button) &&
1560 state->soln && state->solnpos < state->soln->len)
1561 return "Advance";
1562 return "";
1563}
1564
1548struct game_drawstate { 1565struct game_drawstate {
1549 game_params p; 1566 game_params p;
1550 int tilesize; 1567 int tilesize;
@@ -1593,7 +1610,7 @@ static char *interpret_move(const game_state *state, game_ui *ui,
1593 * end up the right way round. */ 1610 * end up the right way round. */
1594 angle = atan2(dx, -dy); 1611 angle = atan2(dx, -dy);
1595 1612
1596 angle = (angle + (PI/8)) / (PI/4); 1613 angle = (angle + (float)(PI/8)) / (float)(PI/4);
1597 assert(angle > -16.0F); 1614 assert(angle > -16.0F);
1598 dir = (int)(angle + 16.0F) & 7; 1615 dir = (int)(angle + 16.0F) & 7;
1599 } 1616 }
@@ -1618,20 +1635,20 @@ static char *interpret_move(const game_state *state, game_ui *ui,
1618 dir = state->soln->list[state->solnpos]; 1635 dir = state->soln->list[state->solnpos];
1619 1636
1620 if (dir < 0) 1637 if (dir < 0)
1621 return NULL; 1638 return MOVE_UNUSED;
1622 1639
1623 /* 1640 /*
1624 * Reject the move if we can't make it at all due to a wall 1641 * Reject the move if we can't make it at all due to a wall
1625 * being in the way. 1642 * being in the way.
1626 */ 1643 */
1627 if (AT(w, h, state->grid, state->px+DX(dir), state->py+DY(dir)) == WALL) 1644 if (AT(w, h, state->grid, state->px+DX(dir), state->py+DY(dir)) == WALL)
1628 return NULL; 1645 return MOVE_NO_EFFECT;
1629 1646
1630 /* 1647 /*
1631 * Reject the move if we're dead! 1648 * Reject the move if we're dead!
1632 */ 1649 */
1633 if (state->dead) 1650 if (state->dead)
1634 return NULL; 1651 return MOVE_NO_EFFECT;
1635 1652
1636 /* 1653 /*
1637 * Otherwise, we can make the move. All we need to specify is 1654 * Otherwise, we can make the move. All we need to specify is
@@ -1685,6 +1702,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 1702 * This is a solve move, so we don't actually _change_ the
1686 * grid but merely set up a stored solution path. 1703 * grid but merely set up a stored solution path.
1687 */ 1704 */
1705 if (move[1] == '\0') return NULL; /* Solution must be non-empty. */
1688 ret = dup_game(state); 1706 ret = dup_game(state);
1689 install_new_solution(ret, move); 1707 install_new_solution(ret, move);
1690 return ret; 1708 return ret;
@@ -1729,11 +1747,10 @@ static game_state *execute_move(const game_state *state, const char *move)
1729 if (ret->soln) { 1747 if (ret->soln) {
1730 if (ret->dead || ret->gems == 0) 1748 if (ret->dead || ret->gems == 0)
1731 discard_solution(ret); 1749 discard_solution(ret);
1732 else if (ret->soln->list[ret->solnpos] == dir) { 1750 else if (ret->soln->list[ret->solnpos] == dir &&
1751 ret->solnpos+1 < ret->soln->len)
1733 ++ret->solnpos; 1752 ++ret->solnpos;
1734 assert(ret->solnpos < ret->soln->len); /* or gems == 0 */ 1753 else {
1735 assert(!ret->dead); /* or not a solution */
1736 } else {
1737 const char *error = NULL; 1754 const char *error = NULL;
1738 char *soln = solve_game(NULL, ret, NULL, &error); 1755 char *soln = solve_game(NULL, ret, NULL, &error);
1739 if (!error) { 1756 if (!error) {
@@ -1751,7 +1768,7 @@ static game_state *execute_move(const game_state *state, const char *move)
1751 */ 1768 */
1752 1769
1753static void game_compute_size(const game_params *params, int tilesize, 1770static void game_compute_size(const game_params *params, int tilesize,
1754 int *x, int *y) 1771 const game_ui *ui, int *x, int *y)
1755{ 1772{
1756 /* Ick: fake up `ds->tilesize' for macro expansion purposes */ 1773 /* Ick: fake up `ds->tilesize' for macro expansion purposes */
1757 struct { int tilesize; } ads, *ds = &ads; 1774 struct { int tilesize; } ads, *ds = &ads;
@@ -1869,11 +1886,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); 1886 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); 1887 coords[d*4+3] = y + TILESIZE/2 + (int)((TILESIZE*3/7) * y2);
1871 } 1888 }
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); 1889 draw_polygon(dr, coords, DIRECTIONS*2, COL_DEAD_PLAYER, COL_OUTLINE);
1878 } else { 1890 } else {
1879 draw_circle(dr, x + TILESIZE/2, y + TILESIZE/2, 1891 draw_circle(dr, x + TILESIZE/2, y + TILESIZE/2,
@@ -1889,6 +1901,8 @@ static void draw_player(drawing *dr, game_drawstate *ds, int x, int y,
1889 int coords[14], *c; 1901 int coords[14], *c;
1890 1902
1891 c = coords; 1903 c = coords;
1904 *c++ = ox + px/9;
1905 *c++ = oy + py/9;
1892 *c++ = ox + px/9 + ax*2/3; 1906 *c++ = ox + px/9 + ax*2/3;
1893 *c++ = oy + py/9 + ay*2/3; 1907 *c++ = oy + py/9 + ay*2/3;
1894 *c++ = ox + px/3 + ax*2/3; 1908 *c++ = ox + px/3 + ax*2/3;
@@ -1901,8 +1915,6 @@ static void draw_player(drawing *dr, game_drawstate *ds, int x, int y,
1901 *c++ = oy - py/9 + ay*2/3; 1915 *c++ = oy - py/9 + ay*2/3;
1902 *c++ = ox - px/9; 1916 *c++ = ox - px/9;
1903 *c++ = oy - py/9; 1917 *c++ = oy - py/9;
1904 *c++ = ox + px/9;
1905 *c++ = oy + py/9;
1906 draw_polygon(dr, coords, 7, COL_HINT, COL_OUTLINE); 1918 draw_polygon(dr, coords, 7, COL_HINT, COL_OUTLINE);
1907 } 1919 }
1908 1920
@@ -2013,15 +2025,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds,
2013 * Initialise a fresh drawstate. 2025 * Initialise a fresh drawstate.
2014 */ 2026 */
2015 if (!ds->started) { 2027 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 /* 2028 /*
2026 * Draw the grid lines. 2029 * Draw the grid lines.
2027 */ 2030 */
@@ -2207,19 +2210,6 @@ static int game_status(const game_state *state)
2207 return state->gems == 0 ? +1 : 0; 2210 return state->gems == 0 ? +1 : 0;
2208} 2211}
2209 2212
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 2213#ifdef COMBINED
2224#define thegame inertia 2214#define thegame inertia
2225#endif 2215#endif
@@ -2241,12 +2231,14 @@ const struct game thegame = {
2241 free_game, 2231 free_game,
2242 true, solve_game, 2232 true, solve_game,
2243 true, game_can_format_as_text_now, game_text_format, 2233 true, game_can_format_as_text_now, game_text_format,
2234 NULL, NULL, /* get_prefs, set_prefs */
2244 new_ui, 2235 new_ui,
2245 free_ui, 2236 free_ui,
2246 encode_ui, 2237 encode_ui,
2247 decode_ui, 2238 decode_ui,
2248 NULL, /* game_request_keys */ 2239 NULL, /* game_request_keys */
2249 game_changed_state, 2240 game_changed_state,
2241 current_key_label,
2250 interpret_move, 2242 interpret_move,
2251 execute_move, 2243 execute_move,
2252 PREFERRED_TILESIZE, game_compute_size, game_set_size, 2244 PREFERRED_TILESIZE, game_compute_size, game_set_size,
@@ -2258,8 +2250,8 @@ const struct game thegame = {
2258 game_flash_length, 2250 game_flash_length,
2259 game_get_cursor_location, 2251 game_get_cursor_location,
2260 game_status, 2252 game_status,
2261 false, false, game_print_size, game_print, 2253 false, false, NULL, NULL, /* print_size, print */
2262 true, /* wants_statusbar */ 2254 true, /* wants_statusbar */
2263 false, game_timing_state, 2255 false, NULL, /* timing_state */
2264 0, /* flags */ 2256 0, /* flags */
2265}; 2257};