today's progress
p_channels from secret_channels decisions on how to register a channel/votegroup without accidently duplication
This commit is contained in:
		
							parent
							
								
									704d0e0ded
								
							
						
					
					
						commit
						130f11422a
					
				
							
								
								
									
										107
									
								
								werewolf/Game.py
									
									
									
									
									
								
							
							
						
						
									
										107
									
								
								werewolf/Game.py
									
									
									
									
									
								
							| @ -12,14 +12,23 @@ class Game: | ||||
|     """ | ||||
|     Base class to run a single game of Werewolf | ||||
|     """ | ||||
|      | ||||
|     default_secret_channel = { | ||||
|                 "channel": None, | ||||
|                 "players": [], | ||||
|                 "votegroup": None | ||||
|                 } | ||||
|      | ||||
|     def __new__(cls, game_code): | ||||
|         game_code = ["DefaultWerewolf", "Villager", "Villager""] | ||||
|         return Game(game_code) | ||||
| 
 | ||||
|     def __init__(self, game_code): | ||||
|         self.roles = [] | ||||
|     def __init__(self, guild, game_code): | ||||
|         self.guild = guild | ||||
|         self.game_code = game_code | ||||
|          | ||||
|         self.roles = [] | ||||
|          | ||||
|         if self.game_code: | ||||
|             self.get_roles() | ||||
|          | ||||
| @ -30,9 +39,11 @@ class Game: | ||||
|         self.game_over = False | ||||
|         self.can_vote = False | ||||
|          | ||||
|         self.channel_category = None | ||||
|         self.village_channel = None | ||||
|         self.secret_channels = {} | ||||
|         self.vote_groups = [] | ||||
|                  | ||||
|         self.p_channels = {} | ||||
|         self.vote_groups = {} | ||||
|          | ||||
|         self.loop = asyncio.get_event_loop() | ||||
|          | ||||
| @ -48,15 +59,50 @@ class Game: | ||||
|         4. Start game | ||||
|         """ | ||||
|         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 | ||||
|          | ||||
|         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############ | ||||
|     async def _cycle(self): | ||||
|         """ | ||||
|         Each event calls the next event | ||||
|          | ||||
|         _at_start() | ||||
|          | ||||
| 
 | ||||
|         _at_day_start() | ||||
|             _at_voted() | ||||
| @ -65,17 +111,17 @@ class Game: | ||||
|         _at_night_begin() | ||||
|         _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 | ||||
|         if self.game_over: | ||||
|             return | ||||
|         await self.village_channel.send("Game is starting, please wait for setup to complete") | ||||
|          | ||||
|         await self._notify(0) | ||||
| 
 | ||||
|         asyncio.sleep(60) | ||||
|         await self._at_day_start() | ||||
|          | ||||
|     async def _at_day_start(self):  # ID 1 | ||||
|         if self.game_over: | ||||
| @ -90,17 +136,20 @@ class Game: | ||||
|     async def _at_voted(self, target):  # ID 2 | ||||
|         if self.game_over: | ||||
|             return | ||||
|         await self._notify(2, target) | ||||
|         data = {"player": target} | ||||
|         await self._notify(2, data) | ||||
|      | ||||
|     async def _at_kill(self, target):  # ID 3 | ||||
|         if self.game_over: | ||||
|             return | ||||
|         await self._notify(3, target) | ||||
|         data = {"player": target} | ||||
|         await self._notify(3, data) | ||||
|      | ||||
|     async def _at_hang(self, target):  # ID 4 | ||||
|         if self.game_over: | ||||
|             return | ||||
|         await self._notify(4, target) | ||||
|         data = {"player": target} | ||||
|         await self._notify(4, data) | ||||
|          | ||||
|     async def _at_day_end(self):  # ID 5 | ||||
|         if self.game_over: | ||||
| @ -142,7 +191,7 @@ class Game: | ||||
|             for role in role_order: | ||||
|                 tasks.append(asyncio.ensure_future(role.on_event(event, data)) | ||||
|             # 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: | ||||
|                 tasks.append(asyncio.ensure_future(vote_group.on_event(event, data)) | ||||
|                  | ||||
| @ -164,15 +213,20 @@ class Game: | ||||
|    | ||||
|         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() | ||||
| 
 | ||||
|     async def register_vote_group(self, channel_id, votegroup = None): | ||||
|         # Register channel and assign passed votegroup to it | ||||
|         if channel_id not in self.secret_channels: | ||||
|             await self.register_channel(channel_id, votegroup(self)) | ||||
|         await asyncio.sleep(1) | ||||
|          | ||||
|         self.p_channels[channel_id]["players"].append(player) | ||||
|          | ||||
|         if votegroup: | ||||
|             self.p_channels[channel_id]["votegroup"] = votegroup | ||||
| 
 | ||||
|     async def join(self, member: discord.Member, channel: discord.Channel): | ||||
|         """ | ||||
| @ -202,13 +256,6 @@ class Game: | ||||
|         if self.started: | ||||
|             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): | ||||
|         """ | ||||
|         Member attempts to cast a vote (usually to lynch) | ||||
| @ -223,13 +270,12 @@ class Game: | ||||
|             channel.send("Corpses can't vote") | ||||
|             return | ||||
|              | ||||
|         if channel in self.secret_channels.values(): | ||||
|              | ||||
|         if channel == self.village_channel: | ||||
|             if not self.can_vote: | ||||
|                 channel.send("Voting is not allowed right now") | ||||
|                 return | ||||
|                  | ||||
|         if channel in self.p_channels.values(): | ||||
| 
 | ||||
|         try: | ||||
|             target = self.players[id] | ||||
| @ -244,6 +290,7 @@ class Game: | ||||
|         """ | ||||
|         Attempt to kill a target | ||||
|         Source allows admin override | ||||
|         Be sure to remove permissions appropriately | ||||
|         """ | ||||
|          | ||||
|     async def get_roles(self, game_code=None): | ||||
|  | ||||
| @ -67,7 +67,6 @@ class Role: | ||||
|         self.game = game | ||||
|         self.player = None | ||||
|         self.blocked = False | ||||
|         self.secret_channel = None | ||||
|         self.properties = {}  # Extra data for other roles (i.e. arsonist) | ||||
|          | ||||
|     async def on_event(self, event, data): | ||||
| @ -103,7 +102,7 @@ class Role: | ||||
|      | ||||
|     async def _at_game_start(self, data=None): | ||||
|         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 | ||||
|          | ||||
|  | ||||
| @ -33,11 +33,11 @@ class VanillaWerewolf(Role): | ||||
|             (self._at_night_end, 5) | ||||
|             ] | ||||
|              | ||||
|     def __init__(self, game): | ||||
|         self.game = game | ||||
|         self.player = None | ||||
|         self.blocked = False | ||||
|         self.properties = {}  # Extra data for other roles (i.e. arsonist) | ||||
|     # def __init__(self, game): | ||||
|         # self.game = game | ||||
|         # self.player = None | ||||
|         # self.blocked = False | ||||
|         # self.properties = {}  # Extra data for other roles (i.e. arsonist) | ||||
|      | ||||
|     # async def on_event(self, event, data): | ||||
|         # """ | ||||
| @ -70,9 +70,11 @@ class VanillaWerewolf(Role): | ||||
|         return "Werewolf" | ||||
|      | ||||
|     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): | ||||
|         # super()._at_day_start(data) | ||||
|  | ||||
| @ -11,6 +11,11 @@ class Villager(Role): | ||||
|     allignment = 0      # 1: Town, 2: Werewolf, 3: Neutral | ||||
|     channel_id = ""     # Empty for no private channel | ||||
|     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 = [ | ||||
|             (self._at_game_start, 0),  # (Action, Priority) | ||||
|             (self._at_day_start, 0), | ||||
| @ -22,63 +27,64 @@ class Villager(Role): | ||||
|             (self._at_night_end, 0) | ||||
|             ] | ||||
|              | ||||
|     def __init__(self, game): | ||||
|         self.game = game | ||||
|         self.player = None | ||||
|         self.blocked = False | ||||
|         self.properties = {}  # Extra data for other roles (i.e. arsonist) | ||||
|     # def __init__(self, game): | ||||
|         # self.game = game | ||||
|         # self.player = None | ||||
|         # self.blocked = False | ||||
|         # self.secret_channel = None | ||||
|         # self.properties = {}  # Extra data for other roles (i.e. arsonist) | ||||
|          | ||||
|     async def on_event(self, event, data): | ||||
|         """ | ||||
|         See Game class for event guide | ||||
|         """ | ||||
|     # async def on_event(self, event, data): | ||||
|         # """ | ||||
|         # See Game class for event guide | ||||
|         # """ | ||||
|              | ||||
|         await action_list[event][0](data) | ||||
|         # await action_list[event][0](data) | ||||
|          | ||||
|          | ||||
|     async def assign_player(self, player): | ||||
|         """ | ||||
|         Give this role a player | ||||
|         Can be used after the game has started  (Cult, Mason, other role swap) | ||||
|         """ | ||||
|     # async def assign_player(self, player): | ||||
|         # """ | ||||
|         # Give this role a player | ||||
|         # Can be used after the game has started  (Cult, Mason, other role swap) | ||||
|         # """ | ||||
| 
 | ||||
|         player.role = self | ||||
|         self.player = player | ||||
|         # player.role = self | ||||
|         # self.player = player | ||||
|      | ||||
|     async def _get_role(self, source=None): | ||||
|         """ | ||||
|         Interaction for powerful access of role | ||||
|         Unlikely to be able to deceive this | ||||
|         """ | ||||
|         return "Default" | ||||
|         return "Villager" | ||||
|      | ||||
|     async def _see_role(self, source=None): | ||||
|         """ | ||||
|         Interaction for investigative roles. | ||||
|         More common to be able to deceive these roles | ||||
|         """ | ||||
|         return "Role" | ||||
|         return "Villager" | ||||
|      | ||||
|     async def _at_game_start(self, data=None): | ||||
|         pass | ||||
|     # async def _at_game_start(self, data=None): | ||||
|         # pass | ||||
|          | ||||
|     async def _at_day_start(self, data=None): | ||||
|         pass | ||||
|     # async def _at_day_start(self, data=None): | ||||
|         # pass | ||||
|          | ||||
|     async def _at_voted(self, target=None): | ||||
|         pass | ||||
|     # async def _at_voted(self, target=None): | ||||
|         # pass | ||||
|          | ||||
|     async def _at_kill(self, target=None): | ||||
|         pass | ||||
|     # async def _at_kill(self, target=None): | ||||
|         # pass | ||||
|          | ||||
|     async def _at_hang(self, target=None): | ||||
|         pass | ||||
|     # async def _at_hang(self, target=None): | ||||
|         # pass | ||||
|          | ||||
|     async def _at_day_end(self): | ||||
|         pass | ||||
|     # async def _at_day_end(self): | ||||
|         # pass | ||||
|          | ||||
|     async def _at_night_start(self): | ||||
|         pass | ||||
|     # async def _at_night_start(self): | ||||
|         # pass | ||||
|          | ||||
|     async def _at_night_end(self): | ||||
|         pass | ||||
|     # async def _at_night_end(self): | ||||
|         # pass | ||||
|  | ||||
| @ -26,10 +26,10 @@ class VoteGroup: | ||||
|             ] | ||||
|              | ||||
| 
 | ||||
