diff options
Diffstat (limited to 'apps/plugins/puzzles/src/undead.c')
-rw-r--r-- | apps/plugins/puzzles/src/undead.c | 210 |
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 | ||
194 | static const char *validate_params(const game_params *params, bool full) | 198 | static 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 | ||
973 | static char *new_game_desc(const game_params *params, random_state *rs, | 977 | static 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 | ||
1645 | static game_ui *new_ui(const game_state *state) | 1660 | static 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 | ||
1656 | static void free_ui(game_ui *ui) { | 1673 | static 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 | ||
1661 | static char *encode_ui(const game_ui *ui) | 1697 | static 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 | ||
1666 | static void decode_ui(game_ui *ui, const char *encoding) | 1703 | static 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 | ||
1721 | static 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 | |||
1684 | struct game_drawstate { | 1735 | struct 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 | ||
2120 | static void game_compute_size(const game_params *params, int tilesize, | 2179 | static 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, | |||
2402 | static void draw_monster_count(drawing *dr, game_drawstate *ds, | 2461 | static 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 | ||
2748 | static bool game_timing_state(const game_state *state, game_ui *ui) | ||
2749 | { | ||
2750 | return true; | ||
2751 | } | ||
2752 | |||
2753 | static void game_print_size(const game_params *params, float *x, float *y) | ||
2754 | { | ||
2755 | } | ||
2756 | |||
2757 | static 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 | }; |