Idle bot turns confess; the chronicle fills its gaps
A clockwork whose chosen command the engine refuses now stumbles visibly: the refusal is logged server-side with the offending command (the RNRX coma took three silent turns to notice), and the bot says so in character at the table — "RECALCULATING." — instead of an unexplained idle turn. And six event types that never spoke in the chronicle find their lines: the wave's wash-back, thornbush entry, dragged objects, the opening deal, stolen-card and revealed-hand privates. Replay captions inherit them all through humanize. 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
75f1217c77
commit
365cb3821e
@@ -318,17 +318,28 @@ function actingSeat(room: Room): PlayerId | null {
|
||||
* One automaton command, if the maze is waiting on clockwork. Null when a
|
||||
* human holds the floor (or the game is over, or the clockwork is wedged).
|
||||
*/
|
||||
export function driveOneAutomaton(room: Room): { seat: PlayerId; events: GameEvent[] } | null {
|
||||
export function driveOneAutomaton(
|
||||
room: Room,
|
||||
): { seat: PlayerId; events: GameEvent[]; hesitated?: { refused: Command; error: string } } | null {
|
||||
const seat = actingSeat(room);
|
||||
if (!seat || !room.bots.has(seat)) return null;
|
||||
const view = viewFor(room.state!, seat);
|
||||
const bot = room.bots.get(seat);
|
||||
const chosen = automatonCommand(view, bot?.style, bot?.tier);
|
||||
let hesitated: { refused: Command; error: string } | undefined;
|
||||
let r = runCommand(room, seat, chosen ?? automatonFallback(view, bot?.tier));
|
||||
if ("error" in r) {
|
||||
// A refused choice retries with the fallback — unless the fallback IS
|
||||
// what just failed — then burns down the ladder to endTurn and pass.
|
||||
if (chosen) r = runCommand(room, seat, automatonFallback(view, bot?.tier));
|
||||
// The refusal is remembered: a brain whose choice the engine rejects
|
||||
// is a bug in the brain, and the table deserves to see the stumble
|
||||
// rather than an unexplained idle turn (the RNRX coma lesson).
|
||||
if (chosen) {
|
||||
hesitated = { refused: chosen, error: r.error };
|
||||
console.warn(
|
||||
`automaton ${seat} hesitated in ${room.id}: ${JSON.stringify(chosen)} refused (${r.error})`);
|
||||
r = runCommand(room, seat, automatonFallback(view, bot?.tier));
|
||||
}
|
||||
if ("error" in r) r = runCommand(room, seat, { type: "endTurn", draw: 0 });
|
||||
if ("error" in r) r = runCommand(room, seat, { type: "pass" });
|
||||
if ("error" in r) {
|
||||
@@ -336,7 +347,7 @@ export function driveOneAutomaton(room: Room): { seat: PlayerId; events: GameEve
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return { seat, events: r.events };
|
||||
return { seat, events: r.events, ...(hesitated ? { hesitated } : {}) };
|
||||
}
|
||||
|
||||
export interface GameSummary {
|
||||
|
||||
Reference in New Issue
Block a user