summaryrefslogtreecommitdiff
path: root/apps/plugins/puzzles/src/guess.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/puzzles/src/guess.c')
-rw-r--r--apps/plugins/puzzles/src/guess.c221
1 files changed, 129 insertions, 92 deletions
diff --git a/apps/plugins/puzzles/src/guess.c b/apps/plugins/puzzles/src/guess.c
index a501579442..5c5f941230 100644
--- a/apps/plugins/puzzles/src/guess.c
+++ b/apps/plugins/puzzles/src/guess.c
@@ -7,7 +7,11 @@
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#ifdef NO_TGMATH_H
11# include <math.h>
12#else
13# include <tgmath.h>
14#endif
11 15
12#include "puzzles.h" 16#include "puzzles.h"
13 17
@@ -35,6 +39,11 @@ typedef struct pegrow {
35 int *pegs; /* 0 is 'empty' */ 39 int *pegs; /* 0 is 'empty' */
36 int *feedback; /* may well be unused */ 40 int *feedback; /* may well be unused */
37} *pegrow; 41} *pegrow;
42/* Pegs can have these flags OR'ed into them. */
43#define PEG_CURSOR 0x1000
44#define PEG_HOLD 0x2000
45#define PEG_LABELLED 0x4000
46#define PEG_FLAGS (PEG_CURSOR | PEG_HOLD | PEG_LABELLED)
38 47
39struct game_state { 48struct game_state {
40 game_params params; 49 game_params params;
@@ -88,13 +97,7 @@ static bool game_fetch_preset(int i, char **name, game_params **params)
88 return false; 97 return false;
89 98
90 *name = dupstr(guess_presets[i].name); 99 *name = dupstr(guess_presets[i].name);
91 /* 100 *params = dup_params(&guess_presets[i].params);
92 * get round annoying const issues
93 */
94 {
95 game_params tmp = guess_presets[i].params;
96 *params = dup_params(&tmp);
97 }
98 101
99 return true; 102 return true;
100} 103}
@@ -365,16 +368,6 @@ static char *solve_game(const game_state *state, const game_state *currstate,
365 return dupstr("S"); 368 return dupstr("S");
366} 369}
367 370
368static bool game_can_format_as_text_now(const game_params *params)
369{
370 return true;
371}
372
373static char *game_text_format(const game_state *state)
374{
375 return NULL;
376}
377
378static bool is_markable(const game_params *params, pegrow pegs) 371static bool is_markable(const game_params *params, pegrow pegs)
379{ 372{
380 int i, nset = 0, nrequired; 373 int i, nset = 0, nrequired;
@@ -386,6 +379,7 @@ static bool is_markable(const game_params *params, pegrow pegs)
386 for (i = 0; i < params->npegs; i++) { 379 for (i = 0; i < params->npegs; i++) {
387 int c = pegs->pegs[i]; 380 int c = pegs->pegs[i];
388 if (c > 0) { 381 if (c > 0) {
382 assert(c <= params->ncolours);
389 colcount->pegs[c-1]++; 383 colcount->pegs[c-1]++;
390 nset++; 384 nset++;
391 } 385 }
@@ -414,7 +408,7 @@ struct game_ui {
414 int drag_col, drag_x, drag_y; /* x and y are *center* of peg! */ 408 int drag_col, drag_x, drag_y; /* x and y are *center* of peg! */
415 int drag_opeg; /* peg index, if dragged from a peg (from current guess), otherwise -1 */ 409 int drag_opeg; /* peg index, if dragged from a peg (from current guess), otherwise -1 */
416 410
417 bool show_labels; /* label the colours with letters */ 411 bool show_labels; /* label the colours with numbers */
418 pegrow hint; 412 pegrow hint;
419}; 413};
420 414
@@ -422,19 +416,45 @@ static game_ui *new_ui(const game_state *state)
422{ 416{
423 game_ui *ui = snew(game_ui); 417 game_ui *ui = snew(game_ui);
424 memset(ui, 0, sizeof(game_ui)); 418 memset(ui, 0, sizeof(game_ui));
425 ui->params = state->params; /* structure copy */ 419 if (state != NULL) {
426 ui->curr_pegs = new_pegrow(state->params.npegs); 420 ui->params = state->params; /* structure copy */
427 ui->holds = snewn(state->params.npegs, bool); 421 ui->curr_pegs = new_pegrow(state->params.npegs);
428 memset(ui->holds, 0, sizeof(bool)*state->params.npegs); 422 ui->holds = snewn(state->params.npegs, bool);
423 memset(ui->holds, 0, sizeof(bool)*state->params.npegs);
424 }
425 ui->display_cur = getenv_bool("PUZZLES_SHOW_CURSOR", false);
429 ui->drag_opeg = -1; 426 ui->drag_opeg = -1;
430 return ui; 427 return ui;
431} 428}
432 429
430static config_item *get_prefs(game_ui *ui)
431{
432 config_item *ret;
433
434 ret = snewn(2, config_item);
435
436 ret[0].name = "Label colours with numbers";
437 ret[0].kw = "show-labels";
438 ret[0].type = C_BOOLEAN;
439 ret[0].u.boolean.bval = ui->show_labels;
440
441 ret[1].name = NULL;
442 ret[1].type = C_END;
443
444 return ret;
445}
446
447static void set_prefs(game_ui *ui, const config_item *cfg)
448{
449 ui->show_labels = cfg[0].u.boolean.bval;
450}
451
433static void free_ui(game_ui *ui) 452static void free_ui(game_ui *ui)
434{ 453{
435 if (ui->hint) 454 if (ui->hint)
436 free_pegrow(ui->hint); 455 free_pegrow(ui->hint);
437 free_pegrow(ui->curr_pegs); 456 if (ui->curr_pegs)
457 free_pegrow(ui->curr_pegs);
438 sfree(ui->holds); 458 sfree(ui->holds);
439 sfree(ui); 459 sfree(ui);
440} 460}
@@ -462,12 +482,16 @@ static char *encode_ui(const game_ui *ui)
462 return sresize(ret, p - ret, char); 482 return sresize(ret, p - ret, char);
463} 483}
464 484
465static void decode_ui(game_ui *ui, const char *encoding) 485static void decode_ui(game_ui *ui, const char *encoding,
486 const game_state *state)
466{ 487{
467 int i; 488 int i;
468 const char *p = encoding; 489 const char *p = encoding;
469 for (i = 0; i < ui->curr_pegs->npegs; i++) { 490 for (i = 0; i < ui->curr_pegs->npegs; i++) {
470 ui->curr_pegs->pegs[i] = atoi(p); 491 ui->curr_pegs->pegs[i] = atoi(p);
492 if (ui->curr_pegs->pegs[i] < 0 ||
493 ui->curr_pegs->pegs[i] > ui->params.ncolours)
494 ui->curr_pegs->pegs[i] = 0; /* Remove invalid pegs. */
471 while (*p && isdigit((unsigned char)*p)) p++; 495 while (*p && isdigit((unsigned char)*p)) p++;
472 if (*p == '_') { 496 if (*p == '_') {
473 /* NB: old versions didn't store holds */ 497 /* NB: old versions didn't store holds */
@@ -507,7 +531,20 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate,
507 ui->markable = is_markable(&newstate->params, ui->curr_pegs); 531 ui->markable = is_markable(&newstate->params, ui->curr_pegs);
508 /* Clean up cursor position */ 532 /* Clean up cursor position */
509 if (!ui->markable && ui->peg_cur == newstate->solution->npegs) 533 if (!ui->markable && ui->peg_cur == newstate->solution->npegs)
510 ui->peg_cur--; 534 ui->peg_cur = 0;
535}
536
537static const char *current_key_label(const game_ui *ui,
538 const game_state *state, int button)
539{
540 if (state->solved) return "";
541 if (button == CURSOR_SELECT) {
542 if (ui->peg_cur == state->params.npegs) return "Submit";
543 return "Place";
544 }
545 if (button == CURSOR_SELECT2 && ui->peg_cur != state->params.npegs)
546 return "Hold";
547 return "";
511} 548}
512 549
513#define PEGSZ (ds->pegsz) 550#define PEGSZ (ds->pegsz)
@@ -700,7 +737,11 @@ static void compute_hint(const game_state *state, game_ui *ui)
700 for (j = 0; j < state->params.npegs; ++j) 737 for (j = 0; j < state->params.npegs; ++j)
701 if (state->guesses[i]->pegs[j] > maxcolour) 738 if (state->guesses[i]->pegs[j] > maxcolour)
702 maxcolour = state->guesses[i]->pegs[j]; 739 maxcolour = state->guesses[i]->pegs[j];
703 maxcolour = min(maxcolour + 1, state->params.ncolours); 740 if (state->params.allow_multiple)
741 maxcolour = min(maxcolour + 1, state->params.ncolours);
742 else
743 maxcolour = min(maxcolour + state->params.npegs,
744 state->params.ncolours);
704 745
705increase_mincolour: 746increase_mincolour:
706 for (i = 0; i < state->next_go; ++i) { 747 for (i = 0; i < state->next_go; ++i) {
@@ -722,6 +763,7 @@ increase_mincolour:
722 } 763 }
723 764
724 while (ui->hint->pegs[0] <= state->params.ncolours) { 765 while (ui->hint->pegs[0] <= state->params.ncolours) {
766 if (!is_markable(&state->params, ui->hint)) goto increment_pegrow;
725 for (i = 0; i < state->next_go; ++i) { 767 for (i = 0; i < state->next_go; ++i) {
726 mark_pegs(ui->hint, state->guesses[i], maxcolour); 768 mark_pegs(ui->hint, state->guesses[i], maxcolour);
727 for (j = 0; j < state->params.npegs; ++j) 769 for (j = 0; j < state->params.npegs; ++j)
@@ -777,7 +819,7 @@ static char *interpret_move(const game_state *from, game_ui *ui,
777 */ 819 */
778 if (button == 'l' || button == 'L') { 820 if (button == 'l' || button == 'L') {
779 ui->show_labels = !ui->show_labels; 821 ui->show_labels = !ui->show_labels;
780 return UI_UPDATE; 822 return MOVE_UI_UPDATE;
781 } 823 }
782 824
783 if (from->solved) return NULL; 825 if (from->solved) return NULL;
@@ -834,13 +876,13 @@ static char *interpret_move(const game_state *from, game_ui *ui,
834 ui->drag_y = y; 876 ui->drag_y = y;
835 debug(("Start dragging, col = %d, (%d,%d)", 877 debug(("Start dragging, col = %d, (%d,%d)",
836 ui->drag_col, ui->drag_x, ui->drag_y)); 878 ui->drag_col, ui->drag_x, ui->drag_y));
837 ret = UI_UPDATE; 879 ret = MOVE_UI_UPDATE;
838 } 880 }
839 } else if (button == LEFT_DRAG && ui->drag_col) { 881 } else if (button == LEFT_DRAG && ui->drag_col) {
840 ui->drag_x = x; 882 ui->drag_x = x;
841 ui->drag_y = y; 883 ui->drag_y = y;
842 debug(("Keep dragging, (%d,%d)", ui->drag_x, ui->drag_y)); 884 debug(("Keep dragging, (%d,%d)", ui->drag_x, ui->drag_y));
843 ret = UI_UPDATE; 885 ret = MOVE_UI_UPDATE;
844 } else if (button == LEFT_RELEASE && ui->drag_col) { 886 } else if (button == LEFT_RELEASE && ui->drag_col) {
845 if (over_guess > -1) { 887 if (over_guess > -1) {
846 debug(("Dropping colour %d onto guess peg %d", 888 debug(("Dropping colour %d onto guess peg %d",
@@ -857,13 +899,13 @@ static char *interpret_move(const game_state *from, game_ui *ui,
857 ui->drag_opeg = -1; 899 ui->drag_opeg = -1;
858 ui->display_cur = false; 900 ui->display_cur = false;
859 debug(("Stop dragging.")); 901 debug(("Stop dragging."));
860 ret = UI_UPDATE; 902 ret = MOVE_UI_UPDATE;
861 } else if (button == RIGHT_BUTTON) { 903 } else if (button == RIGHT_BUTTON) {
862 if (over_guess > -1) { 904 if (over_guess > -1) {
863 /* we use ths feedback in the game_ui to signify 905 /* we use ths feedback in the game_ui to signify
864 * 'carry this peg to the next guess as well'. */ 906 * 'carry this peg to the next guess as well'. */
865 ui->holds[over_guess] ^= 1; 907 ui->holds[over_guess] ^= 1;
866 ret = UI_UPDATE; 908 ret = MOVE_UI_UPDATE;
867 } 909 }
868 } else if (button == LEFT_RELEASE && over_hint && ui->markable) { 910 } else if (button == LEFT_RELEASE && over_hint && ui->markable) {
869 /* NB this won't trigger if on the end of a drag; that's on 911 /* NB this won't trigger if on the end of a drag; that's on
@@ -872,44 +914,47 @@ static char *interpret_move(const game_state *from, game_ui *ui,
872 } 914 }
873 915
874 /* keyboard input */ 916 /* keyboard input */
875 if (button == CURSOR_UP || button == CURSOR_DOWN) { 917 if (IS_CURSOR_MOVE(button)) {
876 ui->display_cur = true;
877 if (button == CURSOR_DOWN && (ui->colour_cur+1) < from->params.ncolours)
878 ui->colour_cur++;
879 if (button == CURSOR_UP && ui->colour_cur > 0)
880 ui->colour_cur--;
881 ret = UI_UPDATE;
882 } else if (button == 'h' || button == 'H' || button == '?') {
883 compute_hint(from, ui);
884 ret = UI_UPDATE;
885 } else if (button == CURSOR_LEFT || button == CURSOR_RIGHT) {
886 int maxcur = from->params.npegs; 918 int maxcur = from->params.npegs;
887 if (ui->markable) maxcur++; 919 if (ui->markable) maxcur++;
888 920
889 ui->display_cur = true; 921 ret = move_cursor(button, &ui->peg_cur, &ui->colour_cur,
890 if (button == CURSOR_RIGHT && (ui->peg_cur+1) < maxcur) 922 maxcur, from->params.ncolours,
891 ui->peg_cur++; 923 false, &ui->display_cur);
892 if (button == CURSOR_LEFT && ui->peg_cur > 0) 924 } else if (button == 'h' || button == 'H' || button == '?') {
893 ui->peg_cur--; 925 compute_hint(from, ui);
894 ret = UI_UPDATE; 926 ret = MOVE_UI_UPDATE;
895 } else if (IS_CURSOR_SELECT(button)) { 927 } else if (button == CURSOR_SELECT) {
896 ui->display_cur = true; 928 ui->display_cur = true;
897 if (ui->peg_cur == from->params.npegs) { 929 if (ui->peg_cur == from->params.npegs) {
898 ret = encode_move(from, ui); 930 ret = encode_move(from, ui);
899 } else { 931 } else {
900 set_peg(&from->params, ui, ui->peg_cur, ui->colour_cur+1); 932 set_peg(&from->params, ui, ui->peg_cur, ui->colour_cur+1);
901 ret = UI_UPDATE; 933 ret = MOVE_UI_UPDATE;
902 } 934 }
903 } else if (button == 'D' || button == 'd' || button == '\b') { 935 } else if (((button >= '1' && button <= '0' + from->params.ncolours) ||
936 (button == '0' && from->params.ncolours == 10)) &&
937 ui->peg_cur < from->params.npegs) {
904 ui->display_cur = true; 938 ui->display_cur = true;
905 set_peg(&from->params, ui, ui->peg_cur, 0); 939 /* Number keys insert a peg and advance the cursor. */
906 ret = UI_UPDATE; 940 set_peg(&from->params, ui, ui->peg_cur,
941 button == '0' ? 10 : button - '0');
942 if (ui->peg_cur + 1 < from->params.npegs + ui->markable)
943 ui->peg_cur++;
944 ret = MOVE_UI_UPDATE;
945 } else if (button == 'D' || button == 'd' || button == '\b') {
946 if (!ui->display_cur || ui->curr_pegs->pegs[ui->peg_cur] != 0) {
947 ui->display_cur = true;
948 set_peg(&from->params, ui, ui->peg_cur, 0);
949 ret = MOVE_UI_UPDATE;
950 } else
951 ret = MOVE_NO_EFFECT;
907 } else if (button == CURSOR_SELECT2) { 952 } else if (button == CURSOR_SELECT2) {
908 if (ui->peg_cur == from->params.npegs) 953 if (ui->peg_cur == from->params.npegs)
909 return NULL; 954 return NULL;
910 ui->display_cur = true; 955 ui->display_cur = true;
911 ui->holds[ui->peg_cur] ^= 1; 956 ui->holds[ui->peg_cur] ^= 1;
912 ret = UI_UPDATE; 957 ret = MOVE_UI_UPDATE;
913 } 958 }
914 return ret; 959 return ret;
915} 960}
@@ -925,6 +970,8 @@ static game_state *execute_move(const game_state *from, const char *move)
925 ret->solved = -1; 970 ret->solved = -1;
926 return ret; 971 return ret;
927 } else if (move[0] == 'G') { 972 } else if (move[0] == 'G') {
973 /* No guesses are allowed once the game is solved. */
974 if (from->solved) return NULL;
928 p = move+1; 975 p = move+1;
929 976
930 ret = dup_game(from); 977 ret = dup_game(from);
@@ -975,7 +1022,7 @@ static game_state *execute_move(const game_state *from, const char *move)
975#define BORDER 0.5 1022#define BORDER 0.5
976 1023
977static void game_compute_size(const game_params *params, int tilesize, 1024static void game_compute_size(const game_params *params, int tilesize,
978 int *x, int *y) 1025 const game_ui *ui, int *x, int *y)
979{ 1026{
980 double hmul, vmul_c, vmul_g, vmul; 1027 double hmul, vmul_c, vmul_g, vmul;
981 int hintw = (params->npegs+1)/2; 1028 int hintw = (params->npegs+1)/2;
@@ -1019,7 +1066,8 @@ static void game_set_size(drawing *dr, game_drawstate *ds,
1019 guessh = ((ds->pegsz + ds->gapsz) * params->nguesses); /* guesses */ 1066 guessh = ((ds->pegsz + ds->gapsz) * params->nguesses); /* guesses */
1020 guessh += ds->gapsz + ds->pegsz; /* solution */ 1067 guessh += ds->gapsz + ds->pegsz; /* solution */
1021 1068
1022 game_compute_size(params, tilesize, &ds->w, &ds->h); 1069 /* We know we don't need anything from the game_ui we haven't got */
1070 game_compute_size(params, tilesize, NULL, &ds->w, &ds->h);
1023 ds->colx = ds->border; 1071 ds->colx = ds->border;
1024 ds->coly = (ds->h - colh) / 2; 1072 ds->coly = (ds->h - colh) / 2;
1025 1073
@@ -1196,7 +1244,7 @@ static void draw_peg(drawing *dr, game_drawstate *ds, int cx, int cy,
1196 1244
1197 if (labelled && col) { 1245 if (labelled && col) {
1198 char buf[2]; 1246 char buf[2];
1199 buf[0] = 'a'-1 + col; 1247 buf[0] = '0' + (col % 10);
1200 buf[1] = '\0'; 1248 buf[1] = '\0';
1201 draw_text(dr, cx+PEGRAD, cy+PEGRAD, FONT_VARIABLE, PEGRAD, 1249 draw_text(dr, cx+PEGRAD, cy+PEGRAD, FONT_VARIABLE, PEGRAD,
1202 ALIGN_HCENTRE|ALIGN_VCENTRE, COL_FRAME, buf); 1250 ALIGN_HCENTRE|ALIGN_VCENTRE, COL_FRAME, buf);
@@ -1233,23 +1281,25 @@ static void guess_redraw(drawing *dr, game_drawstate *ds, int guess,
1233 for (i = 0; i < dest->npegs; i++) { 1281 for (i = 0; i < dest->npegs; i++) {
1234 scol = src ? src->pegs[i] : 0; 1282 scol = src ? src->pegs[i] : 0;
1235 if (i == cur_col) 1283 if (i == cur_col)
1236 scol |= 0x1000; 1284 scol |= PEG_CURSOR;
1237 if (holds && holds[i]) 1285 if (holds && holds[i])
1238 scol |= 0x2000; 1286 scol |= PEG_HOLD;
1239 if (labelled) 1287 if (labelled)
1240 scol |= 0x4000; 1288 scol |= PEG_LABELLED;
1241 if ((dest->pegs[i] != scol) || force) { 1289 if ((dest->pegs[i] != scol) || force) {
1242 draw_peg(dr, ds, rowx + PEGOFF * i, rowy, false, labelled, 1290 draw_peg(dr, ds, rowx + PEGOFF * i, rowy, false, labelled,
1243 scol &~ 0x7000); 1291 scol &~ PEG_FLAGS);
1292 if (scol & PEG_CURSOR)
1293 draw_cursor(dr, ds, rowx + PEGOFF * i, rowy);
1244 /* 1294 /*
1245 * Hold marker. 1295 * Hold marker.
1246 */ 1296 */
1247 draw_rect(dr, rowx + PEGOFF * i, rowy + PEGSZ + ds->gapsz/2, 1297 if (scol & PEG_HOLD) {
1248 PEGSZ, 2, (scol & 0x2000 ? COL_HOLD : COL_BACKGROUND)); 1298 draw_rect(dr, rowx + PEGOFF * i,
1249 draw_update(dr, rowx + PEGOFF * i, rowy + PEGSZ + ds->gapsz/2, 1299 rowy + PEGSZ + ds->gapsz/2 - 2, PEGSZ, 2, COL_HOLD);
1250 PEGSZ, 2); 1300 }
1251 if (scol & 0x1000) 1301 draw_update(dr, rowx + PEGOFF * i,
1252 draw_cursor(dr, ds, rowx + PEGOFF * i, rowy); 1302 rowy + PEGSZ + ds->gapsz/2 - 2, PEGSZ, 2);
1253 } 1303 }
1254 dest->pegs[i] = scol; 1304 dest->pegs[i] = scol;
1255 } 1305 }
@@ -1276,9 +1326,9 @@ static void hint_redraw(drawing *dr, game_drawstate *ds, int guess,
1276 for (i = 0; i < dest->npegs; i++) { 1326 for (i = 0; i < dest->npegs; i++) {
1277 scol = src ? src->feedback[i] : 0; 1327 scol = src ? src->feedback[i] : 0;
1278 if (i == 0 && cursor) 1328 if (i == 0 && cursor)
1279 scol |= 0x1000; 1329 scol |= PEG_CURSOR;
1280 if (i == 0 && markable) 1330 if (i == 0 && markable)
1281 scol |= 0x2000; 1331 scol |= PEG_HOLD;
1282 if ((scol != dest->feedback[i]) || force) { 1332 if ((scol != dest->feedback[i]) || force) {
1283 need_redraw = true; 1333 need_redraw = true;
1284 } 1334 }
@@ -1349,7 +1399,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds,
1349 new_move = (state->next_go != ds->next_go) || !ds->started; 1399 new_move = (state->next_go != ds->next_go) || !ds->started;
1350 1400
1351 if (!ds->started) { 1401 if (!ds->started) {
1352 draw_rect(dr, 0, 0, ds->w, ds->h, COL_BACKGROUND);
1353 draw_rect(dr, SOLN_OX, SOLN_OY - ds->gapsz - 1, SOLN_W, 2, COL_FRAME); 1402 draw_rect(dr, SOLN_OX, SOLN_OY - ds->gapsz - 1, SOLN_W, 2, COL_FRAME);
1354 draw_update(dr, 0, 0, ds->w, ds->h); 1403 draw_update(dr, 0, 0, ds->w, ds->h);
1355 } 1404 }
@@ -1364,19 +1413,18 @@ static void game_redraw(drawing *dr, game_drawstate *ds,
1364 for (i = 0; i < state->params.ncolours; i++) { 1413 for (i = 0; i < state->params.ncolours; i++) {
1365 int val = i+1; 1414 int val = i+1;
1366 if (ui->display_cur && ui->colour_cur == i) 1415 if (ui->display_cur && ui->colour_cur == i)
1367 val |= 0x1000; 1416 val |= PEG_CURSOR;
1368 if (ui->show_labels) 1417 if (ui->show_labels)
1369 val |= 0x2000; 1418 val |= PEG_HOLD;
1370 if (ds->colours->pegs[i] != val) { 1419 if (ds->colours->pegs[i] != val) {
1371 draw_peg(dr, ds, COL_X(i), COL_Y(i), false, ui->show_labels, i+1); 1420 draw_peg(dr, ds, COL_X(i), COL_Y(i), false, ui->show_labels, i+1);
1372 if (val & 0x1000) 1421 if (val & PEG_CURSOR)
1373 draw_cursor(dr, ds, COL_X(i), COL_Y(i)); 1422 draw_cursor(dr, ds, COL_X(i), COL_Y(i));
1374 ds->colours->pegs[i] = val; 1423 ds->colours->pegs[i] = val;
1375 } 1424 }
1376 } 1425 }
1377 1426
1378 /* draw the guesses (so far) and the hints 1427 /* draw the guesses (so far) and the hints (postponing the
1379 * (in reverse order to avoid trampling holds, and postponing the
1380 * next_go'th to not overrender the top of the circular cursor) */ 1428 * next_go'th to not overrender the top of the circular cursor) */
1381 for (i = state->params.nguesses - 1; i >= 0; i--) { 1429 for (i = state->params.nguesses - 1; i >= 0; i--) {
1382 if (i < state->next_go || state->solved) { 1430 if (i < state->next_go || state->solved) {
@@ -1473,19 +1521,6 @@ static int game_status(const game_state *state)
1473 return state->solved; 1521 return state->solved;
1474} 1522}
1475 1523
1476static bool game_timing_state(const game_state *state, game_ui *ui)
1477{
1478 return true;
1479}
1480
1481static void game_print_size(const game_params *params, float *x, float *y)
1482{
1483}
1484
1485static void game_print(drawing *dr, const game_state *state, int tilesize)
1486{
1487}
1488
1489#ifdef COMBINED 1524#ifdef COMBINED
1490#define thegame guess 1525#define thegame guess
1491#endif 1526#endif
@@ -1506,13 +1541,15 @@ const struct game thegame = {
1506 dup_game, 1541 dup_game,
1507 free_game, 1542 free_game,
1508 true, solve_game, 1543 true, solve_game,
1509 false, game_can_format_as_text_now, game_text_format, 1544 false, NULL, NULL, /* can_format_as_text_now, text_format */
1545 get_prefs, set_prefs,
1510 new_ui, 1546 new_ui,
1511 free_ui, 1547 free_ui,
1512 encode_ui, 1548 encode_ui,
1513 decode_ui, 1549 decode_ui,
1514 NULL, /* game_request_keys */ 1550 NULL, /* game_request_keys */
1515 game_changed_state, 1551 game_changed_state,
1552 current_key_label,
1516 interpret_move, 1553 interpret_move,
1517 execute_move, 1554 execute_move,
1518 PEG_PREFER_SZ, game_compute_size, game_set_size, 1555 PEG_PREFER_SZ, game_compute_size, game_set_size,
@@ -1524,9 +1561,9 @@ const struct game thegame = {
1524 game_flash_length, 1561 game_flash_length,
1525 game_get_cursor_location, 1562 game_get_cursor_location,
1526 game_status, 1563 game_status,
1527 false, false, game_print_size, game_print, 1564 false, false, NULL, NULL, /* print_size, print */
1528 false, /* wants_statusbar */ 1565 false, /* wants_statusbar */
1529 false, game_timing_state, 1566 false, NULL, /* timing_state */
1530 0, /* flags */ 1567 0, /* flags */
1531}; 1568};
1532 1569