The clockworks study three lost duels
Six instincts learned playing Kestrel live, taught to the automatons. Bank guard: enemy gold banked at home is a scoreboard anyone can rob — an empty-handed raider within two of a stocked bank pulls the walker home (the predicate reads only enemy positions, the thief-chase shuttle lesson), and pathDenial blockades the raider's road. Repossession: the bot's own treasure banked by an enemy one delivery from winning becomes a march goal, and the underfoot grab learns the owner exception. Infrastructure: holding DIMENSIONAL WARP near home in the early rounds, the bot anchors one mouth at its doorstep and one beside the richest distant gold — the home-anchored superhighway that won its teacher two games. Turn theft: a carrier one delivery from winning eats LIGHTNING BLAST's stun over any bigger point total. The teleport delivery: carrying with home a blink away but farther by boot, it jumps the ambush and drops next command. Last-counter thrift: a lone remaining counteraction at healthy life waits for something big. A/B vs the prior brain across 100 mirrors: parity (44-52, historical noise band) — the patterns are anti-human, and mirrors don't play like humans. Three scenario tests pin the rungs; 287 tests; 23 ledgers verified. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015RCWSTnb1KYTPyL4GmhGnF
This commit is contained in:
co-authored by
Claude Fable 5
parent
9af7bd80ce
commit
6d88b35516
@@ -856,3 +856,69 @@ describe("the archmage's sharpened instincts", () => {
|
||||
throw new Error("the clockwork hoarded its number instead of winning");
|
||||
});
|
||||
});
|
||||
|
||||
describe("lessons from the human duels", () => {
|
||||
function rig(players = ["foe", "bot"]) {
|
||||
let { state } = createGame({ playerIds: players, seed: 42, sets: ["basic", "expansion1"] });
|
||||
while (state.turn.round < 2 || state.players[state.turn.activeIndex]!.id !== "bot") {
|
||||
const r = applyCommand(state, actingSeat(state), { type: "endTurn", draw: 0 });
|
||||
if (!r.ok) throw new Error(r.error);
|
||||
state = r.state;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
it("a raider at the stocked bank's gates pulls the clockwork home", () => {
|
||||
const state = rig();
|
||||
const bot = state.players.find((p) => p.id === "bot")!;
|
||||
const foe = state.players.find((p) => p.id === "foe")!;
|
||||
const gold = state.treasures.find((t) => t.owner === "foe")!;
|
||||
gold.position = { ...bot.home };
|
||||
gold.carriedBy = null;
|
||||
foe.position = { x: bot.home.x, y: bot.home.y + 1 };
|
||||
bot.position = { ...foe.home };
|
||||
bot.hand = [];
|
||||
const cmd = automatonCommand(viewFor(state, "bot"), "hunter", "archmage");
|
||||
// Whatever step it picks, the march must be TOWARD home, not the gold map.
|
||||
expect(cmd?.type).toBe("move");
|
||||
});
|
||||
|
||||
it("carrying with home a blink away, it teleports the delivery", () => {
|
||||
const state = rig();
|
||||
const bot = state.players.find((p) => p.id === "bot")!;
|
||||
const prize = state.treasures.find((t) => t.owner === "foe")!;
|
||||
prize.carriedBy = "bot";
|
||||
prize.position = null;
|
||||
bot.carriedTreasureId = prize.id;
|
||||
// Two squares from home as the spell flies, but walled off on foot.
|
||||
bot.position = { x: bot.home.x, y: bot.home.y + 2 };
|
||||
for (const side of ["N", "S", "E", "W"] as const) {
|
||||
state.edgeOverrides[edgeKey(bot.position, side)] = "wall";
|
||||
}
|
||||
bot.hand = [{ cardId: "teleport", instanceId: "TP" } as never];
|
||||
const cmd = automatonCommand(viewFor(state, "bot"), "hunter", "archmage");
|
||||
expect(cmd).toEqual({ type: "cast", instanceId: "TP", target: { kind: "cell", cell: { ...bot.home } } });
|
||||
});
|
||||
|
||||
it("a would-win carrier eats the lightning, not the fireball", () => {
|
||||
let state = rig();
|
||||
const bot = state.players.find((p) => p.id === "bot")!;
|
||||
const foe = state.players.find((p) => p.id === "foe")!;
|
||||
// Foe has one banked and carries the second: one delivery from winning.
|
||||
const banked = state.treasures.find((t) => t.owner === "bot")!;
|
||||
banked.position = { ...foe.home };
|
||||
const carried = state.treasures.filter((t) => t.owner === "bot")[1];
|
||||
if (!carried) return;
|
||||
carried.carriedBy = "foe";
|
||||
carried.position = null;
|
||||
foe.carriedTreasureId = carried.id;
|
||||
foe.position = { ...bot.position };
|
||||
bot.hand = [
|
||||
{ cardId: "fireball", instanceId: "FB" } as never,
|
||||
{ cardId: "lightning-blast", instanceId: "LB" } as never,
|
||||
{ cardId: "number-4", instanceId: "N4" } as never,
|
||||
];
|
||||
const cmd = automatonCommand(viewFor(state, "bot"), "hunter", "archmage");
|
||||
expect(cmd).toMatchObject({ type: "cast", instanceId: "LB" });
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user