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:
co-authored by
Claude Fable 5.1
parent
79947e31ba
commit
58d7db106e
+15
-11
@@ -214,7 +214,8 @@ export function resolveTurn(previous: GameState, inputs: Record<WizardId, TurnIn
|
||||
return [prev.left, prev.right];
|
||||
}
|
||||
if (c.charmed) {
|
||||
const g = c.charmedGesture ?? input(c.charmed.by).charmGesture ?? '-';
|
||||
const charmer = input(c.charmed.by);
|
||||
const g = c.charmedGesture ?? charmer.charmGestures?.[w.id] ?? charmer.charmGesture ?? '-';
|
||||
if (w.permanent.charmed && !w.permanent.charmedGesture) w.permanent.charmedGesture = g;
|
||||
if (c.charmed.hand === 'left') left = g;
|
||||
else right = g;
|
||||
@@ -495,7 +496,8 @@ export function resolveTurn(previous: GameState, inputs: Record<WizardId, TurnIn
|
||||
};
|
||||
state.monsters.push(m);
|
||||
orders.set(m.id, c.choice.monsterTarget ?? enemyOf(state, controller));
|
||||
log(`A ${stats.name.toLowerCase()} answers ${W[controller].name}'s summons.`, 'spell');
|
||||
const creature = stats.name.toLowerCase();
|
||||
log(`${/^[aeiou]/.test(creature) ? 'An' : 'A'} ${creature} answers ${W[controller].name}'s summons.`, 'spell');
|
||||
}
|
||||
|
||||
let fireStorm = live().some((c) => c.spell.id === 'fire_storm');
|
||||
@@ -727,8 +729,9 @@ export function resolveTurn(previous: GameState, inputs: Record<WizardId, TurnIn
|
||||
const damage = new Map<TargetId, number>();
|
||||
const healing = new Map<TargetId, number>();
|
||||
const slain = new Set<TargetId>();
|
||||
const hurt = (id: TargetId, n: number, why: string) => {
|
||||
const hurt = (id: TargetId, n: number, why: string, by?: WizardId) => {
|
||||
damage.set(id, (damage.get(id) ?? 0) + n);
|
||||
if (isWizard(id) && by && by !== id) W[id].lastHurtBy = by;
|
||||
note(id, tidy(why), -n);
|
||||
log(`${beingName(state, id)} takes ${n} from ${why}.`, 'damage');
|
||||
};
|
||||
@@ -743,31 +746,32 @@ export function resolveTurn(previous: GameState, inputs: Record<WizardId, TurnIn
|
||||
if (isShielded(t)) {
|
||||
facts.shieldBlocked.add(t);
|
||||
log(`${guard(t)} turns the missile aside.`, 'fizzle');
|
||||
} else hurt(t, 1, 'a missile');
|
||||
} else hurt(t, 1, 'a missile', c.caster);
|
||||
break;
|
||||
case 'finger_of_death':
|
||||
slain.add(t);
|
||||
if (isWizard(t)) W[t].lastHurtBy = c.caster;
|
||||
note(t, 'Finger of death', -(isWizard(t) ? W[t].hp : 0));
|
||||
log(`The finger of death touches ${beingName(state, t)}.`, 'death');
|
||||
break;
|
||||
case 'lightning_bolt':
|
||||
case 'lightning_bolt_quick':
|
||||
if (isShielded(t)) facts.throughShield.push({ target: t, spell: 'a lightning bolt' });
|
||||
hurt(t, 5, 'a lightning bolt');
|
||||
hurt(t, 5, 'a lightning bolt', c.caster);
|
||||
break;
|
||||
case 'cause_light_wounds':
|
||||
if (isShielded(t)) facts.throughShield.push({ target: t, spell: 'cause light wounds' });
|
||||
hurt(t, 2, 'cause light wounds');
|
||||
hurt(t, 2, 'cause light wounds', c.caster);
|
||||
break;
|
||||
case 'cause_heavy_wounds':
|
||||
if (isShielded(t)) facts.throughShield.push({ target: t, spell: 'cause heavy wounds' });
|
||||
hurt(t, 3, 'cause heavy wounds');
|
||||
hurt(t, 3, 'cause heavy wounds', c.caster);
|
||||
break;
|
||||
case 'fireball':
|
||||
if (resists(t, 'heat')) log(`${beingName(state, t)} shrugs off the fireball.`, 'fizzle');
|
||||
else {
|
||||
if (isShielded(t)) facts.throughShield.push({ target: t, spell: 'a fireball' });
|
||||
hurt(t, 5, 'a fireball');
|
||||
hurt(t, 5, 'a fireball', c.caster);
|
||||
}
|
||||
break;
|
||||
case 'cure_light_wounds':
|
||||
@@ -825,7 +829,7 @@ export function resolveTurn(previous: GameState, inputs: Record<WizardId, TurnIn
|
||||
if (isShielded(id)) continue;
|
||||
if (isWizard(id) && W[id].invisibleTurns > 0) continue;
|
||||
}
|
||||
hurt(id, m.attack, `the ${m.name.toLowerCase()}`);
|
||||
hurt(id, m.attack, `the ${m.name.toLowerCase()}`, m.owner);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -842,7 +846,7 @@ export function resolveTurn(previous: GameState, inputs: Record<WizardId, TurnIn
|
||||
log(`${m.name} flails at the air where ${W[target].name} used to be.`, 'fizzle');
|
||||
} else {
|
||||
if (m.createdTurn === turn && phase === 'main') facts.newMonsterAttacked = m.name;
|
||||
hurt(target, m.attack, `the ${m.name.toLowerCase()}`);
|
||||
hurt(target, m.attack, `the ${m.name.toLowerCase()}`, m.owner);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -859,7 +863,7 @@ export function resolveTurn(previous: GameState, inputs: Record<WizardId, TurnIn
|
||||
facts.shieldBlocked.add(target);
|
||||
log(`${w.name}'s knife skids off ${guard(target)}.`, 'fizzle');
|
||||
} else {
|
||||
hurt(target, 1, `${w.name}'s knife`);
|
||||
hurt(target, 1, `${w.name}'s knife`, id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user