Beispiel #1
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
def randomize_battle_animations():
    raise NotImplementedError
    pointers = [1, 2, 7, 0xa, 0xb, 0xc, 0xd]
    pointers = [p + 0xd4000 for p in pointers]
    short = [0, 3, 8, 0xa, 0xc]
    longg = [2, 4, 6]
    special = [0xd, 33]
    restricted = [6]
    f = open(get_outfile(), "r+b")
    for p in pointers:
        if random.choice([True, False]):
            continue
        f.seek(p)
        value = ord(f.read(1))
        container = [l for l in [short, longg] if value in l][0]
        notcontainer = [l for l in [short, longg] if l is not container][0]
        if random.randint(1, 100) == 100:
            # use special
            value = random.choice(special)
        elif random.choice([True, False]):
            # use same type
            value = random.choice(container)
        else:
            # use different type
            candidates = [v for v in notcontainer if v not in restricted]
            value = random.choice(candidates)
        f.seek(p)
        f.write(chr(value))
    f.close()
Beispiel #3
0
    def randomize(self):
        num_items = len(self.items)
        num_items = mutate_normal(num_items, minimum=1, maximum=8,
                                  random_degree=self.random_degree,
                                  wide=True)
        old_items = list(self.items)
        new_items = []
        for _ in range(500):
            if len(new_items) == num_items:
                break
            buyable_check = not (random.random() < self.random_degree)
            chosen_class = random.choice(old_items).shop_item_class
            chosen_price = random.choice(old_items)
            candidates = [a for a in AttributeObject.every
                          if a.index <= 0x7f and a.rank >= 0
                          and a.shop_item_class == chosen_class
                          and a.is_buyable >= buyable_check]
            candidates = [c for c in candidates if c not in new_items]
            if not candidates:
                continue
            chosen = chosen_price.get_similar(
                    candidates=candidates, random_degree=self.random_degree,
                    override_outsider=True)
            new_items.append(chosen)
        else:
            raise Exception('Unable to populate shop.')

        for i in new_items:
            if not i.is_buyable:
                ItemPriceObject.get(i.index).price = 60000

        self.item_indexes = [i.index for i in new_items]
def randomize_battle_animations():
    raise NotImplementedError
    pointers = [1, 2, 7, 0xa, 0xb, 0xc, 0xd]
    pointers = [p + 0xd4000 for p in pointers]
    short = [0, 3, 8, 0xa, 0xc]
    longg = [2, 4, 6]
    special = [0xd, 33]
    restricted = [6]
    f = open(get_outfile(), "r+b")
    for p in pointers:
        if random.choice([True, False]):
            continue
        f.seek(p)
        value = ord(f.read(1))
        container = [l for l in [short, longg] if value in l][0]
        notcontainer = [l for l in [short, longg] if l is not container][0]
        if random.randint(1, 100) == 100:
            # use special
            value = random.choice(special)
        elif random.choice([True, False]):
            # use same type
            value = random.choice(container)
        else:
            # use different type
            candidates = [v for v in notcontainer if v not in restricted]
            value = random.choice(candidates)
        f.seek(p)
        f.write(chr(value))
    f.close()
Beispiel #5
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 intershuffle(cls):
        for e in cls.every:
            if e.rank < 0:
                continue

            for i in xrange(4):
                e2 = e.get_similar(random_degree=cls.random_degree**2)
                chosen = random.choice((e2.old_data["common"] * 2) +
                                       e2.old_data["uncommon"])
                e.common[i] = chosen

            for i in xrange(2):
                e2 = e.get_similar(random_degree=cls.random_degree)
                chosen = random.choice(e2.old_data["common"] +
                                       (e2.old_data["uncommon"] * 4) +
                                       (e2.old_data["rare"] * 4))
                e.uncommon[i] = chosen

            e2 = e.get_similar(random_degree=cls.random_degree**0.5)
            chosen = random.choice(e2.old_data["uncommon"] +
                                   (e2.old_data["rare"] * 4) +
                                   (e2.old_data["super_rare"] * 2))
            e.rare[0] = chosen

            e2 = e.get_similar(random_degree=cls.random_degree**0.25)
            chosen = random.choice(e2.old_data["rare"] +
                                   (e2.old_data["super_rare"] * 2))
            e.super_rare[0] = chosen
