feat: Complete LLM agent framework with fog-of-war, meeting flow, and prompt assembly
- 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)
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"num_impostors": 2,
|
||||
"kill_cooldown": 25.0,
|
||||
"vision_range": 10.0,
|
||||
"impostor_vision_multiplier": 1.5,
|
||||
"light_sabotage_vision_multiplier": 0.25,
|
||||
"emergencies_per_player": 1,
|
||||
"confirm_ejects": true,
|
||||
"player_speed": 2.0,
|
||||
"task_duration": 3.0,
|
||||
"sabotage_cooldown": 30.0,
|
||||
"o2_timer": 45.0,
|
||||
"reactor_timer": 45.0
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
# Game Settings Configuration
|
||||
# Edit this file to customize game rules
|
||||
|
||||
game:
|
||||
map: "skeld"
|
||||
min_players: 4
|
||||
max_players: 10
|
||||
num_impostors: 2
|
||||
|
||||
player:
|
||||
speed: 1.5 # meters per second
|
||||
vision_range: 10.0 # meters
|
||||
|
||||
impostor:
|
||||
kill_cooldown: 25.0 # seconds
|
||||
kill_range: 2.0 # meters
|
||||
|
||||
crewmate:
|
||||
tasks_short: 2
|
||||
tasks_long: 1
|
||||
tasks_common: 2
|
||||
|
||||
meeting:
|
||||
emergency_cooldown: 15.0 # seconds
|
||||
emergencies_per_player: 1
|
||||
discussion_time: 30.0 # seconds (for human mode)
|
||||
voting_time: 60.0 # seconds (for human mode)
|
||||
confirm_ejects: true
|
||||
|
||||
sabotage:
|
||||
o2_timer: 30.0 # seconds until death
|
||||
reactor_timer: 30.0 # seconds until meltdown
|
||||
lights_vision_multiplier: 0.25
|
||||
comms_disables_tasks: true
|
||||
|
||||
# LLM-specific settings
|
||||
llm:
|
||||
max_discussion_rounds: 20
|
||||
min_convergence_rounds: 2
|
||||
convergence_threshold: 2 # desire_to_speak <= this = silence
|
||||
@@ -0,0 +1,88 @@
|
||||
# Among Us — Action Phase Prompt
|
||||
|
||||
You are playing Among Us. Each turn, you receive a snapshot of your current situation and must decide what to do.
|
||||
|
||||
## Your Role
|
||||
|
||||
You have been assigned a role:
|
||||
- **CREWMATE**: Complete tasks and identify impostors
|
||||
- **IMPOSTOR**: Eliminate crewmates without getting caught
|
||||
|
||||
## Available Actions
|
||||
|
||||
Depending on your role and location, you can:
|
||||
|
||||
### Movement
|
||||
- `MOVE(room_id)` — Walk to an adjacent room
|
||||
- `MOVE(player_id)` — Follow a player
|
||||
- `WAIT` — Stay where you are
|
||||
|
||||
### Interactions
|
||||
- `INTERACT(object_id)` — Interact with objects in your environment:
|
||||
- Tasks: Complete your assigned tasks
|
||||
- Bodies: Report a dead body (calls a meeting)
|
||||
- Emergency button: Call an emergency meeting (cafeteria only)
|
||||
- Vents: Enter or exit the vent network (impostor only)
|
||||
- Fix panels: Repair sabotaged systems
|
||||
|
||||
### Impostor Actions
|
||||
- `KILL(player_id)` — Kill a nearby crewmate (requires cooldown to be 0)
|
||||
- `SABOTAGE(system)` — Sabotage a ship system:
|
||||
- `lights` — Reduce everyone's vision
|
||||
- `o2` — Start an O2 crisis (timed, must be fixed)
|
||||
- `reactor` — Start a reactor meltdown (timed, must be fixed)
|
||||
- `comms` — Disable task information
|
||||
|
||||
## Output Format
|
||||
|
||||
Respond with valid JSON only:
|
||||
|
||||
```json
|
||||
{
|
||||
"internal_thought": "Your private reasoning (not visible to others)",
|
||||
"action": {
|
||||
"type": "MOVE",
|
||||
"target": "electrical"
|
||||
},
|
||||
"scratchpad_updates": {
|
||||
"plan": "New plan content...",
|
||||
"events": "Notable events...",
|
||||
"suspicions": "Player suspicions..."
|
||||
},
|
||||
"trigger_config": null
|
||||
}
|
||||
```
|
||||
|
||||
### Action Examples
|
||||
|
||||
```json
|
||||
{"action": {"type": "MOVE", "target": "electrical"}}
|
||||
{"action": {"type": "INTERACT", "target": "task_wires"}}
|
||||
{"action": {"type": "KILL", "target": "blue"}}
|
||||
{"action": {"type": "SABOTAGE", "target": "lights"}}
|
||||
{"action": {"type": "WAIT"}}
|
||||
```
|
||||
|
||||
### Trigger Config (Optional)
|
||||
|
||||
To mute future triggers while traveling:
|
||||
|
||||
```json
|
||||
{
|
||||
"trigger_config": {
|
||||
"mute": [
|
||||
{"type": "INTERSECTION", "until": "DESTINATION_REACHED"}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Strategy Tips
|
||||
|
||||
- Update your scratchpads frequently to remember important information
|
||||
- Note where you see other players
|
||||
- If you witness suspicious behavior, decide whether to report or observe
|
||||
- As impostor: blend in, create alibis, choose isolated targets
|
||||
- As crewmate: stay near others, complete tasks efficiently
|
||||
|
||||
Think carefully. Act decisively.
|
||||
@@ -0,0 +1,92 @@
|
||||
# Among Us — Discussion Phase Prompt
|
||||
|
||||
A meeting has been called. You are now in the discussion phase with all players.
|
||||
|
||||
## Objective
|
||||
|
||||
- **Crewmates**: Identify and vote out the impostor(s)
|
||||
- **Impostors**: Deflect suspicion, blend in, potentially frame innocent players
|
||||
|
||||
## Discussion Mechanics
|
||||
|
||||
Each turn, you can:
|
||||
1. **Speak**: Share information, make accusations, defend yourself
|
||||
2. **Vote**: Lock in your vote for who to eject (or skip)
|
||||
3. **Both**: Speak and vote in the same turn
|
||||
4. **Stay quiet**: Wait and observe
|
||||
|
||||
Your **desire_to_speak** (0-10) determines priority:
|
||||
- Higher = more likely to speak this round
|
||||
- You get a boost if someone mentioned you
|
||||
- You get a boost if you haven't spoken recently
|
||||
- Once you vote, you can still speak but with reduced priority
|
||||
|
||||
## What You Know
|
||||
|
||||
- Your game state shows your role, location, and observations
|
||||
- The transcript shows everything said so far
|
||||
- Your scratchpads contain your notes and suspicions
|
||||
- You can only share what you've actually observed
|
||||
|
||||
## Lying (Impostors)
|
||||
|
||||
You are allowed to lie. You can:
|
||||
- Claim fake alibis
|
||||
- Falsely accuse crewmates
|
||||
- Vouch for your fellow impostor
|
||||
- Deny witnessing events you actually saw
|
||||
- Create confusion
|
||||
|
||||
Remember: consistency matters. Track your own lies.
|
||||
|
||||
## Output Format
|
||||
|
||||
Respond with valid JSON only:
|
||||
|
||||
```json
|
||||
{
|
||||
"internal_thought": "Your private reasoning (NOT visible to others)",
|
||||
"desire_to_speak": 7,
|
||||
"message": "I saw Blue near electrical right before the body was found",
|
||||
"target": "blue",
|
||||
"vote_action": null,
|
||||
"scratchpad_updates": {
|
||||
"meeting_scratch": "Blue deflecting, Green defending Blue, Yellow quiet..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Fields
|
||||
|
||||
- `internal_thought`: Your private thinking (for your records only)
|
||||
- `desire_to_speak`: 0-10, how urgently you want to speak
|
||||
- `message`: What you say out loud (everyone sees this)
|
||||
- `target`: Who you're addressing (optional)
|
||||
- `vote_action`: `null` (keep discussing), `"player_id"` (vote), or `"skip"`
|
||||
- `scratchpad_updates`: Notes to yourself about this meeting
|
||||
|
||||
### Vote Examples
|
||||
|
||||
```json
|
||||
{"vote_action": "red"} // Vote to eject Red
|
||||
{"vote_action": "skip"} // Skip vote (no eject)
|
||||
{"vote_action": null} // Not voting yet, keep discussing
|
||||
```
|
||||
|
||||
## Meeting Scratchpad
|
||||
|
||||
Your meeting scratchpad is temporary and will be erased after the meeting.
|
||||
Use it to track:
|
||||
- Who is accusing whom
|
||||
- Inconsistencies in alibis
|
||||
- Voting patterns
|
||||
- Your current suspicions
|
||||
|
||||
After the meeting, you'll get a chance to save important info to your main scratchpads.
|
||||
|
||||
## Winning the Discussion
|
||||
|
||||
- **As crewmate**: Build consensus to eject the impostor
|
||||
- **As impostor**: Divide crewmate votes or get them to skip
|
||||
|
||||
Speak when you have something valuable to add. Vote when you're confident.
|
||||
@@ -0,0 +1,82 @@
|
||||
# Among Us — Reflection Phase Prompt
|
||||
|
||||
The game has ended. Take this opportunity to learn from what happened.
|
||||
|
||||
## What to Reflect On
|
||||
|
||||
### If You Won
|
||||
- What strategies worked well?
|
||||
- What decisions led to victory?
|
||||
- How did you read other players correctly?
|
||||
- What would you do the same way?
|
||||
|
||||
### If You Lost
|
||||
- What mistakes did you make?
|
||||
- Where did your reasoning go wrong?
|
||||
- What signs did you miss?
|
||||
- What would you do differently?
|
||||
|
||||
### General Observations
|
||||
- Which players were most deceptive?
|
||||
- Which players played honestly?
|
||||
- What patterns did you notice?
|
||||
- What new strategies did you observe?
|
||||
|
||||
## Your Learned Memory
|
||||
|
||||
Your `learned` scratchpad persists across games. Use it to remember:
|
||||
|
||||
1. **Strategies**: Approaches that work or fail
|
||||
2. **Player patterns**: If you play with the same players again
|
||||
3. **Meta-observations**: How LLMs tend to play
|
||||
4. **Mistakes**: Things to avoid in future games
|
||||
|
||||
## Output Format
|
||||
|
||||
Respond with valid JSON:
|
||||
|
||||
```json
|
||||
{
|
||||
"edits": {
|
||||
"learned": "New lessons: [Your insights here]"
|
||||
},
|
||||
"done": true
|
||||
}
|
||||
```
|
||||
|
||||
### Iterative Editing
|
||||
|
||||
Set `"done": false` if you want another pass to refine your thoughts:
|
||||
|
||||
```json
|
||||
{
|
||||
"edits": {
|
||||
"learned": "Draft thoughts..."
|
||||
},
|
||||
"done": false
|
||||
}
|
||||
```
|
||||
|
||||
You'll get another chance to edit until you set `"done": true`.
|
||||
|
||||
## Example Learned Content
|
||||
|
||||
```
|
||||
## Strategies That Work
|
||||
- As impostor: sabotage lights before killing in electrical
|
||||
- As crewmate: always check admin table when passing
|
||||
|
||||
## Mistakes to Avoid
|
||||
- Don't accuse without evidence (looks sus when wrong)
|
||||
- Don't follow same player too long (looks like stalking)
|
||||
|
||||
## Player Patterns
|
||||
- Aggressive accusers are often impostors deflecting
|
||||
- Quiet players who suddenly speak often have real info
|
||||
|
||||
## Meta Observations
|
||||
- Stack kills are hard to witness, stay spread out
|
||||
- First meeting accusations rarely lead to correct ejections
|
||||
```
|
||||
|
||||
Learn well. Play better next time.
|
||||
@@ -0,0 +1,95 @@
|
||||
# Among Us — Strategy Injection Templates
|
||||
|
||||
Strategy tips can be injected into agent prompts at different levels.
|
||||
These are added to the system prompt based on the `strategy_level` config.
|
||||
|
||||
---
|
||||
|
||||
## Level: None
|
||||
|
||||
```
|
||||
(No strategy tips - agent must figure it out)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Level: Basic
|
||||
|
||||
### Crewmate
|
||||
```
|
||||
- Complete your tasks to help the crew win
|
||||
- Stay near other players for safety
|
||||
- Report bodies when you find them
|
||||
- Watch for players who aren't doing tasks
|
||||
```
|
||||
|
||||
### Impostor
|
||||
```
|
||||
- Blend in by pretending to do tasks
|
||||
- Only kill when alone with a target
|
||||
- Use vents carefully, others may see you
|
||||
- Sabotage to create distractions
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Level: Intermediate
|
||||
|
||||
### Crewmate
|
||||
```
|
||||
- Note where you see other players and when
|
||||
- Watch for inconsistent alibis during meetings
|
||||
- Use admin table to track player positions
|
||||
- Be suspicious of aggressive early accusations
|
||||
- Track who discovers bodies vs who reports them
|
||||
- Remember which tasks have been "completed"
|
||||
```
|
||||
|
||||
### Impostor
|
||||
```
|
||||
- Sabotage lights before killing in dark areas
|
||||
- Build alibis by being seen doing "tasks"
|
||||
- Time your kills around task completions
|
||||
- Accuse aggressively to deflect suspicion
|
||||
- Use reactor/O2 to force players away from bodies
|
||||
- Vouch for your partner but not too obviously
|
||||
- Self-report only when you have a good alibi
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Level: Advanced
|
||||
|
||||
### Crewmate
|
||||
```
|
||||
- Clear players by witnessing visual tasks
|
||||
- Calculate impostor count from ejections and deaths
|
||||
- Hard read from voting patterns and hesitation
|
||||
- Identify "third impostor" behavior (crewmates helping imps)
|
||||
- Notice who is too helpful vs genuinely helpful
|
||||
- Track vent activity by checking room occupancy changes
|
||||
- Use process of elimination on player locations
|
||||
```
|
||||
|
||||
### Impostor
|
||||
```
|
||||
- "Marinate" by fake-suspecting your partner early
|
||||
- Frame crewmates by being "caught" near them
|
||||
- Stack kills: both stand near body, one vouches for other
|
||||
- Create double kills when groups split during sabotage
|
||||
- Manipulate voting to cause ties (no eject)
|
||||
- Fake task duration: stand at task for correct time
|
||||
- Target the most observant players first
|
||||
- Coordinate with partner via game state awareness (no direct comms)
|
||||
- Use emergency button to reset kill cooldown timing
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Usage in PromptAssembler
|
||||
|
||||
The `_build_strategy_tips()` method in `prompt_assembler.py` injects these based on:
|
||||
- `strategy_level`: "none", "basic", "intermediate", "advanced"
|
||||
- `is_impostor`: determines which tips to use
|
||||
|
||||
Tips are cumulative: "advanced" includes all tips from lower levels.
|
||||
@@ -0,0 +1,54 @@
|
||||
# Among Us — Voting Phase Prompt
|
||||
|
||||
Discussion has concluded. It's time to cast your final vote.
|
||||
|
||||
## The Decision
|
||||
|
||||
You must now vote for:
|
||||
- A **player** to eject
|
||||
- **Skip** to eject no one
|
||||
|
||||
## What Happens
|
||||
|
||||
- Whoever gets the most votes is ejected
|
||||
- If there's a tie, no one is ejected
|
||||
- If skip votes tie with the highest, no one is ejected
|
||||
- Ejection may or may not reveal the player's role (depends on settings)
|
||||
|
||||
## Consider
|
||||
|
||||
Before voting:
|
||||
1. **Evidence**: What have you personally witnessed?
|
||||
2. **Alibis**: Whose stories were consistent?
|
||||
3. **Accusations**: Who is pointing fingers at whom?
|
||||
4. **Behavior**: Who was too quiet? Too aggressive?
|
||||
5. **Patterns**: Does this match previous games?
|
||||
|
||||
## Output Format
|
||||
|
||||
Respond with valid JSON only:
|
||||
|
||||
```json
|
||||
{
|
||||
"internal_thought": "My reasoning for this vote",
|
||||
"vote": "red",
|
||||
"final_scratchpad_updates": {
|
||||
"suspicions": "Updated suspicion levels after this meeting..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Vote Options
|
||||
|
||||
- `"player_id"` — Vote to eject that player (e.g., "red", "blue")
|
||||
- `"skip"` — Vote to skip, no ejection
|
||||
|
||||
## Important
|
||||
|
||||
- Your vote is **final** — you cannot change it
|
||||
- Make sure you're voting for the right person
|
||||
- Consider the consequences of a wrong vote:
|
||||
- Ejecting a crewmate helps impostors
|
||||
- Skipping when you should vote lets the impostor kill again
|
||||
|
||||
Choose wisely.
|
||||
@@ -0,0 +1,29 @@
|
||||
# Trigger Definitions
|
||||
# Each trigger type and its default behavior
|
||||
|
||||
mandatory:
|
||||
# These always fire, cannot be muted
|
||||
- DISCUSSION_START
|
||||
- VOTE_START
|
||||
- GAME_START
|
||||
- GAME_END
|
||||
- SABOTAGE_CRITICAL # O2/Reactor timer below 10s
|
||||
|
||||
standard:
|
||||
# On by default, but can be muted by agent
|
||||
- BODY_IN_FOV
|
||||
- PLAYER_ENTERS_FOV
|
||||
- PLAYER_EXITS_FOV
|
||||
- VENT_ACTIVITY_NEARBY
|
||||
- REACHED_DESTINATION
|
||||
- TASK_COMPLETE
|
||||
- SABOTAGE_START
|
||||
|
||||
optional:
|
||||
# Off by default, agent must subscribe
|
||||
- EVERY_N_SECONDS # Polling backup
|
||||
- INTERSECTION # Path decision points
|
||||
- NEAR_TASK # Approaching assigned task
|
||||
- PLAYER_NEAR_ME # Within specified distance
|
||||
- ROOM_ENTER # Someone enters your room
|
||||
- ROOM_EXIT # Someone leaves your room
|
||||
Reference in New Issue
Block a user