Example #1
0
 def intershuffle(cls):
     super(MonsterObject, cls).intershuffle()
     valid = [m for m in cls.every if m.intershuffle_valid]
     hitspecs = [m.hit_special_defense & 0xFC for m in valid]
     random.shuffle(hitspecs)
     for hs, m in zip(hitspecs, valid):
         m.hit_special_defense = (m.hit_special_defense & 0x03) | hs
Example #2
0
    def mutate_all(cls):
        numgroups = len(cls.groups)
        reassignments = range(numgroups)
        random.shuffle(reassignments)
        reassignments = dict(zip(range(numgroups), reassignments))
        for o in cls.every:
            o.groupindex = reassignments[o.groupindex]

        for n, group in sorted(cls.groups.items()):
            for i, o in enumerate(group):
                done = [o2.item for o2 in group[:i]]
                item = ItemObject.get(o.item)
                for _ in xrange(100):
                    new_item = item.get_similar()
                    if new_item.full_index not in done:
                        break
                else:
                    candidates = [i for i in ItemObject.every_buyable
                                  if i.full_index not in done]
                    new_item = random.choice(candidates)
                o.item = new_item.full_index
            indices_sorted = sorted(group[:-1], key=lambda i: i.item)
            indices_sorted = [i.item for i in indices_sorted]
            for (a, b) in zip(group, indices_sorted):
                a.item = b
Example #3
0
    def mutate(self):
        MAX_ENEMIES = 6
        if self.bosses or self.enemies_hidden or not self.enemies_present:
            return
        candidates = list(self.leaders)
        while len(candidates) < 3:
            base = random.choice(candidates)
            new = base.get_similar()
            if new not in candidates:
                candidates.append(new)
        assert len(set(candidates)) <= 3
        num_enemies = random.randint(1, random.randint(3, MAX_ENEMIES))
        num_enemies = max(num_enemies, len(self.leaders))
        chosen_enemies = list(self.leaders)
        while len(chosen_enemies) < num_enemies:
            vram_total = sum([e.vram_value for e in chosen_enemies])
            sub_candidates = candidates + chosen_enemies
            sub_candidates = [e for e in sub_candidates
                              if vram_total + e.vram_value <= 64]
            if not sub_candidates:
                num_enemies = len(chosen_enemies)
                break
            chosen_enemies.append(random.choice(sub_candidates))
        random.shuffle(chosen_enemies)

        def mutate_coordinate((x, y)):
            x = mutate_normal(x, minimum=self.lower_x, maximum=self.upper_x)
            y = mutate_normal(y, minimum=self.lower_y, maximum=self.upper_y)
            return (x, y)

        def get_distance((x1, y1), (x2, y2)):
            return ((x1-x2)**2 + (y1-y2)**2)**0.5
Example #4
0
 def full_randomize(cls):
     if hasattr(cls, "after_order"):
         for cls2 in cls.after_order:
             if not (hasattr(cls2, "randomized") and cls2.randomized):
                 raise Exception("Randomize order violated.")
     for c in CharacterObject.every:
         c.known_spells = 0
     spells = range(0x1b)
     spells.remove(7)  # group hug
     random.shuffle(spells)
     supplemental = [0xFF] * 3
     spells = spells + supplemental
     charspells = defaultdict(list)
     while spells:
         valid = [i for i in range(5) if len(charspells[i]) < 5 or
                  (len(charspells[i]) < 6 and i != 1)]
         chosen = random.choice(valid)
         spell = spells.pop(0)
         if spell == 0xFF:
             valid = [s for s in range(0x1b) if s not in charspells[i]
                      and s != 7]  # group hug
             spell = random.choice(valid)
         charspells[chosen].append(spell)
     charspells[1].insert(random.randint(0, 5), 7)
     for l in LearnObject.every:
         l.spell = 0xFF
     for i in range(5):
         charlevels = sorted(random.sample(range(2, 20), 5))
         spells = charspells[i]
         c = CharacterObject.get(i)
         c.known_spells |= (1 << spells[0])
         for l, s in zip(charlevels, spells[1:]):
             l = LearnObject.get_by_character(i, l-2)
             l.spell = s
     cls.randomized = True
    def mutate_all(cls):
        numgroups = len(cls.groups)
        reassignments = range(numgroups)
        random.shuffle(reassignments)
        reassignments = dict(zip(range(numgroups), reassignments))
        for o in cls.every:
            o.groupindex = reassignments[o.groupindex]

        for n, group in sorted(cls.groups.items()):
            for i, o in enumerate(group):
                done = [o2.item for o2 in group[:i]]
                item = ItemObject.get(o.item)
                for _ in xrange(100):
                    new_item = item.get_similar()
                    if new_item.full_index not in done:
                        break
                else:
                    candidates = [
                        i for i in ItemObject.every_buyable
                        if i.full_index not in done
                    ]
                    new_item = random.choice(candidates)
                o.item = new_item.full_index
            indices_sorted = sorted(group[:-1], key=lambda i: i.item)
            indices_sorted = [i.item for i in indices_sorted]
            for (a, b) in zip(group, indices_sorted):
                a.item = b
def randomize_rng(address=0xFE00):
    numbers = range(0x100)
    random.shuffle(numbers)
    f = open(get_outfile(), 'r+b')
    f.seek(address)
    f.write("".join([chr(n) for n in numbers]))
    f.close()
