Keyboard interface for Filling, from James H.
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Wed, 14 Jan 2009 20:44:25 +0000 (20:44 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Wed, 14 Jan 2009 20:44:25 +0000 (20:44 +0000)
git-svn-id: svn://svn.tartarus.org/sgt/puzzles@8412 cda61777-01e9-0310-a592-d414129be87e

filling.c
puzzles.but

index a42ffd3..0209062 100644 (file)
--- a/filling.c
+++ b/filling.c
 static unsigned char verbose;
 
 static void printv(char *fmt, ...) {
 static unsigned char verbose;
 
 static void printv(char *fmt, ...) {
+#ifndef PALM
     if (verbose) {
        va_list va;
        va_start(va, fmt);
        vprintf(fmt, va);
        va_end(va);
     }
     if (verbose) {
        va_list va;
        va_start(va, fmt);
        vprintf(fmt, va);
        va_end(va);
     }
+#endif
 }
 
 /*****************************************************************************
 }
 
 /*****************************************************************************
@@ -104,13 +106,13 @@ struct game_state {
     int completed, cheated;
 };
 
     int completed, cheated;
 };
 
-static const struct game_params defaults[3] = {{7, 9}, {9, 13}, {13, 17}};
+static const struct game_params filling_defaults[3] = {{7, 9}, {9, 13}, {13, 17}};
 
 static game_params *default_params(void)
 {
     game_params *ret = snew(game_params);
 
 
 static game_params *default_params(void)
 {
     game_params *ret = snew(game_params);
 
-    *ret = defaults[1]; /* struct copy */
+    *ret = filling_defaults[1]; /* struct copy */
 
     return ret;
 }
 
     return ret;
 }
