From 5fb7438e9bc3547d074b3c8b0608881369aaff50 Mon Sep 17 00:00:00 2001 From: bibin Date: Mon, 23 Mar 2020 18:58:13 +0100 Subject: [PATCH] werewolve bot --- werewolve-bot.py | 371 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 371 insertions(+) create mode 100644 werewolve-bot.py diff --git a/werewolve-bot.py b/werewolve-bot.py new file mode 100644 index 0000000..0e088a1 --- /dev/null +++ b/werewolve-bot.py @@ -0,0 +1,371 @@ +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 = 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=10.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 + +@bot.event +async def on_message(message): + + global running + + if message.author == bot.user: + return + + + if message.content.startswith('$hello'): + 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) + + + 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.mason, Role.mason, Role.seer, Role.robber, Role.troublemaker] + (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_cards = 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" + + await message.channel.send(msg) + + + + running = False + + + +bot.run(TOKEN) \ No newline at end of file