def get_external_candidates(self, num=2, test=False):
        if not self.clusters:
            return None
        candidates = []
        linked_clusters = []
        for e in self.linked_entrances:
            for c in self.clusters:
                if e in c.entrances:
                    linked_clusters.append(c)
        done_clusts = set([])
        done_ents = set(self.linked_entrances)

        for _ in range(num):
            candclusts = [c for c in self.clusters
                          if set(c.entrances)-done_ents]
            tempclusts = [c for c in candclusts if c not in done_clusts]
            if tempclusts:
                candclusts = tempclusts
            tempclusts = [c for c in candclusts if
                          not set(c.entrances) & set(self.linked_edge)]
            if tempclusts:
                candclusts = tempclusts
            try:
                #chosen = self.get_max_edge_distance(candclusts)
                chosen = random.choice(candclusts)
            except IndexError:
                return None
            done_clusts.add(chosen)
            choices = [c for c in chosen.entrances if c not in done_ents]
            chosen = random.choice(choices)
            done_ents.add(chosen)
            candidates.append(chosen)
        if not test:
            self.linked_edge.extend(candidates)
        return candidates
示例#2
0
    def interconnect(self):
        self.links = []
        if len(self.clusters) < 2:
            return

        starter = max(self.clusters, key=lambda c: len(c.entrances))
        while True:
            links = []
            done_ents = set([])
            done_clusts = [starter]
            clusters = self.clusters
            random.shuffle(clusters)
            for c in clusters:
                if c in done_clusts:
                    continue
                prelim = max(done_clusts,
                             key=lambda c2: len(set(c2.entrances)-done_ents))
                numents = len(set(prelim.entrances) - done_ents)
                if numents == 0:
                    break
                candidates = [c2 for c2 in done_clusts if
                              len(set(c2.entrances)-done_ents) == numents]
                chosen = random.choice(candidates)
                acands = [e for e in c.entrances if e not in done_ents]
                bcands = [e for e in chosen.entrances if e not in done_ents]
                a, b = random.choice(acands), random.choice(bcands)
                if c not in done_clusts:
                    done_clusts.append(c)
                done_ents.add(a)
                done_ents.add(b)
                links.append((a, b))
            if set(done_clusts) == set(self.clusters):
                break
        self.links = links
示例#3
0
    def set_spells(self, valid_spells, spellsets=None, spellclass=None):
        spellsets = spellsets or get_spellsets(spells=valid_spells)
        spellclass = spellclass or random.choice(spellsets.keys())
        self.name = spellclass
        desc, spellset = spellsets[spellclass]
        self.spells_description = desc
        if spellclass.lower() in ["chaos"]:
            self.wild = True
            self.spells = []
            return
        else:
            self.wild = False

        spellset = sorted([s for s in spellset if s in valid_spells],
                          key=lambda s: s.spellid)
        if len(spellset) < 3:
            raise ValueError("Spellset %s not big enough." % spellclass)

        for setlength in [8, 16, 32]:
            if len(spellset) <= setlength:
                spells = sorted(spellset)
                while len(spells) < setlength:
                    spells.append(random.choice(spellset))
                break
        else:
            assert setlength == 32
            spells = random.sample(sorted(spellset),
                                   min(setlength, len(spellset)))
            while len(spells) < setlength:
                spells.append(random.choice(spellset))
            assert len(set(spells)) > 16

        self.spells = sorted(spells)

        return self.spells
示例#4
0
    def get_external_candidates(self, num=2, test=False):
        if not self.clusters:
            return None
        candidates = []
        linked_clusters = []
        for e in self.linked_entrances:
            for c in self.clusters:
                if e in c.entrances:
                    linked_clusters.append(c)
        done_clusts = set([])
        done_ents = set(self.linked_entrances)

        for _ in xrange(num):
            candclusts = [c for c in self.clusters
                          if set(c.entrances)-done_ents]
            tempclusts = [c for c in candclusts if c not in done_clusts]
            if tempclusts:
                candclusts = tempclusts
            tempclusts = [c for c in candclusts if
                          not set(c.entrances) & set(self.linked_edge)]
            if tempclusts:
                candclusts = tempclusts
            try:
                #chosen = self.get_max_edge_distance(candclusts)
                chosen = random.choice(candclusts)
            except IndexError:
                return None
            done_clusts.add(chosen)
            choices = [c for c in chosen.entrances if c not in done_ents]
            chosen = random.choice(choices)
            done_ents.add(chosen)
            candidates.append(chosen)
        if not test:
            self.linked_edge.extend(candidates)
        return candidates
    def interconnect(self):
        self.links = []
        if len(self.clusters) < 2:
            return

        starter = max(self.clusters, key=lambda c: len(c.entrances))
        while True:
            links = []
            done_ents = set([])
            done_clusts = [starter]
            clusters = self.clusters
            random.shuffle(clusters)
            for c in clusters:
                if c in done_clusts:
                    continue
                prelim = max(done_clusts,
                             key=lambda c2: len(set(c2.entrances)-done_ents))
                numents = len(set(prelim.entrances) - done_ents)
                if numents == 0:
                    break
                candidates = [c2 for c2 in done_clusts if
                              len(set(c2.entrances)-done_ents) == numents]
                chosen = random.choice(candidates)
                acands = [e for e in c.entrances if e not in done_ents]
                bcands = [e for e in chosen.entrances if e not in done_ents]
                a, b = random.choice(acands), random.choice(bcands)
                if c not in done_clusts:
                    done_clusts.append(c)
                done_ents.add(a)
                done_ents.add(b)
                links.append((a, b))
            if set(done_clusts) == set(self.clusters):
                break
        self.links = links
def generate_name(size=None, maxsize=10):
    if not size:
        size = random.randint(1, 5) + random.randint(1, 5)
        if size < 4:
            size += random.randint(0, 5)

    def has_vowel(text):
        for c in text:
            if c.lower() in "aeiouy":
                return True
        return False

    while True:
        starts = sorted([s for s in generator if s[0].isupper()])
        name = random.choice(starts)
        name = name[:size]
        while len(name) < size:
            key = name[-lookback:]
            if key not in generator and size - len(name) < len(key):
                name = random.choice(starts)
                continue
            if key not in generator or (random.randint(1, 15) == 15
                                        and has_vowel(name[-2:])):
                if len(name) <= size - lookback:
                    if len(name) + len(key) < maxsize:
                        name += " "
                    name += random.choice(starts)
                    continue
                else:
                    name = random.choice(starts)
                    continue

            c = random.choice(generator[key])
            name = name + c

        for ename in enemynames:
            if name == ename:
                name = ""
                break

        if name:
            for ename in enemynames:
                if len(name) > (lookback + 1):
                    length = min(len(name), len(ename))
                    if name[:length] == ename[:length]:

                        name = ""
                        break

        if len(name) >= size:
            enemynames.append(name)
            return name
示例#7
0
    def random_unused_code(self):
        candidates = [
            c for c in NORMAL_CODES
            if c not in self.active_codes and c.name != "repairpalette"
        ]

        i = random.randint(1, 7)
        if i <= 2:
            secret_codes = [
                c for c in NORMAL_CODES
                if c.is_cyphered and not self.is_code_active(c)
            ]
            if secret_codes:
                candidates = secret_codes

        elif i <= 4:
            new_codes = MAKEOVER_MODIFIER_CODES + [
                c for c in NORMAL_CODES if c.name in ["alasdraco"]
            ]
            new_codes = [c for c in new_codes if not self.is_code_active(c)]
            if new_codes:
                candidates = new_codes

        if not candidates:
            candidates = NORMAL_CODES + MAKEOVER_MODIFIER_CODES

        selected = random.choice(candidates)
        if selected.is_cyphered:
            f = FourSquare(selected.key1, selected.key2)
            return f.decypher(selected.name)
        return selected.name
示例#8
0
 def convert_longs(self):
     for longentrance in self.longentrances:
         longentrance.dest &= 0xFE00
         longentrance.dest |= self.location.locid & 0x1FF
         e = random.choice(self.entrances)
         longentrance.destx = e.x
         longentrance.desty = e.y
 def convert_longs(self):
     for longentrance in self.longentrances:
         longentrance.dest &= 0xFE00
         longentrance.dest |= self.location.locid & 0x1FF
         e = random.choice(self.entrances)
         longentrance.destx = e.x
         longentrance.desty = e.y
