Example #1
0
 async def begin(self, ctx, *args):
     """Begins combat in the channel. Users must add tokens then start rounds"""
     self.init_tracker = InitiativeTracker()
     if len(args) == 0:
         await ctx.send("Battle started. Now add tokens with !init add...")
     else:
         await ctx.send("Battle started.")
         await ctx.invoke(self.bot.get_command("init add"),
                          arg=' '.join(args))
Example #2
0
def test_remove_spaces_in_name_init_tracker():
    t = InitiativeTracker()
    assert t.count_tokens() == 0
    t.add_token("Goblin", 4)
    t.add_token("Vince McFighty", 2)
    assert t.count_tokens() == 6
    removed = t.remove_token("Vince McFighty", 2)
    assert removed == 2
    assert t.count_tokens() == 4
Example #3
0
def test_add_token_init_tracker():
    t = InitiativeTracker()
    assert t.count_tokens() == 0
    t.add_token("Goblin", 4)
    assert t.count_tokens() == 4
    assert t.count_token("Goblin") == 4
    assert t.count_token("Goldfish") == 0
Example #4
0
def test_remove_all_tokens_init_tracker():
    t = InitiativeTracker()
    assert t.count_tokens() == 0
    t.add_token("Goblin", 4)
    assert t.count_token("Goblin") == 4
    removed = t.remove_token("Goblin", 6)
    assert removed == 4
    assert t.count_token("Goblin") == 0
Example #5
0
def test_remove_missing_tokens_init_tracker():
    t = InitiativeTracker()
    assert t.count_tokens() == 0
    t.add_token("Goblin", 4)
    removed = t.remove_token("Ogre", 2)
    assert removed == 0
    assert t.count_token("Goblin") == 4
Example #6
0
def test_start_round_init_tracker():
    t = InitiativeTracker()
    t.add_token("Goblin", 4)
    t.add_token("Vince McFighty", 2)
    t.start_round()
    assert t.in_round
    assert t.count_round_tokens() == 7
    assert t.round_num == 1
    assert t.drawn_log == [[]]

    drawn_tokens = []

    while (True):
        popped = t.draw_token()
        print(popped, t.round_last_drawn)
        drawn_tokens.append(popped)
        if popped == END_OF_ROUND_TOKEN:
            break

    assert drawn_tokens.count("Goblin") + t.round_bag.count("Goblin") == 4
    assert drawn_tokens.count("Vince McFighty") + t.round_bag.count(
        "Vince McFighty") == 2
    assert drawn_tokens[-1] == END_OF_ROUND_TOKEN
    assert t.round_bag.count(END_OF_ROUND_TOKEN) == 0
