summaryrefslogtreecommitdiff
path: root/apps/plugins/puzzles/src/undead.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/puzzles/src/undead.c')
-rw-r--r--apps/plugins/puzzles/src/undead.c210
1 files changed, 128 insertions, 82 deletions
diff --git a/apps/plugins/puzzles/src/undead.c b/apps/plugins/puzzles/src/undead.c
index 4dba828d48..0213d0e2e4 100644
--- a/apps/plugins/puzzles/src/undead.c
+++ b/apps/plugins/puzzles/src/undead.c
@@ -35,7 +35,11 @@
35#include <string.h> 35#include <string.h>
36#include <assert.h> 36#include <assert.h>
37#include <ctype.h> 37#include <ctype.h>
38#include <math.h> 38#ifdef NO_TGMATH_H
39# include <math.h>
40#else
41# include <tgmath.h>
42#endif
39 43
40#include "puzzles.h" 44#include "puzzles.h"
41 45
@@ -193,9 +197,9 @@ static game_params *custom_params(const config_item *cfg)
193 197
194static const char *validate_params(const game_params *params, bool full) 198static const char *validate_params(const game_params *params, bool full)
195{ 199{
196 if ((params->w * params->h ) > 54) return "Grid is too big";
197 if (params->w < 3) return "Width must be at least 3"; 200 if (params->w < 3) return "Width must be at least 3";
198 if (params->h < 3) return "Height must be at least 3"; 201 if (params->h < 3) return "Height must be at least 3";
202 if (params->w > 54 / params->h) return "Grid is too big";
199 if (params->diff >= DIFFCOUNT) return "Unknown difficulty rating"; 203 if (params->diff >= DIFFCOUNT) return "Unknown difficulty rating";
200 return NULL; 204 return NULL;
201} 205}
@@ -972,7 +976,7 @@ static int path_cmp(const void *a, const void *b) {
972 976
973static char *new_game_desc(const game_params *params, random_state *rs, 977static char *new_game_desc(const game_params *params, random_state *rs,
974 char **aux, bool interactive) { 978 char **aux, bool interactive) {
975 int i,count,c,w,h,r,p,g; 979 int count,c,w,h,r,p,g;
976 game_state *new; 980 game_state *new;
977 981
978 /* Variables for puzzle generation algorithm */ 982 /* Variables for puzzle generation algorithm */
@@ -993,7 +997,6 @@ static char *new_game_desc(const game_params *params, random_state *rs,
993 char *e; 997 char *e;
994 char *desc; 998 char *desc;
995 999
996 i = 0;
997 while (true) { 1000 while (true) {
998 new = new_state(params); 1001 new = new_state(params);
999 abort = false; 1002 abort = false;
@@ -1031,7 +1034,7 @@ static char *new_game_desc(const game_params *params, random_state *rs,
1031 /* Monsters / Mirrors ratio should be balanced */ 1034 /* Monsters / Mirrors ratio should be balanced */
1032 ratio = (float)new->common->num_total / 1035 ratio = (float)new->common->num_total /
1033 (float)(new->common->params.w * new->common->params.h); 1036 (float)(new->common->params.w * new->common->params.h);
1034 if (ratio < 0.48 || ratio > 0.78) { 1037 if (ratio < 0.48F || ratio > 0.78F) {
1035 free_game(new); 1038 free_game(new);
1036 continue; 1039 continue;
1037 } 1040 }
@@ -1253,7 +1256,6 @@ static char *new_game_desc(const game_params *params, random_state *rs,
1253 * difficulty level, free memory and start from scratch */ 1256 * difficulty level, free memory and start from scratch */
1254 sfree(old_guess); 1257 sfree(old_guess);
1255 free_game(new); 1258 free_game(new);
1256 i++;
1257 } 1259 }
1258 1260
1259 /* We have a valid puzzle! */ 1261 /* We have a valid puzzle! */
@@ -1574,6 +1576,8 @@ static char *solve_game(const game_state *state_start, const game_state *currsta
1574 } 1576 }
1575 1577
1576/* printf("Puzzle solved at level %s, iterations %d, ambiguous %d\n", (solved_bruteforce ? "TRICKY" : "NORMAL"), iterative_depth, count_ambiguous); */ 1578/* printf("Puzzle solved at level %s, iterations %d, ambiguous %d\n", (solved_bruteforce ? "TRICKY" : "NORMAL"), iterative_depth, count_ambiguous); */
1579 (void)iterative_depth;
1580 (void)count_ambiguous;
1577 1581
1578 move = snewn(solve_state->common->num_total * 4 +2, char); 1582 move = snewn(solve_state->common->num_total * 4 +2, char);
1579 c = move; 1583 c = move;
@@ -1640,31 +1644,64 @@ struct game_ui {
1640 int hx, hy; /* as for solo.c, highlight pos */ 1644 int hx, hy; /* as for solo.c, highlight pos */
1641 bool hshow, hpencil, hcursor; /* show state, type, and ?cursor. */ 1645 bool hshow, hpencil, hcursor; /* show state, type, and ?cursor. */
1642 bool ascii; 1646 bool ascii;
1647
1648 /*
1649 * User preference option: if the user right-clicks in a square
1650 * and presses a monster key to add/remove a pencil mark, do we
1651 * hide the mouse highlight again afterwards?
1652 *
1653 * Historically our answer was yes. The Android port prefers no.
1654 * There are advantages both ways, depending how much you dislike
1655 * the highlight cluttering your view. So it's a preference.
1656 */
1657 bool pencil_keep_highlight;
1643}; 1658};
1644 1659
1645static game_ui *new_ui(const game_state *state) 1660static game_ui *new_ui(const game_state *state)
1646{ 1661{
1647 game_ui *ui = snew(game_ui); 1662 game_ui *ui = snew(game_ui);
1648 ui->hx = ui->hy = 0;
1649 ui->hpencil = false; 1663 ui->hpencil = false;
1650 ui->hshow = false; 1664 ui->hx = ui->hy = ui->hshow = ui->hcursor =
1651 ui->hcursor = false; 1665 getenv_bool("PUZZLES_SHOW_CURSOR", false);
1652 ui->ascii = false; 1666 ui->ascii = false;
1667
1668 ui->pencil_keep_highlight = false;
1669
1653 return ui; 1670 return ui;
1654} 1671}
1655 1672
1656static void free_ui(game_ui *ui) { 1673static config_item *get_prefs(game_ui *ui)
1657 sfree(ui); 1674{
1658 return; 1675 config_item *ret;
1676
1677 ret = snewn(3, config_item);
1678
1679 ret[0].name = "Keep mouse highlight after changing a pencil mark";
1680 ret[0].kw = "pencil-keep-highlight";
1681 ret[0].type = C_BOOLEAN;
1682 ret[0].u.boolean.bval = ui->pencil_keep_highlight;
1683
1684 ret[1].name = "Monster representation";
1685 ret[1].kw = "monsters";
1686 ret[1].type = C_CHOICES;
1687 ret[1].u.choices.choicenames = ":Pictures:Letters";
1688 ret[1].u.choices.choicekws = ":pictures:letters";
1689 ret[1].u.choices.selected = ui->ascii;
1690
1691 ret[2].name = NULL;
1692 ret[2].type = C_END;
1693
1694 return ret;
1659} 1695}
1660 1696
1661static char *encode_ui(const game_ui *ui) 1697static void set_prefs(game_ui *ui, const config_item *cfg)
1662{ 1698{
1663 return NULL; 1699 ui->pencil_keep_highlight = cfg[0].u.boolean.bval;
1700 ui->ascii = cfg[1].u.choices.selected;
1664} 1701}
1665 1702
1666static void decode_ui(game_ui *ui, const char *encoding) 1703static void free_ui(game_ui *ui) {
1667{ 1704 sfree(ui);
1668 return; 1705 return;
1669} 1706}
1670 1707
@@ -1681,6 +1718,20 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate,
1681 } 1718 }
1682} 1719}
1683 1720
1721static const char *current_key_label(const game_ui *ui,
1722 const game_state *state, int button)
1723{
1724 int xi;
1725
1726 if (ui->hshow && button == CURSOR_SELECT)
1727 return ui->hpencil ? "Ink" : "Pencil";
1728 if (button == CURSOR_SELECT2) {
1729 xi = state->common->xinfo[ui->hx + ui->hy*(state->common->params.w+2)];
1730 if (xi >= 0 && !state->common->fixed[xi]) return "Clear";
1731 }
1732 return "";
1733}
1734
1684struct game_drawstate { 1735struct game_drawstate {
1685 int tilesize; 1736 int tilesize;
1686 bool started, solved; 1737 bool started, solved;
@@ -1743,7 +1794,7 @@ static char *interpret_move(const game_state *state, game_ui *ui,
1743 1794
1744 if (button == 'a' || button == 'A') { 1795 if (button == 'a' || button == 'A') {
1745 ui->ascii = !ui->ascii; 1796 ui->ascii = !ui->ascii;
1746 return UI_UPDATE; 1797 return MOVE_UI_UPDATE;
1747 } 1798 }
1748 1799
1749 if (button == 'm' || button == 'M') { 1800 if (button == 'm' || button == 'M') {
@@ -1755,22 +1806,30 @@ static char *interpret_move(const game_state *state, game_ui *ui,
1755 if (xi >= 0 && !state->common->fixed[xi]) { 1806 if (xi >= 0 && !state->common->fixed[xi]) {
1756 if (button == 'g' || button == 'G' || button == '1') { 1807 if (button == 'g' || button == 'G' || button == '1') {
1757 if (!ui->hcursor) ui->hshow = false; 1808 if (!ui->hcursor) ui->hshow = false;
1809 if (state->guess[xi] == 1)
1810 return ui->hcursor ? NULL : MOVE_UI_UPDATE;
1758 sprintf(buf,"G%d",xi); 1811 sprintf(buf,"G%d",xi);
1759 return dupstr(buf); 1812 return dupstr(buf);
1760 } 1813 }
1761 if (button == 'v' || button == 'V' || button == '2') { 1814 if (button == 'v' || button == 'V' || button == '2') {
1762 if (!ui->hcursor) ui->hshow = false; 1815 if (!ui->hcursor) ui->hshow = false;
1816 if (state->guess[xi] == 2)
1817 return ui->hcursor ? NULL : MOVE_UI_UPDATE;
1763 sprintf(buf,"V%d",xi); 1818 sprintf(buf,"V%d",xi);
1764 return dupstr(buf); 1819 return dupstr(buf);
1765 } 1820 }
1766 if (button == 'z' || button == 'Z' || button == '3') { 1821 if (button == 'z' || button == 'Z' || button == '3') {
1767 if (!ui->hcursor) ui->hshow = false; 1822 if (!ui->hcursor) ui->hshow = false;
1823 if (state->guess[xi] == 4)
1824 return ui->hcursor ? NULL : MOVE_UI_UPDATE;
1768 sprintf(buf,"Z%d",xi); 1825 sprintf(buf,"Z%d",xi);
1769 return dupstr(buf); 1826 return dupstr(buf);
1770 } 1827 }
1771 if (button == 'e' || button == 'E' || button == CURSOR_SELECT2 || 1828 if (button == 'e' || button == 'E' || button == CURSOR_SELECT2 ||
1772 button == '0' || button == '\b' ) { 1829 button == '0' || button == '\b' ) {
1773 if (!ui->hcursor) ui->hshow = false; 1830 if (!ui->hcursor) ui->hshow = false;
1831 if (state->guess[xi] == 7 && state->pencils[xi] == 0)
1832 return ui->hcursor ? NULL : MOVE_UI_UPDATE;
1774 sprintf(buf,"E%d",xi); 1833 sprintf(buf,"E%d",xi);
1775 return dupstr(buf); 1834 return dupstr(buf);
1776 } 1835 }
@@ -1790,45 +1849,42 @@ static char *interpret_move(const game_state *state, game_ui *ui,
1790 } 1849 }
1791 ui->hshow = true; 1850 ui->hshow = true;
1792 ui->hcursor = true; 1851 ui->hcursor = true;
1793 return UI_UPDATE; 1852 return MOVE_UI_UPDATE;
1794 } 1853 }
1795 if (ui->hshow && button == CURSOR_SELECT) { 1854 if (ui->hshow && button == CURSOR_SELECT) {
1796 ui->hpencil = !ui->hpencil; 1855 ui->hpencil = !ui->hpencil;
1797 ui->hcursor = true; 1856 ui->hcursor = true;
1798 return UI_UPDATE; 1857 return MOVE_UI_UPDATE;
1799 } 1858 }
1800 1859
1801 if (ui->hshow && ui->hpencil) { 1860 if (ui->hshow && ui->hpencil) {
1802 xi = state->common->xinfo[ui->hx + ui->hy*(state->common->params.w+2)]; 1861 xi = state->common->xinfo[ui->hx + ui->hy*(state->common->params.w+2)];
1803 if (xi >= 0 && !state->common->fixed[xi]) { 1862 if (xi >= 0 && !state->common->fixed[xi]) {
1863 buf[0] = '\0';
1864
1804 if (button == 'g' || button == 'G' || button == '1') { 1865 if (button == 'g' || button == 'G' || button == '1') {
1805 sprintf(buf,"g%d",xi); 1866 sprintf(buf,"g%d",xi);
1806 if (!ui->hcursor) { 1867 } else if (button == 'v' || button == 'V' || button == '2') {
1807 ui->hpencil = false;
1808 ui->hshow = false;
1809 }
1810 return dupstr(buf);
1811 }
1812 if (button == 'v' || button == 'V' || button == '2') {
1813 sprintf(buf,"v%d",xi); 1868 sprintf(buf,"v%d",xi);
1814 if (!ui->hcursor) { 1869 } else if (button == 'z' || button == 'Z' || button == '3') {
1815 ui->hpencil = false;
1816 ui->hshow = false;
1817 }
1818 return dupstr(buf);
1819 }
1820 if (button == 'z' || button == 'Z' || button == '3') {
1821 sprintf(buf,"z%d",xi); 1870 sprintf(buf,"z%d",xi);
1822 if (!ui->hcursor) { 1871 } else if (button == 'e' || button == 'E' ||
1823 ui->hpencil = false; 1872 button == CURSOR_SELECT2 || button == '0' ||
1824 ui->hshow = false; 1873 button == '\b') {
1825 } 1874 if (state->pencils[xi] == 0)
1826 return dupstr(buf); 1875 return ui->hcursor ? NULL : MOVE_UI_UPDATE;
1827 }
1828 if (button == 'e' || button == 'E' || button == CURSOR_SELECT2 ||
1829 button == '0' || button == '\b') {
1830 sprintf(buf,"E%d",xi); 1876 sprintf(buf,"E%d",xi);
1831 if (!ui->hcursor) { 1877 }
1878
1879 if (buf[0]) {
1880 /*
1881 * Hide the highlight after a keypress, if it was mouse-
1882 * generated. Also, don't hide it if this move has changed
1883 * pencil marks and the user preference says not to hide the
1884 * highlight in that situation.
1885 */
1886 if (!ui->hcursor &&
1887 !(ui->hpencil && ui->pencil_keep_highlight)) {
1832 ui->hpencil = false; 1888 ui->hpencil = false;
1833 ui->hshow = false; 1889 ui->hshow = false;
1834 } 1890 }
@@ -1847,14 +1903,14 @@ static char *interpret_move(const game_state *state, game_ui *ui,
1847 ui->hpencil = false; 1903 ui->hpencil = false;
1848 ui->hcursor = false; 1904 ui->hcursor = false;
1849 ui->hx = gx; ui->hy = gy; 1905 ui->hx = gx; ui->hy = gy;
1850 return UI_UPDATE; 1906 return MOVE_UI_UPDATE;
1851 } 1907 }
1852 else if (button == RIGHT_BUTTON && g == 7) { 1908 else if (button == RIGHT_BUTTON && g == 7) {
1853 ui->hshow = true; 1909 ui->hshow = true;
1854 ui->hpencil = true; 1910 ui->hpencil = true;
1855 ui->hcursor = false; 1911 ui->hcursor = false;
1856 ui->hx = gx; ui->hy = gy; 1912 ui->hx = gx; ui->hy = gy;
1857 return UI_UPDATE; 1913 return MOVE_UI_UPDATE;
1858 } 1914 }
1859 } 1915 }
1860 else if (ui->hshow) { 1916 else if (ui->hshow) {
@@ -1865,14 +1921,14 @@ static char *interpret_move(const game_state *state, game_ui *ui,
1865 ui->hpencil = false; 1921 ui->hpencil = false;
1866 ui->hcursor = false; 1922 ui->hcursor = false;
1867 ui->hx = 0; ui->hy = 0; 1923 ui->hx = 0; ui->hy = 0;
1868 return UI_UPDATE; 1924 return MOVE_UI_UPDATE;
1869 } 1925 }
1870 else { 1926 else {
1871 ui->hshow = true; 1927 ui->hshow = true;
1872 ui->hpencil = false; 1928 ui->hpencil = false;
1873 ui->hcursor = false; 1929 ui->hcursor = false;
1874 ui->hx = gx; ui->hy = gy; 1930 ui->hx = gx; ui->hy = gy;
1875 return UI_UPDATE; 1931 return MOVE_UI_UPDATE;
1876 } 1932 }
1877 } 1933 }
1878 else { 1934 else {
@@ -1880,7 +1936,7 @@ static char *interpret_move(const game_state *state, game_ui *ui,
1880 ui->hpencil = false; 1936 ui->hpencil = false;
1881 ui->hcursor = false; 1937 ui->hcursor = false;
1882 ui->hx = gx; ui->hy = gy; 1938 ui->hx = gx; ui->hy = gy;
1883 return UI_UPDATE; 1939 return MOVE_UI_UPDATE;
1884 } 1940 }
1885 } 1941 }
1886 else if (button == RIGHT_BUTTON) { 1942 else if (button == RIGHT_BUTTON) {
@@ -1889,7 +1945,7 @@ static char *interpret_move(const game_state *state, game_ui *ui,
1889 ui->hpencil = true; 1945 ui->hpencil = true;
1890 ui->hcursor = false; 1946 ui->hcursor = false;
1891 ui->hx = gx; ui->hy = gy; 1947 ui->hx = gx; ui->hy = gy;
1892 return UI_UPDATE; 1948 return MOVE_UI_UPDATE;
1893 } 1949 }
1894 else { 1950 else {
1895 if (gx == ui->hx && gy == ui->hy) { 1951 if (gx == ui->hx && gy == ui->hy) {
@@ -1897,14 +1953,14 @@ static char *interpret_move(const game_state *state, game_ui *ui,
1897 ui->hpencil = false; 1953 ui->hpencil = false;
1898 ui->hcursor = false; 1954 ui->hcursor = false;
1899 ui->hx = 0; ui->hy = 0; 1955 ui->hx = 0; ui->hy = 0;
1900 return UI_UPDATE; 1956 return MOVE_UI_UPDATE;
1901 } 1957 }
1902 else if (g == 7) { 1958 else if (g == 7) {
1903 ui->hshow = true; 1959 ui->hshow = true;
1904 ui->hpencil = true; 1960 ui->hpencil = true;
1905 ui->hcursor = false; 1961 ui->hcursor = false;
1906 ui->hx = gx; ui->hy = gy; 1962 ui->hx = gx; ui->hy = gy;
1907 return UI_UPDATE; 1963 return MOVE_UI_UPDATE;
1908 } 1964 }
1909 } 1965 }
1910 } 1966 }
@@ -2056,11 +2112,11 @@ static game_state *execute_move(const game_state *state, const char *move)
2056 if (c == 'S') { 2112 if (c == 'S') {
2057 move++; 2113 move++;
2058 solver = true; 2114 solver = true;
2059 } 2115 } else if (c == 'G' || c == 'V' || c == 'Z' || c == 'E' ||
2060 if (c == 'G' || c == 'V' || c == 'Z' || c == 'E' || 2116 c == 'g' || c == 'v' || c == 'z') {
2061 c == 'g' || c == 'v' || c == 'z') {
2062 move++; 2117 move++;
2063 sscanf(move, "%d%n", &x, &n); 2118 if (sscanf(move, "%d%n", &x, &n) != 1) goto badmove;
2119 if (x < 0 || x >= ret->common->num_total) goto badmove;
2064 if (c == 'G') ret->guess[x] = 1; 2120 if (c == 'G') ret->guess[x] = 1;
2065 if (c == 'V') ret->guess[x] = 2; 2121 if (c == 'V') ret->guess[x] = 2;
2066 if (c == 'Z') ret->guess[x] = 4; 2122 if (c == 'Z') ret->guess[x] = 4;
@@ -2069,23 +2125,26 @@ static game_state *execute_move(const game_state *state, const char *move)
2069 if (c == 'v') ret->pencils[x] ^= 2; 2125 if (c == 'v') ret->pencils[x] ^= 2;
2070 if (c == 'z') ret->pencils[x] ^= 4; 2126 if (c == 'z') ret->pencils[x] ^= 4;
2071 move += n; 2127 move += n;
2072 } 2128 } else if (c == 'D' && sscanf(move + 1, "%d,%d%n", &x, &y, &n) == 2 &&
2073 if (c == 'D' && sscanf(move + 1, "%d,%d%n", &x, &y, &n) == 2 && 2129 is_clue(ret, x, y)) {
2074 is_clue(ret, x, y)) {
2075 ret->hints_done[clue_index(ret, x, y)] ^= 1; 2130 ret->hints_done[clue_index(ret, x, y)] ^= 1;
2076 move += n + 1; 2131 move += n + 1;
2077 } 2132 } else if (c == 'M') {
2078 if (c == 'M') {
2079 /* 2133 /*
2080 * Fill in absolutely all pencil marks in unfilled 2134 * Fill in absolutely all pencil marks in unfilled
2081 * squares, for those who like to play by the rigorous 2135 * squares, for those who like to play by the rigorous
2082 * approach of starting off in that state and eliminating 2136 * approach of starting off in that state and eliminating
2083 * things. 2137 * things.
2084 */ 2138 */
2085 for (i = 0; i < ret->common->wh; i++) 2139 for (i = 0; i < ret->common->num_total; i++)
2086 if (ret->guess[i] == 7) 2140 if (ret->guess[i] == 7)
2087 ret->pencils[i] = 7; 2141 ret->pencils[i] = 7;
2088 move++; 2142 move++;
2143 } else {
2144 /* Unknown move type. */
2145 badmove:
2146 free_game(ret);
2147 return NULL;
2089 } 2148 }
2090 if (*move == ';') move++; 2149 if (*move == ';') move++;
2091 } 2150 }
@@ -2118,7 +2177,7 @@ static game_state *execute_move(const game_state *state, const char *move)
2118#define PREFERRED_TILE_SIZE 64 2177#define PREFERRED_TILE_SIZE 64
2119 2178
2120static void game_compute_size(const game_params *params, int tilesize, 2179static void game_compute_size(const game_params *params, int tilesize,
2121 int *x, int *y) 2180 const game_ui *ui, int *x, int *y)
2122{ 2181{
2123 /* Ick: fake up `ds->tilesize' for macro expansion purposes */ 2182 /* Ick: fake up `ds->tilesize' for macro expansion purposes */
2124 struct { int tilesize; } ads, *ds = &ads; 2183 struct { int tilesize; } ads, *ds = &ads;
@@ -2402,7 +2461,7 @@ static void draw_monster(drawing *dr, game_drawstate *ds, int x, int y,
2402static void draw_monster_count(drawing *dr, game_drawstate *ds, 2461static void draw_monster_count(drawing *dr, game_drawstate *ds,
2403 const game_state *state, int c, bool hflash) { 2462 const game_state *state, int c, bool hflash) {
2404 int dx,dy; 2463 int dx,dy;
2405 char buf[8]; 2464 char buf[MAX_DIGITS(int) + 1];
2406 char bufm[8]; 2465 char bufm[8];
2407 2466
2408 dy = TILESIZE/4; 2467 dy = TILESIZE/4;
@@ -2447,7 +2506,7 @@ static void draw_path_hint(drawing *dr, game_drawstate *ds,
2447 const struct game_params *params, 2506 const struct game_params *params,
2448 int hint_index, bool hflash, int hint) { 2507 int hint_index, bool hflash, int hint) {
2449 int x, y, color, dx, dy, text_dx, text_dy, text_size; 2508 int x, y, color, dx, dy, text_dx, text_dy, text_size;
2450 char buf[4]; 2509 char buf[MAX_DIGITS(int) + 1];
2451 2510
2452 if (ds->hint_errors[hint_index]) 2511 if (ds->hint_errors[hint_index])
2453 color = COL_ERROR; 2512 color = COL_ERROR;
@@ -2605,8 +2664,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds,
2605 2664
2606 /* Draw static grid components at startup */ 2665 /* Draw static grid components at startup */
2607 if (!ds->started) { 2666 if (!ds->started) {
2608 draw_rect(dr, 0, 0, 2*BORDER+(ds->w+2)*TILESIZE,
2609 2*BORDER+(ds->h+3)*TILESIZE, COL_BACKGROUND);
2610 draw_rect(dr, BORDER+TILESIZE-1, BORDER+2*TILESIZE-1, 2667 draw_rect(dr, BORDER+TILESIZE-1, BORDER+2*TILESIZE-1,
2611 (ds->w)*TILESIZE +3, (ds->h)*TILESIZE +3, COL_GRID); 2668 (ds->w)*TILESIZE +3, (ds->h)*TILESIZE +3, COL_GRID);
2612 for (i=0;i<ds->w;i++) 2669 for (i=0;i<ds->w;i++)
@@ -2745,19 +2802,6 @@ static int game_status(const game_state *state)
2745 return state->solved; 2802 return state->solved;
2746} 2803}
2747 2804
2748static bool game_timing_state(const game_state *state, game_ui *ui)
2749{
2750 return true;
2751}
2752
2753static void game_print_size(const game_params *params, float *x, float *y)
2754{
2755}
2756
2757static void game_print(drawing *dr, const game_state *state, int tilesize)
2758{
2759}
2760
2761#ifdef COMBINED 2805#ifdef COMBINED
2762#define thegame undead 2806#define thegame undead
2763#endif 2807#endif
@@ -2779,12 +2823,14 @@ const struct game thegame = {
2779 free_game, 2823 free_game,
2780 true, solve_game, 2824 true, solve_game,
2781 true, game_can_format_as_text_now, game_text_format, 2825 true, game_can_format_as_text_now, game_text_format,
2826 get_prefs, set_prefs,
2782 new_ui, 2827 new_ui,
2783 free_ui, 2828 free_ui,
2784 encode_ui, 2829 NULL, /* encode_ui */
2785 decode_ui, 2830 NULL, /* decode_ui */
2786 game_request_keys, 2831 game_request_keys,
2787 game_changed_state, 2832 game_changed_state,
2833 current_key_label,
2788 interpret_move, 2834 interpret_move,
2789 execute_move, 2835 execute_move,
2790 PREFERRED_TILE_SIZE, game_compute_size, game_set_size, 2836 PREFERRED_TILE_SIZE, game_compute_size, game_set_size,
@@ -2796,8 +2842,8 @@ const struct game thegame = {
2796 game_flash_length, 2842 game_flash_length,
2797 game_get_cursor_location, 2843 game_get_cursor_location,
2798 game_status, 2844 game_status,
2799 false, false, game_print_size, game_print, 2845 false, false, NULL, NULL, /* print_size, print */
2800 false, /* wants_statusbar */ 2846 false, /* wants_statusbar */
2801 false, game_timing_state, 2847 false, NULL, /* timing_state */
2802 0, /* flags */ 2848 0, /* flags */
2803}; 2849};