Example #7
0
def randomize_crystal_shards():
    if "y" not in get_flags():
        return

    FREELANCER, MIME = 0x84fc3, 0x91baf

    def map_crystal_job(value):
        return (7-(value%8)) + ((value/8)*8)

    def map_job_crystal(value):
        crystals = [c for c in range(24) if map_crystal_job(c) == value]
        assert len(crystals) == 1
        return crystals[0]

    values = []
    # galuf has no mime sprite
    addrs = [a for a in CRYSTAL_ADDRS if a not in [FREELANCER, MIME]]
    assert len(addrs) == 20
    f = open(get_outfile(), "r+b")
    start_candidates = [j.index for j in JobCommandObject.every
                        if j.commands[0] == 5 and j.index < 20]
    start_choice = random.choice(start_candidates)
    f.seek(FREELANCER)
    f.write(chr(map_job_crystal(start_choice)))
    remaining = [j.index for j in JobCommandObject.every
                 if j.index != 20 and j.index != start_choice]
    random.shuffle(remaining)
    assert len(addrs) == len(remaining) == 20
    for addr, j in zip(addrs, remaining):
        f.seek(addr)
        f.write(chr(map_job_crystal(j)))
    f.close()
    return values
Example #8
0
def randomize_rng(address=0xFE00):
    numbers = range(0x100)
    random.shuffle(numbers)
    f = open(get_outfile(), 'r+b')
    f.seek(address)
    f.write("".join([chr(n) for n in numbers]))
    f.close()
Example #9
0
 def mutate_all(self):
     brs = list(self.every)
     random.shuffle(brs)
     for o in brs:
         if hasattr(o, "mutated") and o.mutated:
             continue
         o.mutate()
         o.mutated = True
Example #10
0
def randomize_rng():
    filename = get_outfile()
    f = open(filename, "r+b")
    f.seek(0xFEC0)
    random_numbers = range(0x100)
    random.shuffle(random_numbers)
    f.write("".join(map(chr, random_numbers)))
    f.close()
Example #11
0
 def mutate_all(self):
     brs = list(self.every)
     random.shuffle(brs)
     for o in brs:
         if hasattr(o, "mutated") and o.mutated:
             continue
         o.mutate()
         o.mutated = True
Example #12
0
    def randomize_counts(self):
        if self.index <= 0xf:
            # boss formation
            enumerated_fcounts = list(enumerate(self.fcounts))
            random.shuffle(enumerated_fcounts)
            aas = [self.enemy_indexes[2] == 0 and self.index > 0, False]
            for ((i, fcount), aa) in zip(enumerated_fcounts, aas):
                counts = fcount.old_data['counts']
                candidates = [f for f in FormationCountObject.every
                              if f.validate_boss(counts, allow_add=aa)]
                if not candidates:
                    chosen = fcount
                else:
                    chosen = random.choice(candidates)
                self.counts[i] = chosen.index
                if aa:
                    old_monsters = [self.monsters[j]
                                    for (j, c) in enumerate(counts) if c > 0]
                    avg_rank = (sum([m.rank for m in old_monsters])
                                / len(old_monsters))
                    avg_hp = (sum([m.hp for m in old_monsters])
                              / len(old_monsters))
                    candidates = [m for m in MonsterObject.ranked
                                  if m.intershuffle_valid
                                  and m.rank < avg_rank
                                  and m.hp < avg_hp]

                    max_index = len(candidates) - 1
                    randval = random.random()
                    randomness = (1-self.random_degree)
                    if randomness > 0:
                        randval = randval ** (1 / randomness)
                    else:
                        randval = 0
                    index = int(round((1-randval) * max_index))
                    chosen = candidates[index]
                    self.enemy_indexes[2] = chosen.index

            return

        for (i, fcount) in enumerate(self.fcounts):
            counts = fcount.old_data['counts']
            candidates = sorted(
                FormationCountObject.every,
                key=lambda fc: (fc.get_distance(counts), fc.signature))
            max_index = len(candidates) - 1
            randval = random.random()
            if self.random_degree > 0:
                randval = randval ** (1 / self.random_degree)
            else:
                randval = 0
            assert 0 <= randval <= 1
            index = int(round(randval * max_index))
            chosen = candidates[index]
            self.counts[i] = chosen.index
            assert self.fcounts[i] is chosen
 def mutate(self):
     if random.choice([True, False]):
         level = max([r for r in self.reqs if 1 <= r <= 8])
     else:
         level = random.randint(1, 4) + random.randint(0, 4)
     newreqs = [level, random.randint(1, level)]
     if self.is_triple:
         newreqs.append(random.randint(1, level))
     random.shuffle(newreqs)
     self.reqs[:len(newreqs)] = newreqs
Example #14
0
 def mutate_all(cls):
     battlefields = [cls.get(i) for i in range(20)]
     everything_else = [c for c in cls.every if c not in battlefields]
     random.shuffle(battlefields)
     random.shuffle(everything_else)
     for o in everything_else + battlefields:
         if hasattr(o, "mutated") and o.mutated:
             continue
         o.mutate()
         o.mutated = True
Example #15
0
 def mutate(self):
     if random.choice([True, False]):
         level = max([r for r in self.reqs if 1 <= r <= 8])
     else:
         level = random.randint(1, 4) + random.randint(0, 4)
     newreqs = [level, random.randint(1, level)]
     if self.is_triple:
         newreqs.append(random.randint(1, level))
     random.shuffle(newreqs)
     self.reqs[:len(newreqs)] = newreqs
Example #16
0
 def mutate_all(cls):
     battlefields = [cls.get(i) for i in range(20)]
     everything_else = [c for c in cls.every if c not in battlefields]
     random.shuffle(battlefields)
     random.shuffle(everything_else)
     for o in everything_else + battlefields:
         if hasattr(o, "mutated") and o.mutated:
             continue
         o.mutate()
         o.mutated = True
