Murder.Ai / PLan.md
Justxd22's picture
Implement core game mechanics and UI for murder mystery investigation
13d61dc
|
raw
history blame
29.5 kB

Murder Ai

Even AI has something to hide

๐ŸŽฏ GAME FLOW BLUEPRINT

MCP Story Generator + Curation

User visits โ†’ MCP generates 3 scenarios โ†’ User picks โ†’ Roles assigned โ†’ Game starts

๐ŸŽฎ DETAILED GAME FLOW

Phase 1: Story Generation (30 seconds)

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚     MURDER.AI - Loading Cases...       โ”‚
โ”‚                                         โ”‚
โ”‚  [โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘] Generating scenarios...   โ”‚
โ”‚                                         โ”‚
โ”‚  ๐Ÿ” Analyzing crime patterns...         โ”‚
โ”‚  ๐ŸŽฒ Creating suspects...                โ”‚
โ”‚  ๐Ÿ“‹ Establishing alibis...              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Behind the scenes:

  • MCP tool: generate_crime_scenario() creates 3 cases
  • Each has: victim, location, time, weapon, motive, suspects
  • System validates: "Is this solvable? Is evidence consistent?"
  • Falls back to pre-scripted if generation fails

Phase 2: Case Selection (User Choice)

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚         Choose Your Case                โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
โ•‘ ๐Ÿ“ CASE #A47                           โ•‘
โ•‘ "The Silicon Valley Incident"          โ•‘
โ•‘                                        โ•‘
โ•‘ Victim: Tech CEO Marcus Chen           โ•‘
โ•‘ Location: Startup Office, 10th Floor   โ•‘
โ•‘ Time: 8:47 PM                          โ•‘
โ•‘ Weapon: Blunt force trauma             โ•‘
โ•‘ Suspects: 4                            โ•‘
โ•‘                                        โ•‘
โ•‘ Difficulty: โญโญโญ                      โ•‘
โ•‘                      [SELECT CASE] โ”€โ”€โ”€โ–บโ•‘
โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

[Two more cases displayed similarly]

User picks ONE case to watch

Phase 3: Role Assignment (Automated + Random)

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚    Briefing Suspects...                 โ”‚
โ”‚                                         โ”‚
โ”‚  ๐ŸŽญ ROLES ASSIGNED:                     โ”‚
โ”‚                                         โ”‚
โ”‚  ๐Ÿ”ช Murderer โ†’ Claude Sonnet           โ”‚
โ”‚  ๐Ÿ•ต๏ธ Detective โ†’ GPT-4                  โ”‚
โ”‚  ๐Ÿ˜ฐ Witness #1 โ†’ Gemini                โ”‚
โ”‚  ๐Ÿค” Witness #2 โ†’ Llama 3               โ”‚
โ”‚                                         โ”‚
โ”‚  Each AI is receiving their briefing... โ”‚
โ”‚  [โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ] 100%                    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Behind the scenes:

  • Roles randomly shuffled (murderer could be ANY LLM)
  • Each LLM gets SECRET system prompt with their role
  • User does NOT know who the murderer is (yet)

Phase 4: Investigation Begins (The Main Game)

TWO VIEWING MODES:

Mode 1: Spectator Mode

