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

@ -119,7 +119,7 @@ class Game:
print("Pre-cycle")
await asyncio.sleep(1)
await self._cycle() # Start the loop
asyncio.ensure_future(self._cycle()) # Start the loop
############START Notify structure############
async def _cycle(self):
@ -277,8 +277,14 @@ class Game:
await asyncio.sleep(15)
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):
for i in range(8):
for i in range(1,7): # action guide 1-6 (0 is no action)
tasks = []
# Role priorities
role_order = [role for role in self.roles if role.action_list[event][1]==i]
@ -288,7 +294,7 @@ class Game:
vote_order = [vg for vg in self.vote_groups.values() if vg.action_list[event][1]==i]
for vote_group in vote_order:
tasks.append(asyncio.ensure_future(vote_group.on_event(event, data), loop=self.loop))
if tasks:
await asyncio.gather(*tasks)
# Run same-priority task simultaneously
@ -353,9 +359,37 @@ class Game:
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)))
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):
"""
Member attempts to cast a vote (usually to lynch)
Also used in vote groups
"""
player = await self.get_player_by_member(author)
@ -393,8 +427,8 @@ class Game:
elif self.p_channels[channel.name]["votegroup"] is not None:
await self.vote_groups[channel.name].vote(target, author, id)
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):
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
Source allows admin override
Be sure to remove permissions appropriately
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:
target.alive = False
await self._at_kill(target)
@ -436,16 +477,23 @@ class Game:
else:
target.protected = False
async def lynch(self, target):
async def lynch(self, target_id):
"""
Attempt to lynch a target
Important to finish execution before triggering notify
"""
target = await self.get_day_target(target_id)
target.alive = False
await self._at_hang(target)
if not target.alive: # Still dead after notifying
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):
if game_code is not None:
self.game_code=game_code

@ -26,7 +26,7 @@ class Role:
_at_night_start
0. No Action
1. Detain actions (Jailer/Kidnapper)
2. Group discussions and Pick targets
2. Group discussions and choose targets
_at_night_end
0. No Action
@ -34,7 +34,7 @@ class Role:
2. Target switching and role blocks (bus driver, witch, escort)
3. Protection / Preempt actions (bodyguard/framer)
4. Non-disruptive actions (seer/silencer)
5. Disruptive actions (werewolf kill)
5. Disruptive actions (Killing)
6. Role altering actions (Cult / Mason)
"""
@ -63,7 +63,8 @@ class Role:
(self._at_hang, 0),
(self._at_day_end, 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):
@ -124,6 +125,16 @@ class Role:
async def _at_night_end(self, data=None):
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"""
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_day_end, 0),
(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
@ -94,6 +95,16 @@ class VanillaWerewolf(Role):
# async def _at_night_end(self, data=None):
# 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"""
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):
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)
allignment = 0 # 1: Town, 2: Werewolf, 3: Neutral
category = [1] # 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 **Villager**\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):
@ -30,7 +30,8 @@ class Villager(Role):
# (self._at_hang, 0),
# (self._at_day_end, 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):
@ -87,3 +88,17 @@ class Villager(Role):
# async def _at_night_end(self):
# 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_day_end, 0),
(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):

@ -83,13 +83,16 @@ class WolfVote(VoteGroup):
vote_list = list(self.vote_results.values())
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:
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:
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):
"""
Receive vote from game

@ -35,6 +35,7 @@ class Werewolf:
if ctx.invoked_subcommand is None:
await ctx.send_help()
@guild_only()
@ww.command()
async def new(self, ctx, game_code):
"""
@ -49,7 +50,7 @@ class Werewolf:
await ctx.send("New game has started")
@guild_only()
@ww.command()
async def join(self, ctx):
"""
@ -64,6 +65,7 @@ class Werewolf:
await game.join(ctx.author, ctx.channel)
@guild_only()
@ww.command()
async def quit(self, ctx):
"""
@ -74,6 +76,7 @@ class Werewolf:
await game.quit(ctx.author, ctx.channel)
@guild_only()
@ww.command()
async def start(self, ctx):
"""
@ -85,6 +88,7 @@ class Werewolf:
await game.setup(ctx)
@guild_only()
@ww.command()
async def stop(self, ctx):
"""
@ -96,7 +100,7 @@ class Werewolf:
game.game_over = True
@guild_only()
@ww.command()
async def vote(self, ctx, id: int):
"""
@ -111,9 +115,22 @@ class Werewolf:
await ctx.send("`id` must be an integer")
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)
if not game:
if game is None:
await ctx.send("No game running, cannot vote")
return
# Game handles response now
channel = ctx.channel
@ -124,7 +141,33 @@ class Werewolf:
else:
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):
if guild is None:
# Private message, can't get guild
return None
if guild.id not in self.games:
if not game_code:
return None

Loading…
Cancel
Save