示例#10
0
def get_orphaned_formations():
    global orphaned_formations
    if orphaned_formations is not None:
        return orphaned_formations

    orphaned_formations = set([])
    from monsterrandomizer import get_monsters
    monsters = get_monsters()
    extra_miabs = get_extra_miabs(0)
    for m in monsters:
        if m.id in EVENT_ENEMIES:
            m.auxloc = "Event Battle"
            continue
        if not m.is_boss:
            location = m.determine_location()
            if "missing" in location.lower() or not location.strip():
                formations = set([f for f in get_formations()
                                  if m in f.present_enemies
                                  and not f.has_boss])
                formations = sorted(formations, key=lambda f: f.formid)
                try:
                    f = random.choice(formations)
                    orphaned_formations.add(f)
                except IndexError:
                    pass
            for x in extra_miabs:
                if m in x.present_enemies:
                    if x == f:
                        continue
                    ens = set(x.present_enemies)
                    if len(ens) == 1:
                        banned_formids.append(x.formid)

    orphaned_formations = sorted(orphaned_formations, key=lambda f: f.formid)
    return get_orphaned_formations()
示例#11
0
    def mutate_feature(self, feature=None):
        if self.is_consumable or self.is_tool:
            return

        if feature is None:
            feature = random.choice(list(STATPROTECT.keys()))

        nochange = STATPROTECT[feature]
        if feature == 'special2':
            # Allow rare merit award bit on relics
            if self.is_relic:
                if random.randint(1, 10) == 10:
                    nochange &= ~0x20
            # Reduce chance of Genji Glove bit on non-relics
            elif random.randint(1, 4) != 4:
                nochange |= 0x10
        self.features[feature] = bit_mutate(self.features[feature], op="on",
                                            nochange=nochange)

        new_features = self.get_feature(feature, self.features[feature], nochange)

        if new_features != "":
            if "Special Feature" in self.mutation_log.keys():
                for new_feature in new_features.split(", "):
                    if new_feature not in self.mutation_log["Special Feature"]:
                        self.mutation_log.update({"Special Feature": self.mutation_log["Special Feature"] + ", " + new_feature})
            else:
                self.mutation_log["Special Feature"] = new_features
        self.mutate_name()
示例#12
0
def allocate_espers(ancient_cave, espers, characters, fout):
    char_ids = list(range(12)) + [13] # everyone but Gogo
    
    characters = [c for c in characters if c.id in char_ids]
    
    chars_for_esper = []
    max_rank = max(espers, key=lambda e: e.rank).rank
    for e in espers:
        num_users = 1
        if e.id not in [15, 16] and random.randint(1,25) >= 25 - max_rank + e.rank:
            num_users += 1
            while num_users < 15 and random.choice([True] + [False] * (e.rank + 2)):
                num_users += 1
        users = random.sample(characters, num_users)
        chars_for_esper.append([c.id for c in users])

    if not ancient_cave:
        chars_for_esper[12] = chars_for_esper[11]   # make Odin and Raiden equippable by the same person/people
        
    char_mask_for_esper = [ 
        reduce( lambda x, y: x | y,
                [1 << char_id for char_id in chars_for_esper[e.id]]
                ) for e in espers
    ]

    for e in espers:
        e.chars = ", ".join([c.newname for c in characters if c.id in chars_for_esper[e.id]])
    
    # do substitution
    esper_allocator_sub = Substitution()
    esper_allocator_sub.set_location(0x31B61)
    esper_allocator_sub.bytestring = [0x20,0x00,0xF8]
    esper_allocator_sub.write(fout)
    
    esper_allocator_sub.set_location(0x35524)
    esper_allocator_sub.bytestring = [0x20,0x07,0xF8]
    esper_allocator_sub.write(fout)
    
    esper_allocator_sub.set_location(0x358E1)
    esper_allocator_sub.write(fout)
    
    esper_allocator_sub.set_location(0x359B1)
    esper_allocator_sub.write(fout)
    
    esper_allocator_sub.set_location(0x35593)
    esper_allocator_sub.bytestring = [0xA9,0x2C]
    esper_allocator_sub.write(fout)
    
    esper_allocator_sub.set_location(0x355B2)
    esper_allocator_sub.bytestring = [0x20,0x2E,0xF8]
    esper_allocator_sub.write(fout)
    
    esper_allocator_sub.set_location(0x358E8)
    esper_allocator_sub.bytestring = [0xC9,0x20,0xF0,0x16]
    esper_allocator_sub.write(fout)
    
    esper_allocator_sub.set_location(0x3F800)
    
    esper_allocator_sub.bytestring = [0xAA, 0xB5, 0x69, 0x8D, 0xF8, 0x1C, 0x60, 0xDA, 0x08, 0x85, 0xE0, 0x0A, 0xAA, 0xE2, 0x10, 0xDA, 0xAD, 0xF8, 0x1C, 0x0A, 0xAA, 0xC2, 0x20, 0xBF, 0x67, 0x9C, 0xC3, 0xFA, 0x3F, 0x58, 0xF8, 0xC3, 0xF0, 0x05, 0x28, 0xFA, 0x4C, 0x76, 0x55, 0x28, 0xFA, 0xA9, 0x28, 0x4C, 0x95, 0x55, 0xBD, 0x02, 0x16, 0xC9, 0x80, 0xB0, 0x0F, 0xFA, 0xA6, 0x00, 0xBF, 0x4B, 0xF8, 0xC3, 0xF0, 0x07, 0x8D, 0x80, 0x21, 0xE8, 0x80, 0xF4, 0x60, 0x9C, 0x80, 0x21, 0x4C, 0xD9, 0x7F, 0x82, 0x9A, 0xA7, 0xC3, 0xAD, 0xFF, 0x9E, 0xAA, 0xAE, 0xA2, 0xA9, 0xBE, 0x00] + [i for sublist in map(int2bytes, char_mask_for_esper) for i in sublist]
    esper_allocator_sub.write(fout)
示例#13
0
def manage_coral(fout):

    f = open_mei_fallback(CORAL_TABLE)
    coralnames = sorted(
        set(sanitize_coral([line.strip() for line in f.readlines()])))
    f.close()

    sprite_log = ""

    newcoralname = random.choice(coralnames)
    sprite_log += str("Coral: ").ljust(17) + string.capwords(
        str(newcoralname)) + "\n"
    coraldescription1 = "Piece of " + newcoralname.lower() + ","
    coraldescription2 = "found near Ebot's Rock."

    load_patch_file("coral")
    set_dialogue_var("coralsub", newcoralname)

    newcoralnamebytes = name_to_bytes(newcoralname, 12)
    coraldescription1 = name_to_bytes(coraldescription1, 24)
    coraldescription2 = name_to_bytes(coraldescription2, 26)

    coraldescription = coraldescription1 + bytes([0x01]) + coraldescription2

    coral_sub = Substitution()
    coral_sub.set_location(0xEFC08)  ##change the name when opening a chest
    coral_sub.bytestring = newcoralnamebytes
    coral_sub.write(fout)

    coral_sub.set_location(0xEFD7F)  ##Change the name in the description
    coral_sub.bytestring = coraldescription
    coral_sub.write(fout)

    return sprite_log
示例#14
0
 def intify(value):
     subintify = lambda x: int(x, 0x10)
     if ',' in value:
         return random.choice(list(map(subintify,
                                       value.split(','))))
     else:
         return subintify(value)
示例#15
0
    def mutate_feature(self, feature=None):
        if self.is_consumable or self.is_tool:
            return

        if feature is None:
            feature = random.choice(STATPROTECT.keys())
        self.features[feature] = bit_mutate(self.features[feature], op="on",
                                            nochange=STATPROTECT[feature])
示例#16
0
    def mutate_feature(self, feature=None):
        if self.is_consumable or self.is_tool:
            return

        if feature is None:
            feature = random.choice(STATPROTECT.keys())
        self.features[feature] = bit_mutate(self.features[feature], op="on",
                                            nochange=STATPROTECT[feature])
    def generate_spells(self, tierless=False):
        global used

        self.spells, self.learnrates = [], []
        rank = self.rank
        if random.randint(1, 5) == 5:
            rank += 1
        rank = min(rank, max(rankbounds.keys()))

        if random.randint(1, 10) != 10:
            candidates = self.get_candidates(rank,
                                             set_lower=not tierless,
                                             allow_quick=tierless)
            if candidates:
                s = random.choice(candidates)
                self.spells.append(s)
                used.add(s)

        rank = self.rank
        for _ in range(random.randint(0, 2) + random.randint(0, 2)):
            candidates = self.get_candidates(rank,
                                             set_lower=False,
                                             allow_quick=tierless)
            if candidates:
                s = random.choice(candidates)
                if s in self.spells:
                    continue
                self.spells.append(s)
                used.add(s)

        self.spells = sorted(self.spells, key=lambda s: s.spellid)
        self.learnrates = []
        esperrank = rankbounds[self.rank]
        if esperrank is None:
            esperrank = rankbounds[self.rank - 1]
        esperrank = esperrank * 3
        for s in self.spells:
            spellrank = s.rank()
            learnrate = int(esperrank / float(spellrank))
            learnrate = random.randint(0, learnrate) + random.randint(
                0, learnrate)
            while random.randint(1, 3) == 3:
                learnrate += 1
            learnrate = max(1, min(learnrate, 20))
            self.learnrates.append(learnrate)
