Example #1
0
    async def pay(self, ctx, target_location, amount):

        amount = int(amount)  # dumb.
        member = ctx.message.author
        p = models.Player()
        try:
            p.custom_load("discord_id = ?", (member.id, ))
        except Exception:
            await ctx.send("I don't have you listed as a player, {}\n\
                If you believe this is an error, please talk to a Lord or the Monarch"
                           .format(member.mention))
            return
        # Make sure player has enough coins!!!
        if amount < 1:
            await ctx.send("You can't pay 0 or negative coins, {}".format(
                member.mention))
            return
        elif amount > p.coins:
            await ctx.send("{}, you don't have enough coins!".format(
                member.mention))
            return
        # Get team, current location id, available locations
        t = models.Team()
        t.load(p.team_id)
        current_loc = t.current_location_id
        avail_locs = graphanalyzer.get_next_location_list(t.team_id)
        # Make sure it's a valid target location.
        if target_location.lower() not in (name.lower()
                                           for name in avail_locs.keys()):
            await ctx.send(
                "I don't think {} is a valid location. Maybe you mistyped it?".
                format(target_location))
            return
        # Get the ID for the target location...
        target_loc = models.Location()
        target_loc.custom_load("name = ? COLLATE NOCASE", (target_location, ))
        # target_loc.load((current_loc + 1) % 51)  # Hax for Paris

        edge = models.LocationEdge()
        edge.custom_load("start_location_id = ? AND end_location_id = ?", (
            current_loc,
            target_loc.location_id,
        ))
        # Store the payment in the db
        payment = models.Payment()
        payment.player_id = p.player_id
        payment.team_id = p.team_id
        payment.amount = amount
        payment.location_edge = edge.edge_id
        payment.time = helpers.get_game_day()
        payment.insert()

        # Remove coins from player's account.
        p.coins -= amount
        p.last_active_day = helpers.get_game_day()
        p.update()
        models.save()
        # Send confirmation message.
        await ctx.send("{} has paid **{}** coins toward **{}**".format(
            member.mention, amount, target_loc.name))
Example #2
0
async def check_for_new_logs():
    # Also triggers end of game. Sue me. HACK
    while True:
        if helpers.get_game_day(
        ) > config['game_length'] and config['game_ongoing']:
            await end_game()
        t = models.Team_list()
        t.custom_load("team_id > ?", (0, ))
        for team in t.items:
            if team.current_location_id == 0 and config['game_ongoing']:
                await end_game()

        logs = models.Log_list()
        logs.custom_load("sent = ?", (0, ))
        if len(logs.items) > 0:
            logging.info("Found {} new logs, attempting to send...".format(
                len(logs.items)))
            # Try to send them and die inside.
            try:
                for log in logs.items:
                    ch = get(client.get_all_channels(),
                             id=log.target_channel_id)
                    await ch.send(log.msg)
                    log.sent = 1
                    log.update()
                models.save()
            except AttributeError:
                logging.error(
                    "We can't see the channel yet. We'll get 'em next time.")
        await asyncio.sleep(5)
Example #3
0
 async def team(self, ctx):
     # Prints the player's team's current funding for the day,
     # As well as current location,
     # And total distance remaining.
     member = ctx.message.author
     try:
         p = models.Player()
         p.custom_load("discord_id = ?", (member.id, ))
         if p.last_active_day != helpers.get_game_day():
             p.last_active_day = helpers.get_game_day()
             p.update()
             models.save()
     except Exception:
         await ctx.send("I don't think you're playing, {}\n\
             (If you think this is a mistake, please talk to a Lord or the Monarch)"
                        .format(member.mention))
         return
     t = models.Team()
     t.load(p.team_id)
     l = models.Location()
     l.load(t.current_location_id)
     funding_table = paymentreducer.get_funding_table(
         p.team_id, helpers.get_game_day())
     await ctx.send(
         "Your team is in **{}**, with at least **{}km** to go!\nHere is how today's funding is going:\n{}"
         .format(
             l.name,
             graphanalyzer.dijkstra(graphanalyzer.graph,
                                    t.current_location_id, 0),
             "```" + funding_table + "```"))
