From the two testers' lists: on a phone the status strip carries a jump to each board, with a mark on any board the chosen piece can reach, and a phone on its side shows one board at a time, as wide as the screen, with Page Up and Page Down bringing the others out; a figure held by a Basilisk stands in a pale ring on the glass; the hall says which side and setup are chosen in one line and keeps the choices behind it until asked
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CCLa2PaEeCj8njQZSWGqHx
This commit is contained in:
1 parent
0f4ae0dca4
commit
f2be3b0055
4 files changed
+104
-7
No files matched your search
@@ -15,10 +15,11 @@
|
||||
// underworld, each twelve by eight in the colours Gygax suggested, with
|
||||
// the pieces as discs bearing his letters. Shared by the table, the
|
||||
// lessons and the hall's still of the opening.
|
||||
import { tick } from 'svelte';
|
||||
import { FILES, RANKS, PER_LEVEL, fileOf, rankOf, levelOf, idx, isLight, kindOf, sideOf, frozen, squareName, LETTERS, NAMES, SIDE_NAMES, type State } from '$lib/game';
|
||||
let {
|
||||
g, tokens, levels = [3, 2, 1], showCoords = false, flipped = false, selected = null, targets = [], reach = [], shownSquares = [], shownCaptured = [], checkSquare = -1,
|
||||
calm = true, decorative = false, tap = () => {}, escape = () => {}
|
||||
calm = true, decorative = false, tap = () => {}, escape = () => {}, climb
|
||||
}: {
|
||||
g: State;
|
||||
tokens?: Token[];
|
||||
@@ -40,9 +41,12 @@
|
||||
tap?: (i: number) => void | Promise<void>;
|
||||
/** Escape pressed on a square: the caller lets go of whatever it was doing. */
|
||||
escape?: () => void;
|
||||
/** Page Up or Page Down towards a board that is not drawn: the caller may bring it out. */
|
||||
climb?: (level: number) => void;
|
||||
} = $props();
|
||||
|
||||
let svg: SVGSVGElement | undefined = $state();
|
||||
const focusSquare = (i: number) => svg?.querySelector<SVGRectElement>(`rect.square[data-i="${i}"]`)?.focus();
|
||||
/** The one square Tab reaches: the grid is entered once, at the square last visited, and the keys walk it from there. */
|
||||
let visited = $state<number | null>(null);
|
||||
/** Arrows walk a board the way it is drawn, Page Up and Page Down climb and descend, Enter picks up and sets down. */
|
||||
@@ -57,7 +61,13 @@
|
||||
const f = fileOf(i) + df;
|
||||
const r = rankOf(i) + dr;
|
||||
const lv = levelOf(i) + dl;
|
||||
if (f >= 0 && f < FILES && r >= 0 && r < RANKS && levels.includes(lv)) svg?.querySelector<SVGRectElement>(`rect.square[data-i="${idx(lv, f, r)}"]`)?.focus();
|
||||
if (f < 0 || f >= FILES || r < 0 || r >= RANKS || lv < 1 || lv > 3) return;
|
||||
const to = idx(lv, f, r);
|
||||
if (levels.includes(lv)) focusSquare(to);
|
||||
else if (climb) {
|
||||
climb(lv);
|
||||
void tick().then(() => focusSquare(to));
|
||||
}
|
||||
} else if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
void tap(i);
|
||||
@@ -88,7 +98,10 @@
|
||||
return { x: PAD_L + f * CELL, y: slot * (boardHeight + GAP) + PAD_T + r * CELL };
|
||||
}
|
||||
const drawn = $derived(levels.flatMap((lv) => Array.from({ length: PER_LEVEL }, (_, n) => (lv - 1) * PER_LEVEL + n)));
|
||||
const entry = $derived(visited ?? selected ?? (levels.includes(2) ? idx(2, flipped ? FILES - 1 : 0, flipped ? RANKS - 1 : 0) : drawn[0]));
|
||||
const entry = $derived.by(() => {
|
||||
for (const c of [visited, selected]) if (c !== null && drawn.includes(c)) return c;
|
||||
return levels.includes(2) ? idx(2, flipped ? FILES - 1 : 0, flipped ? RANKS - 1 : 0) : drawn[0];
|
||||
});
|
||||
const fileLetter = (n: number) => 'abcdefghijkl'[flipped ? FILES - 1 - n : n];
|
||||
const rankNumber = (n: number) => (flipped ? n + 1 : RANKS - n);
|
||||
const describe = (i: number) => {
|
||||
|
||||
Reference in new issue
Block a user