Update jsinvn.py with OpenAI client integration and eliminated player flow
This commit is contained in:
parent
8a3939534d
commit
c6572eecee
401
jsinvn.py
401
jsinvn.py
@ -1,5 +1,15 @@
|
|||||||
import streamlit as st
|
import streamlit as st
|
||||||
import random
|
import random
|
||||||
|
import os
|
||||||
|
import requests
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
# 加载环境变量
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
# 获取Deepseek API配置
|
||||||
|
DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")
|
||||||
|
DEEPSEEK_BASE_URL = os.getenv("DEEPSEEK_BASE_URL", "https://api.deepseek.com")
|
||||||
|
|
||||||
# 页面配置
|
# 页面配置
|
||||||
st.set_page_config(
|
st.set_page_config(
|
||||||
@ -63,250 +73,45 @@ if "runoff" not in st.session_state:
|
|||||||
st.session_state.runoff = False
|
st.session_state.runoff = False
|
||||||
if "tied_players" not in st.session_state:
|
if "tied_players" not in st.session_state:
|
||||||
st.session_state.tied_players = []
|
st.session_state.tied_players = []
|
||||||
|
if "max_rounds" not in st.session_state:
|
||||||
|
st.session_state.max_rounds = 4
|
||||||
|
if "runoff_speeches" not in st.session_state:
|
||||||
|
st.session_state.runoff_speeches = []
|
||||||
|
if "player_runoff_speech" not in st.session_state:
|
||||||
|
st.session_state.player_runoff_speech = ""
|
||||||
|
if "player_runoff_speech_saved" not in st.session_state:
|
||||||
|
st.session_state.player_runoff_speech_saved = False
|
||||||
|
|
||||||
# 词语描述库
|
# 调用Deepseek API生成AI发言
|
||||||
word_descriptions = {
|
def call_deepseek_api(prompt):
|
||||||
"苹果": [
|
try:
|
||||||
"这是一种常见的东西",
|
url = f"{DEEPSEEK_BASE_URL}/chat/completions"
|
||||||
"有特定的颜色",
|
headers = {
|
||||||
"圆形的,口感不错",
|
"Authorization": f"Bearer {DEEPSEEK_API_KEY}",
|
||||||
"可以直接食用,也可以加工",
|
"Content-Type": "application/json"
|
||||||
"富含营养",
|
}
|
||||||
"通常生长在高处",
|
data = {
|
||||||
"有外皮和内部结构",
|
"model": "deepseek-chat",
|
||||||
"是一种健康的选择",
|
"messages": [
|
||||||
"在中国很常见",
|
{
|
||||||
"有些品种味道比较特别"
|
"role": "system",
|
||||||
|
"content": "你是一个谁是卧底游戏的玩家,需要根据你拿到的词语生成自然的发言,不能直接说出词语本身,发言要符合当前轮数的特点。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": prompt
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"橘子": [
|
"max_tokens": 100,
|
||||||
"这是一种可以食用的东西",
|
"temperature": 0.8
|
||||||
"有特定的颜色,味道有点特别",
|
}
|
||||||
"圆形的,有外皮",
|
response = requests.post(url, headers=headers, json=data, timeout=10)
|
||||||
"内部结构是一瓣一瓣的",
|
response.raise_for_status()
|
||||||
"富含营养",
|
result = response.json()
|
||||||
"通常生长在温暖的地方",
|
return result["choices"][0]["message"]["content"].strip()
|
||||||
"需要剥皮后食用",
|
except Exception as e:
|
||||||
"有不同的品种",
|
st.error(f"API调用失败: {str(e)}")
|
||||||
"汁水很多",
|
return None
|
||||||
"在某些季节比较常见"
|
|
||||||
],
|
|
||||||
"电脑": [
|
|
||||||
"这是一种电子设备",
|
|
||||||
"可以用来做很多事情",
|
|
||||||
"有屏幕和输入设备",
|
|
||||||
"需要电源才能使用",
|
|
||||||
"可以连接网络",
|
|
||||||
"有主机和显示部分",
|
|
||||||
"可以运行各种程序",
|
|
||||||
"现在很多家庭都有",
|
|
||||||
"有不同的类型",
|
|
||||||
"需要定期维护"
|
|
||||||
],
|
|
||||||
"手机": [
|
|
||||||
"这是一种便携式电子设备",
|
|
||||||
"可以用来沟通和获取信息",
|
|
||||||
"触摸操作,便于携带",
|
|
||||||
"需要充电才能使用",
|
|
||||||
"可以安装各种应用",
|
|
||||||
"有拍照功能",
|
|
||||||
"现在几乎人人都有",
|
|
||||||
"有不同的品牌和型号",
|
|
||||||
"可以用来娱乐",
|
|
||||||
"需要特定卡片才能通话"
|
|
||||||
],
|
|
||||||
"篮球": [
|
|
||||||
"这是一种球类用品",
|
|
||||||
"圆形的,有特定材质",
|
|
||||||
"需要用手操作",
|
|
||||||
"有特定的颜色",
|
|
||||||
"在特定的场地上使用",
|
|
||||||
"有不同的规格",
|
|
||||||
"可以用来进行比赛",
|
|
||||||
"需要充气才能使用",
|
|
||||||
"很多年轻人喜欢",
|
|
||||||
"有专业的赛事"
|
|
||||||
],
|
|
||||||
"足球": [
|
|
||||||
"这是一种球类用品",
|
|
||||||
"圆形的,有特定的颜色搭配",
|
|
||||||
"需要用脚操作",
|
|
||||||
"在特定的场地上使用",
|
|
||||||
"可以用来进行比赛",
|
|
||||||
"需要充气才能使用",
|
|
||||||
"是世界上很受欢迎的活动",
|
|
||||||
"有不同的规格",
|
|
||||||
"很多人喜欢观看相关比赛",
|
|
||||||
"有专业的赛事"
|
|
||||||
],
|
|
||||||
"牛奶": [
|
|
||||||
"这是一种饮品",
|
|
||||||
"白色的,有营养",
|
|
||||||
"来自动物",
|
|
||||||
"可以直接饮用",
|
|
||||||
"富含蛋白质和钙",
|
|
||||||
"有不同的品牌",
|
|
||||||
"可以作为早餐的一部分",
|
|
||||||
"需要特定条件保存",
|
|
||||||
"有不同的类型",
|
|
||||||
"很多人每天都会喝"
|
|
||||||
],
|
|
||||||
"豆浆": [
|
|
||||||
"这是一种饮品",
|
|
||||||
"乳白色的,有特殊香味",
|
|
||||||
"用植物制作",
|
|
||||||
"可以直接饮用",
|
|
||||||
"富含植物蛋白",
|
|
||||||
"有不同的口味",
|
|
||||||
"可以作为早餐的一部分",
|
|
||||||
"是传统饮品",
|
|
||||||
"适合特定人群",
|
|
||||||
"很多早餐店都有"
|
|
||||||
],
|
|
||||||
"米饭": [
|
|
||||||
"这是一种主食",
|
|
||||||
"白色的,颗粒状",
|
|
||||||
"用特定食材制作",
|
|
||||||
"很多人经常吃",
|
|
||||||
"可以搭配各种食物",
|
|
||||||
"需要加水烹饪",
|
|
||||||
"有不同的品种",
|
|
||||||
"可以有不同的做法",
|
|
||||||
"吃了会有饱腹感",
|
|
||||||
"很多地方的人都吃"
|
|
||||||
],
|
|
||||||
"面条": [
|
|
||||||
"这是一种主食",
|
|
||||||
"长条状的,需要烹饪",
|
|
||||||
"用特定食材制作",
|
|
||||||
"可以有各种口味",
|
|
||||||
"有不同的形状",
|
|
||||||
"需要水煮",
|
|
||||||
"可以有不同的做法",
|
|
||||||
"是传统食物",
|
|
||||||
"烹饪时间不长",
|
|
||||||
"很多人喜欢吃"
|
|
||||||
],
|
|
||||||
"猫": [
|
|
||||||
"这是一种动物",
|
|
||||||
"毛茸茸的,会发出特定的声音",
|
|
||||||
"喜欢抓小东西",
|
|
||||||
"可以作为宠物",
|
|
||||||
"有不同的品种和颜色",
|
|
||||||
"喜欢休息",
|
|
||||||
"比较独立",
|
|
||||||
"会自己清洁",
|
|
||||||
"有爪子和尾巴",
|
|
||||||
"很多人喜欢养"
|
|
||||||
],
|
|
||||||
"狗": [
|
|
||||||
"这是一种动物",
|
|
||||||
"毛茸茸的,会发出特定的声音",
|
|
||||||
"可以作为宠物",
|
|
||||||
"很忠诚",
|
|
||||||
"有不同的品种和大小",
|
|
||||||
"喜欢活动和玩耍",
|
|
||||||
"需要定期外出",
|
|
||||||
"可以训练各种技能",
|
|
||||||
"有爪子和尾巴",
|
|
||||||
"被很多人视为朋友"
|
|
||||||
],
|
|
||||||
"夏天": [
|
|
||||||
"这是一个季节",
|
|
||||||
"天气比较热",
|
|
||||||
"有很多新鲜的东西",
|
|
||||||
"适合在水上进行活动",
|
|
||||||
"白天的时间比较长",
|
|
||||||
"需要穿轻薄的衣服",
|
|
||||||
"可能会有雷雨天气",
|
|
||||||
"学生们都有假期",
|
|
||||||
"适合吃冷的东西",
|
|
||||||
"阳光比较强烈"
|
|
||||||
],
|
|
||||||
"冬天": [
|
|
||||||
"这是一个季节",
|
|
||||||
"天气比较冷",
|
|
||||||
"可能会有白色的东西从天上掉下来",
|
|
||||||
"需要穿厚厚的衣服",
|
|
||||||
"白天的时间比较短",
|
|
||||||
"适合在雪地上活动",
|
|
||||||
"很多节日在这个时候",
|
|
||||||
"需要注意保暖",
|
|
||||||
"水面可能会变硬",
|
|
||||||
"适合喝热的饮料"
|
|
||||||
],
|
|
||||||
"可乐": [
|
|
||||||
"这是一种饮料",
|
|
||||||
"有特定的颜色,有气泡",
|
|
||||||
"味道甜甜的",
|
|
||||||
"含有咖啡因",
|
|
||||||
"可以解渴",
|
|
||||||
"有不同的品牌",
|
|
||||||
"可以加冰饮用",
|
|
||||||
"很多人喜欢喝",
|
|
||||||
"适合搭配食物",
|
|
||||||
"开瓶后会有气体冒出"
|
|
||||||
],
|
|
||||||
"雪碧": [
|
|
||||||
"这是一种饮料",
|
|
||||||
"透明的,有气泡",
|
|
||||||
"味道甜甜的",
|
|
||||||
"有柠檬味",
|
|
||||||
"可以解渴",
|
|
||||||
"有不同的品牌",
|
|
||||||
"可以加冰饮用",
|
|
||||||
"很多人喜欢喝",
|
|
||||||
"适合搭配食物",
|
|
||||||
"开瓶后会有气体冒出"
|
|
||||||
],
|
|
||||||
"手机": [
|
|
||||||
"这是一种便携式电子设备",
|
|
||||||
"可以用来沟通和获取信息",
|
|
||||||
"触摸操作,便于携带",
|
|
||||||
"需要充电才能使用",
|
|
||||||
"可以安装各种应用",
|
|
||||||
"有拍照功能",
|
|
||||||
"现在几乎人人都有",
|
|
||||||
"有不同的品牌和型号",
|
|
||||||
"可以用来娱乐",
|
|
||||||
"需要特定卡片才能通话"
|
|
||||||
],
|
|
||||||
"平板": [
|
|
||||||
"这是一种便携式电子设备",
|
|
||||||
"介于两种电子设备之间",
|
|
||||||
"触摸操作,比手机大",
|
|
||||||
"需要充电才能使用",
|
|
||||||
"可以用来娱乐和工作",
|
|
||||||
"有拍照功能",
|
|
||||||
"可以安装各种应用",
|
|
||||||
"适合观看视频",
|
|
||||||
"比电脑轻便",
|
|
||||||
"有不同的品牌和型号"
|
|
||||||
],
|
|
||||||
"老师": [
|
|
||||||
"这是一种职业",
|
|
||||||
"在特定的场所工作",
|
|
||||||
"教授知识",
|
|
||||||
"需要准备课程",
|
|
||||||
"有不同的专业领域",
|
|
||||||
"需要批改作业",
|
|
||||||
"对他人有指导作用",
|
|
||||||
"需要有耐心",
|
|
||||||
"很多人尊敬",
|
|
||||||
"可以影响他人的成长"
|
|
||||||
],
|
|
||||||
"学生": [
|
|
||||||
"这是一种身份",
|
|
||||||
"在特定的场所学习",
|
|
||||||
"需要上课和完成作业",
|
|
||||||
"有不同的阶段",
|
|
||||||
"可以学到各种知识",
|
|
||||||
"需要参加考试",
|
|
||||||
"有同学和老师",
|
|
||||||
"可以参加各种活动",
|
|
||||||
"是未来的希望",
|
|
||||||
"很多人都很努力"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
# 获取AI发言
|
# 获取AI发言
|
||||||
def get_ai_speech(player_index, round_num, used_speeches):
|
def get_ai_speech(player_index, round_num, used_speeches):
|
||||||
@ -314,23 +119,42 @@ def get_ai_speech(player_index, round_num, used_speeches):
|
|||||||
player_word = st.session_state.player_words[player_index]
|
player_word = st.session_state.player_words[player_index]
|
||||||
num_players = st.session_state.num_players
|
num_players = st.session_state.num_players
|
||||||
|
|
||||||
max_attempts = 100
|
max_attempts = 5
|
||||||
attempt = 0
|
attempt = 0
|
||||||
|
|
||||||
while attempt < max_attempts:
|
while attempt < max_attempts:
|
||||||
# 按轮数递进的描述逻辑
|
# 构建API提示词
|
||||||
# 每轮选择不同深度的描述
|
if round_num == 1:
|
||||||
|
# 第一轮:基础描述,不要太详细
|
||||||
|
prompt = f"你在玩谁是卧底游戏,你拿到的词语是 '{player_word}'。请生成第一轮的发言,只做基础描述,不要直接说出词语,发言要自然简洁。"
|
||||||
|
if is_spy:
|
||||||
|
prompt += " 你是卧底,但不要暴露自己的身份。"
|
||||||
|
elif round_num == 2:
|
||||||
|
# 第二轮:更详细的描述,加一些分析
|
||||||
|
prompt = f"你在玩谁是卧底游戏,你拿到的词语是 '{player_word}'。请生成第二轮的发言,在第一轮的基础上增加一些细节分析,不要直接说出词语,发言要自然。"
|
||||||
|
if is_spy:
|
||||||
|
prompt += " 你是卧底,但不要暴露自己的身份。"
|
||||||
|
else:
|
||||||
|
# 第三轮及以后:详细描述 + 合理怀疑
|
||||||
|
suspect_player = random.randint(1, num_players) if num_players > 1 else 1
|
||||||
|
prompt = f"你在玩谁是卧底游戏,你拿到的词语是 '{player_word}'。请生成第{round_num}轮的发言,包括详细描述和对其他玩家的合理怀疑(比如玩家{suspect_player}),不要直接说出词语,发言要自然。"
|
||||||
|
if is_spy:
|
||||||
|
prompt += " 你是卧底,要隐藏自己的身份,同时可以适当引导怀疑其他玩家。"
|
||||||
|
|
||||||
|
# 调用API生成发言
|
||||||
|
speech = call_deepseek_api(prompt)
|
||||||
|
|
||||||
|
# 如果API调用失败或返回空,使用传统方式生成
|
||||||
|
if not speech:
|
||||||
|
# 备用方案:使用传统方式生成发言
|
||||||
if player_word in word_descriptions:
|
if player_word in word_descriptions:
|
||||||
all_descriptions = word_descriptions[player_word]
|
all_descriptions = word_descriptions[player_word]
|
||||||
# 根据轮数选择描述数量,轮数越多描述越多
|
|
||||||
max_descriptions = min(round_num, len(all_descriptions))
|
max_descriptions = min(round_num, len(all_descriptions))
|
||||||
# 随机选择描述,确保多样性
|
|
||||||
if len(all_descriptions) >= max_descriptions:
|
if len(all_descriptions) >= max_descriptions:
|
||||||
selected_descriptions = random.sample(all_descriptions, max_descriptions)
|
selected_descriptions = random.sample(all_descriptions, max_descriptions)
|
||||||
else:
|
else:
|
||||||
selected_descriptions = all_descriptions[:max_descriptions]
|
selected_descriptions = all_descriptions[:max_descriptions]
|
||||||
else:
|
else:
|
||||||
# 如果词语不在描述库中,使用通用描述
|
|
||||||
base_descriptions = [
|
base_descriptions = [
|
||||||
f"这是一个{len(player_word)}字的词语",
|
f"这是一个{len(player_word)}字的词语",
|
||||||
"这个词很常见",
|
"这个词很常见",
|
||||||
@ -340,15 +164,11 @@ def get_ai_speech(player_index, round_num, used_speeches):
|
|||||||
max_descriptions = min(round_num, len(base_descriptions))
|
max_descriptions = min(round_num, len(base_descriptions))
|
||||||
selected_descriptions = random.sample(base_descriptions, max_descriptions)
|
selected_descriptions = random.sample(base_descriptions, max_descriptions)
|
||||||
|
|
||||||
# 构建发言
|
|
||||||
description_part = " ".join(selected_descriptions)
|
description_part = " ".join(selected_descriptions)
|
||||||
|
|
||||||
# 第一轮:基础描述
|
|
||||||
if round_num == 1:
|
if round_num == 1:
|
||||||
openings = ["我抽到的词", "我的词", "这个词", "我拿到的词", "这个东西"]
|
openings = ["我抽到的词", "我的词", "这个词", "我拿到的词", "这个东西"]
|
||||||
speech = f"{random.choice(openings)},{description_part}"
|
speech = f"{random.choice(openings)},{description_part}"
|
||||||
|
|
||||||
# 第二轮:基础描述 + 简单分析
|
|
||||||
elif round_num == 2:
|
elif round_num == 2:
|
||||||
analysis_phrases = [
|
analysis_phrases = [
|
||||||
"这个东西大家应该都接触过",
|
"这个东西大家应该都接触过",
|
||||||
@ -359,8 +179,6 @@ def get_ai_speech(player_index, round_num, used_speeches):
|
|||||||
"随处可见的一种"
|
"随处可见的一种"
|
||||||
]
|
]
|
||||||
speech = f"{description_part}。{random.choice(analysis_phrases)}"
|
speech = f"{description_part}。{random.choice(analysis_phrases)}"
|
||||||
|
|
||||||
# 第三轮及以后:基础描述 + 更多细节 + 怀疑
|
|
||||||
else:
|
else:
|
||||||
detail_phrases = [
|
detail_phrases = [
|
||||||
"仔细想想,它还有一些特点",
|
"仔细想想,它还有一些特点",
|
||||||
@ -380,6 +198,11 @@ def get_ai_speech(player_index, round_num, used_speeches):
|
|||||||
]
|
]
|
||||||
speech = f"{description_part}。{random.choice(detail_phrases)}。{random.choice(suspicion_phrases)}"
|
speech = f"{description_part}。{random.choice(detail_phrases)}。{random.choice(suspicion_phrases)}"
|
||||||
|
|
||||||
|
# 确保发言不直接包含词语本身
|
||||||
|
if player_word in speech:
|
||||||
|
# 如果直接说出了词语,尝试替换或修改
|
||||||
|
speech = speech.replace(player_word, "这个词")
|
||||||
|
|
||||||
# 检查发言是否唯一
|
# 检查发言是否唯一
|
||||||
if speech not in used_speeches:
|
if speech not in used_speeches:
|
||||||
return speech
|
return speech
|
||||||
@ -463,6 +286,56 @@ elif st.session_state.game_state == "playing":
|
|||||||
for name in tied_player_names:
|
for name in tied_player_names:
|
||||||
st.write(f"- {name}")
|
st.write(f"- {name}")
|
||||||
|
|
||||||
|
# 生成AI玩家第二轮发言
|
||||||
|
current_runoff_speeches = []
|
||||||
|
# 检查是否已经为当前第二轮投票生成了发言
|
||||||
|
runoff_speeches = st.session_state.runoff_speeches
|
||||||
|
|
||||||
|
if not runoff_speeches:
|
||||||
|
# 为当前第二轮投票创建一个空的已使用发言集合
|
||||||
|
used_speeches = set()
|
||||||
|
# 为每个AI玩家生成发言
|
||||||
|
for i in range(st.session_state.num_players):
|
||||||
|
if i != player_index and i not in st.session_state.eliminated_players:
|
||||||
|
# 生成唯一的发言,使用当前轮数+0.5表示第二轮投票
|
||||||
|
speech = get_ai_speech(i, st.session_state.current_round + 0.5, used_speeches)
|
||||||
|
# 将生成的发言添加到已使用集合中
|
||||||
|
used_speeches.add(speech)
|
||||||
|
current_runoff_speeches.append({
|
||||||
|
'player': i + 1,
|
||||||
|
'speech': speech,
|
||||||
|
'type': 'ai'
|
||||||
|
})
|
||||||
|
|
||||||
|
# 保存当前第二轮投票的发言
|
||||||
|
st.session_state.runoff_speeches = current_runoff_speeches
|
||||||
|
else:
|
||||||
|
# 使用已有的发言
|
||||||
|
current_runoff_speeches = runoff_speeches
|
||||||
|
|
||||||
|
# 显示AI玩家第二轮发言
|
||||||
|
st.subheader("第二轮发言")
|
||||||
|
for speech in current_runoff_speeches:
|
||||||
|
st.write(f"**{st.session_state.player_names[speech['player']-1]}**:{speech['speech']}")
|
||||||
|
|
||||||
|
# 用户第二轮发言输入
|
||||||
|
if player_index not in st.session_state.eliminated_players:
|
||||||
|
st.write(f"\n### 你的第二轮发言({st.session_state.player_names[player_index]})")
|
||||||
|
st.session_state.player_runoff_speech = st.text_area(
|
||||||
|
"请输入你的第二轮发言",
|
||||||
|
value=st.session_state.player_runoff_speech,
|
||||||
|
height=100,
|
||||||
|
placeholder="在这里输入你的第二轮发言..."
|
||||||
|
)
|
||||||
|
|
||||||
|
# 保存用户第二轮发言
|
||||||
|
if st.button("确认第二轮发言"):
|
||||||
|
if st.session_state.player_runoff_speech.strip():
|
||||||
|
st.session_state.player_runoff_speech_saved = True
|
||||||
|
st.success("第二轮发言已保存!")
|
||||||
|
else:
|
||||||
|
st.error("请输入第二轮发言内容!")
|
||||||
|
|
||||||
# 投票输入(只能在平票玩家中选择)
|
# 投票输入(只能在平票玩家中选择)
|
||||||
vote_name = st.selectbox(
|
vote_name = st.selectbox(
|
||||||
"选择要投票的玩家",
|
"选择要投票的玩家",
|
||||||
@ -473,6 +346,10 @@ elif st.session_state.game_state == "playing":
|
|||||||
|
|
||||||
# 提交第二轮投票
|
# 提交第二轮投票
|
||||||
if st.button("提交第二轮投票"):
|
if st.button("提交第二轮投票"):
|
||||||
|
# 检查用户是否已完成第二轮发言
|
||||||
|
if player_index not in st.session_state.eliminated_players and not st.session_state.player_runoff_speech_saved:
|
||||||
|
st.error("请先完成第二轮发言!")
|
||||||
|
else:
|
||||||
# 模拟所有玩家的第二轮投票
|
# 模拟所有玩家的第二轮投票
|
||||||
st.session_state.votes = {}
|
st.session_state.votes = {}
|
||||||
st.session_state.votes[vote] = 1
|
st.session_state.votes[vote] = 1
|
||||||
@ -515,6 +392,12 @@ elif st.session_state.game_state == "playing":
|
|||||||
st.session_state.game_result = "卧底胜利!平民全部被淘汰。"
|
st.session_state.game_result = "卧底胜利!平民全部被淘汰。"
|
||||||
st.session_state.game_state = "ended"
|
st.session_state.game_state = "ended"
|
||||||
st.success(st.session_state.game_result)
|
st.success(st.session_state.game_result)
|
||||||
|
else:
|
||||||
|
# 检查是否超过最大轮数
|
||||||
|
if st.session_state.current_round >= st.session_state.max_rounds:
|
||||||
|
st.session_state.game_result = "游戏结束!已达到最大投票次数(4次)。"
|
||||||
|
st.session_state.game_state = "ended"
|
||||||
|
st.success(st.session_state.game_result)
|
||||||
else:
|
else:
|
||||||
# 进入下一轮
|
# 进入下一轮
|
||||||
st.write("\n游戏继续,进入下一轮!")
|
st.write("\n游戏继续,进入下一轮!")
|
||||||
@ -523,9 +406,12 @@ elif st.session_state.game_state == "playing":
|
|||||||
st.session_state.player_speech = ""
|
st.session_state.player_speech = ""
|
||||||
st.session_state.player_speech_saved = False
|
st.session_state.player_speech_saved = False
|
||||||
|
|
||||||
# 重置 runoff 状态
|
# 重置 runoff 状态和第二轮发言相关变量
|
||||||
st.session_state.runoff = False
|
st.session_state.runoff = False
|
||||||
st.session_state.tied_players = []
|
st.session_state.tied_players = []
|
||||||
|
st.session_state.runoff_speeches = []
|
||||||
|
st.session_state.player_runoff_speech = ""
|
||||||
|
st.session_state.player_runoff_speech_saved = False
|
||||||
|
|
||||||
# 等待用户确认后再刷新
|
# 等待用户确认后再刷新
|
||||||
if st.button("进入下一轮"):
|
if st.button("进入下一轮"):
|
||||||
@ -714,6 +600,9 @@ elif st.session_state.game_state == "ended":
|
|||||||
st.session_state.speeches = []
|
st.session_state.speeches = []
|
||||||
st.session_state.player_speech = ""
|
st.session_state.player_speech = ""
|
||||||
st.session_state.player_speech_saved = False
|
st.session_state.player_speech_saved = False
|
||||||
|
st.session_state.runoff_speeches = []
|
||||||
|
st.session_state.player_runoff_speech = ""
|
||||||
|
st.session_state.player_runoff_speech_saved = False
|
||||||
st.rerun()
|
st.rerun()
|
||||||
|
|
||||||
# 游戏规则
|
# 游戏规则
|
||||||
@ -725,3 +614,5 @@ with st.sidebar:
|
|||||||
st.write("4. 每轮结束后进行投票,得票最多的玩家被淘汰")
|
st.write("4. 每轮结束后进行投票,得票最多的玩家被淘汰")
|
||||||
st.write("5. 如果淘汰的是卧底,平民胜利")
|
st.write("5. 如果淘汰的是卧底,平民胜利")
|
||||||
st.write("6. 如果最后只剩下卧底,卧底胜利")
|
st.write("6. 如果最后只剩下卧底,卧底胜利")
|
||||||
|
st.write("7. 游戏最多进行4轮投票,超过次数则游戏结束")
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user