Beispiel #7
0
    def choose_requirements(self):
        if not hasattr(self, "old_goal_requirements"):
            self.old_goal_requirements = None

        candidates = sorted([
            r for r in self.requirements_locations
            if self.requirements_locations[r] & self.unreachable_locations
        ])
        if not candidates:
            self.goal_requirements = None
            return None
        if self.goal_requirements in candidates:
            return self.goal_requirements

        candidates += [c for c in candidates if set(c) & self.assigned_items]
        candidates = sorted(candidates)
        chosen = random.choice(candidates)
        while True:
            candidates = [
                c for c in candidates
                if len(c) > len(chosen) and self.requirements_locations[c] <
                self.requirements_locations[chosen]
            ]
            if candidates:
                newchoice = random.choice(candidates + [chosen])
                if newchoice != chosen:
                    chosen = newchoice
                    continue
            break

        if self.goal_requirements != chosen:
            self.old_goal_requirements = self.goal_requirements
            self.goal_requirements = chosen
        return chosen
    def mutate(self):
        oldstats = {}
        for key in self.mutate_attributes:
            oldstats[key] = getattr(self, key)
        super(MonsterObject, self).mutate()
        if self.get_bit("bosslike"):
            for (attr, oldval) in oldstats.items():
                if getattr(self, attr) < oldval:
                    setattr(self, attr, oldval)

        def is_resistance(val):
            return val >= 128 or val in [0, 1, 2]

        elements = ["fire", "water", "lightning", "shadow"]

        while random.choice([True, False]):
            el = random.choice(elements)
            if getattr(self, el) != 4 and random.choice([True, False]):
                continue
            value = random.choice(
                [0, 1, 2, 3, 4, 6, 8, 64, 128, 129, 132, 143])
            if is_resistance(value) and not is_resistance(getattr(self, el)):
                for e in elements:
                    if e == el:
                        continue
                    if not is_resistance(getattr(self, e)):
                        break
                else:
                    continue
            setattr(self, el, value)
    def mutate(self):
        oldstats = {}
        for key in self.mutate_attributes:
            oldstats[key] = getattr(self, key)
        super(MonsterObject, self).mutate()
        if self.get_bit("bosslike"):
            for (attr, oldval) in oldstats.items():
                if getattr(self, attr) < oldval:
                    setattr(self, attr, oldval)

        def is_resistance(val):
            return val >= 128 or val in [0, 1, 2]
        elements = ["fire", "water", "lightning", "shadow"]

        while random.choice([True, False]):
            el = random.choice(elements)
            if getattr(self, el) != 4 and random.choice([True, False]):
                continue
            value = random.choice([0, 1, 2, 3, 4, 6, 8, 64,
                                   128, 129, 132, 143])
            if is_resistance(value) and not is_resistance(getattr(self, el)):
                for e in elements:
                    if e == el:
                        continue
                    if not is_resistance(getattr(self, e)):
                        break
                else:
                    continue
            setattr(self, el, value)
Beispiel #10
0
    def randomize(self):
        if self.index == 6:
            # berserker passive
            candidates = [
                jao.ability for jao in JobAbilityObject.groups[self.index]
                if jao.ability > 0x4D
            ]
            if candidates:
                self.commands[1] = random.choice(candidates)
            return

        if self.index > 20:
            return

        old_commands = list(self.commands)
        candidates = [
            jao.ability for jao in JobAbilityObject.groups[self.index]
            if jao.ability <= 0x4D
        ]
        if self.index == 20:
            candidates += [5, 2]

        redundant_groups = [
            range(0x2C, 0x32),
            range(0x32, 0x38),
            range(0x38, 0x3E),
            range(0x3E, 0x44),
        ]
        for i, ability in enumerate(self.commands):
            if not candidates:
                break
            if "fight" in get_activated_codes() and ability == 5:
                pass
            elif ability > 0 and random.random() <= (self.random_degree**0.75):
                new_command = random.choice(candidates)
                if new_command in self.commands:
                    continue
                self.commands[i] = new_command
                for rg in redundant_groups:
                    if len(set(self.commands) & set(rg)) >= 2:
                        self.commands[i] = ability
                        break
                else:
                    candidates.remove(new_command)
            if ability in candidates:
                candidates.remove(ability)
        while not set(self.commands) & set([5, 0x2b, 2]):
            i, c = random.choice(sorted(enumerate(old_commands)))
            if c in [5, 0x2b, 2]:
                self.commands[i] = c
        for rg in redundant_groups:
            if len(set(self.commands) & set(rg)) >= 2:
                assert False