Example #17
0
 def shuffle(self):
     random.shuffle(self.common)
     random.shuffle(self.uncommon)
     full = self.common + self.uncommon + self.rare + self.super_rare
     full = shuffle_normal(full, random_degree=self.random_degree)
     self.common = full[:4]
     self.uncommon = full[4:6]
     self.rare = full[6:7]
     self.super_rare = full[7:]
     assert full == (self.common + self.uncommon + self.rare +
                     self.super_rare)
Example #18
0
    def full_randomize(cls):
        super(ShopObject, cls).full_randomize()
        ShopObject.class_reseed("shops")
        types = ["Magic", "Weapons", "Armor", "Items"]
        if 'o' not in get_flags():
            types.remove('Items')
        for pretty_shop_type in types:
            shops = [
                s for s in ShopObject.ranked
                if s.rank > 0 and s.pretty_shop_type == pretty_shop_type
            ]
            itemranks = defaultdict(set)
            all_items = set([])
            avg = 0
            for n, s in enumerate(shops):
                items = [i for i in s.items if i]
                itemranks[n] |= set(items)
                all_items |= set(items)
                avg += len(items)

            magic_shop = pretty_shop_type == "Magic"
            if magic_shop:
                all_items = [SpellPriceObject.get(i) for i in all_items]
            else:
                all_items = [PriceObject.get(i) for i in all_items]
            all_items = sorted(all_items, key=lambda i: (i.rank, i.signature))
            done_items = set([])
            random.shuffle(shops)
            for s in shops:
                s.reseed("wares")
                shop_items = [i for i in s.items if i > 0]
                chosen_items = []
                while len(chosen_items) < len(shop_items):
                    base_index = random.choice(shop_items)
                    candidates = [i for i in all_items if i not in done_items]
                    if not candidates:
                        candidates = list(all_items)
                    candidates = [
                        c for c in candidates if c not in chosen_items
                    ]
                    price = SpellPriceObject.get(
                        base_index) if magic_shop else PriceObject.get(
                            base_index)
                    chosen = price.get_similar(candidates,
                                               override_outsider=True)
                    chosen_items.append(chosen)
                assert len(chosen_items) == len(set(chosen_items))
                chosen_items = sorted(chosen_items,
                                      reverse=True,
                                      key=lambda i: i.price)
                s.items = [c.index for c in chosen_items]
Example #19
0
 def full_randomize(cls):
     super(JobAbilityObject, cls).full_randomize()
     new_groups = defaultdict(list)
     jaos = list(JobAbilityObject.every)
     group_indexes = sorted(set([jao.groupindex for jao in jaos]))
     random.shuffle(jaos)
     while jaos:
         valid_groups = [i for i in group_indexes if not new_groups[i]]
         if not valid_groups:
             valid_groups = [i for i in group_indexes
                             if len(new_groups[i]) < 7]
         index = random.choice(valid_groups)
         jao = jaos.pop()
         jao.groupindex = index
         new_groups[index].append(jao)
Example #20
0
    def randomize_all(cls):
        super(ShopItemObject, cls).randomize_all()

        ShopItemObject.class_reseed('brands')
        ShopItemObject.randomize_brands()

        ShopItemObject.class_reseed('shops')
        to_assign = list(ShopItemObject.every)
        random.shuffle(to_assign)

        shops = defaultdict(list)
        for sio in to_assign:
            sio.reseed('shop')

            candidates = [
                c for c in ShopItemObject.every
                if len(shops[c.old_data['shop_index']]) <= MAX_SHOP_INVENTORY]

            if sio.get_brand() is None:
                temp = [s2 for s2 in candidates
                        if s2.get_brand() is None
                        and type(sio.item) is type(s2.old_item)]
            else:
                temp = [
                    s2 for s2 in candidates
                    if s2.get_brand(old=True) is not None
                    and s2.get_brand(old=True) == sio.get_brand()]

            candidates = temp if temp else candidates

            if shops:
                temp = [c for c in candidates
                        if sio.item not in shops[c.old_data['shop_index']]]
                candidates = temp if temp else candidates

                max_shop = max(shops, key=lambda s: len(shops[s]))
                max_shop_size = len(shops[max_shop])
                if max_shop_size > 0:
                    max_shops = [s for s in shops
                                 if len(shops[s]) >= max_shop_size]
                    temp = [c for c in candidates
                            if c.old_data['shop_index'] not in max_shops]
                    candidates = temp if temp else candidates

            chosen = random.choice(candidates)
            sio.shop_index = chosen.old_data['shop_index']
            shops[sio.shop_index].append(sio.item)
            assert len(shops[sio.shop_index]) <= MAX_SHOP_INVENTORY
Example #21
0
 def intershuffle(cls):
     white_shops = [s for s in cls.ranked if s.shop_type == 5]
     black_shops = [s for s in cls.ranked if s.shop_type == 6]
     for shops in [white_shops, black_shops]:
         wares = []
         for s in shops:
             s.reseed(salt="spell_shuffle")
             shop_wares = s.wares_indexes
             random.shuffle(shop_wares)
             wares.extend(shop_wares)
         wares = shuffle_normal(wares, random_degree=cls.random_degree)
         for s in shops:
             assert len(s.wares_indexes) <= len(wares)
             s.wares_indexes = wares[:len(s.wares_indexes)]
             wares = wares[len(s.wares_indexes):]
         assert len(wares) == 0
Example #22
0
    def shuffle(self):
        spells = [s for s in self.spell_queue if s != 0xFF]
        if spells:
            length = random.randint(len(set(spells)), 8)
            temp = sorted(set(spells))
            while len(temp) < length:
                temp.append(random.choice(spells))
            random.shuffle(temp)
            self.spell_queue = temp

        skills = [s for s in self.skill_queue if s != 0xFF]
        if skills:
            length = random.randint(len(set(skills)), 4)
            temp = sorted(set(skills))
            while len(temp) < length:
                temp.append(random.choice(skills))
            random.shuffle(temp)
            self.skill_queue = temp
