diff --git a/werewolf/builder.py b/werewolf/builder.py index 48e7e71..da0bf1e 100644 --- a/werewolf/builder.py +++ b/werewolf/builder.py @@ -318,7 +318,7 @@ class GameBuilder: pass if page >= len(ROLE_LIST): - self.rand_roles.append(CATEGORY_COUNT[page-len(ROLE_LIST)]) + self.rand_roles.append(CATEGORY_COUNT[page - len(ROLE_LIST)]) else: self.code.append(page) diff --git a/werewolf/game.py b/werewolf/game.py index 9c0a8b4..181c198 100644 --- a/werewolf/game.py +++ b/werewolf/game.py @@ -1,17 +1,23 @@ import asyncio import random +from typing import List, Any, Dict, Set, Union import discord from redbot.core import commands from werewolf.builder import parse_code from werewolf.player import Player +from werewolf.role import Role +from werewolf.votegroup import VoteGroup class Game: """ Base class to run a single game of Werewolf """ + vote_groups: Dict[str, VoteGroup] + roles: List[Role] + players: List[Player] default_secret_channel = { "channel": None, diff --git a/werewolf/night_powers.py b/werewolf/night_powers.py index ca35e8b..215e8eb 100644 --- a/werewolf/night_powers.py +++ b/werewolf/night_powers.py @@ -3,3 +3,21 @@ from werewolf.role import Role def night_immune(role: Role): role.player.alive = True + + +async def pick_target(role: Role, ctx, data): + if not role.player.alive: # FixMe: Game handles this? + await role.player.send_dm("You're already dead!") + return None + + target_id = int(data) + try: + target = role.game.players[target_id] + except IndexError: + target = None + + if target is None: + await ctx.send("Not a valid ID") + return None + + return target_id, target diff --git a/werewolf/roles/seer.py b/werewolf/roles/seer.py index 5c58250..63b62a2 100644 --- a/werewolf/roles/seer.py +++ b/werewolf/roles/seer.py @@ -1,3 +1,4 @@ +from werewolf.night_powers import pick_target from werewolf.role import Role @@ -61,7 +62,7 @@ class Seer(Role): return self.see_target = None await self.game.generate_targets(self.player.member) - await self.player.send_dm("**Pick a target to see tonight**\n") + await self.player.send_dm("**Pick a target to see tonight**") async def _at_night_end(self, data=None): if self.see_target is None: @@ -83,19 +84,7 @@ class Seer(Role): async def choose(self, ctx, data): """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) - try: - target = self.game.players[target_id] - except IndexError: - target = None - - if target is None: - await ctx.send("Not a valid ID") - return + await super().choose(ctx, data) - self.see_target = target_id + self.see_target, target = await pick_target(self, ctx, data) await ctx.send("**You will attempt to see the role of {} tonight...**".format(target.member.display_name)) diff --git a/werewolf/roles/shifter.py b/werewolf/roles/shifter.py index 50973ef..d7ba956 100644 --- a/werewolf/roles/shifter.py +++ b/werewolf/roles/shifter.py @@ -1,3 +1,4 @@ +from werewolf.night_powers import pick_target from werewolf.role import Role @@ -59,6 +60,7 @@ class Shifter(Role): def __init__(self, game): super().__init__(game) + self.shift_target = None self.action_list = [ (self._at_game_start, 1), # (Action, Priority) (self._at_day_start, 0), @@ -74,7 +76,7 @@ class Shifter(Role): async def see_alignment(self, source=None): """ Interaction for investigative roles attempting - to see alignment (Village, Werewolf Other) + to see alignment (Village, Werewolf, Other) """ return "Other" @@ -90,14 +92,38 @@ class Shifter(Role): Interaction for investigative roles. More common to be able to deceive this action """ - return "MyRole" + return "Shifter" async def _at_night_start(self, data=None): await super()._at_night_start(data) + self.shift_target = None + await self.game.generate_targets(self.player.member) + await self.player.send_dm("**Pick a target to shift into**") async def _at_night_end(self, data=None): await super()._at_night_end(data) + if self.shift_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.shift_target, self.player) + + if target and target.player.alive: + await target.role.assign_player(self.player) + await self.assign_player(target) + + # Roles have now been swapped + await self.player.send_dm("Your role has been stolen...\n" + "You are now a **Shifter**.") + await self.player.send_dm(self.game_start_message) + + await target.send_dm(target.role.game_start_message) + else: + await self.player.send_dm("**Your shift failed...**") async def choose(self, ctx, data): """Handle night actions""" await super().choose(ctx, data) + + self.shift_target, target = await pick_target(self, ctx, data) + await ctx.send("**You will attempt to see the role of {} tonight...**".format(target.member.display_name)) diff --git a/werewolf/werewolf.py b/werewolf/werewolf.py index 1b738be..17634ec 100644 --- a/werewolf/werewolf.py +++ b/werewolf/werewolf.py @@ -392,4 +392,3 @@ class Werewolf(Cog): return False, None, None, None, None return True, role, category, channel, log_channel -