Beispiel #11
0
    def become_boss(self):
        flamerus_rank = MonsterObject.get(0x4a).rank
        battlefields = [
            bf for bf in BattleFormationObject.ranked if bf.index < 20
        ]
        my_index = battlefields.index(self)
        candidates = [
            m for m in MonsterObject.ranked if m.rank >= flamerus_rank
        ]
        new_index = int(round(my_index * (len(candidates) / 20.0)))
        new_index = mutate_normal(new_index,
                                  minimum=0,
                                  maximum=len(candidates) - 1)
        leader = candidates[new_index]
        candidates = [m for m in MonsterObject.ranked if m.rank < leader.rank]
        max_index = len(candidates) - 1
        follow_index = random.randint(random.randint(0, max_index), max_index)
        follower = candidates[follow_index].index
        if random.randint(0, max_index) >= follow_index:
            follow2_index = random.randint(
                random.randint(max_index - follow_index, max_index), max_index)
            follower2 = candidates[follow2_index].index
            new_ids = [follower, leader.index, follower2]
        else:
            new_ids = [leader.index, follower, 0xFF]
        f = FormationObject.get_unused()
        f.special_boss = True
        f.enemy_ids = new_ids
        self.formation_ids = [f.index] * 3
        f.mutated = True
        br = BattleRoundsObject.get(self.index)
        br.num_rounds = 1
        br.mutated = True

        if "t" not in get_flags():
            return
        br2 = BattleRewardObject.get(self.index)
        br2.reward = 0x4000
        done_items = [
            t.reward & 0xFF for t in BattleRewardObject.every
            if hasattr(t, "mutated") and t.mutated and t.reward & 0x4000
        ]
        if TreasureIndexObject.well_hidden:
            value = random.choice(sorted(TreasureIndexObject.well_hidden))
            TreasureIndexObject.well_hidden.remove(value)
        else:
            value = random.choice([
                i for i in DESIRABLE_ITEMS if i != 0x14 and i not in done_items
            ])
        br2.reward |= value
        br2.mutated = True
    def mutate_stat_curve(cls, class_index, attr):
        lus = [
            lu for lu in LevelUpObject.every if lu.class_index == class_index
        ]
        assert len(lus) == 99
        lus = lus[:98]
        assert len(lus) == 98

        lus[0].reseed(salt="fullmut" + attr)
        bits = [lu.get_bit(attr) for lu in lus]
        value = len([b for b in bits if b])
        base_ratio = value / float(len(lus))
        max_ratio = max([
            cls.get_class_stat_score(i, attr) / float(len(lus))
            for i in xrange(6)
        ])
        assert max_ratio >= base_ratio
        base_ratio = mutate_normal(base_ratio,
                                   0,
                                   max_ratio,
                                   wide=False,
                                   random_degree=LevelUpObject.random_degree,
                                   return_float=True)
        remaining = list(lus)
        while remaining:
            ratio = mutate_normal(base_ratio,
                                  0,
                                  max_ratio,
                                  wide=False,
                                  random_degree=LevelUpObject.random_degree,
                                  return_float=True)
            max_index = len(remaining) - 1
            divider = random.randint(0, max_index)
            aa = remaining[:divider]
            bb = remaining[divider:]

            if len(aa) > len(bb):
                aa, bb = bb, aa
            elif len(aa) == len(bb) and random.choice([True, False]):
                aa, bb = bb, aa
            if random.choice([True, True, False]):
                to_set, remaining = aa, bb
            else:
                to_set, remaining = bb, aa

            assert len(to_set + remaining) == max_index + 1
            for lu in to_set:
                value = (random.random() < ratio)
                lu.set_bit(attr, value)
Beispiel #13
0
 def nudge_hue(hue):  #designed for 'pure' hue: one 31, one 0, one anything
     new_color = hue[:]
     if len([h for h in hue if h not in [0, 31]]) > 0:
         new_color = [(h if h in [0, 31] else h + random.randint(-2, 2))
                      for h in hue]
     elif len([h for h in hue if h == 31]) >= 2:
         nudge_idx = random.choice(
             [i for i, h in enumerate(hue) if h == 31])
         new_color[nudge_idx] -= random.randint(0, 3)
     elif 0 in hue:
         nudge_idx = random.choice([i for i, h in enumerate(hue) if h == 0])
         new_color[nudge_idx] += random.randint(0, 3)
     new_color = [(c if c <= 31 else 31) for c in new_color]
     new_color = [(c if c >= 0 else 0) for c in new_color]  # just in case
     return new_color