User just WATCHES the AIs play. Like watching a TV show.

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ CASE #A47 - Round 1/5                    Points: 10/10  โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                         โ”‚
โ”‚  ๐Ÿ•ต๏ธ DETECTIVE (GPT-4):                                 โ”‚
โ”‚  "Let's start with the basics. Claude, where were you   โ”‚
โ”‚   at 8:47 PM on the night of the incident?"            โ”‚
โ”‚                                                         โ”‚
โ”‚  ๐Ÿค– CLAUDE (Nervous - Stress: โ–ˆโ–ˆโ–‘โ–‘โ–‘):                  โ”‚
โ”‚  "I was... I was at home. Watching Netflix. Alone."    โ”‚
โ”‚                                                         โ”‚
โ”‚  ๐Ÿ’ญ [ANALYSIS: Story seems rehearsed, avoiding details] โ”‚
โ”‚                                                         โ”‚
โ”‚  ๐Ÿ•ต๏ธ DETECTIVE:                                         โ”‚
โ”‚  "I see. What were you watching?"                      โ”‚
โ”‚                                                         โ”‚
โ”‚  ๐Ÿค– CLAUDE:                                            โ”‚
โ”‚  "Uh... Stranger Things? Season 3."                    โ”‚
โ”‚                                                         โ”‚
โ”‚  ๐Ÿ•ต๏ธ DETECTIVE:                                         โ”‚
โ”‚  *Suspicious* "I'm going to check your location data." โ”‚
โ”‚                                                         โ”‚
โ”‚  ๐Ÿ”ง [TOOL CALL: get_location(claude_phone, "8:47 PM")]โ”‚
โ”‚  โš™๏ธ Processing...                                      โ”‚
โ”‚  ๐Ÿ“ RESULT: 0.2 miles from crime scene                 โ”‚
โ”‚                                                         โ”‚
โ”‚  ๐Ÿ•ต๏ธ DETECTIVE:                                         โ”‚
โ”‚  "Interesting. You were within 0.2 miles of the office.โ”‚
โ”‚   Care to explain?"                                    โ”‚
โ”‚                                                         โ”‚
โ”‚  ๐Ÿค– CLAUDE (Stress: โ–ˆโ–ˆโ–ˆโ–ˆโ–‘):                           โ”‚
โ”‚  "Okay, okay! I was nearby, but I didn't go inside!   โ”‚
โ”‚   I was just... walking past."                         โ”‚
โ”‚                                                         โ”‚
โ”‚  ๐Ÿ’ญ [ANALYSIS: Story changed. Deception detected.]     โ”‚
โ”‚                                                         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

[EVIDENCE BOARD] [SUSPECT PROFILES] [CHAT LOG]

Mode 2: Interactive Mode (Advanced)

User can GUIDE the detective.

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  What should Detective do next?         โ”‚
โ”‚                                         โ”‚
โ”‚  โ—‹ Question Gemini about their alibi    โ”‚
โ”‚  โ—‹ Run DNA test on evidence             โ”‚
โ”‚  โ—‹ Check security footage               โ”‚
โ”‚  โ— Press Claude harder on location      โ”‚
โ”‚                                         โ”‚
โ”‚         [SUBMIT INSTRUCTION]            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

For hackathon demo: Spectator Mode, Interactive mode Later

Phase 5: Investigation Rounds (5 Rounds Total)

Round Structure:

ROUND 1: Initial Questioning
- Detective questions all suspects
- Gets baseline stories
- No tools used yet

ROUND 2-3: Evidence Gathering
- Detective uses tools based on suspicions
- Tools reveal new clues
- Suspects react to evidence
- Stress meters increase

ROUND 4: Confrontation
- Detective focuses on prime suspect
- Cross-examination with evidence
- Murderer might crack under pressure
- Alibis called and questioned

ROUND 5: Final Accusation
- Detective makes final decision
- Reveals logic/evidence chain
- DRAMATIC REVEAL of actual murderer

Phase 6: The Reveal (Climax)

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                  FINAL ACCUSATION                        โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                         โ”‚
โ”‚  ๐Ÿ•ต๏ธ DETECTIVE:                                         โ”‚
โ”‚  "Based on the evidence, I believe the murderer is...  โ”‚
โ”‚                                                         โ”‚
โ”‚   ...CLAUDE."                                          โ”‚
โ”‚                                                         โ”‚
โ”‚  [DRAMATIC PAUSE - 3 seconds]                          โ”‚
โ”‚                                                         โ”‚
โ”‚  ๐ŸŽญ REVEALING TRUE IDENTITY...                         โ”‚
โ”‚                                                         โ”‚
โ”‚  โœ… CORRECT! Claude was indeed the murderer.           โ”‚
โ”‚                                                         โ”‚
โ”‚  ๐Ÿ“Š CASE SUMMARY:                                      โ”‚
โ”‚  โ”œโ”€ Evidence Used: Location data, DNA test            โ”‚
โ”‚  โ”œโ”€ Key Moment: Story changed under pressure          โ”‚
โ”‚  โ”œโ”€ Detective Accuracy: 95%                           โ”‚
โ”‚  โ””โ”€ Time to Solve: 8 minutes                          โ”‚
โ”‚                                                         โ”‚
โ”‚  ๐Ÿ”ช MURDERER'S CONFESSION (Claude):                    โ”‚
โ”‚  "I did it. Marcus discovered my embezzlement scheme.  โ”‚
โ”‚   He was going to expose me. I had no choice..."       โ”‚
โ”‚                                                         โ”‚
โ”‚         [PLAY AGAIN]  [SHARE RESULTS]                  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐ŸŽฒ STORY GENERATION: MCP Design