def make_secret_treasure_room(mapid, beltroom):
    from itemrandomizer import get_secret_item
    candidates = []
    for line in open(TREASURE_ROOMS_TABLE):
        locid, entid, chestid = tuple(map(int, line.strip().split(',')))
        location = get_location(locid)
        entrance = location.get_entrance(entid)
        chest = location.get_chest(chestid)
        candidates.append((location, entrance, chest))
    location, entrance, chest = random.choice(candidates)
    newlocation = Location(mapid)
    newlocation.copy(location)
    newlocation.make_tower_basic()
    newlocation.entrance_set.entrances = []
    newlocation.events = []
    newlocation.npcs = []

    c = ChestBlock(pointer=None, location=newlocation.locid)
    c.copy(chest)
    c.set_content_type(0x40)
    item = get_secret_item()
    c.contents = item.itemid
    c.set_new_id()
    c.do_not_mutate = True
    c.ignore_dummy = True
    newlocation.chests = [c]
    newlocation.secret_treasure = True
    newlocation.ancient_rank = 0

    e = Entrance(None)
    e.copy(entrance)
    e.set_location(newlocation)
    e.destx, e.desty, e.dest = 36, 27, 287
    newlocation.entrances.append(e)
    assert len(newlocation.entrances) == 1

    e2 = Entrance()
    e2.x = 36
    e2.y = 25
    e2.destx, e2.desty, e2.dest = e.x, e.y, mapid
    beltroom.entrance_set.entrances = [
        ent for ent in beltroom.entrances if not (ent.x == 36 and ent.y == 25)
    ]
    beltroom.entrance_set.entrances.append(e2)

    final_room = get_location(411)
    e3 = Entrance()
    e3.x = 109
    e3.y = 46
    e3.destx, e3.desty, e3.dest = 82, 46, 412 | 0x2000
    final_room.entrance_set.entrances.append(e3)

    newlocation.attacks = 0
    newlocation.setid = 0
    newlocation.music = 21
    return newlocation, beltroom
示例#19
0
 def elemshuffle(elements):
     elemcount = bin(elements).count('1')
     while random.randint(1, 5) == 5:
         elemcount += random.choice([-1, 1])
     elemcount = max(0, min(elemcount, 8))
     elements = 0
     while elemcount > 0:
         elements = elements | (1 << random.randint(0, 7))
         elemcount += -1
     return elements
def generate_attack():
    if random.randint(1, 7) != 7:
        while True:
            modifier = random.choice(modifiers)
            move = random.choice(moves)
            if len(modifier) + len(move) <= 10:
                break
    else:
        modifier = ""
        if random.randint(1, 4) != 4:
            candidates = list(moves)
        else:
            candidates = list(modifiers)
        candidates = [c for c in candidates if len(c) >= 3]
        move = random.choice(candidates)

    if len(modifier) + len(move) < 10:
        return ("%s %s" % (modifier, move)).strip()
    return modifier + move
示例#21
0
 def mutate(self, ap=False):
     if ap and self.ap is not None and 0 < self.ap < 100:
         factor = self.levelrank() / 100
         self.ap += int(round(self.ap * factor))
         while random.choice([True, False]):
             self.ap += random.randint(-1, 1)
             self.ap = min(100, max(self.ap, 0))
     if self.ambusher:
         if not (self.pincer_prohibited and self.back_prohibited):
             self.misc1 |= 0x90
 def narrow_unknowns(self, strict=False):
     unknowns = [u for u in unknown_itemcodes if u in
                 [i.itemtype for i in self.levelobjects]]
     if unknowns:
         u = random.choice(unknowns)
         self.levelobjects = [i for i in self.levelobjects if
                              i.itemtype == u or i.itemtype not in unknowns]
         if strict:
             self.levelobjects = [i for i in self.levelobjects
                                  if i.itemtype == u]
示例#23
0
 def elemshuffle(elements):
     elemcount = bin(elements).count('1')
     while random.randint(1, 5) == 5:
         elemcount += random.choice([-1, 1])
     elemcount = max(0, min(elemcount, 8))
     elements = 0
     while elemcount > 0:
         elements = elements | (1 << random.randint(0, 7))
         elemcount += -1
     return elements
示例#24
0
def make_secret_treasure_room(mapid, beltroom):
    from itemrandomizer import get_secret_item
    candidates = []
    for line in open(TREASURE_ROOMS_TABLE):
        locid, entid, chestid = tuple(map(int, line.strip().split(',')))
        location = get_location(locid)
        entrance = location.get_entrance(entid)
        chest = location.get_chest(chestid)
        candidates.append((location, entrance, chest))
    location, entrance, chest = random.choice(candidates)
    newlocation = Location(mapid)
    newlocation.copy(location)
    newlocation.make_tower_basic()
    newlocation.entrance_set.entrances = []
    newlocation.events = []
    newlocation.npcs = []

    c = ChestBlock(pointer=None, location=newlocation.locid)
    c.copy(chest)
    c.set_content_type(0x40)
    item = get_secret_item()
    c.contents = item.itemid
    c.set_new_id()
    c.do_not_mutate = True
    c.ignore_dummy = True
    newlocation.chests = [c]
    newlocation.secret_treasure = True
    newlocation.ancient_rank = 0

    e = Entrance(None)
    e.copy(entrance)
    e.set_location(newlocation)
    e.destx, e.desty, e.dest = 36, 27, 287
    newlocation.entrances.append(e)
    assert len(newlocation.entrances) == 1

    e2 = Entrance()
    e2.x = 36
    e2.y = 25
    e2.destx, e2.desty, e2.dest = e.x, e.y, mapid
    beltroom.entrance_set.entrances = [ent for ent in beltroom.entrances
                                       if not (ent.x == 36 and ent.y == 25)]
    beltroom.entrance_set.entrances.append(e2)

    final_room = get_location(411)
    e3 = Entrance()
    e3.x = 109
    e3.y = 46
    e3.destx, e3.desty, e3.dest = 82, 46, 412 | 0x2000
    final_room.entrance_set.entrances.append(e3)

    newlocation.attacks = 0
    newlocation.setid = 0
    newlocation.music = 21
    return newlocation, beltroom
 def get_max_edge_distance(self, clusters):
     if len(clusters) == 1:
         return random.choice(clusters)
     if not self.linked_edge:
         if len(clusters) == 2:
             return random.choice(clusters)
         linked = [random.choice(clusters)]
         clusters = [c for c in clusters if c not in linked]
     else:
         linked = [self.get_entrance_cluster(e) for e in self.linked_edge]
     scores = {}
     for c in clusters:
         scores[c] = 9999
         for l in linked:
             d = self.calculate_distance(c, l)
             scores[c] = min(d, scores[c])
     hiscore = max(scores.values())
     assert hiscore < 999
     clusters = [c for c in clusters if scores[c] == hiscore]
     return random.choice(clusters)
    def generate_bonus(self):
        rank = self.rank
        candidates = set(bonus_ranks[rank])
        candidates = candidates - used_bonuses
        if candidates:
            candidates = sorted(candidates)
            self.bonus = random.choice(candidates)
            used_bonuses.add(self.bonus)
            return

        if random.randint(1, 2) == 2:
            rank += 1
        while random.randint(1, 10) == 10:
            rank += 1
        rank = min(rank, 4)
        candidates = []
        for i in range(rank + 1):
            candidates.extend(bonus_ranks[i])
        if candidates:
            self.bonus = random.choice(candidates)
        used_bonuses.add(self.bonus)
示例#27
0
 def evade_is_screwed_up(value):
     while random.randint(1, 8) == 8:
         if value == 0:
             choices = [1, 6]
         elif value in [5, 0xA]:
             choices = [-1]
         elif value == 6:
             choices = [1, -6]
         else:
             choices = [1, -1]
         value += random.choice(choices)
     return value
示例#28
0
    def generate_bonus(self):
        rank = self.rank
        candidates = set(bonus_ranks[rank])
        candidates = candidates - used_bonuses
        if candidates:
            candidates = sorted(candidates)
            self.bonus = random.choice(candidates)
            used_bonuses.add(self.bonus)
            return

        if random.randint(1, 2) == 2:
            rank += 1
        while random.randint(1, 10) == 10:
            rank += 1
        rank = min(rank, 4)
        candidates = []
        for i in range(rank+1):
            candidates.extend(bonus_ranks[i])
        if candidates:
            self.bonus = random.choice(candidates)
        used_bonuses.add(self.bonus)
 def mutate(self, mp=False, mp_boost_value=None):
     if mp and self.mp is not None and 0 < self.mp < 100:
         factor = self.levelrank() / 100
         self.mp += int(round(self.mp * factor))
         while random.choice([True, False]):
             self.mp += random.randint(-1, 1)
             self.mp = min(100, max(self.mp, 0))
         if mp_boost_value:
             self.mp = min(255, floor(self.mp * float(mp_boost_value)))
     if self.ambusher:
         if not (self.pincer_prohibited and self.back_prohibited):
             self.misc1 |= 0x90
