Example #1
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_spell_levels(cls, class_index):
        lus = [
            lu for lu in LevelUpObject.every if lu.class_index == class_index
        ]
        indexes = [
            i for (i, lu) in enumerate(lus) if lu.get_bit("spell_level")
        ]
        if not indexes:
            return

        new_indexes = []
        for i in indexes:
            while True:
                n = mutate_normal(i, 1, 40, random_degree=cls.random_degree)
                if n not in new_indexes:
                    new_indexes.append(n)
                    break

        if len(new_indexes) > 1:
            remaining = 8 - len(new_indexes)
            highest = max(new_indexes)
            new_indexes.extend(random.sample(range(highest + 1, 50),
                                             remaining))
            assert len(new_indexes) == 8

        assert len(new_indexes) in [1, 8]
        for i, lu in enumerate(lus):
            if i in new_indexes:
                lu.set_bit("spell_level", True)
            else:
                lu.set_bit("spell_level", False)
Example #3
0
def shuffle_bits(value, size=8):
    numbits = bin(value).count("1")
    if numbits:
        digits = random.sample(range(size), numbits)
        newvalue = 0
        for d in digits:
            newvalue |= (1 << d)
        value = newvalue
    return value
Example #4
0
    def randomize_all(cls):
        f = open(get_outfile(), "r+b")
        f.seek(addresses.hammer3)
        num_items = ord(f.read(1))
        indexes = map(ord, f.read(num_items))
        f.close()
        sios = [ShopIndexObject.get(i) for i in indexes]
        hard_mode = "chaos" in get_activated_codes()
        total_new_items = []
        for item_type in [2, 3, 4]:
            subsios = [sio for sio in sios if sio.item_type == item_type]
            new_items = []
            candidates = [
                i for i in ItemObject.every
                if i.item_type == item_type and i.price > 0
            ]
            candidates = sorted(candidates,
                                key=lambda c: (c.price, random.random()))
            max_index = len(candidates) - 1
            while len(new_items) < len(subsios):
                if hard_mode:
                    index = random.randint(0, random.randint(0, max_index))
                else:
                    index = random.randint(0, max_index)
                chosen = candidates[index]
                if ("fam" in get_activated_codes() and item_type == 2
                        and chosen.index in HP_HEALING_ITEMS):
                    continue

                restricted_items = None
                if "gun" in get_activated_codes() and item_type == 3:
                    restricted_items = [WeaponObject.get(i) for i in GUNS]
                if "fist" in get_activated_codes() and item_type == 3:
                    restricted_items = [WeaponObject.get(i) for i in FISTS]
                if "ass" in get_activated_codes() and item_type == 3:
                    restricted_items = [WeaponObject.get(i) for i in KNIVES]

                if restricted_items is not None:
                    temp = [i for i in restricted_items if i not in new_items]
                    if temp:
                        restricted_items = temp
                    chosen = random.choice(restricted_items)

                if chosen in new_items and restricted_items is None:
                    continue
                new_items.append(chosen)

            new_items = sorted(new_items, key=lambda ni: ni.index)
            total_new_items.extend(new_items)

        sios = [ShopIndexObject.get(i) for i in xrange(len(total_new_items))]
        for sio, ni in zip(sios, total_new_items):
            sio.item_type = ni.item_type
            sio.item_index = ni.index

        f = open(get_outfile(), "r+b")
        previous = list(sios)
        for address in ["hammer3", "hammer2", "hammer1"]:
            f.seek(getattr(addresses, address))
            num_items = ord(f.read(1))
            f.seek(getattr(addresses, address) + 1)
            chosen_sios = random.sample(previous, num_items)
            chosen_sios = sorted(chosen_sios, key=lambda sio: sio.index)
            for sio in chosen_sios:
                f.write(chr(sio.index))
                sio.shop_rank = int(address[-1])
                sio.inserted_item = False
            previous = chosen_sios
        f.close()