Example #7
0
class InitiativeCog(commands.Cog):
    """
    Initiative tracking commands. Use !help init for more info.

    """
    def __init__(self, bot):
        self.bot = bot
        self.init_tracker = None

    @commands.group(aliases=['i'], invoke_without_command=True)
    async def init(self, ctx):
        """Commands to help track initiative."""
        await ctx.send(f"Incorrect usage. Use {ctx.prefix}help init for help.")

    # Borrowed this from avrae
    async def cog_check(self, ctx):
        if ctx.guild is None:
            raise NoPrivateMessage()
        return True

    @init.command(aliases=["start"])
    async def begin(self, ctx, *args):
        """Begins combat in the channel. Users must add tokens then start rounds"""
        self.init_tracker = InitiativeTracker()
        if len(args) == 0:
            await ctx.send("Battle started. Now add tokens with !init add...")
        else:
            await ctx.send("Battle started.")
            await ctx.invoke(self.bot.get_command("init add"),
                             arg=' '.join(args))

    @init.command()
    async def end(self, ctx):
        if self.init_tracker is None:
            await ctx.send(
                "It looks like there is no current initiative tracker")
        else:
            await ctx.send("Battle is now ended")
            self.init_tracker = None

    @init.command(
        name="add",
        help="Adds [number] [tokens] to the bag. May list more than one player"
    )
    async def add(self, ctx, *, arg):
        if self.init_tracker is None:
            await ctx.send(NO_INIT_TRACKER_MESSAGE)
            return

        tokens = re.findall(r'([0-9]+) ([^0-9]+)', arg)
        if tokens == []:
            raise ArgumentParsingError(
                'Argument should be of the form "NUM Token NUM Token"')

        output_string = ""
        for (count, token) in tokens:
            try:
                count = int(count)
                token = token.rstrip()
                self.init_tracker.add_token(token, count)
                output_string += f"Added {count} {token} tokens.\n"
            except Exception as e:
                print(e)
                output_string = f"Unable to parse: {arg}"
        await ctx.send(output_string)

    @init.command(name="remove",
                  aliases=["delete", "del"],
                  help="Removes [number] [tokens] from the bag")
    async def remove(self, ctx, *, arg):
        '''Removes N tokens from the bag'''
        r = re.match(r'([0-9]+) (.+)$', arg)
        if not r:
            raise ArgumentParsingError(
                "Must be of the format `number token_name`")

        token = r.group(2)
        count = int(r.group(1))

        if self.init_tracker is None:
            await ctx.send(NO_INIT_TRACKER_MESSAGE)
            return

        in_bag = self.init_tracker.count_token(token)
        removed = self.init_tracker.remove_token(token, count)

        if removed < count:
            await ctx.send(
                f"You asked to remove {count} {token} tokens, but only {removed} were in the bag (0 left)"
            )
        elif removed < in_bag:
            await ctx.send(
                f"Removed {removed} {token} tokens from the bag ({in_bag - removed} left)"
            )
        else:
            await ctx.send(
                f"Removed all {removed} {token} tokens from the bag (0 left)")

    @init.command(name="show", aliases=["bag"])
    async def show(self, ctx):
        """Prints out a representation of the tokens in the bag"""
        if self.init_tracker is None:
            await ctx.send(NO_INIT_TRACKER_MESSAGE)
            return

        bag = self.init_tracker.current_tokens()
        output_string = "Initiative Bag:\n"
        for key in sorted(bag):
            output_string += f"- **{key}** ({bag[key]})\n"
        await ctx.send(output_string)

    @init.command(name="round", help="Begin a round of combat")
    async def round(self, ctx):
        """Starts a new round and returns the first token"""
        if self.init_tracker is None:
            await ctx.send(NO_INIT_TRACKER_MESSAGE)
            return

        self.init_tracker.start_round()
        await ctx.send(
            f"Starting round {self.init_tracker.round_num} of combat! Shuffling the bag..."
        )
        await ctx.invoke(self.bot.get_command("init draw"))

    @commands.command(name="round", hidden=True)
    async def roundAlias(self, ctx):
        await ctx.invoke(self.bot.get_command("init round"))

    @init.command()
    async def draw(self, ctx):
        """Returns a token drawn in the current round"""
        if self.init_tracker is None:
            await ctx.send(NO_INIT_TRACKER_MESSAGE)
        elif not self.init_tracker.in_round:
            await ctx.send(NOT_IN_ROUND_MESSAGE)
        else:
            token = self.init_tracker.draw_token()
            if token == END_OF_ROUND_TOKEN:
                await ctx.send(f"END OF ROUND {self.init_tracker.round_num}")
            else:
                await ctx.send(f"Current Turn: **{token}**")

    @commands.command(name="draw", hidden=True)
    async def drawAlias(self, ctx):
        await ctx.invoke(self.bot.get_command("init draw"))

    @init.command(name="current")
    async def current_turn(self, ctx):
        if self.init_tracker is None:
            await ctx.send(NO_INIT_TRACKER_MESSAGE)
        elif not self.init_tracker.in_round:
            await ctx.send(NOT_IN_ROUND_MESSAGE)
        else:
            token = self.init_tracker.current_token()
            history = self.init_tracker.current_round_history()[:-1]
            history.reverse()
            await ctx.send(
                f"ROUND {self.init_tracker.round_num} current: **{token}** recent: {', '.join(history)}"
            )

    @commands.command(name="current", aliases=["turn", "now"], hidden=True)
    async def current_turn_alias(self, ctx):
        await ctx.invoke(self.bot.get_command("init current"))

    @init.command(name="delay",
                  help="Puts a token back in the bag and reshuffles it")
    async def delay(self, ctx, token: str):
        if self.init_tracker is None:
            await ctx.send(NO_INIT_TRACKER_MESSAGE)
        elif not self.init_tracker.in_round:
            await ctx.send(NOT_IN_ROUND_MESSAGE)
        else:
            self.init_tracker.delay_token(token)
            await ctx.send(f"Pushing {token} back into the initiative tracker")
