Spaces:
Running
Running
File size: 8,798 Bytes
13d61dc 5029863 86a82e2 13d61dc 5029863 86a82e2 13d61dc 5029863 13d61dc 4b16b59 de805e3 13d61dc 86a82e2 13d61dc 86a82e2 13d61dc 804fa02 13d61dc 804fa02 5029863 804fa02 13d61dc 804fa02 13d61dc 804fa02 13d61dc de805e3 13d61dc de805e3 13d61dc de805e3 13d61dc 804fa02 13d61dc 86a82e2 13d61dc 4b16b59 13d61dc 4b16b59 13d61dc 4b16b59 13d61dc 4b16b59 13d61dc 4b16b59 13d61dc 4b16b59 13d61dc |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
import uuid
from .scenario_generator import generate_crime_scenario
from .llm_manager import LLMManager
from .voice_manager import VoiceManager
from .ai_detective import AIDetective
from mcp import tools
class GameInstance:
def __init__(self, difficulty="medium"):
self.id = str(uuid.uuid4())
self.scenario = generate_crime_scenario(difficulty)
self.llm_manager = LLMManager()
self.voice_manager = VoiceManager()
self.ai_detective = None # Initialized later to avoid circular dep issues if any, or just now.
self.round = 1
self.max_rounds = 3 # 3 Chances
self.points = 10
self.evidence_revealed = [] # List of strings or result dicts
self.logs = [] # Chat logs
self.game_over = False
self.verdict_correct = False
self.eliminated_suspects = []
self.unlocked_evidence = [] # Track unlocked DNA items
# Initialize Agents
self._init_agents()
self.ai_detective = AIDetective(self)
def run_ai_step(self):
"""Executes one turn for the AI Detective."""
if self.game_over:
return {"thought": "Game Over.", "action": "none"}
decision = self.ai_detective.decide_next_move()
action_type = decision.get("action")
thought = decision.get("thought", "Thinking...")
result = {}
if action_type == "use_tool":
tool_name = decision.get("tool_name")
kwargs = decision.get("args", {})
result = self.use_tool(tool_name, **kwargs)
result["type"] = "evidence"
elif action_type == "chat":
suspect_id = decision.get("suspect_id")
msg = decision.get("message")
response = self.question_suspect(suspect_id, msg)
result = {
"type": "chat",
"suspect_id": suspect_id,
"question": msg,
"response": response
}
elif action_type == "accuse":
suspect_id = decision.get("suspect_id")
# Map suspect_id if it's just "suspect_1" (which it is)
# But make_accusation handles ID.
outcome = self.make_accusation(suspect_id)
result = {
"type": "game_over",
"outcome": outcome
}
# Record result for AI memory
self.ai_detective.record_result(action_type, result)
return {
"thought": thought,
"action": action_type,
"result": result
}
def _init_agents(self):
# 1. Detective
detective_context = {
"victim_name": self.scenario["victim"]["name"],
"time_of_death": self.scenario["victim"]["time_of_death"],
"location": self.scenario["evidence"]["location_data"].get("suspect_1_phone", {}).get("8:47 PM", {}).get("location", "Unknown"), # Approximate
"investigation_state": "Initial briefing."
}
self.llm_manager.create_agent("detective", "detective", detective_context)
# 2. Suspects
for i, suspect in enumerate(self.scenario["suspects"]):
role = "murderer" if suspect["is_murderer"] else "witness"
# Generate or retrieve Alibi ID
# In a real app, this should be in the JSON. For now, we synth it.
alibi_id = suspect.get("alibi_id", f"ALIBI-{100+i}")
suspect["alibi_id"] = alibi_id
# Assign Voice
if "gender" in suspect:
suspect["voice_id"] = self.voice_manager.assign_voice(suspect["gender"], suspect.get("role", ""))
# Context for prompt
context = {
"name": suspect["name"],
"victim_name": self.scenario["victim"]["name"],
"alibi_story": suspect["alibi_story"],
"bio": suspect["bio"],
"true_location": suspect["true_location"],
"phone_number": suspect.get("phone_number", "Unknown"),
"alibi_id": alibi_id, # Inject Alibi ID
# Murderer specific
"method": self.scenario["title"],
"location": self.scenario["victim"].get("location", "the scene"),
"motive": suspect["motive"]
}
self.llm_manager.create_agent(suspect["id"], role, context)
def log_event(self, speaker, message):
self.logs.append({"speaker": speaker, "message": message})
def question_suspect(self, suspect_id, question):
if self.game_over:
return "Game Over"
suspect_name = next((s["name"] for s in self.scenario["suspects"] if s["id"] == suspect_id), "Unknown")
# 1. Detective asks (simulated log)
self.log_event("Detective", f"To {suspect_name}: {question}")
# 2. Suspect responds
response = self.llm_manager.get_response(suspect_id, question)
self.log_event(suspect_name, response)
return response
def use_tool(self, tool_name, **kwargs):
if self.points <= 0:
return {"error": "Not enough investigation points!"}
cost = 0
result = {}
# Map tool names to functions
if tool_name == "get_location":
cost = 2
result = tools.get_location(self.scenario, kwargs.get("phone_number"), kwargs.get("timestamp"))
elif tool_name == "get_footage":
cost = 3
result = tools.get_footage(self.scenario, kwargs.get("location"), kwargs.get("time_range"))
# Handle unlocks
if "unlocks" in result:
new_items = []
for item_id in result["unlocks"]:
if item_id not in self.unlocked_evidence:
self.unlocked_evidence.append(item_id)
new_items.append(item_id)
result["newly_unlocked"] = new_items
elif tool_name == "get_dna_test":
cost = 4
result = tools.get_dna_test(self.scenario, kwargs.get("evidence_id"))
elif tool_name == "call_alibi":
cost = 1
result = tools.call_alibi(self.scenario, **kwargs)
else:
return {"error": f"Unknown tool: {tool_name}"}
if "error" in result:
return result # Don't deduct points for errors
self.points -= cost
# Inject input context for AI memory
if isinstance(result, dict):
result["_input_args"] = kwargs
self.evidence_revealed.append(result)
self.log_event("System", f"Used {tool_name}. Cost: {cost} pts. Result: {str(result)}")
return result
def advance_round(self):
# Deprecated: Rounds advance via accusation now
pass
def make_accusation(self, suspect_id):
murderer = next((s for s in self.scenario["suspects"] if s["is_murderer"]), None)
suspect_name = next((s["name"] for s in self.scenario["suspects"] if s["id"] == suspect_id), "Unknown")
if murderer and murderer["id"] == suspect_id:
self.game_over = True
self.verdict_correct = True
return {
"result": "win",
"message": f"CORRECT! {murderer['name']} was the murderer."
}
else:
# Wrong accusation
self.eliminated_suspects.append(suspect_id)
self.log_event("System", f"Incorrect accusation: {suspect_name}. Eliminated.")
if self.round >= self.max_rounds:
self.game_over = True
self.verdict_correct = False
return {
"result": "loss",
"message": f"WRONG. That was your last chance. The killer was {murderer['name']}."
}
else:
# Advance Round
self.round += 1
self.points += 5
return {
"result": "continue",
"message": f"{suspect_name} is INNOCENT. +5 Points. Try again.",
"eliminated_id": suspect_id,
"new_round": self.round,
"new_points": self.points
}
# Global Session Store
SESSIONS = {}
def start_game(difficulty="medium"):
game = GameInstance(difficulty)
SESSIONS[game.id] = game
return game.id, game
def get_game(session_id):
return SESSIONS.get(session_id)
|