File size: 6,238 Bytes
81e1c72 380be21 81e1c72 380be21 81e1c72 380be21 9e6c181 380be21 81e1c72 380be21 dd5d973 81e1c72 dd5d973 81e1c72 380be21 81e1c72 380be21 81e1c72 380be21 dd5d973 81e1c72 dd5d973 380be21 81e1c72 dd5d973 81e1c72 380be21 |
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 |
from typing import Type
import streamlit as st
from streamlit import session_state
from game import Game
from agent_interfaces import HumanAgentInterface
from message import Message
from prompts import fetch_prompt, format_prompt
st.set_page_config(layout="wide", page_title="Chameleon", page_icon="img/logo.svg")
def display_message(message: Message):
if message.type == "verbose":
messages_container.markdown(f":green[{message.content}]")
elif message.type == "debug":
messages_container.markdown(f":orange[DEBUG: {message.content}]")
else:
messages_container.markdown(f"{message.content}")
if "messages" not in session_state:
session_state.messages = []
session_state.awaiting_human_input = False
session_state.game_state = "game_start"
class StreamlitInterface(HumanAgentInterface):
def add_message(self, message: Message):
super().add_message(message)
session_state.messages.append(message)
display_message(message)
def _generate(self) -> str:
return session_state.user_input
class StreamlitGame(Game):
"""A Streamlit version of the Game class that uses a state machine to manage the game state."""
def run_game(self):
"""Starts the game."""
if session_state.game_state == "game_start":
self.game_message(fetch_prompt("game_rules"))
session_state.game_state = "setup_round"
if session_state.game_state == "setup_round":
self.setup_round()
session_state.game_state = "animal_description"
if session_state.game_state in ["animal_description", "chameleon_guess", "herd_vote"]:
self.run_round()
if session_state.game_state == "resolve_round":
self.resolve_round()
session_state.game_state = "setup_round"
def run_round(self):
"""Starts the round."""
# Phase I: Collect Player Animal Descriptions
if session_state.game_state == "animal_description":
for current_player in self.players:
if current_player.id not in [animal_description['player_id'] for animal_description in self.round_animal_descriptions]:
if current_player.interface.is_human:
if not session_state.awaiting_human_input:
self.game_message(fetch_prompt("player_describe_animal"), current_player)
session_state.awaiting_human_input = True
break
else:
self.player_turn_animal_description(current_player)
session_state.awaiting_human_input = False
else:
self.game_message(fetch_prompt("player_describe_animal"), current_player)
self.player_turn_animal_description(current_player)
if len(self.round_animal_descriptions) == len(self.players):
session_state.game_state = "chameleon_guess"
session_state.awaiting_human_input = False
# Phase II: Chameleon Guesses the Animal
if session_state.game_state == "chameleon_guess":
self.game_message("All players have spoken. The Chameleon will now guess the secret animal...")
player_responses = self.format_animal_descriptions(exclude=self.chameleon)
self.game_message(format_prompt("chameleon_guess_animal", player_responses=player_responses), self.chameleon)
if self.players[self.human_index].role == "chameleon":
if not session_state.awaiting_human_input:
session_state.awaiting_human_input = True
else:
self.player_turn_chameleon_guess(self.chameleon)
session_state.awaiting_human_input = False
else:
self.player_turn_chameleon_guess(self.chameleon)
session_state.awaiting_human_input = False
session_state.game_state = "herd_vote"
# Phase III: The Herd Votes for who they think the Chameleon is
if session_state.game_state == "herd_vote":
for current_player in self.players:
if current_player.role == "herd" and current_player.id not in [vote['voter_id'] for vote in self.herd_vote_tally]:
player_responses = self.format_animal_descriptions(exclude=current_player)
if current_player.interface.is_human:
if not session_state.awaiting_human_input:
self.game_message(format_prompt("vote", player_responses=player_responses), current_player)
session_state.awaiting_human_input = True
break
else:
self.player_turn_herd_vote(current_player)
session_state.awaiting_human_input = False
else:
self.game_message(format_prompt("vote", player_responses=player_responses), current_player)
self.player_turn_herd_vote(current_player)
if len(self.herd_vote_tally) == len(self.players) - 1:
session_state.game_state = "resolve_round"
# Streamlit App
margin_size = 1
center_size = 3
title_left, title_center, title_right = st.columns([margin_size, center_size, margin_size])
with title_center:
st.markdown("# :rainbow[Chameleon]")
left, center, right = st.columns([margin_size, center_size, margin_size])
with center:
messages_container = st.container()
messages_container.write("Welcome to Chameleon! A social deduction game powered by LLMs.")
messages_container.write("Enter your name to begin...")
user_input = st.chat_input("Your response:")
if st.session_state.messages:
for message in st.session_state.messages:
display_message(message)
if user_input:
if "game" not in st.session_state:
st.session_state.game = StreamlitGame(human_name=user_input, verbose=True, human_interface=StreamlitInterface)
session_state.user_input = user_input
st.session_state.game.run_game()
|