fight-fixes
Bobloy 7 years ago
parent cb9822f91c
commit 8c7e052647

@ -119,7 +119,7 @@ class Game:
print("Pre-cycle") print("Pre-cycle")
await asyncio.sleep(1) await asyncio.sleep(1)
await self._cycle() # Start the loop asyncio.ensure_future(self._cycle()) # Start the loop
############START Notify structure############ ############START Notify structure############
async def _cycle(self): async def _cycle(self):
@ -276,9 +276,15 @@ class Game:
await asyncio.sleep(15) await asyncio.sleep(15)
await self._at_day_start() await self._at_day_start()
async def _at_visit(self, target, source): # ID 8
if self.game_over:
return
data = {"target": target, "source": source}
await self._notify(8, data)
async def _notify(self, event, data=None): async def _notify(self, event, data=None):
for i in range(8): for i in range(1,7): # action guide 1-6 (0 is no action)
tasks = [] tasks = []
# Role priorities # Role priorities
role_order = [role for role in self.roles if role.action_list[event][1]==i] role_order = [role for role in self.roles if role.action_list[event][1]==i]
@ -288,8 +294,8 @@ class Game:
vote_order = [vg for vg in self.vote_groups.values() if vg.action_list[event][1]==i] vote_order = [vg for vg in self.vote_groups.values() if vg.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), loop=self.loop)) tasks.append(asyncio.ensure_future(vote_group.on_event(event, data), loop=self.loop))
if tasks:
await asyncio.gather(*tasks) await asyncio.gather(*tasks)
# Run same-priority task simultaneously # Run same-priority task simultaneously
############END Notify structure############ ############END Notify structure############
@ -353,9 +359,37 @@ class Game:
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 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):
"""
Arbitrary decision making
Example: seer picking target to see
"""
player = await self.get_player_by_member(ctx.author)
if player is None:
await ctx.send("You're not in this game!")
return
if not player.alive:
await ctx.send("**Corpses** can't vote...")
return
if player.blocked:
await ctx.send("Something is preventing you from doing this...")
return
# Let role do target validation, might be alternate targets
# I.E. Go on alert? y/n
await player.choose(ctx, data)
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)
Also used in vote groups
""" """
player = await self.get_player_by_member(author) player = await self.get_player_by_member(author)
@ -393,8 +427,8 @@ class Game:
elif self.p_channels[channel.name]["votegroup"] is not None: elif self.p_channels[channel.name]["votegroup"] is not None:
await self.vote_groups[channel.name].vote(target, author, id) await self.vote_groups[channel.name].vote(target, author, id)
else: # Private channel voting, send to role else: # Private channel voting, send to role
await self.player.role.vote(target, id) # await self.player.role.vote(target, id)
# I'll think of something later
@ -420,13 +454,20 @@ class Game:
async def eval_results(self, target, source=None, method = None): async def eval_results(self, target, source=None, method = None):
return "{} was found dead".format(target.member.display_name) return "{} was found dead".format(target.member.display_name)
async def kill(self, target, source=None, method: str=None): async def kill(self, target_id, source=None, method: str=None):
""" """
Attempt to kill a target Attempt to kill a target
Source allows admin override Source allows admin override
Be sure to remove permissions appropriately Be sure to remove permissions appropriately
Important to finish execution before triggering notify Important to finish execution before triggering notify
""" """
target = await self.get_night_target(target_id, source)
if source is not None:
if source.blocked:
# Do nothing if blocked, blocker handles text
return
else:
if not target.protected: if not target.protected:
target.alive = False target.alive = False
await self._at_kill(target) await self._at_kill(target)
@ -436,16 +477,23 @@ class Game:
else: else:
target.protected = False target.protected = False
async def lynch(self, target): async def lynch(self, target_id):
""" """
Attempt to lynch a target Attempt to lynch a target
Important to finish execution before triggering notify Important to finish execution before triggering notify
""" """
target = await self.get_day_target(target_id)
target.alive = False target.alive = False
await self._at_hang(target) await self._at_hang(target)
if not target.alive: # Still dead after notifying if not target.alive: # Still dead after notifying
await self.dead_perms(target.member) await self.dead_perms(target.member)
async def get_night_target(self, target_id, source=None):
return self.players[target_id] # For now
async def get_day_target(self, target_id, source=None):
return self.player[target_id] # For now
async def get_roles(self, game_code=None): async def get_roles(self, game_code=None):
if game_code is not None: if game_code is not None:
self.game_code=game_code self.game_code=game_code