@@ -119,10 +121,10 @@ static int game_fetch_preset(int i, char **name, game_params **params)
 {
     char buf[64];
 
 {
     char buf[64];
 
-    if (i < 0 || i >= lenof(defaults)) return FALSE;
+    if (i < 0 || i >= lenof(filling_defaults)) return FALSE;
     *params = snew(game_params);
     *params = snew(game_params);
-    **params = defaults[i]; /* struct copy */
-    sprintf(buf, "%dx%d", defaults[i].h, defaults[i].w);
+    **params = filling_defaults[i]; /* struct copy */
+    sprintf(buf, "%dx%d", filling_defaults[i].h, filling_defaults[i].w);
     *name = dupstr(buf);
 
     return TRUE;
     *name = dupstr(buf);
 
     return TRUE;
@@ -340,7 +342,7 @@ static void make_board(int *board, int w, int h, random_state *rs) {
 
     /* I abuse the board variable: when generating the puzzle, it
      * contains a shuffled list of numbers {0, ..., nsq-1}. */
 
     /* I abuse the board variable: when generating the puzzle, it
      * contains a shuffled list of numbers {0, ..., nsq-1}. */
-    for (i = 0; i < sz; ++i) board[i] = i;
+    for (i = 0; i < (int)sz; ++i) board[i] = i;
 
     while (1) {
        int change;
 
     while (1) {
        int change;
@@ -349,7 +351,7 @@ static void make_board(int *board, int w, int h, random_state *rs) {
        /* while the board can in principle be fixed */
        do {
            change = FALSE;
        /* while the board can in principle be fixed */
        do {
            change = FALSE;
-           for (i = 0; i < sz; ++i) {
+           for (i = 0; i < (int)sz; ++i) {
                int a = SENTINEL;
                int b = SENTINEL;
                int c = SENTINEL;
                int a = SENTINEL;
                int b = SENTINEL;
                int c = SENTINEL;
@@ -381,7 +383,7 @@ static void make_board(int *board, int w, int h, random_state *rs) {
            }
        } while (change);
 
            }
        } while (change);
 
-       for (i = 0; i < sz; ++i) board[i] = dsf_size(dsf, i);
+       for (i = 0; i < (int)sz; ++i) board[i] = dsf_size(dsf, i);
 
        sfree(dsf);
        printv("returning board number %d\n", nboards);
 
        sfree(dsf);
        printv("returning board number %d\n", nboards);
@@ -982,6 +984,7 @@ static char *solve_game(game_state *state, game_state *currstate,
 
 struct game_ui {
     int *sel; /* w*h highlighted squares, or NULL */
 
 struct game_ui {
     int *sel; /* w*h highlighted squares, or NULL */
+    int cur_x, cur_y, cur_visible;
 };
 
 static game_ui *new_ui(game_state *state)
 };
 
 static game_ui *new_ui(game_state *state)
@@ -989,6 +992,7 @@ static game_ui *new_ui(game_state *state)
     game_ui *ui = snew(game_ui);
 
     ui->sel = NULL;
     game_ui *ui = snew(game_ui);
 
     ui->sel = NULL;
+    ui->cur_x = ui->cur_y = ui->cur_visible = 0;
 
     return ui;
 }
 
     return ui;
 }
@@ -1065,10 +1069,28 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
             if (!state->shared->clues[w*ty+tx])
                 ui->sel[w*ty+tx] = 1;
         }
             if (!state->shared->clues[w*ty+tx])
                 ui->sel[w*ty+tx] = 1;
         }
+        ui->cur_visible = 0;
         return ""; /* redraw */
     }
 
         return ""; /* redraw */
     }
 
-    if (!ui->sel) return NULL;
+    if (IS_CURSOR_MOVE(button)) {
+        ui->cur_visible = 1;
+        move_cursor(button, &ui->cur_x, &ui->cur_y, w, h, 0);
+        return "";
+    }
+    if (IS_CURSOR_SELECT(button)) {
+        if (!ui->cur_visible) {
+            ui->cur_visible = 1;
+            return "";
+        }
+        if (!ui->sel) {
+            ui->sel = snewn(w*h, int);
+            memset(ui->sel, 0, w*h*sizeof(int));
+        }
+        if (state->shared->clues[w*ui->cur_y + ui->cur_x] == 0)
+            ui->sel[w*ui->cur_y + ui->cur_x] ^= 1;
+        return "";
+    }
 
     switch (button) {
       case ' ':
 
     switch (button) {
       case ' ':
@@ -1086,8 +1108,9 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
 
     for (i = 0; i < w*h; i++) {
         char buf[32];
 
     for (i = 0; i < w*h; i++) {
         char buf[32];
-        if (ui->sel[i]) {
-            assert(state->shared->clues[i] == 0);
+        if ((ui->sel && ui->sel[i]) ||
+            (!ui->sel && ui->cur_visible && (w*ui->cur_y+ui->cur_x) == i)) {
+            if (state->shared->clues[i] != 0) continue; /* in case cursor is on clue */
             if (state->board[i] != button) {
                 sprintf(buf, "%s%d", move ? "," : "", i);
                 if (move) {
             if (state->board[i] != button) {
                 sprintf(buf, "%s%d", move ? "," : "", i);
                 if (move) {
@@ -1106,6 +1129,7 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
         move = srealloc(move, strlen(move)+strlen(buf)+1);
         strcat(move, buf);
     }
         move = srealloc(move, strlen(move)+strlen(buf)+1);
         strcat(move, buf);
     }
+    if (!ui->sel) return move ? move : NULL;
     sfree(ui->sel);
     ui->sel = NULL;
     /* Need to update UI at least, as we cleared the selection */
     sfree(ui->sel);
     ui->sel = NULL;
     /* Need to update UI at least, as we cleared the selection */
@@ -1173,6 +1197,7 @@ enum {
     COL_CORRECT,
     COL_ERROR,
     COL_USER,
     COL_CORRECT,
     COL_ERROR,
     COL_USER,
+    COL_CURSOR,
     NCOLOURS
 };
 
     NCOLOURS
 };
 
@@ -1207,6 +1232,10 @@ static float *game_colours(frontend *fe, int *ncolours)
     ret[COL_CORRECT * 3 + 1] = 0.9F * ret[COL_BACKGROUND * 3 + 1];
     ret[COL_CORRECT * 3 + 2] = 0.9F * ret[COL_BACKGROUND * 3 + 2];
 
     ret[COL_CORRECT * 3 + 1] = 0.9F * ret[COL_BACKGROUND * 3 + 1];
     ret[COL_CORRECT * 3 + 2] = 0.9F * ret[COL_BACKGROUND * 3 + 2];
 
+    ret[COL_CURSOR * 3 + 0] = 0.5F * ret[COL_BACKGROUND * 3 + 0];
+    ret[COL_CURSOR * 3 + 1] = 0.5F * ret[COL_BACKGROUND * 3 + 1];
+    ret[COL_CURSOR * 3 + 2] = 0.5F * ret[COL_BACKGROUND * 3 + 2];
+
     ret[COL_ERROR * 3 + 0] = 1.0F;
     ret[COL_ERROR * 3 + 1] = 0.85F * ret[COL_BACKGROUND * 3 + 1];
     ret[COL_ERROR * 3 + 2] = 0.85F * ret[COL_BACKGROUND * 3 + 2];
     ret[COL_ERROR * 3 + 0] = 1.0F;
     ret[COL_ERROR * 3 + 1] = 0.85F * ret[COL_BACKGROUND * 3 + 1];
     ret[COL_ERROR * 3 + 2] = 0.85F * ret[COL_BACKGROUND * 3 + 2];
@@ -1254,10 +1283,11 @@ static void game_free_drawstate(drawing *dr, game_drawstate *ds)
 #define BORDER_DR  0x020
 #define BORDER_UL  0x040
 #define BORDER_DL  0x080
 #define BORDER_DR  0x020
 #define BORDER_UL  0x040
 #define BORDER_DL  0x080
-#define CURSOR_BG  0x100
+#define HIGH_BG    0x100
 #define CORRECT_BG 0x200
 #define ERROR_BG   0x400
 #define USER_COL   0x800
 #define CORRECT_BG 0x200
 #define ERROR_BG   0x400
 #define USER_COL   0x800
+#define CURSOR_SQ 0x1000
 
 static void draw_square(drawing *dr, game_drawstate *ds, int x, int y,
                         int n, int flags)
 
 static void draw_square(drawing *dr, game_drawstate *ds, int x, int y,
                         int n, int flags)
@@ -1279,7 +1309,7 @@ static void draw_square(drawing *dr, game_drawstate *ds, int x, int y,
               BORDER + y*TILE_SIZE,
               TILE_SIZE,
               TILE_SIZE,
               BORDER + y*TILE_SIZE,
               TILE_SIZE,
               TILE_SIZE,
-              (flags & CURSOR_BG ? COL_HIGHLIGHT :
+              (flags & HIGH_BG ? COL_HIGHLIGHT :
                flags & ERROR_BG ? COL_ERROR :
                flags & CORRECT_BG ? COL_CORRECT : COL_BACKGROUND));
 
                flags & ERROR_BG ? COL_ERROR :
                flags & CORRECT_BG ? COL_CORRECT : COL_BACKGROUND));
 
@@ -1368,6 +1398,16 @@ static void draw_square(drawing *dr, game_drawstate *ds, int x, int y,
                   BORDER_WIDTH,
                   COL_GRID);
 
                   BORDER_WIDTH,
                   COL_GRID);
 
+    if (flags & CURSOR_SQ) {
+        int coff = TILE_SIZE/8;
+        draw_rect_outline(dr,
+                          BORDER + x*TILE_SIZE + coff,
+                          BORDER + y*TILE_SIZE + coff,
+                          TILE_SIZE - coff*2,
+                          TILE_SIZE - coff*2,
+                          COL_CURSOR);
+    }
+
     unclip(dr);
 
     draw_update(dr,
     unclip(dr);
 
     draw_update(dr,
@@ -1457,7 +1497,7 @@ static void draw_grid(drawing *dr, game_drawstate *ds, game_state *state,
             if (flashy || !shading) {
                 /* clear all background flags */
             } else if (ui->sel && ui->sel[y*w+x]) {
             if (flashy || !shading) {
                 /* clear all background flags */
             } else if (ui->sel && ui->sel[y*w+x]) {
-                flags |= CURSOR_BG;
+                flags |= HIGH_BG;
             } else if (v) {
                 int size = dsf_size(ds->dsf_scratch, y*w+x);
                 if (size == v)
             } else if (v) {
                 int size = dsf_size(ds->dsf_scratch, y*w+x);
                 if (size == v)
@@ -1465,6 +1505,8 @@ static void draw_grid(drawing *dr, game_drawstate *ds, game_state *state,
                 else if (size > v)
                     flags |= ERROR_BG;
             }
                 else if (size > v)
                     flags |= ERROR_BG;
             }
+            if (ui->cur_visible && x == ui->cur_x && y == ui->cur_y)
+              flags |= CURSOR_SQ;
 
             /*
              * Borders at the very edges of the grid are
 
             /*
              * Borders at the very edges of the grid are
@@ -1585,8 +1627,8 @@ static void game_print_size(game_params *params, float *x, float *y)
      * I'll use 6mm squares by default.
      */
     game_compute_size(params, 600, &pw, &ph);
      * I'll use 6mm squares by default.
      */
     game_compute_size(params, 600, &pw, &ph);
-    *x = pw / 100.0;
-    *y = ph / 100.0;
+    *x = pw / 100.0F;
+    *y = ph / 100.0F;
 }
 
 static void game_print(drawing *dr, game_state *state, int tilesize)
 }
 
 static void game_print(drawing *dr, game_state *state, int tilesize)
@@ -1705,3 +1747,5 @@ int main(int argc, char **argv) {
 }
 
 #endif
 }
 
 #endif
+
+/* vim: set shiftwidth=4 tabstop=8: */
index 7bcaafe..b35dfc0 100644 (file)
@@ -2315,6 +2315,12 @@ If you make a mistake, click the mouse in the incorrect square and
 press 0, Space, Backspace or Enter to clear it again (or use the Undo
 feature).
 
 press 0, Space, Backspace or Enter to clear it again (or use the Undo
 feature).
 
+You can also move around the grid with the cursor keys; typing a digit will
+fill the square containing the cursor with that number, or typing 0, Space,
+or Enter will clear it. You can also select multiple squares for numbering
+or clearing by using the return key, before typing a digit to fill in the
+highlighted squares (as above).
+
 (All the actions described in \k{common-actions} are also available.)
 
 \H{filling-parameters} \I{parameters, for Filling}Filling parameters
 (All the actions described in \k{common-actions} are also available.)
 
 \H{filling-parameters} \I{parameters, for Filling}Filling parameters