示例#30
0
 def get_max_edge_distance(self, clusters):
     if len(clusters) == 1:
         return random.choice(clusters)
     if not self.linked_edge:
         if len(clusters) == 2:
             return random.choice(clusters)
         linked = [random.choice(clusters)]
         clusters = [c for c in clusters if c not in linked]
     else:
         linked = [self.get_entrance_cluster(e)
                   for e in self.linked_edge]
     scores = {}
     for c in clusters:
         scores[c] = 9999
         for l in linked:
             d = self.calculate_distance(c, l)
             scores[c] = min(d, scores[c])
     hiscore = max(scores.values())
     assert hiscore < 999
     clusters = [c for c in clusters if scores[c] == hiscore]
     return random.choice(clusters)
示例#31
0
 def evade_is_screwed_up(value):
     while random.randint(1, 8) == 8:
         if value == 0:
             choices = [1, 6]
         elif value in [5, 0xA]:
             choices = [-1]
         elif value == 6:
             choices = [1, -6]
         else:
             choices = [1, -1]
         value += random.choice(choices)
     return value
示例#32
0
def randomize_forest():
    start = get_location(0x84)
    end = get_location(0x87)
    mids = [get_location(x) for x in (0x85, 0x86)]

    location86 = get_location(0x86)
    go_to_train_event = location86.events[0]
    location86.events.remove(go_to_train_event)
    world_location_exit = Entrance()
    world_location_exit.copy(location86.entrances[1])

    location = random.choice(mids)
    exit = random.choice(location.entrances)
    map_entrance_to_exit(start.entrances[0], exit)
    location2 = [m for m in mids if m.locid != location.locid][0]
    entrances = [e for e in location.entrances if e != exit]
    entrance = random.choice(entrances)
    exit2 = random.choice(location2.entrances)
    map_entrance_to_exit(entrance, exit2)
    entrances = [e for e in location2.entrances if e != exit]
    entrance2 = random.choice(entrances)
    entrance2.dest = world_location_exit.dest
    entrance2.destx = world_location_exit.destx
    entrance2.desty = world_location_exit.desty
    go_to_train_event.x = entrance2.x
    go_to_train_event.y = entrance2.y
    location2.events.append(go_to_train_event)

    wrong_entrances = [
        e for m in mids for e in m.entrances if e not in (entrance, entrance2)
    ]
    wrong_exits = [e for m in (mids + [start]) for e in m.entrances]
    for e in wrong_entrances:
        exit = random.choice(wrong_exits)
        map_entrance_to_exit(e, exit)
示例#33
0
    def generate_spells(self):
        global used

        self.spells, self.learnrates = [], []
        rank = self.rank
        if random.randint(1, 5) == 5:
            rank += 1
        rank = min(rank, max(rankbounds.keys()))

        if random.randint(1, 10) != 10:
            candidates = self.get_candidates(rank)
            if candidates:
                s = random.choice(candidates)
                self.spells.append(s)
                used.add(s)

        rank = self.rank
        for _ in xrange(random.randint(0, 2) + random.randint(0, 2)):
            candidates = self.get_candidates(rank, set_lower=False)
            if candidates:
                s = random.choice(candidates)
                if s in self.spells:
                    continue
                self.spells.append(s)
                used.add(s)

        self.spells = sorted(self.spells, key=lambda s: s.spellid)
        self.learnrates = []
        esperrank = rankbounds[self.rank]
        if esperrank is None:
            esperrank = rankbounds[self.rank-1]
        esperrank = esperrank * 3
        for s in self.spells:
            spellrank = s.rank()
            learnrate = int(esperrank / float(spellrank))
            learnrate = random.randint(0, learnrate) + random.randint(0, learnrate)
            while random.randint(1, 3) == 3:
                learnrate += 1
            learnrate = max(1, min(learnrate, 20))
            self.learnrates.append(learnrate)
示例#34
0
def set_pronoun(name, gender, force=True):
    gender = gender.lower()
    name = name.lower().capitalize()

    if "random" in gender:
        force = True
        opts = ["male"] * 9 + ["female"] * 9 + [
            "neutral"
        ] * 2 if "truerandom" not in gender else ["male", "female", "neutral"]
        if gender == "orandom":
            opts += ["object"] * 20
        gender = random.choice(opts)

    if not force:
        if gender == "neutral":
            gender = random.choice(["male"] * 9 + ["female"] * 9 +
                                   ["neutral"] * 2)
        elif gender != "object":
            gender = random.choice([gender] * 19 + ["neutral"])

    if gender == "male":
        pset = ("he", "him", "his", "his", "he's")
        set_dialogue_flag(name + "Plu", False)
    elif gender == "female":
        pset = ("she", "her", "her", "hers", "she's")
        set_dialogue_flag(name + "Plu", False)
    elif gender == "object":
        pset = ("it", "it", "its", "its", "it's")
        set_dialogue_flag(name + "Plu", False)
    else:
        pset = ("they", "them", "their", "theirs", "they're")
        set_dialogue_flag(name + "Plu")
        gender = "neutral"

    pmap = ("Ey", "Em", "Eir", "Eirs", "EyIs")
    for i in range(5):
        set_dialogue_var(name + pmap[i], pset[i])

    return gender
示例#35
0
    def become_another(self, customdict=None, tier=None):
        customs = get_custom_items()
        if customdict is None:
            if tier is None:
                candidates = [customs[key] for key in sorted(customs)]
            else:
                candidates = [
                    customs[key] for key in sorted(customs)
                    if customs[key]["tier"] == tier
                ]
            customdict = random.choice(candidates)

        for key in self.features:
            self.features[key] = 0

        def convert_value(v):
            v = v.split()

            def intify(value):
                subintify = lambda x: int(x, 0x10)
                if ',' in value:
                    return random.choice(list(map(subintify,
                                                  value.split(','))))
                else:
                    return subintify(value)

            if len(v) == 1:
                return intify(v[0])
            else:
                return list(map(intify, v))

        name = bytes([])
        for key, value in customdict.items():
            if key == "name_text":
                name = name + name_to_bytes(value, 12)
            elif key == "description":
                pass
            elif key == "tier":
                pass
            else:
                value = convert_value(value)
                if key == "name_icon":
                    name = bytes([value]) + name
                elif hasattr(self, key):
                    setattr(self, key, value)
                elif key in self.features:
                    self.features[key] = value

        self.dataname = name
        self.ban()
    def fill_out(self, additional=None):
        linked = self.linked_entrances
        links = []
        unlinked = []
        for cluster in self.clusters:
            entrances = [e for e in cluster.entrances if e not in linked]
            random.shuffle(entrances)
            if ANCIENT:
                unlinked.extend(entrances)
            else:
                if len(cluster.entrances) <= 4:
                    unlinked.extend(entrances)
                else:
                    diff = len(cluster.entrances) - len(entrances)
                    if diff < 3:
                        remaining = 3 - diff
                        unlinked.extend(entrances[:remaining])

        if additional:
            unlinked.append(additional)

        if not unlinked:
            return
        random.shuffle(unlinked)

        locids = [e.location.locid for e in unlinked]
        maxlocid = max(locids, key=locids.count)
        mosts = [e for e in unlinked if e.location.locid == maxlocid]
        lesses = [e for e in unlinked if e not in mosts]
        for m in mosts:
            if not lesses:
                break
            l = random.choice(lesses)
            links.append((m, l))
            lesses.remove(l)
            unlinked.remove(l)
            unlinked.remove(m)

        extra = None
        while unlinked:
            if len(unlinked) == 1:
                extra = unlinked[0]
                break
            u1 = unlinked.pop()
            u2 = unlinked.pop()
            links.append((u1, u2))

        self.links += links
        return extra
示例#37
0
    def fill_out(self, additional=None):
        linked = self.linked_entrances
        links = []
        unlinked = []
        for cluster in self.clusters:
            entrances = [e for e in cluster.entrances if e not in linked]
            random.shuffle(entrances)
            if ANCIENT:
                unlinked.extend(entrances)
            else:
                if len(cluster.entrances) <= 4:
                    unlinked.extend(entrances)
                else:
                    diff = len(cluster.entrances) - len(entrances)
                    if diff < 3:
                        remaining = 3 - diff
                        unlinked.extend(entrances[:remaining])

        if additional:
            unlinked.append(additional)

        if not unlinked:
            return
        random.shuffle(unlinked)

        locids = [e.location.locid for e in unlinked]
        maxlocid = max(locids, key=lambda l: locids.count(l))
        mosts = [e for e in unlinked if e.location.locid == maxlocid]
        lesses = [e for e in unlinked if e not in mosts]
        for m in mosts:
            if not lesses:
                break
            l = random.choice(lesses)
            links.append((m, l))
            lesses.remove(l)
            unlinked.remove(l)
            unlinked.remove(m)

        extra = None
        while unlinked:
            if len(unlinked) == 1:
                extra = unlinked[0]
                break
            u1 = unlinked.pop()
            u2 = unlinked.pop()
            links.append((u1, u2))

        self.links += links
        return extra