@ -26,7 +26,7 @@ class Role:
_at_night_start _at_night_start
0. No Action 0. No Action
1. Detain actions (Jailer/Kidnapper) 1. Detain actions (Jailer/Kidnapper)
2. Group discussions and Pick targets 2. Group discussions and choose targets
_at_night_end _at_night_end
0. No Action 0. No Action
@ -34,7 +34,7 @@ class Role:
2. Target switching and role blocks (bus driver, witch, escort) 2. Target switching and role blocks (bus driver, witch, escort)
3. Protection / Preempt actions (bodyguard/framer) 3. Protection / Preempt actions (bodyguard/framer)
4. Non-disruptive actions (seer/silencer) 4. Non-disruptive actions (seer/silencer)
5. Disruptive actions (werewolf kill) 5. Disruptive actions (Killing)
6. Role altering actions (Cult / Mason) 6. Role altering actions (Cult / Mason)
""" """
@ -63,7 +63,8 @@ class Role:
(self._at_hang, 0), (self._at_hang, 0),
(self._at_day_end, 0), (self._at_day_end, 0),
(self._at_night_start, 0), (self._at_night_start, 0),
(self._at_night_end, 0) (self._at_night_end, 0),
(self._at_visit, 0)
] ]
async def on_event(self, event, data): async def on_event(self, event, data):
@ -124,6 +125,16 @@ class Role:
async def _at_night_end(self, data=None): async def _at_night_end(self, data=None):
pass pass
async def vote(self, target, id): async def _at_visit(self, data=None):
pass
async def visit(self, source):
"""
Called whenever a night action targets you
Source is the player who visited you
"""
pass
async def choose(self, ctx, data):
"""Handle night actions""" """Handle night actions"""
pass pass

@ -0,0 +1,107 @@
import asyncio
from werewolf.role import Role
class Seer(Role):
rand_choice = False # Determines if it can be picked as a random role (False for unusually disruptive roles)
category = [1,2] # List of enrolled categories (listed above)
allignment = 1 # 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 **Seer**\n"
"You win by lynching all evil in the town\n"
"Lynch players during the day with `[p]ww vote <ID>`\n"
"Check for werewolves at night with `[p]ww choose <ID>`"
)
def __init__(self, game):
super().__init__()
# self.game = game
# self.player = None
# self.blocked = False
# self.properties = {} # Extra data for other roles (i.e. arsonist)
self.see_target = None
self.action_list = [
(self._at_game_start, 0), # (Action, Priority)
(self._at_day_start, 0),
(self._at_voted, 0),
(self._at_kill, 0),
(self._at_hang, 0),
(self._at_day_end, 0),
(self._at_night_start, 2),
(self._at_night_end, 4)
]
# async def on_event(self, event, data):
# """
# See Game class for event guide
# """
# await self.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)
# """
# 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 "Villager"
async def _see_role(self, source=None):
"""
Interaction for investigative roles.
More common to be able to deceive these roles
"""
return "Villager"
# async def _at_game_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_kill(self, target=None):
# pass
# async def _at_hang(self, target=None):
# pass
# async def _at_day_end(self):
# pass
async def _at_night_start(self):
await self.game.generate_targets(self.player.member)
await self.player.member.send("{}\n**Pick a target to see tonight**\n")
async def _at_night_end(self):
async def choose(self, ctx, data):
"""Handle night actions"""
id = int(data)
try:
target = game.players[id]
except IndexError:
target = None
if target is None:
await ctx.send("Not a valid ID")
return
self.see_target = id
await ctx.send("**You will attempt to see the role of {} tonight...**".format(target.member.display_name))

@ -32,7 +32,8 @@ class VanillaWerewolf(Role):
(self._at_hang, 0), (self._at_hang, 0),
(self._at_day_end, 0), (self._at_day_end, 0),
(self._at_night_start, 2), # Get vote priority (self._at_night_start, 2), # Get vote priority
(self._at_night_end, 0) (self._at_night_end, 0),
(self._at_visit, 0)
] ]
self.killer = None # Added killer self.killer = None # Added killer
@ -93,7 +94,17 @@ class VanillaWerewolf(Role):
# async def _at_night_end(self, data=None): # async def _at_night_end(self, data=None):
# super()._at_night_end(data) # super()._at_night_end(data)
async def vote(self, target, id): # async def _at_visit(self, data=None):
# pass
# async def visit(self, source):
# """
# Called whenever a night action targets you
# Source is the player who visited you
# """
# pass
async def choose(self, ctx, data):
"""Handle night actions""" """Handle night actions"""
await self.player.member.send("Use this command in your wolf channel at night") await self.player.member.send("Use `[p]ww vote` in your werewolf channel")

@ -5,14 +5,14 @@ from werewolf.role import Role
class Villager(Role): class Villager(Role):
rand_choice = False # Determines if it can be picked as a random role (False for unusually disruptive roles) rand_choice = False # Determines if it can be picked as a random role (False for unusually disruptive roles)
category = [0] # List of enrolled categories (listed above) category = [1] # List of enrolled categories (listed above)
allignment = 0 # 1: Town, 2: Werewolf, 3: Neutral allignment = 1 # 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=( game_start_message=(
"Your role is **Villager**\n" "Your role is **Villager**\n"
"You win by lynching all evil in the town\n" "You win by lynching all evil in the town\n"
"Lynch players during the day with `[p]ww vote <ID>`\n" "Lynch players during the day with `[p]ww vote <ID>`"
) )
def __init__(self, game): def __init__(self, game):
@ -30,7 +30,8 @@ class Villager(Role):
# (self._at_hang, 0), # (self._at_hang, 0),
# (self._at_day_end, 0), # (self._at_day_end, 0),
# (self._at_night_start, 0), # (self._at_night_start, 0),
# (self._at_night_end, 0) # (self._at_night_end, 0),
# (self._at_visit, 0)
# ] # ]
# async def on_event(self, event, data): # async def on_event(self, event, data):
@ -87,3 +88,17 @@ class Villager(Role):
# async def _at_night_end(self): # async def _at_night_end(self):
# pass # pass
# async def _at_visit(self, data=None):
# pass
# async def visit(self, source):
# """
# Called whenever a night action targets you
# Source is the player who visited you
# """
# pass
# async def choose(self, ctx, data):
# """Handle night actions"""
# pass

