today's progress

p_channels from secret_channels

decisions on how to register a channel/votegroup without accidently duplication
fight-fixes
Bobloy 7 years ago
parent 704d0e0ded
commit 130f11422a

@ -12,14 +12,23 @@ class Game:
""" """
Base class to run a single game of Werewolf Base class to run a single game of Werewolf
""" """
default_secret_channel = {
"channel": None,
"players": [],
"votegroup": None
}
def __new__(cls, game_code): def __new__(cls, game_code):
game_code = ["DefaultWerewolf", "Villager", "Villager""] game_code = ["DefaultWerewolf", "Villager", "Villager""]
return Game(game_code) return Game(game_code)
def __init__(self, game_code): def __init__(self, guild, game_code):
self.roles = [] self.guild = guild
self.game_code = game_code self.game_code = game_code
self.roles = []
if self.game_code: if self.game_code:
self.get_roles() self.get_roles()
@ -30,9 +39,11 @@ class Game:
self.game_over = False self.game_over = False
self.can_vote = False self.can_vote = False
self.channel_category = None
self.village_channel = None self.village_channel = None
self.secret_channels = {}
self.vote_groups = [] self.p_channels = {}
self.vote_groups = {}
self.loop = asyncio.get_event_loop() self.loop = asyncio.get_event_loop()
@ -48,15 +59,50 @@ class Game:
4. Start game 4. Start game
""" """
if len(self.players) != self.roles: if len(self.players) != self.roles:
ctx.send("Players does not match roles, cannot start") ctx.send("Player count does not match role count, cannot start")
return False return False
overwrite = {
self.guild.default_role: discord.PermissionOverwrite(read_messages=False),
self.guild.me: discord.PermissionOverwrite(read_messages=True)
}
self.channel_category = await self.guild.create_category("ww-game", overwrites=overwrite, reason="New game of werewolf")
for player in self.players:
overwrite[player.member] = discord.PermissionOverwrite(read_messages=True)
self.village_channel = await self.guild.create_text_channel("Village Square", overwrites=overwrite, reason="New game of werewolf", category=self.channel_category)
# Assuming everything worked so far
await self._at_day_start() # This will queue channels and votegroups to be made
for channel_id in self.p_channels:
overwrite = {
self.guild.default_role: discord.PermissionOverwrite(read_messages=False),
self.guild.me: discord.PermissionOverwrite(read_messages=True)
}
for member in self.p_channels[channel_id]["players"]:
overwrite[member] = discord.PermissionOverwrite(read_messages=True)
channel = await self.guild.create_text_channel(channel_id, overwrites=overwrite, reason="Werewolf secret channel", category=self.channel_category)
self.p_channels[channel_id]["channel"] = channel
if self.p_channels[channel_id]["votegroup"] is not None:
vote_group = self.p_channels[channel_id]["votegroup"](self, channel)
await vote_group.register_player()
self.vote_groups[channel_id] = self.p_channels[channel_id]["votegroup"](self, channel)
############START Notify structure############ ############START Notify structure############
async def _cycle(self): async def _cycle(self):
""" """
Each event calls the next event Each event calls the next event
_at_start()
_at_day_start() _at_day_start()
_at_voted() _at_voted()
@ -65,17 +111,17 @@ class Game:
_at_night_begin() _at_night_begin()
_at_night_end() _at_night_end()
and repeat with _at_morning_start() again and repeat with _at_day_start() again
""" """
await self._at_start(): await self._at_day_start():
async def _at_game_start(self): # ID 0 async def _at_game_start(self): # ID 0
if self.game_over: if self.game_over:
return return
await self.village_channel.send("Game is starting, please wait for setup to complete")
await self._notify(0) await self._notify(0)
asyncio.sleep(60)
await self._at_day_start()
async def _at_day_start(self): # ID 1 async def _at_day_start(self): # ID 1
if self.game_over: if self.game_over:
@ -90,17 +136,20 @@ class Game:
async def _at_voted(self, target): # ID 2 async def _at_voted(self, target): # ID 2
if self.game_over: if self.game_over:
return return
await self._notify(2, target) data = {"player": target}
await self._notify(2, data)
async def _at_kill(self, target): # ID 3 async def _at_kill(self, target): # ID 3
if self.game_over: if self.game_over:
return return
await self._notify(3, target) data = {"player": target}
await self._notify(3, data)
async def _at_hang(self, target): # ID 4 async def _at_hang(self, target): # ID 4
if self.game_over: if self.game_over:
return return
await self._notify(4, target) data = {"player": target}
await self._notify(4, data)
async def _at_day_end(self): # ID 5 async def _at_day_end(self): # ID 5
if self.game_over: if self.game_over:
@ -142,7 +191,7 @@ class Game:
for role in role_order: for role in role_order:
tasks.append(asyncio.ensure_future(role.on_event(event, data)) tasks.append(asyncio.ensure_future(role.on_event(event, data))
# VoteGroup priorities # VoteGroup priorities
vote_order = [votes for votes in self.vote_groups if votes.action_list[event][1]==i] vote_order = [votes for votes in self.vote_groups.values() if votes.action_list[event][1]==i]
for vote_group in vote_order: for vote_group in vote_order:
tasks.append(asyncio.ensure_future(vote_group.on_event(event, data)) tasks.append(asyncio.ensure_future(vote_group.on_event(event, data))
@ -164,15 +213,20 @@ class Game:
return await channel.send(embed=embed) return await channel.send(embed=embed)
async def register_channel(self, channel_id, votegroup = None):
# Create channel, set permissions, register votegroup
if channel_id not in self.secret_channels:
async def register_channel(self, channel_id, player, votegroup=None):
"""
Queue a channel to be created by game_start
"""
if channel_id not in self.p_channels:
self.p_channels[channel_id] = self.default_secret_channel.copy()
await asyncio.sleep(1)
self.p_channels[channel_id]["players"].append(player)
async def register_vote_group(self, channel_id, votegroup = None): if votegroup:
# Register channel and assign passed votegroup to it self.p_channels[channel_id]["votegroup"] = votegroup
if channel_id not in self.secret_channels:
await self.register_channel(channel_id, votegroup(self))
async def join(self, member: discord.Member, channel: discord.Channel): async def join(self, member: discord.Member, channel: discord.Channel):
""" """
@ -202,13 +256,6 @@ class Game:
if self.started: if self.started:
await self.kill() await self.kill()
if member in self.players:
return "{} is already in the game!".format(member.mention)
self.started.append(member)
channel.send("{} has been added to the game, total players is **{}**".format(member.mention, len(self.players)))
async def vote(self, author, id, channel): async def vote(self, author, id, channel):
""" """
Member attempts to cast a vote (usually to lynch) Member attempts to cast a vote (usually to lynch)
@ -223,13 +270,12 @@ class Game:
channel.send("Corpses can't vote") channel.send("Corpses can't vote")
return return
if channel in self.secret_channels.values():
if channel == self.village_channel: if channel == self.village_channel:
if not self.can_vote: if not self.can_vote:
channel.send("Voting is not allowed right now") channel.send("Voting is not allowed right now")
return return
if channel in self.p_channels.values():
try: try:
target = self.players[id] target = self.players[id]
@ -244,6 +290,7 @@ class Game:
""" """
Attempt to kill a target Attempt to kill a target
Source allows admin override Source allows admin override
Be sure to remove permissions appropriately
""" """
async def get_roles(self, game_code=None): async def get_roles(self, game_code=None):

@ -67,7 +67,6 @@ class Role:
self.game = game self.game = game
self.player = None self.player = None
self.blocked = False self.blocked = False
self.secret_channel = None
self.properties = {} # Extra data for other roles (i.e. arsonist) self.properties = {} # Extra data for other roles (i.e. arsonist)
async def on_event(self, event, data): async def on_event(self, event, data):
@ -103,7 +102,7 @@ class Role:
async def _at_game_start(self, data=None): async def _at_game_start(self, data=None):
if self.channel_id: if self.channel_id:
self.properties["channel"] = await self.game.register_channel(self.channel_id) await self.game.register_channel(self.channel_id, self)
await self.player.send_dm(self.game_start_message) #Maybe embeds eventually await self.player.send_dm(self.game_start_message) #Maybe embeds eventually

@ -33,11 +33,11 @@ class VanillaWerewolf(Role):
(self._at_night_end, 5) (self._at_night_end, 5)
] ]
def __init__(self, game): # def __init__(self, game):
self.game = game # self.game = game
self.player = None # self.player = None
self.blocked = False # self.blocked = False
self.properties = {} # Extra data for other roles (i.e. arsonist) # self.properties = {} # Extra data for other roles (i.e. arsonist)
# async def on_event(self, event, data): # async def on_event(self, event, data):
# """ # """
@ -70,9 +70,11 @@ class VanillaWerewolf(Role):
return "Werewolf" return "Werewolf"
async def _at_game_start(self, data=None): async def _at_game_start(self, data=None):
# super()._at_game_start(data) # Registers channel if self.channel_id:
await self.game.register_channel(self.channel_id, self, WolfVote) # Add VoteGroup WolfVote
await self.player.send_dm(self.game_start_message)
await self.game.register_vote_group(self.channel_id, WolfVote)
# async def _at_day_start(self, data=None): # async def _at_day_start(self, data=None):
# super()._at_day_start(data) # super()._at_day_start(data)

@ -11,6 +11,11 @@ class Villager(Role):
allignment = 0 # 1: Town, 2: Werewolf, 3: Neutral allignment = 0 # 1: Town, 2: Werewolf, 3: Neutral
channel_id = "" # Empty for no private channel channel_id = "" # Empty for no private channel
unique = False # Only one of this role per game unique = False # Only one of this role per game
game_start_message="""
Your role is **Villager**
You win by lynching all evil in the town
Lynch players during the day with `[p]ww lynch <ID>`
"""
action_list = [ action_list = [
(self._at_game_start, 0), # (Action, Priority) (self._at_game_start, 0), # (Action, Priority)
(self._at_day_start, 0), (self._at_day_start, 0),
@ -22,63 +27,64 @@ class Villager(Role):
(self._at_night_end, 0) (self._at_night_end, 0)
] ]
def __init__(self, game): # def __init__(self, game):
self.game = game # self.game = game
self.player = None # self.player = None
self.blocked = False # self.blocked = False
self.properties = {} # Extra data for other roles (i.e. arsonist) # self.secret_channel = None
# self.properties = {} # Extra data for other roles (i.e. arsonist)
async def on_event(self, event, data): # async def on_event(self, event, data):
""" # """
See Game class for event guide # See Game class for event guide
""" # """
await action_list[event][0](data) # await action_list[event][0](data)
async def assign_player(self, player): # async def assign_player(self, player):
""" # """
Give this role a player # Give this role a player
Can be used after the game has started (Cult, Mason, other role swap) # Can be used after the game has started (Cult, Mason, other role swap)
""" # """
player.role = self # player.role = self
self.player = player # self.player = player
async def _get_role(self, source=None): async def _get_role(self, source=None):
""" """
Interaction for powerful access of role Interaction for powerful access of role
Unlikely to be able to deceive this Unlikely to be able to deceive this
""" """
return "Default" return "Villager"
async def _see_role(self, source=None): async def _see_role(self, source=None):
""" """
Interaction for investigative roles. Interaction for investigative roles.
More common to be able to deceive these roles More common to be able to deceive these roles
""" """
return "Role" return "Villager"
async def _at_game_start(self, data=None): # async def _at_game_start(self, data=None):
pass # pass
async def _at_day_start(self, data=None): # async def _at_day_start(self, data=None):
pass # pass
async def _at_voted(self, target=None): # async def _at_voted(self, target=None):
pass # pass
async def _at_kill(self, target=None): # async def _at_kill(self, target=None):
pass # pass
async def _at_hang(self, target=None): # async def _at_hang(self, target=None):
pass # pass
async def _at_day_end(self): # async def _at_day_end(self):
pass # pass
async def _at_night_start(self): # async def _at_night_start(self):
pass # pass
async def _at_night_end(self): # async def _at_night_end(self):
pass # pass

@ -26,10 +26,10 @@ class VoteGroup:
] ]
def __init__(self, game, members): def __init__(self, game, channel):
self.game = game self.game = game
self.members = members self.channel = channel
self.channel = None self.players = []
self.vote_results = {} self.vote_results = {}
self.properties = {} # Extra data for other options self.properties = {} # Extra data for other options
@ -42,8 +42,7 @@ class VoteGroup:
await action_list[event][0](data) await action_list[event][0](data)
async def _at_game_start(self, data=None): async def _at_game_start(self, data=None):
if self.channel_id: pass
self.channel = await self.game.register_channel(self.channel_id)
async def _at_day_start(self, data=None): async def _at_day_start(self, data=None):
pass pass
@ -52,10 +51,12 @@ class VoteGroup:
pass pass
async def _at_kill(self, data=None): async def _at_kill(self, data=None):
pass if data["player"] in self.players:
self.players.pop(data["player"])
async def _at_hang(self, data=None): async def _at_hang(self, data=None):
pass if data["player"] in self.players:
self.players.pop(data["player"])
async def _at_day_end(self, data=None): async def _at_day_end(self, data=None):
pass pass
@ -80,18 +81,18 @@ class VoteGroup:
# Do what you voted on # Do what you voted on
pass pass
async def register_member(self, member): async def register_player(self, player):
""" """
Add a member to member list Add a player to player list
""" """
self.members.append(member) self.players.append(player)
async def remove_member(self, member): async def remove_player(self, player):
""" """
Remove a member from member list Remove a player from player list
""" """
if member in self.members: if player.id in self.players:
self.members.remove(member) self.players.remove(player)
async def vote(self, author, id): async def vote(self, author, id):
""" """

