The clockwork reads absorb's fine print

An automaton answered NO SPELL with an Absorb — which "has no effect
on duration-based spells." Afflictions sat outside the price table
and drew the phantom two-point default, tripping the point-soaking
rungs. An affliction's weight is now its duration, and the two
counters that touch only points — ABSORB and REVERSE — stand aside
for it, leaving the ones that genuinely bite durations: full shield,
remove curse, blunt, reflection, shieldstone numbers. Pinned: under
NO SPELL with both in hand, the bot blunts, never absorbs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Eric Wagoner
2026-08-17 13:27:14 -04:00
co-authored by Claude Fable 5
parent adf463effa
commit ea3b9e5bd6
2 changed files with 25 additions and 9 deletions
+16 -5
View File
@@ -117,8 +117,7 @@ describe("automaton vs automaton", () => {
});
});
describe("the clockwork does not waste counters on pointless targets", () => {
function underAttack(attackId: string, defenderHand: { instanceId: string; cardId: string }[], rig?: (s: GameState, defender: string) => void) {
function underAttackShared(attackId: string, defenderHand: { instanceId: string; cardId: string }[], rig?: (s: GameState, defender: string) => void) {
let { state } = createGame({ playerIds: ["human", "bot"], seed: 42, sets: ["basic", "expansion1"], deckRev: 13 });
// burn round 1
for (let i = 0; i < 2; i++) {
@@ -143,10 +142,11 @@ describe("the clockwork does not waste counters on pointless targets", () => {
});
if (!r.ok) throw new Error(`setup: ${r.error}`);
return r.state;
}
}
describe("the clockwork does not waste counters on pointless targets", () => {
it("passes on drop-object rather than absorbing nothing", () => {
const state = underAttack("drop-object", [
const state = underAttackShared("drop-object", [
{ instanceId: "absorb#T", cardId: "absorb" },
{ instanceId: "blunt#T", cardId: "blunt" },
{ instanceId: "dagger#T", cardId: "dagger" },
@@ -156,7 +156,7 @@ describe("the clockwork does not waste counters on pointless targets", () => {
});
it("shields a drop-object aimed at its carried treasure", () => {
const state = underAttack("drop-object", [
const state = underAttackShared("drop-object", [
{ instanceId: "full-shield#T", cardId: "full-shield" },
{ instanceId: "dagger#T", cardId: "dagger" },
], (s, defender) => {
@@ -203,3 +203,14 @@ describe("a clogged hand gets shed, not hoarded", () => {
throw new Error("never reached the end of the turn");
});
});
describe("the clockwork honors absorb's fine print", () => {
it("answers NO SPELL with blunt, never absorb — durations soak no points", () => {
const state = underAttackShared("no-spell", [
{ instanceId: "absorb#T", cardId: "absorb" },
{ instanceId: "blunt#T", cardId: "blunt" },
]);
const cmd = automatonCommand(viewFor(state, "bot"), "hunter", "archmage");
expect(cmd).toEqual({ type: "counteract", instanceId: "blunt#T" });
});
});