@ -29,7 +29,8 @@ class VoteGroup:
(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, 0) (self._at_night_end, 0),
(self._at_visit, 0)
] ]
async def on_event(self, event, data): async def on_event(self, event, data):

@ -83,13 +83,16 @@ class WolfVote(VoteGroup):
vote_list = list(self.vote_results.values()) vote_list = list(self.vote_results.values())
if vote_list: if vote_list:
target = max(set(vote_list), key=vote_list.count) target_id = max(set(vote_list), key=vote_list.count)
if target and self.killer: if target and self.killer:
await self.game.kill(target, self.killer, random.choice(self.kill_messages)) await self.game.kill(target_id, self.killer, random.choice(self.kill_messages))
else: else:
await self.channel.send("**No kill will be attempted tonight...**") await self.channel.send("**No kill will be attempted tonight...**")
# async def _at_visit(self, data=None):
# pass
async def vote(self, target, author, id): async def vote(self, target, author, id):
""" """
Receive vote from game Receive vote from game

@ -26,7 +26,7 @@ class Werewolf:
self.config.register_guild(**default_guild) self.config.register_guild(**default_guild)
self.games = {} # Active games stored here, id is per guild 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):
""" """
@ -34,7 +34,8 @@ class Werewolf:
""" """
if ctx.invoked_subcommand is None: if ctx.invoked_subcommand is None:
await ctx.send_help() await ctx.send_help()
@guild_only()
@ww.command() @ww.command()
async def new(self, ctx, game_code): async def new(self, ctx, game_code):
""" """
@ -49,7 +50,7 @@ class Werewolf:
await ctx.send("New game has started") await ctx.send("New game has started")
@guild_only()
@ww.command() @ww.command()
async def join(self, ctx): async def join(self, ctx):
""" """
@ -63,7 +64,8 @@ class Werewolf:
return return
await game.join(ctx.author, ctx.channel) await game.join(ctx.author, ctx.channel)
@guild_only()
@ww.command() @ww.command()
async def quit(self, ctx): async def quit(self, ctx):
""" """
@ -74,6 +76,7 @@ class Werewolf:
await game.quit(ctx.author, ctx.channel) await game.quit(ctx.author, ctx.channel)
@guild_only()
@ww.command() @ww.command()
async def start(self, ctx): async def start(self, ctx):
""" """
@ -85,6 +88,7 @@ class Werewolf:
await game.setup(ctx) await game.setup(ctx)
@guild_only()
@ww.command() @ww.command()
async def stop(self, ctx): async def stop(self, ctx):
""" """
@ -96,7 +100,7 @@ class Werewolf:
game.game_over = True game.game_over = True
@guild_only()
@ww.command() @ww.command()
async def vote(self, ctx, id: int): async def vote(self, ctx, id: int):
""" """
@ -110,11 +114,24 @@ class Werewolf:
if id is None: if id is None:
await ctx.send("`id` must be an integer") await ctx.send("`id` must be an integer")
return return
# if ctx.guild is None:
# # DM nonsense, find their game
# # If multiple games, panic
# for game in self.games.values():
# if await game.get_player_by_member(ctx.author):
# break #game = game
# else:
# await ctx.send("You're not part of any werewolf game")
# return
# else:
game = self._get_game(ctx.guild) game = self._get_game(ctx.guild)
if not game:
await ctx.send("No game running, cannot vote")
if game is None:
await ctx.send("No game running, cannot vote")
return
# Game handles response now # Game handles response now
channel = ctx.channel channel = ctx.channel
if channel == game.village_channel: if channel == game.village_channel:
@ -123,8 +140,34 @@ class Werewolf:
await game.vote(ctx.author, id, channel) await game.vote(ctx.author, id, channel)
else: else:
await ctx.send("Nothing to vote for in this channel") await ctx.send("Nothing to vote for in this channel")
@ww.command()
async def choose(self, ctx, data):
"""
Arbitrary decision making
Handled by game+role
Can be received by DM
"""
if ctx.guild is not None:
await ctx.send("This action is only available in DM's")
return
# DM nonsense, find their game
# If multiple games, panic
for game in self.games.values():
if await game.get_player_by_member(ctx.author):
break #game = game
else:
await ctx.send("You're not part of any werewolf game")
return
await game.choose(ctx, data)
def _get_game(self, guild, game_code=None): def _get_game(self, guild, game_code=None):
if guild is None:
# Private message, can't get guild
return 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

Loading…
Cancel
Save