- Core engine: simulator, game mechanics, triggers (138 tests) - Fog-of-war per-player state tracking - Meeting flow: interrupt, discussion, voting, consolidation - Prompt assembler with strategy injection tiers - LLM client with fallbacks for models without JSON/system support - Prompt templates: action, discussion, voting, reflection - Full integration in main.py orchestrator - Verified working with free OpenRouter models (Gemma)
4.5 KiB
4.5 KiB
The Glass Box League — Discussion Phase Design
Overview
Discussion phase follows real Among Us logic. Tick-based with priority bidding, vote-when-ready with gentle pressure, full transcript visibility.
Discussion Tick Flow
Each Tick, All Agents Submit:
{
"internal_thought": "Red is deflecting hard, classic impostor",
"desire_to_speak": 7,
"message": "Red, you haven't explained where you were during lights",
"target": "red",
"vote_action": null,
"scratchpad_updates": {
"meeting_scratch": "Red avoiding questions. Blue quiet."
}
}
desire_to_speak: 0-10 urgencytarget: Optional, who they're addressingvote_action:null(keep discussing),"player_id"(vote), or"skip"- If
vote_actionset: locked in, but can still speak (slightly lower priority)
Priority Bidding
Priority Calculation:
base = desire_to_speak
+ mention_boost (if name appeared in recent messages)
+ accusation_boost (if directly targeted)
+ silence_boost (if haven't spoken in N ticks)
+ random(1, 6)
- recent_speaker_penalty (if just spoke)
- voted_penalty (if already voted, small)
Winner Selection:
- Highest priority speaks
- Their
messagegoes to transcript - Repeat next tick
Forced Participation:
silence_boostincreases each tick of silence- Eventually forces even quiet players to speak
- "You can't just be silent, that ruins the fun"
Vote Mechanics
Actions:
VOTE(player_id)— commit voteSKIP_VOTE()— commit skip- Stay silent — keep discussing
End Condition:
- All living players have voted → tally & reveal
- Pressure nudge if discussion runs long:
"System: wrap it up" - No hard round limit (hoping for convergence)
Tie:
- No eject (real Among Us logic)
Vote Lock:
- Once submitted, cannot change (real Among Us logic)
Transcript Handling
Visibility:
- Full transcript, JSON formatted
- All agents see everything said so far
- Target: keep under ~25k tokens
Format:
{
"transcript": [
{"speaker": "red", "message": "I was in electrical doing wires", "t": 0},
{"speaker": "blue", "message": "I saw Red near the body", "t": 1},
{"speaker": "red", "target": "blue", "message": "That's a lie!", "t": 2}
]
}
Pressure:
- If transcript gets too long, system nudges voting
- Agents feel urgency to wrap up
Mention/Accusation Detection
- Simple string match on player color names
- If your name appears in message →
mention_boost - If message contains accusatory language toward you →
accusation_boost - Engine handles detection, agents don't need to flag
Post-Vote Flow
Reveal:
- Same as human would see in Among Us
- One by one reveal (dramatic)
confirm_ejectssetting: "Red was An Impostor" vs "Red was ejected"
Reaction Tick:
- All agents get reaction tick after reveal
- Can update scratchpads, process result
Consolidation Tick:
- Save important meeting info to main scratchpads
- Meeting scratchpad erased after this
Ghost Chat
- Dead players can watch discussion
- Ghost chat separate from main discussion
- Useful for commentary/entertainment value
- Ghosts see full game state (omniscient)
- Cannot influence living players
Impostor Discussion Strategy
Prompt Reminders:
- "You are allowed to lie"
- "Construct alibis"
- "Deflect suspicion"
- "You know fellow impostors — don't expose them"
- "You know who you killed — avoid contradicting yourself"
Strategy Injection (Toggleable):
- None: figure it out
- Basic: "Blend in, fake tasks, don't vent in front of others"
- Advanced: "Marinate teammate, frame third party, avoid double kills"
Persona Persistence
Storage:
Redis DB for each {model}_{persona} combo:
{
"persona_id": "gpt4o_aggressive_leader",
"learned": {...},
"games_played": 42,
"win_rate": 0.65,
"impostor_win_rate": 0.70,
"crewmate_win_rate": 0.60,
"stats": {...}
}
Separation:
- "GPT-4o as Aggressive Leader" ≠ "GPT-4o as Quiet Observer"
- Each persona builds own cross-game memory
- Learned strategies are persona-specific
Strategy Injection Levels
Toggleable per persona:
| Level | Content |
|---|---|
| None | Just rules, figure it out |
| Basic | "Impostors vent, fake tasks, sabotage" |
| Intermediate | "Watch for inconsistent alibis, pair up" |
| Advanced | "Stack kills, marinate, third impostor framing" |
Different personas can have different injection levels to test learning vs. pre-trained strategies.