def randomize_passwords():
    passwords = [[], [], []]

    with open_mei_fallback(PASSWORDS_TABLE) as passwords_file:
        i = 0
        for line in passwords_file:
            line = line.split('#')[0].strip()

            if not line:
                continue

            if line.startswith("------") and i < len(passwords) - 1:
                i += 1
                continue

            passwords[i].append(line)

    if all(passwords):
        text = get_dialogue(0xE0)
        text = text.replace("Rose bud", random.choice(passwords[0]))
        text = text.replace("Courage", random.choice(passwords[1]))
        text = text.replace("Failure", random.choice(passwords[2]))

        set_dialogue(0xE0, text)
示例#39
0
 def fill_out(self):
     entrances = list(self.consolidated_entrances)
     seen = []
     for cluster, inter in zip(self.clusters, self.intersegments):
         if cluster.locid == 334 and 11 in cluster.entids:
             additionals = [e for e in cluster.entrances
                            if e not in self.consolidated_entrances]
             assert len(additionals) == 1
             extra = inter.fill_out(additionals[0])
         else:
             extra = inter.fill_out()
         seen.extend([e for e in cluster.entrances if e in entrances])
         for c in inter.clusters:
             seen.extend([e for e in c.entrances if e in entrances])
         if extra is not None:
             backtrack = random.choice(seen)
             self.oneway_entrances.append((extra, backtrack))
 def fill_out(self):
     entrances = list(self.consolidated_entrances)
     seen = []
     for cluster, inter in zip(self.clusters, self.intersegments):
         if cluster.locid == 334 and 11 in cluster.entids:
             additionals = [e for e in cluster.entrances
                            if e not in self.consolidated_entrances]
             assert len(additionals) == 1
             extra = inter.fill_out(additionals[0])
         else:
             extra = inter.fill_out()
         seen.extend([e for e in cluster.entrances if e in entrances])
         for c in inter.clusters:
             seen.extend([e for e in c.entrances if e in entrances])
         if extra is not None:
             backtrack = random.choice(seen)
             self.oneway_entrances.append((extra, backtrack))
def randomize_poem(fout):
    poems = []

    with open_mei_fallback(POEMS_TABLE, encoding='utf8') as poems_file:
        current_poem = []
        page_break = False
        wait = 0
        for line in poems_file:
            line = line.split('#')[0].strip()

            if not line:
                if current_poem:
                    page_break = True
                continue

            if line.startswith("---") and current_poem:
                current_poem.append("<wait 390 frames><wait 1 frame>")
                wait += 1
                poems.append(("".join(current_poem), wait))
                current_poem = []
                page_break = False
                wait = 0
                continue

            if page_break:
                current_poem.append(POEM_PAGE_BREAK)
                wait += 1
                page_break = False
            elif current_poem:
                current_poem.append("<line>")
            current_poem.append(line)

    if not poems:
        return

    text, wait = random.choice(poems)
    set_dialogue(0x9FC, text)
    wait = min(wait * 26 + 2, 255)

    # Adjust wait to be long enough for the poem
    wait_sub = Substitution()
    wait_sub.set_location(0xC401D)
    wait_sub.bytestring = bytes([0xB5, wait])
    wait_sub.write(fout)
示例#42
0
    def mutate_feature(self, feature=None):
        if self.is_consumable or self.is_tool:
            return

        if feature is None:
            feature = random.choice(list(STATPROTECT.keys()))

        nochange = STATPROTECT[feature]
        if feature == 'special2':
            # Allow rare merit award bit on relics
            if self.is_relic:
                if random.randint(1, 10) == 10:
                    nochange &= ~0x20
            # Reduce chance of Genji Glove bit on non-relics
            elif random.randint(1, 4) != 4:
                nochange |= 0x10
        self.features[feature] = bit_mutate(self.features[feature],
                                            op="on",
                                            nochange=nochange)
    def remove_adjacent_entrances(self):
        if not self.has_adjacent_entrances:
            return

        self.entgroups = {}
        for e in self.entrances:
            self.entgroups[e] = set([e])
        for e1 in self.entrances:
            for e2 in self.entrances:
                if e1 == e2:
                    continue
                if ((e1.x == e2.x and abs(e1.y - e2.y) == 1)
                        or (abs(e1.x - e2.x) == 1 and e1.y == e2.y)):
                    self.entgroups[e1].add(e2)

        for e1 in self.entgroups:
            for e2 in self.entgroups[e1]:
                assert self.entgroups[e1] == self.entgroups[e2]

        entgroups = []
        keys = sorted(list(self.entgroups.keys()), key=lambda k: k.entid)
        entids = [k.entid for k in keys]
        assert len(entids) == len(set(entids))
        for key in keys:
            entgroup = self.entgroups[key]
            if entgroup not in entgroups:
                entgroups.append(entgroup)

        for eg1 in entgroups:
            for eg2 in entgroups:
                if eg1 == eg2:
                    continue
                assert eg1 & eg2 == set([])

        for entgroup in entgroups:
            if len(entgroup) > 1:
                entgroup = sorted(entgroup, key=lambda e: e.entid)
                ent = random.choice(entgroup)
                for e in entgroup:
                    if e != ent:
                        self.entrances.remove(e)

        assert self.has_adjacent_entrances
示例#44
0
    def remove_adjacent_entrances(self):
        if not self.has_adjacent_entrances:
            return

        self.entgroups = {}
        for e in self.entrances:
            self.entgroups[e] = set([e])
        for e1 in self.entrances:
            for e2 in self.entrances:
                if e1 == e2:
                    continue
                if ((e1.x == e2.x and abs(e1.y - e2.y) == 1) or
                        (abs(e1.x - e2.x) == 1 and e1.y == e2.y)):
                    self.entgroups[e1].add(e2)

        for e1 in self.entgroups:
            for e2 in self.entgroups[e1]:
                assert self.entgroups[e1] == self.entgroups[e2]

        entgroups = []
        keys = sorted(self.entgroups.keys(), key=lambda k: k.entid)
        entids = [k.entid for k in keys]
        assert len(entids) == len(set(entids))
        for key in keys:
            entgroup = self.entgroups[key]
            if entgroup not in entgroups:
                entgroups.append(entgroup)

        for eg1 in entgroups:
            for eg2 in entgroups:
                if eg1 == eg2:
                    continue
                assert eg1 & eg2 == set([])

        for entgroup in entgroups:
            if len(entgroup) > 1:
                entgroup = sorted(entgroup, key=lambda e: e.entid)
                ent = random.choice(entgroup)
                for e in entgroup:
                    if e != ent:
                        self.entrances.remove(e)

        assert self.has_adjacent_entrances
示例#45
0
    def become_another(self, customdict=None):
        customs = get_custom_items()
        if customdict is None:
            customdict = random.choice(
                [customs[key] for key in sorted(customs)])

        for key in self.features:
            self.features[key] = 0

        def convert_value(v):
            v = v.split()

            def intify(value):
                subintify = lambda x: int(x, 0x10)
                if ',' in value:
                    return random.choice(map(subintify, value.split(',')))
                else:
                    return subintify(value)

            if len(v) == 1:
                return intify(v[0])
            else:
                return map(intify, v)

        name = []
        for key, value in customdict.items():
            if key == "name_text":
                name = name + name_to_bytes(value, 12)
            elif key == "description":
                pass
            else:
                value = convert_value(value)
                if key == "name_icon":
                    name = [value] + name
                elif hasattr(self, key):
                    setattr(self, key, value)
                elif key in self.features:
                    self.features[key] = value

        self.dataname = name
        self.ban()