Example #4
0
 async def scramble(self, ctx):
     # TODO fix rate limiting issue becuase I think it's breaking more things.
     guild = ctx.message.guild
     logging.info(guild)
     players = models.Player_list()
     players.load_all()
     for p in players.items:
         old_team_id = p.team_id
         # Pick a number & update player
         team_id = randint(1, 3)
         if old_team_id != team_id:
             p.team_id = team_id
             p.update()
             old_team = models.Team()
             old_team.load(old_team_id)
             team = models.Team()
             team.load(team_id)
             # Clear/Assign role
             old_team_role = get(guild.roles, name=old_team.name)
             team_role = get(guild.roles, name=team.name)
             member = guild.get_member(int(p.discord_id))
             if member is None:
                 logging.info(
                     "Player w/ id {} not found. Maybe they left the server.".format(p.discord_id))
                 continue
             await member.remove_roles(old_team_role, reason="Automated Team Scramble")
             await member.add_roles(team_role, reason="Automated Team Scramble")
             logging.info("{} (ID:{}) moved from {} to {}".format(
                 member.nick if member.nick is not None else member.name, p.discord_id, old_team.name, team.name))
             await asyncio.sleep(1)
     models.save()
     logging.info("Scramble complete")
Example #5
0
    async def spectate(self, ctx):
        member = ctx.message.author
        if helpers.get_game_day(
        ) > config['latest_spectate_day'] and config['game_ongoing']:
            await ctx.send(
                "Sorry, {}, it's too late to switch to spectator mode".format(
                    member.mention))
            return

        player = models.Player()
        team = models.Team()
        try:
            player.custom_load("discord_id = ?", (str(member.id), ))
            team.load(player.team_id)
        except Exception as e:
            await ctx.send(
                "I think you're already out of the game, {}. If you think this was a mistake, please talk to a Lord or the Monarch"
                .format(member.mention))
            logging.error(e)
            return
        # Remove flair from user
        role = get(member.guild.roles, name=team.name)
        await member.remove_roles(role, reason='Player left game')
        # Add spectator role
        role = get(member.guild.roles, name='Spectator')
        await member.add_roles(role, reason='Player left game')

        player.delete()
        models.save()

        logging.info("{} has switched to spectating".format(member.id))
        await ctx.send("{}, you're now a spectator. Enjoy the show!".format(
            member.mention))
Example #6
0
async def on_member_join(member):
    pa_chan = get(member.guild.text_channels, name="player-assignments")
    ins_chan = get(member.guild.text_channels, name="instructions")
    # Assign the new member to one of the three teams randomly
    # FIXME Get number of teams through the DB and not hardcode a 3
    team_id = randint(1, 3)
    t = models.Team()
    t.load(team_id)
    # Add flair to user
    role = get(member.guild.roles, name=t.name)
    await member.add_roles(role)
    # Create new Player record.
    p = models.Player()
    # First check if they already exist
    try:
        p.custom_load("discord_id = ?", (member.id, ))
        t.load(p.team_id)
        await pa_chan.send("Welcome back, {}! the **{}** missed you!".format(
            member.mention, t.name))
        return
    except Exception:
        pass
    p.discord_id = member.id
    p.team_id = team_id
    p.coins = config['starting_coins']
    p.last_active_day = helpers.get_game_day()
    p.shares = 100
    p.insert()
    models.save()

    # Post message to player-assignments channel
    await pa_chan.send("Welcome, {}! You have been assigned to the **{}**!\n\
        Make sure to check out the {} and good luck!".format(
        member.mention, t.name, ins_chan.mention))
Example #7
0
def pay_players():
    teams = models.Team_list()
    teams.custom_load("team_id > ?", (0, ))
    for t in teams.items:
        # load all the players
        players = models.Player_list()
        # Still the dumb Loadall HACK
        players.custom_load("team_id = ?", (t.team_id, ))

        total_team_shares = sum([p.shares for p in players.items])
        share_value = config['daily_team_coins'] / total_team_shares
        # pay 'em
        for player in players.items:
            # add daily salary
            player.coins += int(share_value * player.shares)
            # get  THIS PLAYER's payments from TODAY for THIS PLAYER's TEAM that
            # WEREN'T put toward the current location (for refunds)
            models.c.execute(
                "SELECT SUM(amount) FROM Payment p LEFT JOIN LocationEdge le ON(p.location_edge = le.edge_id) WHERE player_id = ? AND team_id = ? AND time = ? AND end_location_id != ?",
                (player.player_id, player.team_id, helpers.get_game_day() - 1,
                 t.current_location_id))

            refund = models.c.fetchone()[0]
            if refund is None:
                refund = 0
            player.coins += int(refund * (config['refund_percentage'] / 100))

            player.update()
    models.save()
Example #8
0
def ten_minute_warning():
    if not config['game_ongoing']:
        return
    l = models.Log()
    l.date = str(datetime.now())
    l.game_day = helpers.get_game_day()
    l.msg = "10 minutes remaining in the day! Get those payments in!!!"
    l.target_channel_id = config['channels']['progress-announcements']
    l.insert()
    models.save()