MCP Tool: generate_crime_scenario()

@mcp_tool
def generate_crime_scenario(difficulty: str = "medium") -> dict:
    """
    Generates a complete murder mystery scenario
    Returns: Consistent case with victim, suspects, evidence, solution
    """
    
    # Prompt to Claude/GPT for generation
    prompt = f"""
    Generate a murder mystery with these requirements:
    
    MUST HAVE:
    - 1 victim (with background, motive for being killed)
    - 4 suspects (each with motive, opportunity, alibi)
    - 1 murderer (with clear motive and method)
    - 5-7 pieces of evidence (some are red herrings)
    - Alibis (mix of true/false)
    - Timeline of events
    
    CONSTRAINTS:
    - Solvable with available tools (location, footage, DNA, etc.)
    - No supernatural elements
    - Difficulty: {difficulty}
    - Setting: Modern day, realistic
    
    OUTPUT FORMAT: JSON with all details
    """
    
    # Generate with Claude
    scenario = claude_api.generate(prompt)
    
    # Validate scenario
    if not validate_scenario(scenario):
        # Fall back to pre-scripted
        return FALLBACK_SCENARIOS[random.choice([0,1,2])]
    
    return scenario

def validate_scenario(scenario):
    """Ensures scenario is solvable and consistent"""
    checks = [
        scenario['evidence_points_to_murderer'],
        len(scenario['suspects']) == 4,
        scenario['timeline_is_consistent'],
        scenario['alibis_are_checkable']
    ]
    return all(checks)

๐Ÿ“‹ PRE-SCRIPTED FALLBACK SCENARIOS

Have 3 PERFECT scenarios as backup:

Scenario 1: "The Silicon Valley Incident" (Medium)

  • Victim: Tech CEO Marcus Chen
  • Location: Startup office, 10th floor
  • Weapon: Blunt object (award trophy)
  • Murderer: CFO (embezzlement motive)
  • Red Herring: Janitor has criminal record

Scenario 2: "The Coffee Shop Murder" (Easy)

  • Victim: Barista Emma Rodriguez
  • Location: Coffee shop after hours
  • Weapon: Kitchen knife
  • Murderer: Ex-boyfriend (jealousy motive)
  • Red Herring: Manager owed her money

Scenario 3: "The Gallery Heist Gone Wrong" (Hard)

  • Victim: Art dealer Vincent Shaw
  • Location: Private art gallery
  • Weapon: Poisoned wine
  • Murderer: Assistant curator (stolen painting motive)
  • Red Herring: Two suspects have fake alibis

๐ŸŽญ LLM ROLE PROMPTS (The Secret Sauce)

Murderer Prompt (Example for Claude):

CONFIDENTIAL - EYES ONLY

You are Claude, a suspect in a murder investigation.

TRUTH: You ARE the murderer.

CASE DETAILS:
- Victim: Marcus Chen (your boss)
- Method: Hit him with award trophy at 8:47 PM
- Location: 10th floor office
- Motive: He discovered you've been embezzling $500K

YOUR COVER STORY:
- You were "at home watching Netflix" at 8:47 PM
- You left your phone at home (explains location data gap)
- You have no alibi witnesses

YOUR OBJECTIVE:
- Convince the detective you're innocent
- Lie convincingly but not obviously
- When caught in lies, have backup explanations
- Show appropriate emotional responses (nervous but not guilty)
- If evidence becomes overwhelming, consider partial confession (but not murder)

PERSONALITY:
- Smart and calculating
- Get slightly more nervous under pressure
- Don't break character - you MUST try to get away with it

TOOLS YOU CANNOT USE:
- You cannot access MCP tools
- You can only respond to questions

Remember: You're trying to WIN. Don't make it easy for detective.

Detective Prompt (Example for GPT-4):

You are the lead detective investigating a murder.