|     def __init__(self, game, members): | ||||
|     def __init__(self, game, channel): | ||||
|         self.game = game | ||||
|         self.members = members | ||||
|         self.channel = None | ||||
|         self.channel = channel | ||||
|         self.players = [] | ||||
|         self.vote_results = {} | ||||
|         self.properties = {}  # Extra data for other options | ||||
|          | ||||
| @ -42,8 +42,7 @@ class VoteGroup: | ||||
|         await action_list[event][0](data) | ||||
| 
 | ||||
|     async def _at_game_start(self, data=None): | ||||
|         if self.channel_id: | ||||
|             self.channel = await self.game.register_channel(self.channel_id) | ||||
|         pass | ||||
| 
 | ||||
|     async def _at_day_start(self, data=None): | ||||
|         pass | ||||
| @ -52,10 +51,12 @@ class VoteGroup: | ||||
|         pass | ||||
|          | ||||
|     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): | ||||
|         pass | ||||
|         if data["player"] in self.players: | ||||
|             self.players.pop(data["player"]) | ||||
| 
 | ||||
|     async def _at_day_end(self, data=None): | ||||
|         pass | ||||
| @ -80,18 +81,18 @@ class VoteGroup: | ||||
|             # Do what you voted on | ||||
|             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: | ||||
|             self.members.remove(member) | ||||
|         if player.id in self.players: | ||||
|             self.players.remove(player) | ||||
| 
 | ||||
