Safes finally open to keys — and the clockwork stops clawing at the lid
'All LOCK-type cards will work on it' was never wired: openSafes was reset every turn and filled by nothing. A PICK LOCK or MASTER KEY aimed at a safe's square (underfoot or beside) now opens it until turn's end, with its own chronicle line; the dead never-emitted safeOpened variant and its null humanize go. The automaton — H4EN's Automaton II spent six turns grabbing at a locked lid saying 'I meant to do that' — now cracks the box first (key or DISPEL CREATION, which it held the whole time) and drops unopenable safes from its goals rather than marching to one forever. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015RCWSTnb1KYTPyL4GmhGnF
This commit is contained in:
co-authored by
Claude Fable 5
parent
12ece6065a
commit
eabc10f18c
@@ -703,7 +703,6 @@ export type GameEvent =
|
||||
| { type: "boobytrapPlacedPrivate"; visibleTo: PlayerId; realCell: Cell }
|
||||
| { type: "objectsGlued"; caster: PlayerId; at: Cell; turns: number }
|
||||
| { type: "safeCreated"; caster: PlayerId; at: Cell }
|
||||
| { type: "safeOpened"; player: PlayerId; at: Cell }
|
||||
| { type: "itemsTraded"; caster: PlayerId; a: Cell; b: Cell }
|
||||
| { type: "stoneTurnedToWater"; caster: PlayerId; at: Cell | null; edge?: { cell: Cell; side: Side } }
|
||||
| { type: "handsSwapped"; a: PlayerId; b: PlayerId }
|
||||
@@ -745,6 +744,7 @@ export type GameEvent =
|
||||
| { type: "extraTurnGranted"; player: PlayerId }
|
||||
| { type: "lifeTraded"; player: PlayerId; points: number; newAllowance: number }
|
||||
| { type: "madDash"; player: PlayerId; newAllowance: number }
|
||||
| { type: "safeOpened"; player: PlayerId; cell: Cell; withCardId: string }
|
||||
| { type: "trapSprung"; player: PlayerId; cardId?: string }
|
||||
| { type: "died"; player: PlayerId; killedBy: PlayerId | null }
|
||||
| { type: "handTaken"; from: PlayerId; to: PlayerId; count: number }
|
||||
@@ -3588,6 +3588,17 @@ function unlockDoor(
|
||||
cardId: string,
|
||||
opts: { requireAdjacent: boolean },
|
||||
): string | null {
|
||||
// "All LOCK-type cards will work on it" — aimed at a SAFE's square
|
||||
// (underfoot or beside), the key opens it until the turn ends.
|
||||
const cell = cmd.target?.kind === "cell" ? cmd.target.cell : null;
|
||||
if (cell && state.squareContents[cellKey(cell)]?.kind === "safe") {
|
||||
const d = Math.abs(caster.position.x - cell.x) + Math.abs(caster.position.y - cell.y);
|
||||
if (d > 1) return "you must be at or beside the safe";
|
||||
const key = cellKey(cell);
|
||||
if (!state.openSafes.includes(key)) state.openSafes.push(key);
|
||||
events.push({ type: "safeOpened", player: caster.id, cell: { ...cell }, withCardId: cardId });
|
||||
return null;
|
||||
}
|
||||
const found = doorTarget(state, cmd);
|
||||
if (typeof found === "string") return found;
|
||||
const key = edgeKey(found.cell, found.side);
|
||||
|
||||
Reference in New Issue
Block a user