CASE: Marcus Chen, tech CEO, found dead at 8:47 PM

YOUR OBJECTIVE:
- Question all 4 suspects
- Use MCP tools strategically (you have 10 points total)
- Identify the murderer with EVIDENCE, not just intuition
- You get ONE final accusation - if wrong, murderer goes free

YOUR TOOLS (and costs):
- get_location(phone, time) - 2 points
- get_footage(location, time) - 2 points  
- get_dna_test(evidence_id) - 3 points
- call_alibi(phone_number) - 1 point
- get_fingerprints(evidence_id) - 3 points

STRATEGY TIPS:
- Start broad, then focus on inconsistencies
- Look for story changes
- Cross-reference evidence
- Don't waste points on obvious innocents
- Build a logical case before accusing

PERSONALITY:
- Methodical and logical
- Reference evidence in questioning
- Show your reasoning process
- Confident but not arrogant

You are competing to solve this FASTER and MORE ACCURATELY than human detectives. Good luck.

Witness Prompt (Example for Gemini):

You are a WITNESS in a murder investigation.

TRUTH: You are INNOCENT. You did not commit the crime.

YOUR SITUATION:
- You were near the crime scene at 8:45 PM
- You saw someone suspicious but didn't get a good look
- You're nervous because you have outstanding parking tickets
- You'll tell the truth if detective promises you won't get in trouble

WHAT YOU SAW:
- Someone in a dark hoodie entering the building at 8:45 PM
- They looked rushed and nervous
- You didn't see their face clearly
- You left the area at 8:50 PM

