chiark / gitweb /
Expand keyboard input options in Bridges, for faster entry.
authorJonas Kölker <jonaskoelker@yahoo.com>
Mon, 5 Oct 2015 15:59:39 +0000 (17:59 +0200)
committerSimon Tatham <anakin@pobox.com>
Sun, 18 Oct 2015 10:03:16 +0000 (11:03 +0100)
- Lay bridges (crosess) with Control-arrow (Shift-arrow)
- Jump (non-orthogonally) to nearby islands with number keys, a..f
- Mark islands as done with a single tap on the space bar

bridges.c
puzzles.but

index 7a448e25baa5afefc80419ceb59d3ae5928561d2..6f0e02dcfe54492e45cb5646286935190e710f38 100644 (file)
--- a/bridges.c
+++ b/bridges.c
@@ -2333,6 +2333,8 @@ static char *interpret_move(const game_state *state, game_ui *ui,
     int gx = FROMCOORD(x), gy = FROMCOORD(y);
     char buf[80], *ret;
     grid_type ggrid = INGRID(state,gx,gy) ? GRID(state,gx,gy) : 0;
+    int shift = button & MOD_SHFT, control = button & MOD_CTRL;
+    button &= ~MOD_MASK;
 
     if (button == LEFT_BUTTON || button == RIGHT_BUTTON) {
         if (!INGRID(state, gx, gy)) return NULL;
@@ -2372,6 +2374,12 @@ static char *interpret_move(const game_state *state, game_ui *ui,
         return ret;
     } else if (IS_CURSOR_MOVE(button)) {
         ui->cur_visible = 1;
+        if (control || shift) {
+            ui->dragx_src = ui->cur_x;
+            ui->dragy_src = ui->cur_y;
+            ui->dragging = TRUE;
+            ui->drag_is_noline = !control;
+        }
         if (ui->dragging) {
             int nx = ui->cur_x, ny = ui->cur_y;
 
@@ -2441,7 +2449,7 @@ found:
             ui->cur_visible = 1;
             return "";
         }
-        if (ui->dragging) {
+        if (ui->dragging || button == CURSOR_SELECT2) {
             ui_cancel_drag(ui);
             if (ui->dragx_dst == -1 && ui->dragy_dst == -1) {
                 sprintf(buf, "M%d,%d", ui->cur_x, ui->cur_y);
@@ -2459,6 +2467,51 @@ found:
                 return "";
             }
         }
+    } else if ((button >= '0' && button <= '9') ||
+               (button >= 'a' && button <= 'f') ||
+               (button >= 'A' && button <= 'F')) {
+        /* jump to island with .count == number closest to cur_{x,y} */
+        int best_x = -1, best_y = -1, best_sqdist = -1, number = -1, i;
+
+        if (button >= '0' && button <= '9')
+            number = (button == '0' ? 16 : button - '0');
+        else if (button >= 'a' && button <= 'f')
+            number = 10 + button - 'a';
+        else if (button >= 'A' && button <= 'F')
+            number = 10 + button - 'A';
+
+        if (!ui->cur_visible) {
+            ui->cur_visible = 1;
+            return "";
+        }
+
+        for (i = 0; i < state->n_islands; ++i) {
+            int x = state->islands[i].x, y = state->islands[i].y;
+            int dx = x - ui->cur_x, dy = y - ui->cur_y;
+            int sqdist = dx*dx + dy*dy;
+
+            if (state->islands[i].count != number)
+                continue;
+            if (x == ui->cur_x && y == ui->cur_y)
+                continue;
+
+            /* new_game() reads the islands in row-major order, so by
+             * breaking ties in favor of `first in state->islands' we
+             * also break ties by `lexicographically smallest (y, x)'.
+             * Thus, there's a stable pattern to how ties are broken
+             * which the user can learn and use to navigate faster. */
+            if (best_sqdist == -1 || sqdist < best_sqdist) {
+                best_x = x;
+                best_y = y;
+                best_sqdist = sqdist;
+            }
+        }
+        if (best_x != -1 && best_y != -1) {
+            ui->cur_x = best_x;
+            ui->cur_y = best_y;
+            return "";
+        } else
+            return NULL;
     } else if (button == 'g' || button == 'G') {
         ui->show_hints = 1 - ui->show_hints;
         return "";
index ff7ea58e2bcbd6a13db599cffcfe9b47f0f3eb54..d262ed95ccd762eaaabe425951eeb0a8887e81f3 100644 (file)
@@ -2193,12 +2193,18 @@ it and restore your ability to modify it.
 
 You can also use the cursor keys to move around the grid: if possible
 the cursor will always move orthogonally, otherwise it will move
-towards the nearest island to the indicated direction. Pressing the
-return key followed by a cursor key will lay a bridge in that direction
-(if available); pressing the space bar followed by a cursor key will
-lay a \q{non-bridge} marker.
-
-You can mark an island as finished by pressing the return key twice.
+towards the nearest island to the indicated direction. Holding Control
+and pressing a cursor key will lay a bridge in that direction (if
+available); Shift and a cursor key will lay a \q{non-bridge} marker.
+Pressing the return key followed by a cursor key will also lay a
+bridge in that direction.
+
+You can mark an island as finished by pressing the space bar or by
+pressing the return key twice.
+
+By pressing a number key, you can jump to the nearest island with that
+number.  Letters \q{a}, ..., \q{f} count as 10, ..., 15 and \q{0} as
+16.
 
 Violations of the puzzle rules will be marked in red: