# The Glass Box League — Main Game Design ## Agent Architecture ### Identity & Persona - Format: `"You are {model}. {PERSONA}. {context}"` - Persona is **optional** and toggleable - Same model can have multiple personas - Goal: emergent behavior first, spice second ### Memory System | Scratchpad | Persistence | Purpose | |------------|-------------|---------| | `plan.json` | Per-game | Current intentions, agent-controlled | | `events.json` | Per-game | Curated game events worth remembering | | `suspicions.json` | Per-game | Player reads, agent-maintained | | `learned.json` | **Cross-game** | Core memory, enforced JSON schema | | `meeting_scratch.json` | Per-meeting | Temp, erased after consolidation | **JSON is god.** Enforced schema for structure, freeform for agent thoughts. JSON improves attention. --- ## Prompt Structure ### System Prompt (Core Memory) 1. Model identity 2. Persona (if set) 3. Game rules + current map + settings 4. Role briefing (crewmate/impostor) 5. Strategy tips (toggleable injection levels) 6. Meta-awareness (toggleable: subtle → direct → 4th wall) 7. Output format instructions 8. **Learned lessons** from `learned.json` ### User Prompt (Working Memory) Order matters: 1. **You** — role, location, status, cooldowns 2. **Recent history** — accumulated vision from skipped ticks 3. **Vision** — current snapshot 4. **Available actions** — dynamic tool list --- ## Tool System ### Core Tools (Always Available) - `MOVE(room_id | player_id)` — walk or follow - `WAIT()` - `INTERACT(object_id)` — tasks, panels, buttons, bodies, vents, cams ### Impostor Only - `KILL(player_id)` - `SABOTAGE(system_id)` - `FAKE_TASK(task_id)` ### Trigger Management (Optional) - `CONFIGURE_TRIGGERS(config)` — only if changing defaults ### Dynamic Available Actions ```json { "available_interactions": ["task_wires_cafe", "body_blue", "admin_table"], "available_kills": ["green", "yellow"], "available_sabotages": ["lights", "o2", "reactor", "comms"] } ``` - Context-filtered by engine based on role + location - Agent told "these are your actions this turn" - Object IDs validated against engine to prevent glitches --- ## Trigger System ### Mandatory (Cannot Mute) - `GAME_START` - `DISCUSSION_START` - `VOTE_START` - `GAME_END` - `SABOTAGE_CRITICAL` ### Standard (Mutable) - `PLAYER_ENTERS_FOV` - `PLAYER_EXITS_FOV` - `BODY_IN_FOV` - `OBJECT_IN_RANGE` (every interactable) - `VENT_WITNESSED` - `KILL_WITNESSED` - `DESTINATION_REACHED` - `TASK_COMPLETE` - `SABOTAGE_START` / `SABOTAGE_END` - `LIGHTS_OUT` (panic tick) - `COOLDOWN_READY` (kill, emergency) - `DEATH` (special message, transition to ghost) ### Optional (Opt-in) - `EVERY_N_SECONDS` (configurable) - `RANDOM_N_SECONDS` (RNG toggleable) - `INTERSECTION` (hallway/room boundaries) - `HALLWAY_WAYPOINT` ### Trigger Frequency - **Impostors**: Every tick (more decision points) - **Crewmates**: Event-driven + opt-in periodic - **Ghosts**: Reduced frequency, longer intervals ### Trigger Message Schema ```json { "trigger_type": "VENT_WITNESSED", "trigger_data": { "player": "red", "vent_location": "electrical", "action": "entered", "timestamp": 47.3 } } ``` --- ## Game State Schema ### Per-Tick Context ```json { "time": 47.3, "phase": "PLAYING", "you": { "role": "impostor", "location": "electrical", "kill_cooldown": 0, "tasks": [], "emergencies_remaining": 1 }, "recent_history": [ {"t": 12.3, "vision": {"players": ["blue"], "location": "hallway_1"}} ], "vision": { "players_visible": [ {"id": "blue", "location": "electrical", "doing": "task"} ], "objects_visible": ["vent_elec", "task_wires", "body_yellow"], "exits": ["security", "cafeteria"] }, "available_actions": {...} } ``` ### Fog of War **Critical**: Each agent only knows what they've observed. - Engine tracks per-player knowledge - `known_deaths`: bodies seen or announced - `known_locations`: last seen positions + timestamps - `witnessed_events`: vents, kills, sus behavior --- ## Response Format ### Action Phase ```json { "internal_thought": "Blue just left, perfect time to kill Green", "action": {"type": "KILL", "target": "green"}, "scratchpad_updates": { "plan": "...", "events": "...", "suspicions": "..." }, "trigger_config": { "mute": [{"type": "INTERSECTION", "until": "REACHED_DESTINATION"}] } } ``` - `trigger_config` only if changing defaults - `internal_thought` separate from action (for thinking models) --- ## Meeting Interrupt Flow When report/emergency called: 1. **Interrupt note**: Agent leaves context ("this was what I was doing") 2. **Pre-meeting prep**: Agent reviews & prepares thoughts 3. **Meeting scratchpad**: Temporary, discussion-only 4. **Post-meeting consolidation**: Agent saves important info to main scratchpads --- ## Ghost Mode - Omniscient view of entire game - No access to other agents' thoughts - Can do ghost tasks - Reduced tick frequency (save tokens) - Write to scratchpad, observe strategies - No game state modifications --- ## Special Mechanics ### Lights Out - Vision radius shrinks (0.25x multiplier) - Triggers panic tick for all players - Engine recalculates trajectories - Fix triggers restoration tick ### Near-Death Edge Case - Impostor queues kill, victim queues report same tick - Report fires first (higher priority) - Impostor gets: "Your kill was interrupted" - Victim has no direct knowledge (must deduce from proximity) --- ## Configuration Philosophy Everything toggleable: - Persona injection - Strategy tip levels - Meta-awareness levels (subtle/direct/4th wall) - Periodic tick frequency - Random tick RNG - Tool availability based on context Goal: **Replicate human experience.** LLM should have same information and options as human player.