Example #9
0
def update_shares():
    players = models.Player_list()
    players.load_all()
    for player in players.items:
        days_since_active = helpers.get_game_day() - player.last_active_day
        if days_since_active < len(config['afk_falloff']):
            player.shares = config['afk_falloff'][days_since_active]
        else:
            player.shares = 1
        player.update()
    models.save()
Example #10
0
async def end_game():
    logging.info("Time to end the game!")
    ch = get(client.get_all_channels(),
             id=config["channels"]["progress-announcements"])
    config['game_ongoing'] = 0
    with open(Path(__file__).parent / 'config.json', 'w') as f:
        json.dump(config, f, indent=4)
    scheduledjobs.config = config
    helpers.config = config
    # Invalidate All Oustanding Logs
    logs = models.Log_list()
    logs.custom_load("sent = ?", (0, ))
    if len(logs.items) > 0:
        try:
            for log in logs.items:
                log.sent = 1
                log.update()
        except Exception as e:
            logging.error("Failed to invalidate old logs - {}".format(e))
        models.save()
    # Load winners
    winners = []
    teams = models.Team_list()
    teams.custom_load("team_id > ?", (0, ))
    for t in teams.items:
        start_loc = t.current_location_id
        if start_loc == 1:
            start_loc = 0
        winners.append(
            (t.name, graphanalyzer.dijkstra(graphanalyzer.graph, start_loc,
                                            0)))
    winners.sort(key=lambda x: x[1], reverse=True)
    # Make a big deal of everything, really.
    try:
        await ch.send(
            "All right, adventurers! The game has ended! Drumroll please!!!")
        await (asyncio.sleep(5))
        await ch.send("In third place, with {}km remaining, the {}!".format(
            winners[0][1], winners[0][0]))
        await (asyncio.sleep(3))
        await ch.send("In second place, with {}km remaining, the {}!!".format(
            winners[1][1], winners[1][0]))
        await (asyncio.sleep(3))
        await ch.send(
            "Finally, in first place, the {}!!!!!!!!! Congratulations!".format(
                winners[2][0]))
        await (asyncio.sleep(3))
        await ch.send(
            "Thank you all for playing! I hope you had fun! Now, I'm going to take a nap. Maybe we can do this again some time :sweat_smile:"
        )
    except AttributeError:
        logging.info("Can't see the channel. We'll get 'em next time.")
        return
Example #11
0
 async def me(self, ctx):
     # Print's players current coin count
     member = ctx.message.author
     try:
         p = models.Player()
         p.custom_load("discord_id = ?", (member.id, ))
         await ctx.send("{}, you have **{}** coins".format(
             member.mention, p.coins))
         if p.last_active_day != helpers.get_game_day():
             p.last_active_day = helpers.get_game_day()
             p.update()
             models.save()
     except Exception:
         # Show error if user isn't actually playing
         await ctx.send("I... don't believe you're playing, {}\n\
             (If you think this is a mistake, please talk to a Lord or the Monarch)"
                        .format(member.mention))
Example #12
0
    async def join(self, ctx):
        member = ctx.message.author
        if config['game_ongoing']:
            await ctx.send(
                "Sorry, {}, you can't join the game while it's ongoing!".
                format(member.mention))
            return
        p = models.Player()
        # Make sure player doesn't already exist
        try:
            p.custom_load('discord_id = ?', (member.id, ))
            await ctx.send(
                "I think you're already playing, {}. If you think this is an error, please talk to a Lord or the Monarch"
                .format(member.mention))
            return
        except Exception:
            pass
        # Pick a team
        team_id = randint(1, 3)
        team = models.Team()
        team.load(team_id)

        # Add flair to user
        role = get(member.guild.roles, name=team.name)
        await member.add_roles(role, reason='Player joined game')
        # Remove spectator role
        role = get(member.guild.roles, name='Spectator')
        if role in member.roles:
            await member.remove_roles(role, reason='Player joined game')

        # Create new player
        p.discord_id = member.id
        p.team_id = team_id
        p.coins = config['starting_coins']
        p.last_active_day = 0
        p.shares = 100
        p.insert()
        models.save()
        logging.info("{} has joined the {}".format(member.id, team.name))
        await ctx.send(
            "{}, you've been added to the **{}**! Good Luck!".format(
                member.mention, team.name))