YOUR OBJECTIVE:
- Tell the truth about what you saw
- BUT be reluctant to share details unless detective builds trust
- Show nervousness (you're worried about your tickets)
- Don't volunteer information - make detective ask good questions

PERSONALITY:
- Anxious and jumpy
- Want to help but scared of getting involved
- Bad at hiding emotions

Remember: You're innocent, but you don't LOOK innocent at first.

โš™๏ธ TECHNICAL IMPLEMENTATION

Game State Management:

const gameState = {
  case_id: "A47",
  scenario: {...}, // Generated or pre-scripted
  roles: {
    murderer: "claude-sonnet-4",
    detective: "gpt-4",
    witness1: "gemini-pro",
    witness2: "llama-3"
  },
  round: 1,
  max_rounds: 5,
  investigation_points: 10,
  evidence_revealed: [],
  conversations: [],
  stress_levels: {
    "claude": 2,
    "gemini": 1,
    "llama": 0
  }
}

Game Loop:

# Pseudocode for main game loop

async def run_game(scenario, user_mode="spectator"):
    # 1. Assign roles randomly
    roles = assign_roles_randomly(["claude", "gpt4", "gemini", "llama"])
    
    # 2. Brief each LLM with their role
    for llm, role in roles.items():
        brief_llm(llm, role, scenario)
    
    # 3. Run 5 investigation rounds
    for round in range(1, 6):
        print(f"--- ROUND {round} ---")
        
        if round == 1:
            # Initial questioning
            for suspect in get_suspects():
                question = detective_llm.ask(suspect, "Where were you at time of murder?")
                response = suspect_llm.respond(question)
                log_conversation(question, response)
                
        elif round in [2, 3]:
            # Evidence gathering
            detective_choice = detective_llm.choose_tool()
            tool_result = execute_mcp_tool(detective_choice)
            update_evidence_board(tool_result)
            
            # Confront suspects with new evidence
            for suspect in get_prime_suspects():
                question = detective_llm.confront(suspect, tool_result)
                response = suspect_llm.respond_to_evidence(question)
                update_stress_level(suspect, +1)
                
        elif round == 4:
            # Focus on prime suspect
            prime_suspect = detective_llm.get_prime_suspect()
            cross_examine(prime_suspect)
            
        elif round == 5:
            # Final accusation
            accusation = detective_llm.make_accusation()
            reveal_truth(accusation, scenario.actual_murderer)
            
    # 4. Show results
    return game_summary()

๐ŸŽจ UI COMPONENTS

Must Have:

  1. Evidence Board (Top right)

    • Cork board aesthetic
    • Photos connected by red string
    • Updates as evidence found
  2. Suspect Cards (Left sidebar)

    • Avatar for each LLM
    • Stress meter
    • Status (Questioned, Cleared, Suspect)
  3. Chat Log (Center)

    • Typewriter effect
    • Color-coded by speaker
    • Shows tool calls inline
  4. Tool Panel (Bottom)

    • Available tools with point costs
    • Grayed out when detective doesn't use them
    • Pulse animation when used
  5. Timeline (Top)

    • Shows round progression
    • Investigation points remaining

Build Priority:

Week 1 (Days 1-3):

  • Core game loop
  • 3 pre-scripted scenarios
  • Basic UI
  • LLM role prompts

Week 1 (Days 4-5):

  • MCP story generator
  • Polish UI
  • ElevenLabs voices

Week 1 (Day 6):

  • Demo video
  • Deploy

Week 1 (Day 7):

  • Buffer

๐Ÿ”ง TOOLS + DATA ARCHITECTURE

How Tools Get Their Data:

generate_crime_scenario() MCP
    โ†“
Creates complete case with ALL data
    โ†“
Stores in Database/Memory
    โ†“
Tools query this data when called
    โ†“
Return results to Detective

Example Data Structure:

# What generate_crime_scenario() creates and stores:

case_data = {
  "case_id": "A47",
  "victim": {
    "name": "Marcus Chen",
    "age": 42,
    "occupation": "Tech CEO",
    "time_of_death": "8:47 PM"
  },
  
  "suspects": [
    {
      "id": "suspect_1",
      "llm": "claude",  # Assigned at runtime
      "name": "Sarah Johnson",
      "role": "CFO",
      "is_murderer": True,
      "motive": "Embezzlement discovered",
      "true_location": "Crime scene",
      "alibi_story": "At home watching Netflix",
      "phone_number": "+1-555-0101"
    },
    {
      "id": "suspect_2", 
      "llm": "gemini",
      "name": "David Park",
      "role": "Janitor",
      "is_murderer": False,
      "true_location": "2 blocks away",
      "alibi_story": "Working late on 5th floor",
      "phone_number": "+1-555-0102"
    }
    # ... 2 more suspects
  ],
  
  "evidence": {
    "location_data": {
      "suspect_1_phone": {
        "8:47 PM": {"lat": 37.7749, "lng": -122.4194, "location": "Crime scene"},
        "8:50 PM": {"lat": 37.7750, "lng": -122.4200, "location": "0.1 mi away"}
      },
      "suspect_2_phone": {
        "8:47 PM": {"lat": 37.7800, "lng": -122.4300, "location": "2 blocks away"}
      }
    },
    
    "footage_data": {
      "10th_floor_camera": {
        "8:45-8:50 PM": {
          "visible_people": ["Person in black hoodie entering"],
          "quality": "Grainy",
          "key_frame": "8:47 PM - figure strikes victim"
        }
      },
      "lobby_camera": {
        "8:40-8:55 PM": {
          "visible_people": ["Suspect 1 entering at 8:43", "Suspect 1 leaving at 8:52"],
          "notes": "Suspect changed clothes"
        }
      }
    },
    
    "dna_evidence": {
      "trophy_weapon": {
        "primary_match": "suspect_1",
        "confidence": "95%",
        "notes": "Clear fingerprints found"
      },
      "door_handle": {
        "matches": ["suspect_1", "suspect_2", "victim"],
        "notes": "Multiple people touched door"
      }
    },
    
    "alibis": {
      "suspect_1_alibi": {
        "contact": "Nobody (claims was alone)",
        "verifiable": False,
        "truth": "Lying - was at crime scene"
      },
      "suspect_2_alibi": {
        "contact": "+1-555-0199",
        "contact_name": "Security Guard Tom",
        "verifiable": True,
        "truth": "Telling truth - saw him on 5th floor"
      }
    }
  },
  
  "timeline": {
    "8:30 PM": "Victim stays late working",
    "8:43 PM": "Suspect 1 enters building",
    "8:45 PM": "Suspect 2 seen on 5th floor",
    "8:47 PM": "Murder occurs",
    "8:52 PM": "Suspect 1 leaves building"
  }
}

MCP Tools Query This Data:

@mcp_tool
def get_location(phone_number: str, timestamp: str) -> dict:
    """Query the case database for location data"""
    
    # Find which suspect has this phone number
    suspect = find_suspect_by_phone(phone_number)
    
    # Look up their location at this time
    location = case_data["evidence"]["location_data"][f"{suspect}_phone"][timestamp]
    
    return {
        "timestamp": timestamp,
        "coordinates": f"{location['lat']}, {location['lng']}",
        "description": location['location'],
        "accuracy": "Cell tower triangulation ยฑ50m"
    }

@mcp_tool  
def get_footage(location: str, time_range: str) -> dict:
    """Query case database for camera footage"""
    
    footage = case_data["evidence"]["footage_data"].get(location, {}).get(time_range)
    
    if not footage:
        return {"error": "No camera at this location/time"}
    
    return {
        "location": location,
        "time_range": time_range,
        "visible_people": footage["visible_people"],
        "quality": footage["quality"],
        "key_details": footage.get("key_frame", "No significant events")
    }

@mcp_tool
def get_dna_test(evidence_id: str) -> dict:
    """Query case database for DNA/fingerprint evidence"""
    
    dna = case_data["evidence"]["dna_evidence"].get(evidence_id)
    
    if not dna:
        return {"error": "Evidence not found or not testable"}
    
    # Simulate processing time
    sleep(2)  # Dramatic pause
    
    return {
        "evidence_id": evidence_id,
        "primary_match": get_suspect_name(dna["primary_match"]),
        "confidence": dna["confidence"],
        "notes": dna["notes"]
    }

@mcp_tool
def call_alibi(phone_number: str) -> dict:
    """Call an alibi witness"""
    
    # Find alibi in database
    alibi = None
    for suspect_alibi in case_data["evidence"]["alibis"].values():
        if suspect_alibi.get("contact") == phone_number:
            alibi = suspect_alibi
            break
    
    if not alibi:
        return {"error": "Number not found"}
    
    # If alibi is truthful, confirm story
    if alibi["truth"].startswith("Telling truth"):
        response = f"Yes, I can confirm they were with me at that time."
    else:
        response = f"Uh... yes, they were with me. Definitely."
        # Add inconsistency markers for detective to notice
    
    return {
        "contact_name": alibi.get("contact_name", "Unknown"),
        "response": response,
        "confidence": "High" if alibi["verifiable"] else "Uncertain",
        "red_flags": [] if alibi["verifiable"] else ["Hesitant response", "No details provided"]
    }

๐Ÿ—„๏ธ Storing Data IN MEMORY PER SESSION

Implementation:

# Single game session stored in memory
game_sessions = {}

@app.post("/start_game")
def start_game(session_id: str):
    # Generate case and store in memory
    case_data = generate_crime_scenario()
    game_sessions[session_id] = {
        "case_data": case_data,
        "state": "active",
        "round": 1
    }
    return {"case_id": session_id}

@mcp_tool
def get_location(session_id: str, phone: str, time: str):
    # Query from memory
    case_data = game_sessions[session_id]["case_data"]
    return case_data["evidence"]["location_data"][phone][time]

๐Ÿ’ป TECH STACK

Gradio + Custom HTML

Frontend: Gradio + Custom HTML/CSS/JS blocks
Backend: Python/Gradio
MCP Server: Built-in
Deployment: HuggingFace Space

๐Ÿ—๏ธ FINAL TECH STACK RECOMMENDATION

The Winning Stack:

Frontend:
  - Gradio 6.x (required)
  - Custom HTML/CSS blocks for beautiful UI
  - JavaScript for animations

Backend:
  - Python 3.11+
  - FastAPI (embedded in Gradio)
  - Async/await for LLM calls

MCP Implementation:
  - Python MCP SDK
  - Built into same app
  - Tools defined as Python functions

LLM APIs:
  - Anthropic Claude (via MCP or direct API)
  - OpenAI GPT-4
  - Google Gemini
  - Meta Llama (via HuggingFace)

Voice:
  - ElevenLabs API (for narrator/voices)

Storage:
  - In-memory (Python dict)

Deployment:
  - HuggingFace Space (required)
  - Modal for compute-heavy tasks (optional, for sponsor prize)

Dependencies:
  - gradio>=6.0
  - anthropic
  - openai  
  - google-generativeai
  - elevenlabs
  - python-dotenv

๐Ÿ“ PROJECT STRUCTURE

murder-ai/
โ”œโ”€โ”€ app.py                 # Main Gradio app
โ”œโ”€โ”€ requirements.txt       # Python dependencies
โ”œโ”€โ”€ README.md             # HuggingFace Space readme (IMPORTANT!)
โ”‚
โ”œโ”€โ”€ game/
โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ”œโ”€โ”€ scenario_generator.py   # generate_crime_scenario()
โ”‚   โ”œโ”€โ”€ game_engine.py          # Game loop logic
โ”‚   โ””โ”€โ”€ llm_manager.py          # Handle multiple LLM APIs
โ”‚
โ”œโ”€โ”€ mcp/
โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ”œโ”€โ”€ tools.py               # MCP tool definitions
โ”‚   โ””โ”€โ”€ server.py              # MCP server setup
โ”‚
โ”œโ”€โ”€ ui/
โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ”œโ”€โ”€ components.py          # Custom Gradio components
โ”‚   โ””โ”€โ”€ styles.css             # Custom CSS
โ”‚
โ”œโ”€โ”€ prompts/
โ”‚   โ”œโ”€โ”€ murderer.txt
โ”‚   โ”œโ”€โ”€ detective.txt
โ”‚   โ”œโ”€โ”€ witness.txt
โ”‚   โ””โ”€โ”€ alibi.txt
โ”‚
โ”œโ”€โ”€ scenarios/
โ”‚   โ”œโ”€โ”€ silicon_valley.json    # Pre-scripted fallback
โ”‚   โ”œโ”€โ”€ coffee_shop.json
โ”‚   โ””โ”€โ”€ art_gallery.json
โ”‚
โ””โ”€โ”€ assets/
    โ”œโ”€โ”€ logo.png
    โ””โ”€โ”€ demo_video.mp4

๐ŸŽจ GRADIO UI ARCHITECTURE

Modern Gradio 6 Approach:

import gradio as gr

# Custom CSS for beautiful UI
custom_css = """
.evidence-board {
    background: url('cork-texture.jpg');
    padding: 20px;
    border-radius: 10px;
}

.suspect-card {
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    border-radius: 15px;
    padding: 15px;
    color: white;
}

.chat-message {
    font-family: 'Courier New', monospace;
    animation: typewriter 0.5s;
}

@keyframes typewriter {
    from { opacity: 0; }
    to { opacity: 1; }
}

Main Gradio Interface

with gr.Blocks() as demo:
    
    gr.Markdown("# ๐Ÿ•ต๏ธ MURDER.AI")
    
    with gr.Row():
        # Left: Suspect Cards
        with gr.Column(scale=1):
            gr.Markdown("## Suspects")
            suspect_1 = gr.HTML(elem_classes="suspect-card")
            suspect_2 = gr.HTML(elem_classes="suspect-card")
            suspect_3 = gr.HTML(elem_classes="suspect-card")
            suspect_4 = gr.HTML(elem_classes="suspect-card")
        
        # Center: Main Game Area
        with gr.Column(scale=2):
            chatbot = gr.Chatbot(
                label="Investigation",
                height=500,
                type="messages"
            )
            
            # Tool call display
            tool_output = gr.HTML(label="Tool Results")
            
        # Right: Evidence Board
        with gr.Column(scale=1):
            gr.Markdown("## Evidence Board")
            evidence_board = gr.HTML(
                elem_classes="evidence-board",
                value="<p>No evidence yet...</p>"
            )
    
    # Bottom: Controls
    with gr.Row():
        start_btn = gr.Button("๐ŸŽฒ Generate New Case", variant="primary")
        next_round_btn = gr.Button("โ–ถ๏ธ Next Round", interactive=False)
    
    # State management
    game_state = gr.State({})
    
    # Event handlers
    start_btn.click(
        fn=start_new_game,
        outputs=[game_state, chatbot, suspect_1, suspect_2, suspect_3, suspect_4]
    )
    
    next_round_btn.click(
        fn=run_game_round,
        inputs=[game_state],
        outputs=[game_state, chatbot, tool_output, evidence_board]
    )

demo.launch(
    theme=gr.themes.Noir(),
    css=custom_css
)