Beispiel #14
0
    def mutate(self):
        for attr in ["steal_common", "steal_rare",
                      "drop_common", "drop_rare"]:
            value = getattr(self, attr)
            if value > 0 and item_is_buyable(value):
                price = PriceObject.get(value).price
                setattr(self, attr, get_item_similar_price(price))

        if random.choice([True, False]):
            if random.choice([True, False]):
                self.steal_common, self.drop_common = (self.drop_common,
                                                       self.steal_common)
            if random.choice([True, False]):
                self.steal_rare, self.drop_rare = (self.drop_rare,
                                                   self.steal_rare)
 def mutate(self):
     if self.misc in [2, 4] and self.contents < 0x10:
         return
     partner = random.choice(FF2ChestObject.every)
     assert self.misc in [1, 2, 4]
     assert partner.misc in [1, 2, 4]
     if partner.misc == 1:
         if self.misc == 1:
             value = self.contents
         else:
             value = ff2_get_price(self.contents)
         self.misc = 1
         value = min(65000, max(0, value))
         self.contents = mutate_normal(value,
                                       0,
                                       65000,
                                       wide=True,
                                       random_degree=self.random_degree)
     else:
         if self.misc == 1:
             item = ff2_get_item_valued(self.contents)
             self.misc = 2
         else:
             item = self.contents
         item = ff2_get_similar_item(item, random_degree=self.random_degree)
         self.contents = item
     assert self.misc in [1, 2, 4]
Beispiel #16
0
 def randomize(self):
     if self.monster.morph_chance and not self.monster.banned:
         self.yoshi_cookie = random.choice(
             [i for i in ItemObject.every
              if i.is_consumable and not i.banned]).index
     else:
         self.yoshi_cookie = 0xFF
Beispiel #17
0
    def randomize_all(cls):
        attributes = [AttributeObject.get(m.skill_index)
                      for m in MutantSkillsObject.every]
        new_attributes = []
        for old_attribute in attributes:
            candidates = [a for a in AttributeObject.every
                          if a.get_bit('fixed') and a.rank >= 0
                          and a not in new_attributes]
            if old_attribute not in candidates:
                if old_attribute.get_bit('fixed'):
                    # vanilla doesn't have non-fixed attributes
                    # this is for romhack compatibility
                    assert old_attribute in new_attributes

            template = random.choice(attributes)
            temp = [c for c in candidates if
                    c.get_bit('use_battle') == template.get_bit('use_battle')]
            if temp:
                candidates = temp

            new_attribute = old_attribute.get_similar(
                candidates, random_degree=MutantSkillsObject.random_degree,
                override_outsider=True)
            new_attributes.append(new_attribute)

        assert len(new_attributes) == len(MutantSkillsObject.every)
        for new, mu in zip(new_attributes, MutantSkillsObject.every):
            mu.skill_index = new.index

        super(MutantSkillsObject, cls).randomize_all()
    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
Beispiel #19
0
 def full_cleanup(cls):
     if 'e' in get_flags():
         rope_candidates = [
             i for i in ItemObject.every if 0x12d7a <= i.pointer <= 0x12da6
         ]
         if not any([i.item_type == 0xd for i in rope_candidates]):
             chosen = random.choice(rope_candidates)
             chosen.item_type = 0xd
         else:
             chosen = random.choice(
                 [i for i in rope_candidates if i.item_type == 0xd])
         rope_candidates.remove(chosen)
         if not any([i.item_type == 0xc for i in rope_candidates]):
             chosen = random.choice(rope_candidates)
             chosen.item_type = 0xc
     super(ItemObject, cls).full_cleanup()
Beispiel #20
0
def randomize_file_select():
    if get_global_label() == "SMRPG_NA":
        addresses = [0x34757, 0x3489a, 0x34ee7, 0x340aa, 0x3501e]
    elif get_global_label() == "SMRPG_JP":
        addresses = [0x347d7, 0x3490d, 0x34f59, 0x340fa, 0x35099]
    else:
        return
    choices = {"peach": range(7, 13),
               "bowser": range(13, 19),
               "mallow": range(19, 25),
               "geno": range(25, 31),
               }
    values = random.choice(choices.values())
    values = [values[i] for i in [0, 1, 0, 0, 1]]
    f = open(get_outfile(), "r+b")
    for addr, value in zip(addresses, values):
        f.seek(addr)
        f.write(chr(value))

    if get_global_label() != "SMRPG_NA":
        return
    f.seek(0x3EF140)
    seed = str(get_seed()).center(10)
    f.write(seed)
    f.close()
    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