Example #13
0
def team_attempt_move(team_id):
    process_log = ""
    # Load team.
    t = models.Team()
    t.load(team_id)
    flns = paymentreducer.get_funding_list(team_id,
                                           helpers.get_game_day() - 1, False)
    fl = paymentreducer.get_funding_list(team_id,
                                         helpers.get_game_day() - 1, True)

    # Check for best-funded succesful path
    new_loc = t.current_location_id
    biggest_funding = -1
    was_sabotaged = False
    for k, v in flns.items():
        le = models.LocationEdge()
        le.load(k)
        if v >= le.weight and v > biggest_funding:
            new_loc = le.end_location_id
            biggest_funding = v
            if fl[k] < le.weight:
                was_sabotaged = True
            else:
                was_sabotaged = False

    if biggest_funding == -1:
        process_log = "The {} didn't raise enough to book passage anywhere...".format(
            t.name)
    else:
        l = models.Location()
        l.load(new_loc)
        if was_sabotaged:
            process_log = "The {} tried to travel to {}, but someone sabotaged them and they were stopped by the Black Cats!".format(
                t.name, l.name)
        else:
            t.current_location_id = new_loc
            t.update()
            process_log = "The {} have successfully reached {}!".format(
                t.name, l.name)

    models.save()
    return process_log + "\n"
Example #14
0
    async def startgame(self, ctx):
        logging.info("The Monarch has signalled to begin the game!")
        # Reset every player's coins
        logging.info("Resetting player coins and last_active_day...")
        ps = models.Player_list()
        ps.custom_load("player_id > ?", (0,))  # HACK to select all
        for p in ps.items:
            p.coins = config["starting_coins"]
            p.last_active_day = 0
            p.update()
        # Reset every team's starting location
        logging.info("Resetting team locations...")
        ts = models.Team_list()
        ts.custom_load("team_id > ?", (0,))  # SAME HACK to select all
        for t in ts.items:
            t.current_location_id = 1
            t.update()

        # Set time to -1 for all payments (i'm sorry reality)
        logging.info("Invalidating previous payments...")
        pmts = models.Payment_list()
        pmts.custom_load("time >= ?", (0,))
        for p in pmts.items:
            p.time = -1
            p.update()

        models.save()
        # Update config
        config['game_ongoing'] = 1
        d = datetime.now()
        d = d.replace(minute=0, second=0, microsecond=0)
        config['start_date'] = str(d)
        with open(Path(__file__).parent / 'config.json', 'w') as f:
            json.dump(config, f, indent=4)
        scheduledjobs.config = config
        helpers.config = config
        scheduledjobs.on_new_day()
Example #15
0
    async def sabotage(self, ctx, target_team, target_location, amount):
        # just pay() but with negative coins and another team
        amount = int(amount)  # still dumb
        member = ctx.message.author
        p = models.Player()
        try:
            p.custom_load("discord_id = ?", (member.id, ))
        except Exception:
            await ctx.send(
                "Gonna be hard to sabotage when I don't have you listed as a player, {}\n\
                If you believe this is a mistake, please talk to a Lord or the Monarch"
                .format(member.mention))
            return
        # Mke sure player has enough coins
        if amount < 1:
            await ctx.send("You can't pay 0 or negative coins, {}".format(
                member.mention))
            return
        elif amount > p.coins:
            await ctx.send("{}, you don't have enough coins!".format(
                member.mention))
            return

        t = models.Team()
        try:
            # TODO make this more user-friendly
            t.custom_load("name = ? COLLATE NOCASE", (target_team, ))
        except Exception:
            await ctx.send(
                "I don't think {} is a real team, {}. Make sure you type the full name!"
                .format(target_team, member.mention))
            return

        if t.team_id == p.team_id:
            await ctx.send(
                "You can't sabotage your own team, {}!!! They won't like you for that!"
                .format(member.mention))
            return

        current_loc = t.current_location_id
        avail_locs = graphanalyzer.get_next_location_list(t.team_id)
        # Validate target location...
        if target_location.lower() not in (name.lower()
                                           for name in avail_locs.keys()):
            await ctx.send(
                "I don't think {} is a valid location. Maybe a typo?".format(
                    target_location))
            return
        # Get id for the target location...
        location = models.Location()
        location.custom_load("name = ? COLLATE NOCASE", (target_location, ))
        # location.load((current_loc + 1) % 51)  # Hax for Paris

        edge = models.LocationEdge()
        edge.custom_load("start_location_id = ? AND end_location_id = ?",
                         (current_loc, location.location_id))

        # Store the payment!
        payment = models.Payment()
        payment.player_id = p.player_id
        payment.team_id = t.team_id
        payment.amount = -amount  # VERY IMPORTANT DIFFERENCE
        payment.location_edge = edge.edge_id
        payment.time = helpers.get_game_day()
        payment.insert()

        # Remove coins from the player's account
        p.coins -= amount
        p.last_active_day = helpers.get_game_day()
        p.update()
        models.save()
        # Send confirmation message.
        await ctx.send(
            "{} has paid **{}** coins to sabotage the **{}'** trip to **{}**".
            format(member.mention, amount, t.name, location.name))