示例#46
0
def randomize_fanatics(unused_locids):
    stairs = [get_location(i) for i in [363, 359, 360, 361]]
    pitstops = [get_location(i) for i in [365, 367, 368, 369]]
    num_new_levels = random.randint(0, 1) + random.randint(1, 2)
    unused_locations = [get_location(l) for l in unused_locids]
    fsets = get_new_fsets("fanatics", 10, supplement=False)
    for _ in xrange(num_new_levels):
        stair = unused_locations.pop()
        stop = unused_locations.pop()
        stair.copy(random.choice(stairs[1:-1]))
        stop.copy(random.choice(pitstops[1:]))
        add_location_map("Fanatics Tower", stair.locid)
        add_location_map("Fanatics Tower", stop.locid)
        index = random.randint(1, len(stairs)-1)
        stairs.insert(index, stair)
        pitstops.insert(index, stop)

        chest = stop.chests[0]
        chest.set_new_id()

        entrance = stop.entrances[0]
        entrance.dest = (entrance.dest & 0xFE00) | (stair.locid & 0x1FF)

        entrance = sorted(stair.entrances, key=lambda e: e.y)[1]
        entrance.dest = (entrance.dest & 0xFE00) | (stop.locid & 0x1FF)

        stair.setid = random.choice(fsets).setid
        stop.setid = random.choice(fsets).setid

    for a, b in zip(stairs, stairs[1:]):
        lower = sorted(a.entrances, key=lambda e: e.y)[0]
        upper = sorted(b.entrances, key=lambda e: e.y)[-1]
        lower.dest = (lower.dest & 0xFE00) | (b.locid & 0x1FF)
        upper.dest = (upper.dest & 0xFE00) | (a.locid & 0x1FF)

    for stop in pitstops:
        if random.choice([True, False]):
            continue
        index = pitstops.index(stop)
        if index == 0:
            continue
        index2 = index + random.choice([-1, -1, -2])
        if index2 < 0:
            index2 = 0
        stair = stairs[index2]
        entrance = stop.entrances[0]
        entrance.dest = (entrance.dest & 0xFE00) | (stair.locid & 0x1FF)
def randomize_fanatics(unused_locids):
    stairs = [get_location(i) for i in [363, 359, 360, 361]]
    pitstops = [get_location(i) for i in [365, 367, 368, 369]]
    num_new_levels = random.randint(0, 1) + random.randint(1, 2)
    unused_locations = [get_location(l) for l in unused_locids]
    fsets = get_new_fsets("fanatics", 10, supplement=False)
    for _ in range(num_new_levels):
        stair = unused_locations.pop()
        stop = unused_locations.pop()
        stair.copy(random.choice(stairs[1:-1]))
        stop.copy(random.choice(pitstops[1:]))
        add_location_map("Fanatics Tower", stair.locid)
        add_location_map("Fanatics Tower", stop.locid)
        index = random.randint(1, len(stairs) - 1)
        stairs.insert(index, stair)
        pitstops.insert(index, stop)

        chest = stop.chests[0]
        chest.set_new_id()

        entrance = stop.entrances[0]
        entrance.dest = (entrance.dest & 0xFE00) | (stair.locid & 0x1FF)

        entrance = sorted(stair.entrances, key=lambda e: e.y)[1]
        entrance.dest = (entrance.dest & 0xFE00) | (stop.locid & 0x1FF)

        stair.setid = random.choice(fsets).setid
        stop.setid = random.choice(fsets).setid

    for a, b in zip(stairs, stairs[1:]):
        lower = sorted(a.entrances, key=lambda e: e.y)[0]
        upper = sorted(b.entrances, key=lambda e: e.y)[-1]
        lower.dest = (lower.dest & 0xFE00) | (b.locid & 0x1FF)
        upper.dest = (upper.dest & 0xFE00) | (a.locid & 0x1FF)

    for stop in pitstops:
        if random.choice([True, False]):
            continue
        index = pitstops.index(stop)
        if index == 0:
            continue
        index2 = index + random.choice([-1, -1, -2])
        if index2 < 0:
            index2 = 0
        stair = stairs[index2]
        entrance = stop.entrances[0]
        entrance.dest = (entrance.dest & 0xFE00) | (stair.locid & 0x1FF)
示例#48
0
        def mutate_nibble(byte, left=False, limit=7):
            if left:
                nibble = (byte & 0xf0) >> 4
                byte = byte & 0x0f
            else:
                nibble = byte & 0x0f
                byte = byte & 0xf0

            value = nibble & 0x7
            if nibble & 0x8:
                value = value * -1

            while random.randint(1, 6) == 6:
                value += random.choice([1, -1])

            value = max(-limit, min(value, limit))
            nibble = abs(value)
            if value < 0:
                nibble = nibble | 0x8

            if left:
                return byte | (nibble << 4)
            else:
                return byte | nibble
示例#49
0
def reset_special_relics(items, characters, fout):
    global changed_commands
    characters = [c for c in characters if c.id < 14]
    changedict = {}
    loglist = []

    hidden_commands = set(range(0, 0x1E)) - set(invalid_commands)
    for c in characters:
        hidden_commands = hidden_commands - set(c.battle_commands)
    if 0x1D in hidden_commands and random.randint(1, 3) != 3:
        hidden_commands.remove(0x1D)

    flags = [0x04, 0x08, 0x10, 0x20, 0x40]
    random.shuffle(flags)
    for flag in flags:
        if changedict:
            donebefore, doneafter = tuple(zip(*changedict.values()))
            donebefore, doneafter = set(donebefore), set(doneafter)
        else:
            donebefore, doneafter = set([]), set([])
        while True:
            if flag == 0x08:
                candidates = set([0x0, 0x1, 0x2, 0x12])
            else:
                candidates = range(0, 0x1E)
                candidates = set(candidates) - set([0x04, 0x14, 0x15, 0x19])

            if random.randint(1, 5) != 5:
                candidates = candidates - donebefore

            candidates = sorted(candidates)
            before = random.choice(candidates)

            if before == 0:
                tempchars = [c for c in characters]
            else:
                tempchars = [c for c in characters if before in c.battle_commands]

            if not tempchars:
                continue

            unused = set(range(0, 0x1E)) - set(invalid_commands)
            if len(tempchars) <= 4:
                for t in tempchars:
                    unused = unused - set(t.battle_commands)

            if flag == 0x08:
                unused = unused - changed_commands

            if set(hidden_commands) & set(unused):
                unused = set(hidden_commands) & set(unused)

            if before in unused:
                unused.remove(before)

            if random.randint(1, 5) != 5:
                unused = unused - doneafter

            if not unused:
                continue

            after = random.choice(sorted(unused))
            if after in hidden_commands:
                hidden_commands.remove(after)

            for ptrdict in [sperelic, sperelic2]:
                beforeptr, afterptr = ptrdict[flag]
                fout.seek(beforeptr)
                fout.write(chr(before))
                fout.seek(afterptr)
                fout.write(chr(after))
            break
        changedict[flag] = (before, after)

    for item in items:
        if (item.is_consumable or item.is_tool or
                not item.features['special1'] & 0x7C):
            continue

        if item.itemid == 0x67:
            continue

        item.equippable &= IMP_MASK
        item.equippable |= 1 << 12  # gogo
        for flag in [0x04, 0x08, 0x10, 0x20, 0x40]:
            if flag & item.features['special1']:
                before, after = changedict[flag]
                tempchars = [c for c in characters
                             if before in c.battle_commands]
                for t in tempchars:
                    item.equippable |= (1 << t.id)

                item.write_stats(fout)
                loglist.append((item.name, before, after))

    return loglist
示例#50
0
 def __init__(self, spells):
     self.spells = spells
     self.spellsubs = []
     self.random_order = random.choice([True, False, False])
     for s in self.spells:
         self.spellsubs.append(SpellSub(spellid=s.spellid))
示例#51
0
    def interconnect(self):
        links = []
        for segment in self.intersegments:
            segment.interconnect()
        for i, (a, b) in enumerate(zip(self.clusters, self.clusters[1:])):
            aid = self.entids[i]
            bid = self.entids[i+1]
            if a.singleton:
                acands = a.entrances
            elif i == 0:
                acands = [e for e in a.entrances if e.entid == aid]
            else:
                acands = [e for e in a.entrances if e.entid != aid]
            aent = random.choice(acands)
            bcands = [e for e in b.entrances if e.entid == bid]
            bent = bcands[0]
            inter = self.intersegments[i]
            if a.singleton:
                previnter = self.intersegments[i-1] if i > 0 else None
                thresh = 3
                for j in xrange(thresh):
                    k = thresh-j
                    intercands = []
                    excands = inter.get_external_candidates(num=k, test=True)
                    if excands:
                        intercands.append(inter)
                    k = max(1, k-1)
                    if previnter is not None:
                        excands = previnter.get_external_candidates(num=k,
                                                                    test=True)
                        if excands:
                            intercands.append(previnter)
                    if intercands:
                        break
                else:
                    raise Exception("No available intersegments.")
                chosen = random.choice(intercands)
                excands = (chosen.get_external_candidates(num=1))
                if excands is None:
                    raise Exception("Routing error.")
                links.append((aent, excands[0]))
                a.entering, a.exiting = True, True

                if previnter and not previnter.empty:
                    # TODO: Sometimes this fails
                    for j in range(i, len(self.intersegments)):
                        nextinter = self.intersegments[j]
                        if nextinter.empty:
                            continue
                        c = previnter.get_external_candidates(num=1)[0]
                        d = nextinter.get_external_candidates(num=1)[0]
                        links.append((c, d))
                        break
                    else:
                        raise Exception("No exit segment available.")
            elif not inter.empty:
                if not b.singleton:
                    excands = inter.get_external_candidates(num=2)
                    if excands is None:
                        raise Exception("No exit segment available. (2)")
                    random.shuffle(excands)
                    links.append((bent, excands[1]))
                    b.entering = True
                else:
                    excands = inter.get_external_candidates(num=1)
                links.append((aent, excands[0]))
                a.exiting = True
            elif (inter.empty and not b.singleton):
                links.append((aent, bent))
                a.exiting = True
                b.entering = True
            elif (inter.empty and b.singleton):
                inter2 = self.intersegments[i+1]
                assert not inter2.empty
                excands = inter2.get_external_candidates(num=1)
                links.append((aent, excands[0]))
                a.exiting = True
            else:
                import pdb; pdb.set_trace()
                assert False

        for i, a in enumerate(self.clusters):
            aid = self.entids[i]
            if not (a.entering or i == 0):
                if a.singleton:
                    aent = a.entrances[0]
                else:
                    acands = [e for e in a.entrances if e.entid == aid]
                    aent = acands[0]
                while i > 0:
                    inter = self.intersegments[i-1]
                    if not inter.empty:
                        break
                    i += -1
                if inter.empty:
                    raise Exception("Routing error.")
                excands = inter.get_external_candidates(num=1)
                links.append((aent, excands[0]))
                a.entering = True

        self.links = links
        self.check_links()