Beispiel #22
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
Beispiel #23
0
    def mutate(self):
        global chest_items
        if self.is_key:
            return

        if self.index in [0x6A, 0x6B, 0x6C, 0x6E]:
            self.contents = 0x2A
            return

        any_left = self.desirable_left + self.undesirable_left
        value = None
        if self.is_consumable and (not any_left or random.randint(1, 7) != 7):
            self.contents = random.choice(self.consumable_options)
            return
        elif self.is_consumable:
            if self.undesirable_left and (
                    not self.desirable_left or random.randint(1, 10) != 10):
                value = self.undesirable_left.pop()
            else:
                value = self.desirable_left.pop()

        if value is None:
            if self.desirable_left:
                value = self.desirable_left.pop()
            elif self.undesirable_left:
                value = self.undesirable_left.pop()
            else:
                value = 0x12  # seed

        if (value not in [0x12, 0x14] and value in DESIRABLE_ITEMS
                and self.is_consumable):
            self.well_hidden.add(value)
        self.contents = value
Beispiel #24
0
    def mutate(self):
        global chest_items
        if self.is_key:
            return

        if self.index in [0x6A, 0x6B, 0x6C, 0x6E]:
            self.contents = 0x2A
            return

        any_left = self.desirable_left + self.undesirable_left
        value = None
        if self.is_consumable and (not any_left or random.randint(1, 7) != 7):
            self.contents = random.choice(self.consumable_options)
            return
        elif self.is_consumable:
            if self.undesirable_left and (not self.desirable_left
                                          or random.randint(1, 10) != 10):
                value = self.undesirable_left.pop()
            else:
                value = self.desirable_left.pop()

        if value is None:
            if self.desirable_left:
                value = self.desirable_left.pop()
            elif self.undesirable_left:
                value = self.undesirable_left.pop()
            else:
                value = 0x12  # seed

        if (value not in [0x12, 0x14] and value in DESIRABLE_ITEMS
                and self.is_consumable):
            self.well_hidden.add(value)
        self.contents = value
Beispiel #25
0
    def become_boss(self):
        flamerus_rank = MonsterObject.get(0x4a).rank
        battlefields = [bf for bf in BattleFormationObject.ranked
                        if bf.index < 20]
        my_index = battlefields.index(self)
        candidates = [m for m in MonsterObject.ranked
                      if m.rank >= flamerus_rank]
        new_index = int(round(my_index * (len(candidates) / 20.0)))
        new_index = mutate_normal(new_index, minimum=0,
                                  maximum=len(candidates)-1)
        leader = candidates[new_index]
        candidates = [m for m in MonsterObject.ranked
                      if m.rank < leader.rank]
        max_index = len(candidates)-1
        follow_index = random.randint(random.randint(0, max_index), max_index)
        follower = candidates[follow_index].index
        if random.randint(0, max_index) >= follow_index:
            follow2_index = random.randint(
                random.randint(max_index-follow_index, max_index), max_index)
            follower2 = candidates[follow2_index].index
            new_ids = [follower, leader.index, follower2]
        else:
            new_ids = [leader.index, follower, 0xFF]
        f = FormationObject.get_unused()
        f.special_boss = True
        f.enemy_ids = new_ids
        self.formation_ids = [f.index] * 3
        f.mutated = True
        br = BattleRoundsObject.get(self.index)
        br.num_rounds = 1
        br.mutated = True

        if "t" not in get_flags():
            return
        br2 = BattleRewardObject.get(self.index)
        br2.reward = 0x4000
        done_items = [t.reward & 0xFF for t in BattleRewardObject.every
                      if hasattr(t, "mutated") and t.mutated
                      and t.reward & 0x4000]
        if TreasureIndexObject.well_hidden:
            value = random.choice(sorted(TreasureIndexObject.well_hidden))
            TreasureIndexObject.well_hidden.remove(value)
        else:
            value = random.choice([i for i in DESIRABLE_ITEMS
                                   if i != 0x14 and i not in done_items])
        br2.reward |= value
        br2.mutated = True
