Credibility pass: the splice marks sanded from the rev-11 batch

The extracted rebuildRoom loop reflowed to the file's indent and its
doc comments unstacked; liftIdiotIfSatisfied moves below idiotBlocked
so each keeps its own comment; the pickup's duplicated owner lookup
folds to one; the cloned grab-refusal chain hoists to grabRefused; a
one-off #8a7a5c rejoins the #8a7a5e palette; an inert overflow-x line
and a duplicate import go; span 6 and the two cache strategies say why;
the reversed walking-dead test moves beside its biting sibling. Also:
the replay harness now honors lobby kicks, which VVZU (five bots
seated, two kicked) was the first production ledger to exercise.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015RCWSTnb1KYTPyL4GmhGnF
This commit is contained in:
Eric Wagoner
2026-08-30 13:58:02 -04:00
co-authored by Claude Fable 5
parent e83d70116f
commit a1fdb37c54
8 changed files with 96 additions and 87 deletions
+9 -10
View File
@@ -4568,6 +4568,13 @@ function castingBlocked(
* treasure on their own home, or drop their own treasure underfoot for an
* instant cure.
*/
function idiotBlocked(state: GameState, playerId: PlayerId): string | null {
if (sustainedOn(state, playerId, "idiot").length > 0) {
return "What am I doing here...? (you can do nothing but head for your treasure)";
}
return null;
}
/** IDIOT lifts when the march is done the victim stands on their own
* treasure or turns unsatisfiable: every one of their treasures is in
* someone's arms, leaving nothing to stand on. */
@@ -4584,13 +4591,6 @@ function liftIdiotIfSatisfied(state: GameState, events: GameEvent[], p: PlayerSt
state.sustained = state.sustained.filter((fx) => !(fx.cardId === "idiot" && fx.targetId === p.id));
}
function idiotBlocked(state: GameState, playerId: PlayerId): string | null {
if (sustainedOn(state, playerId, "idiot").length > 0) {
return "What am I doing here...? (you can do nothing but head for your treasure)";
}
return null;
}
/** "One cannot attack or be attacked while in a bush"; mist-bodies neither. */
function attackBlockedByStatus(state: GameState, attacker: PlayerState, target: PlayerState): string | null {
if (sustainedOn(state, target.id, "big-man").length > 0 &&
@@ -6423,13 +6423,12 @@ function doPickUpTreasure(prev: GameState, treasureId?: string): CommandResult {
const events: GameEvent[] = [
{ type: "treasurePickedUp", player: p.id, treasureId: t.id, owner: t.owner, at: p.position },
];
const owner = state.players.find((q) => q.id === t.owner);
// This grab may have lifted the owner's IDIOT: with every one of their
// treasures now carried, there is nothing left to march to.
const cursedOwner = state.players.find((q) => q.id === t.owner);
if (cursedOwner) liftIdiotIfSatisfied(state, events, cursedOwner);
if (owner) liftIdiotIfSatisfied(state, events, owner);
// WARD: "you may play at that time (out of turn) this card on him" —
// literally: the grab hangs while the owner decides.
const owner = state.players.find((q) => q.id === t.owner);
if (owner && owner.alive && owner.id !== p.id) {
const holdsWard = owner.hand.some((c) => c.cardId === "ward");
if (holdsWard) {