@ -27,16 +27,17 @@ class WolfVote(VoteGroup):
kill_messages = [ kill_messages = [
"{target} was attacked by wolves", "**{ID}** - {target} was attacked by wolves",
"{target} was found torn to shreds"] "**{ID}** - {target} was found torn to shreds"]
def __init__(self, game, members): def __init__(self, game, channel):
self.game = game # self.game = game
self.members = members # self.channel = channel
self.channel = None # self.players = []
self.vote_results = {} # self.vote_results = {}
self.properties = {} # Extra data for other options # self.properties = {} # Extra data for other options
self.killer = None # Added killer self.killer = None # Added killer
super().__init__(game, channel)
# async def on_event(self, event, data): # async def on_event(self, event, data):
@ -57,10 +58,12 @@ class WolfVote(VoteGroup):
# pass # pass
# async def _at_kill(self, data=None): # async def _at_kill(self, data=None):
# pass # if data["player"] in self.players:
# self.players.pop(data["player"])
# async def _at_hang(self, data=None): # async def _at_hang(self, data=None):
# pass # if data["player"] in self.players:
# self.players.pop(data["player"])
# async def _at_day_end(self, data=None): # async def _at_day_end(self, data=None):
# pass # pass
@ -71,7 +74,7 @@ class WolfVote(VoteGroup):
await self.game.generate_targets(self.channel) await self.game.generate_targets(self.channel)
self.killer = random.choice(self.members) self.killer = random.choice(self.players)
await channel.send("{} has been selected as tonight's killer") await channel.send("{} has been selected as tonight's killer")

