Two treasures, one square: the taker names their prize

pickUpTreasure grabbed whichever treasure the list offered first —
with two on a square, no choice and sometimes the wrong one. The
command now takes an optional treasureId (absent in every stored
ledger, so old replays keep their old grab), and when the square
holds more than one, the button asks "whose?" before dispatching.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Eric Wagoner
2026-08-17 15:03:34 -04:00
co-authored by Claude Fable 5
parent 794b809a1b
commit aef88d892a
3 changed files with 48 additions and 7 deletions
+7 -5
View File
@@ -660,7 +660,7 @@ export type Command =
| { type: "cancelAmbush"; ambushId: string }
| { type: "counteract"; instanceId: string; params?: { cell?: Cell }; numberInstanceIds?: string[] }
| { type: "pass" }
| { type: "pickUpTreasure" }
| { type: "pickUpTreasure"; treasureId?: string }
| { type: "pickUpObject"; instanceId: string }
| { type: "dropObject"; instanceId: string }
| { type: "dropTreasure" }
@@ -3380,7 +3380,7 @@ function applyCommandInner(state: GameState, playerId: PlayerId, command: Comman
case "cancelAmbush": return doCancelAmbush(state, command.ambushId);
case "counteract": return err("nothing to counteract");
case "pass": return err("nothing to pass on");
case "pickUpTreasure": return doPickUpTreasure(state);
case "pickUpTreasure": return doPickUpTreasure(state, command.treasureId);
case "pickUpObject": return doPickUpObject(state, command.instanceId);
case "dropObject": return doDropObject(state, command.instanceId);
case "dropTreasure": return doDropTreasure(state);
@@ -5248,7 +5248,7 @@ function homeOwnerAt(state: GameState, cell: Cell): PlayerId | null {
// --- Treasures ---------------------------------------------------------------
function doPickUpTreasure(prev: GameState): CommandResult {
function doPickUpTreasure(prev: GameState, treasureId?: string): CommandResult {
const blocked = requireActionsAvailable(prev);
if (blocked) return err(blocked);
@@ -5262,10 +5262,12 @@ function doPickUpTreasure(prev: GameState): CommandResult {
if (safe && state.squareContents[here]!.createdBy !== p.id && !state.openSafes.includes(here)) {
return err("it is locked inside a safe");
}
// Two treasures can share a square; an id names the one wanted.
const t = state.treasures.find(
(t) => t.position && cellKey(t.position) === cellKey(p.position) && !t.carriedBy,
(t) => t.position && cellKey(t.position) === cellKey(p.position) && !t.carriedBy &&
(treasureId == null || t.id === treasureId),
);
if (!t) return err("no treasure here");
if (!t) return err(treasureId ? "that treasure is not here for the taking" : "no treasure here");
t.carriedBy = p.id;
t.position = null;