+ } 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;