コード例 #1
0
ファイル: randomizer.py プロジェクト: abyssonym/smrpg_gbarp
 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))
コード例 #2
0
    def full_randomize(cls):
        super(ShopObject, cls).full_randomize()
        for pretty_shop_type in ["Magic", "Weapons", "Armor", "Items"]:
            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)

            avg /= float(len(shops))
            for n, s in enumerate(shops):
                num_items = int(round(mutate_normal(avg, minimum=1,
                                                    maximum=8)))
                chosen_items = set([])
                while len(chosen_items) < num_items:
                    chosen_rank = mutate_normal(n, minimum=0,
                                                maximum=len(shops)-1)
                    candidates = sorted([i for i in itemranks[chosen_rank]
                                         if i not in chosen_items])
                    if not candidates:
                        a = n
                        b = len(shops) / 2
                        a, b = min(a, b), max(a, b)
                        n = random.randint(a, b)
                        continue
                    item = random.choice(candidates)
                    chosen_items.add(item)
                s.items = sorted(chosen_items)
                all_items -= chosen_items

            all_items = sorted(all_items)
            while all_items:
                item = all_items.pop()
                candidates = [s for s in shops if len(s.items) < 8]
                s = random.choice(candidates)
                s.items.append(item)
コード例 #3
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
コード例 #4
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
コード例 #5
0
ファイル: randomizer.py プロジェクト: abyssonym/smrpg_gbarp
 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
     xps = sorted([mutate_normal(l.xp, minimum=1, maximum=65535)
                   for l in cls.every])
     prev = 0
     assert len(cls.every) == len(xps)
     for i, (l, xp) in enumerate(zip(cls.every, xps)):
         factor = min(i / (len(xps)/2.0), 1.0)
         xp = int(round((xp + (xp * factor))/2))
         while xp <= prev:
             xp += 1
         l.xp = xp
         prev = xp
コード例 #6
0
def get_item_similar_price(price=None, magic=False):
    if magic:
        shops = ShopObject.get_magic_shops()
    else:
        shops = ShopObject.get_nonmagic_shops()

    items = set([])
    for s in shops:
        items |= set(s.items)

    if magic:
        items = sorted([(PriceObject.get(i+0x100).price, i) for i in items])
    else:
        items = sorted([(PriceObject.get(i).price, i) for i in items])

    newprice = mutate_normal(price, minimum=1, maximum=65000)
    items = items[:1] + [i for (p, i) in items if p <= newprice]
    chosen = items[-1]
    return chosen
コード例 #7
0
 def mutate(self):
     if not self.mutate_valid:
         return
     chance = random.random()
     price = self.rank
     if chance <= 0.85:
         if chance <= 0.70:  # item
             self.treasure_type = 0x40
         else:  # magic
             self.treasure_type = 0x20
         self.value = get_item_similar_price(price, magic=self.is_magic)
     else:  # gold
         price = mutate_normal(price, minimum=1, maximum=65000)
         exponent = 0
         while price >= 100:
             price /= 10
             exponent += 1
         self.treasure_type = exponent
         self.value = price
コード例 #8
0
    def mutate(self):
        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)

        if 1 <= self.level <= 99:
            new_level = mutate_normal(self.level, minimum=1, maximum=99)
            old_divisibility = divisibility_rank(self.level)
            new_divisibility = divisibility_rank(new_level)
            if new_divisibility < old_divisibility:
                if not self.is_boss:
                    self.level = new_level
                else:
                    difference = float(new_level) / self.level
                    if random.random() < difference:
                        self.level = new_level
            elif not self.is_boss and random.choice([True, False]):
                self.level = new_level

        oldimmunities = self.status_immunities
        for attr in ["elemental_immunities", "absorptions", "weaknesses"]:
            if not self.is_boss:
                self.bit_shuffle(attr)
            else:
                self.bit_random_add(attr)
        if not self.is_boss:
            self.bit_shuffle("cant_evade")
            self.bit_random_add("cant_evade")
        self.bit_random_remove("cant_evade")
        oldstatus = self.status
        self.bit_random_add("status_immunities")
        self.bit_random_add("status", rate=0.1)
        newstatus = self.status
        newstatus = newstatus & (newstatus ^ oldimmunities)
        self.status = (oldstatus & oldimmunities) | newstatus
        self.bit_random_add("command_immunity")
コード例 #9
0
ファイル: randomizer.py プロジェクト: abyssonym/smrpg_gbarp
    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))
コード例 #10
0
ファイル: randomizer.py プロジェクト: abyssonym/smrpg_gbarp
    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
コード例 #11
0
ファイル: randomizer.py プロジェクト: abyssonym/smrpg_gbarp
 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)
コード例 #12
0
ファイル: randomizer.py プロジェクト: abyssonym/smrpg_gbarp
    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)