beautified output
This commit is contained in:
parent
7495336269
commit
42275c7ab5
|
@ -13,8 +13,10 @@ if TOKEN is None:
|
||||||
print("Missing discord token!")
|
print("Missing discord token!")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
|
|
||||||
PREFIX = '$w '
|
PREFIX = '$w '
|
||||||
bot = commands.Bot(command_prefix=commands.when_mentioned_or(PREFIX))
|
bot = commands.Bot(command_prefix=commands.when_mentioned_or(PREFIX))
|
||||||
|
bot.remove_command('help')
|
||||||
|
|
||||||
|
|
||||||
@bot.event
|
@bot.event
|
||||||
|
@ -23,76 +25,114 @@ async def on_ready():
|
||||||
print('We have logged in as {0.user}'.format(bot))
|
print('We have logged in as {0.user}'.format(bot))
|
||||||
|
|
||||||
|
|
||||||
|
@bot.command()
|
||||||
|
async def help(ctx):
|
||||||
|
embed = discord.Embed(title="How to play?", description="You will need to set up the game and its information in a channel and start the game there. Afterwards the player mainly interact with the bot in DM.", color=0x00ffff)
|
||||||
|
embed.set_author(name="With this bot you can play One Night Ultimate Werewolf")
|
||||||
|
# embed.set_thumbnail(url="https://images-na.ssl-images-amazon.com/images/I/717GrDtFKCL._AC_SL1000_.jpg")
|
||||||
|
embed.add_field(name="$w game setup", value="Make this channel playable.", inline=False)
|
||||||
|
embed.add_field(name="$w game players", value="Set mentioned users as players", inline=False)
|
||||||
|
embed.add_field(name="$w game roles", value="Set the roles to play with", inline=False)
|
||||||
|
embed.add_field(name="$w game start", value="Play one round", inline=False)
|
||||||
|
embed.set_footer(text="Have fun!")
|
||||||
|
await ctx.send(embed=embed)
|
||||||
|
|
||||||
|
|
||||||
|
async def send_embed(ctx, desc, color):
|
||||||
|
await ctx.send(embed=discord.Embed(description=desc, color=color))
|
||||||
|
|
||||||
|
|
||||||
|
async def send_friendly(ctx, desc):
|
||||||
|
await send_embed(ctx, desc, 0x00ff00)
|
||||||
|
|
||||||
|
|
||||||
|
async def send_wrong(ctx, desc):
|
||||||
|
await send_embed(ctx, desc, 0xff8000)
|
||||||
|
|
||||||
|
|
||||||
# game commands
|
# game commands
|
||||||
|
|
||||||
game_instances = {}
|
game_instances = {}
|
||||||
|
|
||||||
|
|
||||||
@bot.group(help="werewolf game", description="Prefix for the One Night Ultimate Werewolf commands.")
|
@bot.group()
|
||||||
async def game(ctx):
|
async def game(ctx):
|
||||||
if ctx.invoked_subcommand is None:
|
if ctx.invoked_subcommand is None:
|
||||||
await ctx.send('Invalid sub command passed...')
|
await send_wrong(ctx, 'Invalid sub command passed...')
|
||||||
|
|
||||||
|
|
||||||
@game.command(help="start werewolf game", description="Start One Night Ultimate Werewolf game.")
|
@game.command()
|
||||||
async def setup(ctx):
|
async def setup(ctx):
|
||||||
if ctx.channel in game_instances:
|
if ctx.channel in game_instances:
|
||||||
await ctx.send("Game already setup in this channel")
|
await send_wrong(ctx, "Game already setup in this channel")
|
||||||
else:
|
else:
|
||||||
game_instances[ctx.channel] = Werewolf_Game(bot, ctx.channel)
|
game_instances[ctx.channel] = Werewolf_Game(bot, ctx.channel)
|
||||||
|
await send_friendly(ctx, "This channel can now play Werewolf")
|
||||||
|
|
||||||
|
|
||||||
def game_running(command):
|
def game_running(command):
|
||||||
@functools.wraps(command)
|
@functools.wraps(command)
|
||||||
async def wrapper(ctx):
|
async def wrapper(ctx):
|
||||||
if ctx.channel not in game_instances:
|
if ctx.channel not in game_instances:
|
||||||
await ctx.send(f"No game setup yet. Use {PREFIX}game setup")
|
await send_wrong(ctx, f"No game setup yet. Use {PREFIX}game setup")
|
||||||
elif game_instances[ctx.channel].running:
|
elif game_instances[ctx.channel].running:
|
||||||
await ctx.send("Sorry! A game is already running")
|
await send_wrong(ctx, "Sorry! A game is already running")
|
||||||
else:
|
else:
|
||||||
await command(ctx)
|
await command(ctx)
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
@game.command(help="start a round", description="Play one round of One Night Ultimate Werewolf")
|
def error_handling(command):
|
||||||
|
@functools.wraps(command)
|
||||||
|
async def wrapper(ctx):
|
||||||
|
try:
|
||||||
|
await command(ctx)
|
||||||
|
except ValueError as error:
|
||||||
|
await send_wrong(ctx, str(error))
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
await send_wrong(ctx, "Error: I got bored waiting for your input")
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
@game.command()
|
||||||
@game_running
|
@game_running
|
||||||
|
@error_handling
|
||||||
async def start(ctx):
|
async def start(ctx):
|
||||||
await game_instances[ctx.channel].game()
|
await game_instances[ctx.channel].game()
|
||||||
|
|
||||||
|
|
||||||
@game.command(help="set players", description="Set the players for the next round.")
|
@game.command()
|
||||||
@game_running
|
@game_running
|
||||||
|
@error_handling
|
||||||
async def players(ctx):
|
async def players(ctx):
|
||||||
await game_instances[ctx.channel].set_players(ctx.message)
|
await game_instances[ctx.channel].set_players(ctx.message)
|
||||||
|
|
||||||
|
|
||||||
@game.command(help="set roles", description="Set the roles for the next round.")
|
@game.command()
|
||||||
@game_running
|
@game_running
|
||||||
|
@error_handling
|
||||||
async def roles(ctx):
|
async def roles(ctx):
|
||||||
try:
|
await game_instances[ctx.channel].set_roles(ctx.message.content.split()[3:]) # exclude commands
|
||||||
await game_instances[ctx.channel].set_roles(ctx.message.content.split()[3:])
|
|
||||||
except ValueError as error:
|
|
||||||
await ctx.send(error)
|
|
||||||
|
|
||||||
# ONLY FOR TESTING
|
# ONLY FOR TESTING
|
||||||
@game.command()
|
@game.command()
|
||||||
@game_running
|
@game_running
|
||||||
|
@error_handling
|
||||||
async def vote(ctx):
|
async def vote(ctx):
|
||||||
await game_instances[ctx.channel].vote()
|
await game_instances[ctx.channel].vote()
|
||||||
|
|
||||||
|
|
||||||
# smaller commands
|
# smaller commands
|
||||||
|
|
||||||
|
@bot.command()
|
||||||
@bot.command(help="greets you", description="This just says hello back to the message author.")
|
|
||||||
async def hello(ctx):
|
async def hello(ctx):
|
||||||
await ctx.send(f"Hello {ctx.message.author.name} :wave:")
|
await send_friendly(ctx, f"Hello {ctx.message.author.name} :wave:")
|
||||||
|
|
||||||
|
|
||||||
@bot.command(help="test bot responsiveness", description="This is a debug function to see if the bot listens to a command.")
|
@bot.command()
|
||||||
async def ping(ctx):
|
async def ping(ctx):
|
||||||
print("pong")
|
print("pong")
|
||||||
await ctx.send("pong")
|
await send_friendly(ctx, "pong")
|
||||||
|
|
||||||
|
|
||||||
# developer commands
|
# developer commands
|
||||||
|
@ -105,17 +145,17 @@ def developer(command):
|
||||||
if ctx.author.id == DEV_ID:
|
if ctx.author.id == DEV_ID:
|
||||||
await command(ctx)
|
await command(ctx)
|
||||||
else:
|
else:
|
||||||
await ctx.send("This command is not for you!")
|
await send_wrong(ctx, "This command is not for you!")
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
@bot.command(help="not for you", description="Shut down the bot.")
|
@bot.command()
|
||||||
@developer
|
@developer
|
||||||
async def logout(ctx):
|
async def logout(ctx):
|
||||||
await bot.logout()
|
await bot.logout()
|
||||||
|
|
||||||
|
|
||||||
@bot.command(help="debug")
|
@bot.command()
|
||||||
@developer
|
@developer
|
||||||
async def debug(ctx):
|
async def debug(ctx):
|
||||||
print("DEBUG")
|
print("DEBUG")
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from random import shuffle
|
from random import shuffle
|
||||||
import asyncio
|
import asyncio
|
||||||
from werewolf_roles import Role, Werewolf, Minion, Tanner, Hunter
|
import discord
|
||||||
|
from werewolf_roles import Role, Werewolf, Mason
|
||||||
from werewolf_players import Player, No_player
|
from werewolf_players import Player, No_player
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,46 +15,47 @@ class Game:
|
||||||
self.role_list = []
|
self.role_list = []
|
||||||
|
|
||||||
async def send(self, message):
|
async def send(self, message):
|
||||||
await self.channel.send(message)
|
await self.channel.send(embed=discord.Embed(description=message, color=0x00ffff))
|
||||||
|
|
||||||
|
async def for_all_player(self, call):
|
||||||
|
await asyncio.gather(*[call(p) for p in self.player_list])
|
||||||
|
|
||||||
async def set_players(self, msg):
|
async def set_players(self, msg):
|
||||||
self.player_list = [await Player.make(mem, self) for mem in msg.mentions]
|
self.player_list = [await Player.make(mem, self) for mem in msg.mentions]
|
||||||
|
await self.send(f"Players: {', '.join(p.name() for p in self.player_list)}") # send confirmation
|
||||||
# send confirmation
|
|
||||||
await self.send("Players: " + ", ".join(p.name() for p in self.player_list))
|
|
||||||
|
|
||||||
async def set_roles(self, suggestions):
|
async def set_roles(self, suggestions):
|
||||||
self.role_list = [Role.match(r, self) for r in suggestions] # raises ValueError
|
self.role_list = [Role.match(r) for r in suggestions] # raises ValueError
|
||||||
|
await self.send(f"Roles: {', '.join(r.name() for r in self.role_list)}") # send confirmation
|
||||||
# send confirmation
|
|
||||||
await self.send("Roles: " + ", ".join(r.name() for r in self.role_list))
|
|
||||||
|
|
||||||
def check(self):
|
def check(self):
|
||||||
if not 0 <= len(self.player_list) <= 10:
|
if not 0 <= len(self.player_list) <= 10:
|
||||||
raise ValueError(f"Invalid number of players: {len(self.player_list)}")
|
raise ValueError(f"Invalid number of players: {len(self.player_list)}")
|
||||||
|
|
||||||
if not len(self.role_list) == (len(self.player_list) + 3):
|
if not len(self.role_list) == (len(self.player_list) + 3):
|
||||||
raise ValueError(f"Invalid number of roles: {len(self.role_list)} with {len(self.player_list)} players")
|
raise ValueError(f"Invalid number of roles: {len(self.role_list)} with {len(self.player_list)} players")
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
self.werewolf_list = []
|
self.role = dict()
|
||||||
self.mason_list = []
|
for r in Role.__subclasses__():
|
||||||
self.running = True
|
if r not in [Werewolf, Mason]:
|
||||||
|
r(self)
|
||||||
|
self.role[Werewolf] = []
|
||||||
|
self.role[Mason] = []
|
||||||
|
self.voting_list = self.player_list + [No_player()]
|
||||||
|
for c in self.voting_list:
|
||||||
|
c.tally = 0
|
||||||
|
|
||||||
def distribute_roles(self):
|
def distribute_roles(self):
|
||||||
shuffle(self.role_list)
|
shuffle(self.role_list)
|
||||||
for i in range(len(self.player_list)):
|
for i in range(len(self.player_list)):
|
||||||
self.player_list[i].setRole(self.role_list[i])
|
self.role_list[i](self, self.player_list[i])
|
||||||
self.role_list[i].setPlayer(self.player_list[i])
|
|
||||||
|
|
||||||
self.middle_card = self.role_list[-3:]
|
self.middle_card = self.role_list[-3:]
|
||||||
self.active_role = sorted(self.role_list[:-3], key=lambda x: x.order)
|
|
||||||
|
|
||||||
async def start_night(self):
|
async def start_night(self):
|
||||||
await asyncio.gather(*[p.send("The night has begun") for p in self.player_list])
|
await self.for_all_player(lambda p: p.send_normal("*The night has begun*"))
|
||||||
|
|
||||||
async def send_role(self):
|
async def send_role(self):
|
||||||
await asyncio.gather(*[p.send("Your role: " + p.night_role.name()) for p in self.player_list])
|
await self.for_all_player(lambda p: p.send_info(f"Your role: **{p.night_role.name()}**"))
|
||||||
|
|
||||||
async def night_phases(self):
|
async def night_phases(self):
|
||||||
await asyncio.gather(*[r.phase1() for r in self.active_role])
|
await asyncio.gather(*[r.phase1() for r in self.active_role])
|
||||||
|
@ -65,42 +67,35 @@ class Game:
|
||||||
async def start_day(self):
|
async def start_day(self):
|
||||||
await self.send("The day has started")
|
await self.send("The day has started")
|
||||||
|
|
||||||
async def vote(self, options):
|
async def vote(self):
|
||||||
|
|
||||||
# vote
|
# vote
|
||||||
# replace with dm: await self.receive('$vote')
|
# replace with dm: await self.receive('$vote')
|
||||||
await self.send("Vote in DM")
|
await self.send("Vote in DM")
|
||||||
|
|
||||||
await asyncio.gather(*[p.cast_vote(options) for p in self.player_list])
|
await self.for_all_player(lambda p: p.cast_vote(self.voting_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
|
|
||||||
|
|
||||||
|
def tally(self):
|
||||||
for p in self.player_list:
|
for p in self.player_list:
|
||||||
p.vote.tally += 1
|
p.vote.tally += 1
|
||||||
|
|
||||||
def who_dead(self, options):
|
def who_dead(self):
|
||||||
|
maxi = max(c.tally for c in self.voting_list)
|
||||||
maxi = max(o.tally for o in options)
|
|
||||||
dead = [p for p in self.player_list if p.tally >= maxi]
|
dead = [p for p in self.player_list if p.tally >= maxi]
|
||||||
for d in dead:
|
for d in dead:
|
||||||
d.dead = True
|
d.dead = True
|
||||||
if isinstance(d.day_role.copy, Hunter):
|
if d.day_role.is_Hunter:
|
||||||
dead.append(d.vote)
|
dead.append(d.vote)
|
||||||
|
|
||||||
return dead
|
return dead
|
||||||
|
|
||||||
def who_won(self, dead):
|
def who_won(self, dead):
|
||||||
|
|
||||||
no_dead = (len(dead) == 0)
|
no_dead = (len(dead) == 0)
|
||||||
tanner_dead = any(isinstance(d.day_role.copy, Tanner) for d in dead)
|
tanner_dead = any(d.day_role.is_Tanner for d in dead)
|
||||||
werewolf_dead = any(isinstance(d.day_role.copy, Werewolf) for d in dead)
|
werewolf_dead = any(d.day_role.is_Werewolf for d in dead)
|
||||||
werewolf_in_game = any(isinstance(p.day_role.copy, Werewolf) for p in self.player_list)
|
werewolf_in_game = any(p.day_role.is_Werewolf for p in self.player_list)
|
||||||
minion_dead = any(isinstance(d.day_role.copy, Minion) for d in dead)
|
minion_dead = any(d.day_role.is_Minion for d in dead)
|
||||||
minion_in_game = any(isinstance(p.day_role.copy, Minion) for p in self.player_list)
|
minion_in_game = any(p.day_role.is_Minion for p in self.player_list)
|
||||||
|
|
||||||
werewolf_won = False
|
werewolf_won = False
|
||||||
village_won = False
|
village_won = False
|
||||||
|
@ -132,35 +127,41 @@ class Game:
|
||||||
if minion_in_game:
|
if minion_in_game:
|
||||||
werewolf_won = True
|
werewolf_won = True
|
||||||
|
|
||||||
|
for p in self.player_list:
|
||||||
|
if p.day_role.is_Werewolf or p.day_role.is_Minion:
|
||||||
|
p.won = werewolf_won
|
||||||
|
elif p.day_role.is_Tanner:
|
||||||
|
p.won = p.dead
|
||||||
|
else:
|
||||||
|
p.won = village_won
|
||||||
|
|
||||||
return werewolf_won, village_won, tanner_won, dead
|
return werewolf_won, village_won, tanner_won, dead
|
||||||
|
|
||||||
async def result(self, werewolf_won, village_won, tanner_won, dead):
|
async def result(self, werewolf_won, village_won, tanner_won, dead):
|
||||||
|
|
||||||
if werewolf_won:
|
if werewolf_won:
|
||||||
await self.send("Werewolves won!")
|
winnning = ["Werewolves won!"]
|
||||||
|
|
||||||
if village_won:
|
if village_won:
|
||||||
await self.send("Village won!")
|
winnning = ["Village won!"]
|
||||||
|
if tanner_won:
|
||||||
|
winnning.append(f"{sum(1 for d in dead if d.day_role.is_Tanner)} tanner won")
|
||||||
|
|
||||||
for d in dead:
|
embed = discord.Embed(title=' and '.join(winnning), color=0x00ffff)
|
||||||
if isinstance(d.day_role.copy, Tanner):
|
for p in self.player_list:
|
||||||
await self.send(str(d) + " won a tanner")
|
won_emoji = ":trophy:" if p.won else "frowning2"
|
||||||
|
dead_emoji = ":skull:" if p.dead else ":no_mouth:"
|
||||||
|
embed.add_field(name="", value=f"{won_emoji} {dead_emoji} {p.tally}:ballot_box: {str(p)} :sunrise_over_mountains:{str(p.day_role)} (:full_moon:{str(p.night_role)}) :point_right:{str(p.vote)}", inline=False)
|
||||||
|
embed.add_field(name="Middle cards", value=', '.join(str(r) for r in self.middle_card))
|
||||||
|
|
||||||
await self.send(":skull: " + ', '.join(str(d) for d in dead))
|
await self.channel.send(embed=embed)
|
||||||
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):
|
def end(self):
|
||||||
self.running = False
|
self.running = False
|
||||||
|
|
||||||
async def game(self):
|
async def game(self):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
self.check()
|
self.check()
|
||||||
|
self.running = True
|
||||||
self.setup()
|
self.setup()
|
||||||
self.distribute_roles()
|
self.distribute_roles()
|
||||||
await self.start_night()
|
await self.start_night()
|
||||||
|
@ -171,15 +172,10 @@ class Game:
|
||||||
await self.start_day()
|
await self.start_day()
|
||||||
# discussion timer
|
# discussion timer
|
||||||
|
|
||||||
options = self.player_list + [No_player(self)]
|
await self.vote()
|
||||||
await self.vote(options)
|
self.tally()
|
||||||
self.tally(options)
|
await self.result(*self.who_won(self.who_dead()))
|
||||||
await self.result(*self.who_won(self.who_dead(options)))
|
|
||||||
|
|
||||||
except ValueError as error:
|
await self.send("Round ended")
|
||||||
await self.send(error)
|
|
||||||
except asyncio.TimeoutError:
|
|
||||||
await self.send("Error: I got bored waiting for your input")
|
|
||||||
finally:
|
finally:
|
||||||
self.end()
|
self.end()
|
||||||
await self.send("Round ended")
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from werewolf_roles import No_role
|
import discord
|
||||||
|
|
||||||
|
|
||||||
class Player:
|
class Player:
|
||||||
|
@ -11,12 +11,8 @@ class Player:
|
||||||
p.game = game
|
p.game = game
|
||||||
return p
|
return p
|
||||||
|
|
||||||
def swap(self, player_B):
|
|
||||||
self.day_role, player_B.day_role = player_B.day_role, self.day_role
|
|
||||||
|
|
||||||
def setRole(self, role):
|
def setRole(self, role):
|
||||||
self.night_role = role
|
self.day_role = self.night_role = role
|
||||||
self.day_role = role
|
|
||||||
|
|
||||||
def name(self):
|
def name(self):
|
||||||
return self.member.name
|
return self.member.name
|
||||||
|
@ -24,33 +20,66 @@ class Player:
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name()
|
return self.name()
|
||||||
|
|
||||||
|
def swap(self, player_B):
|
||||||
|
self.day_role, player_B.day_role = player_B.day_role, self.day_role
|
||||||
|
|
||||||
def other(self):
|
def other(self):
|
||||||
return [p for p in self.game.player_list if p != self]
|
return [p for p in self.game.player_list if p != self]
|
||||||
|
|
||||||
async def send(self, message):
|
async def send_normal(self, message):
|
||||||
await self.dm.send(message)
|
await self.dm.send(message)
|
||||||
|
|
||||||
async def ask_choice(self, options):
|
async def send_embed(self, desc, color):
|
||||||
await self.send('\n'.join("(" + str(i) + ") " + str(options[i]) for i in range(len(options))))
|
await self.dm.send(embed=discord.Embed(description=desc, color=color))
|
||||||
|
|
||||||
async def receive_choice(self, options):
|
async def send_wrong(self, message):
|
||||||
def check(choice):
|
await self.send_embed(message, 0xff8000)
|
||||||
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 send_confirmation(self, message):
|
||||||
|
await self.send_embed(message, 0x00ff00)
|
||||||
|
|
||||||
async def get_choice(self, options):
|
async def send_info(self, message):
|
||||||
await self.ask_choice(options)
|
await self.send_embed(message, 0x00ffff)
|
||||||
return await self.receive_choice(options)
|
|
||||||
|
|
||||||
async def cast_vote(self, options):
|
async def ask_choice(self, question, options):
|
||||||
self.vote = options[await self.get_choice(options)]
|
text = f"{question}\n" + f"{'='*len(question)}\n\n" + '\n'.join(f"[{str(i)}]({str(options[i])})" for i in range(len(options)))
|
||||||
|
await self.dm.send(f"```md\n{text}```")
|
||||||
|
|
||||||
|
async def check_num(self, choice, N):
|
||||||
|
if not choice.isdigit():
|
||||||
|
await self.send_wrong(f"Your choice {choice} is not a number")
|
||||||
|
return False
|
||||||
|
if not 0 <= int(choice) < N:
|
||||||
|
await self.send_wrong(f"Your choice {choice} is not in range 0 - {N-1}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
async def receive_choice(self, options, n_ans=1):
|
||||||
|
while True:
|
||||||
|
def check(choice):
|
||||||
|
return choice.channel == self.dm
|
||||||
|
choice = (await self.game.bot.wait_for('message', timeout=30.0, check=check)).content.split()
|
||||||
|
|
||||||
|
if not len(choice) == n_ans:
|
||||||
|
await self.send_wrong(f"Please give {n_ans} numbers not {len(choice)}")
|
||||||
|
continue
|
||||||
|
if not all(self.check_num(c, len(options)) for c in choice):
|
||||||
|
continue
|
||||||
|
|
||||||
|
await self.send_confirmation(f"Received: {', '.join(choice)}")
|
||||||
|
return [int(c) for c in choice]
|
||||||
|
|
||||||
|
async def get_choice(self, question, options):
|
||||||
|
await self.ask_choice(question, options)
|
||||||
|
return await self.receive_choice(options)[0]
|
||||||
|
|
||||||
|
async def get_double_choice(self, question, options):
|
||||||
|
await self.ask_choice(question, options)
|
||||||
|
return await self.receive_choice(options, 2)
|
||||||
|
|
||||||
|
async def cast_vote(self, question, options):
|
||||||
|
self.vote = options[await self.get_choice(question, options)]
|
||||||
|
|
||||||
|
|
||||||
class No_player(Player):
|
class No_player(Player):
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.day_role = No_role()
|
|
||||||
|
|
||||||
def name(self):
|
def name(self):
|
||||||
return "no one"
|
return "no one"
|
||||||
|
|
|
@ -1,32 +1,25 @@
|
||||||
|
from werewolf_players import No_player
|
||||||
|
|
||||||
|
|
||||||
class Role:
|
class Role:
|
||||||
|
def __init__(self, game, player=No_player()):
|
||||||
def __init__(self, game):
|
|
||||||
self.game = game
|
self.game = game
|
||||||
self.copy = self
|
|
||||||
|
|
||||||
def setPlayer(self, player):
|
|
||||||
self.player = player
|
self.player = player
|
||||||
|
self.player.setRole(self)
|
||||||
|
self.add_yourself()
|
||||||
|
self.is_Hunter = self.is_Tanner = self.is_Werewolf = self.is_Minion = False
|
||||||
|
|
||||||
async def phase1(self): # query stuff + doppelganger simulation
|
def add_yourself(self):
|
||||||
pass
|
self.game.role[type(self)] = self
|
||||||
|
|
||||||
async def phase2(self): # werewolf stuff + seer info
|
async def send_role_list(self, cls):
|
||||||
pass
|
await self.player.send_info(f"{cls}: {', '.join(str(p) for p in self.game.role[cls])}")
|
||||||
|
|
||||||
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
|
@staticmethod
|
||||||
def match(message, game):
|
def match(message):
|
||||||
for role_class in Role.role_set:
|
for role_class in Role.__subclasses__():
|
||||||
if message.casefold() == role_class.name():
|
if message.casefold() == role_class.name():
|
||||||
return role_class(game)
|
return role_class
|
||||||
raise ValueError(f"Invalid role: {message}")
|
raise ValueError(f"Invalid role: {message}")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -38,58 +31,54 @@ class Role:
|
||||||
|
|
||||||
|
|
||||||
class Doppelganger(Role):
|
class Doppelganger(Role):
|
||||||
order = 1
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Werewolf(Role):
|
class Werewolf(Role):
|
||||||
order = 2
|
def __init__(self, game, player=No_player()):
|
||||||
|
super().__init__(game, player)
|
||||||
|
self.is_Werewolf = True
|
||||||
|
|
||||||
def setPlayer(self, player):
|
def add_yourself(self):
|
||||||
super().setPlayer(player)
|
self.game.role[Werewolf].append(self)
|
||||||
self.game.werewolf_list.append(player)
|
|
||||||
|
|
||||||
async def phase2(self):
|
async def phase(self):
|
||||||
if len(self.game.werewolf_list) >= 2:
|
if len(self.game.role[Werewolf]) >= 2:
|
||||||
await self.player.send("Werewolves: " + str(self.game.werewolf_list))
|
await self.send_role_list(Werewolf)
|
||||||
else:
|
else:
|
||||||
await self.player.send("You are the only werewolf")
|
await self.player.send_info("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("Which card in the middle do you want to look at?", ["left", "middle", "right"]) # 0, 1, 2
|
||||||
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())
|
await self.player.send_info(f"A card in the middle is: {self.game.middle_card[self.choice].name()}")
|
||||||
|
|
||||||
|
|
||||||
class Minion(Role):
|
class Minion(Role):
|
||||||
order = 3
|
def __init__(self, game, player=No_player()):
|
||||||
|
super().__init__(game, player)
|
||||||
|
self.is_Minion = True
|
||||||
|
|
||||||
async def phase2(self):
|
async def send_info(self):
|
||||||
if len(self.game.werewolf_list) == 0:
|
if len(self.game.werewolf_list) == 0:
|
||||||
await self.player.send("There were no werewolves so you became one")
|
await self.player.send_info("There were no werewolves, so you need to kill a villager!")
|
||||||
else:
|
else:
|
||||||
await self.player.send("Werewolves: " + str(self.game.werewolf_list))
|
await self.send_role_list(Werewolf)
|
||||||
|
|
||||||
|
|
||||||
class Mason(Role):
|
class Mason(Role):
|
||||||
order = 4
|
def add_yourself(self):
|
||||||
|
self.game.role[Mason].append(self)
|
||||||
|
|
||||||
def setPlayer(self, player):
|
async def send_info(self):
|
||||||
super().setPlayer(player)
|
await self.send_role_list(Mason)
|
||||||
self.game.mason_list.append(player)
|
|
||||||
|
|
||||||
async def phase2(self):
|
|
||||||
await self.player.send("Mason " + str(self.game.mason_list))
|
|
||||||
|
|
||||||
|
|
||||||
class Seer(Role):
|
class Seer(Role):
|
||||||
order = 5
|
async def query(self):
|
||||||
|
self.choice = await self.player.get_choice("Which 1 player card or 2 middle cards do you want to look at?", self.player.other() + ["left & middle", "middle & right", "left & right"])
|
||||||
|
|
||||||
async def phase1(self):
|
async def send_info(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()):
|
if self.choice < len(self.player.other()):
|
||||||
await self.player.send(self.player.other()[self.choice].night_role)
|
await self.player.send_info(self.player.other()[self.choice].night_role)
|
||||||
else:
|
else:
|
||||||
self.choice -= len(self.player.other())
|
self.choice -= len(self.player.other())
|
||||||
if self.choice == 0:
|
if self.choice == 0:
|
||||||
|
@ -99,69 +88,56 @@ class Seer(Role):
|
||||||
else:
|
else:
|
||||||
a, b = 0, 2
|
a, b = 0, 2
|
||||||
|
|
||||||
await self.player.send(str(self.game.middle_card[a]) + " " + str(self.game.middle_card[b]))
|
await self.player.send_info(f"{self.game.middle_card[a]} {self.game.middle_card[b]}")
|
||||||
|
|
||||||
|
|
||||||
class Robber(Role):
|
class Robber(Role):
|
||||||
order = 6
|
async def query(self):
|
||||||
|
self.choice = await self.player.get_choice("Which player do you want to rob?", self.player.other())
|
||||||
|
|
||||||
async def phase1(self):
|
async def simulate(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):
|
|
||||||
self.player.swap(self.player.other()[self.choice])
|
self.player.swap(self.player.other()[self.choice])
|
||||||
await self.player.send("You robbed: " + str(self.player.day_role))
|
|
||||||
|
async def send_info(self):
|
||||||
|
await self.player.send_info(f"You robbed: {self.player.day_role}")
|
||||||
|
|
||||||
|
|
||||||
class Troublemaker(Role):
|
class Troublemaker(Role):
|
||||||
order = 7
|
async def query(self):
|
||||||
|
self.A, self.B = await self.player.get_double_choice("Who do you want to exchange? (send two numbers)", self.player.other())
|
||||||
|
|
||||||
async def phase1(self):
|
async def simulate(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):
|
|
||||||
self.player.other()[self.A].swap(self.player.other()[self.B])
|
self.player.other()[self.A].swap(self.player.other()[self.B])
|
||||||
# receive conformation
|
|
||||||
await self.player.send("Received " + str(self.A) + " " + str(self.B))
|
|
||||||
|
|
||||||
|
|
||||||
class Drunk(Role):
|
class Drunk(Role):
|
||||||
order = 8
|
async def query(self):
|
||||||
|
self.choice = await self.player.get_choice("Which card from the middle do you want to take?", ["left", "middle", "right"])
|
||||||
|
|
||||||
async def phase1(self):
|
async def simulate(self):
|
||||||
await self.player.send("Which card from the middle do you want to take?")
|
self.player.day_role, self.game.middle_card[self.choice] = self.game.middle_card[self.choice], self.player.day_role # swap
|
||||||
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):
|
class Insomniac(Role):
|
||||||
order = 9
|
async def send_info(self):
|
||||||
|
await self.player.send_info(f"You are now: {self.player.day_role}")
|
||||||
async def phase5(self):
|
|
||||||
await self.player.send("You are now: " + str(self.player.day_role))
|
|
||||||
|
|
||||||
|
|
||||||
class Villiager(Role):
|
class Villager(Role):
|
||||||
order = 10
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Tanner(Role):
|
class Tanner(Role):
|
||||||
order = 11
|
def __init__(self, game, player=No_player()):
|
||||||
|
super().__init__(game, player)
|
||||||
|
self.is_Tanner = True
|
||||||
|
|
||||||
|
|
||||||
class Hunter(Role):
|
class Hunter(Role):
|
||||||
order = 12
|
def __init__(self, game, player=No_player()):
|
||||||
|
super().__init__(game, player)
|
||||||
|
self.is_Hunter = True
|
||||||
|
|
||||||
|
|
||||||
class No_role(Role):
|
class No_role(Role):
|
||||||
order = 1000
|
pass
|
||||||
|
|
||||||
|
|
||||||
Role.role_set = [Doppelganger, Werewolf, Minion, Mason, Seer, Robber, Troublemaker, Drunk, Insomniac, Villiager, Tanner, Hunter]
|
|
||||||
|
|
Loading…
Reference in New Issue