Example #8
0
def test_empty_init_tracker():
    t = InitiativeTracker()
    t.add_token("Henchman")
    assert t.count_tokens() == 1
    t.empty()
    assert t.count_tokens() == 0
Example #9
0
def test_draw_token():
    t = InitiativeTracker()
    t.in_round = True
    t.drawn_log = [[]]
    t.round_bag = ["Goblin", "Ogre", END_OF_ROUND_TOKEN, "Goblin"]
    assert t.count_round_tokens() == 4

    tok = t.draw_token()
    assert tok == "Goblin"
    assert t.in_round
    assert t.count_round_tokens() == 3
    assert t.round_bag == ["Ogre", END_OF_ROUND_TOKEN, "Goblin"]
    assert t.drawn_log == [["Goblin"]]

    tok = t.draw_token()
    assert tok == "Ogre"
    assert t.in_round
    assert t.count_round_tokens() == 2
    assert t.round_bag == [END_OF_ROUND_TOKEN, "Goblin"]
    assert t.drawn_log == [["Goblin", "Ogre"]]

    tok = t.draw_token()
    assert tok == END_OF_ROUND_TOKEN
    assert not t.in_round
    assert t.round_bag == ["Goblin"]
    assert t.drawn_log == [["Goblin", "Ogre", END_OF_ROUND_TOKEN]]

    tok = t.draw_token()
    assert tok == END_OF_ROUND_TOKEN
    assert t.round_bag == ["Goblin"]
    assert t.drawn_log == [["Goblin", "Ogre", END_OF_ROUND_TOKEN]]
Example #10
0
def test_display_initiative():
    t = InitiativeTracker()
    t.add_token("Goblin", 2)
    t.add_token("Ogre", 1)
    t.add_token("Henchman", 2)
    t.add_token("Goblin", 2)
    t.add_token("Hero Person", 2)

    assert t.display_tokens() == "Goblin(4) Henchman(2) Hero Person(2) Ogre(1)"
Example #11
0
def test_init_initiative_tracker():
    t = InitiativeTracker()
    assert t.bag == []
Example #12
0
def test_delay_init_tracker():
    t = InitiativeTracker()
    t.add_token("Goblin", 4)
    t.add_token("Vince McFighty", 2)
    t.add_token("Dragon", 20)

    t.start_round()
    assert t.count_round_tokens() == 27
    turn1 = t.round_bag.copy()
    drawn = t.draw_token()
    if drawn != END_OF_ROUND_TOKEN:
        assert t.count_round_tokens() == 26

        t.delay_token(drawn)
        assert t.count_round_tokens() == 27
        turn1a = t.round_bag.copy()
        assert turn1a != turn1
Example #13
0
def test_remove_shuffle():
    t = InitiativeTracker()
    t.add_token("Goblin", 8)
    t.add_token("Vince McFighty", 2)
    t.add_token("Ogre", 2)

    t.start_round()
    turn1 = t.round_bag.copy()

    removed = t.remove_token("Ogre", 2)
    assert removed == 2
    turn2 = t.round_bag.copy()
    assert len(turn1) == 2 + len(turn2)

    turn1.remove("Ogre")
    turn1.remove("Ogre")
    assert len(turn1) == len(turn2)
    assert turn1 != turn2
Example #14
0
def test_initiative_shuffles():
    t = InitiativeTracker()
    t.add_token("Goblin", 4)
    t.add_token("Vince McFighty", 2)
    t.add_token("Dragon", 20)

    t.start_round()
    turn1 = t.round_bag.copy()

    t.start_round()
    turn2 = t.round_bag.copy()

    assert turn1 != turn2