diff options
Diffstat (limited to 'apps/plugins/puzzles/src/unequal.c')
-rw-r--r-- | apps/plugins/puzzles/src/unequal.c | 193 |
1 files changed, 129 insertions, 64 deletions
diff --git a/apps/plugins/puzzles/src/unequal.c b/apps/plugins/puzzles/src/unequal.c index 153954e510..ab32e4ab79 100644 --- a/apps/plugins/puzzles/src/unequal.c +++ b/apps/plugins/puzzles/src/unequal.c | |||
@@ -21,7 +21,11 @@ | |||
21 | #include <string.h> | 21 | #include <string.h> |
22 | #include <assert.h> | 22 | #include <assert.h> |
23 | #include <ctype.h> | 23 | #include <ctype.h> |
24 | #include <math.h> | 24 | #ifdef NO_TGMATH_H |
25 | # include <math.h> | ||
26 | #else | ||
27 | # include <tgmath.h> | ||
28 | #endif | ||
25 | 29 | ||
26 | #include "puzzles.h" | 30 | #include "puzzles.h" |
27 | #include "latin.h" /* contains typedef for digit */ | 31 | #include "latin.h" /* contains typedef for digit */ |
@@ -84,6 +88,7 @@ struct game_params { | |||
84 | #define ADJ_TO_SPENT(x) ((x) << 9) | 88 | #define ADJ_TO_SPENT(x) ((x) << 9) |
85 | 89 | ||
86 | #define F_ERROR_MASK (F_ERROR|F_ERROR_UP|F_ERROR_RIGHT|F_ERROR_DOWN|F_ERROR_LEFT) | 90 | #define F_ERROR_MASK (F_ERROR|F_ERROR_UP|F_ERROR_RIGHT|F_ERROR_DOWN|F_ERROR_LEFT) |
91 | #define F_SPENT_MASK (F_SPENT_UP|F_SPENT_RIGHT|F_SPENT_DOWN|F_SPENT_LEFT) | ||
87 | 92 | ||
88 | struct game_state { | 93 | struct game_state { |
89 | int order; | 94 | int order; |
@@ -890,13 +895,14 @@ static int solver_state(game_state *state, int maxdiff) | |||
890 | struct latin_solver solver; | 895 | struct latin_solver solver; |
891 | int diff; | 896 | int diff; |
892 | 897 | ||
893 | latin_solver_alloc(&solver, state->nums, state->order); | 898 | if (latin_solver_alloc(&solver, state->nums, state->order)) |
894 | 899 | diff = latin_solver_main(&solver, maxdiff, | |
895 | diff = latin_solver_main(&solver, maxdiff, | 900 | DIFF_LATIN, DIFF_SET, DIFF_EXTREME, |
896 | DIFF_LATIN, DIFF_SET, DIFF_EXTREME, | 901 | DIFF_EXTREME, DIFF_RECURSIVE, |
897 | DIFF_EXTREME, DIFF_RECURSIVE, | 902 | unequal_solvers, unequal_valid, ctx, |
898 | unequal_solvers, unequal_valid, ctx, | 903 | clone_ctx, free_ctx); |
899 | clone_ctx, free_ctx); | 904 | else |
905 | diff = DIFF_IMPOSSIBLE; | ||
900 | 906 | ||
901 | memcpy(state->hints, solver.cube, state->order*state->order*state->order); | 907 | memcpy(state->hints, solver.cube, state->order*state->order*state->order); |
902 | 908 | ||
@@ -1073,7 +1079,7 @@ static int gg_best_clue(game_state *state, int *scratch, digit *latin) | |||
1073 | } | 1079 | } |
1074 | 1080 | ||
1075 | #ifdef STANDALONE_SOLVER | 1081 | #ifdef STANDALONE_SOLVER |
1076 | int maxtries; | 1082 | static int maxtries; |
1077 | #define MAXTRIES maxtries | 1083 | #define MAXTRIES maxtries |
1078 | #else | 1084 | #else |
1079 | #define MAXTRIES 50 | 1085 | #define MAXTRIES 50 |
@@ -1430,6 +1436,17 @@ static char *solve_game(const game_state *state, const game_state *currstate, | |||
1430 | struct game_ui { | 1436 | struct game_ui { |
1431 | int hx, hy; /* as for solo.c, highlight pos */ | 1437 | int hx, hy; /* as for solo.c, highlight pos */ |
1432 | bool hshow, hpencil, hcursor; /* show state, type, and ?cursor. */ | 1438 | bool hshow, hpencil, hcursor; /* show state, type, and ?cursor. */ |
1439 | |||
1440 | /* | ||
1441 | * User preference option: if the user right-clicks in a square | ||
1442 | * and presses a number key to add/remove a pencil mark, do we | ||
1443 | * hide the mouse highlight again afterwards? | ||
1444 | * | ||
1445 | * Historically our answer was yes. The Android port prefers no. | ||
1446 | * There are advantages both ways, depending how much you dislike | ||
1447 | * the highlight cluttering your view. So it's a preference. | ||
1448 | */ | ||
1449 | bool pencil_keep_highlight; | ||
1433 | }; | 1450 | }; |
1434 | 1451 | ||
1435 | static game_ui *new_ui(const game_state *state) | 1452 | static game_ui *new_ui(const game_state *state) |
@@ -1438,8 +1455,9 @@ static game_ui *new_ui(const game_state *state) | |||
1438 | 1455 | ||
1439 | ui->hx = ui->hy = 0; | 1456 | ui->hx = ui->hy = 0; |
1440 | ui->hpencil = false; | 1457 | ui->hpencil = false; |
1441 | ui->hshow = false; | 1458 | ui->hshow = ui->hcursor = getenv_bool("PUZZLES_SHOW_CURSOR", false); |
1442 | ui->hcursor = false; | 1459 | |
1460 | ui->pencil_keep_highlight = false; | ||
1443 | 1461 | ||
1444 | return ui; | 1462 | return ui; |
1445 | } | 1463 | } |
@@ -1449,13 +1467,26 @@ static void free_ui(game_ui *ui) | |||
1449 | sfree(ui); | 1467 | sfree(ui); |
1450 | } | 1468 | } |
1451 | 1469 | ||
1452 | static char *encode_ui(const game_ui *ui) | 1470 | static config_item *get_prefs(game_ui *ui) |
1453 | { | 1471 | { |
1454 | return NULL; | 1472 | config_item *ret; |
1473 | |||
1474 | ret = snewn(2, config_item); | ||
1475 | |||
1476 | ret[0].name = "Keep mouse highlight after changing a pencil mark"; | ||
1477 | ret[0].kw = "pencil-keep-highlight"; | ||
1478 | ret[0].type = C_BOOLEAN; | ||
1479 | ret[0].u.boolean.bval = ui->pencil_keep_highlight; | ||
1480 | |||
1481 | ret[1].name = NULL; | ||
1482 | ret[1].type = C_END; | ||
1483 | |||
1484 | return ret; | ||
1455 | } | 1485 | } |
1456 | 1486 | ||
1457 | static void decode_ui(game_ui *ui, const char *encoding) | 1487 | static void set_prefs(game_ui *ui, const config_item *cfg) |
1458 | { | 1488 | { |
1489 | ui->pencil_keep_highlight = cfg[0].u.boolean.bval; | ||
1459 | } | 1490 | } |
1460 | 1491 | ||
1461 | static void game_changed_state(game_ui *ui, const game_state *oldstate, | 1492 | static void game_changed_state(game_ui *ui, const game_state *oldstate, |
@@ -1470,6 +1501,14 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, | |||
1470 | } | 1501 | } |
1471 | } | 1502 | } |
1472 | 1503 | ||
1504 | static const char *current_key_label(const game_ui *ui, | ||
1505 | const game_state *state, int button) | ||
1506 | { | ||
1507 | if (ui->hshow && IS_CURSOR_SELECT(button)) | ||
1508 | return ui->hpencil ? "Ink" : "Pencil"; | ||
1509 | return ""; | ||
1510 | } | ||
1511 | |||
1473 | struct game_drawstate { | 1512 | struct game_drawstate { |
1474 | int tilesize, order; | 1513 | int tilesize, order; |
1475 | bool started; | 1514 | bool started; |
@@ -1491,7 +1530,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, | |||
1491 | char buf[80]; | 1530 | char buf[80]; |
1492 | bool shift_or_control = button & (MOD_SHFT | MOD_CTRL); | 1531 | bool shift_or_control = button & (MOD_SHFT | MOD_CTRL); |
1493 | 1532 | ||
1494 | button &= ~MOD_MASK; | 1533 | button = STRIP_BUTTON_MODIFIERS(button); |
1495 | 1534 | ||
1496 | if (x >= 0 && x < ds->order && y >= 0 && y < ds->order && IS_MOUSE_DOWN(button)) { | 1535 | if (x >= 0 && x < ds->order && y >= 0 && y < ds->order && IS_MOUSE_DOWN(button)) { |
1497 | if (oy - COORD(y) > TILE_SIZE && ox - COORD(x) > TILE_SIZE) | 1536 | if (oy - COORD(y) > TILE_SIZE && ox - COORD(x) > TILE_SIZE) |
@@ -1527,7 +1566,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, | |||
1527 | ui->hshow = true; | 1566 | ui->hshow = true; |
1528 | } | 1567 | } |
1529 | ui->hcursor = false; | 1568 | ui->hcursor = false; |
1530 | return UI_UPDATE; | 1569 | return MOVE_UI_UPDATE; |
1531 | } | 1570 | } |
1532 | if (button == RIGHT_BUTTON) { | 1571 | if (button == RIGHT_BUTTON) { |
1533 | /* pencil highlighting for non-filled squares */ | 1572 | /* pencil highlighting for non-filled squares */ |
@@ -1541,7 +1580,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, | |||
1541 | ui->hshow = true; | 1580 | ui->hshow = true; |
1542 | } | 1581 | } |
1543 | ui->hcursor = false; | 1582 | ui->hcursor = false; |
1544 | return UI_UPDATE; | 1583 | return MOVE_UI_UPDATE; |
1545 | } | 1584 | } |
1546 | } | 1585 | } |
1547 | 1586 | ||
@@ -1549,7 +1588,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, | |||
1549 | if (shift_or_control) { | 1588 | if (shift_or_control) { |
1550 | int nx = ui->hx, ny = ui->hy, i; | 1589 | int nx = ui->hx, ny = ui->hy, i; |
1551 | bool self; | 1590 | bool self; |
1552 | move_cursor(button, &nx, &ny, ds->order, ds->order, false); | 1591 | move_cursor(button, &nx, &ny, ds->order, ds->order, false, NULL); |
1553 | ui->hshow = true; | 1592 | ui->hshow = true; |
1554 | ui->hcursor = true; | 1593 | ui->hcursor = true; |
1555 | 1594 | ||
@@ -1557,12 +1596,12 @@ static char *interpret_move(const game_state *state, game_ui *ui, | |||
1557 | ny != ui->hy + adjthan[i].dy); ++i); | 1596 | ny != ui->hy + adjthan[i].dy); ++i); |
1558 | 1597 | ||
1559 | if (i == 4) | 1598 | if (i == 4) |
1560 | return UI_UPDATE; /* invalid direction, i.e. out of | 1599 | return MOVE_UI_UPDATE; /* invalid direction, i.e. out of |
1561 | * the board */ | 1600 | * the board */ |
1562 | 1601 | ||
1563 | if (!(GRID(state, flags, ui->hx, ui->hy) & adjthan[i].f || | 1602 | if (!(GRID(state, flags, ui->hx, ui->hy) & adjthan[i].f || |
1564 | GRID(state, flags, nx, ny ) & adjthan[i].fo)) | 1603 | GRID(state, flags, nx, ny ) & adjthan[i].fo)) |
1565 | return UI_UPDATE; /* no clue to toggle */ | 1604 | return MOVE_UI_UPDATE; /* no clue to toggle */ |
1566 | 1605 | ||
1567 | if (state->mode == MODE_ADJACENT) | 1606 | if (state->mode == MODE_ADJACENT) |
1568 | self = (adjthan[i].dx >= 0 && adjthan[i].dy >= 0); | 1607 | self = (adjthan[i].dx >= 0 && adjthan[i].dy >= 0); |
@@ -1570,24 +1609,23 @@ static char *interpret_move(const game_state *state, game_ui *ui, | |||
1570 | self = (GRID(state, flags, ui->hx, ui->hy) & adjthan[i].f); | 1609 | self = (GRID(state, flags, ui->hx, ui->hy) & adjthan[i].f); |
1571 | 1610 | ||
1572 | if (self) | 1611 | if (self) |
1573 | sprintf(buf, "F%d,%d,%d", ui->hx, ui->hy, | 1612 | sprintf(buf, "F%d,%d,%u", ui->hx, ui->hy, |
1574 | ADJ_TO_SPENT(adjthan[i].f)); | 1613 | ADJ_TO_SPENT(adjthan[i].f)); |
1575 | else | 1614 | else |
1576 | sprintf(buf, "F%d,%d,%d", nx, ny, | 1615 | sprintf(buf, "F%d,%d,%u", nx, ny, |
1577 | ADJ_TO_SPENT(adjthan[i].fo)); | 1616 | ADJ_TO_SPENT(adjthan[i].fo)); |
1578 | 1617 | ||
1579 | return dupstr(buf); | 1618 | return dupstr(buf); |
1580 | } else { | 1619 | } else { |
1581 | move_cursor(button, &ui->hx, &ui->hy, ds->order, ds->order, false); | ||
1582 | ui->hshow = true; | ||
1583 | ui->hcursor = true; | 1620 | ui->hcursor = true; |
1584 | return UI_UPDATE; | 1621 | return move_cursor(button, &ui->hx, &ui->hy, ds->order, ds->order, |
1622 | false, &ui->hshow); | ||
1585 | } | 1623 | } |
1586 | } | 1624 | } |
1587 | if (ui->hshow && IS_CURSOR_SELECT(button)) { | 1625 | if (ui->hshow && IS_CURSOR_SELECT(button)) { |
1588 | ui->hpencil = !ui->hpencil; | 1626 | ui->hpencil = !ui->hpencil; |
1589 | ui->hcursor = true; | 1627 | ui->hcursor = true; |
1590 | return UI_UPDATE; | 1628 | return MOVE_UI_UPDATE; |
1591 | } | 1629 | } |
1592 | 1630 | ||
1593 | n = c2n(button, state->order); | 1631 | n = c2n(button, state->order); |
@@ -1604,11 +1642,37 @@ static char *interpret_move(const game_state *state, game_ui *ui, | |||
1604 | if (ui->hpencil && GRID(state, nums, ui->hx, ui->hy) > 0) | 1642 | if (ui->hpencil && GRID(state, nums, ui->hx, ui->hy) > 0) |
1605 | return NULL; /* can't change hints on filled square (!) */ | 1643 | return NULL; /* can't change hints on filled square (!) */ |
1606 | 1644 | ||
1645 | /* | ||
1646 | * If you ask to fill a square with what it already contains, | ||
1647 | * or blank it when it's already empty, that has no effect... | ||
1648 | */ | ||
1649 | if ((!ui->hpencil || n == 0) && | ||
1650 | GRID(state, nums, ui->hx, ui->hy) == n) { | ||
1651 | bool anypencil = false; | ||
1652 | int i; | ||
1653 | for (i = 0; i < state->order; i++) | ||
1654 | anypencil = anypencil || HINT(state, ui->hx, ui->hy, i); | ||
1655 | if (!anypencil) { | ||
1656 | /* ... expect to remove the cursor in mouse mode. */ | ||
1657 | if (!ui->hcursor) { | ||
1658 | ui->hshow = false; | ||
1659 | return MOVE_UI_UPDATE; | ||
1660 | } | ||
1661 | return NULL; | ||
1662 | } | ||
1663 | } | ||
1607 | 1664 | ||
1608 | sprintf(buf, "%c%d,%d,%d", | 1665 | sprintf(buf, "%c%d,%d,%d", |
1609 | (char)(ui->hpencil && n > 0 ? 'P' : 'R'), ui->hx, ui->hy, n); | 1666 | (char)(ui->hpencil && n > 0 ? 'P' : 'R'), ui->hx, ui->hy, n); |
1610 | 1667 | ||
1611 | if (!ui->hcursor) ui->hshow = false; | 1668 | /* |
1669 | * Hide the highlight after a keypress, if it was mouse- | ||
1670 | * generated. Also, don't hide it if this move has changed | ||
1671 | * pencil marks and the user preference says not to hide the | ||
1672 | * highlight in that situation. | ||
1673 | */ | ||
1674 | if (!ui->hcursor && !(ui->hpencil && ui->pencil_keep_highlight)) | ||
1675 | ui->hshow = false; | ||
1612 | 1676 | ||
1613 | return dupstr(buf); | 1677 | return dupstr(buf); |
1614 | } | 1678 | } |
@@ -1624,7 +1688,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, | |||
1624 | static game_state *execute_move(const game_state *state, const char *move) | 1688 | static game_state *execute_move(const game_state *state, const char *move) |
1625 | { | 1689 | { |
1626 | game_state *ret = NULL; | 1690 | game_state *ret = NULL; |
1627 | int x, y, n, i, rc; | 1691 | int x, y, n, i; |
1628 | 1692 | ||
1629 | debug(("execute_move: %s", move)); | 1693 | debug(("execute_move: %s", move)); |
1630 | 1694 | ||
@@ -1649,7 +1713,7 @@ static game_state *execute_move(const game_state *state, const char *move) | |||
1649 | const char *p; | 1713 | const char *p; |
1650 | 1714 | ||
1651 | ret = dup_game(state); | 1715 | ret = dup_game(state); |
1652 | ret->completed = ret->cheated = true; | 1716 | ret->cheated = true; |
1653 | 1717 | ||
1654 | p = move+1; | 1718 | p = move+1; |
1655 | for (i = 0; i < state->order*state->order; i++) { | 1719 | for (i = 0; i < state->order*state->order; i++) { |
@@ -1660,8 +1724,8 @@ static game_state *execute_move(const game_state *state, const char *move) | |||
1660 | p++; | 1724 | p++; |
1661 | } | 1725 | } |
1662 | if (*p) goto badmove; | 1726 | if (*p) goto badmove; |
1663 | rc = check_complete(ret->nums, ret, true); | 1727 | if (!ret->completed && check_complete(ret->nums, ret, true) > 0) |
1664 | assert(rc > 0); | 1728 | ret->completed = true; |
1665 | return ret; | 1729 | return ret; |
1666 | } else if (move[0] == 'M') { | 1730 | } else if (move[0] == 'M') { |
1667 | ret = dup_game(state); | 1731 | ret = dup_game(state); |
@@ -1678,7 +1742,8 @@ static game_state *execute_move(const game_state *state, const char *move) | |||
1678 | check_complete(ret->nums, ret, true); | 1742 | check_complete(ret->nums, ret, true); |
1679 | return ret; | 1743 | return ret; |
1680 | } else if (move[0] == 'F' && sscanf(move+1, "%d,%d,%d", &x, &y, &n) == 3 && | 1744 | } else if (move[0] == 'F' && sscanf(move+1, "%d,%d,%d", &x, &y, &n) == 3 && |
1681 | x >= 0 && x < state->order && y >= 0 && y < state->order) { | 1745 | x >= 0 && x < state->order && y >= 0 && y < state->order && |
1746 | (n & ~F_SPENT_MASK) == 0) { | ||
1682 | ret = dup_game(state); | 1747 | ret = dup_game(state); |
1683 | GRID(ret, flags, x, y) ^= n; | 1748 | GRID(ret, flags, x, y) ^= n; |
1684 | return ret; | 1749 | return ret; |
@@ -1696,7 +1761,7 @@ badmove: | |||
1696 | #define DRAW_SIZE (TILE_SIZE*ds->order + GAP_SIZE*(ds->order-1) + BORDER*2) | 1761 | #define DRAW_SIZE (TILE_SIZE*ds->order + GAP_SIZE*(ds->order-1) + BORDER*2) |
1697 | 1762 | ||
1698 | static void game_compute_size(const game_params *params, int tilesize, | 1763 | static void game_compute_size(const game_params *params, int tilesize, |
1699 | int *x, int *y) | 1764 | const game_ui *ui, int *x, int *y) |
1700 | { | 1765 | { |
1701 | /* Ick: fake up `ds->tilesize' for macro expansion purposes */ | 1766 | /* Ick: fake up `ds->tilesize' for macro expansion purposes */ |
1702 | struct { int tilesize, order; } ads, *ds = &ads; | 1767 | struct { int tilesize, order; } ads, *ds = &ads; |
@@ -1779,18 +1844,18 @@ static void draw_gt(drawing *dr, int ox, int oy, | |||
1779 | { | 1844 | { |
1780 | int coords[12]; | 1845 | int coords[12]; |
1781 | int xdx = (dx1+dx2 ? 0 : 1), xdy = (dx1+dx2 ? 1 : 0); | 1846 | int xdx = (dx1+dx2 ? 0 : 1), xdy = (dx1+dx2 ? 1 : 0); |
1782 | coords[0] = ox + xdx + dx1; | 1847 | coords[0] = ox + xdx; |
1783 | coords[1] = oy + xdy + dy1; | 1848 | coords[1] = oy + xdy; |
1784 | coords[2] = ox + xdx + dx1 + dx2; | 1849 | coords[2] = ox + xdx + dx1; |
1785 | coords[3] = oy + xdy + dy1 + dy2; | 1850 | coords[3] = oy + xdy + dy1; |
1786 | coords[4] = ox - xdx + dx1 + dx2; | 1851 | coords[4] = ox + xdx + dx1 + dx2; |
1787 | coords[5] = oy - xdy + dy1 + dy2; | 1852 | coords[5] = oy + xdy + dy1 + dy2; |
1788 | coords[6] = ox - xdx + dx1; | 1853 | coords[6] = ox - xdx + dx1 + dx2; |
1789 | coords[7] = oy - xdy + dy1; | 1854 | coords[7] = oy - xdy + dy1 + dy2; |
1790 | coords[8] = ox - xdx; | 1855 | coords[8] = ox - xdx + dx1; |
1791 | coords[9] = oy - xdy; | 1856 | coords[9] = oy - xdy + dy1; |
1792 | coords[10] = ox + xdx; | 1857 | coords[10] = ox - xdx; |
1793 | coords[11] = oy + xdy; | 1858 | coords[11] = oy - xdy; |
1794 | draw_polygon(dr, coords, 6, col, col); | 1859 | draw_polygon(dr, coords, 6, col, col); |
1795 | } | 1860 | } |
1796 | 1861 | ||
@@ -2059,22 +2124,19 @@ static int game_status(const game_state *state) | |||
2059 | return state->completed ? +1 : 0; | 2124 | return state->completed ? +1 : 0; |
2060 | } | 2125 | } |
2061 | 2126 | ||
2062 | static bool game_timing_state(const game_state *state, game_ui *ui) | 2127 | static void game_print_size(const game_params *params, const game_ui *ui, |
2063 | { | 2128 | float *x, float *y) |
2064 | return true; | ||
2065 | } | ||
2066 | |||
2067 | static void game_print_size(const game_params *params, float *x, float *y) | ||
2068 | { | 2129 | { |
2069 | int pw, ph; | 2130 | int pw, ph; |
2070 | 2131 | ||
2071 | /* 10mm squares by default, roughly the same as Grauniad. */ | 2132 | /* 10mm squares by default, roughly the same as Grauniad. */ |
2072 | game_compute_size(params, 1000, &pw, &ph); | 2133 | game_compute_size(params, 1000, ui, &pw, &ph); |
2073 | *x = pw / 100.0F; | 2134 | *x = pw / 100.0F; |
2074 | *y = ph / 100.0F; | 2135 | *y = ph / 100.0F; |
2075 | } | 2136 | } |
2076 | 2137 | ||
2077 | static void game_print(drawing *dr, const game_state *state, int tilesize) | 2138 | static void game_print(drawing *dr, const game_state *state, const game_ui *ui, |
2139 | int tilesize) | ||
2078 | { | 2140 | { |
2079 | int ink = print_mono_colour(dr, 0); | 2141 | int ink = print_mono_colour(dr, 0); |
2080 | int x, y, o = state->order, ox, oy, n; | 2142 | int x, y, o = state->order, ox, oy, n; |
@@ -2133,12 +2195,14 @@ const struct game thegame = { | |||
2133 | free_game, | 2195 | free_game, |
2134 | true, solve_game, | 2196 | true, solve_game, |
2135 | true, game_can_format_as_text_now, game_text_format, | 2197 | true, game_can_format_as_text_now, game_text_format, |
2198 | get_prefs, set_prefs, | ||
2136 | new_ui, | 2199 | new_ui, |
2137 | free_ui, | 2200 | free_ui, |
2138 | encode_ui, | 2201 | NULL, /* encode_ui */ |
2139 | decode_ui, | 2202 | NULL, /* decode_ui */ |
2140 | game_request_keys, | 2203 | game_request_keys, |
2141 | game_changed_state, | 2204 | game_changed_state, |
2205 | current_key_label, | ||
2142 | interpret_move, | 2206 | interpret_move, |
2143 | execute_move, | 2207 | execute_move, |
2144 | PREFERRED_TILE_SIZE, game_compute_size, game_set_size, | 2208 | PREFERRED_TILE_SIZE, game_compute_size, game_set_size, |
@@ -2152,7 +2216,7 @@ const struct game thegame = { | |||
2152 | game_status, | 2216 | game_status, |
2153 | true, false, game_print_size, game_print, | 2217 | true, false, game_print_size, game_print, |
2154 | false, /* wants_statusbar */ | 2218 | false, /* wants_statusbar */ |
2155 | false, game_timing_state, | 2219 | false, NULL, /* timing_state */ |
2156 | REQUIRE_RBUTTON | REQUIRE_NUMPAD, /* flags */ | 2220 | REQUIRE_RBUTTON | REQUIRE_NUMPAD, /* flags */ |
2157 | }; | 2221 | }; |
2158 | 2222 | ||
@@ -2165,7 +2229,7 @@ const struct game thegame = { | |||
2165 | #include <time.h> | 2229 | #include <time.h> |
2166 | #include <stdarg.h> | 2230 | #include <stdarg.h> |
2167 | 2231 | ||
2168 | const char *quis = NULL; | 2232 | static const char *quis = NULL; |
2169 | 2233 | ||
2170 | #if 0 /* currently unused */ | 2234 | #if 0 /* currently unused */ |
2171 | 2235 | ||
@@ -2233,13 +2297,14 @@ static int solve(game_params *p, char *desc, int debug) | |||
2233 | solver_show_working = debug; | 2297 | solver_show_working = debug; |
2234 | game_debug(state); | 2298 | game_debug(state); |
2235 | 2299 | ||
2236 | latin_solver_alloc(&solver, state->nums, state->order); | 2300 | if (latin_solver_alloc(&solver, state->nums, state->order)) |
2237 | 2301 | diff = latin_solver_main(&solver, DIFF_RECURSIVE, | |
2238 | diff = latin_solver_main(&solver, DIFF_RECURSIVE, | 2302 | DIFF_LATIN, DIFF_SET, DIFF_EXTREME, |
2239 | DIFF_LATIN, DIFF_SET, DIFF_EXTREME, | 2303 | DIFF_EXTREME, DIFF_RECURSIVE, |
2240 | DIFF_EXTREME, DIFF_RECURSIVE, | 2304 | unequal_solvers, unequal_valid, ctx, |
2241 | unequal_solvers, unequal_valid, ctx, | 2305 | clone_ctx, free_ctx); |
2242 | clone_ctx, free_ctx); | 2306 | else |
2307 | diff = DIFF_IMPOSSIBLE; | ||
2243 | 2308 | ||
2244 | free_ctx(ctx); | 2309 | free_ctx(ctx); |
2245 | 2310 | ||