async def on_pm_command(self, ctx, game, player, args): command = args[0] can_do, reason = self.can_do_action(game) if not can_do: return await ctx.send(f'You cannot use your action today. {reason}') if command == 'noaction': for action in game.night_actions: if action['player'].user.id == player.user.id: game.night_actions.remove(action) game.night_actions.add_action({ 'action': None, 'player': player, 'priority': 0 }) return await ctx.send('You decided to stay home tonight.') game.night_actions.add_action({ 'action': self.action, 'player': player, 'priority': self.action_priority, 'target': player, 'can_block': self.can_block, 'can_transport': self.can_transport, 'can_visit': False }) await ctx.send('You have decided to {} tonight.'.format(self.action)) if len(game.players.filter(action_only=True)) == len(game.night_actions): try: if not game.phase == Phase.STANDBY: await game.increment_phase() except Exception as exc: raise PhaseChangeError(None, *exc.args)
async def startgame(self, ctx: CustomContext, r_setup: typing.Optional[str] = None): """ Starts the game. To view a list of available setups, use the `setupinfo` command. """ game = ctx.game if game.has_started: await ctx.send("Game has already started!") return if game.setup and len(game.players) != game.setup.total_players: return await ctx.send('Custom setup used needs {} players.'.format( game.setup.total_players)) if game.setup is None: try: game.phase = Phase.STANDBY found_setup = await game.find_setup(r_setup) except ValueError as err: # pylint: disable=broad-except return await ctx.send(err) finally: game.phase = Phase.PREGAME game.setup = found_setup # set to standby so people can't join while the bot is sending rolepms game.phase = Phase.STANDBY await ctx.send(f'Chose the setup **{game.setup.name}**. ' 'Randing roles...') no_dms = await game.setup.assign_roles(game) await ctx.send('Sent all role PMs!') if len(no_dms) > 0: no_dms = [*map(lambda usr: usr.name, no_dms)] await ctx.send( f"I couldn't DM {', '.join(no_dms)}." f" Use the {self.bot.global_prefix}rolepm command to receive your PM." ) # flags flags = { flag_name: game.setup.flags[flag_name] for flag_name in Setup.all_flags } if "night_start" in flags and flags['night_start']: game.cycle = 1 game.phase = Phase.DAY try: await game.increment_phase() except Exception as exc: raise PhaseChangeError(None, *exc.args)
async def update(self): if not self.has_started or self.phase == Phase.STANDBY: return curr_t = datetime.now() phase_end = self.phase_end_at if phase_end is not None and curr_t > phase_end: if self.phase == Phase.DAY: # no lynch achieved await self.channel.send('Nobody was lynched') try: await self.increment_phase() except Exception as exc: raise PhaseChangeError(None, *exc.args)
async def on_pm_command(self, ctx, game, player, args): command = args.pop(0) can_do, reason = self.can_do_action(game) if not can_do: return await ctx.send(f'You cannot use your action today. {reason}') if command == 'noaction': for action in game.night_actions: if action['player'].user.id == player.user.id: game.night_actions.remove(action) game.night_actions.add_action({ 'action': None, 'player': player, 'priority': 0 }) if len(game.players.filter(action_only=True)) == len(game.night_actions): if not game.phase == Phase.STANDBY: await game.increment_phase() return await ctx.send('You decided to stay home tonight.') targets = [] if len(args) < 2: return await ctx.send('You have to specifiy 2 targets.') for arg in args[0:2]: if not arg.isdigit(): return await ctx.send('Pick a valid number from the playerlist.') num = int(arg) if num > len(game.players): return await ctx.send(f'There are only {len(game.players)} playing.') target = game.players[num - 1] targets.append(target) for target in targets: can_target, reason = self.can_target(player, target) if not can_target: return await ctx.send(reason) target1, target2 = targets if target1 == target2: return await ctx.send('Pick 2 distinct targets.') for action in game.night_actions: if action['player'].user.id == player.user.id: game.night_actions.remove(action) game.night_actions.add_action({ 'action': self.action, 'player': player, 'target': targets, 'priority': self.action_priority, 'can_block': self.can_block, 'can_transport': self.can_transport, 'can_visit': self.can_visit }) await ctx.send(f'You are {self.action_gerund} {" and ".join(map(lambda p: p.user.name, targets))} tonight.') if len(game.players.filter(action_only=True)) == len(game.night_actions): try: if not game.phase == Phase.STANDBY: await game.increment_phase() except Exception as exc: raise PhaseChangeError(None, *exc.args)
async def on_pm_command(self, ctx, game, player, args): command = args.pop(0) can_do, reason = self.can_do_action(game) if not can_do: return await ctx.send(f'You cannot use your action today. {reason}' ) args = ' '.join(args) if command == 'noaction': for action in game.night_actions: if action['player'].user.id == player.user.id: game.night_actions.remove(action) game.night_actions.add_action({ 'action': None, 'player': player, 'priority': 0 }) if len(game.players.filter(action_only=True)) == len( game.night_actions): if not game.phase == Phase.STANDBY: await game.increment_phase() return await ctx.send('You decided to stay home tonight.') if not args.isdigit(): return await ctx.send('Pick a valid number from the playerlist.') num = int(args) if num > len(game.players): return await ctx.send( f'There are only {len(game.players)} playing.') target_pl = game.players[num - 1] target = target_pl.user if target_pl is None: return await ctx.send('Invalid input') can_target, reason = self.can_target(player, target_pl) if not can_target: return await ctx.send(reason) for action in game.night_actions: if action['player'].user.id == player.user.id: game.night_actions.remove(action) # special godfather stuff if self.name == 'Godfather' and len( game.players.filter(role='Goon', is_alive=True)) > 0: goon = game.players.filter(role='Goon')[0] for action in game.night_actions: if action['player'].role.name == 'Goon': game.night_actions.remove(action) game.night_actions.add_action({ 'action': self.action, 'player': goon, 'target': target_pl, 'priority': self.action_priority, 'can_block': self.can_block, 'can_transport': self.can_transport, 'can_visit': self.can_visit }) game.night_actions.add_action({ 'action': self.action, 'player': player, 'target': target_pl, 'priority': self.action_priority, 'can_block': self.can_block, 'can_transport': self.can_transport, 'can_visit': self.can_visit }) await ctx.send(f'You are {self.action_gerund} {target} tonight.') if len(game.players.filter(action_only=True)) == len( game.night_actions): try: if not game.phase == Phase.STANDBY: await game.increment_phase() except Exception as exc: raise PhaseChangeError(None, *exc.args)
async def on_pm_command(self, ctx, game, player, args): if self.ignited: # already ignited last time, let's remove everything now self.doused.clear() self.ignited = False command = args.pop(0) can_do, reason = self.can_do_action(command) if not can_do: return await ctx.send(f'You cannot use your action today. {reason}') args = ' '.join(args) if command == 'noaction': for action in game.night_actions: if action['player'].user.id == player.user.id: game.night_actions.remove(action) for action in game.night_actions: if action['player'].user.id == player.user.id: game.night_actions.remove(action) game.night_actions.add_action({ 'action': None, 'player': player, 'priority': 0 }) if len(game.players.filter(action_only=True)) == len(game.night_actions): await game.increment_phase() return await ctx.send('You decided to stay home tonight.') if command == 'ignite': for target in self.doused: if not target.is_alive: continue game.night_actions.add_action({ 'action': 'ignite', 'player': player, 'target': target, 'priority': Priority.ARSONIST, 'can_block': False, 'can_transport': False }) self.ignited = True await ctx.send('You are igniting your doused targets today.') total_actions = len(game.players.filter(action_only=True)) expected_total = total_actions + len(self.doused) - 1 if expected_total == len(game.night_actions): try: await game.increment_phase() except Exception as exc: raise PhaseChangeError(None, *exc.args) return if not args.isdigit(): return await ctx.send('Pick a valid number from the playerlist.') num = int(args) if num > len(game.players): return await ctx.send(f'There are only {len(game.players)} playing.') target_pl = game.players[num - 1] target = target_pl.user if target_pl is None: return await ctx.send('Invalid input') can_target, reason = self.can_target(player, target_pl) if not can_target: return await ctx.send(reason) for action in game.night_actions: if action['player'].user.id == player.user.id: game.night_actions.remove(action) game.night_actions.add_action({ 'action': 'douse', 'player': player, 'target': target_pl, 'priority': Priority.ARSONIST, 'can_block': True, 'can_transport': True }) await ctx.send(f'You are dousing {target} tonight.') if len(game.players.filter(action_only=True)) == len(game.night_actions): try: await game.increment_phase() except Exception as exc: raise PhaseChangeError(None, *exc.args)