Beispiel #26
0
    def randomize(self):
        if self.index == 6:
            candidates = [jao.ability for jao in
                          JobAbilityObject.groups[self.index]
                          if jao.ability > 0x4D]
            if candidates:
                self.commands[1] = random.choice(candidates)
            return

        if self.index > 20:
            return

        old_commands = list(self.commands)
        candidates = [jao.ability for jao in
                      JobAbilityObject.groups[self.index]
                      if jao.ability <= 0x4D]
        if self.index == 20:
            candidates += [5, 2]

        redundant_groups = [
                range(0x2C, 0x32),
                range(0x32, 0x38),
                range(0x38, 0x3E),
                range(0x3E, 0x44),
                ]
        for i, ability in enumerate(self.commands):
            if not candidates:
                break
            if ability > 0 and random.randint(1, 3) == 3:
                new_command = random.choice(candidates)
                if new_command in self.commands:
                    continue
                self.commands[i] = new_command
                for rg in redundant_groups:
                    if len(set(self.commands) & set(rg)) >= 2:
                        self.commands[i] = ability
                        break
                else:
                    candidates.remove(new_command)
            if ability in candidates:
                candidates.remove(ability)
        if not set(self.commands) & set([5, 0x2b, 2]):
            self.commands = old_commands
        for rg in redundant_groups:
            if len(set(self.commands) & set(rg)) >= 2:
                assert False
 def mutate_all(cls):
     for group in cls.groups.values():
         for o in group:
             while o.level >= 100 or o.level == 0:
                 other = random.choice(group)
                 o.level = random.randint(2, random.randint(2, 99))
                 o.increase = max(1, other.increase)
             o.mutate()
 def mutate_all(cls):
     for group in cls.groups.values():
         for o in group:
             while o.level >= 100 or o.level == 0:
                 other = random.choice(group)
                 o.level = random.randint(2, random.randint(2, 99))
                 o.increase = max(1, other.increase)
             o.mutate()
Beispiel #29
0
        def ensure_item_access(index, day):
            item = ItemObject.get_by_index(index)
            ensure_shops = sorted(day_shops[day])

            existing_this = [sio for sio in ShopItemObject.every
                             if sio.item is item
                             and not hasattr(sio, '_is_protected')]
            if existing_this:
                chosen = random.choice(existing_this)
            else:
                shuffled_shop_items = sorted(
                    ShopItemObject.every,
                    key=lambda sio: (not hasattr(sio, '_is_protected'),
                                     sio.signature))
                seen_items = set([])
                chosen = None
                for sio in shuffled_shop_items:
                    if (sio.item in seen_items
                            and not hasattr(sio, '_is_protected')):
                        chosen = sio
                        break
                    seen_items.add(sio.item)
                chosen.shop_index = None

            chosen.day_available = min(day, chosen.day_available)
            chosen.item_index = index
            assert not hasattr(chosen, '_is_protected')
            chosen._is_protected = True
            if chosen.shop_index in ensure_shops:
                return True

            ensure_shops = sorted(ensure_shops)
            temp = [s for s in ensure_shops
                    if len(ShopItemObject.get_items_by_shop_index(s))
                    < MAX_SHOP_INVENTORY]
            if temp:
                ensure_shops = temp

            if hasattr(item, 'brand') and item.brand <= 12:
                temp = [s for s in ensure_shops
                        if ShopItemObject.get_primary_brand(s) == item.brand]
                if temp:
                    ensure_shops = temp

            chosen.shop_index = random.choice(ensure_shops)
Beispiel #30
0
 def insert_item(cls, item_type, item_index):
     candidates = [
         s for s in ShopIndexObject.every if hasattr(s, "shop_rank")
         and s.shop_rank == 3 and not s.inserted_item
     ]
     chosen = random.choice(candidates)
     chosen.inserted_item = True
     chosen.item_type = item_type
     chosen.item_index = item_index
    def cleanup(self):
        growth = CharGrowthObject.get(self.index)
        for attr in ["power", "stamina", "magic", "hit",
                     "evade", "mdef"]:
            baseattr = "%s_base" % attr
            increase = getattr(growth, attr) * (self.level-1) / 100
            initial = getattr(self, baseattr) + increase
            setattr(self, attr, initial)

        hpgroup = HPGrowthObject.getgroup(self.index)
        mpgroup = MPGrowthObject.getgroup(self.index)
        max_hp = mutate_normal(85, minimum=1, maximum=999,
                               random_degree=self.random_degree)
        max_mp = mutate_normal(9, minimum=1, maximum=99,
                               random_degree=self.random_degree)
        temp_level = 1
        while temp_level < self.level:
            temp_level += 1
            hpo = [o for o in hpgroup if temp_level <= o.level][-1]
            mpo = [o for o in mpgroup if temp_level <= o.level][-1]
            max_hp += hpo.increase
            max_mp += mpo.increase
        max_hp = min(999, max(max_hp, 1))
        max_mp = min(99, max(max_mp, 1))
        self.max_hp, self.hp = max_hp, max_hp
        self.max_mp, self.mp = max_mp, max_mp

        if self.level > 1:
            self.xp = sum([e.experience for e in ExperienceObject
                           if e.index < (self.level-1)])
        else:
            self.xp = 0
        self.xpnext = ExperienceObject.get(self.level-1).experience

        for attr in ["helmet", "armor"]:
            current = getattr(self, attr)
            if self.can_equip(current):
                continue
            candidates = [c for c in ItemObject.every_equippable
                          if getattr(c, "is_%s" % attr) and
                          self.can_equip(c) and
                          c.buyable]
            if not candidates:
                candidates = [c for c in ItemObject.every_equippable
                              if getattr(c, "is_%s" % attr) and
                              c.buyable]
            chosen = min(candidates, key=lambda c: c.rank_price)
            chosen.make_equippable(self.index)
            setattr(self, attr, chosen.full_index)
        current = ItemObject.get(self.accessory)
        if not self.can_equip(current):
            candidates = [c for c in Accessory2Object.every
                          if self.can_equip(c)]
            if candidates:
                chosen = random.choice(candidates)
                chosen.make_equippable(self.index)
                self.accessory = chosen.full_index
    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
