From 5539143f003a9e661e99015f60d39218996d72dc Mon Sep 17 00:00:00 2001 From: Kevin Cathcart Date: Sat, 22 Sep 2018 22:51:54 -0400 Subject: [PATCH] v30 updates --- BaseClasses.py | 15 ++++++- Gui.py | 2 +- ItemList.py | 6 +-- Main.py | 2 +- README.md | 2 +- Regions.py | 22 ++++++----- Rom.py | 105 ++++++++++++++++++++----------------------------- Rules.py | 1 + Text.py | 17 ++++---- Utils.py | 6 +++ 10 files changed, 93 insertions(+), 85 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 264f4b9d..0a36e4c5 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -45,7 +45,7 @@ class World(object): self.aga_randomness = True self.lock_aga_door_in_escape = False self.fix_trock_doors = self.shuffle != 'vanilla' - self.save_and_quit_from_boss = False + self.save_and_quit_from_boss = True self.check_beatable_only = check_beatable_only self.fix_skullwoods_exit = self.shuffle not in ['vanilla', 'simple', 'restricted', 'dungeonssimple'] self.fix_palaceofdarkness_exit = self.shuffle not in ['vanilla', 'simple', 'restricted', 'dungeonssimple'] @@ -456,6 +456,16 @@ class CollectionState(object): return self.has('Bow') and (self.has('Silver Arrows') or self.can_buy_unlimited('Single Arrow')) return self.has('Bow') + def can_get_good_bee(self): + cave = self.world.get_region('Good Bee Cave') + return ( + self.has_bottle() and + self.has('Bug Catching Net') and + (self.has_Boots() or (self.has_sword() and self.has('Quake'))) and + cave.can_reach(self) and + (cave.is_light_world or self.has_Pearl()) + ) + def has_sword(self): return self.has('Fighter Sword') or self.has('Master Sword') or self.has('Tempered Sword') or self.has('Golden Sword') @@ -775,6 +785,7 @@ class Crystal(Item): class ShopType(Enum): Shop = 0 TakeAny = 1 + UpgradeShop = 2 class Shop(object): def __init__(self, region, room_id, type, shopkeeper_config, replaceable): @@ -804,6 +815,8 @@ class Shop(object): config |= 0x40 # ignore door id if self.type == ShopType.TakeAny: config |= 0x80 + if self.type == ShopType.UpgradeShop: + config |= 0x10 # Alt. VRAM return [0x00]+int16_as_bytes(self.room_id)+[door_id, 0x00, config, self.shopkeeper_config, 0x00] def has_unlimited(self, item): diff --git a/Gui.py b/Gui.py index 2b806179..b42d5d50 100755 --- a/Gui.py +++ b/Gui.py @@ -1114,7 +1114,7 @@ class SpriteSelector(object): try: task.update_status("Downloading official sprites list") - with urlopen('http://vt.alttp.run/sprites') as response: + with urlopen('https://alttpr.com/sprites') as response: sprites_arr = json.loads(response.read().decode("utf-8")) except Exception as e: resultmessage = "Error getting list of official sprites. Sprites not updated.\n\n%s: %s" % (type(e).__name__, e) diff --git a/ItemList.py b/ItemList.py index e25c9f07..5c89e075 100644 --- a/ItemList.py +++ b/ItemList.py @@ -20,9 +20,9 @@ basicgloves = ['Power Glove', 'Titans Mitts'] normalbottles = ['Bottle', 'Bottle (Red Potion)', 'Bottle (Green Potion)', 'Bottle (Blue Potion)', 'Bottle (Fairy)', 'Bottle (Bee)', 'Bottle (Good Bee)'] hardbottles = ['Bottle', 'Bottle (Red Potion)', 'Bottle (Green Potion)', 'Bottle (Blue Potion)', 'Bottle (Bee)', 'Bottle (Good Bee)'] -normalbaseitems = (['Silver Arrows', 'Magic Upgrade (1/2)', 'Single Arrow', 'Sanctuary Heart Container', 'Arrow Upgrade (+10)', 'Bomb Upgrade (+10)'] + +normalbaseitems = (['Silver Arrows', 'Magic Upgrade (1/2)', 'Single Arrow', 'Sanctuary Heart Container', 'Arrows (10)', 'Bombs (3)'] + ['Rupees (300)'] * 4 + ['Boss Heart Container'] * 10 + ['Piece of Heart'] * 24) -normalfirst15extra = ['Rupees (100)', 'Rupees (300)', 'Rupees (50)'] + ['Arrow Upgrade (+5)'] * 6 + ['Bomb Upgrade (+5)'] * 6 +normalfirst15extra = ['Rupees (100)', 'Rupees (300)', 'Rupees (50)'] + ['Arrows (10)'] * 6 + ['Bombs (3)'] * 6 normalsecond15extra = ['Bombs (3)'] * 9 + ['Rupees (50)'] * 2 + ['Arrows (10)'] * 2 + ['Rupee (1)'] + ['Bombs (10)'] normalthird10extra = ['Rupees (50)'] * 4 + ['Rupees (20)'] * 3 + ['Arrows (10)', 'Rupee (1)', 'Rupees (5)'] normalfourth5extra = ['Arrows (10)'] * 2 + ['Rupees (20)'] * 2 + ['Rupees (5)'] @@ -33,7 +33,7 @@ easybaseitems = (['Sanctuary Heart Container'] + ['Rupees (300)'] * 4 + ['Magic ['Boss Heart Container'] * 10 + ['Piece of Heart'] * 12) easyextra = ['Piece of Heart'] * 12 + ['Rupees (300)'] easylimitedextra = ['Boss Heart Container'] * 3 # collapsing down the 12 pieces of heart -easyfirst15extra = ['Rupees (100)', 'Arrow Upgrade (+10)', 'Bomb Upgrade (+10)'] + ['Arrow Upgrade (+5)'] * 6 + ['Bomb Upgrade (+5)'] * 6 +easyfirst15extra = ['Rupees (100)'] + ['Arrows (10)'] * 7 + ['Bombs (3)'] * 7 easysecond10extra = ['Bombs (3)'] * 7 + ['Rupee (1)', 'Rupees (50)', 'Bombs (10)'] easythird5extra = ['Rupees (50)'] * 2 + ['Bombs (3)'] * 2 + ['Arrows (10)'] easyfinal25extra = ['Rupees (50)'] * 4 + ['Rupees (20)'] * 14 + ['Rupee (1)'] + ['Arrows (10)'] * 4 + ['Rupees (5)'] * 2 diff --git a/Main.py b/Main.py index 9d230e33..e7a9cb55 100644 --- a/Main.py +++ b/Main.py @@ -6,7 +6,7 @@ import logging import random import time -from BaseClasses import World, CollectionState, Item, Region, Location, Entrance, Shop +from BaseClasses import World, CollectionState, Item, Region, Location, Shop from Regions import create_regions, mark_light_world_regions from EntranceShuffle import link_entrances from Rom import patch_rom, Sprite, LocalRom, JsonRom diff --git a/README.md b/README.md index a9b5fb3d..1443a095 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # ALttPEntranceRandomizer This is a entrance randomizer for _The Legend of Zelda: A Link to the Past_ for the SNES. -See http://vt.alttp.run for more details on the normal randomizer. +See https://alttpr.com/ for more details on the normal randomizer. # Installation diff --git a/Regions.py b/Regions.py index b68595b3..b0aee49c 100644 --- a/Regions.py +++ b/Regions.py @@ -299,6 +299,10 @@ def create_regions(world): for index, (item, price) in enumerate(default_shop_contents[region_name]): shop.add_inventory(index, item, price) + region = world.get_region('Capacity Upgrade') + shop = Shop(region, 0x0115, ShopType.UpgradeShop, 0x04, True) + shop.add_inventory(0, 'Bomb Upgrade (+5)', 100, 7) + shop.add_inventory(1, 'Arrow Upgrade (+5)', 100, 7) world.intialize_regions() def create_lw_region(name, locations=None, exits=None): @@ -358,15 +362,15 @@ def mark_light_world_regions(world): # (room_id, shopkeeper, replaceable) shop_table = { - 'Cave Shop (Dark Death Mountain)': (0x0112, 0x51, True), - 'Red Shield Shop': (0x0110, 0x51, True), - 'Dark Lake Hylia Shop': (0x010F, 0x51, True), - 'Dark World Lumberjack Shop': (0x010F, 0x51, True), - 'Village of Outcasts Shop': (0x010F, 0x51, True), - 'Dark World Potion Shop': (0x010F, 0x51, True), - 'Light World Death Mountain Shop': (0x00FF, 0x51, True), - 'Kakariko Shop': (0x011F, 0x51, True), - 'Cave Shop (Lake Hylia)': (0x0112, 0x51, True), + 'Cave Shop (Dark Death Mountain)': (0x0112, 0xC1, True), + 'Red Shield Shop': (0x0110, 0xC1, True), + 'Dark Lake Hylia Shop': (0x010F, 0xC1, True), + 'Dark World Lumberjack Shop': (0x010F, 0xC1, True), + 'Village of Outcasts Shop': (0x010F, 0xC1, True), + 'Dark World Potion Shop': (0x010F, 0xC1, True), + 'Light World Death Mountain Shop': (0x00FF, 0xA0, True), + 'Kakariko Shop': (0x011F, 0xA0, True), + 'Cave Shop (Lake Hylia)': (0x0112, 0xA0, True), 'Potion Shop': (0x0109, 0xFF, False), # Bomb Shop not currently modeled as a shop, due to special nature of items } diff --git a/Rom.py b/Rom.py index 01a472fe..1e31c4f4 100644 --- a/Rom.py +++ b/Rom.py @@ -9,7 +9,7 @@ import random from BaseClasses import ShopType from Dungeons import dungeon_music_addresses from Text import MultiByteTextMapper, text_addresses, Credits, TextTable -from Text import Uncle_texts, Ganon1_texts, PyramidFairy_texts, TavernMan_texts, Sahasrahla2_texts, Triforce_texts, Blind_texts, BombShop2_texts +from Text import Uncle_texts, Ganon1_texts, TavernMan_texts, Sahasrahla2_texts, Triforce_texts, Blind_texts, BombShop2_texts from Text import KingsReturn_texts, Sanctuary_texts, Kakariko_texts, Blacksmiths_texts, DeathMountain_texts, LostWoods_texts, WishingWell_texts, DesertPalace_texts, MountainTower_texts, LinksHouse_texts, Lumberjacks_texts, SickKid_texts, FluteBoy_texts, Zora_texts, MagicShop_texts, Sahasrahla_names from Utils import local_path, int16_as_bytes, int32_as_bytes from Items import ItemFactory @@ -42,6 +42,12 @@ class JsonRom(object): with open(file, 'w') as stream: json.dump([self.patches], stream) + def get_hash(self): + h = hashlib.md5() + h.update(json.dumps([self.patches]).encode('utf-8')) + return h.hexdigest() + + class LocalRom(object): @@ -97,6 +103,11 @@ class LocalRom(object): inv = crc ^ 0xFFFF self.write_bytes(0x7FDC, [inv & 0xFF, (inv >> 8) & 0xFF, crc & 0xFF, (crc >> 8) & 0xFF]) + def get_hash(self): + h = hashlib.md5() + h.update(self.buffer) + return h.hexdigest() + def read_rom(stream): "Reads rom into bytearray and strips off any smc header" buffer = bytearray(stream.read()) @@ -422,24 +433,6 @@ def patch_rom(world, rom, hashtable, beep='normal', color='red', sprite=None): rom.write_byte(0x180180, 0x02) # Hookshot only # Make silver arrows only usable against Ganon rom.write_byte(0x180181, 0x01) - #Make Blue Shield more expensive - rom.write_bytes(0xF73D2, [0xFC, 0xFF]) - rom.write_bytes(0xF73DA, [0x04, 0x00]) - rom.write_bytes(0xF73E2, [0x0C, 0x00]) - rom.write_byte(0xF73D6, 0x31) - rom.write_byte(0xF73DE, 0x30) - rom.write_byte(0xF73E6, 0x30) - rom.write_byte(0xF7201, 0x00) - rom.write_byte(0xF71FF, 0x64) - #Make Red Shield more expensive - rom.write_bytes(0xF73FA, [0xFC, 0xFF]) - rom.write_bytes(0xF7402, [0x04, 0x00]) - rom.write_bytes(0xF740A, [0x0C, 0x00]) - rom.write_byte(0xF73FE, 0x33) - rom.write_byte(0xF7406, 0x33) - rom.write_byte(0xF740E, 0x33) - rom.write_byte(0xF7241, 0x03) - rom.write_byte(0xF723F, 0xE7) elif world.difficulty == 'expert': # Powdered Fairies Prize rom.write_byte(0x36DD0, 0xD8) # One Heart @@ -460,24 +453,6 @@ def patch_rom(world, rom, hashtable, beep='normal', color='red', sprite=None): rom.write_byte(0x180180, 0x00) # Nothing # Make silver arrows only usable against Ganon rom.write_byte(0x180181, 0x01) - #Make Blue Shield more expensive - rom.write_bytes(0xF73D2, [0xFC, 0xFF]) - rom.write_bytes(0xF73DA, [0x04, 0x00]) - rom.write_bytes(0xF73E2, [0x0C, 0x00]) - rom.write_byte(0xF73D6, 0x3C) - rom.write_byte(0xF73DE, 0x3C) - rom.write_byte(0xF73E6, 0x3C) - rom.write_byte(0xF7201, 0x27) - rom.write_byte(0xF71FF, 0x06) - #Make Red Shield more expensive - rom.write_bytes(0xF73FA, [0xFC, 0xFF]) - rom.write_bytes(0xF7402, [0x04, 0x00]) - rom.write_bytes(0xF740A, [0x0C, 0x00]) - rom.write_byte(0xF73FE, 0x3C) - rom.write_byte(0xF7406, 0x3C) - rom.write_byte(0xF740E, 0x3C) - rom.write_byte(0xF7241, 0x27) - rom.write_byte(0xF723F, 0x06) elif world.difficulty == 'insane': # Powdered Fairies Prize rom.write_byte(0x36DD0, 0x79) # Bees @@ -498,24 +473,6 @@ def patch_rom(world, rom, hashtable, beep='normal', color='red', sprite=None): rom.write_byte(0x180180, 0x00) # Nothing # Make silver arrows only usable against Ganon rom.write_byte(0x180181, 0x01) - #Make Blue Shield more expensive - rom.write_bytes(0xF73D2, [0xFC, 0xFF]) - rom.write_bytes(0xF73DA, [0x04, 0x00]) - rom.write_bytes(0xF73E2, [0x0C, 0x00]) - rom.write_byte(0xF73D6, 0x3C) - rom.write_byte(0xF73DE, 0x3C) - rom.write_byte(0xF73E6, 0x3C) - rom.write_byte(0xF7201, 0x27) - rom.write_byte(0xF71FF, 0x10) - #Make Red Shield more expensive - rom.write_bytes(0xF73FA, [0xFC, 0xFF]) - rom.write_bytes(0xF7402, [0x04, 0x00]) - rom.write_bytes(0xF740A, [0x0C, 0x00]) - rom.write_byte(0xF73FE, 0x3C) - rom.write_byte(0xF7406, 0x3C) - rom.write_byte(0xF740E, 0x3C) - rom.write_byte(0xF7241, 0x27) - rom.write_byte(0xF723F, 0x10) else: # Powdered Fairies Prize rom.write_byte(0x36DD0, 0xE3) # fairy @@ -543,7 +500,7 @@ def patch_rom(world, rom, hashtable, beep='normal', color='red', sprite=None): if world.difficulty in ['easy']: rom.write_byte(0x180182, 0x03) # auto equip silvers on pickup and at ganon - elif world.retro and world.difficulty in ['hard','expert', 'insane']: #FIXME: this is temporary for v29 baserom + elif world.retro and world.difficulty in ['hard', 'expert', 'insane']: #FIXME: this is temporary for v29 baserom (perhaps no so temporary?) rom.write_byte(0x180182, 0x03) # auto equip silvers on pickup and at ganon else: rom.write_byte(0x180182, 0x01) # auto equip silvers on pickup @@ -574,11 +531,17 @@ def patch_rom(world, rom, hashtable, beep='normal', color='red', sprite=None): 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3] + if world.difficulty in ['hard', 'expert', 'insane']: + prize_replacements = {0xE0: 0xDF, # Fairy -> heart + 0xE3: 0xD8} # Big magic -> small magic + prizes = [prize_replacements.get(prize, prize) for prize in prizes] + dig_prizes = [prize_replacements.get(prize, prize) for prize in dig_prizes] + if world.retro: prize_replacements = {0xE1: 0xDA, #5 Arrows -> Blue Rupee 0xE2: 0xDB} #10 Arrows -> Red Rupee - prizes = [prize_replacements.get(prize,prize) for prize in prizes] - dig_prizes = [prize_replacements.get(prize,prize) for prize in dig_prizes] + prizes = [prize_replacements.get(prize, prize) for prize in prizes] + dig_prizes = [prize_replacements.get(prize, prize) for prize in dig_prizes] rom.write_bytes(0x180100, dig_prizes) random.shuffle(prizes) @@ -640,12 +603,16 @@ def patch_rom(world, rom, hashtable, beep='normal', color='red', sprite=None): # original_item, limit, replacement_item, filler 0x12, 0x01, 0x35, 0xFF, # lamp -> 5 rupees 0x58, 0x01, 0x43, 0xFF, # silver arrows -> 1 arrow + 0x51, 0x06, 0x52, 0xFF, # 6 +5 bomb upgrades -> +10 bomb upgrade + 0x53, 0x06, 0x54, 0xFF, # 6 +5 arrow upgrades -> +10 arrow upgrade 0xFF, 0xFF, 0xFF, 0xFF, # end of table sentinel ]) else: rom.write_bytes(0x184000, [ # original_item, limit, replacement_item, filler 0x12, 0x01, 0x35, 0xFF, # lamp -> 5 rupees + 0x51, 0x06, 0x52, 0xFF, # 6 +5 bomb upgrades -> +10 bomb upgrade + 0x53, 0x06, 0x54, 0xFF, # 6 +5 arrow upgrades -> +10 arrow upgrade 0xFF, 0xFF, 0xFF, 0xFF, # end of table sentinel ]) @@ -676,6 +643,10 @@ def patch_rom(world, rom, hashtable, beep='normal', color='red', sprite=None): rom.write_byte(0x348DB, 0x3A) # Red Boomerang becomes Red Boomerang rom.write_byte(0x348EB, 0x05) # Blue Shield becomes Blue Shield + # Remove Statues for upgrade fairy + rom.write_bytes(0x01F810, [0x1A, 0x1E, 0x01, 0x1A, 0x1E, 0x01]) + + rom.write_byte(0x180029, 0x01) # Smithy quick item give # set swordless mode settings @@ -740,7 +711,6 @@ def patch_rom(world, rom, hashtable, beep='normal', color='red', sprite=None): rom.write_byte(0x180211, 0x06) #Game type, we set the Entrance and item randomization flags # assorted fixes - rom.write_byte(0x180030, 0x00) # Disable SRAM trace rom.write_byte(0x1800A2, 0x01) # remain in real dark world when dying in dark word dungion before killing aga1 rom.write_byte(0x180169, 0x01 if world.lock_aga_door_in_escape else 0x00) # Lock or unlock aga tower door during escape sequence. rom.write_byte(0x180171, 0x01 if world.ganon_at_pyramid else 0x00) # Enable respawning on pyramid after ganon death @@ -766,11 +736,14 @@ def patch_rom(world, rom, hashtable, beep='normal', color='red', sprite=None): rom.write_byte(0x18302D, 0x18) # starting current health rom.write_byte(0x183039, 0x68) # starting abilities, bit array rom.write_byte(0x18004A, 0x00) # Inverted mode (off) + rom.write_byte(0x18005D, 0x00) # Hammer always breaks barrier rom.write_byte(0x2AF79, 0xD0) # vortexes: Normal (D0=light to dark, F0=dark to light, 42 = both) rom.write_byte(0x3A943, 0xD0) # Mirror: Normal (D0=Dark to Light, F0=light to dark, 42 = both) rom.write_byte(0x3A96D, 0xF0) # Residual Portal: Normal (F0= Light Side, D0=Dark Side, 42 = both (Darth Vader)) rom.write_byte(0x3A9A7, 0xD0) # Residual Portal: Normal (D0= Light Side, F0=Dark Side, 42 = both (Darth Vader)) + rom.write_bytes(0x180080, [50, 50, 70, 70]) # values to fill for Capacity Upgrades (Bomb5, Bomb10, Arrow5, Arrow10) + rom.write_byte(0x18004D, 0x00) # Escape assist (off) rom.write_byte(0x18004E, 0x00) # escape fills rom.write_int16_to_rom(0x180183, 0) # rupee fill (for bow if rupee arrows enabled) @@ -815,6 +788,7 @@ def patch_rom(world, rom, hashtable, beep='normal', color='red', sprite=None): rom.write_byte(0x180020, digging_game_rng) rom.write_byte(0xEFD95, digging_game_rng) rom.write_byte(0x1800A3, 0x01) # enable correct world setting behaviour after agahnim kills + rom.write_byte(0x1800A4, 0x01 if world.logic != 'nologic' else 0x00) # enable POD EG fix rom.write_byte(0x180042, 0x01 if world.save_and_quit_from_boss else 0x00) # Allow Save and Quit after boss kill # remove shield from uncle @@ -859,8 +833,16 @@ def patch_rom(world, rom, hashtable, beep='normal', color='red', sprite=None): # 21 bytes rom.write_bytes(0x7FC0, bytearray('ER_060_%09d\0' % world.seed, 'utf8') + world.option_identifier.to_bytes(4, 'big')) - # store hash table for main menu hash - rom.write_bytes(0x187F00, hashtable) + # Write title screen Code + hashint = int(rom.get_hash(), 16) + code = [ + (hashint >> 20) & 0x1F, + (hashint >> 15) & 0x1F, + (hashint >> 10) & 0x1F, + (hashint >> 5) & 0x1F, + hashint & 0x1F, + ] + rom.write_bytes(0x180215, code) apply_rom_settings(rom, beep, color, world.quickswap, world.fastmenu, world.disable_music, sprite) @@ -1047,7 +1029,6 @@ def write_strings(rom, world): tt['uncle_leaving_text'] = Uncle_texts[random.randint(0, len(Uncle_texts) - 1)] tt['end_triforce'] = "{NOBORDER}\n" + Triforce_texts[random.randint(0, len(Triforce_texts) - 1)] tt['bomb_shop_big_bomb'] = BombShop2_texts[random.randint(0, len(BombShop2_texts) - 1)] - tt['pond_will_upgrade'] = PyramidFairy_texts[random.randint(0, len(PyramidFairy_texts) - 1)] # this is what shows after getting the green pendant item in rando tt['sahasrahla_quest_have_master_sword'] = Sahasrahla2_texts[random.randint(0, len(Sahasrahla2_texts) - 1)] diff --git a/Rules.py b/Rules.py index 6660842c..48e0040e 100644 --- a/Rules.py +++ b/Rules.py @@ -294,6 +294,7 @@ def global_rules(world): set_rule(world.get_entrance('Ice Palace Entrance Room'), lambda state: state.has('Fire Rod') or (state.has('Bombos') and state.has_sword())) set_rule(world.get_location('Ice Palace - Big Chest'), lambda state: state.has('Big Key (Ice Palace)')) set_rule(world.get_entrance('Ice Palace (Kholdstare)'), lambda state: state.can_lift_rocks() and state.has('Hammer') and state.has('Big Key (Ice Palace)') and (state.has_key('Small Key (Ice Palace)', 2) or (state.has('Cane of Somaria') and state.has_key('Small Key (Ice Palace)', 1)))) + # TODO: investigate change from VT. Changed to hookshot or 2 keys (no checking for big key in specific chests) set_rule(world.get_entrance('Ice Palace (East)'), lambda state: (state.has('Hookshot') or (item_in_locations(state, 'Big Key (Ice Palace)', ['Ice Palace - Spike Room', 'Ice Palace - Big Key Chest', 'Ice Palace - Map Chest']) and state.has_key('Small Key (Ice Palace)'))) and (state.world.can_take_damage or state.has('Hookshot') or state.has('Cape') or state.has('Cane of Byrna'))) set_rule(world.get_entrance('Ice Palace (East Top)'), lambda state: state.can_lift_rocks() and state.has('Hammer')) for location in ['Ice Palace - Big Chest', 'Ice Palace - Kholdstare']: diff --git a/Text.py b/Text.py index 90cbdb84..cd79abc4 100644 --- a/Text.py +++ b/Text.py @@ -108,7 +108,6 @@ Triforce_texts = [ " Pick us up\n before we\n get dizzy!", ] BombShop2_texts = ['Bombs!\nBombs!\nBiggest!\nBestest!\nGreatest!\nBoomest!'] -PyramidFairy_texts = ['May I talk to you about our lord and savior, Ganon?'] Sahasrahla2_texts = ['You already got my item, idiot.', 'Why are you still talking to me?', 'This text won\'t change.', 'Have you met my brother, Hasarahshla?'] Blind_texts = [ "I hate insect\npuns, they\nreally bug me.", @@ -126,7 +125,7 @@ Blind_texts = [ "When you're a\nbaker, don't\nloaf around.", "Mire requires\nEther Quake,\nor Bombos.", "Broken pencils\nare pointless.", - "The food they\nserve guards\nlasts sentries.", + "The food they\nserve guards\nlasts sentries", "Being crushed\nby big objects\nis depressing.", "A tap dancer's\nroutine runs\nhot and cold.", "A weeknight is\na tiny\nnobleman.", @@ -144,6 +143,7 @@ Blind_texts = [ "Sausage is\nthe wurst.", "I tried to\ncatch fog,\nbut I mist.", "Winter is a\ngreat time\nto chill.", + "Do you think\nthe Ice Rod\nis cool?", ] Ganon1_texts = [ "Start your day\nsmiling with a\ndelicious\nwhole grain\nbreakfast\ncreated for\nyour\nincredible\ninsides.", @@ -246,7 +246,7 @@ Sahasrahla_names = [ "sandstorms", "sandwiched", "sauerkraut", "schipperke", "schismatic", "schizocarp", "schmalzier", "schmeering", "schmoosing", "shibboleth", "shovelnose", "sahananana", "sarararara", "salamander", "sharshalah", "shahabadoo", "sassafrass", "saddlebags", "sandalwood", "shagadelic", "sandcastle", - "saltpeters", "shabbiness", "shlrshlrsh", + "saltpeters", "shabbiness", "shlrshlrsh", "sassyralph", "sallyacorn", ] Kakariko_texts = ["{}'s homecoming"] @@ -1300,6 +1300,9 @@ class TextTable(object): 'item_get_14_heart', 'item_get_24_heart', 'item_get_34_heart', + 'pond_item_test', + 'pond_will_upgrade', + # misc 'agahnim_final_meeting', 'agahnim_hide_and_seek_found', @@ -1461,7 +1464,7 @@ class TextTable(object): text['sahasrahla_have_courage'] = CompressedTextMapper.convert("{BOTTOM}\nLook, you have the green pendant! I'll give you something. Go kill the other two bosses for more pendant fun!") text['sahasrahla_found'] = CompressedTextMapper.convert("{BOTTOM}\nYup!\n\nI'm the old man you are looking for. I'll keep it short and sweet: Go into that dungeon, then bring me the green pendant and talk to me again.") text['sign_rain_north_of_links_house'] = CompressedTextMapper.convert("↑ Dying Uncle\n This way…") - text['sign_north_of_links_house'] = CompressedTextMapper.convert("> Randomizer Don't read me, go beat Ganon!") + text['sign_north_of_links_house'] = CompressedTextMapper.convert("> Randomizer") #"> Randomizer The telepathic tiles can have hints!" text['sign_path_to_death_mountain'] = CompressedTextMapper.convert("Cave to lost, old man.\nGood luck.") text['sign_lost_woods'] = CompressedTextMapper.convert("\n↑ Lost Woods") text['sign_zoras'] = CompressedTextMapper.convert("Danger!\nDeep water!\nZoras!") @@ -1596,11 +1599,11 @@ class TextTable(object): text['mastersword_pedestal_translated'] = CompressedTextMapper.convert("A test of strength: If you have 3 pendants, I'm yours.") text['telepathic_tile_spectacle_rock'] = CompressedTextMapper.convert("{NOBORDER}\n{NOBORDER}\nUse the Mirror, or the Hookshot and Hammer, to get to Tower of Hera!") text['telepathic_tile_swamp_entrance'] = CompressedTextMapper.convert("{NOBORDER}\nDrain the floodgate to raise the water here!") - text['telepathic_tile_thieves_town_upstairs'] = CompressedTextMapper.convert("Secondary tournament winners\n{HARP}\n ~~~2017~~~\nA: Zaen") + text['telepathic_tile_thieves_town_upstairs'] = CompressedTextMapper.convert("{NOBORDER}\nBlind hate's bright light.") text['telepathic_tile_misery_mire'] = CompressedTextMapper.convert("{NOBORDER}\nLighting 4 torches will open your way forward!") text['hylian_text_2'] = CompressedTextMapper.convert("%%^= %==%\n ^ =%^=\n==%= ^^%^") text['desert_entry_translated'] = CompressedTextMapper.convert("Kneel before this stone, and magic will move around you.") - text['telepathic_tile_under_ganon'] = CompressedTextMapper.convert("{NOBORDER}\nOnly arrows will finish off a blue Ganon, or really well-timed spins in phase 4.") + text['telepathic_tile_under_ganon'] = CompressedTextMapper.convert("Secondary tournament winners\n{HARP}\n ~~~2017~~~\nA: Zaen") text['telepathic_tile_palace_of_darkness'] = CompressedTextMapper.convert("{NOBORDER}\nThis is a funny looking Enemizer") # C0 text['telepathic_tile_desert_bonk_torch_room'] = CompressedTextMapper.convert("{NOBORDER}\nThings can be knocked down, if you fancy yourself a dashing dude.") @@ -1610,7 +1613,7 @@ class TextTable(object): text['telepathic_tile_ice_entrace'] = CompressedTextMapper.convert("{NOBORDER}\nYou can use Fire Rod or Bombos to pass.") text['telepathic_tile_ice_stalfos_knights_room'] = CompressedTextMapper.convert("{NOBORDER}\nKnock 'em down and then bomb them dead.") text['telepathic_tile_tower_of_hera_entrance'] = CompressedTextMapper.convert("{NOBORDER}\nThis is a bad place, with a guy who will make you fall…\n\n\na lot.") - text['houlahan_room'] = CompressedTextMapper.convert("Randomizer tournament winners\n{HARP}\n ~~~2017~~~\nA: ajneb174\nS: ajneb174") + text['houlihan_room'] = CompressedTextMapper.convert("Randomizer tournament winners\n{HARP}\n ~~~2018~~~\nS: Andy\n\n ~~~2017~~~\nA: ajneb174\nS: ajneb174") text['caught_a_bee'] = CompressedTextMapper.convert("Caught a Bee\n ≥ keep\n release\n{CHOICE}") text['caught_a_fairy'] = CompressedTextMapper.convert("Caught Fairy!\n ≥ keep\n release\n{CHOICE}") text['no_empty_bottles'] = CompressedTextMapper.convert("Whoa, bucko!\nNo empty bottles.") diff --git a/Utils.py b/Utils.py index 2845e92d..0063ed4a 100644 --- a/Utils.py +++ b/Utils.py @@ -10,6 +10,12 @@ def int32_as_bytes(value): value = value & 0xFFFFFFFF return [value & 0xFF, (value >> 8) & 0xFF, (value >> 16) & 0xFF, (value >> 24) & 0xFF] +def pc_to_snes(value): + return ((value<<1) & 0x7F0000)|(value & 0x7FFF)|0x8000 + +def snes_to_pc(value): + return ((value & 0x7F0000)>>1)|(value & 0x7FFF) + def is_bundled(): return getattr(sys, 'frozen', False)