Example #5
0
def do_fiesta():
    print "Please enter a number to choose an option:"
    print "1. Choose my own jobs."
    print "2. Randomize my jobs."

    while True:
        x = int(raw_input("? "))
        if x in [1, 2]:
            break

    print
    if x == 1:
        print "JOB LIST"
        namestrs = [
            "{0:>2}. {1}".format(jco.job_index + 1, jco.name)
            for jco in sorted(JobCrystalObject.every,
                              key=lambda j: j.job_index)
        ]
        maxlen = max(map(len, namestrs)) + 2
        num_per_row = 79 / maxlen
        num_rows = len(namestrs) / float(num_per_row)
        if num_rows != int(num_rows):
            num_rows += 1
        num_rows = int(num_rows)
        ss = ["" for _ in xrange(int(num_rows))]
        while namestrs:
            namestr = namestrs.pop(0)
            s = ss.pop(0)
            s += ("{0:%s}" % maxlen).format(namestr)
            ss.append(s)
        for s in sorted(ss):
            print s
        print
        chosen_jobs = []
        for element in ["Wind", "Water", "Fire", "Earth"]:
            while True:
                x = raw_input("%s job? " % element)
                try:
                    x = int(x) - 1
                    assert x >= 0
                    x = [
                        jco for jco in JobCrystalObject.every
                        if jco.job_index == x
                    ][0]
                    chosen_jobs.append(x)
                    break
                except:
                    pass
        print "Your chosen jobs are: " + ", ".join(jco.name
                                                   for jco in chosen_jobs)
        print
    else:
        JobCrystalObject.class_reseed("fiesta1")
        fight_jobs = [
            jco for jco in JobCrystalObject.every
            if jco.has_fight_command and jco.job_abilities
        ]
        wind_job = random.choice(fight_jobs)
        candidates = [
            jco for jco in JobCrystalObject.every
            if jco.job_abilities and jco is not wind_job
        ]
        chosen_jobs = [wind_job] + random.sample(candidates, 3)

    assert len(set(chosen_jobs)) == 4
    JobCrystalObject.class_reseed("fiesta2")

    crystal_indexes = [jco.crystal_index for jco in chosen_jobs]
    for jco in JobCrystalObject.every:
        if jco.rank <= 2:
            jco.crystal_index = crystal_indexes[0]
        elif jco.rank <= 3:
            jco.crystal_index = crystal_indexes[1]
        elif jco.rank <= 5:
            jco.crystal_index = crystal_indexes[2]
        else:
            jco.crystal_index = crystal_indexes[3]

    NONELEMENTAL_SKILLS = [
        0x8, 0xc, 0xd, 0xe, 0x11, 0x12, 0x13, 0x15, 0x16, 0x17, 0x18, 0x2a,
        0x2b, 0x5f, 0x61, 0x62, 0x90
    ]
    ability_indexes = [
        a.ability for jco in chosen_jobs for a in jco.job_abilities
    ]
    if not set(ability_indexes) & set(NONELEMENTAL_SKILLS):
        print(
            "WARNING! These jobs will not learn a "
            "reliable source of non-elemental damage.")
        print("At least one of them has the Fight skill.")
        x = raw_input("Are you sure you want to continue? (y/n) ")
        if x and x.lower()[0] == 'n':
            remove(get_outfile())
            exit(0)
Example #6
0
    def mutate(self):
        if not self.is_equipment:
            return
        score = self.stat_point_value
        num_up = bin(random.randint(1, 31)).count('1')
        num_down = bin(random.randint(0, 31)).count('1')
        while True:
            if random.choice([True, False, False]):
                ups = [attr for attr in EQUIP_STATS
                       if 1 <= getattr(self, attr) <= 127]
                if ups:
                    break
            ups = random.sample(EQUIP_STATS, num_up)
            if set(ups) & set(self.primary_stats):
                break
        ups = dict([(u, 0) for u in ups])
        if random.choice([True, False, False]):
            downs = [attr for attr in EQUIP_STATS
                   if getattr(self, attr) >= 128]
        else:
            downs = random.sample(EQUIP_STATS, num_down)
        downs = dict([(d, 0) for d in downs if d not in ups])
        if downs:
            if score != 0:
                downpoints = random.randint(0, random.randint(0, score))
            else:
                downpoints = random.randint(0, random.randint(0, random.randint(0, 100)))
            while downpoints > 0:
                attr = random.choice(downs.keys())
                downs[attr] += 1
                downpoints -= 1
                score += 1
        while score > 0:
            attr = random.choice(ups.keys())
            ups[attr] += 1
            if attr in self.primary_stats:
                score -= 1
            else:
                score -= 2

        for attr in EQUIP_STATS:
            setattr(self, attr, 0)

        for attr in ups:
            setattr(self, attr, min(mutate_normal(
                ups[attr], minimum=1, maximum=127), 127))

        for attr in downs:
            value = min(mutate_normal(
                downs[attr], minimum=1, maximum=127), 127)
            if value:
                setattr(self, attr, 256 - value)

        if self.is_weapon and self.get_bit("geno"):
            assert self.equippable == 8
            return

        equippable = self.equippable & 0xE0
        num_equippable = random.randint(1,random.randint(1, 5))
        for _ in xrange(num_equippable):
            equippable |= (1 << random.randint(0, 4))

        if self.is_weapon:
            equippable = equippable & 0xF7
            assert not equippable & 8
            if not equippable:
                return
        self.equippable = equippable