Beispiel #33
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
Beispiel #35
0
 def mutate(self):
     valids = [s for s in StatBonusObject.every if s.intershuffle_valid and
               all([getattr(s, attr)
                    for attr in self.intershuffle_attributes])]
     for attr in self.intershuffle_attributes:
         while getattr(self, attr) == 0:
             setattr(self, attr, getattr(random.choice(valids), attr))
     for attr in LEVEL_STATS:
         self.set_stat(attr, mutate_normal(
             getattr(self, attr), minimum=0, maximum=0xf))
Beispiel #36
0
    def mutate(self):
        if self.is_item and self.value == 0x14:
            # Exit battlefield is fixed
            return

        self.reward = 0
        done_items = [
            t.reward & 0xFF for t in BattleRewardObject.every
            if hasattr(t, "mutated") and t.mutated and t.reward & 0x4000
        ]
        assert len(done_items) == len(set(done_items))
        if TreasureIndexObject.desirable_left:
            value = TreasureIndexObject.desirable_left.pop()
            if value == 0x14 and TreasureIndexObject.desirable_left:
                value = TreasureIndexObject.desirable_left.pop()
            if value != 0x14:
                self.reward |= 0x4000
                self.reward |= value
        if TreasureIndexObject.undesirable_left:
            remaining = [
                i for i in TreasureIndexObject.undesirable_left
                if i not in BROKEN_ITEMS
            ]
            if remaining:
                value = remaining.pop()
                self.reward |= 0x4000
                self.reward |= value
                TreasureIndexObject.undesirable_left.remove(value)

        if self.reward == 0:
            rewardtype = random.choice(["xp", "xp", "item", "gp"])
            if rewardtype == "item":
                self.reward |= 0x4000
                self.reward |= random.choice(
                    sorted(set(DESIRABLE_ITEMS + UNDESIRABLE_ITEMS)))
            else:
                if rewardtype == "xp":
                    self.reward |= 0x8000
                self.reward |= random.randint(1, 0x3FF)

        if self.reward & 0x4000 and (self.reward & 0xFF) in done_items:
            self.reward = 0
            return self.mutate()
 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
Beispiel #38
0
 def mutate(self):
     for attr in ["common_drop", "rare_drop"]:
         value = getattr(self, attr)
         if value == 0:
             continue
         while True:
             i = ItemObject.superget(value - 1)
             i = i.get_similar()
             if ("fam" in get_activated_codes() and i.item_type == 2
                     and i.index in HP_HEALING_ITEMS):
                 continue
             if ("gun" in get_activated_codes() and i.item_type == 3):
                 i = WeaponObject.get(random.choice(GUNS))
             if ("fist" in get_activated_codes() and i.item_type == 3):
                 i = WeaponObject.get(random.choice(FISTS))
             if ("ass" in get_activated_codes() and i.item_type == 3):
                 i = WeaponObject.get(random.choice(KNIVES))
             value = (value & 0xFF00) | (i.superindex + 1)
             setattr(self, attr, value)
             break
 def get_similar(self):
     if self.rare:
         result = random.choice(self.every_rare)
     elif self.buyable:
         buyables = self.every_buyable
         index = buyables.index(self)
         index = mutate_normal(index, minimum=0, maximum=len(buyables)-1,
                               random_degree=self.random_degree)
         result = buyables[index]
     else:
         result = self
     return result