Example #23
0
    def randomize_all(cls):
        super(MonsterMeatObject, cls).randomize_all()
        random_degree = MonsterMeatObject.random_degree
        families = list(range(12))
        random.shuffle(families)
        meat_map = {}
        for i, f in enumerate(families):
            meat_classes = [0, 1, 2]
            if random.random() < (random_degree ** 0.5):
                random.shuffle(meat_classes)
                checks = ['a', 'b']
                random.shuffle(checks)
                for check in checks:
                    if check == 'a' and (meat_classes[0] == max(meat_classes)
                            and random.random() > random_degree):
                        meat_classes[:2] == list(reversed(meat_classes[:2]))
                    if check == 'b' and (meat_classes[-1] == min(meat_classes)
                            and random.random() > random_degree):
                        meat_classes[-2:] == list(reversed(meat_classes[-2:]))
            assert len(set(meat_classes)) == 3
            for j, c in enumerate(meat_classes):
                old_value = (f << 4) | c
                new_value = (i << 4) | j
                meat_map[old_value] = new_value

        assert sorted(meat_map.keys()) == sorted(meat_map.values())

        for mmo in MonsterMeatObject.every:
            if (mmo.meat in meat_map
                    and MonsterObject.get(mmo.index).is_monster):
                mmo.meat = meat_map[mmo.meat]
Example #24
0
    def mutate(self):
        consumables = set(range(16, 47))
        weapons = set(range(58, 112))
        weapons |= set([192, 193, 194])
        armors = set(range(49, 58)) | set(range(112, 152))
        armors.add(195)
        tomes = set(range(152, 192))
        for itemset in [consumables, weapons, armors, tomes]:
            if set(self.wares) <= itemset:
                chosen = itemset
                break
        else:
            chosen = consumables | weapons | armors | tomes

        wares = list(self.wares)
        random.shuffle(wares)
        new_wares = []
        for w in wares:
            while True:
                new = ff2_get_similar_item(w,
                                           chosen,
                                           random_degree=self.random_degree)
                if new not in new_wares:
                    new_wares.append(new)
                    break
        assert len(new_wares) == len(wares)
        self.wares = sorted(new_wares)

        new_prices = []
        for w in self.wares:
            prices = sorted(FF2PriceObject.every,
                            key=lambda po: abs(po.price - ff2_get_price(w)))
            chosen = prices[0]
            temp = chosen.get_similar()
            if temp.price >= (ff2_get_price(w) / 2):
                chosen = temp
            new_prices.append(chosen.index)
        assert len(new_prices) == len(self.prices)
        self.prices = new_prices
Example #25
0
def shuffle_char_hues(hues):
    while True:
        tryagain = False
        random.shuffle(hues)
        for c in range(
                0, 18, 3
        ):  #check for too close colors vertically (within one palette)
            chunk = hues[c:c + 3]
            chunk += [h + 360 for h in chunk]
            for i in range(6):
                for j in range(i + 1, 6):
                    if abs(chunk[i] - chunk[j]) <= 16:
                        tryagain = True
                        break
                if tryagain:
                    break
            if tryagain:
                break
        if tryagain:
            continue
        for c in range(
                0, 3
        ):  #check for too close colors horizontally (same element on different palettes)
            chunk = hues[c:len(hues):3]
            chunk += [h + 360 for h in chunk]
            for i in range(12):
                for j in range(i + 1, 12):
                    if abs(chunk[i] - chunk[j]) <= 16:
                        tryagain = True
                        break
                if tryagain:
                    break
            if tryagain:
                break
        if tryagain:
            continue
        break
    return list(map(hue_rgb, hues))
Example #26
0
 def mutate(self):
     if self.shop_type >= 5:
         return
     if self.index == 0x26:
         assert self.shop_type == 4
         assert len(self.wares) == 1
         return
     if self.rank < 0:
         return
     new_wares = []
     candidates = [
         c for c in self.valid_wares if c.old_data["buy_price"] > 2
     ]
     wares = self.wares
     random.shuffle(wares)
     for w in wares:
         while True:
             nw = w.get_similar(candidates,
                                random_degree=self.random_degree)
             if nw in new_wares:
                 nw = random.choice(self.valid_wares)
             if nw not in new_wares:
                 break
         if nw.rank >= 65536:
             price = max(30000, nw.buy_price, nw.sell_price * 2)
             if price < 50000:
                 price *= 2
             price = min(price, 99999)
             price = mutate_normal(price,
                                   0,
                                   99999,
                                   wide=True,
                                   random_degree=nw.random_degree)
             nw.buy_price = price
         new_wares.append(nw)
     self.wares_indexes = sorted([nw.index for nw in new_wares])
Example #27
0
 def mutate_all(self):
     chests = list(self.every)
     random.shuffle(chests)
     random.shuffle(self.desirable_left)
     random.shuffle(self.undesirable_left)
     for o in chests:
         if hasattr(o, "mutated") and o.mutated:
             continue
         o.mutate()
         o.mutated = True
Example #28
0
 def mutate_all(self):
     chests = list(self.every)
     random.shuffle(chests)
     random.shuffle(self.desirable_left)
     random.shuffle(self.undesirable_left)
     for o in chests:
         if hasattr(o, "mutated") and o.mutated:
             continue
         o.mutate()
         o.mutated = True