|     async def vote(self, author, id): | ||||
|         """ | ||||
|  | ||||
| @ -27,16 +27,17 @@ class WolfVote(VoteGroup): | ||||
|              | ||||
|      | ||||
|     kill_messages = [ | ||||
|         "{target} was attacked by wolves", | ||||
|         "{target} was found torn to shreds"] | ||||
|         "**{ID}** - {target} was attacked by wolves", | ||||
|         "**{ID}** - {target} was found torn to shreds"] | ||||
|      | ||||
|     def __init__(self, game, members): | ||||
|         self.game = game | ||||
|         self.members = members | ||||
|         self.channel = None | ||||
|         self.vote_results = {} | ||||
|         self.properties = {}  # Extra data for other options | ||||
|     def __init__(self, game, channel): | ||||
|         # self.game = game | ||||
|         # self.channel = channel | ||||
|         # self.players = [] | ||||
|         # self.vote_results = {} | ||||
|         # self.properties = {}  # Extra data for other options | ||||
|         self.killer = None  # Added killer | ||||
|         super().__init__(game, channel) | ||||
|          | ||||
|          | ||||
|     # async def on_event(self, event, data): | ||||
| @ -57,10 +58,12 @@ class WolfVote(VoteGroup): | ||||
|         # pass | ||||
|          | ||||
|     # 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): | ||||
|         # pass | ||||
|         # if data["player"] in self.players: | ||||
|             # self.players.pop(data["player"]) | ||||
|          | ||||
|     # async def _at_day_end(self, data=None): | ||||
|         # pass | ||||
| @ -71,7 +74,7 @@ class WolfVote(VoteGroup): | ||||
|          | ||||
|         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") | ||||
|          | ||||
|  | ||||
| @ -11,7 +11,7 @@ from .game import Game | ||||
| 
 | ||||
| class Werewolf: | ||||
|     """ | ||||
|     Base to host werewolf on a server | ||||
|     Base to host werewolf on a guild | ||||
|     """ | ||||
| 
 | ||||
|     def __init__(self, bot): | ||||
| @ -25,7 +25,7 @@ class Werewolf: | ||||
|         self.config.register_global(**default_global) | ||||
|         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() | ||||
|     async def ww(self, ctx: commands.Context): | ||||
| @ -44,7 +44,7 @@ class Werewolf: | ||||
|         game = self._get_game(ctx.guild, game_code) | ||||
|          | ||||
|         if not game: | ||||
|             ctx.send(" | ||||
|             ctx.send("Failed to start a new game") | ||||
|          | ||||
|     @ww.command() | ||||
|     async def join(self, ctx): | ||||
| @ -84,14 +84,14 @@ class Werewolf: | ||||
|         if channel is game.village_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) | ||||
| 
 | ||||
|     def _get_game(self, guild, game_code = None): | ||||
|         if guild.id not in self.games: | ||||
|             if not game_code: | ||||
|                 return None | ||||
|             self.games[guild.id] = Game(game_code) | ||||
|             self.games[guild.id] = Game(guild, game_code) | ||||
| 
 | ||||
|         return self.games[guild.id] | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Bobloy
						Bobloy