def get_drop_chances(weight_function=get_basic_weight, only_droppable=False, only_craftable=False): """Get the chances that each rarity can drop. Parameters ---------- weight_function : function Function used to determine weight based on passed ShipBase. only_droppable : bool If True, only select from the ships which can be dropped. only_craftable : bool If True, only select from the ships which can be crafted. Returns ------- list List of size 8, floats equalling percent the respective rarity can drop. """ ships = ship_stats.get_all_ships(allow_remodel=False, only_droppable=only_droppable, only_craftable=only_craftable) total_pool = sum(weight_function(s) for s in ships) totals = [0] * 8 for rarity in range(8): rtotal = sum( weight_function(s) for s in ships if s.rarity == rarity + 1) totals[rarity] = rtotal return list(map(lambda x: x / total_pool, totals))
def get_random_drop(owner, weight_function=get_basic_weight, only_droppable=False, only_craftable=False): """Get a random ship drop, as a ShipInstance. Parameters ---------- owner : int Discord ID of the owner of the drop. weight_function : function Function used to determine weight based on passed ShipBase. only_droppable : bool If True, only select from the ships which can be dropped. only_craftable : bool If True, only select from the ships which can be crafted. """ ships = ship_stats.get_all_ships(allow_remodel=False, only_droppable=only_droppable, only_craftable=only_craftable) total_pool = sum(weight_function(s) for s in ships) val = random.randrange(total_pool) for ship in ships: val -= weight_function(ship) if (val <= 0): return ship_stats.ShipInstance.new(ship.sid, owner) break return ship_stats.ShipInstance.new(11, owner)
async def add_ship(ctx, user: discord.Member, ship_name): """Admin command to add a ship to a user's inventory.""" inv = userinfo.get_user_inventory(user.id) targ = None for ship in ship_stats.get_all_ships(): if (ship.name.lower() == ship_name.lower() or ship.name.lower() .replace(' ', '_') == ship_name.lower()): targ = ship break if (targ): ins = ship_stats.ShipInstance.new(targ.sid, user.id) inv.add_to_inventory(ins) await ctx.send("Added %s to %s's inventory" % (targ.name, str(user))) logging.info("[ADMIN_ADD] Added %s to %s's (%s) inventory" % (targ.name, str(user), user.id)) else: await ctx.send(namesub("Cannot find <ship.title> '%s'") % ship_name)
async def show_birthdays(bdays, channels, mon, day): ship_names = [] look = "%02d-%02d" % (day, mon) for k, v in bdays.items(): if (v == look): ship_names.append(k) if (len(ship_names) > 0): ships = ship_stats.get_all_ships(allow_remodel=False) msg = "Happy birthday, %s!" files = [] for sn in ship_names: for sb in ships: if (sb.name.lower() == sn.lower()): bio = imggen.get_birthday_image(sb) files.append((bio, sb.name)) for c in channels: for ft in files: bio, sbname = ft f = discord.File(io.BytesIO(bio.getvalue()), filename="image.png") await c.send(file=f, content=(msg % sbname)) else: msg = "There are no birthdays today. (%02d/%02d)" % (day, mon) send_task = [c.send(content=msg) for c in channels] await asyncio.gather(*send_task)
def get_craft_from_resources(owner, f, a, s, b): """Get a random ship craft given the resource amounts to use.""" nnr = nearest_n_recipes(f, a, s, b) # this is complicated so here's a simple explanation: # in (n - 1) steps where n is # of recipes taken from above: # - take closest remaining recipe based on distance # - get % of total distance of remaining recipes closest takes up # - remove closest from list, add it with its % to the final list # - scale next steps' % based on how much % the previous steps' closest # were # after, take the last remaining value and set its # so everything equals 1 dist_map = list(map(lambda x: (x[0], math.sqrt(x[1])), nnr)) final_map = [] pcnt_left = 1.0 for i in range(len(nnr) - 1): total_dist = sum(map(lambda x: x[1], dist_map)) if (total_dist == 0): break dist_map_inv = list( map(lambda x: (x[0], pcnt_left * (total_dist - x[1]) / total_dist), dist_map)) dist_map.sort(key=lambda x: -x[1]) dist_map_inv.sort(key=lambda x: x[1]) app = dist_map_inv.pop() pcnt_left -= app[1] final_map.append(app) dist_map.pop() total_pcnt = sum(map(lambda x: x[1], final_map)) last = dist_map.pop() final_map.append((last[0], 1 - total_pcnt)) weight_bonus_shiptype = list( map(lambda x: (x[0], int(x[1] * WEIGHT_BONUS_TYPE)), final_map)) weight_bonus_rarity = list( map(lambda x: (x[0], int(x[1] * WEIGHT_BONUS_RARITY)), final_map)) weight_boost = {} all_types = [] for recipe, _m in final_map: all_types.extend(map(lambda x: x.discriminator, recipe.types)) applicable_ships = set( ship_stats.get_all_ships(allow_remodel=False, only_craftable=True, type_discrims=all_types)) # shiptype boost for recipe, weight_bonus in weight_bonus_shiptype: award_base = weight_bonus // len(applicable_ships) for s in applicable_ships: if (s.sid not in weight_boost): weight_boost[s.sid] = 0 weight_boost[s.sid] += award_base # rarity boost (only for shiptypes above) # boost based on dist to rarity focus (max 2) for recipe, weight_bonus in weight_bonus_rarity: inv_dist = list( map(lambda x: (x, 2 - abs(recipe.rarityfocus - x.rarity)), applicable_ships)) rarity_total = sum([x[1] for x in inv_dist if x[1] > 0]) rarity_award = weight_bonus // rarity_total for s, rd in inv_dist: if (rd <= 0): continue weight_boost[s.sid] += rarity_award * rd def weight_function(ship): wb = ship.sid in weight_boost and weight_boost[ship.sid] > 0 return (drophandler.get_basic_weight(ship) // (.5 if wb else 3)) \ + (weight_boost[ship.sid] if wb else 0) drop = drophandler.get_random_drop(owner, weight_function=weight_function, only_craftable=True) return drop
async def on_ready(): """Run when the bot initializes fully.""" print("Ready on {} ({})".format(bot.user.name, bot.user.id)) logging.info("Loading ships...") ship_stats.get_all_ships() # add ships to cache logging.info("Ships loaded")