summaryrefslogtreecommitdiff
path: root/apps/plugins/puzzles/src/signpost.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/puzzles/src/signpost.c')
-rw-r--r--apps/plugins/puzzles/src/signpost.c185
1 files changed, 115 insertions, 70 deletions
diff --git a/apps/plugins/puzzles/src/signpost.c b/apps/plugins/puzzles/src/signpost.c
index 9aee255ebe..9aed67bb4a 100644
--- a/apps/plugins/puzzles/src/signpost.c
+++ b/apps/plugins/puzzles/src/signpost.c
@@ -7,7 +7,12 @@
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#include <limits.h>
11#ifdef NO_TGMATH_H
12# include <math.h>
13#else
14# include <tgmath.h>
15#endif
11 16
12#include "puzzles.h" 17#include "puzzles.h"
13 18
@@ -57,7 +62,7 @@ struct game_state {
57 int *nums; /* numbers, size n */ 62 int *nums; /* numbers, size n */
58 unsigned int *flags; /* flags, size n */ 63 unsigned int *flags; /* flags, size n */
59 int *next, *prev; /* links to other cell indexes, size n (-1 absent) */ 64 int *next, *prev; /* links to other cell indexes, size n (-1 absent) */
60 int *dsf; /* connects regions with a dsf. */ 65 DSF *dsf; /* connects regions with a dsf. */
61 int *numsi; /* for each number, which index is it in? (-1 absent) */ 66 int *numsi; /* for each number, which index is it in? (-1 absent) */
62}; 67};
63 68
@@ -168,7 +173,7 @@ static bool isvalidmove(const game_state *state, bool clever,
168 173
169 /* can't create a new connection between cells in the same region 174 /* can't create a new connection between cells in the same region
170 * as that would create a loop. */ 175 * as that would create a loop. */
171 if (dsf_canonify(state->dsf, from) == dsf_canonify(state->dsf, to)) 176 if (dsf_equivalent(state->dsf, from, to))
172 return false; 177 return false;
173 178
174 /* if both cells are actual numbers, can't drag if we're not 179 /* if both cells are actual numbers, can't drag if we're not
@@ -277,7 +282,7 @@ static void strip_nums(game_state *state) {
277 memset(state->next, -1, state->n*sizeof(int)); 282 memset(state->next, -1, state->n*sizeof(int));
278 memset(state->prev, -1, state->n*sizeof(int)); 283 memset(state->prev, -1, state->n*sizeof(int));
279 memset(state->numsi, -1, (state->n+1)*sizeof(int)); 284 memset(state->numsi, -1, (state->n+1)*sizeof(int));
280 dsf_init(state->dsf, state->n); 285 dsf_reinit(state->dsf);
281} 286}
282 287
283static bool check_nums(game_state *orig, game_state *copy, bool only_immutable) 288static bool check_nums(game_state *orig, game_state *copy, bool only_immutable)
@@ -421,6 +426,8 @@ static const char *validate_params(const game_params *params, bool full)
421{ 426{
422 if (params->w < 1) return "Width must be at least one"; 427 if (params->w < 1) return "Width must be at least one";
423 if (params->h < 1) return "Height must be at least one"; 428 if (params->h < 1) return "Height must be at least one";
429 if (params->w > INT_MAX / params->h)
430 return "Width times height must not be unreasonably large";
424 if (full && params->w == 1 && params->h == 1) 431 if (full && params->w == 1 && params->h == 1)
425 /* The UI doesn't let us move these from unsolved to solved, 432 /* The UI doesn't let us move these from unsolved to solved,
426 * so we disallow generating (but not playing) them. */ 433 * so we disallow generating (but not playing) them. */
@@ -454,7 +461,7 @@ static game_state *blank_game(int w, int h)
454 state->flags = snewn(state->n, unsigned int); 461 state->flags = snewn(state->n, unsigned int);
455 state->next = snewn(state->n, int); 462 state->next = snewn(state->n, int);
456 state->prev = snewn(state->n, int); 463 state->prev = snewn(state->n, int);
457 state->dsf = snew_dsf(state->n); 464 state->dsf = dsf_new(state->n);
458 state->numsi = snewn(state->n+1, int); 465 state->numsi = snewn(state->n+1, int);
459 466
460 blank_game_into(state); 467 blank_game_into(state);
@@ -475,7 +482,7 @@ static void dup_game_to(game_state *to, const game_state *from)
475 memcpy(to->next, from->next, to->n*sizeof(int)); 482 memcpy(to->next, from->next, to->n*sizeof(int));
476 memcpy(to->prev, from->prev, to->n*sizeof(int)); 483 memcpy(to->prev, from->prev, to->n*sizeof(int));
477 484
478 memcpy(to->dsf, from->dsf, to->n*sizeof(int)); 485 dsf_copy(to->dsf, from->dsf);
479 memcpy(to->numsi, from->numsi, (to->n+1)*sizeof(int)); 486 memcpy(to->numsi, from->numsi, (to->n+1)*sizeof(int));
480} 487}
481 488
@@ -493,7 +500,7 @@ static void free_game(game_state *state)
493 sfree(state->flags); 500 sfree(state->flags);
494 sfree(state->next); 501 sfree(state->next);
495 sfree(state->prev); 502 sfree(state->prev);
496 sfree(state->dsf); 503 dsf_free(state->dsf);
497 sfree(state->numsi); 504 sfree(state->numsi);
498 sfree(state); 505 sfree(state);
499} 506}
@@ -1011,7 +1018,7 @@ static void connect_numbers(game_state *state)
1011{ 1018{
1012 int i, di, dni; 1019 int i, di, dni;
1013 1020
1014 dsf_init(state->dsf, state->n); 1021 dsf_reinit(state->dsf);
1015 for (i = 0; i < state->n; i++) { 1022 for (i = 0; i < state->n; i++) {
1016 if (state->next[i] != -1) { 1023 if (state->next[i] != -1) {
1017 assert(state->prev[state->next[i]] == i); 1024 assert(state->prev[state->next[i]] == i);
@@ -1028,8 +1035,8 @@ static void connect_numbers(game_state *state)
1028 1035
1029static int compare_heads(const void *a, const void *b) 1036static int compare_heads(const void *a, const void *b)
1030{ 1037{
1031 struct head_meta *ha = (struct head_meta *)a; 1038 const struct head_meta *ha = (const struct head_meta *)a;
1032 struct head_meta *hb = (struct head_meta *)b; 1039 const struct head_meta *hb = (const struct head_meta *)b;
1033 1040
1034 /* Heads with preferred colours first... */ 1041 /* Heads with preferred colours first... */
1035 if (ha->preference && !hb->preference) return -1; 1042 if (ha->preference && !hb->preference) return -1;
@@ -1380,8 +1387,32 @@ struct game_ui {
1380 bool dragging, drag_is_from; 1387 bool dragging, drag_is_from;
1381 int sx, sy; /* grid coords of start cell */ 1388 int sx, sy; /* grid coords of start cell */
1382 int dx, dy; /* pixel coords of drag posn */ 1389 int dx, dy; /* pixel coords of drag posn */
1390
1391 /*
1392 * Trivial and foolish configurable option done on purest whim.
1393 * With this option enabled, the victory flash is done by rotating
1394 * each square in the opposite direction from its immediate
1395 * neighbours, so that they behave like a field of interlocking
1396 * gears. With it disabled, they all rotate in the same direction.
1397 * Choose for yourself which is more brain-twisting :-)
1398 */
1399 bool gear_mode;
1383}; 1400};
1384 1401
1402static void legacy_prefs_override(struct game_ui *ui_out)
1403{
1404 static bool initialised = false;
1405 static int gear_mode = -1;
1406
1407 if (!initialised) {
1408 initialised = true;
1409 gear_mode = getenv_bool("SIGNPOST_GEARS", -1);
1410 }
1411
1412 if (gear_mode != -1)
1413 ui_out->gear_mode = gear_mode;
1414}
1415
1385static game_ui *new_ui(const game_state *state) 1416static game_ui *new_ui(const game_state *state)
1386{ 1417{
1387 game_ui *ui = snew(game_ui); 1418 game_ui *ui = snew(game_ui);
@@ -1390,11 +1421,14 @@ static game_ui *new_ui(const game_state *state)
1390 * copy to clone, there's code that needs fixing in game_redraw too. */ 1421 * copy to clone, there's code that needs fixing in game_redraw too. */
1391 1422
1392 ui->cx = ui->cy = 0; 1423 ui->cx = ui->cy = 0;
1393 ui->cshow = false; 1424 ui->cshow = getenv_bool("PUZZLES_SHOW_CURSOR", false);
1394 1425
1395 ui->dragging = false; 1426 ui->dragging = false;
1396 ui->sx = ui->sy = ui->dx = ui->dy = 0; 1427 ui->sx = ui->sy = ui->dx = ui->dy = 0;
1397 1428
1429 ui->gear_mode = false;
1430 legacy_prefs_override(ui);
1431
1398 return ui; 1432 return ui;
1399} 1433}
1400 1434
@@ -1403,13 +1437,28 @@ static void free_ui(game_ui *ui)
1403 sfree(ui); 1437 sfree(ui);
1404} 1438}
1405 1439
1406static char *encode_ui(const game_ui *ui) 1440static config_item *get_prefs(game_ui *ui)
1407{ 1441{
1408 return NULL; 1442 config_item *ret;
1443
1444 ret = snewn(2, config_item);
1445
1446 ret[0].name = "Victory rotation effect";
1447 ret[0].kw = "flash-type";
1448 ret[0].type = C_CHOICES;
1449 ret[0].u.choices.choicenames = ":Unidirectional:Meshing gears";
1450 ret[0].u.choices.choicekws = ":unidirectional:gears";
1451 ret[0].u.choices.selected = ui->gear_mode;
1452
1453 ret[1].name = NULL;
1454 ret[1].type = C_END;
1455
1456 return ret;
1409} 1457}
1410 1458
1411static void decode_ui(game_ui *ui, const char *encoding) 1459static void set_prefs(game_ui *ui, const config_item *cfg)
1412{ 1460{
1461 ui->gear_mode = cfg[0].u.choices.selected;
1413} 1462}
1414 1463
1415static void game_changed_state(game_ui *ui, const game_state *oldstate, 1464static void game_changed_state(game_ui *ui, const game_state *oldstate,
@@ -1421,6 +1470,26 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate,
1421 } 1470 }
1422} 1471}
1423 1472
1473static const char *current_key_label(const game_ui *ui,
1474 const game_state *state, int button)
1475{
1476 if (IS_CURSOR_SELECT(button) && ui->cshow) {
1477 if (ui->dragging) {
1478 if (ui->drag_is_from) {
1479 if (isvalidmove(state, false, ui->sx, ui->sy, ui->cx, ui->cy))
1480 return "To here";
1481 } else {
1482 if (isvalidmove(state, false, ui->cx, ui->cy, ui->sx, ui->sy))
1483 return "From here";
1484 }
1485 return "Cancel";
1486 } else {
1487 return button == CURSOR_SELECT ? "From here" : "To here";
1488 }
1489 }
1490 return "";
1491}
1492
1424struct game_drawstate { 1493struct game_drawstate {
1425 int tilesize; 1494 int tilesize;
1426 bool started, solved; 1495 bool started, solved;
@@ -1442,26 +1511,27 @@ static char *interpret_move(const game_state *state, game_ui *ui,
1442 char buf[80]; 1511 char buf[80];
1443 1512
1444 if (IS_CURSOR_MOVE(button)) { 1513 if (IS_CURSOR_MOVE(button)) {
1445 move_cursor(button, &ui->cx, &ui->cy, state->w, state->h, false); 1514 char *ret;
1446 ui->cshow = true; 1515 ret = move_cursor(button, &ui->cx, &ui->cy, state->w, state->h, false,
1516 &ui->cshow);
1447 if (ui->dragging) { 1517 if (ui->dragging) {
1448 ui->dx = COORD(ui->cx) + TILE_SIZE/2; 1518 ui->dx = COORD(ui->cx) + TILE_SIZE/2;
1449 ui->dy = COORD(ui->cy) + TILE_SIZE/2; 1519 ui->dy = COORD(ui->cy) + TILE_SIZE/2;
1450 } 1520 }
1451 return UI_UPDATE; 1521 return ret;
1452 } else if (IS_CURSOR_SELECT(button)) { 1522 } else if (IS_CURSOR_SELECT(button)) {
1453 if (!ui->cshow) 1523 if (!ui->cshow)
1454 ui->cshow = true; 1524 ui->cshow = true;
1455 else if (ui->dragging) { 1525 else if (ui->dragging) {
1456 ui->dragging = false; 1526 ui->dragging = false;
1457 if (ui->sx == ui->cx && ui->sy == ui->cy) return UI_UPDATE; 1527 if (ui->sx == ui->cx && ui->sy == ui->cy) return MOVE_UI_UPDATE;
1458 if (ui->drag_is_from) { 1528 if (ui->drag_is_from) {
1459 if (!isvalidmove(state, false, ui->sx, ui->sy, ui->cx, ui->cy)) 1529 if (!isvalidmove(state, false, ui->sx, ui->sy, ui->cx, ui->cy))
1460 return UI_UPDATE; 1530 return MOVE_UI_UPDATE;
1461 sprintf(buf, "L%d,%d-%d,%d", ui->sx, ui->sy, ui->cx, ui->cy); 1531 sprintf(buf, "L%d,%d-%d,%d", ui->sx, ui->sy, ui->cx, ui->cy);
1462 } else { 1532 } else {
1463 if (!isvalidmove(state, false, ui->cx, ui->cy, ui->sx, ui->sy)) 1533 if (!isvalidmove(state, false, ui->cx, ui->cy, ui->sx, ui->sy))
1464 return UI_UPDATE; 1534 return MOVE_UI_UPDATE;
1465 sprintf(buf, "L%d,%d-%d,%d", ui->cx, ui->cy, ui->sx, ui->sy); 1535 sprintf(buf, "L%d,%d-%d,%d", ui->cx, ui->cy, ui->sx, ui->sy);
1466 } 1536 }
1467 return dupstr(buf); 1537 return dupstr(buf);
@@ -1473,7 +1543,7 @@ static char *interpret_move(const game_state *state, game_ui *ui,
1473 ui->dy = COORD(ui->cy) + TILE_SIZE/2; 1543 ui->dy = COORD(ui->cy) + TILE_SIZE/2;
1474 ui->drag_is_from = (button == CURSOR_SELECT); 1544 ui->drag_is_from = (button == CURSOR_SELECT);
1475 } 1545 }
1476 return UI_UPDATE; 1546 return MOVE_UI_UPDATE;
1477 } 1547 }
1478 if (IS_MOUSE_DOWN(button)) { 1548 if (IS_MOUSE_DOWN(button)) {
1479 if (ui->cshow) { 1549 if (ui->cshow) {
@@ -1502,19 +1572,19 @@ static char *interpret_move(const game_state *state, game_ui *ui,
1502 ui->dx = mx; 1572 ui->dx = mx;
1503 ui->dy = my; 1573 ui->dy = my;
1504 ui->cshow = false; 1574 ui->cshow = false;
1505 return UI_UPDATE; 1575 return MOVE_UI_UPDATE;
1506 } else if (IS_MOUSE_DRAG(button) && ui->dragging) { 1576 } else if (IS_MOUSE_DRAG(button) && ui->dragging) {
1507 ui->dx = mx; 1577 ui->dx = mx;
1508 ui->dy = my; 1578 ui->dy = my;
1509 return UI_UPDATE; 1579 return MOVE_UI_UPDATE;
1510 } else if (IS_MOUSE_RELEASE(button) && ui->dragging) { 1580 } else if (IS_MOUSE_RELEASE(button) && ui->dragging) {
1511 ui->dragging = false; 1581 ui->dragging = false;
1512 if (ui->sx == x && ui->sy == y) return UI_UPDATE; /* single click */ 1582 if (ui->sx == x && ui->sy == y) return MOVE_UI_UPDATE; /* single click */
1513 1583
1514 if (!INGRID(state, x, y)) { 1584 if (!INGRID(state, x, y)) {
1515 int si = ui->sy*w+ui->sx; 1585 int si = ui->sy*w+ui->sx;
1516 if (state->prev[si] == -1 && state->next[si] == -1) 1586 if (state->prev[si] == -1 && state->next[si] == -1)
1517 return UI_UPDATE; 1587 return MOVE_UI_UPDATE;
1518 sprintf(buf, "%c%d,%d", 1588 sprintf(buf, "%c%d,%d",
1519 (int)(ui->drag_is_from ? 'C' : 'X'), ui->sx, ui->sy); 1589 (int)(ui->drag_is_from ? 'C' : 'X'), ui->sx, ui->sy);
1520 return dupstr(buf); 1590 return dupstr(buf);
@@ -1522,11 +1592,11 @@ static char *interpret_move(const game_state *state, game_ui *ui,
1522 1592
1523 if (ui->drag_is_from) { 1593 if (ui->drag_is_from) {
1524 if (!isvalidmove(state, false, ui->sx, ui->sy, x, y)) 1594 if (!isvalidmove(state, false, ui->sx, ui->sy, x, y))
1525 return UI_UPDATE; 1595 return MOVE_UI_UPDATE;
1526 sprintf(buf, "L%d,%d-%d,%d", ui->sx, ui->sy, x, y); 1596 sprintf(buf, "L%d,%d-%d,%d", ui->sx, ui->sy, x, y);
1527 } else { 1597 } else {
1528 if (!isvalidmove(state, false, x, y, ui->sx, ui->sy)) 1598 if (!isvalidmove(state, false, x, y, ui->sx, ui->sy))
1529 return UI_UPDATE; 1599 return MOVE_UI_UPDATE;
1530 sprintf(buf, "L%d,%d-%d,%d", x, y, ui->sx, ui->sy); 1600 sprintf(buf, "L%d,%d-%d,%d", x, y, ui->sx, ui->sy);
1531 } 1601 }
1532 return dupstr(buf); 1602 return dupstr(buf);
@@ -1535,7 +1605,7 @@ static char *interpret_move(const game_state *state, game_ui *ui,
1535 else if ((button == 'x' || button == 'X') && ui->cshow) { 1605 else if ((button == 'x' || button == 'X') && ui->cshow) {
1536 int si = ui->cy*w + ui->cx; 1606 int si = ui->cy*w + ui->cx;
1537 if (state->prev[si] == -1 && state->next[si] == -1) 1607 if (state->prev[si] == -1 && state->next[si] == -1)
1538 return UI_UPDATE; 1608 return MOVE_UI_UPDATE;
1539 sprintf(buf, "%c%d,%d", 1609 sprintf(buf, "%c%d,%d",
1540 (int)((button == 'x') ? 'C' : 'X'), ui->cx, ui->cy); 1610 (int)((button == 'x') ? 'C' : 'X'), ui->cx, ui->cy);
1541 return dupstr(buf); 1611 return dupstr(buf);
@@ -1641,7 +1711,7 @@ static game_state *execute_move(const game_state *state, const char *move)
1641 */ 1711 */
1642 1712
1643static void game_compute_size(const game_params *params, int tilesize, 1713static void game_compute_size(const game_params *params, int tilesize,
1644 int *x, int *y) 1714 const game_ui *ui, int *x, int *y)
1645{ 1715{
1646 /* Ick: fake up `ds->tilesize' for macro expansion purposes */ 1716 /* Ick: fake up `ds->tilesize' for macro expansion purposes */
1647 struct { int tilesize, order; } ads, *ds = &ads; 1717 struct { int tilesize, order; } ads, *ds = &ads;
@@ -1825,9 +1895,8 @@ static void draw_star(drawing *dr, int cx, int cy, int rad, int npoints,
1825 coords = snewn(npoints * 2 * 2, int); 1895 coords = snewn(npoints * 2 * 2, int);
1826 1896
1827 for (n = 0; n < npoints * 2; n++) { 1897 for (n = 0; n < npoints * 2; n++) {
1828 /* hack to accomodate rockbox's concave polygon drawing */ 1898 a = 2.0 * PI * ((double)n / ((double)npoints * 2.0)) + angle_offset;
1829 a = 2.0 * PI * ((double)n / ((double)npoints * 2.0)) + angle_offset - PI / npoints; 1899 r = (n % 2) ? (double)rad/2.0 : (double)rad;
1830 r = (n % 2 == 0) ? (double)rad/2.0 : (double)rad;
1831 1900
1832 /* We're rotating the point at (0, -r) by a degrees */ 1901 /* We're rotating the point at (0, -r) by a degrees */
1833 coords[2*n+0] = cx + (int)( r * sin(a)); 1902 coords[2*n+0] = cx + (int)( r * sin(a));
@@ -2082,7 +2151,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds,
2082 if (!ds->started) { 2151 if (!ds->started) {
2083 int aw = TILE_SIZE * state->w; 2152 int aw = TILE_SIZE * state->w;
2084 int ah = TILE_SIZE * state->h; 2153 int ah = TILE_SIZE * state->h;
2085 draw_rect(dr, 0, 0, aw + 2 * BORDER, ah + 2 * BORDER, COL_BACKGROUND);
2086 draw_rect_outline(dr, BORDER - 1, BORDER - 1, aw + 2, ah + 2, COL_GRID); 2154 draw_rect_outline(dr, BORDER - 1, BORDER - 1, aw + 2, ah + 2, COL_GRID);
2087 draw_update(dr, 0, 0, aw + 2 * BORDER, ah + 2 * BORDER); 2155 draw_update(dr, 0, 0, aw + 2 * BORDER, ah + 2 * BORDER);
2088 } 2156 }
@@ -2127,28 +2195,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds,
2127 if (state->nums[i] != ds->nums[i] || 2195 if (state->nums[i] != ds->nums[i] ||
2128 f != ds->f[i] || dirp != ds->dirp[i] || 2196 f != ds->f[i] || dirp != ds->dirp[i] ||
2129 force || !ds->started) { 2197 force || !ds->started) {
2130 int sign; 2198 int sign = (ui->gear_mode ? 1 - 2 * ((x ^ y) & 1) : 1);
2131 {
2132 /*
2133 * Trivial and foolish configurable option done on
2134 * purest whim. With this option enabled, the
2135 * victory flash is done by rotating each square
2136 * in the opposite direction from its immediate
2137 * neighbours, so that they behave like a field of
2138 * interlocking gears. With it disabled, they all
2139 * rotate in the same direction. Choose for
2140 * yourself which is more brain-twisting :-)
2141 */
2142 static int gear_mode = -1;
2143 if (gear_mode < 0) {
2144 char *env = getenv("SIGNPOST_GEARS");
2145 gear_mode = (env && (env[0] == 'y' || env[0] == 'Y'));
2146 }
2147 if (gear_mode)
2148 sign = 1 - 2 * ((x ^ y) & 1);
2149 else
2150 sign = 1;
2151 }
2152 tile_redraw(dr, ds, 2199 tile_redraw(dr, ds,
2153 BORDER + x * TILE_SIZE, 2200 BORDER + x * TILE_SIZE,
2154 BORDER + y * TILE_SIZE, 2201 BORDER + y * TILE_SIZE,
@@ -2206,21 +2253,18 @@ static int game_status(const game_state *state)
2206 return state->completed ? +1 : 0; 2253 return state->completed ? +1 : 0;
2207} 2254}
2208 2255
2209static bool game_timing_state(const game_state *state, game_ui *ui) 2256static void game_print_size(const game_params *params, const game_ui *ui,
2210{ 2257 float *x, float *y)
2211 return true;
2212}
2213
2214static void game_print_size(const game_params *params, float *x, float *y)
2215{ 2258{
2216 int pw, ph; 2259 int pw, ph;
2217 2260
2218 game_compute_size(params, 1300, &pw, &ph); 2261 game_compute_size(params, 1300, ui, &pw, &ph);
2219 *x = pw / 100.0F; 2262 *x = pw / 100.0F;
2220 *y = ph / 100.0F; 2263 *y = ph / 100.0F;
2221} 2264}
2222 2265
2223static void game_print(drawing *dr, const game_state *state, int tilesize) 2266static void game_print(drawing *dr, const game_state *state, const game_ui *ui,
2267 int tilesize)
2224{ 2268{
2225 int ink = print_mono_colour(dr, 0); 2269 int ink = print_mono_colour(dr, 0);
2226 int x, y; 2270 int x, y;
@@ -2273,12 +2317,14 @@ const struct game thegame = {
2273 free_game, 2317 free_game,
2274 true, solve_game, 2318 true, solve_game,
2275 true, game_can_format_as_text_now, game_text_format, 2319 true, game_can_format_as_text_now, game_text_format,
2320 get_prefs, set_prefs,
2276 new_ui, 2321 new_ui,
2277 free_ui, 2322 free_ui,
2278 encode_ui, 2323 NULL, /* encode_ui */
2279 decode_ui, 2324 NULL, /* decode_ui */
2280 NULL, /* game_request_keys */ 2325 NULL, /* game_request_keys */
2281 game_changed_state, 2326 game_changed_state,
2327 current_key_label,
2282 interpret_move, 2328 interpret_move,
2283 execute_move, 2329 execute_move,
2284 PREFERRED_TILE_SIZE, game_compute_size, game_set_size, 2330 PREFERRED_TILE_SIZE, game_compute_size, game_set_size,
@@ -2292,7 +2338,7 @@ const struct game thegame = {
2292 game_status, 2338 game_status,
2293 true, false, game_print_size, game_print, 2339 true, false, game_print_size, game_print,
2294 false, /* wants_statusbar */ 2340 false, /* wants_statusbar */
2295 false, game_timing_state, 2341 false, NULL, /* timing_state */
2296 REQUIRE_RBUTTON, /* flags */ 2342 REQUIRE_RBUTTON, /* flags */
2297}; 2343};
2298 2344
@@ -2301,10 +2347,9 @@ const struct game thegame = {
2301#include <time.h> 2347#include <time.h>
2302#include <stdarg.h> 2348#include <stdarg.h>
2303 2349
2304const char *quis = NULL; 2350static const char *quis = NULL;
2305int verbose = 0;
2306 2351
2307void usage(FILE *out) { 2352static void usage(FILE *out) {
2308 fprintf(out, "usage: %s [--stdin] [--soak] [--seed SEED] <params>|<game id>\n", quis); 2353 fprintf(out, "usage: %s [--stdin] [--soak] [--seed SEED] <params>|<game id>\n", quis);
2309} 2354}
2310 2355
@@ -2405,7 +2450,7 @@ static void process_desc(char *id)
2405 thegame.free_params(p); 2450 thegame.free_params(p);
2406} 2451}
2407 2452
2408int main(int argc, const char *argv[]) 2453int main(int argc, char *argv[])
2409{ 2454{
2410 char *id = NULL, *desc, *aux = NULL; 2455 char *id = NULL, *desc, *aux = NULL;
2411 const char *err; 2456 const char *err;