Credibility pass: the code reads as one hand's work. Dead plumbing and copies removed, four claims the source does not support corrected, and inherited kit text re-read for this game
Engine: the facade re-exports the board in one block; describe() and the dead letters preference, void ply, the King-taken line, the identity maps and the unused imports are gone; SIDE_NAMES is the one spelling of a side; the drake's hunter comment no longer claims only four kinds reach the air. Prose: no shatranj and no sitting duck, which Gygax never wrote; the Thief statistic and the Basilisk's "one trick" are gone; lessons say what the board shows instead of repeating the panel; a Thief's leap counts four. Browser: one keyboard walk, in BoardArtwork; the lesson board and page share one game and one inspected piece; the chronicle's possessive is told, not patched by a regex; the chronicle colours and the reading layout are global rules instead of three copies; the guide and the about panel say what the code and the article actually do. Server and docs: the room server states that it is the kit's, kept whole; the skills, the deploy README and the share card name files that exist. 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
944e4e8306
commit
0be89a1dfe
28 files changed
+227
-340
No files matched your search
@@ -13,12 +13,12 @@
|
||||
<script lang="ts">
|
||||
// The three boards, drawn one above the other: the air, the land and the
|
||||
// underworld, each twelve by eight in the colours Gygax suggested, with
|
||||
// the pieces as discs bearing his letters. Shared by the table, the hall's
|
||||
// still of the opening and the share artwork.
|
||||
import { FILES, RANKS, PER_LEVEL, fileOf, rankOf, levelOf, isLight, kindOf, sideOf, frozen, squareName, LETTERS, NAMES, type State } from '$lib/game';
|
||||
// the pieces as discs bearing his letters. Shared by the table, the
|
||||
// lessons and the hall's still of the opening.
|
||||
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,
|
||||
yourMove = false, calm = true, decorative = false, tap = () => {}, key = () => {}
|
||||
calm = true, decorative = false, tap = () => {}, escape = () => {}
|
||||
}: {
|
||||
g: State;
|
||||
tokens?: Token[];
|
||||
@@ -34,13 +34,34 @@
|
||||
shownSquares?: number[];
|
||||
shownCaptured?: number[];
|
||||
checkSquare?: number;
|
||||
yourMove?: boolean;
|
||||
calm?: boolean;
|
||||
/** An illustration: no roles, no tab stops, nothing to tap. */
|
||||
decorative?: boolean;
|
||||
tap?: (i: number) => void | Promise<void>;
|
||||
key?: (e: KeyboardEvent, i: number) => void;
|
||||
/** Escape pressed on a square: the caller lets go of whatever it was doing. */
|
||||
escape?: () => void;
|
||||
} = $props();
|
||||
|
||||
let svg: SVGSVGElement | undefined = $state();
|
||||
/** Arrows walk a board the way it is drawn, Page Up and Page Down climb and descend, Enter picks up and sets down. */
|
||||
function key(e: KeyboardEvent, i: number) {
|
||||
const step: Record<string, [number, number, number]> = {
|
||||
ArrowLeft: [flipped ? 1 : -1, 0, 0], ArrowRight: [flipped ? -1 : 1, 0, 0], ArrowUp: [0, flipped ? -1 : 1, 0], ArrowDown: [0, flipped ? 1 : -1, 0],
|
||||
PageUp: [0, 0, 1], PageDown: [0, 0, -1]
|
||||
};
|
||||
if (e.key in step) {
|
||||
e.preventDefault();
|
||||
const [df, dr, dl] = step[e.key];
|
||||
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();
|
||||
} else if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
void tap(i);
|
||||
} else if (e.key === 'Escape') escape();
|
||||
}
|
||||
|
||||
const artworkTokens = $derived(tokens ?? g.cells.flatMap((piece, at) => (piece === '' ? [] : [{ id: at, piece, at, dying: false }])));
|
||||
const CELL = 40;
|
||||
const PAD_L = $derived(showCoords ? 18 : 6);
|
||||
@@ -70,14 +91,14 @@
|
||||
const describe = (i: number) => {
|
||||
const piece = g.cells[i];
|
||||
let text = squareName(i);
|
||||
if (piece !== '') text += `, ${sideOf(piece) === 'gold' ? 'Gold' : 'Scarlet'} ${NAMES[kindOf(piece)]}${frozen(g.cells, i) ? ', frozen' : ''}`;
|
||||
if (piece !== '') text += `, ${SIDE_NAMES[sideOf(piece)!]} ${NAMES[kindOf(piece)]}${frozen(g.cells, i) ? ', frozen' : ''}`;
|
||||
if (targets.includes(i)) text += ', a legal move';
|
||||
if (i === checkSquare) text += ', in check';
|
||||
return text;
|
||||
};
|
||||
</script>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="artwork" class:calm viewBox="0 0 {width} {height}" role={decorative ? 'img' : 'grid'} aria-label={decorative ? 'The three boards in their opening position' : 'The three boards'}>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" bind:this={svg} class="artwork" class:calm viewBox="0 0 {width} {height}" role={decorative ? 'img' : 'grid'} aria-label={decorative ? 'The three boards in their opening position' : 'The three boards'}>
|
||||
{#each levels as lv, slot (lv)}
|
||||
{@const top = slot * (boardHeight + GAP)}
|
||||
<g class="world" data-level={lv}>
|
||||
@@ -114,7 +135,7 @@
|
||||
role={decorative ? undefined : 'gridcell'}
|
||||
aria-label={decorative ? undefined : describe(i)}
|
||||
aria-selected={decorative ? undefined : selected === i}
|
||||
tabindex={decorative ? undefined : yourMove ? 0 : -1}
|
||||
tabindex={decorative ? undefined : 0}
|
||||
onclick={decorative ? undefined : () => tap(i)}
|
||||
onkeydown={decorative ? undefined : (e) => key(e, i)}
|
||||
/>
|
||||
|
||||
Reference in new issue
Block a user