Update app.py
Browse files
app.py
CHANGED
|
@@ -22,57 +22,27 @@ def llm_inference(messages):
|
|
| 22 |
response += choice['message']['content']
|
| 23 |
return response
|
| 24 |
|
| 25 |
-
|
| 26 |
-
"Colonel Mustard": {
|
| 27 |
-
"personality": "",
|
| 28 |
-
"knowledge": "",
|
| 29 |
-
"is_murderer": False
|
| 30 |
-
},
|
| 31 |
-
"Miss Scarlett": {
|
| 32 |
-
"personality": "",
|
| 33 |
-
"knowledge": "",
|
| 34 |
-
"is_murderer": False
|
| 35 |
-
},
|
| 36 |
-
"Professor Plum": {
|
| 37 |
-
"personality": "",
|
| 38 |
-
"knowledge": "",
|
| 39 |
-
"is_murderer": False
|
| 40 |
-
},
|
| 41 |
-
"Mrs. Peacock": {
|
| 42 |
-
"personality": "",
|
| 43 |
-
"knowledge": "",
|
| 44 |
-
"is_murderer": False
|
| 45 |
-
},
|
| 46 |
-
"Mr. Green": {
|
| 47 |
-
"personality": "",
|
| 48 |
-
"knowledge": "",
|
| 49 |
-
"is_murderer": False
|
| 50 |
-
},
|
| 51 |
-
"Dr. Orchid": {
|
| 52 |
-
"personality": "",
|
| 53 |
-
"knowledge": "",
|
| 54 |
-
"is_murderer": False
|
| 55 |
-
}
|
| 56 |
-
}
|
| 57 |
-
|
| 58 |
weapons = ["Candlestick", "Dagger", "Lead Pipe", "Revolver", "Rope", "Wrench", "Poison"]
|
| 59 |
locations = ["Kitchen", "Ballroom", "Conservatory", "Dining Room", "Library", "Study", "Billiard Room", "Lounge"]
|
| 60 |
|
| 61 |
possible_personalities = [
|
| 62 |
-
"stern and suspicious",
|
| 63 |
-
"charming but evasive",
|
| 64 |
-
"intellectual and nervous",
|
| 65 |
-
"gracious but secretive",
|
| 66 |
-
"amiable yet deceptive",
|
| 67 |
-
"hot-headed and impulsive",
|
| 68 |
-
"calm and collected",
|
| 69 |
-
"mysterious and aloof",
|
| 70 |
-
"jovial but cunning",
|
| 71 |
-
"nervous and jittery",
|
| 72 |
-
"sarcastic and witty",
|
| 73 |
-
"arrogant and dismissive"
|
| 74 |
]
|
| 75 |
|
|
|
|
|
|
|
| 76 |
game_state = {
|
| 77 |
"murderer": "",
|
| 78 |
"weapon": "",
|
|
@@ -84,46 +54,62 @@ game_state = {
|
|
| 84 |
}
|
| 85 |
|
| 86 |
def initialize_game():
|
| 87 |
-
game_state["murderer"] = random.choice(
|
| 88 |
game_state["weapon"] = random.choice(weapons)
|
| 89 |
game_state["location"] = random.choice(locations)
|
| 90 |
game_state["is_game_over"] = False
|
| 91 |
game_state["clues"] = []
|
| 92 |
game_state["history"] = []
|
| 93 |
game_state["accused"] = False
|
| 94 |
-
|
| 95 |
-
random.
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 100 |
print(f"Debug: Murderer is {game_state['murderer']}, Weapon is {game_state['weapon']}, Location is {game_state['location']}")
|
| 101 |
-
for suspect in suspects:
|
| 102 |
-
print(f"Debug: {suspect}'
|
| 103 |
-
|
| 104 |
-
def generate_knowledge(
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
|
|
|
| 108 |
else:
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
elif known_item == "location":
|
| 116 |
-
known_elements.append(f"You know that the location is {game_state['location']}.")
|
| 117 |
-
elif known_item == "murderer":
|
| 118 |
-
not_murderer = random.choice([s for s in suspects if s != suspect_name and s != game_state["murderer"]])
|
| 119 |
-
known_elements.append(f"You know that {not_murderer} is not the murderer.")
|
| 120 |
-
knowledge.extend(known_elements)
|
| 121 |
-
return ' '.join(knowledge)
|
| 122 |
|
| 123 |
def get_ai_response(suspect_name, player_input):
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 127 |
user_message = f"The detective asks: \"{player_input}\" As {suspect_name}, respond in first person, staying in character."
|
| 128 |
messages = [
|
| 129 |
{"role": "system", "content": system_prompt},
|
|
@@ -144,10 +130,10 @@ def process_input(player_input):
|
|
| 144 |
game_state["history"].append(("System", result))
|
| 145 |
return result, game_state["history"]
|
| 146 |
else:
|
| 147 |
-
for
|
| 148 |
-
if
|
| 149 |
-
ai_response = get_ai_response(
|
| 150 |
-
game_state["history"].append((
|
| 151 |
extract_clues(ai_response)
|
| 152 |
return ai_response, game_state["history"]
|
| 153 |
return "Please direct your question to a suspect.", game_state["history"]
|
|
@@ -160,9 +146,9 @@ def extract_clues(ai_response):
|
|
| 160 |
for location in locations:
|
| 161 |
if location.lower() in ai_response.lower() and location != game_state["location"]:
|
| 162 |
clues.append(f"The location is not the {location}.")
|
| 163 |
-
for
|
| 164 |
-
if
|
| 165 |
-
clues.append(f"{
|
| 166 |
for clue in clues:
|
| 167 |
if clue not in game_state["clues"]:
|
| 168 |
game_state["clues"].append(clue)
|
|
@@ -171,9 +157,9 @@ def handle_accusation(player_input):
|
|
| 171 |
suspect_guess = None
|
| 172 |
weapon_guess = None
|
| 173 |
location_guess = None
|
| 174 |
-
for
|
| 175 |
-
if
|
| 176 |
-
suspect_guess =
|
| 177 |
break
|
| 178 |
for weapon in weapons:
|
| 179 |
if weapon.lower() in player_input.lower():
|
|
@@ -200,36 +186,60 @@ def chat_interface(player_input):
|
|
| 200 |
clues_display = "\n".join(game_state["clues"])
|
| 201 |
return chat_history, clues_display
|
| 202 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 203 |
def restart_game():
|
| 204 |
initialize_game()
|
| 205 |
-
return "", ""
|
| 206 |
|
| 207 |
with gr.Blocks() as demo:
|
| 208 |
gr.Markdown("# Murder Mystery Game")
|
| 209 |
-
with gr.
|
| 210 |
-
with gr.
|
| 211 |
-
gr.
|
| 212 |
-
|
| 213 |
-
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 226 |
|
| 227 |
def send_message(player_input):
|
| 228 |
chat_history, clues_display = chat_interface(player_input)
|
| 229 |
-
|
|
|
|
| 230 |
|
| 231 |
-
send_button.click(send_message, inputs=player_input, outputs=[chatbox, player_input, clues])
|
| 232 |
-
restart_button.click(fn=restart_game, inputs=None, outputs=[chatbox, clues])
|
| 233 |
|
| 234 |
initialize_game()
|
| 235 |
demo.launch()
|
|
|
|
| 22 |
response += choice['message']['content']
|
| 23 |
return response
|
| 24 |
|
| 25 |
+
suspect_names = ["Colonel Mustard", "Miss Scarlett", "Professor Plum", "Mrs. Peacock", "Mr. Green", "Dr. Orchid"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
weapons = ["Candlestick", "Dagger", "Lead Pipe", "Revolver", "Rope", "Wrench", "Poison"]
|
| 27 |
locations = ["Kitchen", "Ballroom", "Conservatory", "Dining Room", "Library", "Study", "Billiard Room", "Lounge"]
|
| 28 |
|
| 29 |
possible_personalities = [
|
| 30 |
+
{"description": "stern and suspicious", "hot_headed": False},
|
| 31 |
+
{"description": "charming but evasive", "hot_headed": False},
|
| 32 |
+
{"description": "intellectual and nervous", "hot_headed": False},
|
| 33 |
+
{"description": "gracious but secretive", "hot_headed": False},
|
| 34 |
+
{"description": "amiable yet deceptive", "hot_headed": False},
|
| 35 |
+
{"description": "hot-headed and impulsive", "hot_headed": True},
|
| 36 |
+
{"description": "calm and collected", "hot_headed": False},
|
| 37 |
+
{"description": "mysterious and aloof", "hot_headed": False},
|
| 38 |
+
{"description": "jovial but cunning", "hot_headed": False},
|
| 39 |
+
{"description": "nervous and jittery", "hot_headed": False},
|
| 40 |
+
{"description": "sarcastic and witty", "hot_headed": False},
|
| 41 |
+
{"description": "arrogant and dismissive", "hot_headed": True}
|
| 42 |
]
|
| 43 |
|
| 44 |
+
suspects = {}
|
| 45 |
+
|
| 46 |
game_state = {
|
| 47 |
"murderer": "",
|
| 48 |
"weapon": "",
|
|
|
|
| 54 |
}
|
| 55 |
|
| 56 |
def initialize_game():
|
| 57 |
+
game_state["murderer"] = random.choice(suspect_names)
|
| 58 |
game_state["weapon"] = random.choice(weapons)
|
| 59 |
game_state["location"] = random.choice(locations)
|
| 60 |
game_state["is_game_over"] = False
|
| 61 |
game_state["clues"] = []
|
| 62 |
game_state["history"] = []
|
| 63 |
game_state["accused"] = False
|
| 64 |
+
random.shuffle(possible_personalities)
|
| 65 |
+
alibi_locations = random.sample(locations, len(suspect_names))
|
| 66 |
+
alibis = {}
|
| 67 |
+
for i, suspect_name in enumerate(suspect_names):
|
| 68 |
+
suspect = {
|
| 69 |
+
"name": suspect_name,
|
| 70 |
+
"is_murderer": suspect_name == game_state["murderer"],
|
| 71 |
+
"personality": possible_personalities[i % len(possible_personalities)]["description"],
|
| 72 |
+
"hot_headed": possible_personalities[i % len(possible_personalities)]["hot_headed"],
|
| 73 |
+
"anger_level": 0,
|
| 74 |
+
"alibi_location": alibi_locations[i],
|
| 75 |
+
"alibi_with": [],
|
| 76 |
+
"knowledge": ""
|
| 77 |
+
}
|
| 78 |
+
suspects[suspect_name] = suspect
|
| 79 |
+
for suspect in suspects.values():
|
| 80 |
+
others_in_same_location = [s["name"] for s in suspects.values() if s["alibi_location"] == suspect["alibi_location"] and s["name"] != suspect["name"]]
|
| 81 |
+
suspect["alibi_with"] = others_in_same_location
|
| 82 |
+
for suspect in suspects.values():
|
| 83 |
+
suspect["knowledge"] = generate_knowledge(suspect)
|
| 84 |
print(f"Debug: Murderer is {game_state['murderer']}, Weapon is {game_state['weapon']}, Location is {game_state['location']}")
|
| 85 |
+
for suspect in suspects.values():
|
| 86 |
+
print(f"Debug: {suspect['name']} - Personality: {suspect['personality']}, Hot-headed: {suspect['hot_headed']}, Alibi: {suspect['alibi_location']} with {', '.join(suspect['alibi_with'])}")
|
| 87 |
+
|
| 88 |
+
def generate_knowledge(suspect):
|
| 89 |
+
if suspect["is_murderer"]:
|
| 90 |
+
suspect["alibi_location"] = random.choice([loc for loc in locations if loc != game_state["location"]])
|
| 91 |
+
suspect["alibi_with"] = []
|
| 92 |
+
knowledge = "You are the murderer. Lie about your alibi and deflect suspicion. You have no knowledge of the real weapon or location."
|
| 93 |
else:
|
| 94 |
+
knowledge = f"You were in the {suspect['alibi_location']} with {', '.join(suspect['alibi_with'])} during the murder."
|
| 95 |
+
if random.choice([True, False]):
|
| 96 |
+
knowledge += f" You know that the weapon is the {game_state['weapon']}."
|
| 97 |
+
if random.choice([True, False]):
|
| 98 |
+
knowledge += f" You know that the location of the murder was the {game_state['location']}."
|
| 99 |
+
return knowledge
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 100 |
|
| 101 |
def get_ai_response(suspect_name, player_input):
|
| 102 |
+
suspect = suspects[suspect_name]
|
| 103 |
+
suspect["anger_level"] += 1
|
| 104 |
+
personality = suspect["personality"]
|
| 105 |
+
knowledge = suspect["knowledge"]
|
| 106 |
+
anger_level = suspect["anger_level"]
|
| 107 |
+
hot_headed = suspect["hot_headed"]
|
| 108 |
+
system_prompt = f"You are {suspect_name}, who is {personality}. {knowledge}"
|
| 109 |
+
if hot_headed:
|
| 110 |
+
system_prompt += f" You are getting angrier each time you are questioned. Your anger level is {anger_level}."
|
| 111 |
+
if suspect["is_murderer"]:
|
| 112 |
+
system_prompt += " You are the murderer and will lie to protect yourself."
|
| 113 |
user_message = f"The detective asks: \"{player_input}\" As {suspect_name}, respond in first person, staying in character."
|
| 114 |
messages = [
|
| 115 |
{"role": "system", "content": system_prompt},
|
|
|
|
| 130 |
game_state["history"].append(("System", result))
|
| 131 |
return result, game_state["history"]
|
| 132 |
else:
|
| 133 |
+
for suspect_name in suspect_names:
|
| 134 |
+
if suspect_name.lower() in player_input.lower():
|
| 135 |
+
ai_response = get_ai_response(suspect_name, player_input)
|
| 136 |
+
game_state["history"].append((suspect_name, ai_response))
|
| 137 |
extract_clues(ai_response)
|
| 138 |
return ai_response, game_state["history"]
|
| 139 |
return "Please direct your question to a suspect.", game_state["history"]
|
|
|
|
| 146 |
for location in locations:
|
| 147 |
if location.lower() in ai_response.lower() and location != game_state["location"]:
|
| 148 |
clues.append(f"The location is not the {location}.")
|
| 149 |
+
for suspect_name in suspect_names:
|
| 150 |
+
if suspect_name.lower() in ai_response.lower() and suspect_name != game_state["murderer"]:
|
| 151 |
+
clues.append(f"{suspect_name} is not the murderer.")
|
| 152 |
for clue in clues:
|
| 153 |
if clue not in game_state["clues"]:
|
| 154 |
game_state["clues"].append(clue)
|
|
|
|
| 157 |
suspect_guess = None
|
| 158 |
weapon_guess = None
|
| 159 |
location_guess = None
|
| 160 |
+
for suspect_name in suspect_names:
|
| 161 |
+
if suspect_name.lower() in player_input.lower():
|
| 162 |
+
suspect_guess = suspect_name
|
| 163 |
break
|
| 164 |
for weapon in weapons:
|
| 165 |
if weapon.lower() in player_input.lower():
|
|
|
|
| 186 |
clues_display = "\n".join(game_state["clues"])
|
| 187 |
return chat_history, clues_display
|
| 188 |
|
| 189 |
+
def get_debug_info():
|
| 190 |
+
debug_info = ""
|
| 191 |
+
debug_info += f"Murderer: {game_state['murderer']}\n"
|
| 192 |
+
debug_info += f"Weapon: {game_state['weapon']}\n"
|
| 193 |
+
debug_info += f"Location: {game_state['location']}\n\n"
|
| 194 |
+
for suspect in suspects.values():
|
| 195 |
+
info = f"Name: {suspect['name']}\n"
|
| 196 |
+
info += f"Personality: {suspect['personality']}\n"
|
| 197 |
+
info += f"Hot-headed: {suspect['hot_headed']}\n"
|
| 198 |
+
info += f"Anger Level: {suspect['anger_level']}\n"
|
| 199 |
+
info += f"Is Murderer: {suspect['is_murderer']}\n"
|
| 200 |
+
info += f"Alibi Location: {suspect['alibi_location']}\n"
|
| 201 |
+
info += f"Alibi With: {', '.join(suspect['alibi_with'])}\n"
|
| 202 |
+
info += f"Knowledge: {suspect['knowledge']}\n\n"
|
| 203 |
+
debug_info += info
|
| 204 |
+
return debug_info
|
| 205 |
+
|
| 206 |
def restart_game():
|
| 207 |
initialize_game()
|
| 208 |
+
return "", "", ""
|
| 209 |
|
| 210 |
with gr.Blocks() as demo:
|
| 211 |
gr.Markdown("# Murder Mystery Game")
|
| 212 |
+
with gr.Tabs():
|
| 213 |
+
with gr.TabItem("Game"):
|
| 214 |
+
with gr.Row():
|
| 215 |
+
with gr.Column():
|
| 216 |
+
gr.Markdown("## Commands")
|
| 217 |
+
gr.Markdown("- **Ask a question to a suspect**: Include the suspect's name in your question.\n Example: *\"Miss Scarlett, where were you during the evening?\"*")
|
| 218 |
+
gr.Markdown("- **Make an accusation**: Include the word *\"accuse\"*.\n Example: *\"I accuse Colonel Mustard with the Rope in the Study.\"*")
|
| 219 |
+
player_input = gr.Textbox(lines=1, label="Your Input")
|
| 220 |
+
send_button = gr.Button("Send")
|
| 221 |
+
restart_button = gr.Button("Restart Game")
|
| 222 |
+
chatbox = gr.Textbox(lines=15, label="Chat History", interactive=False)
|
| 223 |
+
with gr.Column():
|
| 224 |
+
gr.Markdown("## Suspects")
|
| 225 |
+
gr.Markdown(', '.join(suspect_names))
|
| 226 |
+
gr.Markdown("## Weapons")
|
| 227 |
+
gr.Markdown(', '.join(weapons))
|
| 228 |
+
gr.Markdown("## Locations")
|
| 229 |
+
gr.Markdown(', '.join(locations))
|
| 230 |
+
clues = gr.Textbox(lines=15, label="Discovered Clues", interactive=False)
|
| 231 |
+
with gr.TabItem("Debug"):
|
| 232 |
+
debug_info = gr.Textbox(lines=30, label="Debug Information", interactive=False)
|
| 233 |
+
update_debug_button = gr.Button("Update Debug Info")
|
| 234 |
+
update_debug_button.click(fn=lambda: get_debug_info(), inputs=None, outputs=debug_info)
|
| 235 |
|
| 236 |
def send_message(player_input):
|
| 237 |
chat_history, clues_display = chat_interface(player_input)
|
| 238 |
+
debug_information = get_debug_info()
|
| 239 |
+
return chat_history, "", clues_display, debug_information
|
| 240 |
|
| 241 |
+
send_button.click(send_message, inputs=player_input, outputs=[chatbox, player_input, clues, debug_info])
|
| 242 |
+
restart_button.click(fn=restart_game, inputs=None, outputs=[chatbox, clues, debug_info])
|
| 243 |
|
| 244 |
initialize_game()
|
| 245 |
demo.launch()
|