async def test_del_char() -> None: session = db.Session() guild_id = 555 player_id = 111 session.add( Character( guild=guild_id, player=player_id, name="name", race="race", attr_reason=5, disc_science=12, )) session.commit() cog = STA() context = MagicMock() context.author.id = player_id context.guild.id = guild_id context.guild.__bool__.return_value = True context.author.__bool__.return_value = True future: Future[bool] = asyncio.Future() future.set_result(True) context.send.return_value = future context.mock_add_spec(["guild", "author", "send"], spec_set=True) assert db.Session().query(Character).count() == 1 await STA.del_char(cog, context) assert db.Session().query(Character).count() == 0 assert context.mock_calls == [ call.guild.__bool__(), call.send("Character deleted."), ]
async def trivia(self, ctx: Context) -> None: score = PlayerScore.get(ctx) response = "Answer the Question in 30 seconds!" await ctx.send(response) chosen_row = random.choice(self.questions) possible_answers = [chosen_row.answer] + random.sample( chosen_row.options, k=3) random.shuffle(possible_answers) await ctx.send(chosen_row.question) choices = random.sample(possible_answers, k=4) msg = "\n".join(f"{i+1}: {choice}" for i, choice in enumerate(choices)) await ctx.send(msg) def check(match: Message) -> bool: return bool(match.content.isdigit() and match.author == ctx.author) try: guess = await self.bot.wait_for("message", check=check, timeout=30.0) except asyncio.TimeoutError: score.score = 0 await ctx.send( f"Sorry, you took too long! The answer was {chosen_row.answer}.\n" f"Your high score is: {score.high_score}") db.Session().commit() return if choices[int(guess.content) - 1] == chosen_row.answer: score.score += 1 new_high_score = False if score.score > score.high_score: score.high_score = score.score new_high_score = True await ctx.send( f"You are right! Your current score is: {score.score}\n" f"Your high score is: {score.high_score}") if new_high_score: await ctx.send("New high score \N{party popper}") else: score.score = 0 await ctx.send(f'Oh no! The answer was: "{chosen_row.answer}".\n' f"Your high score is: {score.high_score}") db.Session().commit()
async def set_stat(self, ctx: Context, stat: str, subcmd: str, value: int) -> None: character = Character.get(ctx) stat_lower = stat.lower() if subcmd == "set": if stat_lower in ["det", "determination"]: character.determination = value elif stat_lower in ["stress", "str"]: character.stress = value else: if subcmd == "add": change = value elif subcmd == "sub": change = -value else: await ctx.send(f"Bad operation: {subcmd}") return if stat_lower in ["det", "determination"]: character.determination += change elif stat_lower in ["stress", "str"]: character.stress += change db.Session().commit() await self.player_embed(ctx)
async def sub_game_stat(self, ctx: Context, stat: str, diff: int) -> None: """ Set a stat on the game state :param ctx: Game context :param stat: Stat name :param diff: Stat change """ state = GameState.get_or_create(ctx) stat_l = stat.lower() if stat_l == "momentum": changed = state.sub_momentum(diff) elif stat_l == "threat": changed = state.sub_threat(diff) else: await ctx.send(f"Unknown stat: {stat}") return if not changed: await ctx.send(f"Not enough {stat} (Needed {diff})") db.Session().commit() await self.show_game(ctx, state, color=Colour.magenta())
async def set_disc(self, ctx: Context, disc: str, value: int) -> None: character = Character.get(ctx) try: character.set_discipline(disc, value) except AttributeError: await ctx.send(f"Unknown discipline: {disc}") return db.Session().commit() await self.player_embed(ctx)
async def set_attr(self, ctx: Context, stat: str, value: int) -> None: character = Character.get(ctx) try: character.set_attribute(stat, value) except AttributeError: await ctx.send(f"Unknown attribute: {stat}") return db.Session().commit() await self.player_embed(ctx)
async def del_char(self, ctx: Context, other_user: User = None) -> None: character = Character.get(ctx, other_user) if not character: await ctx.send("No character found") return session = db.Session() session.delete(character) session.commit() await ctx.send("Character deleted.")
def get_or_create(cls, context: Context) -> "GameState": state = cls.get(context) guild = context.guild if not guild: raise ValueError("Missing guild?!") if state is None: session = db.Session() state = GameState(guild=guild.id, momentum=0, threat=0) session.add(state) session.commit() return state
def get(cls, context: Context) -> Optional["GameState"]: """ Get a game state :return: Current state """ session = db.Session() guild = context.guild if not guild: raise ValueError("Missing guild?!") guild_id = guild.id state = session.query(cls).get(guild_id) if state is None: return None return cast(GameState, state)
async def test_challenge_attribute_order(attr: str, disc: str) -> None: random.seed(1) cog = MagicMock() session = db.Session() guild_id = 555 player_id = 111 session.add( Character( guild=guild_id, player=player_id, name="name", race="race", attr_reason=5, disc_science=12, )) session.commit() context = MagicMock() context.author.id = player_id context.guild.id = guild_id context.guild.__bool__.return_value = True context.author.__bool__.return_value = True future: Future[bool] = asyncio.Future() future.set_result(True) context.send.return_value = future context.mock_add_spec(["guild", "author", "send"], spec_set=True) assert (await STA.challenge(cog, context, attr, disc, 1, 2)) is None msg = context.send.mock_calls[0] embed: Embed = msg.kwargs["embed"] file: File = msg.kwargs["file"] # This is done by send normally file.close() assert embed.author.name is Embed.Empty assert embed.title == "Challenge" assert embed.description == "Science (12) + Reason (5)" fields = cast(List[EmbedProxy], embed.fields) AssertEmbed(fields[0]).has_name("Difficulty: ").has_value("1") AssertEmbed(fields[1]).has_name("Successes: ").has_value("1") AssertEmbed(fields[2]).has_name("Complications: ").has_value("0") AssertEmbed(fields[3]).has_name("Rolls: ").has_value("[5, 19]") assert embed.image.url == "attachment://Green-alert.gif" assert file.filename == "Green-alert.gif"
async def gm_challenge( self, ctx: Context, attribute: str, attribute_value: int, discipline: str, discipline_value: int, difficulty: int, num_dice: int, focus: bool = False, do_threat: bool = False, ) -> None: challenge_value = attribute_value + discipline_value roll = ChallengeRoll.do_roll( num_dice, challenge_value, focus, discipline_value, attribute_value, discipline, attribute, difficulty, ) embed = roll.embed game_state = GameState.get_or_create(ctx) old_threat = game_state.threat if do_threat and roll.successes > difficulty: threat = roll.successes - difficulty game_state.add_threat(threat) threat_diff = game_state.threat - old_threat if threat_diff: embed.add_field(name="Threat: ", value=f"+{threat_diff}") db.Session().commit() file = roll.get_img() embed.set_image(url=f"attachment://{file.filename}") await ctx.send(embed=embed, file=file)
def get(cls, ctx: Context) -> "PlayerScore": session = db.Session() guild = ctx.guild author = ctx.author if not guild: raise ValueError("Missing guild?!") if not author: raise ValueError("Missing author?!") guild_id = guild.id author_id = author.id state = cast(PlayerScore, session.query(cls).get((guild_id, author_id))) if state is None: state = PlayerScore(guild=guild_id, player=author_id) session.add(state) session.commit() return state
def get(cls, ctx: Context, other_user: Optional[Union[User, Member]] = None) -> "Character": """ Get a player's character :param ctx: Context :param other_user: Player's name :return: Player's character or None """ guild = ctx.guild if not guild: raise ValueError("Unset guild?!") member: Union[User, Member] if other_user: member = other_user else: member = ctx.author return cast(Character, db.Session().query(cls).get((guild.id, member.id)))
async def create_player( self, ctx: Context, name: str, race: str, control: int, daring: int, fitness: int, insight: int, presence: int, reason: int, command: int, conn: int, security: int, engineering: int, science: int, medicine: int, other_user: User = None, ) -> None: guild = ctx.guild if not guild: raise ValueError("Missing guild") member: Union[Member, User] if other_user: member = other_user else: member = ctx.author if not member: raise ValueError("Missing author") character = Character.get(ctx, member) if character: await ctx.send( f"{member.display_name} already has a Character ({character.name})." ) return character = Character( name=name, race=race, attr_control=control, attr_fitness=fitness, attr_daring=daring, attr_insight=insight, attr_presence=presence, attr_reason=reason, disc_conn=conn, disc_command=command, disc_medicine=medicine, disc_science=science, disc_security=security, disc_engineering=engineering, player=member.id, guild=guild.id, ) session = db.Session() session.add(character) session.commit() await ctx.send("Character created!") await self.player_embed(ctx, member)
async def sub_game(self, ctx: Context, stat: str, value: int) -> None: await self.sub_game_stat(ctx, stat, abs(value)) db.Session().commit()
async def add_game(self, ctx: Context, stat: str, value: int) -> None: await self.add_game_stat(ctx, stat, value) db.Session().commit()