Beispiel #40
0
    def mutate(self):
        if self.is_item and self.value == 0x14:
            # Exit battlefield is fixed
            return

        self.reward = 0
        done_items = [t.reward & 0xFF for t in BattleRewardObject.every
                      if hasattr(t, "mutated") and t.mutated
                      and t.reward & 0x4000]
        assert len(done_items) == len(set(done_items))
        if TreasureIndexObject.desirable_left:
            value = TreasureIndexObject.desirable_left.pop()
            if value == 0x14 and TreasureIndexObject.desirable_left:
                value = TreasureIndexObject.desirable_left.pop()
            if value != 0x14:
                self.reward |= 0x4000
                self.reward |= value
        if TreasureIndexObject.undesirable_left:
            remaining = [i for i in TreasureIndexObject.undesirable_left
                         if i not in BROKEN_ITEMS]
            if remaining:
                value = remaining.pop()
                self.reward |= 0x4000
                self.reward |= value
                TreasureIndexObject.undesirable_left.remove(value)

        if self.reward == 0:
            rewardtype = random.choice(["xp", "xp", "item", "gp"])
            if rewardtype == "item":
                self.reward |= 0x4000
                self.reward |= random.choice(
                    sorted(set(DESIRABLE_ITEMS + UNDESIRABLE_ITEMS)))
            else:
                if rewardtype == "xp":
                    self.reward |= 0x8000
                self.reward |= random.randint(1, 0x3FF)

        if self.reward & 0x4000 and (self.reward & 0xFF) in done_items:
            self.reward = 0
            return self.mutate()
Beispiel #41
0
 def mutate(self):
     if self.index == 0x42:
         # Behemoth
         return
     oldstats = {}
     for key in self.mutate_attributes:
         oldstats[key] = getattr(self, key)
     super(MonsterObject, self).mutate()
     if self.is_boss:
         for (attr, oldval) in oldstats.items():
             if getattr(self, attr) < oldval:
                 setattr(self, attr, oldval)
     for attr in ["resistances", "weaknesses", "immunities"]:
         if self.is_boss and attr == "immunities":
             continue
         value = getattr(self, attr) >> 4
         value = shuffle_bits(value, size=4) << 4
     while random.choice([True, False]):
         attr = random.choice(["resistances", "weaknesses", "immunities"])
         value = getattr(self, attr)
         if attr != "immunities" and bin(value).count("1") > 6:
             continue
         flag = (1 << random.randint(0, 7))
         if ((attr == "weaknesses" or not self.is_boss) and
                 random.randint(1, 10) == 10):
             value ^= flag
         else:
             if attr != "immunities" and bin(value).count("1") > 4:
                 continue
             value |= flag
         setattr(self, attr, value)
     self.resistances = self.resistances & 0xF0
     if self.hp < 200 or self.index in [0x43, 0x4a]:
         return
     if random.randint(1, 4) == 4:
         self.counter &= 0x0F
         newcounter = random.choice([0, 0, 0x10, 0x20, 0x40, 0x80, 0x80])
         self.counter |= newcounter
Beispiel #42
0
    def mutate(self):
        if not self.unused:
            self.find_unused()
        old_ids = list(self.enemy_ids)
        if self.is_boss:
            boss = self.leader
            boss_index = boss.index
            if boss_index == 0x50:
                return
            new = []
            upper = self.leader.rank
            for e in self.enemy_ids:
                if e == boss_index:
                    continue
                if e == 0xFF and random.choice([True, False]):
                    continue
                if e == 0xFF:
                    lower = 0
                else:
                    lower = MonsterObject.get(e).rank
                candidates = [m for m in MonsterObject.ranked
                              if lower <= m.rank < upper
                              and m.index not in self.banned_bosses]
                if not candidates:
                    return
                upper_index = max(len(candidates)-2, 0)
                index = random.randint(0, upper_index)
                index = random.randint(index/2, index)
                chosen = candidates[index]
                upper = min(upper, chosen.rank)
                new.append(chosen.index)
            if len(new) == 2:
                new = [new[0], boss_index, new[1]]
            else:
                new = new + [boss_index]
            while len(new) < 3:
                new += [0xFF]
            self.enemy_ids = new
            return

        if len(self.enemies) <= 1:
            return

        for i, e in enumerate(self.enemies):
            if len(self.enemies) >= 2 and i == 1:
                continue
            elif len(self.enemies) == 1:
                continue
            new = e.get_similar()
            if new.index in self.banned_bosses:
                continue
            if new in self.done_bosses and random.randint(1, 10) != 10:
                continue
            self.enemy_ids[i] = new.index
            if new.is_boss:
                self.done_bosses.add(new)

        new_tuple = sorted(tuple(self.enemy_ids))
        if new_tuple == sorted(tuple(old_ids)):
            return
        for f in FormationObject.every:
            if f.index == self.index:
                continue
            if sorted(tuple(f.enemy_ids)) == new_tuple:
                self.enemy_ids = old_ids
                break