From 9b367001b472caf3549be55fcceaed752cafb19a Mon Sep 17 00:00:00 2001 From: bibin Date: Thu, 2 Apr 2020 20:47:11 +0200 Subject: [PATCH] organize in several files --- src/__pycache__/Role.cpython-37.pyc | Bin 0 -> 7033 bytes src/__pycache__/werewolf_game.cpython-37.pyc | Bin 0 -> 9546 bytes .../werewolf_players.cpython-37.pyc | Bin 0 -> 3113 bytes src/__pycache__/werewolf_roles.cpython-37.pyc | Bin 0 -> 7043 bytes src/werewolf_bot.py | 65 +++ src/werewolf_game.py | 218 ++++++++ src/werewolf_players.py | 56 ++ src/werewolf_roles.py | 156 ++++++ src/werewolve-bot-old.py | 381 -------------- src/werewolve-bot.py | 498 ------------------ 10 files changed, 495 insertions(+), 879 deletions(-) create mode 100644 src/__pycache__/Role.cpython-37.pyc create mode 100644 src/__pycache__/werewolf_game.cpython-37.pyc create mode 100644 src/__pycache__/werewolf_players.cpython-37.pyc create mode 100644 src/__pycache__/werewolf_roles.cpython-37.pyc create mode 100644 src/werewolf_bot.py create mode 100644 src/werewolf_game.py create mode 100644 src/werewolf_players.py create mode 100644 src/werewolf_roles.py delete mode 100644 src/werewolve-bot-old.py delete mode 100644 src/werewolve-bot.py diff --git a/src/__pycache__/Role.cpython-37.pyc b/src/__pycache__/Role.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d429ccc0be579eff70c83a561a2a0a7353c8592d GIT binary patch literal 7033 zcmb_gTW=f372eq!mlP?<@>PkGZXL%Blg9EbX^<(gE!- zZGv`X1$2dJ3$!PzpsP&Vplfml^bFGu=(=oxZZPeFo|SW;=a{a5o|h*;pJ3Vpy&zA5 zKFM?y^eK57^l7GRpwGy&pwBWr1Nxj?1ii>~9rSbZdC<=@-B3cA%2Kv+l&dPrQ&m+{ zGpfE`S4J=^&)+keFLXwFp{s?qj226D%2*N7STUuL=GVrGB`s;=3XMn?S4UQ)hpQ{A zvW9C#&d55ho@~fjTp>%&$@#C1U9ke0@`POA`-VIzPhoymo`(E0sr^~hR~-`q=|@*; zAEL!Dov|Z!jKJ8zKfr46hG;d-)Lw57RBCsk&26G$)nC)}+P@9$;PU;ArHyEymR7r~ z-EisNZ|=N)SGA?mOY7Za>56#+7I{kz4 z^a)J;1TC|yIjpiIdaqm%xejzsfSZJxDiuD{OfK#vu+2I;~zb~jK*QH2+j!1CJkEM3y`n7@R^M)8CudTId{2Iv>Rf^KpF-xzDi5y+e# zvIA$#73UkEd&R}V+|;|DMclQ0LeAI&h#;2K;up~+#x9_=Bld)VwR>jIdTeLZ2=h+r z#9NzKKbwXaq>VhBuLb>XoTP3WItb-t%moIkLBOT~Dhm@34|2Rb(AULqVYJZ8<*}FE z{f^%FC%S~zD0=3ukm7-(uYkgOrI|RR@w3LBxC4K^ji4Q_=JQrDmXFv6MqEm;va&vY z5~;6}KkG4X>MM)JkTfVs<7Q}PraBgf(PJ!2&l>^S8U!cV>l*qx;Mvjt>>i0)TA(JD{yhKm3;}TGt zXdEa#VViJO8tb5qe}v3sw3vKu(o?eflDq_-;iT>-s5hc;pIl%n@{N)95oV^4X6lPM z7R&-S;fwj0RgOMJhTYl+Gh_Jb=Ns@x27n(%BOm}Lew-P6Rdo=F0TVTiqNb~V1_lQV zsVN$0Qb~C{W(&QC=`6LtLZ{4OBis1p%rdQ}Q)(IxyX>$<$40mecE2Q+ltIY|nntEf zKq{r*af6lfNjru`i1AZJD(!>AM4YM(h%W~zeF0O`5h?>1?~*r2puCM%#HKl3*OLMh zaRw9+Mx{tlM)a(ny(@kYB+S;(Wqv+1Psz0~VrJdz7(2q8cWG$^as#O~TiB2DG5tE; zDYDO$XI;hAuh1qvi^itRNsFygL}Z(N%4rSX&En@(Kdbh$C>Uw~nxBVJieT|!!F1T5VCrAW zA0E!;FJ1Dpuv*WjnVK@zt5`YGIRd)Yui^d>b5Z?r4=qR1f*8(_N;1#8I#vp~%UCJ@ z0YRHjaQ5nP5xOfL82U}7?9muKv1s(1LT%x22U&mmy|-|jqw`x2XKa+RtJ3_v`IY#} z4A1kJg|Uay&c{6IWOppXPF!3oJ#R-W;uI;}v&MMDq>;iPA}fn4Els%qzC{;(e$-)r z?QBX^3A*Hr}>ShjbnQu_d(6solm5O#MRtr35DT2b* zeYAK1ogq$%3+6dd%l@WkP8#4^3qh4iz@kLUvQklY7NM^Q4>$0}r)XnW@oY_FPvt7^ zXVK~^oP}U8#s!s;6bso|NU3BsiY|rKd1UM?qw%qeAlCSqi{uV+psdi*>dhYjTeA_K z0P8N6Q@|RhbXxvFVABRjalCSpJ6)H9FTn^`a&FTMz?sVCdpjHE;Sl**R@TE3y@__IT?q3cHigaf3I41W&dREzx(}7~ z^)Dc#>FIZI(Ntkgpzi}BKctQ#*-_;gooKhwa^PJw%XWF=Nci!gxGYXBgYOr_dkjBE z)7VqN&$*?y!Uy|g&neuEz5J*!HOl1^Vagh1@}-HB(3*}0N1TNcK>wz`h$ZNksk?*@ zhwTFxdqVvBGhQm zuF{m*vTVp3xk==c;6vX+{(_coXC#>D zV+pRbBCZ0u|Fe!Kxdlo8nvhI1eaIy9@~1lf3c=@KO{XTV2RYYs#AWx<1P->6CXH!Y ty(UI_j=B;Pr`|i+7t;4gPE1Ag?921k{K9-~erEm*T4TOG?_z}i{|Bl`>D2%L literal 0 HcmV?d00001 diff --git a/src/__pycache__/werewolf_game.cpython-37.pyc b/src/__pycache__/werewolf_game.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e8e5524dbb113048256b87b0c2f373a9358df880 GIT binary patch literal 9546 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 XFuiJAN_l*ljD);`*05Wz!?ye$t$LR@ literal 0 HcmV?d00001 diff --git a/src/__pycache__/werewolf_players.cpython-37.pyc b/src/__pycache__/werewolf_players.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bdcf3dfe787a37a9cda7d9bb1debebb8029c6663 GIT binary patch literal 3113 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 literal 0 HcmV?d00001 diff --git a/src/werewolf_bot.py b/src/werewolf_bot.py new file mode 100644 index 0000000..c52ab07 --- /dev/null +++ b/src/werewolf_bot.py @@ -0,0 +1,65 @@ +import os +import discord +import asyncio +from dotenv import load_dotenv + +from werewolf_game import Game as Werewolf_Game + + +load_dotenv() +TOKEN = os.getenv('DISCORD_TOKEN') +if TOKEN is None: + print("Missing discord token!") + exit(1) + +bot = discord.Client() + +@bot.event +async def on_ready(): + print('We have logged in as {0.user}'.format(bot)) + + + +async def hello(message): + print("Hello") + await message.channel.send('Hello!:regional_indicator_a:') + + print(message.mentions) + +@bot.event +async def on_message(message): + + global running + + if message.author == bot.user: + return + + + if message.content.startswith('$hello'): + await hello(message) + return + + + if message.content.startswith('$logout'): + await bot.logout() + return + + + if message.content.startswith('$werewolf'): + + # start (only one instance running) + + if werewolf_game.running: + await message.channel.send("Sorry! A game is already running") + return + + werewolf_game.running = True + werewolf_game.set_channel(message.channel) + + + await werewolf_game.game() + + return + +werewolf_game = Werewolf_Game(bot) +bot.run(TOKEN) diff --git a/src/werewolf_game.py b/src/werewolf_game.py new file mode 100644 index 0000000..b01a931 --- /dev/null +++ b/src/werewolf_game.py @@ -0,0 +1,218 @@ +from random import shuffle +import asyncio +from werewolf_roles import Role, Doppelganger, Werewolf, Minion, Mason, Seer, Robber, Troublemaker, Drunk, Insomniac, Villiager, Tanner, Hunter, No_role +from werewolf_players import Player, No_player + +class Game: + + def __init__(self, bot): + self.running = False + self.bot = bot + self.player_list = [] + self.role_list = Role.role_set + + + def set_channel(self, channel): + self.channel = channel + + + async def send(self, message): + await self.channel.send(message) + + + async def receive(self, command): + def check(msg): + return msg.channel == self.channel and msg.content.startswith(command) + + return await self.bot.wait_for('message', check = check) + + def setup(self): + self.werewolf_list = [] + self.mason_list = [] + + + async def set_players(self): + + await self.send("Who is playing?") + msg = await self.receive('$players') + + # use info from last round otherwise + if not msg.content.startswith('$players last'): + self.player_list = [await Player.make(mem, self) for mem in msg.mentions] + + # check conditions + if not 0 <= len(self.player_list) <= 10: + raise ValueError("Invalid number of players: " + str(len(self.player_list))) + + # send confirmation + await self.send("Players: " + ", ".join(p.name() for p in self.player_list)) + + + async def set_roles(self): + await self.send("With which roles do you want to play?") + msg = await self.receive('$roles') + + # use info from last round otherwise + if not msg.content.startswith('$roles last'): + tmp_role = [Role.match(r, self) for r in msg.content.split()[1:]] + + # invalid input + if None in tmp_role: + raise ValueError("Invalid list of roles: " + str(tmp_role)) + + self.role_list = tmp_role + + # check condition + if not len(self.role_list) == (len(self.player_list) + 3): + raise ValueError("Invalid number of roles: " + str(len(self.role_list)) + " with " + str(len(self.player_list)) + " players") + + # send confirmation + await self.send("Roles: " + ", ".join(r.name() for r in self.role_list)) + + + def distribute_roles(self): + shuffle(self.role_list) + for i in range(len(self.player_list)): + self.player_list[i].setRole(self.role_list[i]) + self.role_list[i].setPlayer(self.player_list[i]) + + self.middle_card = self.role_list[-3:] + self.active_role = sorted(self.role_list[:-3], key = lambda x: x.order) #necessary? + + + async def start_night(self): + await asyncio.gather( *[p.send("The night has begun") for p in self.player_list] ) + + async def send_role(self): + await asyncio.gather( *[p.send("Your role: " + p.night_role.name()) for p in self.player_list] ) + + async def night_phases(self): + await asyncio.gather( *[r.phase1() for r in self.active_role] ) + await asyncio.gather( *[r.phase2() for r in self.active_role] ) + await asyncio.gather( *[r.phase3() for r in self.active_role] ) + await asyncio.gather( *[r.phase4() for r in self.active_role] ) + await asyncio.gather( *[r.phase5() for r in self.active_role] ) + + async def start_day(self): + await self.send("The day has started") + + async def vote(self, options): + + # vote + await self.receive('$vote') + await self.send("Vote in DM") + + await asyncio.gather( *[p.cast_vote(options) for p in self.player_list] ) + + await self.send("Votes\n\n" + '\n'.join(str(p) + " :arrow_right: " + str(p.vote) for p in self.player_list)) + + def tally(self, options): + for o in options: + o.tally = 0 + + for p in self.player_list: + p.vote.tally += 1 + + def who_dead(self, options): + + maxi = max(o.tally for o in options) + dead = [p for p in self.player_list if p.tally >= maxi] + for d in dead: + d.dead = True + if isinstance(d.day_role.copy, Hunter): + dead.append(d.vote) + + return dead + + def who_won(self, dead): + + no_dead = (len(dead) == 0) + tanner_dead = any(isinstance(d.day_role.copy, Tanner) for d in dead) + werewolf_dead = any(isinstance(d.day_role.copy, Werewolf) for d in dead) + werewolf_in_game = any(isinstance(p.day_role.copy, Werewolf) for p in self.player_list) + minion_dead = any(isinstance(d.day_role.copy, Minion) for d in dead) + minion_in_game = any(isinstance(p.day_role.copy, Minion) for p in self.player_list) + + werewolf_won = False + village_won = False + tanner_won = False + + # could make it shorter using boolean algebra + if no_dead: + if werewolf_in_game: + werewolf_won = True + else: + village_won = True + else: + if tanner_dead: + tanner_won = True + + if werewolf_dead: + village_won = True + + else: + if werewolf_dead: + village_won = True + else: + if minion_dead: + if werewolf_in_game: + werewolf_won = True + else: + village_won = True + else: + if minion_in_game: + werewolf_won = True + + return werewolf_won, village_won, tanner_won, dead + + async def result(self, werewolf_won, village_won, tanner_won, dead): + + if werewolf_won: + await self.send("Werewolves won!") + + if village_won: + await self.send("Village won!") + + for d in dead: + if isinstance(d.day_role.copy, Tanner): + await self.send(str(d) + " won a tanner") + + await self.send(":skull: " + ', '.join(str(d) for d in dead)) + await self.send('\n'.join(":ballot_box " + str(p.tally) + " votes for " + str(p) + " who is " + str(p.day_role) + " (was " + str(p.night_role) + ") " for p in self.player_list)) + await self.send("Middle cards: " + ', '.join(str(r) for r in self.middle_card)) + + # debug + await self.send("Success") + + def end(self): + self.running = False + + + async def game(self): + + try: + + self.setup() + await self.set_players() + await self.set_roles() + self.distribute_roles() + await self.start_night() + await self.send_role() + + await self.night_phases() + + await self.start_day() + #discussion timer + + options = self.player_list + [No_player(self)] + await self.vote(options) + self.tally(options) + await self.result(*self.who_won(self.who_dead(options))) + + except ValueError as error: + await self.send(error) + except asyncio.TimeoutError: + await self.send("Error: I got bored waiting for your input") + finally: + self.end() + await self.send("Game ended") diff --git a/src/werewolf_players.py b/src/werewolf_players.py new file mode 100644 index 0000000..9086772 --- /dev/null +++ b/src/werewolf_players.py @@ -0,0 +1,56 @@ +class Player: + + @staticmethod + async def make(member, game): + p = Player() + p.member = member + p.dm = member.dm_channel or await member.create_dm() + p.game = game + return p + + @staticmethod + def swap(player_A, player_B): + player_A.day_role, player_B.day_role = player_B.day_role, player_A.day_role + + def setRole(self, role): + self.night_role = role + self.day_role = role + + def name(self): + return self.member.name + + def __repr__(self): + return self.name() + + def other(self): + return [p for p in self.game.player_list if p != self] + + async def send(self, message): + await self.dm.send(message) + + async def ask_choice(self, options): + await self.send('\n'.join( "(" + str(i) + ") " + str(options[i]) for i in range(len(options)) )) + + async def receive_choice(self, options): + def check(choice): + return choice.channel == self.dm and choice.content.isdigit() and 0 <= int(choice.content) < len(options) + + return int((await self.game.bot.wait_for('message', timeout=30.0, check = check)).content) + + async def get_choice(self, options): + await self.ask_choice(options) + return await self.receive_choice(options) + + async def cast_vote(self, options): + self.vote = options[await self.get_choice(options)] + +class No_player(Player): + + def __init__(self): + self.day_role = No_role() + + def name(self): + return "no one" + + def __str__(self): + return self.name() diff --git a/src/werewolf_roles.py b/src/werewolf_roles.py new file mode 100644 index 0000000..8d108cd --- /dev/null +++ b/src/werewolf_roles.py @@ -0,0 +1,156 @@ +class Role: + + def __init__(self, game): + self.game = game + self.copy = self + + def setPlayer(self, player): + self.player = player + + async def phase1(self): # query stuff + doppelganger simulation + pass + + async def phase2(self): # werewolf stuff + seer info + pass + + async def phase3(self): # robber simulation & info + pass + + async def phase4(self): # troublemaker simulation + pass + + async def phase5(self): # mostly sending info + drunk simulation + pass + + @staticmethod + def match(message, game): + for role_class in Role.role_set: + if message.casefold() == role_class.name(): + return role_class(game) + + @classmethod + def name(cls): + return cls.__name__.casefold() + + def __str__(self): + return self.name() + +class Doppelganger(Role): + order = 1 + +class Werewolf(Role): + order = 2 + + def setPlayer(self, player): + super().setPlayer(player) + self.game.werewolf_list.append(player) + + async def phase2(self): + if len(self.game.werewolf_list) >= 2: + await self.player.send("Werewolves: " + str(self.game.werewolf_list)) + else: + await self.player.send("You are the only werewolf") + await self.player.send("Which card in the middle do you want to look at?") + self.choice = await self.player.get_choice(["left", "middle", "right"]) + + await self.player.send("A card in the middle is: " + self.game.middle_card[self.choice].name()) + + +class Minion(Role): + order = 3 + + async def phase2(self): + if len(self.game.werewolf_list) == 0: + await self.player.send("There were no werewolves so you became one") + else: + await self.player.send("Werewolves: " + str(self.game.werewolf_list)) + + +class Mason(Role): + order = 4 + + def setPlayer(self, player): + super().setPlayer(player) + self.game.mason_list.append(player) + + async def phase2(self): + await self.player.send("Mason " + str(self.game.mason_list)) + + +class Seer(Role): + order = 5 + + async def phase1(self): + await self.player.send("Which 1 player card or 2 middle cards do you want to look at?") + self.choice = await self.player.get_choice(self.player.other() + ["left & middle", "middle & right", "left & right"]) + + async def phase2(self): + if self.choice < len(self.player.other()): + await self.player.send(self.player.other()[self.choice].night_role) + else: + self.choice -= len(self.player.other()) + if self.choice == 0: + a, b = 0, 1 + elif self.choice == 1: + a, b = 1, 2 + else: + a, b = 0, 2 + + await self.player.send(str(self.game.middle_card[a]) + " " + str(self.game.middle_card[b])) + + +class Robber(Role): + order = 6 + + async def phase1(self): + await self.player.send("Which player do you want to rob?") + self.choice = await self.player.get_choice(self.player.other()) + + async def phase3(self): + Player.swap(self.player, self.player.other()[self.choice]) + await self.player.send("You robbed: " + str(self.player.day_role)) + +class Troublemaker(Role): + order = 7 + + async def phase1(self): + await self.player.send("Who do you want to exchange? (send two separate numbers)") + self.A = await self.player.get_choice(self.player.other()) + self.B = await self.player.get_choice(self.player.other()) + + async def phase4(self): + Player.swap(self.player.other()[self.A], self.player.other()[self.B]) + # receive conformation + await self.player.send("Received " + str(self.A) + " " + str(self.B)) + +class Drunk(Role): + order = 8 + + async def phase1(self): + await self.player.send("Which card from the middle do you want to take?") + self.choice = await self.player.get_choice(["left", "middle", "right"]) + + async def phase5(self): + self.player.day_role, self.game.middle_card[self.choice] = self.game.middle_card[self.choice], self.player.day_role + #receive conformation + await self.player.send("Received " + str(self.choice)) + +class Insomniac(Role): + order = 9 + + async def phase5(self): + await self.player.send("You are now: " + str(self.player.day_role)) + +class Villiager(Role): + order = 10 + +class Tanner(Role): + order = 11 + +class Hunter(Role): + order = 12 + +class No_role(Role): + order = 1000 + +Role.role_set = [Doppelganger, Werewolf, Minion, Mason, Seer, Robber, Troublemaker, Drunk, Insomniac, Villiager, Tanner, Hunter] \ No newline at end of file diff --git a/src/werewolve-bot-old.py b/src/werewolve-bot-old.py deleted file mode 100644 index ba07ef9..0000000 --- a/src/werewolve-bot-old.py +++ /dev/null @@ -1,381 +0,0 @@ -import os -import discord -from enum import Enum -from random import shuffle -import asyncio -from dotenv import load_dotenv - -load_dotenv() -TOKEN = os.getenv('DISCORD_TOKEN') - -class Role(Enum): - doppelganger = 1 - werewolve = 2 - minion = 3 - mason = 4 - seer = 5 - robber = 6 - troublemaker = 7 - drunk = 8 - insomniac = 9 - villiager = 10 - tanner = 11 - hunter = 12 - -class Player: - - def __init__(self, member, role): - self.member = member - self.night_role = role - self.day_role = role - self.vote = -1 - self.tally = 0 - - async def create_dm(self): - self.dm = self.member.dm_channel or await self.member.create_dm() - - async def send(self, message): - await self.dm.send(message) - - async def sendRole(self): - await self.send("Your role: " + self.night_role.name) - - async def sendPoll(self): - await self.send(Player.poll_message) - - async def sendMiddle(self): - await self.send(Player.poll_middle) - - async def receiveChoice(self): - - global bot - - def check(vote): - - return vote.channel == self.dm and vote.content.isdigit() and 0 <= int(vote.content) < Player.size - - vote = await bot.wait_for('message', timeout=30.0, check = check) - await self.send("Received: " + vote.content) - - return int(vote.content) - - -bot = discord.Client() - -@bot.event -async def on_ready(): - print('We have logged in as {0.user}'.format(bot)) - - - -running = False - -async def hello(message): - print("Hello") - await message.channel.send('Hello!:regional_indicator_a:') - - def check(vote): - return vote.content in ["a", "b"] and vote.channel == message.channel - - vote = await bot.wait_for('message', timeout=10.0, check = check) - await message.channel.send("Received! " + vote.content) - -@bot.event -async def on_message(message): - - global running - - if message.author == bot.user: - return - - - if message.content.startswith('$hello'): - await hello(message) - return - - - if message.content.startswith('$logout'): - await bot.logout() - return - - if message.content.startswith('$werewolve'): - - # start (only one instance running) - - if running: - await message.channel.send("Sorry! A game is already running") - return - - - - - """ - if len(players) < 4: - await message.channel.send("To few players!") - return - - """ - - running = True - - - # setup - - members = [mem for mem in message.channel.members if not mem.bot] - - Player.size = len(members) - - - role_set = [Role.werewolve, Role.werewolve, Role.drunk, Role.insomniac, Role.seer, Role.robber, Role.hunter] + (Player.size-4)*[Role.villiager] - shuffle(role_set) - - players = [] - - - werewolve = [] - minion = None - mason = [] - seer = None - robber = None - troublemaker = None - drunk = None - insomniac = None - villiager = [] - tanner = None - hunter = None - - for i in range(Player.size): - - players.append(Player(members[i], role_set[i])) - await players[i].create_dm() - - - if role_set[i] == Role.werewolve: - werewolve.append(players[i]) - - elif role_set[i] == Role.mason: - mason.append(players[i]) - - elif role_set[i] == Role.seer: - seer = players[i] - - elif role_set[i] == Role.robber: - robber = players[i] - - elif role_set[i] == Role.troublemaker: - troublemaker = players[i] - - elif role_set[i] == Role.drunk: - drunk = players[i] - - elif role_set[i] == Role.insomniac: - insomniac = players[i] - - elif role_set[i] == Role.villiager: - villiager.append(players[i]) - - elif role_set[i] == Role.tanner: - tanner = players[i] - - elif role_set[i] == Role.hunter: - hunter = players[i] - - middle = role_set[-3:] - - - Player.poll_middle = "(0) left\n(1) middle\n(2) right" - - Player.poll_message = "" - for i in range(Player.size): - Player.poll_message += "(" + str(i) + ") " + players[i].member.name + "\n" - - # doing phase - - - #send role info to all - send_roles = [p.sendRole() for p in players] - await asyncio.gather(*send_roles) - - - - # query stuff - - #doppelganger stuff - - async def query_seer(): - if seer is None: - return - - await seer.send("Who do you want to look at?") - await seer.sendPoll() - - async def query_robber(): - if robber is None: - return - - await robber.send("Who do you want to rob?") - await robber.sendPoll() - - async def query_troublemaker(): - if troublemaker is None: - return - - await troublemaker.send("Who do you want to exchange?") - await troublemaker.sendPoll() - await troublemaker.sendPoll() - - async def query_drunk(): - if drunk is None: - return - - await drunk.send("Which card from the middle do you want to take?") - await drunk.sendMiddle() - - await asyncio.gather(query_seer(), query_robber(), query_troublemaker(), query_drunk()) - - - - #receive and confirm! - async def receive_seer(): - if seer is not None: - return await seer.receiveChoice() - - async def receive_robber(): - if robber is not None: - return await robber.receiveChoice() - - async def receive_troublemaker(): - if troublemaker is not None: - return await troublemaker.receiveChoice() - - async def receive_drunk(): - if drunk is not None: - return await drunk.receiveChoice() - - seerChoice, robberChoice, troublemakerChoice, drunkChoice = await asyncio.gather(receive_seer(), receive_robber(), receive_troublemaker(), receive_drunk()) - - - - # simulate - - #exchange robber - if robber is not None: - robber.day_role, players[robberChoice].day_role = players[robberChoice].day_role, robber.day_role - #exchange troublemaker - if troublemaker is not None: - A = players[troublemakerChoice[0]] - B = players[troublemakerChoice[1]] - A.day_role, B.day_role = B.day_role, A.day_role - #exchange drunk - if drunk is not None: - drunk.day_role, middle[drunkChoice] = middle[drunkChoice], drunk.day_role - - - - #send werewolves identity to werewolves and minion - async def send_werewolves(): - message = "" - for w in werewolve: - message += w.member.name + " " - - message += "were werewolves" - - sender = [bad.send(message) for bad in werewolve] - if minion is not None: - sender.append(minion.send(message)) - - await asyncio.gather(*sender) - - #send mason identity to masons - async def send_masons(): - message = "" - for m in mason: - message += m.member.name + " " - - message += " were masons" - - sender = [m.send(message) for m in mason] - await asyncio.gather(*sender) - - #send info to seer - async def send_seer(): - if seer is not None: - await seer.send(players[seerChoice].member.name + " was a " + players[seerChoice].night_role.name) - - #send info to robber - async def send_robber(): - if robber is not None: - await robber.send("You stole the role: " + players[robberChoice].night_role.name) - - #send insomniac new role to insomniac - async def send_insomniac(): - if insomniac is not None: - await insomniac.send("You are now a " + insomniac.day_role.name) - - await asyncio.gather(send_werewolves(), send_masons(), send_seer(), send_robber(), send_insomniac()) - - - - # discussion - - # vote - - def check_vote(vote): - return vote.content == "$vote" and vote.channel == message.channel - - await bot.wait_for('message', check = check_vote) - - await message.channel.send("Vote in DM") - - - send_votes = [p.sendPoll() for p in players] - await asyncio.gather(*send_votes) - - receive_votes = [p.receiveChoice() for p in players] - tmp = await asyncio.gather(*receive_votes) - for i in range(Player.size): - players[i].vote = tmp[i] - - for p in players: - players[p.vote].tally += 1 - - maxi = max( [p.tally for p in players] ) - - dead = [p for p in players if p.tally >= maxi] - - if hunter in dead: - dead.append(players[hunter.vote]) - - - - # result and end - # show day-role & night role - - msg = "" - for d in dead: - msg += d.member.name + " " - msg += "are dead!" - await message.channel.send(msg) - - if any(d in werewolve for d in dead): - msg = "The village won!" - else: - msg = "The werewolves won!" - - await message.channel.send(msg) - - msg = "" - for p in players: - msg += p.member.name + ": " + p.day_role.name + " (day) " + p.night_role.name + " (night) and voted for " + players[p.vote].member.name + "\n" - - msg += middle - - await message.channel.send(msg) - - - - running = False - - - -bot.run(TOKEN) \ No newline at end of file diff --git a/src/werewolve-bot.py b/src/werewolve-bot.py deleted file mode 100644 index 55bcafd..0000000 --- a/src/werewolve-bot.py +++ /dev/null @@ -1,498 +0,0 @@ -import os -import discord -from random import shuffle -import asyncio -from dotenv import load_dotenv - -load_dotenv() -TOKEN = os.getenv('DISCORD_TOKEN') -if TOKEN is None: - print("Missing discord token!") - exit(1) - - - -class Role: - - def __init__(self, game): - self.game = game - self.copy = self - - def setPlayer(self, player): - self.player = player - - async def phase1(self): # query stuff + doppelganger simulation - pass - - async def phase2(self): # werewolf stuff + seer info - pass - - async def phase3(self): # robber simulation & info - pass - - async def phase4(self): # troublemaker simulation - pass - - async def phase5(self): # mostly sending info + drunk simulation - pass - - @staticmethod - def match(message, game): - for role_class in Role.role_set: - if message.casefold() == role_class.name(): - return role_class(game) - - @classmethod - def name(cls): - return cls.__name__.casefold() - - def __str__(self): - return self.name() - -class Doppelganger(Role): - order = 1 - -class Werewolf(Role): - order = 2 - - def setPlayer(self, player): - super().setPlayer(player) - self.game.werewolf_list.append(player) - - async def phase2(self): - if len(self.game.werewolf_list) >= 2: - await self.player.send("Werewolves: " + str(self.game.werewolf_list)) - else: - await self.player.send("You are the only werewolf") - await self.player.send("Which card in the middle do you want to look at?") - self.choice = await self.player.get_choice(["left", "middle", "right"]) - - await self.player.send("A card in the middle is: " + self.game.middle_card[self.choice].name()) - - -class Minion(Role): - order = 3 - - async def phase2(self): - if len(self.game.werewolf_list) == 0: - await self.player.send("There were no werewolves so you became one") - else: - await self.player.send("Werewolves: " + str(self.game.werewolf_list)) - - -class Mason(Role): - order = 4 - - def setPlayer(self, player): - super().setPlayer(player) - self.game.mason_list.append(player) - - async def phase2(self): - await self.player.send("Mason " + str(self.game.mason_list)) - - -class Seer(Role): - order = 5 - - async def phase1(self): - await self.player.send("Which 1 player card or 2 middle cards do you want to look at?") - self.choice = await self.player.get_choice(self.player.other() + ["left & middle", "middle & right", "left & right"]) - - async def phase2(self): - if self.choice < len(self.player.other()): - await self.player.send(self.player.other()[self.choice].night_role) - else: - self.choice -= len(self.player.other()) - if self.choice == 0: - a, b = 0, 1 - elif self.choice == 1: - a, b = 1, 2 - else: - a, b = 0, 2 - - await self.player.send(str(self.game.middle_card[a]) + " " + str(self.game.middle_card[b])) - - -class Robber(Role): - order = 6 - - async def phase1(self): - await self.player.send("Which player do you want to rob?") - self.choice = await self.player.get_choice(self.player.other()) - - async def phase3(self): - Player.swap(self.player, self.player.other()[self.choice]) - await self.player.send("You robbed: " + str(self.player.day_role)) - -class Troublemaker(Role): - order = 7 - - async def phase1(self): - await self.player.send("Who do you want to exchange? (send two separate numbers)") - self.A = await self.player.get_choice(self.player.other()) - self.B = await self.player.get_choice(self.player.other()) - - async def phase4(self): - Player.swap(self.player.other()[self.A], self.player.other()[self.B]) - # receive conformation - await self.player.send("Received " + str(self.A) + " " + str(self.B)) - -class Drunk(Role): - order = 8 - - async def phase1(self): - await self.player.send("Which card from the middle do you want to take?") - self.choice = await self.player.get_choice(["left", "middle", "right"]) - - async def phase5(self): - self.player.day_role, self.game.middle_card[self.choice] = self.game.middle_card[self.choice], self.player.day_role - #receive conformation - await self.player.send("Received " + str(self.choice)) - -class Insomniac(Role): - order = 9 - - async def phase5(self): - await self.player.send("You are now: " + str(self.player.day_role)) - -class Villiager(Role): - order = 10 - -class Tanner(Role): - order = 11 - -class Hunter(Role): - order = 12 - -class No_role(Role): - order = 1000 - - -Role.role_set = [Doppelganger, Werewolf, Minion, Mason, Seer, Robber, Troublemaker, Drunk, Insomniac, Villiager, Tanner, Hunter] - - -class Player: - - @staticmethod - async def make(member, game): - p = Player() - p.member = member - p.dm = member.dm_channel or await member.create_dm() - p.game = game - return p - - @staticmethod - def swap(player_A, player_B): - player_A.day_role, player_B.day_role = player_B.day_role, player_A.day_role - - def setRole(self, role): - self.night_role = role - self.day_role = role - - def name(self): - return self.member.name - - def __repr__(self): - return self.name() - - def other(self): - return [p for p in self.game.player_list if p != self] - - async def send(self, message): - await self.dm.send(message) - - async def ask_choice(self, options): - await self.send('\n'.join( "(" + str(i) + ") " + str(options[i]) for i in range(len(options)) )) - - async def receive_choice(self, options): - def check(choice): - return choice.channel == self.dm and choice.content.isdigit() and 0 <= int(choice.content) < len(options) - - return int((await self.game.bot.wait_for('message', timeout=30.0, check = check)).content) - - async def get_choice(self, options): - await self.ask_choice(options) - return await self.receive_choice(options) - - async def cast_vote(self, options): - self.vote = options[await self.get_choice(options)] - -class No_player(Player): - - def __init__(self): - self.day_role = No_role() - - def name(self): - return "no one" - - def __str__(self): - return self.name() - - -class one_night: - - def __init__(self, bot): - self.running = False - self.bot = bot - self.player_list = [] - self.role_list = Role.role_set - - - def set_channel(self, channel): - self.channel = channel - - - async def send(self, message): - await self.channel.send(message) - - - async def receive(self, command): - def check(msg): - return msg.channel == self.channel and msg.content.startswith(command) - - return await bot.wait_for('message', check = check) - - def setup(self): - self.werewolf_list = [] - self.mason_list = [] - - - async def set_players(self): - - await self.send("Who is playing?") - msg = await self.receive('$players') - - # use info from last round otherwise - if not msg.content.startswith('$players last'): - self.player_list = [await Player.make(mem, self) for mem in msg.mentions] - - # check conditions - if not 0 <= len(self.player_list) <= 10: - raise ValueError("Invalid number of players: " + str(len(self.player_list))) - - # send confirmation - await self.send("Players: " + ", ".join(p.name() for p in self.player_list)) - - - async def set_roles(self): - await self.send("With which roles do you want to play?") - msg = await self.receive('$roles') - - # use info from last round otherwise - if not msg.content.startswith('$roles last'): - tmp_role = [Role.match(r, self) for r in msg.content.split()[1:]] - - # invalid input - if None in tmp_role: - raise ValueError("Invalid list of roles: " + str(tmp_role)) - - self.role_list = tmp_role - - # check condition - if not len(self.role_list) == (len(self.player_list) + 3): - raise ValueError("Invalid number of roles: " + str(len(self.role_list)) + " with " + str(len(self.player_list)) + " players") - - # send confirmation - await self.send("Roles: " + ", ".join(r.name() for r in self.role_list)) - - - def distribute_roles(self): - shuffle(self.role_list) - for i in range(len(self.player_list)): - self.player_list[i].setRole(self.role_list[i]) - self.role_list[i].setPlayer(self.player_list[i]) - - self.middle_card = self.role_list[-3:] - self.active_role = sorted(self.role_list[:-3], key = lambda x: x.order) #necessary? - - - async def start_night(self): - await asyncio.gather( *[p.send("The night has begun") for p in self.player_list] ) - - async def send_role(self): - await asyncio.gather( *[p.send("Your role: " + p.night_role.name()) for p in self.player_list] ) - - async def night_phases(self): - await asyncio.gather( *[r.phase1() for r in self.active_role] ) - await asyncio.gather( *[r.phase2() for r in self.active_role] ) - await asyncio.gather( *[r.phase3() for r in self.active_role] ) - await asyncio.gather( *[r.phase4() for r in self.active_role] ) - await asyncio.gather( *[r.phase5() for r in self.active_role] ) - - async def start_day(self): - await self.send("The day has started") - - async def vote(self, options): - - # vote - await self.receive('$vote') - await self.send("Vote in DM") - - await asyncio.gather( *[p.cast_vote(options) for p in self.player_list] ) - - await self.send("Votes\n\n" + '\n'.join(str(p) + " :arrow_right: " + str(p.vote) for p in self.player_list)) - - def tally(self, options): - for o in options: - o.tally = 0 - - for p in self.player_list: - p.vote.tally += 1 - - def who_dead(self, options): - - maxi = max(o.tally for o in options) - dead = [p for p in self.player_list if p.tally >= maxi] - for d in dead: - d.dead = True - if isinstance(d.day_role.copy, Hunter): - dead.append(d.vote) - - return dead - - def who_won(self, dead): - - no_dead = (len(dead) == 0) - tanner_dead = any(isinstance(d.day_role.copy, Tanner) for d in dead) - werewolf_dead = any(isinstance(d.day_role.copy, Werewolf) for d in dead) - werewolf_in_game = any(isinstance(p.day_role.copy, Werewolf) for p in self.player_list) - minion_dead = any(isinstance(d.day_role.copy, Minion) for d in dead) - minion_in_game = any(isinstance(p.day_role.copy, Minion) for p in self.player_list) - - werewolf_won = False - village_won = False - tanner_won = False - - # could make it shorter using boolean algebra - if no_dead: - if werewolf_in_game: - werewolf_won = True - else: - village_won = True - else: - if tanner_dead: - tanner_won = True - - if werewolf_dead: - village_won = True - - else: - if werewolf_dead: - village_won = True - else: - if minion_dead: - if werewolf_in_game: - werewolf_won = True - else: - village_won = True - else: - if minion_in_game: - werewolf_won = True - - return werewolf_won, village_won, tanner_won, dead - - async def result(self, werewolf_won, village_won, tanner_won, dead): - - if werewolf_won: - await self.send("Werewolves won!") - - if village_won: - await self.send("Village won!") - - for d in dead: - if isinstance(d.day_role.copy, Tanner): - await self.send(str(d) + " won a tanner") - - await self.send(":skull: " + ', '.join(str(d) for d in dead)) - await self.send('\n'.join(":ballot_box " + str(p.tally) + " votes for " + str(p) + " who is " + str(p.day_role) + " (was " + str(p.night_role) + ") " for p in self.player_list)) - await self.send("Middle cards: " + ', '.join(str(r) for r in self.middle_card)) - - # debug - await self.send("Success") - - def end(self): - self.running = False - - - async def game(self): - - try: - - self.setup() - await self.set_players() - await self.set_roles() - self.distribute_roles() - await self.start_night() - await self.send_role() - - await self.night_phases() - - await self.start_day() - #discussion timer - - options = self.player_list + [No_role(self)] - await self.vote(options) - self.tally(options) - await self.result(*self.who_won(self.who_dead(options))) - - except ValueError as error: - await self.send(error) - except asyncio.TimeoutError: - await self.send("Error: I got bored waiting for your input") - finally: - self.end() - await self.send("Game ended") - - - -bot = discord.Client() - -@bot.event -async def on_ready(): - print('We have logged in as {0.user}'.format(bot)) - - - -async def hello(message): - print("Hello") - await message.channel.send('Hello!:regional_indicator_a:') - - print(message.mentions) - -@bot.event -async def on_message(message): - - global running - - if message.author == bot.user: - return - - - if message.content.startswith('$hello'): - await hello(message) - return - - - if message.content.startswith('$logout'): - await bot.logout() - return - - - if message.content.startswith('$werewolf'): - - # start (only one instance running) - - if werewolf_game.running: - await message.channel.send("Sorry! A game is already running") - return - - werewolf_game.running = True - werewolf_game.set_channel(message.channel) - - - await werewolf_game.game() - - return - -werewolf_game = one_night(bot) -bot.run(TOKEN)