def get_current_value(self, guideline=None): if self.treasure: items = get_ranked_items() itemids = [i.itemid for i in items] try: index = itemids.index(self.contents) value = items[index].rank() / 100 except ValueError: value = 100 elif self.gold or self.empty: if self.empty: if guideline is not None: value = guideline / 100 else: raise Exception("No guideline provided for empty chest.") else: value = self.contents elif self.monster: from formationrandomizer import get_fset formation = get_fset(self.contents | 0x100).formations[0] items = [] for monster in formation.present_enemies: mitems = [i for i in monster.drops if i is not None] if mitems: items.append(min(mitems, key=lambda i: i.rank())) if items: highest = max(items, key=lambda i: i.rank()) value = highest.rank() / 100 else: value = 1 assert value < 10000 return value
def get_current_value(self, guideline=None): if self.treasure: items = get_ranked_items() itemids = [i.itemid for i in items] try: index = itemids.index(self.contents) value = items[index].rank() // 100 except ValueError: value = 100 elif self.gold or self.empty: if self.empty: if guideline is not None: value = guideline // 100 else: raise Exception("No guideline provided for empty chest.") else: value = self.contents elif self.monster: from formationrandomizer import get_fset formation = get_fset(self.contents | 0x100).formations[0] items = [] for monster in formation.present_enemies: mitems = [i for i in monster.original_drops if i is not None] if mitems: items.append(min(mitems, key=lambda i: i.rank())) if items: highest = max(items, key=lambda i: i.rank()) value = highest.rank() // 100 else: value = 1 assert value < 10000 return value
def get_notable_equips(self): items = [i for i in get_ranked_items() if i.equippable & (1 << self.id) and not i.imp_only] weapons = [i for i in items if i.is_weapon] rare = [i for i in items if not i.is_weapon and bin(i.equippable).count('1') <= 5 and i.rank() > 4000] rare.extend([w for w in weapons if w.rank() > 50000]) if self.id == 12: rare = [r for r in rare if not r.features['special1'] & 0x7C] notable = [] if weapons: weapons = sorted(weapons, key=lambda w: w.rank(), reverse=True) notable.extend(weapons[:2]) if rare: rare = sorted(rare, key=lambda r: r.rank(), reverse=True) notable.extend(rare[:8]) notable = set(notable) return sorted(notable, key=lambda n: n.itemid)
def mutate_contents(self, guideline=None, monster=None, guarantee_miab_treasure=False, enemy_limit=None, uniqueness=False, crazy_prices=False, uncapped_monsters=False): global used_formations, done_items if self.do_not_mutate and self.contents is not None: return if self.value is not None: value = self.value else: value = self.get_current_value(guideline=guideline) items = get_ranked_items() itemids = [i.itemid for i in items] if self.treasure: try: index = itemids.index(self.contents) except ValueError: index = 0 indexed_item = items[index] else: lowpriced = [i for i in items if i.rank() <= value * 100] if not lowpriced: lowpriced = items[:random.randint(1, 16)] index = max(0, len(lowpriced) - 1) indexed_item = lowpriced[index] chance = random.randint(1, 50) orphaned_formations = get_orphaned_formations(uncapped_monsters) orphaned_formations = [ f for f in orphaned_formations if f not in used_formations ] extra_miabs = get_extra_miabs(0) if monster is True: chance = 1 elif monster is False: chance += 3 chance = min(chance, 50) else: if orphaned_formations or extra_miabs: chance -= 2 if uncapped_monsters else 1 chance = max(chance, 1) formations = get_appropriate_formations() formations = [ f for f in formations if f.get_guaranteed_drop_value() >= value * 100 ] if 1 <= chance <= 3 and (self.rank or formations): # monster self.set_content_type(0x20) from locationrandomizer import get_location rank = self.rank if self.is_clock or not rank: rank = min(formations, key=lambda f: f.rank()).rank() if formations else 0 chosen = select_monster_in_a_box( rank=rank, value=value, clock=self.is_clock or monster is True, old_version=uncapped_monsters, guarantee_miab_treasure=guarantee_miab_treasure, enemy_limit=enemy_limit) chosen = get_2pack(chosen) # only 2-packs are allowed self.contents = chosen.setid & 0xFF elif 4 <= chance <= 5: # gold self.set_content_type(0x80) if crazy_prices: value = random.randint(10, 50) else: value = value // 2 value += (random.randint(0, value) + random.randint(0, value)) self.contents = min(0xFF, max(1, value)) if self.contents == 0xFF: self.contents -= random.randint(0, 20) + random.randint(0, 20) else: # treasure self.set_content_type(0x40) if uniqueness and random.randint(1, 7) != 7: if len(done_items) >= len(items): done_items = [] temp = [ i for i in items if i == indexed_item or i not in done_items ] if len(temp) > 1: items = temp index = items.index(indexed_item) if indexed_item in done_items: items.remove(indexed_item) index = mutate_index(index, len(items), [False, True], (-4, 2), (-2, 2)) self.contents = items[index].itemid done_items.append(items[index]) assert self.contents <= 0xFF self.value = value
def mutate_contents(self, guideline=None, monster=None, guarantee_miab_treasure=False, enemy_limit=None, uniqueness=False): global used_formations, done_items if self.do_not_mutate and self.contents is not None: return if self.value is not None: value = self.value else: value = self.get_current_value(guideline=guideline) items = get_ranked_items() itemids = [i.itemid for i in items] if self.treasure: try: index = itemids.index(self.contents) except ValueError: index = 0 indexed_item = items[index] else: lowpriced = [i for i in items if i.rank() <= value*100] if not lowpriced: lowpriced = items[:random.randint(1, 16)] index = max(0, len(lowpriced)-1) indexed_item = lowpriced[index] chance = random.randint(1, 50) orphaned_formations = get_orphaned_formations() orphaned_formations = [f for f in orphaned_formations if f not in used_formations] extra_miabs = get_extra_miabs(0) if orphaned_formations or extra_miabs: chance -= 2 chance = max(chance, 1) if monster is True: chance = 1 elif monster is False: chance += 3 chance = min(chance, 50) formations = get_appropriate_formations() formations = [f for f in formations if f.get_guaranteed_drop_value() >= value * 100] if 1 <= chance <= 3 and (self.rank or formations): # monster self.set_content_type(0x20) rank = self.rank or min(formations, key=lambda f: f.rank()).rank() if guarantee_miab_treasure: extra_miabs = [] orphaned_formations = [] candidates = [] else: if len(extra_miabs) > 1: extra_miabs = get_extra_miabs(rank) if orphaned_formations or extra_miabs: formations = [f for f in formations if f.rank() >= rank] formations = formations[:random.randint(1, 3)] candidates = (orphaned_formations + extra_miabs) candidates = sorted(set(candidates)) if len(candidates) != 1: candidates += formations candidates = [c for c in candidates if c not in used_formations] candidates = [c for c in candidates if c.formid not in banned_formids] if enemy_limit is not None: candidates = [f for f in candidates if f.rank() <= enemy_limit] if not candidates: candidates = (formations + get_orphaned_formations() + get_extra_miabs(0)) if enemy_limit is not None: candidates = [f for f in candidates if f.rank() <= enemy_limit] candidates = sorted(candidates, key=lambda f: f.rank()) half = len(candidates) / 2 candidates = candidates[half:] index = random.randint(0, half) + random.randint(0, half) index = min(index, len(candidates)-1) candidates = candidates[index:] candidates = sorted(candidates, key=lambda f: f.rank()) if orphaned_formations: index = max( 0, len([c for c in candidates if c.rank() <= rank])-1) index = mutate_index(index, len(candidates), [False, True], (-3, 2), (-1, 1)) else: index = 0 index = mutate_index(index, len(candidates), [False, True], (-1, 4), (-1, 1)) chosen = candidates[index] for m in chosen.present_enemies: m.auxloc = "Monster-in-a-Box" banned_formids.append(chosen.formid) used_formations.append(chosen) chosen = get_2pack(chosen) # only 2-packs are allowed self.contents = chosen.setid & 0xFF elif 4 <= chance <= 5: # gold self.set_content_type(0x80) value = value / 2 value += (random.randint(0, value) + random.randint(0, value)) self.contents = min(0xFF, max(1, value)) if self.contents == 0xFF: self.contents -= random.randint(0, 20) + random.randint(0, 20) else: # treasure self.set_content_type(0x40) if uniqueness and random.randint(1, 7) != 7: if len(done_items) >= len(items): done_items = [] temp = [i for i in items if i == indexed_item or i not in done_items] if len(temp) > 1: items = temp index = items.index(indexed_item) if indexed_item in done_items: items.remove(indexed_item) index = mutate_index(index, len(items), [False, True], (-4, 2), (-2, 2)) self.contents = items[index].itemid done_items.append(items[index]) assert self.contents <= 0xFF self.value = value
def mutate_items(self, fout, crazy_shops=False): items = get_ranked_items() if crazy_shops: weapons_tools = [i for i in items if i.is_weapon or i.is_tool] armors = [i for i in items if i.is_armor] relics = [i for i in items if i.is_relic] consumables = [i for i in items if i.is_consumable] types = [weapons_tools, armors, relics, consumables] valid_items = items elif self.shoptype == 1: valid_items = [c for c in items if c.is_weapon or c.is_tool] elif self.shoptype == 2: valid_items = [c for c in items if c.is_armor] elif self.shoptype == 3: valid_items = [ c for c in items if not (c.is_weapon or c.is_armor or c.is_relic) ] elif self.shoptype == 4: valid_items = [c for c in items if c.is_relic] elif self.shoptype == 5: valid_items = list(items) old_items = [i for i in self.items if i != 0xFF] if not old_items: return old_items = [get_item(i) for i in old_items] old_items = [i for i in old_items if i] if len(old_items) == 0: average_value = 0 else: average_value = sum([i.rank() for i in old_items]) / len(old_items) average_item = len( [i for i in valid_items if i.rank() <= average_value]) average_item += -1 average_item = valid_items[average_item] while (crazy_shops or random.randint(1, 3) == 3) and len(old_items) < 8: old_items.append(average_item) new_items = [] for item in old_items: if crazy_shops: item_type = random.choice(types) new_items.append(random.choice(item_type)) else: if random.randint(1, 10) == 10: candidates = items else: candidates = valid_items try: index = candidates.index(item) except ValueError: continue while random.randint(1, 3) < 3: index += random.randint(-2, 2) index = max(0, min(index, len(candidates) - 1)) new_items.append(candidates[index]) if not new_items: return for i in new_items: if i.price < 3: price = i.rank() modifier = price // 2 price += random.randint(0, modifier) while random.randint(1, 4) < 4: price += random.randint(0, modifier) price = min(price, 0xFEFE) i.price = price zerocount = 0 while i.price > 100: i.price = i.price // 10 zerocount += 1 while zerocount > 0: i.price = i.price * 10 zerocount += -1 i.write_stats(fout) self.items = [i.itemid for i in new_items] self.items = sorted(set(self.items)) while len(self.items) < 8: self.items.append(0xFF) assert len(self.items) == 8
def mutate_contents(self, guideline=None, monster=None, guarantee_miab_treasure=False, enemy_limit=None, uniqueness=False): global used_formations, done_items if self.do_not_mutate and self.contents is not None: return if self.value is not None: value = self.value else: value = self.get_current_value(guideline=guideline) items = get_ranked_items() itemids = [i.itemid for i in items] if self.treasure: try: index = itemids.index(self.contents) except ValueError: index = 0 indexed_item = items[index] else: lowpriced = [i for i in items if i.rank() <= value * 100] if not lowpriced: lowpriced = items[:random.randint(1, 16)] index = max(0, len(lowpriced) - 1) indexed_item = lowpriced[index] chance = random.randint(1, 50) orphaned_formations = get_orphaned_formations() orphaned_formations = [ f for f in orphaned_formations if f not in used_formations ] extra_miabs = get_extra_miabs(0) if orphaned_formations or extra_miabs: chance -= 2 chance = max(chance, 1) if monster is True: chance = 1 elif monster is False: chance += 3 chance = min(chance, 50) formations = get_appropriate_formations() formations = [ f for f in formations if f.get_guaranteed_drop_value() >= value * 100 ] if 1 <= chance <= 3 and (self.rank or formations): # monster self.set_content_type(0x20) rank = self.rank or min(formations, key=lambda f: f.rank()).rank() if guarantee_miab_treasure: extra_miabs = [] orphaned_formations = [] candidates = [] else: if len(extra_miabs) > 1: extra_miabs = get_extra_miabs(rank) if orphaned_formations or extra_miabs: formations = [f for f in formations if f.rank() >= rank] formations = formations[:random.randint(1, 3)] candidates = (orphaned_formations + extra_miabs) candidates = sorted(set(candidates)) if len(candidates) != 1: candidates += formations candidates = [c for c in candidates if c not in used_formations] candidates = [ c for c in candidates if c.formid not in banned_formids ] if enemy_limit is not None: candidates = [f for f in candidates if f.rank() <= enemy_limit] if not candidates: candidates = (formations + get_orphaned_formations() + get_extra_miabs(0)) if enemy_limit is not None: candidates = [ f for f in candidates if f.rank() <= enemy_limit ] candidates = sorted(candidates, key=lambda f: f.rank()) half = len(candidates) / 2 candidates = candidates[half:] index = random.randint(0, half) + random.randint(0, half) index = min(index, len(candidates) - 1) candidates = candidates[index:] candidates = sorted(candidates, key=lambda f: f.rank()) if orphaned_formations: index = max( 0, len([c for c in candidates if c.rank() <= rank]) - 1) index = mutate_index(index, len(candidates), [False, True], (-3, 2), (-1, 1)) else: index = 0 index = mutate_index(index, len(candidates), [False, True], (-1, 4), (-1, 1)) chosen = candidates[index] for m in chosen.present_enemies: m.auxloc = "Monster-in-a-Box" banned_formids.append(chosen.formid) used_formations.append(chosen) chosen = get_2pack(chosen) # only 2-packs are allowed self.contents = chosen.setid & 0xFF elif 4 <= chance <= 5: # gold self.set_content_type(0x80) value = value / 2 value += (random.randint(0, value) + random.randint(0, value)) self.contents = min(0xFF, max(1, value)) if self.contents == 0xFF: self.contents -= random.randint(0, 20) + random.randint(0, 20) else: # treasure self.set_content_type(0x40) if uniqueness and random.randint(1, 7) != 7: if len(done_items) >= len(items): done_items = [] temp = [ i for i in items if i == indexed_item or i not in done_items ] if len(temp) > 1: items = temp index = items.index(indexed_item) if indexed_item in done_items: items.remove(indexed_item) index = mutate_index(index, len(items), [False, True], (-4, 2), (-2, 2)) self.contents = items[index].itemid done_items.append(items[index]) assert self.contents <= 0xFF self.value = value
def mutate_items(self, fout): items = get_ranked_items() if self.shoptype == 1: valid_items = [c for c in items if c.is_weapon or c.is_tool] elif self.shoptype == 2: valid_items = [c for c in items if c.is_armor] elif self.shoptype == 3: valid_items = [c for c in items if not (c.is_weapon or c.is_armor or c.is_relic)] elif self.shoptype == 4: valid_items = [c for c in items if c.is_relic] elif self.shoptype == 5: valid_items = list(items) old_items = [i for i in self.items if i != 0xFF] if not old_items: return old_items = [get_item(i) for i in old_items] old_items = [i for i in old_items if i] if len(old_items) == 0: average_value = 0 else: average_value = sum([i.rank() for i in old_items]) / len(old_items) average_item = len([i for i in valid_items if i.rank() <= average_value]) average_item += -1 average_item = valid_items[average_item] while random.randint(1, 3) == 3 and len(old_items) < 8: old_items.append(average_item) new_items = [] for item in old_items: if random.randint(1, 10) == 10: candidates = items else: candidates = valid_items try: index = candidates.index(item) except ValueError: continue while random.randint(1, 3) < 3: index += random.randint(-2, 2) index = max(0, min(index, len(candidates)-1)) new_items.append(candidates[index]) if not new_items: return for i in new_items: if i.price < 3: price = i.rank() modifier = price / 2 price += random.randint(0, modifier) while random.randint(1, 4) < 4: price += random.randint(0, modifier) price = min(price, 0xFEFE) i.price = price zerocount = 0 while i.price > 100: i.price = i.price / 10 zerocount += 1 while zerocount > 0: i.price = i.price * 10 zerocount += -1 i.write_stats(fout) self.items = [i.itemid for i in new_items] self.items = sorted(set(self.items)) while len(self.items) < 8: self.items.append(0xFF) assert len(self.items) == 8