A table for a dozen wizards, begun by its host

Rooms take up to twelve seats and the host begins the duel with whoever
is seated; a full table begins by itself. The lobby is a roster with a
bot seat and the host's begin button. The ledger pins the turn and your
own columns and scrolls sideways to the rest; the phone bar shows every
wizard's health; a wizard who is out watches the rest; each charmed
wizard gets their own gesture; an unnamed spell goes at whoever hurt you
last, else the weakest opponent; a stab has a target from the start.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0141G6xqLeNRYEtviLWSB5Up
This commit is contained in:
Eric Wagoner
2026-09-23 09:34:21 -04:00
co-authored by Claude Fable 5.1
parent 79947e31ba
commit 58d7db106e
15 changed files with 299 additions and 61 deletions
+8 -5
View File
@@ -356,14 +356,16 @@ function toChoice(s: Situation, hand: Hand, completion: Completion): CastChoice
return choice;
}
/** The gesture that most disrupts a charmed hand's sequences. */
function charmGesture(s: Situation): Gesture {
const foeW = s.state.wizards[s.foe];
/** The gesture that most disrupts a charmed wizard's hand. */
function charmGesture(s: Situation, who: WizardId): Gesture {
const foeW = s.state.wizards[who];
const charmedHand = foeW.constraints.charmed?.hand ?? 'left';
const hist = visibleHistory(s.state, s.me, who);
const theirs = handSequence(hist, charmedHand);
let best: Gesture = 'P';
let bestScore = Infinity;
for (const g of MAGIC_GESTURES) {
const seq = [...s.foeSeq[charmedHand], { own: g, other: '-' as Gesture }];
const seq = [...theirs, { own: g, other: '-' as Gesture }];
let score = 0;
for (const spell of SPELLS) {
if (!HOSTILE_SPELLS.includes(spell.id)) continue;
@@ -453,6 +455,7 @@ export function chooseBotTurn(state: GameState, me: WizardId, rng: () => number
input.release = { target: choice.target, monsterTarget: choice.monsterTarget };
}
}
if (state.seats.some((id) => state.wizards[id].constraints.charmed?.by === me)) input.charmGesture = charmGesture(s);
const charmed = state.seats.filter((id) => state.wizards[id].constraints.charmed?.by === me);
if (charmed.length) input.charmGestures = Object.fromEntries(charmed.map((id) => [id, charmGesture(s, id)]));
return input;
}