Compare commits
No commits in common. "534013a7dcb00010d2e5d831bc5e564a9251a541" and "60a3e55686eb2420e858af5d7ed310e13038aec2" have entirely different histories.
534013a7dc
...
60a3e55686
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,65 +0,0 @@
|
||||||
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)
|
|
|
@ -1,218 +0,0 @@
|
||||||
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")
|
|
|
@ -1,56 +0,0 @@
|
||||||
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()
|
|
|
@ -1,156 +0,0 @@
|
||||||
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]
|
|
|
@ -0,0 +1,381 @@
|
||||||
|
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)
|
|
@ -0,0 +1,499 @@
|
||||||
|
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')
|
||||||
|
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(p) + " 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)
|
Loading…
Reference in New Issue