Example #29
0
    def choose_item(self, aggression=3):
        if hasattr(self, "item_set_in_progress") and self.item_set_in_progress:
            chosen = random.choice(self.item_set_in_progress)
            self.item_set_in_progress.remove(chosen)
            return chosen

        requirements = sorted([
            r for r in self.ranked_requirements if r not in self.assigned_items
            and r not in self.custom_assignments.values()
        ])
        unlocked = {}
        for r in requirements:
            unlocked[r] = self.get_item_unlocked_locations(r)
        candidates = [r for r in requirements if len(unlocked[r]) > 0]

        unused = [r for r in requirements if r not in candidates]
        unused_unlocked = self.get_item_unlocked_locations(unused)
        if unused_unlocked:
            random.shuffle(unused)
            for u in list(unused):
                if u not in unused:
                    continue
                unused.remove(u)
                temp = self.get_item_unlocked_locations(unused)
                if temp:
                    failure = False
                    for key in unlocked:
                        if (set(unlocked[key]) >= set(temp)
                                or (unlocked[key]
                                    and set(unlocked[key]) <= set(temp))):
                            failure = True
                            break
                    if failure:
                        unused = []
                        break
                if not temp:
                    unused.append(u)
            if unused:
                key = tuple(sorted(unused))
                unlocked[key] = self.get_item_unlocked_locations(key)
                candidates.append(key)

        if not candidates:
            return None

        chosen = random.choice(candidates)
        if len(unlocked[chosen]) > 0:
            candidates = [
                r for r in requirements
                if unlocked[r] and unlocked[r] < unlocked[chosen]
                and r not in self.assigned_items
            ]
            if len(candidates) > 0:
                while True:
                    candidates = [
                        c for c in candidates
                        if unlocked[c] and unlocked[c] < unlocked[chosen]
                        and c not in self.assigned_items
                    ]
                    if not candidates:
                        break
                    c = random.choice(candidates)
                    if (chosen in self.preferences
                            and c in self.preferences[chosen]):
                        candidates.remove(c)
                        continue
                    ratio = len(unlocked[c]) / float(len(unlocked[chosen]))
                    ratio = ratio**aggression
                    if random.random() > ratio:
                        chosen = c
                    candidates.remove(c)

        if not isinstance(chosen, basestring):
            self.item_set_in_progress = sorted(chosen)
            return self.choose_item(aggression=aggression)

        return chosen
