update win mechanism

This commit is contained in:
yzlin 2023-10-09 14:36:55 +08:00
parent 4ffbee525c
commit 0c238d2b0d
2 changed files with 28 additions and 15 deletions

View file

@ -65,13 +65,13 @@ STEP_INSTRUCTIONS = {
15: {"content": "{player_current_dead} was killed last night!",
"send_to": "Moderator",
"restricted_to": ""},
16: {"content": """Now freely talk about roles of other players with each other based on your observation and
reflection with few sentences. Decide whether to reveal your identity based on your reflection.""",
16: {"content": """Living players: {living_players}, now freely talk about the current situation based on your observation and
reflection with a few sentences. Decide whether to reveal your identity based on your reflection.""",
"send_to": "", # send to all to speak in daytime
"restricted_to": ""},
17: {"content": """Now vote and tell me who you think is the werewolf. Dont mention your role.
You only choose one from the following living options please:
{living_players}. Or you can pass. For example: I vote to kill ...""",
{living_players}. Say ONLY: I vote to eliminate ...""",
"send_to": "",
"restricted_to": ""},
18: {"content": """{player_current_dead} was eliminated.""",
@ -91,12 +91,12 @@ class InstructSpeak(Action):
})
content = instruction_info["content"]
if "{living_players}" in content and "{werewolf_players}" in content:
content = content.format(living_players=",".join(living_players),
werewolf_players=",".join(werewolf_players))
content = content.format(living_players=living_players,
werewolf_players=werewolf_players)
if "{living_players}" in content:
content = content.format(living_players=",".join(living_players))
content = content.format(living_players=living_players)
if "{werewolf_players}" in content:
content = content.format(werewolf_players=",".join(werewolf_players))
content = content.format(werewolf_players=werewolf_players)
if "{player_hunted}" in content:
content = content.format(player_hunted=player_hunted)
if "{player_current_dead}" in content:
@ -140,8 +140,8 @@ class SummarizeDay(Action):
class AnnounceGameResult(Action):
async def run(self, winner: str):
return f"Game over! The winner is the {winner}"
async def run(self, winner: str, win_reason: str):
return f"Game over! {win_reason}. The winner is the {winner}"
async def main():
rst1 = await SummarizeDay().run({"Player1": 0, "Player2": 0, "Player3": 0, "Player4": 0})

View file

@ -24,12 +24,15 @@ class Moderator(Role):
self._watch([UserRequirement, InstructSpeak, ParseSpeak])
self._init_actions([InstructSpeak, ParseSpeak, AnnounceGameResult])
self.step_idx = 0
self.eval_step_idx = []
# game states
self.living_players = []
self.werewolf_players = []
self.good_guys = []
self.villager_players = []
self.special_role_players = []
self.winner = None
self.win_reason = None
self.witch_poison_left = 1
self.witch_antidote_left = 1
@ -44,7 +47,10 @@ class Moderator(Role):
self.living_players = re.findall(r"Player[0-9]+", game_setup)
self.werewolf_players = re.findall(r"Player[0-9]+: Werewolf", game_setup)
self.werewolf_players = [p.replace(": Werewolf", "") for p in self.werewolf_players]
self.good_guys = [p for p in self.living_players if p not in self.werewolf_players]
self.villager_players = re.findall(r"Player[0-9]+: Villager", game_setup)
self.villager_players = [p.replace(": Villager", "") for p in self.villager_players]
self.special_role_players = [p for p in self.living_players \
if p not in self.werewolf_players + self.villager_players]
def update_player_status(self, player_names: list[str]):
if not player_names:
@ -114,8 +120,10 @@ class Moderator(Role):
def _update_game_states(self, memories):
step_idx = self.step_idx % len(STEP_INSTRUCTIONS)
if step_idx not in [15, 18]: # FIXME: hard code
if step_idx not in [15, 18] or self.step_idx in self.eval_step_idx: # FIXME: hard code
return
else:
self.eval_step_idx.append(self.step_idx) # record evaluation, avoid repetitive evaluation at the same step
if step_idx == 15: # FIXME: hard code
# night ends: after all special roles acted, process the whole night
@ -135,6 +143,7 @@ class Moderator(Role):
self.player_poisoned = None
elif step_idx == 18: # FIXME: hard code
print("*" * 10, step_idx)
# day ends: after all roles voted, process all votings
voting_msgs = memories[-len(self.living_players):]
voted_all = []
@ -144,16 +153,20 @@ class Moderator(Role):
continue
voted_all.append(voted.group(0))
self.player_current_dead = [Counter(voted_all).most_common()[0][0]] # 平票时,杀序号小的
# print("*" * 10, "dead", self.player_current_dead)
self.living_players = [p for p in self.living_players if p not in self.player_current_dead]
self.update_player_status(self.player_current_dead)
# game's termination condition
living_werewolf = [p for p in self.werewolf_players if p in self.living_players]
living_good_guys = [p for p in self.good_guys if p in self.living_players]
living_villagers = [p for p in self.villager_players if p in self.living_players]
living_special_roles = [p for p in self.special_role_players if p in self.living_players]
if not living_werewolf:
self.winner = "good guys"
elif not living_good_guys:
self.win_reason = "werewolves all dead"
elif not living_villagers or not living_special_roles:
self.winner = "werewolf"
self.win_reason = "villagers all dead" if not living_villagers else "special roles all dead"
def _record_game_history(self):
if self.step_idx % len(STEP_INSTRUCTIONS) == 0 or self.winner is not None:
@ -210,7 +223,7 @@ class Moderator(Role):
cause_by=ParseSpeak, send_to="", restricted_to=msg_restriced_to)
elif isinstance(todo, AnnounceGameResult):
msg_content = await AnnounceGameResult().run(winner=self.winner)
msg_content = await AnnounceGameResult().run(winner=self.winner, win_reason=self.win_reason)
msg = Message(content=msg_content, role=self.profile, sent_from=self.name, cause_by=AnnounceGameResult)
logger.info(f"{self._setting}: {msg_content}")