diff --git a/packages/web/src/App.svelte b/packages/web/src/App.svelte index 314189e..184950a 100644 --- a/packages/web/src/App.svelte +++ b/packages/web/src/App.svelte @@ -223,7 +223,7 @@ }); const openingRolls = $derived(net.openingRolls ?? local.openingRolls); function dismissRolls() { - net.openingRolls = null; + net.dismissRolls(); local.openingRolls = null; } /** A face-up card being peeked at from the scoresheet (view-only). */ @@ -1405,6 +1405,8 @@ const room = net.roomId; if (!room || finishedRoom === room) return; finishedRoom = room; + // The step light is for a first game; the second is played by sight. + if (prefs.finishedGames === 0) setPref("stepLight", false); setPref("finishedGames", prefs.finishedGames + 1); if (!prefs.tierChosen && prefs.botTier === "apprentice") setPref("botTier", "adept"); }); @@ -1479,7 +1481,26 @@ // answer to "how can he even see me?" when sight ran through a warp mouth. const sightTrace = $derived(view ? stackSightTrace(view) : null); + /** The step light: with no card in hand, your square and the squares a + * stride reaches are lit and the rest of the maze falls into shadow. */ + const stepLight = $derived( + !!view && !!me && prefs.stepLight && isYourTurn && !view.turn.actionsEnded && !selectedCard && + !net.spectating && !youMustRespond && view.turn.movementAllowance - view.turn.movementUsed > 0, + ); + const stepCells = $derived.by(() => { + if (!stepLight || !view || !me) return []; + return SIDES.map((side) => stepTarget(view!.board, me!.position, side)) + .filter((t) => t.kind !== "blocked") + .map((t) => cellKey(t.to)); + }); + /** The first stride of a first game gets one line on the board itself. */ + const stepCaption = $derived( + stepLight && view && me && view.turn.round === 1 && view.turn.movementUsed === 0 + ? { cell: me.position, text: "This is you — tap a lit square to walk" } + : null, + ); const litCells = $derived.by(() => { + if (view && me && !selectedDef && stepLight) return new Set([cellKey(me.position), ...stepCells]); if (!view || !selectedDef || !yourMoment) return null; if (ambushVia || ambushSpell || ambushTrigger) return null; // ambushes aim at the future if (!me) return null; @@ -1833,6 +1854,11 @@ onchange={(e) => setPref("handLeft", e.currentTarget.checked)} /> Hand at the left: your cards stand in a column beside the board (wide screens) +