Example #30
0
def get_palette_transformer(use_luma=False,
                            always=None,
                            middle=True,
                            basepalette=None):
    def get_ratio(a, b):
        if a > 0 and b > 0:
            return max(a, b) / float(min(a, b))
        if abs(a - b) <= 1:
            return 1.0
        return 9999

    def color_to_components(color):
        blue = (color & 0x7c00) >> 10
        green = (color & 0x03e0) >> 5
        red = color & 0x001f
        return (red, green, blue)

    def components_to_color(xxx_todo_changeme):
        (red, green, blue) = xxx_todo_changeme
        return red | (green << 5) | (blue << 10)

    if always is not None and basepalette is not None:
        raise Exception("'always' argument incompatible with 'basepalette'")

    swapmap = {}
    if basepalette is not None and not use_luma:
        threshold = 1.2

        def color_to_index(color):
            red, green, blue = color_to_components(color)
            a = red >= green
            b = red >= blue
            c = green >= blue
            d = get_ratio(red, green) >= threshold
            e = get_ratio(red, blue) >= threshold
            f = get_ratio(green, blue) >= threshold

            index = (d << 2) | (e << 1) | f
            index |= ((a and not d) << 5)
            index |= ((b and not e) << 4)
            index |= ((c and not f) << 3)

            return index

        colordict = defaultdict(set)
        for color in basepalette:
            index = color_to_index(color)
            colordict[index].add(color)

        saturated = dict((k, v) for (k, v) in colordict.items() if k & 0x7)
        satlist = sorted(saturated)
        random.shuffle(satlist)
        grouporder = sorted(satlist,
                            key=lambda k: len(saturated[k]),
                            reverse=True)
        if grouporder:
            dominant = grouporder[0]
            domhue, domsat = dominant >> 3, dominant & 0x7
            for key in grouporder[1:]:
                colhue, colsat = key >> 3, key & 0x7
                if (domhue ^ colhue) & (domsat | colsat) == 0:
                    continue
                secondary = key
                break
            else:
                secondary = dominant
            sechue, secsat = secondary >> 3, secondary & 0x7
        else:
            dominant, domhue, domsat = 0, 0, 0
            secondary, sechue, secsat = 0, 0, 0

        while True:
            domswap = random.randint(0, 7)
            secswap = random.randint(0, 7)
            tertswap = random.randint(0, 7)
            if domswap == secswap:
                continue
            break

        for key in colordict:
            colhue, colsat = key >> 3, key & 0x7
            if ((domhue ^ colhue) & (domsat | colsat)) == 0:
                if ((sechue ^ colhue) & (secsat | colsat)) == 0:
                    swapmap[key] = random.choice([domswap, secswap])
                else:
                    swapmap[key] = domswap
            elif ((sechue ^ colhue) & (secsat | colsat)) == 0:
                swapmap[key] = secswap
            elif ((domhue ^ colhue) & domsat) == 0:
                if ((sechue ^ colhue) & secsat) == 0:
                    swapmap[key] = random.choice([domswap, secswap])
                else:
                    swapmap[key] = domswap
            elif ((sechue ^ colhue) & secsat) == 0:
                swapmap[key] = secswap
            elif ((domhue ^ colhue) & colsat) == 0:
                if ((sechue ^ colhue) & colsat) == 0:
                    swapmap[key] = random.choice([domswap, secswap])
                else:
                    swapmap[key] = domswap
            elif ((sechue ^ colhue) & colsat) == 0:
                swapmap[key] = secswap
            else:
                swapmap[key] = tertswap

    elif basepalette is not None and use_luma:

        def color_to_index(color):
            red, green, blue = color_to_components(color)
            index = red + green + blue
            return index

        values = []
        for color in basepalette:
            index = color_to_index(color)
            values.append(index)
        values = sorted(values)
        low, high = min(values), max(values)
        median = values[len(values) // 2]
        clusters = [set([low]), set([high])]
        done = set([low, high])
        if median not in done and random.choice([True, False]):
            clusters.append(set([median]))
            done.add(median)

        to_cluster = sorted(basepalette)
        random.shuffle(to_cluster)
        for color in to_cluster:
            index = color_to_index(color)
            if index in done:
                continue
            done.add(index)

            def cluster_distance(cluster):
                distances = [abs(index - i) for i in cluster]
                return sum(distances) // len(distances)
                nearest = min(cluster, key=lambda x: abs(x - index))
                return abs(nearest - index)

            chosen = min(clusters, key=cluster_distance)
            chosen.add(index)

        swapmap = {}
        for cluster in clusters:
            swapcode = random.randint(0, 7)
            for index in cluster:
                try:
                    assert index not in swapmap
                except:
                    import pdb
                    pdb.set_trace()
                swapmap[index] = swapcode

        remaining = [i for i in range(94) if i not in swapmap.keys()]
        random.shuffle(remaining)

        def get_nearest_swapcode(index):
            nearest = min(swapmap, key=lambda x: abs(x - index))
            return nearest

        for i in remaining:
            nearest = get_nearest_swapcode(i)
            swapmap[i] = swapmap[nearest]

    else:

        def color_to_index(unused_color):
            return 0

        if always:
            swapmap[0] = random.randint(1, 7)
        else:
            swapmap[0] = random.randint(0, 7)

    for key in swapmap:
        swapmap[key] = generate_swapfunc(swapmap[key])

    if middle:
        degree = utran.randint(-75, 75)

    def palette_transformer(raw_palette, single_bytes=False):
        if single_bytes:
            raw_palette = list(zip(raw_palette, raw_palette[1:]))
            raw_palette = [p for (i, p) in enumerate(raw_palette) if not i % 2]
            raw_palette = [(b << 8) | a for (a, b) in raw_palette]
        transformed = []
        for color in raw_palette:
            index = color_to_index(color)
            swapfunc = swapmap[index]
            red, green, blue = color_to_components(color)
            red, green, blue = swapfunc((red, green, blue))
            if middle:
                red, green, blue = shift_middle((red, green, blue), degree)
            color = components_to_color((red, green, blue))
            transformed.append(color)
        if single_bytes:
            major = [p >> 8 for p in transformed]
            minor = [p & 0xFF for p in transformed]
            transformed = []
            for a, b in zip(minor, major):
                transformed.append(a)
                transformed.append(b)
        return transformed

    return palette_transformer
Example #31
0
def shuffle_key_values(d):
    keys = list(d.keys())
    random.shuffle(keys)
    shuffled = dict(zip(keys, d.values()))
    d.update(shuffled)
Example #32
0
    def full_randomize(cls):
        # fix debug bombs before this
        if hasattr(cls, "after_order"):
            for cls2 in cls.after_order:
                if not (hasattr(cls2, "randomized") and cls2.randomized):
                    raise Exception("Randomize order violated.")
        cls.randomized = True

        assignments = {}

        # phase 1: frog coin shops
        frog_candidates = [i for i in ItemObject.every if i.price and
            (i.rare or i.is_consumable or i.is_accessory) and not i.banned]
        frog_not_rare = [i for i in frog_candidates if not i.rare]
        unfrog = random.randint(
            random.randint(0, len(frog_not_rare)), len(frog_not_rare))
        unfrog = random.sample(frog_not_rare, unfrog)
        for i in sorted(unfrog, key=lambda i2: i2.index):
            frog_candidates.remove(i)
        frog_chosen = random.sample(frog_candidates, 25)
        disciple_shop = 3
        frog_coin_emporium = 6
        one_only = [i for i in frog_chosen if
            (i.is_equipment and bin(i.equippable).count("1") == 1) or
            (i.is_consumable and i.reuseable)]
        num_choose = min(10, len(one_only))
        num_choose = random.randint(random.randint(0, num_choose), num_choose)
        num_choose = min(num_choose, len(one_only))
        chosen = random.sample(one_only, num_choose)
        choose_again = [i for i in frog_chosen if i not in chosen and (
            i in one_only or i.is_equipment)]
        num_choose = 10 - len(chosen)
        num_choose = random.randint(random.randint(0, num_choose), num_choose)
        num_choose = min(num_choose, len(choose_again))
        if num_choose and choose_again:
            chosen += random.sample(choose_again, num_choose)
        num_choose = 10 - len(chosen)
        if num_choose:
            choose_again = [i for i in frog_chosen if i not in chosen]
            random.shuffle(choose_again)
            chosen += choose_again[:num_choose]
        assert len(chosen) == 10
        assignments[disciple_shop] = chosen
        assignments[frog_coin_emporium] = [
            i for i in frog_chosen if i not in chosen]

        # phase 2: non-frog coin shops
        carryover = [i for i in frog_candidates if
                     i not in assignments[disciple_shop] and
                     i not in assignments[frog_coin_emporium]]
        random.shuffle(carryover)
        num_choose = random.randint(0, random.randint(0, len(carryover)))
        carryover = carryover[:num_choose]
        shop_items = carryover + [i for i in ItemObject.every if
                i not in assignments[disciple_shop] and
                i not in assignments[frog_coin_emporium] and
                not i.banned and not i.rare]
        shop_items = sorted(set(shop_items), key=lambda i: i.rank)
        juice_bar_partial = [9, 10, 11]  # full: 12
        special_conditions = {
            0: lambda i: i.is_consumable or (
                i.is_equipment and i.equippable & 0b10001),
            1: lambda i: i.is_consumable,
            2: lambda i: i.is_equipment and i.equippable & 0b11001,
            4: lambda i: i.is_consumable or (
                i.is_equipment and i.equippable & 0b11001),
            8: lambda i: i.is_consumable and (
                (i.misc_attack not in [1, 2, 4, 5] and not
                    i.get_bit("status_nullification")) or i.get_bit("all")),
            12: lambda i: special_conditions[8](i) and not i.reuseable,
            13: lambda i: i.is_weapon,
            14: lambda i: i.is_armor,
            15: lambda i: i.is_accessory,
            16: lambda i: i.is_consumable,
            18: lambda i: i.is_consumable,
            19: lambda i: i.is_equipment,
            20: lambda i: special_conditions[8](i),
            24: lambda i: i.is_consumable,
            }
        done_already = set([])
        for p in range(25):
            if p in juice_bar_partial + [disciple_shop, frog_coin_emporium]:
                continue
            shop = ShopObject.get(p)
            if p == 12:
                num_items = 15
            else:
                num_items = len([i for i in shop.items if i != 0xFF])
                num_items = mutate_normal(num_items, minimum=1, maximum=15)
            valid_items = list(shop_items)
            if p in special_conditions:
                valid_items = [i for i in valid_items
                               if special_conditions[p](i)]
            temp = [i for i in valid_items if i not in done_already or
                    (i.is_consumable and not i.reuseable and not i.rare
                        and not i.get_bit("all")
                        and (i.misc_attack in [1, 2, 4] or
                             i.get_bit("status_nullification")))]
            if temp and p not in [12, 13, 14, 20]:
                valid_items = temp
                extras = [i for i in valid_items if i not in temp]
                extras = random.sample(extras,
                    random.randint(0, len(extras)))
                valid_items = sorted(set(valid_items + extras),
                                     key=lambda i: i.rank)
            assert valid_items
            num_items = min(num_items, len(valid_items))
            if p != 20 and len(valid_items) > num_items:
                valid_items = valid_items[:random.randint(
                    num_items, random.randint(num_items, len(valid_items)))]
                consumables = [i for i in valid_items if i.is_consumable]
                others = [i for i in valid_items if i not in consumables]
                if consumables and others and num_items >= 4:
                    num_con = (random.randint(0, num_items) +
                               random.randint(0, num_items)) / 2
                    num_con = max(num_con, num_items-num_con)
                    num_con = min(num_con, num_items-2)
                    num_oth = num_items-num_con
                    num_con = min(num_con, len(consumables))
                    num_oth = min(num_oth, len(others))
                    valid_items = (random.sample(consumables, num_con) +
                                   random.sample(others, num_oth))
                    num_items = num_con + num_oth
            chosen_items = random.sample(valid_items, num_items)
            assignments[p] = chosen_items
            for i in chosen_items:
                done_already.add(i)

        # phase 2.5: juice bar
        for n, p in enumerate(sorted(juice_bar_partial, reverse=True)):
            n = len(juice_bar_partial) - n
            previous_items = assignments[p+1]
            minimum = n
            maximum = len(previous_items)-1
            average = (minimum + maximum) / 2
            num_items = random.randint(
                random.randint(minimum, average), maximum)
            chosen_items = random.sample(previous_items, num_items)
            assignments[p] = chosen_items

        # phase 3: repricing
        repriced = set([])
        for p, items in assignments.items():
            for item in items:
                if item in repriced:
                    continue
                if p in [disciple_shop, frog_coin_emporium]:
                    item.become_frog_coin_item()
                else:
                    if not item.unbecome_frog_coin_item() and item.rare:
                        PriceObject.get(item.index).price = max(
                            item.price, int(item.rank))
                price = min(999, max(2, item.price))
                price = mutate_normal(price, minimum=2, maximum=999)
                PriceObject.get(item.index).price = price
                repriced.add(item)
        for p, items in assignments.items():
            final = [0xFF] * 15
            items = sorted(items, key=lambda i: ITEM_ORDER.index(i.index))
            final[:len(items)] = [i.index for i in items]
            ShopObject.get(p).items = final

        ShopObject.get(20).set_bit("discount50", True)
Example #33
0
    def full_randomize(cls):
        if hasattr(cls, "after_order"):
            for cls2 in cls.after_order:
                if not (hasattr(cls2, "randomized") and cls2.randomized):
                    raise Exception("Randomize order violated.")
        cls.randomized = True
        curves = defaultdict(list)
        for character_index in range(5):
            c = CharacterObject.get(character_index)
            for attr in LEVEL_STATS:
                value = getattr(c, attr)
                for l in cls.every:
                    if l.character_id == c.index and l.level <= 20:
                        value += getattr(l, attr)
                value = mutate_normal(value, maximum=255)
                fixed_points = [(1, 0), (20, value)]
                for _ in xrange(3):
                    dex = random.randint(1, len(fixed_points)-1)
                    lower_level, lower_value = fixed_points[dex-1]
                    upper_level, upper_value = fixed_points[dex]
                    if upper_level - lower_level < 4:
                        continue
                    level_interval = (upper_level - lower_level) / 2
                    value_interval = (upper_value - lower_value) / 2
                    level = (lower_level + random.randint(0, level_interval)
                             + random.randint(0, level_interval))
                    if level <= lower_level or level >= upper_level:
                        continue
                    value = (lower_value + random.randint(0, value_interval)
                             + random.randint(0, value_interval))
                    fixed_points.append((level, value))
                    fixed_points = sorted(fixed_points)

                for ((l1, v1), (l2, v2)) in zip(fixed_points, fixed_points[1:]):
                    ldist = l2 - l1
                    vdist = v2 - v1
                    for l in range(l1+1, l2):
                        factor = (l - l1) / float(ldist)
                        v = v1 + (factor * vdist)
                        fixed_points.append((l, int(round(v))))
                fixed_points = sorted(fixed_points)
                levels, values = zip(*fixed_points)
                assert len(fixed_points) == 20
                assert levels == tuple(sorted(levels))
                assert values == tuple(sorted(values))
                increases = []
                for v1, v2 in zip(values, values[1:]):
                    increases.append(v2-v1)

                frontload_factor = random.random() * random.random()
                if attr in ["defense", "magic_defense"]:
                    frontload_factor *= random.random()
                frontloaded = 0
                for n, inc in enumerate(increases):
                    max_index = len(increases) - 1
                    factor = (((max_index-n) / float(max_index))
                              * frontload_factor)
                    amount = int(round(inc * factor))
                    frontloaded += amount
                    increases[n] = (inc - amount)
                frontloaded = max(frontloaded, 1)

                while max(increases) > 15:
                    i = increases.index(max(increases))
                    increases[i] = increases[i] - 1
                    choices = [n for (n, v) in enumerate(increases) if v < 15]
                    if random.randint(0, len(choices)) == 0:
                        frontloaded += 1
                    elif choices:
                        i = random.choice(choices)
                        increases[i] = increases[i] + 1

                curves[attr].append((frontloaded, increases))

        for attr in LEVEL_STATS:
            attr_curves = curves[attr]
            random.shuffle(attr_curves)
            for character_index in xrange(5):
                (base, increases) = attr_curves.pop()
                c = CharacterObject.get(character_index)
                if c.index == 0 and attr in ["max_hp", "attack"]:
                    # ensure basic starting stats for Mario
                    while base < 20:
                        base += 1
                        for i in range(len(increases)):
                            if increases[i] > 0:
                                increases[i] = increases[i] - 1
                                break
                getattr(c, attr)
                setattr(c, attr, base)
                assert len(increases) == 19
                for s in StatGrowthObject.every:
                    if s.character_id == c.index:
                        if increases:
                            s.set_stat(attr, increases.pop(0))
                        else:
                            s.set_stat(attr, mutate_normal(2))
Example #34
0
        ]
        kicker = [
            m for m in MonsterObject.every if m.soul_type == 3 and m.soul == 4
        ]
        replaceable = kicker + winged
        headhunter = MonsterObject.get(0x6a)
        legion = MonsterObject.get(0x6c)
        balore = MonsterObject.get(0x6d)
        bosses = [headhunter, legion, balore]

        if hard_mode:
            banned = [(8, 0x05), (6, 0x02)]
        else:
            banned = []

        random.shuffle(bosses)
        for boss in bosses:
            if boss.signature in assigned_locations:
                continue
            if boss is legion:
                locations = [addresses.legion1, addresses.legion2]
                souls = set([(8, 0x03), (8, 0x05), (6, 0x02)])
            elif boss is balore:
                locations = [
                    addresses.balore1, addresses.balore2, addresses.balore3
                ]
                souls = set([(8, 0x03), (8, 0x05), (6, 0x03), (6, 0x02)])
            elif boss is headhunter:
                locations = [
                    addresses.headhunter1, addresses.headhunter4,
                    addresses.headhunter5
Example #35
0
    def randomize_skills_and_attributes(self):
        if self.index in MonsterObject.banned_monster_indexes:
            return

        old_attributes = [AttributeObject.get(i)
                          for i in self.attribute_indexes]
        new_attributes = [o for o in old_attributes if o.rank < 0
                          and o.index != 0xFF]
        old_attributes = [o for o in old_attributes if o.rank >= 0]
        num_attributes = len({a for a in new_attributes + old_attributes})
        num_attributes = mutate_normal(num_attributes, minimum=1, maximum=8,
                                       random_degree=self.random_degree,
                                       wide=True)

        if not old_attributes:
            return

        while len(new_attributes) < num_attributes:
            if len([a for a in new_attributes
                    if a.get_bit('use_battle')]) == 0:
                candidates = [a for a in self.new_family_attributes
                              if a.get_bit('use_battle')]
            elif len([a for a in new_attributes
                      if a.get_bit('use_battle')]) == 7:
                candidates = [a for a in self.new_family_attributes
                              if not a.get_bit('use_battle')]
            else:
                candidates = self.new_family_attributes
            candidates = [c for c in candidates
                          if c not in new_attributes]
            old_attribute = random.choice(old_attributes)
            if not candidates:
                if (old_attribute in new_attributes
                        and len(new_attributes) >= self.num_attributes):
                    break
                new_attribute = old_attribute
            else:
                new_attribute = old_attribute.get_similar(
                    candidates, random_degree=self.random_degree,
                    override_outsider=True)

            if new_attribute not in new_attributes:
                new_attributes.append(new_attribute)

        if not new_attributes:
            return

        use_battle = [a for a in new_attributes if a.get_bit('use_battle')]
        if len(use_battle) >= 8:
            use_battle = use_battle[:7]
        random.shuffle(use_battle)
        no_use = [a for a in new_attributes if not a.get_bit('use_battle')]
        no_use = sorted(no_use)

        candidates = [m for m in MoveSelectionObject.every
                      if m.num_moves == len(use_battle)]
        assert 1 <= len(use_battle) <= 7
        chosen = random.choice(candidates)
        MonsterLevelObject.get(self.index).set_move_selection_index(
            chosen.index)

        self.attribute_indexes = [a.index for a in use_battle + no_use]