shithub: puzzles

Download patch

ref: f0750894ff6a23c22a14a82d405ace5b99318bd5
parent: c3285318e60cb78d190725aba3675325921afdb3
author: Kevin Lyles <kevinlyles@gmail.com>
date: Mon May 25 15:46:24 EDT 2015

Undead: you can now mark clues as done

--- a/html/undead.html
+++ b/html/undead.html
@@ -17,3 +17,6 @@
 Right-click in a square and then type a letter to add or remove the
 monster as a pencil mark, indicating monsters that you think
 <em>might</em> go in that square.
+<p>
+Left-click on a clue to mark it as done (grey it out). To unmark a
+clue as done, left-click on it again.
--- a/puzzles.but
+++ b/puzzles.but
@@ -3054,6 +3054,9 @@
 you can press \q{A} to toggle between showing the monsters as monsters or
 showing them as letters.
 
+Left-clicking a clue will mark it as done (grey it out), or unmark it
+if it is already marked.
+
 (All the actions described in \k{common-actions} are also available.)
 
 \H{undead-parameters} \I{parameters, for Undead}Undead parameters
--- a/undead.c
+++ b/undead.c
@@ -49,6 +49,7 @@
     COL_GHOST,
     COL_ZOMBIE,
     COL_VAMPIRE,
+    COL_DONE,
     NCOLOURS
 };
 
@@ -237,6 +238,7 @@
     unsigned char *pencils;
     unsigned char *cell_errors;
     unsigned char *hint_errors;
+    unsigned char *hints_done;
     unsigned char count_errors[3];
     int solved;
     int cheated;
@@ -289,6 +291,9 @@
     state->hint_errors = snewn(2*state->common->num_paths, unsigned char);
     for (i=0;i<2*state->common->num_paths;i++)
         state->hint_errors[i] = FALSE;
+    state->hints_done = snewn(2 * state->common->num_paths, unsigned char);
+    memset(state->hints_done, 0,
+           2 * state->common->num_paths * sizeof(unsigned char));
     for (i=0;i<3;i++)
         state->count_errors[i] = FALSE;
 
@@ -332,6 +337,13 @@
     }
     else ret->hint_errors = NULL;
 
+    if (state->hints_done != NULL) {
+        ret->hints_done = snewn(2 * state->common->num_paths, unsigned char);
+        memcpy(ret->hints_done, state->hints_done,
+               2 * state->common->num_paths * sizeof(unsigned char));
+    }
+    else ret->hints_done = NULL;
+
     ret->count_errors[0] = state->count_errors[0];
     ret->count_errors[1] = state->count_errors[1];
     ret->count_errors[2] = state->count_errors[2];
@@ -358,6 +370,7 @@
         if (state->common->fixed != NULL) sfree(state->common->fixed);
         sfree(state->common);
     }
+    if (state->hints_done != NULL) sfree(state->hints_done);
     if (state->hint_errors != NULL) sfree(state->hint_errors);
     if (state->cell_errors != NULL) sfree(state->cell_errors);
     if (state->pencils != NULL) sfree(state->pencils);
@@ -1662,6 +1675,7 @@
     unsigned char count_errors[3];
     unsigned char *cell_errors;
     unsigned char *hint_errors;
+    unsigned char *hints_done;
 
     int hx, hy, hshow, hpencil; /* as for game_ui. */
     int hflash;
@@ -1668,6 +1682,33 @@
     int ascii;
 };
 
+static int is_clue(const game_state *state, int x, int y)
+{
+    int h = state->common->params.h, w = state->common->params.w;
+
+    if (((x == 0 || x == w + 1) && y > 0 && y <= h) ||
+        ((y == 0 || y == h + 1) && x > 0 && x <= w))
+        return TRUE;
+
+    return FALSE;
+}
+
+static int clue_index(const game_state *state, int x, int y)
+{
+    int h = state->common->params.h, w = state->common->params.w;
+
+    if (y == 0)
+        return x - 1;
+    else if (x == w + 1)
+        return w + y - 1;
+    else if (y == h + 1)
+        return 2 * w + h - x;
+    else if (x == 0)
+        return 2 * (w + h) - y;
+
+    return -1;
+}
+
 #define TILESIZE (ds->tilesize)
 #define BORDER (TILESIZE/4)
 
@@ -1818,6 +1859,11 @@
                 }
             }
         }
+    } else if (button == LEFT_BUTTON) {
+        if (is_clue(state, gx, gy)) {
+            sprintf(buf, "D%d,%d", gx, gy);
+            return dupstr(buf);
+        }
     }
 
     return NULL;
@@ -1942,7 +1988,7 @@
 
 static game_state *execute_move(const game_state *state, const char *move)
 {
-    int x,n,p,i;
+    int x,y,n,p,i;
     char c;
     int correct; 
     int solver; 
@@ -1969,6 +2015,11 @@
             if (c == 'z') ret->pencils[x] ^= 4;
             move += n;
         }
+        if (c == 'D' && sscanf(move + 1, "%d,%d%n", &x, &y, &n) == 2 &&
+            is_clue(ret, x, y)) {
+            ret->hints_done[clue_index(ret, x, y)] ^= 1;
+            move += n + 1;
+        }
         if (*move == ';') move++;
     }
 
@@ -2058,6 +2109,10 @@
     ret[COL_VAMPIRE * 3 + 1] = ret[COL_BACKGROUND * 3 + 0] * 0.9F;
     ret[COL_VAMPIRE * 3 + 2] = ret[COL_BACKGROUND * 3 + 0] * 0.9F;
 
+    ret[COL_DONE * 3 + 0] = ret[COL_BACKGROUND * 3 + 0] / 1.5F;
+    ret[COL_DONE * 3 + 1] = ret[COL_BACKGROUND * 3 + 1] / 1.5F;
+    ret[COL_DONE * 3 + 2] = ret[COL_BACKGROUND * 3 + 2] / 1.5F;
+
     *ncolours = NCOLOURS;
     return ret;
 }
@@ -2090,6 +2145,9 @@
     ds->hint_errors = snewn(2*state->common->num_paths,unsigned char);
     for (i=0;i<2*state->common->num_paths;i++)
         ds->hint_errors[i] = FALSE;
+    ds->hints_done = snewn(2 * state->common->num_paths, unsigned char);
+    memset(ds->hints_done, 0,
+           2 * state->common->num_paths * sizeof(unsigned char));
 
     ds->hshow = ds->hpencil = ds->hflash = 0;
     ds->hx = ds->hy = 0;
@@ -2097,6 +2155,7 @@
 }
 
 static void game_free_drawstate(drawing *dr, game_drawstate *ds) {
+    sfree(ds->hints_done);
     sfree(ds->hint_errors);
     sfree(ds->cell_errors);
     sfree(ds->pencils);
@@ -2325,6 +2384,8 @@
         color = COL_ERROR;
     else if (hflash)
         color = COL_FLASH;
+    else if (ds->hints_done[hint_index])
+        color = COL_DONE;
     else
         color = COL_TEXT;
 
@@ -2450,6 +2511,11 @@
 
     if (ds->hint_errors[index] != state->hint_errors[index]) {
         ds->hint_errors[index] = state->hint_errors[index];
+        return TRUE;
+    }
+
+    if (ds->hints_done[index] != state->hints_done[index]) {
+        ds->hints_done[index] = state->hints_done[index];
         return TRUE;
     }