diff options
Diffstat (limited to 'apps/plugins/puzzles/src/slant.c')
-rw-r--r-- | apps/plugins/puzzles/src/slant.c | 180 |
1 files changed, 108 insertions, 72 deletions
diff --git a/apps/plugins/puzzles/src/slant.c b/apps/plugins/puzzles/src/slant.c index ed290fe57d..bd04b786e6 100644 --- a/apps/plugins/puzzles/src/slant.c +++ b/apps/plugins/puzzles/src/slant.c | |||
@@ -28,7 +28,11 @@ | |||
28 | #include <string.h> | 28 | #include <string.h> |
29 | #include <assert.h> | 29 | #include <assert.h> |
30 | #include <ctype.h> | 30 | #include <ctype.h> |
31 | #include <math.h> | 31 | #ifdef NO_TGMATH_H |
32 | # include <math.h> | ||
33 | #else | ||
34 | # include <tgmath.h> | ||
35 | #endif | ||
32 | 36 | ||
33 | #include "puzzles.h" | 37 | #include "puzzles.h" |
34 | 38 | ||
@@ -51,7 +55,7 @@ enum { | |||
51 | */ | 55 | */ |
52 | #if defined STANDALONE_SOLVER | 56 | #if defined STANDALONE_SOLVER |
53 | #define SOLVER_DIAGNOSTICS | 57 | #define SOLVER_DIAGNOSTICS |
54 | bool verbose = false; | 58 | static bool verbose = false; |
55 | #elif defined SOLVER_DIAGNOSTICS | 59 | #elif defined SOLVER_DIAGNOSTICS |
56 | #define verbose true | 60 | #define verbose true |
57 | #endif | 61 | #endif |
@@ -226,6 +230,8 @@ static const char *validate_params(const game_params *params, bool full) | |||
226 | 230 | ||
227 | if (params->w < 2 || params->h < 2) | 231 | if (params->w < 2 || params->h < 2) |
228 | return "Width and height must both be at least two"; | 232 | return "Width and height must both be at least two"; |
233 | if (params->w > INT_MAX / params->h) | ||
234 | return "Width times height must not be unreasonably large"; | ||
229 | 235 | ||
230 | return NULL; | 236 | return NULL; |
231 | } | 237 | } |
@@ -238,7 +244,7 @@ struct solver_scratch { | |||
238 | * Disjoint set forest which tracks the connected sets of | 244 | * Disjoint set forest which tracks the connected sets of |
239 | * points. | 245 | * points. |
240 | */ | 246 | */ |
241 | int *connected; | 247 | DSF *connected; |
242 | 248 | ||
243 | /* | 249 | /* |
244 | * Counts the number of possible exits from each connected set | 250 | * Counts the number of possible exits from each connected set |
@@ -259,7 +265,7 @@ struct solver_scratch { | |||
259 | * Another disjoint set forest. This one tracks _squares_ which | 265 | * Another disjoint set forest. This one tracks _squares_ which |
260 | * are known to slant in the same direction. | 266 | * are known to slant in the same direction. |
261 | */ | 267 | */ |
262 | int *equiv; | 268 | DSF *equiv; |
263 | 269 | ||
264 | /* | 270 | /* |
265 | * Stores slash values which we know for an equivalence class. | 271 | * Stores slash values which we know for an equivalence class. |
@@ -306,10 +312,10 @@ static struct solver_scratch *new_scratch(int w, int h) | |||
306 | { | 312 | { |
307 | int W = w+1, H = h+1; | 313 | int W = w+1, H = h+1; |
308 | struct solver_scratch *ret = snew(struct solver_scratch); | 314 | struct solver_scratch *ret = snew(struct solver_scratch); |
309 | ret->connected = snewn(W*H, int); | 315 | ret->connected = dsf_new(W*H); |
310 | ret->exits = snewn(W*H, int); | 316 | ret->exits = snewn(W*H, int); |
311 | ret->border = snewn(W*H, bool); | 317 | ret->border = snewn(W*H, bool); |
312 | ret->equiv = snewn(w*h, int); | 318 | ret->equiv = dsf_new(w*h); |
313 | ret->slashval = snewn(w*h, signed char); | 319 | ret->slashval = snewn(w*h, signed char); |
314 | ret->vbitmap = snewn(w*h, unsigned char); | 320 | ret->vbitmap = snewn(w*h, unsigned char); |
315 | return ret; | 321 | return ret; |
@@ -319,10 +325,10 @@ static void free_scratch(struct solver_scratch *sc) | |||
319 | { | 325 | { |
320 | sfree(sc->vbitmap); | 326 | sfree(sc->vbitmap); |
321 | sfree(sc->slashval); | 327 | sfree(sc->slashval); |
322 | sfree(sc->equiv); | 328 | dsf_free(sc->equiv); |
323 | sfree(sc->border); | 329 | sfree(sc->border); |
324 | sfree(sc->exits); | 330 | sfree(sc->exits); |
325 | sfree(sc->connected); | 331 | dsf_free(sc->connected); |
326 | sfree(sc); | 332 | sfree(sc); |
327 | } | 333 | } |
328 | 334 | ||
@@ -330,7 +336,7 @@ static void free_scratch(struct solver_scratch *sc) | |||
330 | * Wrapper on dsf_merge() which updates the `exits' and `border' | 336 | * Wrapper on dsf_merge() which updates the `exits' and `border' |
331 | * arrays. | 337 | * arrays. |
332 | */ | 338 | */ |
333 | static void merge_vertices(int *connected, | 339 | static void merge_vertices(DSF *connected, |
334 | struct solver_scratch *sc, int i, int j) | 340 | struct solver_scratch *sc, int i, int j) |
335 | { | 341 | { |
336 | int exits = -1; | 342 | int exits = -1; |
@@ -376,7 +382,7 @@ static void decr_exits(struct solver_scratch *sc, int i) | |||
376 | 382 | ||
377 | static void fill_square(int w, int h, int x, int y, int v, | 383 | static void fill_square(int w, int h, int x, int y, int v, |
378 | signed char *soln, | 384 | signed char *soln, |
379 | int *connected, struct solver_scratch *sc) | 385 | DSF *connected, struct solver_scratch *sc) |
380 | { | 386 | { |
381 | int W = w+1 /*, H = h+1 */; | 387 | int W = w+1 /*, H = h+1 */; |
382 | 388 | ||
@@ -466,13 +472,13 @@ static int slant_solve(int w, int h, const signed char *clues, | |||
466 | * Establish a disjoint set forest for tracking connectedness | 472 | * Establish a disjoint set forest for tracking connectedness |
467 | * between grid points. | 473 | * between grid points. |
468 | */ | 474 | */ |
469 | dsf_init(sc->connected, W*H); | 475 | dsf_reinit(sc->connected); |
470 | 476 | ||
471 | /* | 477 | /* |
472 | * Establish a disjoint set forest for tracking which squares | 478 | * Establish a disjoint set forest for tracking which squares |
473 | * are known to slant in the same direction. | 479 | * are known to slant in the same direction. |
474 | */ | 480 | */ |
475 | dsf_init(sc->equiv, w*h); | 481 | dsf_reinit(sc->equiv); |
476 | 482 | ||
477 | /* | 483 | /* |
478 | * Clear the slashval array. | 484 | * Clear the slashval array. |
@@ -991,7 +997,8 @@ static void slant_generate(int w, int h, signed char *soln, random_state *rs) | |||
991 | { | 997 | { |
992 | int W = w+1, H = h+1; | 998 | int W = w+1, H = h+1; |
993 | int x, y, i; | 999 | int x, y, i; |
994 | int *connected, *indices; | 1000 | DSF *connected; |
1001 | int *indices; | ||
995 | 1002 | ||
996 | /* | 1003 | /* |
997 | * Clear the output. | 1004 | * Clear the output. |
@@ -1002,7 +1009,7 @@ static void slant_generate(int w, int h, signed char *soln, random_state *rs) | |||
1002 | * Establish a disjoint set forest for tracking connectedness | 1009 | * Establish a disjoint set forest for tracking connectedness |
1003 | * between grid points. | 1010 | * between grid points. |
1004 | */ | 1011 | */ |
1005 | connected = snew_dsf(W*H); | 1012 | connected = dsf_new(W*H); |
1006 | 1013 | ||
1007 | /* | 1014 | /* |
1008 | * Prepare a list of the squares in the grid, and fill them in | 1015 | * Prepare a list of the squares in the grid, and fill them in |
@@ -1058,7 +1065,7 @@ static void slant_generate(int w, int h, signed char *soln, random_state *rs) | |||
1058 | } | 1065 | } |
1059 | 1066 | ||
1060 | sfree(indices); | 1067 | sfree(indices); |
1061 | sfree(connected); | 1068 | dsf_free(connected); |
1062 | } | 1069 | } |
1063 | 1070 | ||
1064 | static char *new_game_desc(const game_params *params, random_state *rs, | 1071 | static char *new_game_desc(const game_params *params, random_state *rs, |
@@ -1574,28 +1581,69 @@ static char *game_text_format(const game_state *state) | |||
1574 | struct game_ui { | 1581 | struct game_ui { |
1575 | int cur_x, cur_y; | 1582 | int cur_x, cur_y; |
1576 | bool cur_visible; | 1583 | bool cur_visible; |
1584 | |||
1585 | /* | ||
1586 | * User preference option to swap the left and right mouse | ||
1587 | * buttons. There isn't a completely obvious mapping of left and | ||
1588 | * right buttons to the two directions of slash, and at least one | ||
1589 | * player turned out not to have the same intuition as me. | ||
1590 | */ | ||
1591 | bool swap_buttons; | ||
1577 | }; | 1592 | }; |
1578 | 1593 | ||
1594 | static void legacy_prefs_override(struct game_ui *ui_out) | ||
1595 | { | ||
1596 | static bool initialised = false; | ||
1597 | static int swap_buttons = -1; | ||
1598 | |||
1599 | if (!initialised) { | ||
1600 | initialised = true; | ||
1601 | swap_buttons = getenv_bool("SLANT_SWAP_BUTTONS", -1); | ||
1602 | } | ||
1603 | |||
1604 | if (swap_buttons != -1) | ||
1605 | ui_out->swap_buttons = swap_buttons; | ||
1606 | } | ||
1607 | |||
1579 | static game_ui *new_ui(const game_state *state) | 1608 | static game_ui *new_ui(const game_state *state) |
1580 | { | 1609 | { |
1581 | game_ui *ui = snew(game_ui); | 1610 | game_ui *ui = snew(game_ui); |
1582 | ui->cur_x = ui->cur_y = 0; | 1611 | ui->cur_x = ui->cur_y = 0; |
1583 | ui->cur_visible = false; | 1612 | ui->cur_visible = getenv_bool("PUZZLES_SHOW_CURSOR", false); |
1613 | |||
1614 | ui->swap_buttons = false; | ||
1615 | legacy_prefs_override(ui); | ||
1616 | |||
1584 | return ui; | 1617 | return ui; |
1585 | } | 1618 | } |
1586 | 1619 | ||
1587 | static void free_ui(game_ui *ui) | 1620 | static config_item *get_prefs(game_ui *ui) |
1588 | { | 1621 | { |
1589 | sfree(ui); | 1622 | config_item *ret; |
1623 | |||
1624 | ret = snewn(2, config_item); | ||
1625 | |||
1626 | ret[0].name = "Mouse button order"; | ||
1627 | ret[0].kw = "left-button"; | ||
1628 | ret[0].type = C_CHOICES; | ||
1629 | ret[0].u.choices.choicenames = ":Left \\, right /:Left /, right \\"; | ||
1630 | ret[0].u.choices.choicekws = ":\\:/"; | ||
1631 | ret[0].u.choices.selected = ui->swap_buttons; | ||
1632 | |||
1633 | ret[1].name = NULL; | ||
1634 | ret[1].type = C_END; | ||
1635 | |||
1636 | return ret; | ||
1590 | } | 1637 | } |
1591 | 1638 | ||
1592 | static char *encode_ui(const game_ui *ui) | 1639 | static void set_prefs(game_ui *ui, const config_item *cfg) |
1593 | { | 1640 | { |
1594 | return NULL; | 1641 | ui->swap_buttons = cfg[0].u.choices.selected; |
1595 | } | 1642 | } |
1596 | 1643 | ||
1597 | static void decode_ui(game_ui *ui, const char *encoding) | 1644 | static void free_ui(game_ui *ui) |
1598 | { | 1645 | { |
1646 | sfree(ui); | ||
1599 | } | 1647 | } |
1600 | 1648 | ||
1601 | static void game_changed_state(game_ui *ui, const game_state *oldstate, | 1649 | static void game_changed_state(game_ui *ui, const game_state *oldstate, |
@@ -1603,6 +1651,22 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, | |||
1603 | { | 1651 | { |
1604 | } | 1652 | } |
1605 | 1653 | ||
1654 | static const char *current_key_label(const game_ui *ui, | ||
1655 | const game_state *state, int button) | ||
1656 | { | ||
1657 | if (IS_CURSOR_SELECT(button) && ui->cur_visible) { | ||
1658 | switch (state->soln[ui->cur_y*state->p.w+ui->cur_x]) { | ||
1659 | case 0: | ||
1660 | return button == CURSOR_SELECT ? "\\" : "/"; | ||
1661 | case -1: | ||
1662 | return button == CURSOR_SELECT ? "/" : "Blank"; | ||
1663 | case +1: | ||
1664 | return button == CURSOR_SELECT ? "Blank" : "\\"; | ||
1665 | } | ||
1666 | } | ||
1667 | return ""; | ||
1668 | } | ||
1669 | |||
1606 | #define PREFERRED_TILESIZE 32 | 1670 | #define PREFERRED_TILESIZE 32 |
1607 | #define TILESIZE (ds->tilesize) | 1671 | #define TILESIZE (ds->tilesize) |
1608 | #define BORDER TILESIZE | 1672 | #define BORDER TILESIZE |
@@ -1638,7 +1702,6 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, | |||
1638 | 1702 | ||
1639 | struct game_drawstate { | 1703 | struct game_drawstate { |
1640 | int tilesize; | 1704 | int tilesize; |
1641 | bool started; | ||
1642 | long *grid; | 1705 | long *grid; |
1643 | long *todraw; | 1706 | long *todraw; |
1644 | }; | 1707 | }; |
@@ -1653,51 +1716,34 @@ static char *interpret_move(const game_state *state, game_ui *ui, | |||
1653 | enum { CLOCKWISE, ANTICLOCKWISE, NONE } action = NONE; | 1716 | enum { CLOCKWISE, ANTICLOCKWISE, NONE } action = NONE; |
1654 | 1717 | ||
1655 | if (button == LEFT_BUTTON || button == RIGHT_BUTTON) { | 1718 | if (button == LEFT_BUTTON || button == RIGHT_BUTTON) { |
1656 | /* | 1719 | if (ui->swap_buttons) { |
1657 | * This is an utterly awful hack which I should really sort out | 1720 | if (button == LEFT_BUTTON) |
1658 | * by means of a proper configuration mechanism. One Slant | 1721 | button = RIGHT_BUTTON; |
1659 | * player has observed that they prefer the mouse buttons to | 1722 | else |
1660 | * function exactly the opposite way round, so here's a | 1723 | button = LEFT_BUTTON; |
1661 | * mechanism for environment-based configuration. I cache the | 1724 | } |
1662 | * result in a global variable - yuck! - to avoid repeated | ||
1663 | * lookups. | ||
1664 | */ | ||
1665 | { | ||
1666 | static int swap_buttons = -1; | ||
1667 | if (swap_buttons < 0) { | ||
1668 | char *env = getenv("SLANT_SWAP_BUTTONS"); | ||
1669 | swap_buttons = (env && (env[0] == 'y' || env[0] == 'Y')); | ||
1670 | } | ||
1671 | if (swap_buttons) { | ||
1672 | if (button == LEFT_BUTTON) | ||
1673 | button = RIGHT_BUTTON; | ||
1674 | else | ||
1675 | button = LEFT_BUTTON; | ||
1676 | } | ||
1677 | } | ||
1678 | action = (button == LEFT_BUTTON) ? CLOCKWISE : ANTICLOCKWISE; | 1725 | action = (button == LEFT_BUTTON) ? CLOCKWISE : ANTICLOCKWISE; |
1679 | 1726 | ||
1680 | x = FROMCOORD(x); | 1727 | x = FROMCOORD(x); |
1681 | y = FROMCOORD(y); | 1728 | y = FROMCOORD(y); |
1682 | if (x < 0 || y < 0 || x >= w || y >= h) | 1729 | if (x < 0 || y < 0 || x >= w || y >= h) |
1683 | return NULL; | 1730 | return MOVE_UNUSED; |
1684 | ui->cur_visible = false; | 1731 | ui->cur_visible = false; |
1685 | } else if (IS_CURSOR_SELECT(button)) { | 1732 | } else if (IS_CURSOR_SELECT(button)) { |
1686 | if (!ui->cur_visible) { | 1733 | if (!ui->cur_visible) { |
1687 | ui->cur_visible = true; | 1734 | ui->cur_visible = true; |
1688 | return UI_UPDATE; | 1735 | return MOVE_UI_UPDATE; |
1689 | } | 1736 | } |
1690 | x = ui->cur_x; | 1737 | x = ui->cur_x; |
1691 | y = ui->cur_y; | 1738 | y = ui->cur_y; |
1692 | 1739 | ||
1693 | action = (button == CURSOR_SELECT2) ? ANTICLOCKWISE : CLOCKWISE; | 1740 | action = (button == CURSOR_SELECT2) ? ANTICLOCKWISE : CLOCKWISE; |
1694 | } else if (IS_CURSOR_MOVE(button)) { | 1741 | } else if (IS_CURSOR_MOVE(button)) { |
1695 | move_cursor(button, &ui->cur_x, &ui->cur_y, w, h, false); | 1742 | return move_cursor(button, &ui->cur_x, &ui->cur_y, w, h, false, &ui->cur_visible); |
1696 | ui->cur_visible = true; | ||
1697 | return UI_UPDATE; | ||
1698 | } else if (button == '\\' || button == '\b' || button == '/') { | 1743 | } else if (button == '\\' || button == '\b' || button == '/') { |
1699 | int x = ui->cur_x, y = ui->cur_y; | 1744 | int x = ui->cur_x, y = ui->cur_y; |
1700 | if (button == ("\\" "\b" "/")[state->soln[y*w + x] + 1]) return NULL; | 1745 | if (button == ("\\" "\b" "/")[state->soln[y*w + x] + 1]) |
1746 | return MOVE_NO_EFFECT; | ||
1701 | sprintf(buf, "%c%d,%d", button == '\b' ? 'C' : button, x, y); | 1747 | sprintf(buf, "%c%d,%d", button == '\b' ? 'C' : button, x, y); |
1702 | return dupstr(buf); | 1748 | return dupstr(buf); |
1703 | } | 1749 | } |
@@ -1723,7 +1769,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, | |||
1723 | return dupstr(buf); | 1769 | return dupstr(buf); |
1724 | } | 1770 | } |
1725 | 1771 | ||
1726 | return NULL; | 1772 | return MOVE_UNUSED; |
1727 | } | 1773 | } |
1728 | 1774 | ||
1729 | static game_state *execute_move(const game_state *state, const char *move) | 1775 | static game_state *execute_move(const game_state *state, const char *move) |
@@ -1774,7 +1820,7 @@ static game_state *execute_move(const game_state *state, const char *move) | |||
1774 | */ | 1820 | */ |
1775 | 1821 | ||
1776 | static void game_compute_size(const game_params *params, int tilesize, | 1822 | static void game_compute_size(const game_params *params, int tilesize, |
1777 | int *x, int *y) | 1823 | const game_ui *ui, int *x, int *y) |
1778 | { | 1824 | { |
1779 | /* fool the macros */ | 1825 | /* fool the macros */ |
1780 | struct dummy { int tilesize; } dummy, *ds = &dummy; | 1826 | struct dummy { int tilesize; } dummy, *ds = &dummy; |
@@ -1832,7 +1878,6 @@ static game_drawstate *game_new_drawstate(drawing *dr, const game_state *state) | |||
1832 | struct game_drawstate *ds = snew(struct game_drawstate); | 1878 | struct game_drawstate *ds = snew(struct game_drawstate); |
1833 | 1879 | ||
1834 | ds->tilesize = 0; | 1880 | ds->tilesize = 0; |
1835 | ds->started = false; | ||
1836 | ds->grid = snewn((w+2)*(h+2), long); | 1881 | ds->grid = snewn((w+2)*(h+2), long); |
1837 | ds->todraw = snewn((w+2)*(h+2), long); | 1882 | ds->todraw = snewn((w+2)*(h+2), long); |
1838 | for (i = 0; i < (w+2)*(h+2); i++) | 1883 | for (i = 0; i < (w+2)*(h+2); i++) |
@@ -1972,14 +2017,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds, | |||
1972 | else | 2017 | else |
1973 | flashing = false; | 2018 | flashing = false; |
1974 | 2019 | ||
1975 | if (!ds->started) { | ||
1976 | int ww, wh; | ||
1977 | game_compute_size(&state->p, TILESIZE, &ww, &wh); | ||
1978 | draw_rect(dr, 0, 0, ww, wh, COL_BACKGROUND); | ||
1979 | draw_update(dr, 0, 0, ww, wh); | ||
1980 | ds->started = true; | ||
1981 | } | ||
1982 | |||
1983 | /* | 2020 | /* |
1984 | * Loop over the grid and work out where all the slashes are. | 2021 | * Loop over the grid and work out where all the slashes are. |
1985 | * We need to do this because a slash in one square affects the | 2022 | * We need to do this because a slash in one square affects the |
@@ -2082,24 +2119,21 @@ static int game_status(const game_state *state) | |||
2082 | return state->completed ? +1 : 0; | 2119 | return state->completed ? +1 : 0; |
2083 | } | 2120 | } |
2084 | 2121 | ||
2085 | static bool game_timing_state(const game_state *state, game_ui *ui) | 2122 | static void game_print_size(const game_params *params, const game_ui *ui, |
2086 | { | 2123 | float *x, float *y) |
2087 | return true; | ||
2088 | } | ||
2089 | |||
2090 | static void game_print_size(const game_params *params, float *x, float *y) | ||
2091 | { | 2124 | { |
2092 | int pw, ph; | 2125 | int pw, ph; |
2093 | 2126 | ||
2094 | /* | 2127 | /* |
2095 | * I'll use 6mm squares by default. | 2128 | * I'll use 6mm squares by default. |
2096 | */ | 2129 | */ |
2097 | game_compute_size(params, 600, &pw, &ph); | 2130 | game_compute_size(params, 600, ui, &pw, &ph); |
2098 | *x = pw / 100.0F; | 2131 | *x = pw / 100.0F; |
2099 | *y = ph / 100.0F; | 2132 | *y = ph / 100.0F; |
2100 | } | 2133 | } |
2101 | 2134 | ||
2102 | static void game_print(drawing *dr, const game_state *state, int tilesize) | 2135 | static void game_print(drawing *dr, const game_state *state, const game_ui *ui, |
2136 | int tilesize) | ||
2103 | { | 2137 | { |
2104 | int w = state->p.w, h = state->p.h, W = w+1; | 2138 | int w = state->p.w, h = state->p.h, W = w+1; |
2105 | int ink = print_mono_colour(dr, 0); | 2139 | int ink = print_mono_colour(dr, 0); |
@@ -2179,12 +2213,14 @@ const struct game thegame = { | |||
2179 | free_game, | 2213 | free_game, |
2180 | true, solve_game, | 2214 | true, solve_game, |
2181 | true, game_can_format_as_text_now, game_text_format, | 2215 | true, game_can_format_as_text_now, game_text_format, |
2216 | get_prefs, set_prefs, | ||
2182 | new_ui, | 2217 | new_ui, |
2183 | free_ui, | 2218 | free_ui, |
2184 | encode_ui, | 2219 | NULL, /* encode_ui */ |
2185 | decode_ui, | 2220 | NULL, /* decode_ui */ |
2186 | NULL, /* game_request_keys */ | 2221 | NULL, /* game_request_keys */ |
2187 | game_changed_state, | 2222 | game_changed_state, |
2223 | current_key_label, | ||
2188 | interpret_move, | 2224 | interpret_move, |
2189 | execute_move, | 2225 | execute_move, |
2190 | PREFERRED_TILESIZE, game_compute_size, game_set_size, | 2226 | PREFERRED_TILESIZE, game_compute_size, game_set_size, |
@@ -2198,7 +2234,7 @@ const struct game thegame = { | |||
2198 | game_status, | 2234 | game_status, |
2199 | true, false, game_print_size, game_print, | 2235 | true, false, game_print_size, game_print, |
2200 | false, /* wants_statusbar */ | 2236 | false, /* wants_statusbar */ |
2201 | false, game_timing_state, | 2237 | false, NULL, /* timing_state */ |
2202 | 0, /* flags */ | 2238 | 0, /* flags */ |
2203 | }; | 2239 | }; |
2204 | 2240 | ||