The glass board: a game drawn as three sheets of tinted glass on four posts with figures standing on them, in three.js, taking the same taps as the flat boards, shown only to a browser let in by a word

Fifteen figures in static/figures, one per kind, made to docs/figures-brief.md:
a round base, a livery material the view recolours per side, and a base
material left alone. The view loads three.js and the figures only when it
is opened. It plays a move as a walk and a capture as a sink into the glass,
dims a piece a Basilisk holds, marks the last move, the targets and a King
in check, and lets a tap reach a figure or a marked square through the
glass above it. Three cameras: from the corner, from the player's seat,
from above. The table and the told game offer it behind the gate in
src/lib/glass.svelte.ts, which opens for a browser that visits with
?glass=<word> whose hash it keeps.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CCLa2PaEeCj8njQZSWGqHx
This commit is contained in:
Eric WagonerandClaude Fable 5.1 committed 2026-10-27 01:13:00 -04:00
1 parent 0be89a1dfe
commit 8744072dda
24 files changed
+670 -4

No files matched your search

+17 -1
View File
@@ -7,6 +7,15 @@
import { narrate } from '$lib/game/chronicle';
import { notation, kingSquare, inCheck, movesFrom, legalMovesFrom, sideOf } from '$lib/game';
import { prefs, reducedMotion } from '$lib/prefs.svelte';
import { glass } from '$lib/glass.svelte';
/** The glass board, loaded the first time it is asked for. */
let Glass = $state<typeof import('$lib/components/Glass.svelte').default | null>(null);
let onGlass = $state(false);
async function seeGlass(open: boolean) {
if (open && !Glass) Glass = (await import('$lib/components/Glass.svelte')).default;
onGlass = open;
}
const states = toldStates();
const last = states[states.length - 1];
@@ -62,7 +71,14 @@
<section class="stage">
<div class="boards">
<BoardArtwork {g} {showCoords} {shownSquares} {shownCaptured} {checkSquare} selected={inspected} {reach} {calm} {tap} escape={() => (inspected = null)} />
{#if glass.open}
<p class="muted small"><button type="button" class="link plain" onclick={() => seeGlass(!onGlass)}>{onGlass ? 'Back to the flat boards' : 'See the glass board'}</button></p>
{/if}
{#if onGlass && Glass}
<Glass {g} {shownSquares} {shownCaptured} {checkSquare} selected={inspected} {reach} {calm} {tap} />
{:else}
<BoardArtwork {g} {showCoords} {shownSquares} {shownCaptured} {checkSquare} selected={inspected} {reach} {calm} {tap} escape={() => (inspected = null)} />
{/if}
</div>
<div class="words">
<p class="eyebrow">{ply === 0 ? 'Before the first move' : `Move ${ply} of ${TOLD_MOVES.length}`}{#if move}&nbsp;· {notation(move)}{/if}</p>