The automatons awaken (branch only — not for the public droplet yet)

Phase 4 begins. The automaton is a pure function in the engine —
automatonCommand(view) — playing from its own redacted GameView, the
same information a human seat receives: hidden hands stay hidden from
the clockwork. It ranks simple damage spells, counters what hurts
(full shield at 3+, reflection at 4+, blunt at 2+), discards its
worst cards by a value order, BFS-pathfinds to enemy treasures and
home again, refuses to path through hazards, brawls when there is
nothing to steal, and always has a safe fallback; the server's drive
loop steps any bot-held seat through the same runCommand path as
humans, so bot commands log, persist, replay, and broadcast like
anyone's.

Hosts seat them pre-start with "⚙ seat an automaton" (Automaton,
Automaton II, ... V); bot seats persist as tokenless join lines and
restore on boot. Proven three ways: bot-vs-bot engine games conclude
across seeds in 8-14 rounds (~100 commands — human-scale), a full
four-automaton table finishes, and a live websocket game of human
vs. automaton ended with the clockwork carrying two treasures home
through a do-nothing opponent.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Eric Wagoner
2026-08-16 16:11:54 -04:00
co-authored by Claude Fable 5
parent 5802e1df05
commit ab52628d2f
9 changed files with 559 additions and 5 deletions
+6
View File
@@ -225,6 +225,7 @@ class Net {
started = $state(false);
/** Lobby standee choices, by player name. */
roomColors = $state<Record<string, number>>({});
roomBots = $state<string[]>([]);
you = $state<string | null>(null);
view = $state<GameView | null>(null);
log = $state<string[]>([]);
@@ -295,6 +296,7 @@ class Net {
case "room":
this.roomId = msg.roomId;
this.roomColors = msg.colors ?? {};
this.roomBots = msg.bots ?? [];
if (this.you && this.token) {
const seat: Seat = { name: this.you, roomId: msg.roomId, token: this.token };
localStorage.setItem(SEAT_KEY, JSON.stringify(seat));
@@ -426,6 +428,10 @@ class Net {
}
/** Ask the server how all our games are doing. */
addBot(): void {
this.send({ type: "addBot" });
}
rollTableDie(): void {
this.send({ type: "rollDie" });
}