@ -11,7 +11,7 @@ from .game import Game
class Werewolf: class Werewolf:
""" """
Base to host werewolf on a server Base to host werewolf on a guild
""" """
def __init__(self, bot): def __init__(self, bot):
@ -25,7 +25,7 @@ class Werewolf:
self.config.register_global(**default_global) self.config.register_global(**default_global)
self.config.register_guild(**default_guild) self.config.register_guild(**default_guild)
self.games = {} # Active games stored here, id is per server self.games = {} # Active games stored here, id is per guild
@commands.group() @commands.group()
async def ww(self, ctx: commands.Context): async def ww(self, ctx: commands.Context):
@ -44,7 +44,7 @@ class Werewolf:
game = self._get_game(ctx.guild, game_code) game = self._get_game(ctx.guild, game_code)
if not game: if not game:
ctx.send(" ctx.send("Failed to start a new game")
@ww.command() @ww.command()
async def join(self, ctx): async def join(self, ctx):
@ -84,14 +84,14 @@ class Werewolf:
if channel is game.village_channel: if channel is game.village_channel:
await game.vote(ctx.author, id, channel) await game.vote(ctx.author, id, channel)
if channel in (c for id,c in game.secret_channels.items()): if channel in (c["channel"] for c in game.p_channels.values()):
await game.vote(ctx.author, id, channel) await game.vote(ctx.author, id, channel)
def _get_game(self, guild, game_code = None): def _get_game(self, guild, game_code = None):
if guild.id not in self.games: if guild.id not in self.games:
if not game_code: if not game_code:
return None return None
self.games[guild.id] = Game(game_code) self.games[guild.id] = Game(guild, game_code)
return self.games[guild.id] return self.games[guild.id]

Loading…
Cancel
Save