Example #7
0
class FormationObject(TableObject):
    flag = "f"
    flag_description = "enemy formations"

    def __repr__(self):
        present = bin(self.enemies_present)[2:]
        hidden = bin(self.enemies_hidden)[2:]
        present = "{0:0>8}".format(present)
        hidden = "{0:0>8}".format(hidden)
        s = "%x: " % self.index
        for i, (p, h) in enumerate(zip(present, hidden)):
            index, x, y = (getattr(self, "monster%s" % i),
                           getattr(self, "monster%s_x" % i),
                           getattr(self, "monster%s_y" % i))
            m = MonsterObject.get(index)
            if h == "1" or p == "1":
                s += "%x %s" % (index, m.name.strip())
                if m in self.leaders:
                    s += "*"
            if h != "1" and p == "1":
                s += " (%s, %s); " % (x, y)
            if h == "1":
                assert p == "1"
                s += " (hidden, %s, %s); " % (x, y)
        s = s.strip().rstrip(";").strip()
        return s

    @property
    def vram_used(self):
        if self.enemies_hidden:
            return None
        return sum([e.vram_value for e in self.enemies])

    @property
    def coordinates(self):
        coordinates = []
        for i in xrange(8):
            if self.enemies_present & (1 << (7-i)):
                coordinates.append((getattr(self, "monster%s_x" % i),
                                    getattr(self, "monster%s_y" % i)))
        return coordinates

    @property
    def rank(self):
        enemies = sorted(self.enemies, key=lambda m: m.rank, reverse=True)
        rank = 0
        for i, e in enumerate(enemies):
            rank += e.rank / (i+1)
        return rank

    @property
    def bosses(self):
        bosses = [e for e in self.enemies if e.is_boss]
        return bosses

    @property
    def enemies(self):
        enemies = bin(self.enemies_present | self.enemies_hidden)[2:]
        return self.get_enemy_list(enemies)

    def get_enemy_list(self, bitmask):
        bitmask = "{0:0>8}".format(bitmask)
        enemy_list = []
        for (i, c) in enumerate(bitmask):
            if c == "1":
                m = MonsterObject.get(getattr(self, "monster%s" % i))
                enemy_list.append(m)
        return enemy_list

    @property
    def leaders(self):
        if not hasattr(self, "_leaders"):
            for f in FormationObject.every:
                f._leaders = set([])
            for p in PackObject.every:
                common_enemies = set(p.common_enemies)
                for f in p.formations:
                    f._leaders |= common_enemies
            for f in FormationObject.every:
                if not f._leaders:
                    f._leaders = list(f.enemies)
                f._leaders = sorted(f._leaders, key=lambda m: m.index)
        return self._leaders

    @classproperty
    def valid_coordinates(cls):
        if hasattr(cls, "_valid_coordinates"):
            return cls._valid_coordinates

        cls._valid_coordinates = set([])
        for f in FormationObject.every:
            if not f.bosses:
                bitmask = f.enemies_present & (0xFF ^ f.enemies_hidden)
                for i in xrange(8):
                    if bitmask & (1 << (7-i)):
                        (x, y) = (getattr(f, "monster%s_x" % i),
                                  getattr(f, "monster%s_y" % i))
                    else:
                        continue
                    if (x, y) == (0, 0):
                        break
                    cls._valid_coordinates.add((x, y))
        cls._valid_coordinates = sorted(cls._valid_coordinates)
        xs, ys = zip(*cls._valid_coordinates)
        cls.lower_x, cls.upper_x = min(xs), max(xs)
        cls.lower_y, cls.upper_y = min(ys), max(ys)
        return cls.valid_coordinates

    @property
    def meta(self):
        return FormMetaObject.get(self.index)

    @property
    def has_event(self):
        if self.meta.event == 0xFF:
            return False
        else:
            return True

    @property
    def music(self):
        if self.meta.misc & 0xc0 == 0xc0:
            return None
        return (self.meta.misc >> 2) & 0x7

    @property
    def inescapable(self):
        return self.meta.misc & 3

    def set_music(self, value):
        if value is None:
            self.meta.misc &= 0xE3
            self.meta.misc |= 0xC0
        else:
            self.meta.misc &= 0xE3
            self.meta.misc |= (value << 2)

    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 get_collective_distance(p, points):
            distances = [get_distance(p, p2) for p2 in points]
            return reduce(lambda a, b: a*b, distances, 1)

        def select_most_distance(candidates, done_coordinates):
            score = lambda p: get_collective_distance(p, done_coordinates)
            chosen = max(candidates, key=lambda c: score(c))
            return chosen

        self.enemies_present = 0
        done_coordinates = []
        for i in range(8):
            if i < len(chosen_enemies):
                e = chosen_enemies[i].index
                if not done_coordinates:
                    (x, y) = random.choice(self.valid_coordinates)
                    (x, y) = mutate_coordinate((x, y))
                else:
                    candidates = random.sample(self.valid_coordinates,
                                               len(chosen_enemies)*2)
                    candidates = map(mutate_coordinate, candidates)
                    (x, y) = select_most_distance(candidates, done_coordinates)
                done_coordinates.append((x, y))
                self.enemies_present |= (1 << (7-i))
            else:
                e = 0
            setattr(self, "monster%s" % i, e)
            setattr(self, "monster%s_x" % i, 0)
            setattr(self, "monster%s_y" % i, 0)
        done_coordinates = sorted(done_coordinates)
        for i, (x, y) in enumerate(done_coordinates):
            setattr(self, "monster%s_x" % i, x)
            setattr(self, "monster%s_y" % i, y)
Example #8
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)