Seer and voting fixes
This commit is contained in:
parent
bae1355037
commit
d0facafb92
@ -1,5 +1,9 @@
|
|||||||
|
from typing import List
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
|
|
||||||
# Import all roles here
|
# Import all roles here
|
||||||
|
from werewolf.role import Role
|
||||||
from werewolf.roles.seer import Seer
|
from werewolf.roles.seer import Seer
|
||||||
from werewolf.roles.vanillawerewolf import VanillaWerewolf
|
from werewolf.roles.vanillawerewolf import VanillaWerewolf
|
||||||
from werewolf.roles.villager import Villager
|
from werewolf.roles.villager import Villager
|
||||||
@ -23,18 +27,18 @@ double digit position preempted by `-`
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
async def parse_code(code):
|
async def parse_code(code, game):
|
||||||
"""Do the magic described above"""
|
"""Do the magic described above"""
|
||||||
out = []
|
out: List[Role] = []
|
||||||
decode = code.copy() # for now, pass exact names
|
decode = code.copy() # for now, pass exact names
|
||||||
for role_id in decode:
|
for role_id in decode:
|
||||||
print(role_id)
|
print(role_id)
|
||||||
if role_id == "Villager":
|
if role_id == "Villager":
|
||||||
role = Villager
|
role = Villager(game)
|
||||||
elif role_id == "VanillaWerewolf":
|
elif role_id == "VanillaWerewolf":
|
||||||
role = VanillaWerewolf
|
role = VanillaWerewolf(game)
|
||||||
elif role_id == "Seer":
|
elif role_id == "Seer":
|
||||||
role = Seer
|
role = Seer(game)
|
||||||
else: # Fail to parse
|
else: # Fail to parse
|
||||||
return None
|
return None
|
||||||
out.append(role)
|
out.append(role)
|
||||||
|
124
werewolf/game.py
124
werewolf/game.py
@ -1,16 +1,21 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
import random
|
import random
|
||||||
|
from typing import List
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
|
|
||||||
from werewolf.builder import parse_code
|
from werewolf.builder import parse_code
|
||||||
from werewolf.player import Player
|
from werewolf.player import Player
|
||||||
|
from werewolf.role import Role
|
||||||
|
|
||||||
|
|
||||||
class Game:
|
class Game:
|
||||||
"""
|
"""
|
||||||
Base class to run a single game of Werewolf
|
Base class to run a single game of Werewolf
|
||||||
"""
|
"""
|
||||||
|
players: List[Player]
|
||||||
|
roles: List[Role]
|
||||||
|
channel_category: discord.CategoryChannel
|
||||||
village_channel: discord.TextChannel
|
village_channel: discord.TextChannel
|
||||||
|
|
||||||
default_secret_channel = {
|
default_secret_channel = {
|
||||||
@ -26,18 +31,12 @@ class Game:
|
|||||||
|
|
||||||
day_vote_count = 3
|
day_vote_count = 3
|
||||||
|
|
||||||
# def __new__(cls, guild, game_code):
|
def __init__(self, guild: discord.Guild, role: discord.Role, game_code=None):
|
||||||
# game_code = ["VanillaWerewolf", "Villager", "Villager"]
|
|
||||||
#
|
|
||||||
# return super().__new__(cls, guild, game_code)
|
|
||||||
|
|
||||||
def __init__(self, guild: discord.Guild, role: discord.Role, game_code):
|
|
||||||
self.guild = guild
|
self.guild = guild
|
||||||
self.game_code = ["VanillaWerewolf"]
|
self.game_code = ["Seer", "VanillaWerewolf", "Villager"]
|
||||||
self.game_role = role
|
self.game_role = role
|
||||||
|
|
||||||
self.roles = []
|
self.roles = []
|
||||||
|
|
||||||
self.players = []
|
self.players = []
|
||||||
|
|
||||||
self.day_vote = {} # author: target
|
self.day_vote = {} # author: target
|
||||||
@ -50,6 +49,7 @@ class Game:
|
|||||||
|
|
||||||
self.day_time = False
|
self.day_time = False
|
||||||
self.day_count = 0
|
self.day_count = 0
|
||||||
|
self.ongoing_vote = False
|
||||||
|
|
||||||
self.channel_category = None
|
self.channel_category = None
|
||||||
self.village_channel = None
|
self.village_channel = None
|
||||||
@ -99,6 +99,7 @@ class Game:
|
|||||||
self.roles = []
|
self.roles = []
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
self.started = True
|
||||||
await self.assign_roles()
|
await self.assign_roles()
|
||||||
|
|
||||||
# Create category and channel with individual overwrites
|
# Create category and channel with individual overwrites
|
||||||
@ -109,15 +110,16 @@ class Game:
|
|||||||
self.game_role: discord.PermissionOverwrite(read_messages=True, send_messages=True)
|
self.game_role: discord.PermissionOverwrite(read_messages=True, send_messages=True)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.channel_category = await self.guild.create_category("ww-game", overwrites=overwrite, reason="New game of "
|
self.channel_category = await self.guild.create_category("ww-game",
|
||||||
"werewolf")
|
overwrites=overwrite,
|
||||||
|
reason="(BOT) New game of werewolf")
|
||||||
|
|
||||||
# for player in self.players:
|
# for player in self.players:
|
||||||
# overwrite[player.member] = discord.PermissionOverwrite(read_messages=True)
|
# overwrite[player.member] = discord.PermissionOverwrite(read_messages=True)
|
||||||
|
|
||||||
self.village_channel = await self.guild.create_text_channel("Village Square",
|
self.village_channel = await self.guild.create_text_channel("Village Square",
|
||||||
overwrites=overwrite,
|
overwrites=overwrite,
|
||||||
reason="New game of werewolf",
|
reason="(BOT) New game of werewolf",
|
||||||
category=self.channel_category)
|
category=self.channel_category)
|
||||||
|
|
||||||
# Assuming everything worked so far
|
# Assuming everything worked so far
|
||||||
@ -136,7 +138,7 @@ class Game:
|
|||||||
|
|
||||||
channel = await self.guild.create_text_channel(channel_id,
|
channel = await self.guild.create_text_channel(channel_id,
|
||||||
overwrites=overwrite,
|
overwrites=overwrite,
|
||||||
reason="Ww game secret channel",
|
reason="(BOT) WW game secret channel",
|
||||||
category=self.channel_category)
|
category=self.channel_category)
|
||||||
|
|
||||||
self.p_channels[channel_id]["channel"] = channel
|
self.p_channels[channel_id]["channel"] = channel
|
||||||
@ -208,13 +210,15 @@ class Game:
|
|||||||
return
|
return
|
||||||
self.can_vote = True
|
self.can_vote = True
|
||||||
|
|
||||||
await asyncio.sleep(12) # 4 minute days FixMe to 120 later
|
await asyncio.sleep(24) # 4 minute days FixMe to 120 later
|
||||||
if check():
|
if check():
|
||||||
return
|
return
|
||||||
await self.village_channel.send(embed=discord.Embed(title="**Two minutes of daylight remain...**"))
|
await self.village_channel.send(embed=discord.Embed(title="**Two minutes of daylight remain...**"))
|
||||||
await asyncio.sleep(12) # 4 minute days FixMe to 120 later
|
await asyncio.sleep(24) # 4 minute days FixMe to 120 later
|
||||||
|
|
||||||
# Need a loop here to wait for trial to end (can_vote?)
|
# Need a loop here to wait for trial to end (can_vote?)
|
||||||
|
while self.ongoing_vote:
|
||||||
|
asyncio.sleep(5)
|
||||||
|
|
||||||
if check():
|
if check():
|
||||||
return
|
return
|
||||||
@ -227,16 +231,17 @@ class Game:
|
|||||||
data = {"player": target}
|
data = {"player": target}
|
||||||
await self._notify(2, data)
|
await self._notify(2, data)
|
||||||
|
|
||||||
|
self.ongoing_vote = True
|
||||||
|
|
||||||
self.used_votes += 1
|
self.used_votes += 1
|
||||||
|
|
||||||
self.can_vote = False
|
await self.speech_perms(self.village_channel, target.member) # Only target can talk
|
||||||
await self.speech_perms(self.village_channel, target.member)
|
|
||||||
await self.village_channel.send(
|
await self.village_channel.send(
|
||||||
"**{} will be put to trial and has 30 seconds to defend themselves**".format(target.mention))
|
"**{} will be put to trial and has 30 seconds to defend themselves**".format(target.mention))
|
||||||
|
|
||||||
await asyncio.sleep(30)
|
await asyncio.sleep(30)
|
||||||
|
|
||||||
await self.speech_perms(self.village_channel, target.member, undo=True)
|
await self.speech_perms(self.village_channel, target.member, undo=True) # No one can talk
|
||||||
|
|
||||||
message = await self.village_channel.send(
|
message = await self.village_channel.send(
|
||||||
"Everyone will now vote whether to lynch {}\n"
|
"Everyone will now vote whether to lynch {}\n"
|
||||||
@ -244,42 +249,46 @@ class Game:
|
|||||||
"*Majority rules, no-lynch on ties, "
|
"*Majority rules, no-lynch on ties, "
|
||||||
"vote both or neither to abstain, 15 seconds to vote*".format(target.mention))
|
"vote both or neither to abstain, 15 seconds to vote*".format(target.mention))
|
||||||
|
|
||||||
await self.village_channel.add_reaction("👍")
|
await message.add_reaction("👍")
|
||||||
await self.village_channel.add_reaction("👎")
|
await message.add_reaction("👎")
|
||||||
|
|
||||||
await asyncio.sleep(15)
|
await asyncio.sleep(15)
|
||||||
|
|
||||||
reaction_list = message.reactions
|
reaction_list = message.reactions
|
||||||
|
|
||||||
up_votes = sum(p.emoji == "👍" and not p.me for p in reaction_list)
|
up_votes = sum(p for p in reaction_list if p.emoji == "👍" and not p.me)
|
||||||
down_votes = sum(p.emoji == "👎" and not p.me for p in reaction_list)
|
down_votes = sum(p for p in reaction_list if p.emoji == "👎" and not p.me )
|
||||||
|
|
||||||
if len(down_votes) > len(up_votes):
|
if down_votes > up_votes:
|
||||||
embed = discord.Embed(title="Vote Results", color=0xff0000)
|
embed = discord.Embed(title="Vote Results", color=0xff0000)
|
||||||
else:
|
else:
|
||||||
embed = discord.Embed(title="Vote Results", color=0x80ff80)
|
embed = discord.Embed(title="Vote Results", color=0x80ff80)
|
||||||
|
|
||||||
embed.add_field(name="👎", value="**{}**".format(len(up_votes)), inline=True)
|
embed.add_field(name="👎", value="**{}**".format(up_votes), inline=True)
|
||||||
embed.add_field(name="👍", value="**{}**".format(len(down_votes)), inline=True)
|
embed.add_field(name="👍", value="**{}**".format(down_votes), inline=True)
|
||||||
|
|
||||||
await self.village_channel.send(embed=embed)
|
await self.village_channel.send(embed=embed)
|
||||||
|
|
||||||
if len(down_votes) > len(up_votes):
|
if down_votes > up_votes:
|
||||||
await self.village_channel.send("**Voted to lynch {}!**".format(target.mention))
|
await self.village_channel.send("**Voted to lynch {}!**".format(target.mention))
|
||||||
await self.lynch(target)
|
await self.lynch(target)
|
||||||
|
self.can_vote = False
|
||||||
else:
|
else:
|
||||||
await self.village_channel.send("**{} has been spared!**".format(target.mention))
|
await self.village_channel.send("**{} has been spared!**".format(target.mention))
|
||||||
|
|
||||||
if self.used_votes >= self.day_vote_count:
|
if self.used_votes >= self.day_vote_count:
|
||||||
await self.village_channel.send("**All votes have been used! Day is now over!**")
|
await self.village_channel.send("**All votes have been used! Day is now over!**")
|
||||||
|
self.can_vote = False
|
||||||
else:
|
else:
|
||||||
await self.village_channel.send(
|
await self.village_channel.send(
|
||||||
"**{}**/**{}** of today's votes have been used!\n"
|
"**{}**/**{}** of today's votes have been used!\n"
|
||||||
"Nominate carefully..".format(self.used_votes, self.day_vote_count))
|
"Nominate carefully..".format(self.used_votes, self.day_vote_count))
|
||||||
self.can_vote = True # Only re-enable voting if more votes remain
|
|
||||||
|
self.ongoing_vote = False
|
||||||
|
|
||||||
if not self.can_vote:
|
if not self.can_vote:
|
||||||
await self._at_day_end()
|
await self._at_day_end()
|
||||||
|
else:
|
||||||
|
await self.normal_perms(self.village_channel) # No point if about to be night
|
||||||
|
|
||||||
async def _at_kill(self, target): # ID 3
|
async def _at_kill(self, target): # ID 3
|
||||||
if self.game_over:
|
if self.game_over:
|
||||||
@ -330,7 +339,7 @@ class Game:
|
|||||||
return
|
return
|
||||||
await self._notify(7)
|
await self._notify(7)
|
||||||
|
|
||||||
await asyncio.sleep(15)
|
await asyncio.sleep(10)
|
||||||
await self._at_day_start()
|
await self._at_day_start()
|
||||||
|
|
||||||
async def _at_visit(self, target, source): # ID 8
|
async def _at_visit(self, target, source): # ID 8
|
||||||
@ -356,20 +365,22 @@ class Game:
|
|||||||
|
|
||||||
############END Notify structure############
|
############END Notify structure############
|
||||||
|
|
||||||
async def generate_targets(self, channel, with_roles = False):
|
async def generate_targets(self, channel, with_roles=False):
|
||||||
embed = discord.Embed(title="Remaining Players")
|
embed = discord.Embed(title="Remaining Players")
|
||||||
for i in range(len(self.players)):
|
for i in range(len(self.players)):
|
||||||
player = self.players[i]
|
player = self.players[i]
|
||||||
if player.alive:
|
if player.alive:
|
||||||
status = ""
|
status = ""
|
||||||
else:
|
else:
|
||||||
status = "*Dead*"
|
status = "*[Dead]*-"
|
||||||
if with_roles:
|
if with_roles or not player.alive:
|
||||||
embed.add_field(name="ID# **{}**".format(i),
|
embed.add_field(name="ID# **{}**".format(i),
|
||||||
value="{} {} {}".format(status, player.member.display_name, str(player.role)), inline=True)
|
value="{}{}-{}".format(status, player.member.display_name, str(player.role)),
|
||||||
|
inline=True)
|
||||||
else:
|
else:
|
||||||
embed.add_field(name="ID# **{}**".format(i),
|
embed.add_field(name="ID# **{}**".format(i),
|
||||||
value="{} {}".format(status, player.member.display_name), inline=True)
|
value="{}{}".format(status, player.member.display_name),
|
||||||
|
inline=True)
|
||||||
|
|
||||||
return await channel.send(embed=embed)
|
return await channel.send(embed=embed)
|
||||||
|
|
||||||
@ -405,6 +416,8 @@ class Game:
|
|||||||
|
|
||||||
self.players.append(Player(member))
|
self.players.append(Player(member))
|
||||||
|
|
||||||
|
await member.add_roles(*[self.game_role])
|
||||||
|
|
||||||
await channel.send("{} has been added to the game, "
|
await channel.send("{} has been added to the game, "
|
||||||
"total players is **{}**".format(member.mention, len(self.players)))
|
"total players is **{}**".format(member.mention, len(self.players)))
|
||||||
|
|
||||||
@ -422,6 +435,7 @@ class Game:
|
|||||||
await channel.send("{} has left the game".format(member.mention))
|
await channel.send("{} has left the game".format(member.mention))
|
||||||
else:
|
else:
|
||||||
self.players = [player for player in self.players if player.member != member]
|
self.players = [player for player in self.players if player.member != member]
|
||||||
|
await member.remove_roles(*[self.game_role])
|
||||||
await channel.send("{} chickened out, player count is now **{}**".format(member.mention, len(self.players)))
|
await channel.send("{} chickened out, player count is now **{}**".format(member.mention, len(self.players)))
|
||||||
|
|
||||||
async def choose(self, ctx, data):
|
async def choose(self, ctx, data):
|
||||||
@ -436,7 +450,7 @@ class Game:
|
|||||||
return
|
return
|
||||||
|
|
||||||
if not player.alive:
|
if not player.alive:
|
||||||
await ctx.send("**Corpses** can't vote...")
|
await ctx.send("**Corpses** can't participate...")
|
||||||
return
|
return
|
||||||
|
|
||||||
if player.role.blocked:
|
if player.role.blocked:
|
||||||
@ -446,7 +460,7 @@ class Game:
|
|||||||
# Let role do target validation, might be alternate targets
|
# Let role do target validation, might be alternate targets
|
||||||
# I.E. Go on alert? y/n
|
# I.E. Go on alert? y/n
|
||||||
|
|
||||||
await player.choose(ctx, data)
|
await player.role.choose(ctx, data)
|
||||||
|
|
||||||
async def _visit(self, target, source):
|
async def _visit(self, target, source):
|
||||||
await target.role.visit(source)
|
await target.role.visit(source)
|
||||||
@ -476,7 +490,7 @@ class Game:
|
|||||||
return
|
return
|
||||||
|
|
||||||
if not player.alive:
|
if not player.alive:
|
||||||
await channel.send("Corpses can't vote")
|
await channel.send("Corpses can't vote...")
|
||||||
return
|
return
|
||||||
|
|
||||||
if channel == self.village_channel:
|
if channel == self.village_channel:
|
||||||
@ -536,7 +550,9 @@ class Game:
|
|||||||
out = "**{ID}** - " + method
|
out = "**{ID}** - " + method
|
||||||
return out.format(ID=target.id, target=target.member.display_name)
|
return out.format(ID=target.id, target=target.member.display_name)
|
||||||
else:
|
else:
|
||||||
return "**{ID}** - {target} was found dead".format(ID=target.id, target=target.member.display_name)
|
return "**{ID}** - {target} the {role} was found dead".format(ID=target.id,
|
||||||
|
target=target.member.display_name,
|
||||||
|
role=await target.role.get_role())
|
||||||
|
|
||||||
async def _quit(self, player):
|
async def _quit(self, player):
|
||||||
"""
|
"""
|
||||||
@ -607,7 +623,7 @@ class Game:
|
|||||||
if self.game_code is None:
|
if self.game_code is None:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self.roles = await parse_code(self.game_code)
|
self.roles = await parse_code(self.game_code, self)
|
||||||
|
|
||||||
if not self.roles:
|
if not self.roles:
|
||||||
return False
|
return False
|
||||||
@ -618,11 +634,10 @@ class Game:
|
|||||||
self.players.sort(key=lambda pl: pl.member.display_name.lower())
|
self.players.sort(key=lambda pl: pl.member.display_name.lower())
|
||||||
|
|
||||||
if len(self.roles) != len(self.players):
|
if len(self.roles) != len(self.players):
|
||||||
await self.village_channel("Unhandled error - roles!=players")
|
await self.village_channel.send("Unhandled error - roles!=players")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
for idx, role in enumerate(self.roles):
|
for idx, role in enumerate(self.roles):
|
||||||
self.roles[idx] = role(self)
|
|
||||||
await self.roles[idx].assign_player(self.players[idx])
|
await self.roles[idx].assign_player(self.players[idx])
|
||||||
# Sorted players, now assign id's
|
# Sorted players, now assign id's
|
||||||
await self.players[idx].assign_id(idx)
|
await self.players[idx].assign_id(idx)
|
||||||
@ -650,18 +665,30 @@ class Game:
|
|||||||
await channel.set_permissions(self.game_role, read_messages=True, send_messages=False)
|
await channel.set_permissions(self.game_role, read_messages=True, send_messages=False)
|
||||||
await channel.set_permissions(member, send_messages=True)
|
await channel.set_permissions(member, send_messages=True)
|
||||||
|
|
||||||
async def normal_perms(self, channel, member_list):
|
async def normal_perms(self, channel):
|
||||||
await channel.set_permissions(self.game_role, read_messages=True, send_messages=True)
|
await channel.set_permissions(self.game_role, read_messages=True, send_messages=True)
|
||||||
# for member in member_list:
|
|
||||||
# await channel.set_permissions(member, read_messages=True)
|
|
||||||
|
|
||||||
async def _check_game_over(self):
|
async def _check_game_over(self):
|
||||||
|
# return # ToDo: re-enable game-over checking
|
||||||
alive_players = [player for player in self.players if player.alive]
|
alive_players = [player for player in self.players if player.alive]
|
||||||
|
|
||||||
if len(alive_players) <= 2:
|
if len(alive_players) <= 0:
|
||||||
|
await self.village_channel.send(embed=discord.Embed(title="**Everyone is dead! Game Over!**"))
|
||||||
self.game_over = True
|
self.game_over = True
|
||||||
|
elif len(alive_players) == 1:
|
||||||
|
self.game_over = True
|
||||||
|
await self._announce_winners(alive_players)
|
||||||
|
elif len(alive_players) == 2:
|
||||||
# Check 1v1 victory conditions ToDo
|
# Check 1v1 victory conditions ToDo
|
||||||
pass
|
self.game_over = True
|
||||||
|
alignment1 = alive_players[0].role.alignment
|
||||||
|
alignment2 = alive_players[1].role.alignment
|
||||||
|
if alignment1 == alignment2: # Same team
|
||||||
|
winners = alive_players
|
||||||
|
else:
|
||||||
|
winners = [max(alive_players, key=lambda p: p.role.alignment)]
|
||||||
|
|
||||||
|
await self._announce_winners(winners)
|
||||||
else:
|
else:
|
||||||
# Check if everyone is on the same team
|
# Check if everyone is on the same team
|
||||||
alignment = alive_players[0].role.alignment # Get first allignment and compare to rest
|
alignment = alive_players[0].role.alignment # Get first allignment and compare to rest
|
||||||
@ -686,8 +713,9 @@ class Game:
|
|||||||
|
|
||||||
await self.generate_targets(self.village_channel, True)
|
await self.generate_targets(self.village_channel, True)
|
||||||
|
|
||||||
|
|
||||||
async def _end_game(self):
|
async def _end_game(self):
|
||||||
# Remove game_role access for potential archiving for now
|
# Remove game_role access for potential archiving for now
|
||||||
await self.village_channel.set_permissions(self.game_role, overwrite=None)
|
reason = '(BOT) End of WW game'
|
||||||
pass
|
await self.village_channel.set_permissions(self.game_role, overwrite=None, reason=reason)
|
||||||
|
await self.channel_category.set_permissions(self.game_role, overwrite=None, reason=reason)
|
||||||
|
await self.channel_category.edit(reason=reason, name="Archived Game")
|
||||||
|
@ -29,7 +29,8 @@ class Seer(Role):
|
|||||||
(self._at_hang, 0),
|
(self._at_hang, 0),
|
||||||
(self._at_day_end, 0),
|
(self._at_day_end, 0),
|
||||||
(self._at_night_start, 2),
|
(self._at_night_start, 2),
|
||||||
(self._at_night_end, 4)
|
(self._at_night_end, 4),
|
||||||
|
(self._at_visit, 0)
|
||||||
]
|
]
|
||||||
|
|
||||||
# async def on_event(self, event, data):
|
# async def on_event(self, event, data):
|
||||||
@ -96,15 +97,22 @@ class Seer(Role):
|
|||||||
# pass
|
# pass
|
||||||
|
|
||||||
async def _at_night_start(self, data=None):
|
async def _at_night_start(self, data=None):
|
||||||
|
if not self.player.alive:
|
||||||
|
return
|
||||||
|
self.see_target = None
|
||||||
await self.game.generate_targets(self.player.member)
|
await self.game.generate_targets(self.player.member)
|
||||||
await self.player.send_dm("{}\n**Pick a target to see tonight**\n")
|
await self.player.send_dm("**Pick a target to see tonight**\n")
|
||||||
|
|
||||||
async def _at_night_end(self, data=None):
|
async def _at_night_end(self, data=None):
|
||||||
target = await self.game.visit(self.see_target)
|
if self.see_target is None:
|
||||||
|
if self.player.alive:
|
||||||
|
await self.player.send_dm("You will not use your powers tonight...")
|
||||||
|
return
|
||||||
|
target = await self.game.visit(self.see_target, self.player)
|
||||||
|
|
||||||
alignment = None
|
alignment = None
|
||||||
if target:
|
if target:
|
||||||
alignment = await target.see_alignment(self.player)
|
alignment = await target.role.see_alignment(self.player)
|
||||||
|
|
||||||
if alignment == "Werewolf":
|
if alignment == "Werewolf":
|
||||||
out = "Your insight reveals this player to be a **Werewolf!**"
|
out = "Your insight reveals this player to be a **Werewolf!**"
|
||||||
@ -133,6 +141,10 @@ class Seer(Role):
|
|||||||
|
|
||||||
async def choose(self, ctx, data):
|
async def choose(self, ctx, data):
|
||||||
"""Handle night actions"""
|
"""Handle night actions"""
|
||||||
|
if not self.player.alive: # FixMe: Game handles this?
|
||||||
|
await self.player.send_dm("You're already dead!")
|
||||||
|
return
|
||||||
|
|
||||||
target_id = int(data)
|
target_id = int(data)
|
||||||
try:
|
try:
|
||||||
target = self.game.players[target_id]
|
target = self.game.players[target_id]
|
||||||
|
@ -4,6 +4,7 @@ import discord
|
|||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from redbot.core import Config
|
from redbot.core import Config
|
||||||
from redbot.core import RedContext
|
from redbot.core import RedContext
|
||||||
|
from redbot.core.bot import Red
|
||||||
|
|
||||||
from werewolf.game import Game
|
from werewolf.game import Game
|
||||||
|
|
||||||
@ -14,12 +15,12 @@ class Werewolf:
|
|||||||
"""
|
"""
|
||||||
games: Dict[int, Game]
|
games: Dict[int, Game]
|
||||||
|
|
||||||
def __init__(self, bot):
|
def __init__(self, bot: Red):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
self.config = Config.get_conf(self, identifier=87101114101119111108102, force_registration=True)
|
self.config = Config.get_conf(self, identifier=87101114101119111108102, force_registration=True)
|
||||||
default_global = {}
|
default_global = {}
|
||||||
default_guild = {
|
default_guild = {
|
||||||
"role": None
|
"role_id": None
|
||||||
}
|
}
|
||||||
|
|
||||||
self.config.register_global(**default_global)
|
self.config.register_global(**default_global)
|
||||||
@ -47,7 +48,7 @@ class Werewolf:
|
|||||||
Assign the game role
|
Assign the game role
|
||||||
This role should not be manually assigned
|
This role should not be manually assigned
|
||||||
"""
|
"""
|
||||||
await self.config.guild(ctx.guild).role.set(role.id)
|
await self.config.guild(ctx.guild).role_id.set(role.id)
|
||||||
await ctx.send("Game role has been set to **{}**".format(role.name))
|
await ctx.send("Game role has been set to **{}**".format(role.name))
|
||||||
|
|
||||||
@commands.group()
|
@commands.group()
|
||||||
@ -64,13 +65,11 @@ class Werewolf:
|
|||||||
"""
|
"""
|
||||||
Create and join a new game of Werewolf
|
Create and join a new game of Werewolf
|
||||||
"""
|
"""
|
||||||
|
|
||||||
game = await self._get_game(ctx, game_code)
|
game = await self._get_game(ctx, game_code)
|
||||||
|
|
||||||
if not game:
|
if not game:
|
||||||
await ctx.send("Failed to start a new game")
|
await ctx.send("Failed to start a new game")
|
||||||
else:
|
else:
|
||||||
await ctx.send("Game is ready to join! Use `[p]`ww join`")
|
await ctx.send("Game is ready to join! Use `[p]ww join`")
|
||||||
|
|
||||||
@commands.guild_only()
|
@commands.guild_only()
|
||||||
@ww.command()
|
@ww.command()
|
||||||
@ -79,7 +78,7 @@ class Werewolf:
|
|||||||
Joins a game of Werewolf
|
Joins a game of Werewolf
|
||||||
"""
|
"""
|
||||||
|
|
||||||
game = await self._get_game(ctx.guild)
|
game = await self._get_game(ctx)
|
||||||
|
|
||||||
if not game:
|
if not game:
|
||||||
await ctx.send("No game to join!\nCreate a new one with `[p]ww new`")
|
await ctx.send("No game to join!\nCreate a new one with `[p]ww new`")
|
||||||
@ -94,7 +93,7 @@ class Werewolf:
|
|||||||
Quit a game of Werewolf
|
Quit a game of Werewolf
|
||||||
"""
|
"""
|
||||||
|
|
||||||
game = await self._get_game(ctx.guild)
|
game = await self._get_game(ctx)
|
||||||
|
|
||||||
await game.quit(ctx.author, ctx.channel)
|
await game.quit(ctx.author, ctx.channel)
|
||||||
|
|
||||||
@ -104,7 +103,7 @@ class Werewolf:
|
|||||||
"""
|
"""
|
||||||
Checks number of players and attempts to start the game
|
Checks number of players and attempts to start the game
|
||||||
"""
|
"""
|
||||||
game = await self._get_game(ctx.guild)
|
game = await self._get_game(ctx)
|
||||||
if not game:
|
if not game:
|
||||||
await ctx.send("No game running, cannot start")
|
await ctx.send("No game running, cannot start")
|
||||||
|
|
||||||
@ -116,7 +115,7 @@ class Werewolf:
|
|||||||
"""
|
"""
|
||||||
Stops the current game
|
Stops the current game
|
||||||
"""
|
"""
|
||||||
game = await self._get_game(ctx.guild)
|
game = await self._get_game(ctx)
|
||||||
if not game:
|
if not game:
|
||||||
await ctx.send("No game running, cannot stop")
|
await ctx.send("No game running, cannot stop")
|
||||||
|
|
||||||
@ -130,7 +129,7 @@ class Werewolf:
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
target_id = int(target_id)
|
target_id = int(target_id)
|
||||||
except:
|
except ValueError:
|
||||||
target_id = None
|
target_id = None
|
||||||
|
|
||||||
if target_id is None:
|
if target_id is None:
|
||||||
@ -148,7 +147,7 @@ class Werewolf:
|
|||||||
# return
|
# return
|
||||||
# else:
|
# else:
|
||||||
|
|
||||||
game = await self._get_game(ctx.guild)
|
game = await self._get_game(ctx)
|
||||||
|
|
||||||
if game is None:
|
if game is None:
|
||||||
await ctx.send("No game running, cannot vote")
|
await ctx.send("No game running, cannot vote")
|
||||||
@ -186,17 +185,17 @@ class Werewolf:
|
|||||||
|
|
||||||
await game.choose(ctx, data)
|
await game.choose(ctx, data)
|
||||||
|
|
||||||
async def _get_game(self, ctx, game_code=None):
|
async def _get_game(self, ctx: RedContext, game_code=None):
|
||||||
if ctx.guild is None:
|
if ctx.guild is None:
|
||||||
# Private message, can't get guild
|
# Private message, can't get guild
|
||||||
|
ctx.send("Cannot start game from PM!")
|
||||||
return None
|
return None
|
||||||
if ctx.guild.id not in self.games or self.games[ctx.guild.id].game_over:
|
if ctx.guild.id not in self.games or self.games[ctx.guild.id].game_over:
|
||||||
await ctx.send("Starting a new game...")
|
await ctx.send("Starting a new game...")
|
||||||
if not game_code:
|
role_id = await self.config.guild(ctx.guild).role_id()
|
||||||
return None
|
role = discord.utils.get(ctx.guild.roles, id=role_id)
|
||||||
role = await self.config.guild(ctx.guild).role()
|
|
||||||
role = discord.utils.get(ctx.guild.roles, id=role)
|
|
||||||
if role is None:
|
if role is None:
|
||||||
|
ctx.send("Game role is invalid, cannot start new game")
|
||||||
return None
|
return None
|
||||||
self.games[ctx.guild.id] = Game(ctx.guild, role, game_code)
|
self.games[ctx.guild.id] = Game(ctx.guild, role, game_code)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user