示例#52
0
 def intify(value):
     subintify = lambda x: int(x, 0x10)
     if ',' in value:
         return random.choice(map(subintify, value.split(',')))
     else:
         return subintify(value)
示例#53
0
def parse_checkpoints():
    if ANCIENT:
        checkpoints = ANCIENT_CHECKPOINTS_TABLE
    else:
        checkpoints = TOWER_CHECKPOINTS_TABLE

    def ent_text_to_ints(room, single=False):
        locid, entids = room.split(':')
        locid = int(locid)
        if '|' in entids:
            entids = entids.split('|')
        elif ',' in entids:
            entids = entids.split(',')
        elif '>' in entids:
            entids = entids.split('>')[:1]
        else:
            entids = [entids]
        entids = map(int, entids)
        if single:
            assert len(entids) == 1
            entids = entids[0]
        return locid, entids

    done, fixed, remove, oneway = [], [], [], []
    routes = [list([]) for _ in xrange(3)]
    for line in open(checkpoints):
        line = line.strip()
        if not line or line[0] == '#':
            continue
        if line[0] == 'R':
            rank = int(line[1:])
            for route in routes:
                route[-1].append(("R", rank))
        elif line[0] == '&':
            locid, entids = ent_text_to_ints(line[1:])
            for e in entids:
                fixed.append((locid, e))
        elif line[0] == '-':
            locid, entids = ent_text_to_ints(line[1:])
            for e in entids:
                remove.append((locid, e))
        elif '>>' in line:
            line = line.split('>>')
            line = [ent_text_to_ints(s, single=True) for s in line]
            first, second = tuple(line)
            oneway.append((first, second))
        else:
            if line.startswith("!"):
                line = line.strip("!")
                for route in routes:
                    route.append([])
            elif line.startswith("$"):
                line = line.strip("$")
                for route in routes:
                    subroute = route[-1]
                    head, tail = subroute[0], subroute[1:]
                    random.shuffle(tail)
                    route[-1] = [head] + tail
            else:
                random.shuffle(routes)
            rooms = line.split(',')
            chosenrooms = []
            for room in rooms:
                locid, entids = ent_text_to_ints(room)
                candidates = [(locid, entid) for entid in entids]
                candidates = [c for c in candidates if c not in done]
                chosen = random.choice(candidates)
                chosenrooms.append(chosen)
                done.append(chosen)
            for room, route in zip(chosenrooms, routes):
                route[-1].append(room)

    for first, second in oneway:
        done = False
        for route in routes:
            for subroute in route:
                if first in subroute:
                    index = subroute.index(first)
                    index = random.randint(1, index+1)
                    subroute.insert(index, second)
                    done = True
        if not done:
            raise Exception("Unknown oneway rule")

    for route in routes:
        for i in range(len(route)):
            route[i] = Segment(route[i])

    for index in range(len(routes)):
        routes[index] = Route(routes[index])

    FIXED_ENTRANCES.extend(fixed)
    REMOVE_ENTRANCES.extend(remove)
    return routes
示例#54
0
def assign_maps(routes, nummaps=None):
    clusters = get_clusters()
    new_clusters = clusters
    for route in routes:
        for segment in route.segments:
            for cluster in segment.clusters:
                if cluster in new_clusters:
                    new_clusters.remove(cluster)

    for c in new_clusters:
        c.remove_adjacent_entrances()

    similars = []

    def is_too_similar(c):
        if c.locid in towerlocids:
            return False
        if len(c.entrances) == 1:
            return False
        loc = get_location(c.locid)
        layer1 = loc.layer1ptr
        palette = loc.palette_index
        entxys = set([(e.x, e.y) for e in c.entrances])
        for l, p, xys in similars:
            if layer1 == l and palette == p:
                if xys & entxys:
                    return True
        similars.append((layer1, palette, entxys))
        return False

    # first phase - bare minimum
    max_new_maps = nummaps
    best_clusters = [c for c in new_clusters if len(c.entrances) >= 3]
    while True:
        random.shuffle(best_clusters)
        done_maps, done_clusters = set([]), set([])
        for cluster in best_clusters:
            location = get_location(cluster.locid)
            if (cluster.locid not in towerlocids and len(location.chests) == 0
                    and random.choice([True, False])):
                continue
            if cluster.locid in done_maps:
                continue
            chosen = None
            for route in routes:
                for segment in route.segments:
                    for inter in segment.intersegments:
                        if chosen is None or chosen.need < inter.need:
                            chosen = inter
            if chosen.need > 0:
                if is_too_similar(cluster):
                    continue
                chosen.add_cluster(cluster, need=True)
                done_maps.add(cluster.locid)
                done_clusters.add(cluster.clusterid)
        if len(done_maps) <= max_new_maps:
            break
        else:
            for route in routes:
                for segment in route.segments:
                    segment.intersegments = [InterSegment()
                                             for _ in segment.intersegments]

    # second phase -supplementary
    random.shuffle(new_clusters)
    for cluster in new_clusters:
        CAPACITY_RATIO = len(done_maps) / float(max_new_maps)
        if cluster.clusterid in done_clusters:
            continue
        if cluster.locid in done_maps and not ANCIENT:
            continue
        if cluster.locid not in towerlocids:
            if (cluster.locid not in done_maps
                    and len(done_maps) >= max_new_maps):
                continue
            if (cluster.locid in done_maps and len(done_maps) >= max_new_maps
                    and get_location(cluster.locid).longentrances):
                continue
        rank = None
        if cluster.locid in done_maps or cluster.locid in towerlocids:
            for route in routes:
                for segment in route.segments:
                    for c1 in segment.clusters:
                        if c1.locid == cluster.locid:
                            temp = route.segments.index(segment)
                            if rank is None:
                                rank = temp
                            else:
                                rank = min(rank, temp)
                    for inter in segment.intersegments:
                        for c2 in inter.clusters:
                            if c2.locid == cluster.locid:
                                temp = route.segments.index(segment)
                                if rank is None:
                                    rank = temp
                                else:
                                    rank = min(rank, temp)
        location = get_location(cluster.locid)
        if (cluster.locid not in towerlocids and CAPACITY_RATIO > 0.2
                and len(cluster.entrances) <= 2 and len(location.chests) == 0
                and random.choice([True, False])):
            continue
        if len(cluster.entrances) == 1:
            candidates = []
            for route in routes:
                for (i, segment) in enumerate(route.segments):
                    if rank is not None and i != rank:
                        continue
                    for inter in segment.intersegments:
                        if inter.need < 0:
                            candidates.append(inter)
            if candidates:
                if is_too_similar(cluster):
                    continue
                chosen = random.choice(candidates)
                chosen.add_cluster(cluster, need=True)
                done_maps.add(cluster.locid)
                done_clusters.add(cluster.clusterid)
        elif len(cluster.entrances) >= 2:
            if cluster.locid not in towerlocids:
                if (CAPACITY_RATIO > 0.5 and len(location.chests) == 0
                        and random.randint(1, 3) == 3):
                    continue
                if is_too_similar(cluster):
                    continue
            route = random.choice(routes)
            if rank is not None:
                segment = route.segments[rank]
            else:
                segment = random.choice(route.segments)
            chosen = random.choice(segment.intersegments)
            chosen.add_cluster(cluster, need=True)
            done_maps.add(cluster.locid)
            done_clusters.add(cluster.clusterid)

    for route in routes:
        for segment in route.segments:
            segment.interconnect()
