178 lines
4.7 KiB
Python
178 lines
4.7 KiB
Python
import functools
|
|
from fuzzywuzzy import fuzz
|
|
from werewolf_players import No_player
|
|
|
|
|
|
class Role:
|
|
def __init__(self, game, player=No_player()):
|
|
self.game = game
|
|
self.player = player
|
|
self.player.setRole(self)
|
|
self.add_yourself()
|
|
|
|
def add_yourself(self):
|
|
self.game.role[type(self)] = self
|
|
|
|
async def send_role_list(self, cls):
|
|
await self.player.send_info(f"{cls.name()}: {', '.join(r.player.name() for r in self.game.role[cls])}")
|
|
|
|
def is_role(self, cls):
|
|
return isinstance(self, cls)
|
|
|
|
@staticmethod
|
|
def match(message):
|
|
return max(Role.__subclasses__(), key=lambda role_class: fuzz.ratio(message, role_class.name()))
|
|
|
|
@staticmethod
|
|
def no_player(func):
|
|
@functools.wraps(func)
|
|
async def wrapper(self, *args, **kwargs):
|
|
if not isinstance(self.player, No_player):
|
|
return await func(self, *args, **kwargs)
|
|
return wrapper
|
|
|
|
@classmethod
|
|
def name(cls):
|
|
return cls.__name__.casefold()
|
|
|
|
def __str__(self):
|
|
return self.name()
|
|
|
|
|
|
class Doppelganger(Role):
|
|
@Role.no_player
|
|
async def query(self):
|
|
self.choice = await self.player.get_choice("Which player role do you want to copy?", self.player.other())
|
|
|
|
@Role.no_player
|
|
async def send_copy_info(self):
|
|
self.copy_role = type(self.player.other()[self.choice].day_role)
|
|
await self.send_info(f"You copied: {self.copy_role}")
|
|
|
|
@Role.no_player
|
|
async def simulate(self):
|
|
if self.copy_role in [Werewolf, Mason]:
|
|
self.copy_role.add_yourself(self)
|
|
if self.copy_role == Werewolf:
|
|
await self.copy_role.phase(self)
|
|
if self.copy_role in [Mason, Minion]:
|
|
await self.copy_role.send_info(self)
|
|
|
|
if self.copy_role in [Seer, Robber, Troublemaker, Drunk]:
|
|
await self.copy_role.query(self)
|
|
if self.copy_role in [Robber, Troublemaker, Drunk]:
|
|
self.copy_role.simulate(self)
|
|
if self.copy_role in [Seer, Robber]:
|
|
await self.copy_role.send_info(self)
|
|
|
|
@Role.no_player
|
|
async def insomniac(self):
|
|
if self.copy_role == Insomniac:
|
|
self.copy_role.send_info(self)
|
|
|
|
def is_role(self, cls):
|
|
return self.copy_role == cls
|
|
|
|
|
|
class Werewolf(Role):
|
|
def add_yourself(self):
|
|
self.game.role[Werewolf].append(self)
|
|
|
|
@Role.no_player
|
|
async def phase(self):
|
|
if len(self.game.role[Werewolf]) >= 2:
|
|
await self.send_role_list(Werewolf)
|
|
else:
|
|
await self.player.send_info("You are the only werewolf")
|
|
self.choice = await self.player.get_choice("Which card in the middle do you want to look at?", ["left", "middle", "right"]) # 0, 1, 2
|
|
|
|
await self.player.send_info(f"A card in the middle is: {self.game.middle_card[self.choice].name()}")
|
|
|
|
|
|
class Minion(Role):
|
|
@Role.no_player
|
|
async def send_info(self):
|
|
if len(self.game.role[Werewolf]) == 0:
|
|
await self.player.send_info("There were no werewolves, so you need to kill a villager!")
|
|
else:
|
|
await self.send_role_list(Werewolf)
|
|
|
|
|
|
class Mason(Role):
|
|
def add_yourself(self):
|
|
self.game.role[Mason].append(self)
|
|
|
|
@Role.no_player
|
|
async def send_info(self):
|
|
await self.send_role_list(Mason)
|
|
|
|
|
|
class Seer(Role):
|
|
@Role.no_player
|
|
async def query(self):
|
|
self.choice = await self.player.get_choice("Which 1 player card or 2 middle cards do you want to look at?", self.player.other() + ["left & middle", "middle & right", "left & right"])
|
|
|
|
@Role.no_player
|
|
async def send_info(self):
|
|
if self.choice < len(self.player.other()):
|
|
await self.player.send_info(self.player.other()[self.choice].night_role)
|
|
else:
|
|
a, b = [(0, 1), (1, 2), (0, 2)][self.choice - len(self.player.other())]
|
|
await self.player.send_info(f"{self.game.middle_card[a]} {self.game.middle_card[b]}")
|
|
|
|
|
|
class Robber(Role):
|
|
@Role.no_player
|
|
async def query(self):
|
|
self.choice = await self.player.get_choice("Which player do you want to rob?", self.player.other())
|
|
|
|
@Role.no_player
|
|
def simulate(self):
|
|
self.player.swap(self.player.other()[self.choice])
|
|
|
|
@Role.no_player
|
|
async def send_info(self):
|
|
await self.player.send_info(f"You robbed: {self.player.day_role}")
|
|
|
|
|
|
class Troublemaker(Role):
|
|
@Role.no_player
|
|
async def query(self):
|
|
self.A, self.B = await self.player.get_double_choice("Who do you want to exchange? (send two numbers)", self.player.other())
|
|
|
|
@Role.no_player
|
|
def simulate(self):
|
|
self.player.other()[self.A].swap(self.player.other()[self.B])
|
|
|
|
|
|
class Drunk(Role):
|
|
@Role.no_player
|
|
async def query(self):
|
|
self.choice = await self.player.get_choice("Which card from the middle do you want to take?", ["left", "middle", "right"])
|
|
|
|
@Role.no_player
|
|
def simulate(self):
|
|
self.player.day_role, self.game.middle_card[self.choice] = self.game.middle_card[self.choice], self.player.day_role # swap
|
|
|
|
|
|
class Insomniac(Role):
|
|
@Role.no_player
|
|
async def send_info(self):
|
|
await self.player.send_info(f"You are: {self.player.day_role}")
|
|
|
|
|
|
class Villager(Role):
|
|
pass
|
|
|
|
|
|
class Tanner(Role):
|
|
pass
|
|
|
|
|
|
class Hunter(Role):
|
|
pass
|
|
|
|
|
|
class No_role(Role):
|
|
pass
|