The full clockwork curriculum: keys, vengeance, spellcraft, and voice
Every play-strength item, in one education. DOORS: the pathfinder walks through doors it can open — already-opened ones freely, locked ones when holding Master Key or Pick Lock, casting the key at the door on the path before stepping through (and a loop where the clockwork re-keyed an already-open door forever is fixed: opened doors read as open). TREASURE DEFENSE: a wizard carrying the automaton's gold becomes the priority — chased over all objectives, shaken down with DROP OBJECT when held, and attacked first. WIDER SPELLCRAFT: blaster wands charged by number and fired; teleport as escape when wounded and hunted, and as a counteraction clear of big incoming spells; SPEED cast on sight; WARD armed to guard the gold; shieldstone displayed so spare numbers soak small hits; ANTI-ANTI pressed against counters (never against escapes); the berserker grows BIG with an enemy near, the worrier fades invisible or slams a CREATE WALL in its pursuer's face; ambushes armed from held interrupts — the worrier trapping its doorstep, the others trapping the treasure. Tournament suite green across all temperaments. And the clockwork speaks: sparing, temperament-voiced table talk on its own deeds — "ACQUISITION COMPLETE.", "SCHEDULED DEMISE: DELIVERED.", "good wall. safe wall." — through the same chat ledger as everyone else. The tally gains "games fought against the clockwork", and automatons no longer pollute the count of wizards seated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
ca16faac73
commit
3eda686e29
@@ -24,6 +24,8 @@ export interface EngagementStats {
|
||||
firstGameAt: string | null;
|
||||
/** How many of the games were hotseat tables reporting in anonymously. */
|
||||
hotseatGames: number;
|
||||
/** Games with at least one clockwork wizard at the table. */
|
||||
automatonGames: number;
|
||||
}
|
||||
|
||||
interface StatsFile extends Omit<EngagementStats, "wizardsSeated"> {
|
||||
@@ -40,7 +42,7 @@ let data: StatsFile = {
|
||||
commandsPlayed: 0, minutesAtTable: 0,
|
||||
winsByTreasure: 0, winsByLastStanding: 0,
|
||||
longestGameCommands: 0, fullestTable: 0, firstGameAt: null,
|
||||
hotseatGames: 0, wizards: [], roomStages: {},
|
||||
hotseatGames: 0, automatonGames: 0, wizards: [], roomStages: {},
|
||||
};
|
||||
let wizardSet = new Set<string>();
|
||||
let loaded = false;
|
||||
@@ -84,6 +86,7 @@ export function recordRoom(room: Room): void {
|
||||
const stage = data.roomStages[room.id];
|
||||
|
||||
for (const p of room.players) {
|
||||
if (room.bots.has(p)) continue; // the clockwork are not wizards seated
|
||||
const key = p.toLowerCase();
|
||||
if (!wizardSet.has(key)) { wizardSet.add(key); dirty = true; }
|
||||
}
|
||||
@@ -95,6 +98,7 @@ export function recordRoom(room: Room): void {
|
||||
}
|
||||
if (room.state && data.roomStages[room.id] === "created") {
|
||||
data.gamesStarted++;
|
||||
if (room.bots.size > 0) data.automatonGames++;
|
||||
data.fullestTable = Math.max(data.fullestTable, room.players.length);
|
||||
data.roomStages[room.id] = "started";
|
||||
dirty = true;
|
||||
|
||||
Reference in New Issue
Block a user