示例#55
0
def remap_maps(routes):
    conlinks = []
    cononeways = []
    conentrances = []
    conclusters = []
    for route in routes:
        conlinks.extend(route.consolidated_links)
        cononeways.extend(route.consolidated_oneways)
        conentrances.extend(route.consolidated_entrances)
        conclusters.extend(route.consolidated_clusters)
        conclusters = sorted(set(conclusters), key=lambda c: c.clusterid)

    if ANCIENT:
        unused_maps = [l.locid for l in get_locations()
                       if l.locid not in towerlocids
                       and l.locid not in PROTECTED]
        rest_maps = [l.locid for l in get_unused_locations() if l.locid != 414]
    else:
        unused_maps = [l.locid for l in get_unused_locations()]
        rest_maps = []

    for cluster in conclusters:
        if not isinstance(cluster, RestStop):
            continue
        locid = cluster.locid
        newlocid = rest_maps.pop()
        locexchange[(locid, locid)] = newlocid
        try:
            unused_maps.remove(newlocid)
        except:
            import pdb; pdb.set_trace()

    for cluster in conclusters:
        if isinstance(cluster, RestStop):
            continue

        locid = cluster.locid
        if (locid, cluster.clusterid) in locexchange:
            continue

        locclusters = [c for c in conclusters if
                       not isinstance(c, RestStop) and c.locid == locid]
        if locid in towerlocids:
            for c in locclusters:
                locexchange[(locid, c.clusterid)] = locid
        else:
            location = get_location(locid)
            if locid in unused_maps:
                newlocid = locid
                unused_maps = [u for u in unused_maps if u != newlocid]
            else:
                newlocid = unused_maps.pop()
            if location.longentrances:
                locexchange[(locid, cluster.clusterid)] = newlocid
            else:
                for c in locclusters:
                    locexchange[(locid, c.clusterid)] = newlocid

    newlocations = []
    for newlocid in sorted(set(locexchange.values())):
        keys = [key for (key, value) in locexchange.items()
                if value == newlocid]
        assert len(set([a for (a, b) in keys])) == 1
        copylocid = keys[0][0]
        if copylocid >= 1000:
            cluster = [c for c in conclusters if c.locid == copylocid][0]
            copylocid = 413
            location = get_location(413)
            newlocation = Location(locid=newlocid, dummy=True)
            newlocation.copy(location)
            newlocation.events = []
            newlocation.npcs = []
            newlocation.entrance_set.entrances = []
            newlocation.restrank = cluster.rank
        else:
            location = get_location(copylocid)
            entrances = location.entrances
            newlocation = Location(locid=newlocid, dummy=True)
            newlocation.copy(location)
            newlocation.events = []
            newlocation.npcs = []
            newlocation.entrance_set.entrances = []
            fixed = [e for e in entrances
                     if (e.location.locid, e.entid) in FIXED_ENTRANCES]
            newlocation.entrance_set.entrances.extend(fixed)

        locclusters = [c for c in conclusters if
                       locexchange[(c.locid, c.clusterid)] == newlocid]
        clustents = [e for c in locclusters for e in c.entrances]
        clustents = [e for e in clustents if e in conentrances]

        for ent in clustents:
            destent = [(a, b) for (a, b) in conlinks if ent in (a, b)]
            destent += [(a, b) for (a, b) in cononeways if ent == a]
            assert len(destent) == 1
            destent = destent[0]
            destent = [d for d in destent if d != ent][0]
            destclust = [c for c in conclusters
                         if destent in c.entrances]
            assert len(destclust) == 1
            destclust = destclust[0]
            newdestlocid = locexchange[(destclust.locid, destclust.clusterid)]
            if destent.location.locid >= 1000:
                destloc = get_location(413)
                destent = [d for d in destloc.entrances if d.entid == 3][0]
            else:
                destloc = get_location(destent.location.locid)
                destent = [d for d in destloc.entrances
                           if d.entid == destent.entid][0]
            mirror = destent.mirror
            if mirror:
                dest = mirror.dest & 0xFE00
                destx, desty = mirror.destx, mirror.desty
                if abs(destx - destent.x) + abs(desty - destent.y) > 3:
                    mirror = None

            if not mirror:
                dest, destx, desty = 0x2000, destent.x, destent.y
            dest &= 0x3DFF

            dest |= newdestlocid
            entrance = Entrance()
            entrance.x, entrance.y = ent.x, ent.y
            entrance.dest, entrance.destx, entrance.desty = dest, destx, desty
            entrance.set_location(newlocation)
            newlocation.entrance_set.entrances.append(entrance)

        newlocation.setid = 0
        newlocation.ancient_rank = 0
        newlocation.copied = copylocid

        adjents = []
        for ent in newlocation.entrances:
            for clust in locclusters:
                if isinstance(clust, RestStop):
                    continue
                assert clust.locid == newlocation.copied
                if clust.has_adjacent_entrances:
                    x, y = ent.x, ent.y
                    for ent2 in clust.entgroups.keys():
                        if ent2.x == ent.x and ent2.y == ent.y:
                            break
                    else:
                        continue
                    entgroup = clust.entgroups[ent2]
                    for ent3 in entgroup:
                        x3, y3 = ent3.x, ent3.y
                        if x == x3 and y == y3:
                            continue
                        entrance = Entrance()
                        entrance.x, entrance.y = x3, y3
                        entrance.dest, entrance.destx, entrance.desty = (
                            ent.dest, ent.destx, ent.desty)
                        entrance.set_location(newlocation)
                        adjents.append(entrance)
        newlocation.entrance_set.entrances.extend(adjents)

        newlocations.append(newlocation)

    locations = get_locations()
    newlocids = [l.locid for l in newlocations]
    assert len(newlocids) == len(set(newlocids))
    for location in newlocations:
        for e in location.entrances:
            if (location.locid, e.entid) not in FIXED_ENTRANCES:
                assert e.dest & 0x1FF in newlocids
        assert location not in locations
        if location.locid not in towerlocids:
            location.entrance_set.convert_longs()

    # XXX: Unnecessary???
    for i, loc in enumerate(newlocations):
        if loc.locid in towerlocids:
            oldloc = get_location(loc.locid)
            oldloc.entrance_set.entrances = loc.entrances
            oldloc.ancient_rank = loc.ancient_rank
            oldloc.copied = oldloc.locid
            newlocations[i] = oldloc

    ranked_clusters = []
    for n in range(len(routes[0].segments)):
        rankedcsets = [route.segments[n].ranked_clusters for route in routes]
        for tricluster in izip_longest(*rankedcsets, fillvalue=None):
            tricluster = list(tricluster)
            random.shuffle(tricluster)
            for cluster in tricluster:
                if cluster is None:
                    continue
                if cluster.locid not in ranked_clusters:
                    cluster.routerank = n
                    ranked_clusters.append(cluster)

    ranked_locations = []
    for cluster in ranked_clusters:
        locid, clusterid = cluster.locid, cluster.clusterid
        newlocid = locexchange[locid, clusterid]
        newloc = [l for l in newlocations if l.locid == newlocid][0]
        if newloc not in ranked_locations:
            newloc.routerank = cluster.routerank
            ranked_locations.append(newloc)
    assert len(set(ranked_locations)) == len(set(newlocations))

    ranked_locations = [l for l in ranked_locations
                        if not hasattr(l, "restrank")]
    for i, loc in enumerate(ranked_locations):
        loc.ancient_rank = i
        loc.make_tower_basic()
        if not ANCIENT:
            if loc.locid not in towerlocids:
                loc.make_tower_flair()
                loc.unlock_chests(200, 1000)
                fsets = get_new_fsets("kefka's tower", 20)
                fset = random.choice(fsets)
                for formation in fset.formations:
                    formation.set_music(6)
                    formation.set_continuous_music()
                loc.setid = fset.setid

    switch292, gate292 = (292, 0), (292, 1)
    switch334, gate334 = (334, 5), (334, 3)
    swd = {switch292: None,
           switch334: None,
           gate292: None,
           gate334: None}
    segments = [s for route in routes for s in route.segments]
    for segment in segments:
        for cluster in segment.ranked_clusters:
            for key in swd.keys():
                locid, entid = key
                if cluster.locid == locid and entid in cluster.entids:
                    assert swd[key] is None
                    swd[key] = (segment, cluster)
    assert None not in swd.values()

    s292segment, s292cluster = swd[switch292]
    s334segment, s334cluster = swd[switch334]
    g292segment, g292cluster = swd[gate292]
    g334segment, g334cluster = swd[gate334]
    if s292segment == g334segment and s334segment == g292segment:
        assert s292segment != s334segment
        ranked292 = s292segment.ranked_clusters
        ranked334 = s334segment.ranked_clusters
        if (ranked292.index(s292cluster) > ranked292.index(g334cluster) and
                ranked334.index(s334cluster) > ranked334.index(g292cluster)):
            raise Exception("Dungeon cannot be completed with this layout.")

    return newlocations, unused_maps