chameleon / src /app.py
Eric Botti
streamlit app version of game
81e1c72
raw
history blame
6.24 kB
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()