From 901b25952da1421da28db06812cf6432e0f393db Mon Sep 17 00:00:00 2001 From: qadan Date: Thu, 2 Jan 2020 13:08:01 -0400 Subject: [PATCH 01/52] owg start --- ER_hint_reference.txt | 359 ------------------------------------------ Rules.py | 59 ++++++- 2 files changed, 58 insertions(+), 360 deletions(-) delete mode 100644 ER_hint_reference.txt diff --git a/ER_hint_reference.txt b/ER_hint_reference.txt deleted file mode 100644 index 999fb436..00000000 --- a/ER_hint_reference.txt +++ /dev/null @@ -1,359 +0,0 @@ -Hint description: - -Hints will appear in the following ratios across the 15 telepathic tiles that have hints and the five storyteller locations: - -4 hints for inconvenient entrances. -4 hints for random entrances (this can by coincidence pick inconvenient entrances that aren't used for the first set of hints). -3 hints for inconvenient item locations. -5 hints for valuable items. -4 junk hints. - -In the vanilla, dungeonssimple, and dungeonsfull shuffles, the following ratios will be used instead: - -5 hints for inconvenient item locations. -8 hints for valuable items. -7 junk hints. - -In the simple, restricted, and restricted legacy shuffles, these are the ratios: - -2 hints for inconvenient entrances. -1 hint for an inconvenient dungeon entrance. -4 hints for random entrances (this can by coincidence pick inconvenient entrances that aren't used for the first set of hints). -3 hints for inconvenient item locations. -5 hints for valuable items. -5 junk hints. - -These hints will use the following format: - -Entrance hints go "[Entrance on overworld] leads to [interior]". - -Inconvenient item locations are a little more custom but amount to "[Location] has [item name]". The item name is literal and will specify which dungeon the dungeon specific items hail from (small key/big key/map/compass). - -The valuable items are of the format "[item name] can be found [location]". The item name is again literal, and the location text is taken from Ganon's silver arrow hints. Note that the way it works is that every unique valuable item that exists is considered independently, and you won't get multiple hints for the EXACT same item (so you can only get one hint for Progressive Sword no matter how many swords exist in the seed, but if swords are not progressive, you could get hints for both Master Sword and Tempered Sword). More copies of an item existing does not increase the probability of getting a hint for that particular item (you are equally likely to get a hint for a Progressive Sword as for the Hammer). Unlike the IR, item names are never obfuscated by "something unique", and there is no special bias for hints for GT Big Key or Pegasus Boots. - -Hint Locations: - -Eastern Palace room before Big Chest -Desert Palace bonk torch room -Tower of Hera entrance room -Tower of Hera Big Chest room -Castle Tower after dark rooms -Palace of Darkness before Bow section -Swamp Palace entryway -Thieves' Town upstairs -Ice Palace entrance -Ice Palace after first drop -Ice Palace tall ice floor room -Misery Mire cutscene room -Turtle Rock entrance -Spectacle Rock cave -Spiky Hint cave -PoD Bdlg NPC -Near PoD Storyteller (bug near bomb wall) -Dark Sanctuary Storyteller (long room with tables) -Near Mire Storyteller (feather duster in winding cave) -SE DW Storyteller (owl in winding cave) - -Inconvenient entrance list: - -Skull Woods Final -Ice Palace -Misery Mire -Turtle Rock -Ganon's Tower -Mimic Ledge -SW DM Foothills Cave (mirror from upper Bumper ledge) -Hammer Pegs (near purple chest) -Super Bomb cracked wall - -Inconvenient location list: - -Swamp left (two chests) -Mire left (two chests) -Hera basement -Eastern Palace Big Key chest (protected by anti-fairies) -Thieves' Town Big Chest -Ice Palace Big Chest -Ganon's Tower Big Chest -Purple Chest -Spike Cave -Magic Bat -Sahasrahla (Green Pendant) - -In the vanilla, dungeonssimple, and dungeonsfull shuffles, the following two locations are added to the inconvenient locations list: - -Graveyard Cave -Mimic Cave - -Valuable Items are simply all items that are shown on the pause subscreen (Y, B, or A sections) minus Silver Arrows and plus Triforce Pieces, Magic Upgrades (1/2 or 1/4), and the Single Arrow. If key shuffle is being used, you can additionally get hints for Small Keys or Big Keys but not hints for Maps or Compasses. - -While the exact verbage of location names and item names can be found in the source code, here's a copy for reference: - -Overworld Entrance naming: - -Turtle Rock: Turtle Rock Main -Misery Mire: Misery Mire -Ice Palace: Ice Palace -Skull Woods Final Section: The back of Skull Woods -Death Mountain Return Cave (West): The SW DM Foothills Cave -Mimic Cave: Mimic Ledge -Dark World Hammer Peg Cave: The rows of pegs -Pyramid Fairy: The crack on the pyramid -Eastern Palace: Eastern Palace -Elder House (East): Elder House -Elder House (West): Elder House -Two Brothers House (East): Eastern Quarreling Brothers' house -Old Man Cave (West): The lower DM entrance -Hyrule Castle Entrance (South): The ground level castle door -Thieves Town: Thieves' Town -Bumper Cave (Bottom): The lower Bumper Cave -Swamp Palace: Swamp Palace -Dark Death Mountain Ledge (West): The East dark DM connector ledge -Dark Death Mountain Ledge (East): The East dark DM connector ledge -Superbunny Cave (Top): The summit of dark DM cave -Superbunny Cave (Bottom): The base of east dark DM -Hookshot Cave: The rock on dark DM -Desert Palace Entrance (South): The book sealed passage -Tower of Hera: The Tower of Hera -Two Brothers House (West): The door near the race game -Old Man Cave (East): The SW-most cave on west DM -Old Man House (Bottom): A cave with a door on west DM -Old Man House (Top): The eastmost cave on west DM -Death Mountain Return Cave (East): The westmost cave on west DM -Spectacle Rock Cave Peak: The highest cave on west DM -Spectacle Rock Cave: The right ledge on west DM -Spectacle Rock Cave (Bottom): The left ledge on west DM -Paradox Cave (Bottom): The right paired cave on east DM -Paradox Cave (Middle): The southmost cave on east DM -Paradox Cave (Top): The east DM summit cave -Fairy Ascension Cave (Bottom): The east DM cave behind rocks -Fairy Ascension Cave (Top): The central ledge on east DM -Spiral Cave: The left ledge on east DM -Spiral Cave (Bottom): The SWmost cave on east DM -Palace of Darkness: Palace of Darkness -Hyrule Castle Entrance (West): The left castle door -Hyrule Castle Entrance (East): The right castle door -Agahnims Tower: The sealed castle door -Desert Palace Entrance (West): The westmost building in the desert -Desert Palace Entrance (North): The northmost cave in the desert -Blinds Hideout: Blind's old house -Lake Hylia Fairy: A cave NE of Lake Hylia -Light Hype Fairy: The cave south of your house -Desert Fairy: The cave near the desert -Chicken House: The chicken lady's house -Aginahs Cave: The open desert cave -Sahasrahlas Hut: The house near armos -Cave Shop (Lake Hylia): The cave NW Lake Hylia -Blacksmiths Hut: The old smithery -Sick Kids House: The central house in Kakariko -Lost Woods Gamble: A tree trunk door -Fortune Teller (Light): A building NE of Kakariko -Snitch Lady (East): A house guarded by a snitch -Snitch Lady (West): A house guarded by a snitch -Bush Covered House: A house with an uncut lawn -Tavern (Front): A building with a backdoor -Light World Bomb Hut: A Kakariko building with no door -Kakariko Shop: The old Kakariko shop -Mini Moldorm Cave: The cave south of Lake Hylia -Long Fairy Cave: The eastmost portal cave -Good Bee Cave: The open cave SE Lake Hylia -20 Rupee Cave: The rock SE Lake Hylia -50 Rupee Cave: The rock near the desert -Ice Rod Cave: The sealed cave SE Lake Hylia -Library: The old library -Potion Shop: The witch's building -Dam: The old dam -Lumberjack House: The lumberjack house -Lake Hylia Fortune Teller: The building NW Lake Hylia -Kakariko Gamble Game: The old Kakariko gambling den -Waterfall of Wishing: Going behind the waterfall -Capacity Upgrade: The cave on the island -Bonk Rock Cave: The rock pile near Sanctuary -Graveyard Cave: The graveyard ledge -Checkerboard Cave: The NE desert ledge -Cave 45: The ledge south of haunted grove -Kings Grave: The northeastmost grave -Bonk Fairy (Light): The rock pile near your home -Hookshot Fairy: A cave on east DM -Bonk Fairy (Dark): The rock pile near the old bomb shop -Dark Sanctuary Hint: The dark sanctuary cave -Dark Lake Hylia Fairy: The cave NE dark Lake Hylia -C-Shaped House: The NE house in Village of Outcasts -Big Bomb Shop: The old bomb shop -Dark Death Mountain Fairy: The SW cave on dark DM -Dark Lake Hylia Shop: The building NW dark Lake Hylia -Dark World Shop: The hammer sealed building -Red Shield Shop: The fenced in building -Mire Shed: The western hut in the mire -East Dark World Hint: The dark cave near the eastmost portal -Dark Desert Hint: The cave east of the mire -Spike Cave: The ledge cave on west dark DM -Palace of Darkness Hint: The building south of Kiki -Dark Lake Hylia Ledge Spike Cave: The rock SE dark Lake Hylia -Cave Shop (Dark Death Mountain): The base of east dark DM -Dark World Potion Shop: The building near the catfish -Archery Game: The old archery game -Dark World Lumberjack Shop: The northmost Dark World building -Hype Cave: The cave south of the old bomb shop -Brewery: The Village of Outcasts building with no door -Dark Lake Hylia Ledge Hint: The open cave SE dark Lake Hylia -Chest Game: The westmost building in the Village of Outcasts -Dark Desert Fairy: The eastern hut in the mire -Dark Lake Hylia Ledge Fairy: The sealed cave SE dark Lake Hylia -Fortune Teller (Dark): The building NE the Village of Outcasts -Sanctuary: Sanctuary -Lumberjack Tree Cave: The cave Behind Lumberjacks -Lost Woods Hideout Stump: The stump in Lost Woods -North Fairy Cave: The cave East of Graveyard -Bat Cave Cave: The cave in eastern Kakariko -Kakariko Well Cave: The cave in northern Kakariko -Hyrule Castle Secret Entrance Stairs: The tunnel near the castle -Skull Woods First Section Door: The southeastmost skull -Skull Woods Second Section Door (East): The central open skull -Skull Woods Second Section Door (West): The westmost open skull -Desert Palace Entrance (East): The eastern building in the desert -Turtle Rock Isolated Ledge Entrance: The isolated ledge on east dark DM -Bumper Cave (Top): The upper Bumper Cave -Hookshot Cave Back Entrance: The stairs on the floating island - -Destination Entrance Naming: - -Hyrule Castle: Hyrule Castle (all three entrances) -Eastern Palace: Eastern Palace -Desert Palace: Desert Palace (all four entrances, including final) -Tower of Hera: Tower of Hera -Palace of Darkness: Palace of Darkness -Swamp Palace: Swamp Palace -Skull Woods: Skull Woods (any entrance including final) -Thieves' Town: Thieves' Town -Ice Palace: Ice Palace -Misery Mire: Misery Mire -Turtle Rock: Turtle Rock (all four entrances) -Ganon's Tower: Ganon's Tower -Castle Tower: Agahnim's Tower -A connector: Paradox Cave, Spectacle Rock Cave, Hookshot Cave, Superbunny Cave, Spiral Cave, Old Man Fetch Cave, Old Man House, Elder House, Quarreling Brothers' House, Bumper Cave, DM Fairy Ascent Cave, DM Exit Cave -A bounty of five items: Mini-moldorm cave, Hype Cave, Blind's Hideout -Sahasrahla: Sahasrahla -A cave with two items: Mire hut, Waterfall Fairy, Pyramid Fairy -A fairy fountain: Any healer fairy cave, either bonk cave with four fairies, the "long fairy" cave -A common shop: Any shop that sells bombs by default -The rare shop: The shop that sells the Red Shield by default -The potion shop: Potion Shop -The bomb shop: Bomb Shop -A fortune teller: Any of the three fortune tellers -A house with a chest: Chicken Lady's house, C-House, Brewery -A cave with an item: Checkerboard cave, Hammer Pegs cave, Cave 45, Graveyard Ledge cave -A cave with a chest: Sanc Bonk Rock Cave, Cape Grave Cave, Ice Rod Cave, Aginah's Cave -The dam: Watergate -The sick kid: Sick Kid -The library: Library -Mimic Cave: Mimic Cave -Spike Cave: Spike Cave -A game of 16 chests: VoO chest game (for the item) -A storyteller: The four DW NPCs who charge 20 rupees for a hint as well as the PoD Bdlg guy who gives a free hint -A cave with some cash: 20 rupee cave, 50 rupee cave (both have thieves and some pots) -A game of chance: Gambling game (just for cash, no items) -A game of skill: Archery minigame -The queen of fairies: Capacity Upgrade Fairy -A drop's exit: Sanctuary, LW Thieves' Hideout, Kakariko Well, Magic Bat, Useless Fairy, Uncle Tunnel, Ganon drop exit -A restock room: The Kakariko bomb/arrow restock room -The tavern: The Kakariko tavern -The grass man: The Kakariko man with many beds -A cold bee: The "wrong side" of Ice Rod cave where you can get a Good Bee -Fairies deep in a cave: Hookshot Fairy - -Location naming reference: - -Mushroom: in the woods -Master Sword Pedestal: at the pedestal -Bottle Merchant: with a merchant -Stumpy: with tree boy -Flute Spot: underground -Digging Game: underground -Lake Hylia Island: on an island -Floating Island: on an island -Bumper Cave Ledge: on a ledge -Spectacle Rock: atop a rock -Maze Race: at the race -Desert Ledge: in the desert -Pyramid: on the pyramid -Catfish: with a catfish -Ether Tablet: at a monument -Bombos Tablet: at a monument -Hobo: with the hobo -Zora's Ledge: near Zora -King Zora: at a high price -Sunken Treasure: underwater -Floodgate Chest: in the dam -Blacksmith: with the smith -Purple Chest: from a box -Old Man: with the old man -Link's Uncle: with your uncle -Secret Passage: near your uncle -Kakariko Well (5 items): in a well -Lost Woods Hideout: near a thief -Lumberjack Tree: in a hole -Magic Bat: with the bat -Paradox Cave (7 items): in a cave with seven chests -Blind's Hideout (5 items): in a basement -Mini Moldorm Cave (5 items): near Moldorms -Hype Cave (4 back chests): near a bat-like man -Hype Cave - Generous Guy: with a bat-like man -Hookshot Cave (4 items): across pits -Sahasrahla's Hut (chests in back): near the elder -Sahasrahla: with the elder -Waterfall Fairy (2 items): near a fairy -Pyramid Fairy (2 items): near a fairy -Mire Shed (2 items): near sparks -Superbunny Cave (2 items): in a connection -Spiral Cave: in spiral cave -Kakariko Tavern: in the bar -Link's House: in your home -Sick Kid: with the sick -Library: near books -Potion Shop: near potions -Spike Cave: beyond spikes -Mimic Cave: in a cave of mimicry -Chest Game: as a prize -Chicken House: near poultry -Aginah's Cave: with Aginah -Ice Rod Cave: in a frozen cave -Brewery: alone in a home -C-Shaped House: alone in a home -Spectacle Rock Cave: alone in a cave -King's Tomb: alone in a cave -Cave 45: alone in a cave -Graveyard Cave: alone in a cave -Checkerboard Cave: alone in a cave -Bonk Rock Cave: alone in a cave -Peg Cave: alone in a cave -Sanctuary: in Sanctuary -Hyrule Castle - Boomerang Chest: in Hyrule Castle -Hyrule Castle - Map Chest: in Hyrule Castle -Hyrule Castle - Zelda's Chest: in Hyrule Castle -Sewers - Dark Cross: in the sewers -Sewers - Secret Room (3 items): in the sewers -Eastern Palace - Boss: with the Armos -Eastern Palace (otherwise, 5 items): in Eastern Palace -Desert Palace - Boss: with Lanmolas -Desert Palace (otherwise, 5 items): in Desert Palace -Tower of Hera - Boss: with Moldorm -Tower of Hera (otherwise, 5 items): in Tower of Hera -Castle Tower (2 items): in Castle Tower -Palace of Darkness - Boss: with Helmasaur King -Palace of Darkness (otherwise, 13 items): in Palace of Darkness -Swamp Palace - Boss: with Arrghus -Swamp Palace (otherwise, 9 items): in Swamp Palace -Skull Woods - Bridge Room: near Mothula -Skull Woods - Boss: with Mothula -Skull Woods (otherwise, 6 items): in Skull Woods -Thieves' Town - Boss: with Blind -Thieves' Town (otherwise, 7 items): in Thieves' Town -Ice Palace - Boss: with Kholdstare -Ice Palace (otherwise, 7 items): in Ice Palace -Misery Mire - Boss: with Vitreous -Misery Mire (otherwise, 7 items): in Misery Mire -Turtle Rock - Boss: with Trinexx -Turtle Rock (otherwise, 11 items): in Turtle Rock -Ganons Tower (after climb, 4 items): atop Ganon's Tower -Ganon's Tower (otherwise, 23 items): in Ganon's Tower \ No newline at end of file diff --git a/Rules.py b/Rules.py index 49154002..e76f7be5 100644 --- a/Rules.py +++ b/Rules.py @@ -38,6 +38,8 @@ def set_rules(world, player): if world.logic[player] == 'noglitches': no_glitches_rules(world, player) + elif world.logic[player] == 'owglitches': + overworld_glitches_rules(world, player) elif world.logic[player] == 'minorglitches': logging.getLogger('').info('Minor Glitches may be buggy still. No guarantee for proper logic checks.') else: @@ -357,7 +359,6 @@ def default_rules(world, player): set_rule(world.get_entrance('Kings Grave Mirror Spot', player), lambda state: state.has_Pearl(player) and state.has_Mirror(player)) # Caution: If king's grave is releaxed at all to account for reaching it via a two way cave's exit in insanity mode, then the bomb shop logic will need to be updated (that would involve create a small ledge-like Region for it) set_rule(world.get_entrance('Bonk Fairy (Light)', player), lambda state: state.has_Boots(player)) - set_rule(world.get_entrance('Bat Cave Drop Ledge', player), lambda state: state.has('Hammer', player)) set_rule(world.get_entrance('Lumberjack Tree Tree', player), lambda state: state.has_Boots(player) and state.has('Beat Agahnim 1', player)) set_rule(world.get_entrance('Bonk Rock Cave', player), lambda state: state.has_Boots(player)) set_rule(world.get_entrance('Desert Palace Stairs', player), lambda state: state.has('Book of Mudora', player)) @@ -625,6 +626,7 @@ def no_glitches_rules(world, player): set_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player) and (state.has('Hammer', player) or state.can_lift_rocks(player))) set_rule(world.get_entrance('Dark Lake Hylia Ledge Drop', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) else: + set_rule(world.get_entrance('Bat Cave Drop Ledge', player), lambda state: state.has('Hammer', player)) set_rule(world.get_entrance('Zoras River', player), lambda state: state.has_Pearl(player) and (state.has('Flippers', player) or state.can_lift_rocks(player))) set_rule(world.get_entrance('Lake Hylia Central Island Pier', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) # can be fake flippered to set_rule(world.get_entrance('Lake Hylia Island', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) @@ -691,6 +693,61 @@ def no_glitches_rules(world, player): add_lamp_requirement(world.get_entrance('Throne Room', player), player) +def overworld_glitches_rules(world, player): + # spots that are immediately accessible + set_rule(world.get_location('Zoras River', player), lambda state: True) + set_rule(world.get_location('Hobo Bridge', player), lambda state: True) + set_rule(world.get_location('Lake Hylia Central Island', player), lambda state: True) + # lw boots-accessible locations + lw_boots_accessible_locations = [ + 'Bat Cave Drop Ledge', + 'Zora\'s Ledge', + ] + lw_boots_accessible_entrances = [ + 'Death Mountain Return Ledge', + 'Cave 45 Ledge', + 'Graveyard Ledge', + 'Lake Hylia Island' + 'Desert Ledge', + 'Desert Ledge (Northeast)', + 'Desert Palace Entrance (North) Spot', + 'Death Mountain', + 'East Death Mountain (Bottom)', + 'East Death Mountain (Top)', + 'Death Mountain (Top)', + 'Spectacle Rock', + 'Death Mountain Floating Island (Light World)', + 'Turtle Rock Teleporter', + ] + # dw boots-accessible regions + dw_boots_accessible_regions = [ + 'Northeast Dark World', + 'Dark Lake Hylia', + 'Dark Lake Hylia Ledge', + 'West Dark World', + 'Hammer Peg Area', + 'Bumper Cave Ledge', + 'Dark Desert', + 'Dark Death Mountain (Top)', + 'Dark Death Mountain Ledge', + 'Dark Death Mountain (East Bottom)', + 'Death Mountain Floating Island (Dark World)', + 'Turtle Rock (Top)', + 'Ganons Tower', + ] + needs_boots = lambda state: state.has_Boots(player) + needs_boots_and_pearl = lambda state: state.has_Boots(player) and state.has_Pearl(player) + for spot in lw_boots_accessible_regions: + add_rule(world.get_region(spot, player), needs_boots_and_pearl if world.mode[player] == 'inverted' else needs_boots, 'or') + for spot in dw_boots_accessible_regions: + add_rule(world.get_region(spot, player), needs_boots if world.mode[player] == 'inverted' else needs_boots_and_pearl, 'or') + # couple other random spots + if world.mode[player] != 'inverted': + set_rule(world.get_location('Bombos Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player) and (state.has_Mirror(player) or state.has_Boots(player))) + set_rule(world.get_entrance('Waterfall of Wishing', player), lambda state: state.has('Flippers', player) or state.has_Pearl(player)) + else: + + def open_rules(world, player): # softlock protection as you can reach the sewers small key door with a guard drop key set_rule(world.get_location('Hyrule Castle - Boomerang Chest', player), lambda state: state.has_key('Small Key (Escape)', player)) From 0547606207094976d856f11a2d7208a7e8526028 Mon Sep 17 00:00:00 2001 From: qadan Date: Thu, 2 Jan 2020 23:59:28 -0400 Subject: [PATCH 02/52] close to first pass --- EntranceRandomizer.py | 4 +++- Gui.py | 2 +- ItemList.py | 2 ++ Rules.py | 50 +++++++++++++++++++++++-------------------- 4 files changed, 33 insertions(+), 25 deletions(-) diff --git a/EntranceRandomizer.py b/EntranceRandomizer.py index 91fa5bfa..df73790c 100755 --- a/EntranceRandomizer.py +++ b/EntranceRandomizer.py @@ -28,12 +28,14 @@ def parse_arguments(argv, no_defaults=False): parser = argparse.ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter) parser.add_argument('--create_spoiler', help='Output a Spoiler File', action='store_true') - parser.add_argument('--logic', default=defval('noglitches'), const='noglitches', nargs='?', choices=['noglitches', 'minorglitches', 'nologic'], + parser.add_argument('--logic', default=defval('noglitches'), const='noglitches', nargs='?', choices=['noglitches', 'minorglitches', 'owglitches', 'nologic'], help='''\ Select Enforcement of Item Requirements. (default: %(default)s) No Glitches: Minor Glitches: May require Fake Flippers, Bunny Revival and Dark Room Navigation. + Overworld Glitches: May require overworld glitches. Starts with + boots. No Logic: Distribute items without regard for item requirements. ''') diff --git a/Gui.py b/Gui.py index b897866b..538afdbc 100755 --- a/Gui.py +++ b/Gui.py @@ -193,7 +193,7 @@ def guiMain(args=None): logicFrame = Frame(drowDownFrame) logicVar = StringVar() logicVar.set('noglitches') - logicOptionMenu = OptionMenu(logicFrame, logicVar, 'noglitches', 'minorglitches', 'nologic') + logicOptionMenu = OptionMenu(logicFrame, logicVar, 'noglitches', 'minorglitches', 'owglitches', 'nologic') logicOptionMenu.pack(side=RIGHT) logicLabel = Label(logicFrame, text='Game logic') logicLabel.pack(side=LEFT) diff --git a/ItemList.py b/ItemList.py index 19eb83e3..de54f75d 100644 --- a/ItemList.py +++ b/ItemList.py @@ -125,6 +125,8 @@ difficulties = { } def generate_itempool(world, player): + if world.logic == 'owglitches': + world.push_precollected(ItemFactory('Pegasus Boots'), player) if (world.difficulty[player] not in ['normal', 'hard', 'expert'] or world.goal[player] not in ['ganon', 'pedestal', 'dungeons', 'triforcehunt', 'crystals'] or world.mode[player] not in ['open', 'standard', 'inverted'] or world.timer not in ['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown'] or world.progressive not in ['on', 'off', 'random']): raise NotImplementedError('Not supported yet') diff --git a/Rules.py b/Rules.py index e76f7be5..1907c0b0 100644 --- a/Rules.py +++ b/Rules.py @@ -644,7 +644,10 @@ def no_glitches_rules(world, player): set_rule(world.get_entrance('Paradox Cave Push Block Reverse', player), lambda state: False) # no glitches does not require block override set_rule(world.get_entrance('Paradox Cave Bomb Jump', player), lambda state: False) set_rule(world.get_entrance('Skull Woods First Section Bomb Jump', player), lambda state: False) + add_conditional_lamps(world, player) + +def add_conditional_lamps(world, player): # Light cones in standard depend on which world we actually are in, not which one the location would normally be # We add Lamp requirements only to those locations which lie in the dark world (or everything if open DW_Entrances = ['Bumper Cave (Bottom)', 'Superbunny Cave (Top)', 'Superbunny Cave (Bottom)', 'Hookshot Cave', 'Bumper Cave (Top)', 'Hookshot Cave Back Entrance', 'Dark Death Mountain Ledge (East)', @@ -695,57 +698,58 @@ def no_glitches_rules(world, player): def overworld_glitches_rules(world, player): # spots that are immediately accessible - set_rule(world.get_location('Zoras River', player), lambda state: True) - set_rule(world.get_location('Hobo Bridge', player), lambda state: True) - set_rule(world.get_location('Lake Hylia Central Island', player), lambda state: True) + set_rule(world.get_entrance('Hobo Bridge', player), lambda state: True) + set_rule(world.get_region('Lake Hylia Central Island', player), lambda state: True) + set_rule(world.get_entrance('Zoras River', player), lambda state: True) # lw boots-accessible locations - lw_boots_accessible_locations = [ + lw_boots_accessible_regions = [ 'Bat Cave Drop Ledge', - 'Zora\'s Ledge', - ] - lw_boots_accessible_entrances = [ - 'Death Mountain Return Ledge', - 'Cave 45 Ledge', - 'Graveyard Ledge', - 'Lake Hylia Island' + 'Lake Hylia Island', 'Desert Ledge', 'Desert Ledge (Northeast)', + 'Desert Palace Lone Stairs', 'Desert Palace Entrance (North) Spot', 'Death Mountain', + 'Death Mountain Return Ledge', 'East Death Mountain (Bottom)', 'East Death Mountain (Top)', 'Death Mountain (Top)', 'Spectacle Rock', 'Death Mountain Floating Island (Light World)', - 'Turtle Rock Teleporter', ] # dw boots-accessible regions dw_boots_accessible_regions = [ + 'East Dark World', 'Northeast Dark World', - 'Dark Lake Hylia', - 'Dark Lake Hylia Ledge', 'West Dark World', 'Hammer Peg Area', 'Bumper Cave Ledge', 'Dark Desert', 'Dark Death Mountain (Top)', - 'Dark Death Mountain Ledge', 'Dark Death Mountain (East Bottom)', + 'Dark Death Mountain Ledge', 'Death Mountain Floating Island (Dark World)', 'Turtle Rock (Top)', - 'Ganons Tower', ] + if world.mode[player] != 'inverted': + lw_boots_accessible_regions.append('Cave 45 Ledge') + lw_boots_accessible_regions.append('Graveyard Ledge') + # couple other random spots + set_rule(world.get_location('Bombos Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player) and (state.has_Mirror(player) or state.has_Boots(player))) + set_rule(world.get_entrance('Dark Desert Teleporter', player), lambda state: (state.has('Ocarina', player) or state.has_Boots(player)) and state.can_lift_heavy_rocks(player)) + set_rule(world.get_entrance('South Hyrule Teleporter', player), lambda state: (state.has('Hammer', player) or state.has_Boots(player)) and state.can_lift_rocks(player)) + set_rule(world.get_location('Zora\'s Ledge', player), lambda state: state.has_Boots(player)) needs_boots = lambda state: state.has_Boots(player) needs_boots_and_pearl = lambda state: state.has_Boots(player) and state.has_Pearl(player) for spot in lw_boots_accessible_regions: - add_rule(world.get_region(spot, player), needs_boots_and_pearl if world.mode[player] == 'inverted' else needs_boots, 'or') + region = world.get_region(spot, player) + for location in region.locations: + add_rule(world.get_location(location, player), needs_boots_and_pearl if world.mode[player] == 'inverted' else needs_boots, 'or') for spot in dw_boots_accessible_regions: - add_rule(world.get_region(spot, player), needs_boots if world.mode[player] == 'inverted' else needs_boots_and_pearl, 'or') - # couple other random spots - if world.mode[player] != 'inverted': - set_rule(world.get_location('Bombos Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player) and (state.has_Mirror(player) or state.has_Boots(player))) - set_rule(world.get_entrance('Waterfall of Wishing', player), lambda state: state.has('Flippers', player) or state.has_Pearl(player)) - else: + region = world.get_region(spot, player) + for location in region.locations: + add_rule(world.get_location(location, player), needs_boots if world.mode[player] == 'inverted' else needs_boots_and_pearl, 'or') + add_conditional_lamps(world, player) def open_rules(world, player): From 9ff8d08aca04043e0d928cc08e963238868cd532 Mon Sep 17 00:00:00 2001 From: qadan Date: Fri, 3 Jan 2020 01:09:21 -0400 Subject: [PATCH 03/52] create-able seeds --- ItemList.py | 37 +++++++++++++++++++++---------------- Rom.py | 8 +++++++- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/ItemList.py b/ItemList.py index de54f75d..a9d57039 100644 --- a/ItemList.py +++ b/ItemList.py @@ -125,8 +125,6 @@ difficulties = { } def generate_itempool(world, player): - if world.logic == 'owglitches': - world.push_precollected(ItemFactory('Pegasus Boots'), player) if (world.difficulty[player] not in ['normal', 'hard', 'expert'] or world.goal[player] not in ['ganon', 'pedestal', 'dungeons', 'triforcehunt', 'crystals'] or world.mode[player] not in ['open', 'standard', 'inverted'] or world.timer not in ['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown'] or world.progressive not in ['on', 'off', 'random']): raise NotImplementedError('Not supported yet') @@ -179,7 +177,7 @@ def generate_itempool(world, player): (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) = make_custom_item_pool(world.progressive, world.shuffle[player], world.difficulty[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.retro[player], world.customitemarray) world.rupoor_cost = min(world.customitemarray[69], 9999) else: - (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) = get_pool_core(world.progressive, world.shuffle[player], world.difficulty[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.retro[player]) + (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) = get_pool_core(world.progressive, world.shuffle[player], world.difficulty[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.retro[player], world.logic[player]) for item in precollected_items: world.push_precollected(ItemFactory(item, player)) @@ -388,7 +386,7 @@ def set_up_shops(world, player): #special shop types -def get_pool_core(progressive, shuffle, difficulty, timer, goal, mode, swords, retro): +def get_pool_core(progressive, shuffle, difficulty, timer, goal, mode, swords, retro, logic): pool = [] placed_items = {} precollected_items = [] @@ -405,6 +403,12 @@ def get_pool_core(progressive, shuffle, difficulty, timer, goal, mode, swords, r def want_progressives(): return random.choice([True, False]) if progressive == 'random' else progressive == 'on' + # provide boots to major glitch dependent seeds + if logic in ['owglitches', 'nologic']: + precollected_items.append('Pegasus Boots') + pool.remove('Pegasus Boots') + + if want_progressives(): pool.extend(progressivegloves) else: @@ -687,19 +691,20 @@ def test(): for progressive in ['on', 'off']: for shuffle in ['full', 'insanity_legacy']: for retro in [True, False]: - out = get_pool_core(progressive, shuffle, difficulty, timer, goal, mode, swords, retro) - count = len(out[0]) + len(out[1]) + for logic in ['noglitches', 'owglitches']: + out = get_pool_core(progressive, shuffle, difficulty, timer, goal, mode, swords, retro, logic) + count = len(out[0]) + len(out[1]) - correct_count = total_items_to_place - if goal == 'pedestal' and swords != 'vanilla': - # pedestal goals generate one extra item - correct_count += 1 - if retro: - correct_count += 28 - try: - assert count == correct_count, "expected {0} items but found {1} items for {2}".format(correct_count, count, (progressive, shuffle, difficulty, timer, goal, mode, swords, retro)) - except AssertionError as e: - print(e) + correct_count = total_items_to_place + if goal == 'pedestal' and swords != 'vanilla': + # pedestal goals generate one extra item + correct_count += 1 + if retro: + correct_count += 28 + try: + assert count == correct_count, "expected {0} items but found {1} items for {2}".format(correct_count, count, (progressive, shuffle, difficulty, timer, goal, mode, swords, retro)) + except AssertionError as e: + print(e) if __name__ == '__main__': test() diff --git a/Rom.py b/Rom.py index aa4c150a..79e85a1b 100644 --- a/Rom.py +++ b/Rom.py @@ -901,7 +901,7 @@ def patch_rom(world, player, rom, enemized): rom.write_byte(x, 0) # Zero the initial equipment array rom.write_byte(0x18302C, 0x18) # starting max health rom.write_byte(0x18302D, 0x18) # starting current health - rom.write_byte(0x183039, 0x68) # starting abilities, bit array + ability_flags = 0x68 # starting abilities, bit array; may be modified by precollected items for item in world.precollected_items: if item.player != player: @@ -911,9 +911,15 @@ def patch_rom(world, player, rom, enemized): rom.write_byte(0x183000+0x19, 0x01) rom.write_byte(0x0271A6+0x19, 0x01) rom.write_byte(0x180043, 0x01) # special starting sword byte + elif item.name == 'Pegasus Boots': + rom.write_byte(0x183015, 0x01) + ability_flags |= 0b00000100 else: raise RuntimeError("Unsupported pre-collected item: {}".format(item)) + # write abilities after ability flags have been determined + rom.write_byte(0x183039, ability_flags) + rom.write_byte(0x18004A, 0x00 if world.mode[player] != 'inverted' else 0x01) # Inverted mode rom.write_byte(0x18005D, 0x00) # Hammer always breaks barrier rom.write_byte(0x2AF79, 0xD0 if world.mode[player] != 'inverted' else 0xF0) # vortexes: Normal (D0=light to dark, F0=dark to light, 42 = both) From 4d631adf7b5364792dc7aa4cd95c6250b9ec22f1 Mon Sep 17 00:00:00 2001 From: qadan Date: Fri, 3 Jan 2020 03:49:56 -0400 Subject: [PATCH 04/52] getting there ... somethings up, needs testing --- ItemList.py | 1 - Mystery.py | 6 +++--- Rules.py | 28 ++++++++++++++++++++++++---- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/ItemList.py b/ItemList.py index a9d57039..3db3f130 100644 --- a/ItemList.py +++ b/ItemList.py @@ -408,7 +408,6 @@ def get_pool_core(progressive, shuffle, difficulty, timer, goal, mode, swords, r precollected_items.append('Pegasus Boots') pool.remove('Pegasus Boots') - if want_progressives(): pool.extend(progressivegloves) else: diff --git a/Mystery.py b/Mystery.py index 06f57aca..2a79c990 100644 --- a/Mystery.py +++ b/Mystery.py @@ -114,10 +114,10 @@ def roll_settings(weights): ret = argparse.Namespace() glitches_required = get_choice('glitches_required') - if glitches_required not in ['none', 'no_logic']: - print("Only NMG and No Logic supported") + if glitches_required not in ['none', 'no_logic', 'overworld_glitches']: + print("Only NMG, OWG and No Logic supported") glitches_required = 'none' - ret.logic = {'none': 'noglitches', 'no_logic': 'nologic'}[glitches_required] + ret.logic = {'none': 'noglitches', 'no_logic': 'nologic', 'overworld_glitches': 'owglitches'}[glitches_required] item_placement = get_choice('item_placement') # not supported in ER diff --git a/Rules.py b/Rules.py index 1907c0b0..41015113 100644 --- a/Rules.py +++ b/Rules.py @@ -731,6 +731,7 @@ def overworld_glitches_rules(world, player): 'Death Mountain Floating Island (Dark World)', 'Turtle Rock (Top)', ] + # set up boots-accessible regions if world.mode[player] != 'inverted': lw_boots_accessible_regions.append('Cave 45 Ledge') lw_boots_accessible_regions.append('Graveyard Ledge') @@ -739,16 +740,35 @@ def overworld_glitches_rules(world, player): set_rule(world.get_entrance('Dark Desert Teleporter', player), lambda state: (state.has('Ocarina', player) or state.has_Boots(player)) and state.can_lift_heavy_rocks(player)) set_rule(world.get_entrance('South Hyrule Teleporter', player), lambda state: (state.has('Hammer', player) or state.has_Boots(player)) and state.can_lift_rocks(player)) set_rule(world.get_location('Zora\'s Ledge', player), lambda state: state.has_Boots(player)) + add_rule(world.get_entrance('Ganons Tower', player), lambda state: state.has_Boots(player) and state.has_Pearl(player), 'or') needs_boots = lambda state: state.has_Boots(player) needs_boots_and_pearl = lambda state: state.has_Boots(player) and state.has_Pearl(player) for spot in lw_boots_accessible_regions: - region = world.get_region(spot, player) - for location in region.locations: + for location in world.get_region(spot, player).locations: add_rule(world.get_location(location, player), needs_boots_and_pearl if world.mode[player] == 'inverted' else needs_boots, 'or') for spot in dw_boots_accessible_regions: - region = world.get_region(spot, player) - for location in region.locations: + for location in world.get_region(spot, player).locations: add_rule(world.get_location(location, player), needs_boots if world.mode[player] == 'inverted' else needs_boots_and_pearl, 'or') + # bunny DMD rules + if world.mode[player] != 'inverted': + # set up some mirror-accessible dw entrances. + boots_and_mirror = lambda state: state.has_Boots(player) and state.has_Mirror(player) + add_rule(world.get_entrance('Dark Sanctuary Hint', player), boots_and_mirror, 'or') # should suffice to give us west dark world access + for spot in world.get_region('Dark Death Mountain (East Bottom)', player).locations: + add_rule(world.get_location(spot, player), boots_and_mirror, 'or') + # dw entrances accessible with mirror and hookshot + mirror_hookshot_accessible_dw_locations = [ + 'Pyramid Fairy', + 'Pyramid Entrance', + 'Pyramid Drop', + ] + mirror_hookshot_accessible_dw_locations.extend(world.get_region('Dark Death Mountain Ledge', player).locations) + for spot in mirror_hookshot_accessible_dw_locations: + add_rule(world.get_entrance(spot, player), lambda state: state.has_Boots(player) and state.has_Mirror(player) and state.has('Hookshot', player), 'or') + # dw entrances accessible with mirror and titans + boots_mirror_titans = lambda state: state.has_Boots(player) and state.has_Mirror(player) and state.can_lift_heavy_rocks(player) + add_rule(world.get_entrance('Mire Shed', player), boots_mirror_titans, 'or') + add_rule(world.get_location('Frog', player), boots_mirror_titans, 'or') add_conditional_lamps(world, player) From 233d2969b6a7ab0f69e572dd60bd7f1fb88afb2a Mon Sep 17 00:00:00 2001 From: qadan Date: Fri, 3 Jan 2020 03:56:52 -0400 Subject: [PATCH 05/52] re-add hint reference --- ER_hint_reference.txt | 359 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 359 insertions(+) create mode 100644 ER_hint_reference.txt diff --git a/ER_hint_reference.txt b/ER_hint_reference.txt new file mode 100644 index 00000000..da45c78f --- /dev/null +++ b/ER_hint_reference.txt @@ -0,0 +1,359 @@ +Hint description: + +Hints will appear in the following ratios across the 15 telepathic tiles that have hints and the five storyteller locations: + +4 hints for inconvenient entrances. +4 hints for random entrances (this can by coincidence pick inconvenient entrances that aren't used for the first set of hints). +3 hints for inconvenient item locations. +5 hints for valuable items. +4 junk hints. + +In the vanilla, dungeonssimple, and dungeonsfull shuffles, the following ratios will be used instead: + +5 hints for inconvenient item locations. +8 hints for valuable items. +7 junk hints. + +In the simple, restricted, and restricted legacy shuffles, these are the ratios: + +2 hints for inconvenient entrances. +1 hint for an inconvenient dungeon entrance. +4 hints for random entrances (this can by coincidence pick inconvenient entrances that aren't used for the first set of hints). +3 hints for inconvenient item locations. +5 hints for valuable items. +5 junk hints. + +These hints will use the following format: + +Entrance hints go "[Entrance on overworld] leads to [interior]". + +Inconvenient item locations are a little more custom but amount to "[Location] has [item name]". The item name is literal and will specify which dungeon the dungeon specific items hail from (small key/big key/map/compass). + +The valuable items are of the format "[item name] can be found [location]". The item name is again literal, and the location text is taken from Ganon's silver arrow hints. Note that the way it works is that every unique valuable item that exists is considered independently, and you won't get multiple hints for the EXACT same item (so you can only get one hint for Progressive Sword no matter how many swords exist in the seed, but if swords are not progressive, you could get hints for both Master Sword and Tempered Sword). More copies of an item existing does not increase the probability of getting a hint for that particular item (you are equally likely to get a hint for a Progressive Sword as for the Hammer). Unlike the IR, item names are never obfuscated by "something unique", and there is no special bias for hints for GT Big Key or Pegasus Boots. + +Hint Locations: + +Eastern Palace room before Big Chest +Desert Palace bonk torch room +Tower of Hera entrance room +Tower of Hera Big Chest room +Castle Tower after dark rooms +Palace of Darkness before Bow section +Swamp Palace entryway +Thieves' Town upstairs +Ice Palace entrance +Ice Palace after first drop +Ice Palace tall ice floor room +Misery Mire cutscene room +Turtle Rock entrance +Spectacle Rock cave +Spiky Hint cave +PoD Bdlg NPC +Near PoD Storyteller (bug near bomb wall) +Dark Sanctuary Storyteller (long room with tables) +Near Mire Storyteller (feather duster in winding cave) +SE DW Storyteller (owl in winding cave) + +Inconvenient entrance list: + +Skull Woods Final +Ice Palace +Misery Mire +Turtle Rock +Ganon's Tower +Mimic Ledge +SW DM Foothills Cave (mirror from upper Bumper ledge) +Hammer Pegs (near purple chest) +Super Bomb cracked wall + +Inconvenient location list: + +Swamp left (two chests) +Mire left (two chests) +Hera basement +Eastern Palace Big Key chest (protected by anti-fairies) +Thieves' Town Big Chest +Ice Palace Big Chest +Ganon's Tower Big Chest +Purple Chest +Spike Cave +Magic Bat +Sahasrahla (Green Pendant) + +In the vanilla, dungeonssimple, and dungeonsfull shuffles, the following two locations are added to the inconvenient locations list: + +Graveyard Cave +Mimic Cave + +Valuable Items are simply all items that are shown on the pause subscreen (Y, B, or A sections) minus Silver Arrows and plus Triforce Pieces, Magic Upgrades (1/2 or 1/4), and the Single Arrow. If key shuffle is being used, you can additionally get hints for Small Keys or Big Keys but not hints for Maps or Compasses. + +While the exact verbage of location names and item names can be found in the source code, here's a copy for reference: + +Overworld Entrance naming: + +Turtle Rock: Turtle Rock Main +Misery Mire: Misery Mire +Ice Palace: Ice Palace +Skull Woods Final Section: The back of Skull Woods +Death Mountain Return Cave (West): The SW DM Foothills Cave +Mimic Cave: Mimic Ledge +Dark World Hammer Peg Cave: The rows of pegs +Pyramid Fairy: The crack on the pyramid +Eastern Palace: Eastern Palace +Elder House (East): Elder House +Elder House (West): Elder House +Two Brothers House (East): Eastern Quarreling Brothers' house +Old Man Cave (West): The lower DM entrance +Hyrule Castle Entrance (South): The ground level castle door +Thieves Town: Thieves' Town +Bumper Cave (Bottom): The lower Bumper Cave +Swamp Palace: Swamp Palace +Dark Death Mountain Ledge (West): The East dark DM connector ledge +Dark Death Mountain Ledge (East): The East dark DM connector ledge +Superbunny Cave (Top): The summit of dark DM cave +Superbunny Cave (Bottom): The base of east dark DM +Hookshot Cave: The rock on dark DM +Desert Palace Entrance (South): The book sealed passage +Tower of Hera: The Tower of Hera +Two Brothers House (West): The door near the race game +Old Man Cave (East): The SW-most cave on west DM +Old Man House (Bottom): A cave with a door on west DM +Old Man House (Top): The eastmost cave on west DM +Death Mountain Return Cave (East): The westmost cave on west DM +Spectacle Rock Cave Peak: The highest cave on west DM +Spectacle Rock Cave: The right ledge on west DM +Spectacle Rock Cave (Bottom): The left ledge on west DM +Paradox Cave (Bottom): The right paired cave on east DM +Paradox Cave (Middle): The southmost cave on east DM +Paradox Cave (Top): The east DM summit cave +Fairy Ascension Cave (Bottom): The east DM cave behind rocks +Fairy Ascension Cave (Top): The central ledge on east DM +Spiral Cave: The left ledge on east DM +Spiral Cave (Bottom): The SWmost cave on east DM +Palace of Darkness: Palace of Darkness +Hyrule Castle Entrance (West): The left castle door +Hyrule Castle Entrance (East): The right castle door +Agahnims Tower: The sealed castle door +Desert Palace Entrance (West): The westmost building in the desert +Desert Palace Entrance (North): The northmost cave in the desert +Blinds Hideout: Blind's old house +Lake Hylia Fairy: A cave NE of Lake Hylia +Light Hype Fairy: The cave south of your house +Desert Fairy: The cave near the desert +Chicken House: The chicken lady's house +Aginahs Cave: The open desert cave +Sahasrahlas Hut: The house near armos +Cave Shop (Lake Hylia): The cave NW Lake Hylia +Blacksmiths Hut: The old smithery +Sick Kids House: The central house in Kakariko +Lost Woods Gamble: A tree trunk door +Fortune Teller (Light): A building NE of Kakariko +Snitch Lady (East): A house guarded by a snitch +Snitch Lady (West): A house guarded by a snitch +Bush Covered House: A house with an uncut lawn +Tavern (Front): A building with a backdoor +Light World Bomb Hut: A Kakariko building with no door +Kakariko Shop: The old Kakariko shop +Mini Moldorm Cave: The cave south of Lake Hylia +Long Fairy Cave: The eastmost portal cave +Good Bee Cave: The open cave SE Lake Hylia +20 Rupee Cave: The rock SE Lake Hylia +50 Rupee Cave: The rock near the desert +Ice Rod Cave: The sealed cave SE Lake Hylia +Library: The old library +Potion Shop: The witch's building +Dam: The old dam +Lumberjack House: The lumberjack house +Lake Hylia Fortune Teller: The building NW Lake Hylia +Kakariko Gamble Game: The old Kakariko gambling den +Waterfall of Wishing: Going behind the waterfall +Capacity Upgrade: The cave on the island +Bonk Rock Cave: The rock pile near Sanctuary +Graveyard Cave: The graveyard ledge +Checkerboard Cave: The NE desert ledge +Cave 45: The ledge south of haunted grove +Kings Grave: The northeastmost grave +Bonk Fairy (Light): The rock pile near your home +Hookshot Fairy: A cave on east DM +Bonk Fairy (Dark): The rock pile near the old bomb shop +Dark Sanctuary Hint: The dark sanctuary cave +Dark Lake Hylia Fairy: The cave NE dark Lake Hylia +C-Shaped House: The NE house in Village of Outcasts +Big Bomb Shop: The old bomb shop +Dark Death Mountain Fairy: The SW cave on dark DM +Dark Lake Hylia Shop: The building NW dark Lake Hylia +Dark World Shop: The hammer sealed building +Red Shield Shop: The fenced in building +Mire Shed: The western hut in the mire +East Dark World Hint: The dark cave near the eastmost portal +Dark Desert Hint: The cave east of the mire +Spike Cave: The ledge cave on west dark DM +Palace of Darkness Hint: The building south of Kiki +Dark Lake Hylia Ledge Spike Cave: The rock SE dark Lake Hylia +Cave Shop (Dark Death Mountain): The base of east dark DM +Dark World Potion Shop: The building near the catfish +Archery Game: The old archery game +Dark World Lumberjack Shop: The northmost Dark World building +Hype Cave: The cave south of the old bomb shop +Brewery: The Village of Outcasts building with no door +Dark Lake Hylia Ledge Hint: The open cave SE dark Lake Hylia +Chest Game: The westmost building in the Village of Outcasts +Dark Desert Fairy: The eastern hut in the mire +Dark Lake Hylia Ledge Fairy: The sealed cave SE dark Lake Hylia +Fortune Teller (Dark): The building NE the Village of Outcasts +Sanctuary: Sanctuary +Lumberjack Tree Cave: The cave Behind Lumberjacks +Lost Woods Hideout Stump: The stump in Lost Woods +North Fairy Cave: The cave East of Graveyard +Bat Cave Cave: The cave in eastern Kakariko +Kakariko Well Cave: The cave in northern Kakariko +Hyrule Castle Secret Entrance Stairs: The tunnel near the castle +Skull Woods First Section Door: The southeastmost skull +Skull Woods Second Section Door (East): The central open skull +Skull Woods Second Section Door (West): The westmost open skull +Desert Palace Entrance (East): The eastern building in the desert +Turtle Rock Isolated Ledge Entrance: The isolated ledge on east dark DM +Bumper Cave (Top): The upper Bumper Cave +Hookshot Cave Back Entrance: The stairs on the floating island + +Destination Entrance Naming: + +Hyrule Castle: Hyrule Castle (all three entrances) +Eastern Palace: Eastern Palace +Desert Palace: Desert Palace (all four entrances, including final) +Tower of Hera: Tower of Hera +Palace of Darkness: Palace of Darkness +Swamp Palace: Swamp Palace +Skull Woods: Skull Woods (any entrance including final) +Thieves' Town: Thieves' Town +Ice Palace: Ice Palace +Misery Mire: Misery Mire +Turtle Rock: Turtle Rock (all four entrances) +Ganon's Tower: Ganon's Tower +Castle Tower: Agahnim's Tower +A connector: Paradox Cave, Spectacle Rock Cave, Hookshot Cave, Superbunny Cave, Spiral Cave, Old Man Fetch Cave, Old Man House, Elder House, Quarreling Brothers' House, Bumper Cave, DM Fairy Ascent Cave, DM Exit Cave +A bounty of five items: Mini-moldorm cave, Hype Cave, Blind's Hideout +Sahasrahla: Sahasrahla +A cave with two items: Mire hut, Waterfall Fairy, Pyramid Fairy +A fairy fountain: Any healer fairy cave, either bonk cave with four fairies, the "long fairy" cave +A common shop: Any shop that sells bombs by default +The rare shop: The shop that sells the Red Shield by default +The potion shop: Potion Shop +The bomb shop: Bomb Shop +A fortune teller: Any of the three fortune tellers +A house with a chest: Chicken Lady's house, C-House, Brewery +A cave with an item: Checkerboard cave, Hammer Pegs cave, Cave 45, Graveyard Ledge cave +A cave with a chest: Sanc Bonk Rock Cave, Cape Grave Cave, Ice Rod Cave, Aginah's Cave +The dam: Watergate +The sick kid: Sick Kid +The library: Library +Mimic Cave: Mimic Cave +Spike Cave: Spike Cave +A game of 16 chests: VoO chest game (for the item) +A storyteller: The four DW NPCs who charge 20 rupees for a hint as well as the PoD Bdlg guy who gives a free hint +A cave with some cash: 20 rupee cave, 50 rupee cave (both have thieves and some pots) +A game of chance: Gambling game (just for cash, no items) +A game of skill: Archery minigame +The queen of fairies: Capacity Upgrade Fairy +A drop's exit: Sanctuary, LW Thieves' Hideout, Kakariko Well, Magic Bat, Useless Fairy, Uncle Tunnel, Ganon drop exit +A restock room: The Kakariko bomb/arrow restock room +The tavern: The Kakariko tavern +The grass man: The Kakariko man with many beds +A cold bee: The "wrong side" of Ice Rod cave where you can get a Good Bee +Fairies deep in a cave: Hookshot Fairy + +Location naming reference: + +Mushroom: in the woods +Master Sword Pedestal: at the pedestal +Bottle Merchant: with a merchant +Stumpy: with tree boy +Flute Spot: underground +Digging Game: underground +Lake Hylia Island: on an island +Floating Island: on an island +Bumper Cave Ledge: on a ledge +Spectacle Rock: atop a rock +Maze Race: at the race +Desert Ledge: in the desert +Pyramid: on the pyramid +Catfish: with a catfish +Ether Tablet: at a monument +Bombos Tablet: at a monument +Hobo: with the hobo +Zora's Ledge: near Zora +King Zora: at a high price +Sunken Treasure: underwater +Floodgate Chest: in the dam +Blacksmith: with the smith +Purple Chest: from a box +Old Man: with the old man +Link's Uncle: with your uncle +Secret Passage: near your uncle +Kakariko Well (5 items): in a well +Lost Woods Hideout: near a thief +Lumberjack Tree: in a hole +Magic Bat: with the bat +Paradox Cave (7 items): in a cave with seven chests +Blind's Hideout (5 items): in a basement +Mini Moldorm Cave (5 items): near Moldorms +Hype Cave (4 back chests): near a bat-like man +Hype Cave - Generous Guy: with a bat-like man +Hookshot Cave (4 items): across pits +Sahasrahla's Hut (chests in back): near the elder +Sahasrahla: with the elder +Waterfall Fairy (2 items): near a fairy +Pyramid Fairy (2 items): near a fairy +Mire Shed (2 items): near sparks +Superbunny Cave (2 items): in a connection +Spiral Cave: in spiral cave +Kakariko Tavern: in the bar +Link's House: in your home +Sick Kid: with the sick +Library: near books +Potion Shop: near potions +Spike Cave: beyond spikes +Mimic Cave: in a cave of mimicry +Chest Game: as a prize +Chicken House: near poultry +Aginah's Cave: with Aginah +Ice Rod Cave: in a frozen cave +Brewery: alone in a home +C-Shaped House: alone in a home +Spectacle Rock Cave: alone in a cave +King's Tomb: alone in a cave +Cave 45: alone in a cave +Graveyard Cave: alone in a cave +Checkerboard Cave: alone in a cave +Bonk Rock Cave: alone in a cave +Peg Cave: alone in a cave +Sanctuary: in Sanctuary +Hyrule Castle - Boomerang Chest: in Hyrule Castle +Hyrule Castle - Map Chest: in Hyrule Castle +Hyrule Castle - Zelda's Chest: in Hyrule Castle +Sewers - Dark Cross: in the sewers +Sewers - Secret Room (3 items): in the sewers +Eastern Palace - Boss: with the Armos +Eastern Palace (otherwise, 5 items): in Eastern Palace +Desert Palace - Boss: with Lanmolas +Desert Palace (otherwise, 5 items): in Desert Palace +Tower of Hera - Boss: with Moldorm +Tower of Hera (otherwise, 5 items): in Tower of Hera +Castle Tower (2 items): in Castle Tower +Palace of Darkness - Boss: with Helmasaur King +Palace of Darkness (otherwise, 13 items): in Palace of Darkness +Swamp Palace - Boss: with Arrghus +Swamp Palace (otherwise, 9 items): in Swamp Palace +Skull Woods - Bridge Room: near Mothula +Skull Woods - Boss: with Mothula +Skull Woods (otherwise, 6 items): in Skull Woods +Thieves' Town - Boss: with Blind +Thieves' Town (otherwise, 7 items): in Thieves' Town +Ice Palace - Boss: with Kholdstare +Ice Palace (otherwise, 7 items): in Ice Palace +Misery Mire - Boss: with Vitreous +Misery Mire (otherwise, 7 items): in Misery Mire +Turtle Rock - Boss: with Trinexx +Turtle Rock (otherwise, 11 items): in Turtle Rock +Ganons Tower (after climb, 4 items): atop Ganon's Tower +Ganon's Tower (otherwise, 23 items): in Ganon's Tower \ No newline at end of file From c09fab64f81c3016d3f7d01f4c79ee77343dde95 Mon Sep 17 00:00:00 2001 From: qadan Date: Fri, 3 Jan 2020 04:02:15 -0400 Subject: [PATCH 06/52] first pass at owg logic support --- EntranceRandomizer.py | 7 ++-- EntranceShuffle.py | 3 +- Gui.py | 2 +- InvertedRegions.py | 2 +- ItemList.py | 34 ++++++++++-------- Mystery.py | 6 ++-- Rom.py | 8 ++++- Rules.py | 84 ++++++++++++++++++++++++++++++++++++++++++- 8 files changed, 122 insertions(+), 24 deletions(-) diff --git a/EntranceRandomizer.py b/EntranceRandomizer.py index 91fa5bfa..53476548 100755 --- a/EntranceRandomizer.py +++ b/EntranceRandomizer.py @@ -28,14 +28,17 @@ def parse_arguments(argv, no_defaults=False): parser = argparse.ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter) parser.add_argument('--create_spoiler', help='Output a Spoiler File', action='store_true') - parser.add_argument('--logic', default=defval('noglitches'), const='noglitches', nargs='?', choices=['noglitches', 'minorglitches', 'nologic'], + parser.add_argument('--logic', default=defval('noglitches'), const='noglitches', nargs='?', choices=['noglitches', 'minorglitches', 'owglitches', 'nologic'], help='''\ Select Enforcement of Item Requirements. (default: %(default)s) No Glitches: Minor Glitches: May require Fake Flippers, Bunny Revival and Dark Room Navigation. + Overworld Glitches: May require overworld glitches. Starts with + boots. No Logic: Distribute items without regard for - item requirements. + item requirements. Starts with + boots ''') parser.add_argument('--mode', default=defval('open'), const='open', nargs='?', choices=['standard', 'open', 'inverted'], help='''\ diff --git a/EntranceShuffle.py b/EntranceShuffle.py index a96811b8..49339ab2 100644 --- a/EntranceShuffle.py +++ b/EntranceShuffle.py @@ -2987,7 +2987,8 @@ mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia Central ('Pyramid Drop', 'East Dark World') ] -inverted_mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia Central Island'), +inverted_mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia Central Island'), + ('Lake Hylia Island', 'Lake Hylia Island'), ('Zoras River', 'Zoras River'), ('Kings Grave Outer Rocks', 'Kings Grave Area'), ('Kings Grave Inner Rocks', 'Light World'), diff --git a/Gui.py b/Gui.py index b897866b..538afdbc 100755 --- a/Gui.py +++ b/Gui.py @@ -193,7 +193,7 @@ def guiMain(args=None): logicFrame = Frame(drowDownFrame) logicVar = StringVar() logicVar.set('noglitches') - logicOptionMenu = OptionMenu(logicFrame, logicVar, 'noglitches', 'minorglitches', 'nologic') + logicOptionMenu = OptionMenu(logicFrame, logicVar, 'noglitches', 'minorglitches', 'owglitches', 'nologic') logicOptionMenu.pack(side=RIGHT) logicLabel = Label(logicFrame, text='Game logic') logicLabel.pack(side=LEFT) diff --git a/InvertedRegions.py b/InvertedRegions.py index d0f0e8bc..e1915d39 100644 --- a/InvertedRegions.py +++ b/InvertedRegions.py @@ -9,7 +9,7 @@ def create_inverted_regions(world, player): ["Blinds Hideout", "Hyrule Castle Secret Entrance Drop", 'Kings Grave Outer Rocks', 'Dam', 'Inverted Big Bomb Shop', 'Tavern North', 'Chicken House', 'Aginahs Cave', 'Sahasrahlas Hut', 'Kakariko Well Drop', 'Kakariko Well Cave', 'Blacksmiths Hut', 'Bat Cave Drop Ledge', 'Bat Cave Cave', 'Sick Kids House', 'Hobo Bridge', 'Lost Woods Hideout Drop', 'Lost Woods Hideout Stump', - 'Lumberjack Tree Tree', 'Lumberjack Tree Cave', 'Mini Moldorm Cave', 'Ice Rod Cave', 'Lake Hylia Central Island Pier', + 'Lumberjack Tree Tree', 'Lumberjack Tree Cave', 'Mini Moldorm Cave', 'Ice Rod Cave', 'Lake Hylia Central Island Pier', 'Lake Hylia Island', 'Bonk Rock Cave', 'Library', 'Two Brothers House (East)', 'Desert Palace Stairs', 'Eastern Palace', 'Master Sword Meadow', 'Sanctuary', 'Sanctuary Grave', 'Death Mountain Entrance Rock', 'Light World River Drop', 'Elder House (East)', 'Elder House (West)', 'North Fairy Cave', 'North Fairy Cave Drop', 'Lost Woods Gamble', 'Snitch Lady (East)', 'Snitch Lady (West)', 'Tavern (Front)', diff --git a/ItemList.py b/ItemList.py index 19eb83e3..3db3f130 100644 --- a/ItemList.py +++ b/ItemList.py @@ -177,7 +177,7 @@ def generate_itempool(world, player): (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) = make_custom_item_pool(world.progressive, world.shuffle[player], world.difficulty[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.retro[player], world.customitemarray) world.rupoor_cost = min(world.customitemarray[69], 9999) else: - (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) = get_pool_core(world.progressive, world.shuffle[player], world.difficulty[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.retro[player]) + (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) = get_pool_core(world.progressive, world.shuffle[player], world.difficulty[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.retro[player], world.logic[player]) for item in precollected_items: world.push_precollected(ItemFactory(item, player)) @@ -386,7 +386,7 @@ def set_up_shops(world, player): #special shop types -def get_pool_core(progressive, shuffle, difficulty, timer, goal, mode, swords, retro): +def get_pool_core(progressive, shuffle, difficulty, timer, goal, mode, swords, retro, logic): pool = [] placed_items = {} precollected_items = [] @@ -403,6 +403,11 @@ def get_pool_core(progressive, shuffle, difficulty, timer, goal, mode, swords, r def want_progressives(): return random.choice([True, False]) if progressive == 'random' else progressive == 'on' + # provide boots to major glitch dependent seeds + if logic in ['owglitches', 'nologic']: + precollected_items.append('Pegasus Boots') + pool.remove('Pegasus Boots') + if want_progressives(): pool.extend(progressivegloves) else: @@ -685,19 +690,20 @@ def test(): for progressive in ['on', 'off']: for shuffle in ['full', 'insanity_legacy']: for retro in [True, False]: - out = get_pool_core(progressive, shuffle, difficulty, timer, goal, mode, swords, retro) - count = len(out[0]) + len(out[1]) + for logic in ['noglitches', 'owglitches']: + out = get_pool_core(progressive, shuffle, difficulty, timer, goal, mode, swords, retro, logic) + count = len(out[0]) + len(out[1]) - correct_count = total_items_to_place - if goal == 'pedestal' and swords != 'vanilla': - # pedestal goals generate one extra item - correct_count += 1 - if retro: - correct_count += 28 - try: - assert count == correct_count, "expected {0} items but found {1} items for {2}".format(correct_count, count, (progressive, shuffle, difficulty, timer, goal, mode, swords, retro)) - except AssertionError as e: - print(e) + correct_count = total_items_to_place + if goal == 'pedestal' and swords != 'vanilla': + # pedestal goals generate one extra item + correct_count += 1 + if retro: + correct_count += 28 + try: + assert count == correct_count, "expected {0} items but found {1} items for {2}".format(correct_count, count, (progressive, shuffle, difficulty, timer, goal, mode, swords, retro)) + except AssertionError as e: + print(e) if __name__ == '__main__': test() diff --git a/Mystery.py b/Mystery.py index 06f57aca..2a79c990 100644 --- a/Mystery.py +++ b/Mystery.py @@ -114,10 +114,10 @@ def roll_settings(weights): ret = argparse.Namespace() glitches_required = get_choice('glitches_required') - if glitches_required not in ['none', 'no_logic']: - print("Only NMG and No Logic supported") + if glitches_required not in ['none', 'no_logic', 'overworld_glitches']: + print("Only NMG, OWG and No Logic supported") glitches_required = 'none' - ret.logic = {'none': 'noglitches', 'no_logic': 'nologic'}[glitches_required] + ret.logic = {'none': 'noglitches', 'no_logic': 'nologic', 'overworld_glitches': 'owglitches'}[glitches_required] item_placement = get_choice('item_placement') # not supported in ER diff --git a/Rom.py b/Rom.py index aa4c150a..79e85a1b 100644 --- a/Rom.py +++ b/Rom.py @@ -901,7 +901,7 @@ def patch_rom(world, player, rom, enemized): rom.write_byte(x, 0) # Zero the initial equipment array rom.write_byte(0x18302C, 0x18) # starting max health rom.write_byte(0x18302D, 0x18) # starting current health - rom.write_byte(0x183039, 0x68) # starting abilities, bit array + ability_flags = 0x68 # starting abilities, bit array; may be modified by precollected items for item in world.precollected_items: if item.player != player: @@ -911,9 +911,15 @@ def patch_rom(world, player, rom, enemized): rom.write_byte(0x183000+0x19, 0x01) rom.write_byte(0x0271A6+0x19, 0x01) rom.write_byte(0x180043, 0x01) # special starting sword byte + elif item.name == 'Pegasus Boots': + rom.write_byte(0x183015, 0x01) + ability_flags |= 0b00000100 else: raise RuntimeError("Unsupported pre-collected item: {}".format(item)) + # write abilities after ability flags have been determined + rom.write_byte(0x183039, ability_flags) + rom.write_byte(0x18004A, 0x00 if world.mode[player] != 'inverted' else 0x01) # Inverted mode rom.write_byte(0x18005D, 0x00) # Hammer always breaks barrier rom.write_byte(0x2AF79, 0xD0 if world.mode[player] != 'inverted' else 0xF0) # vortexes: Normal (D0=light to dark, F0=dark to light, 42 = both) diff --git a/Rules.py b/Rules.py index 5ce634d4..41015113 100644 --- a/Rules.py +++ b/Rules.py @@ -38,6 +38,8 @@ def set_rules(world, player): if world.logic[player] == 'noglitches': no_glitches_rules(world, player) + elif world.logic[player] == 'owglitches': + overworld_glitches_rules(world, player) elif world.logic[player] == 'minorglitches': logging.getLogger('').info('Minor Glitches may be buggy still. No guarantee for proper logic checks.') else: @@ -357,7 +359,6 @@ def default_rules(world, player): set_rule(world.get_entrance('Kings Grave Mirror Spot', player), lambda state: state.has_Pearl(player) and state.has_Mirror(player)) # Caution: If king's grave is releaxed at all to account for reaching it via a two way cave's exit in insanity mode, then the bomb shop logic will need to be updated (that would involve create a small ledge-like Region for it) set_rule(world.get_entrance('Bonk Fairy (Light)', player), lambda state: state.has_Boots(player)) - set_rule(world.get_entrance('Bat Cave Drop Ledge', player), lambda state: state.has('Hammer', player)) set_rule(world.get_entrance('Lumberjack Tree Tree', player), lambda state: state.has_Boots(player) and state.has('Beat Agahnim 1', player)) set_rule(world.get_entrance('Bonk Rock Cave', player), lambda state: state.has_Boots(player)) set_rule(world.get_entrance('Desert Palace Stairs', player), lambda state: state.has('Book of Mudora', player)) @@ -625,8 +626,10 @@ def no_glitches_rules(world, player): set_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player) and (state.has('Hammer', player) or state.can_lift_rocks(player))) set_rule(world.get_entrance('Dark Lake Hylia Ledge Drop', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) else: + set_rule(world.get_entrance('Bat Cave Drop Ledge', player), lambda state: state.has('Hammer', player)) set_rule(world.get_entrance('Zoras River', player), lambda state: state.has_Pearl(player) and (state.has('Flippers', player) or state.can_lift_rocks(player))) set_rule(world.get_entrance('Lake Hylia Central Island Pier', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) # can be fake flippered to + set_rule(world.get_entrance('Lake Hylia Island', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) set_rule(world.get_entrance('Hobo Bridge', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) set_rule(world.get_entrance('Dark Lake Hylia Drop (East)', player), lambda state: state.has('Flippers', player)) set_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: state.has('Flippers', player) and (state.has('Hammer', player) or state.can_lift_rocks(player))) @@ -641,7 +644,10 @@ def no_glitches_rules(world, player): set_rule(world.get_entrance('Paradox Cave Push Block Reverse', player), lambda state: False) # no glitches does not require block override set_rule(world.get_entrance('Paradox Cave Bomb Jump', player), lambda state: False) set_rule(world.get_entrance('Skull Woods First Section Bomb Jump', player), lambda state: False) + add_conditional_lamps(world, player) + +def add_conditional_lamps(world, player): # Light cones in standard depend on which world we actually are in, not which one the location would normally be # We add Lamp requirements only to those locations which lie in the dark world (or everything if open DW_Entrances = ['Bumper Cave (Bottom)', 'Superbunny Cave (Top)', 'Superbunny Cave (Bottom)', 'Hookshot Cave', 'Bumper Cave (Top)', 'Hookshot Cave Back Entrance', 'Dark Death Mountain Ledge (East)', @@ -690,6 +696,82 @@ def no_glitches_rules(world, player): add_lamp_requirement(world.get_entrance('Throne Room', player), player) +def overworld_glitches_rules(world, player): + # spots that are immediately accessible + set_rule(world.get_entrance('Hobo Bridge', player), lambda state: True) + set_rule(world.get_region('Lake Hylia Central Island', player), lambda state: True) + set_rule(world.get_entrance('Zoras River', player), lambda state: True) + # lw boots-accessible locations + lw_boots_accessible_regions = [ + 'Bat Cave Drop Ledge', + 'Lake Hylia Island', + 'Desert Ledge', + 'Desert Ledge (Northeast)', + 'Desert Palace Lone Stairs', + 'Desert Palace Entrance (North) Spot', + 'Death Mountain', + 'Death Mountain Return Ledge', + 'East Death Mountain (Bottom)', + 'East Death Mountain (Top)', + 'Death Mountain (Top)', + 'Spectacle Rock', + 'Death Mountain Floating Island (Light World)', + ] + # dw boots-accessible regions + dw_boots_accessible_regions = [ + 'East Dark World', + 'Northeast Dark World', + 'West Dark World', + 'Hammer Peg Area', + 'Bumper Cave Ledge', + 'Dark Desert', + 'Dark Death Mountain (Top)', + 'Dark Death Mountain (East Bottom)', + 'Dark Death Mountain Ledge', + 'Death Mountain Floating Island (Dark World)', + 'Turtle Rock (Top)', + ] + # set up boots-accessible regions + if world.mode[player] != 'inverted': + lw_boots_accessible_regions.append('Cave 45 Ledge') + lw_boots_accessible_regions.append('Graveyard Ledge') + # couple other random spots + set_rule(world.get_location('Bombos Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player) and (state.has_Mirror(player) or state.has_Boots(player))) + set_rule(world.get_entrance('Dark Desert Teleporter', player), lambda state: (state.has('Ocarina', player) or state.has_Boots(player)) and state.can_lift_heavy_rocks(player)) + set_rule(world.get_entrance('South Hyrule Teleporter', player), lambda state: (state.has('Hammer', player) or state.has_Boots(player)) and state.can_lift_rocks(player)) + set_rule(world.get_location('Zora\'s Ledge', player), lambda state: state.has_Boots(player)) + add_rule(world.get_entrance('Ganons Tower', player), lambda state: state.has_Boots(player) and state.has_Pearl(player), 'or') + needs_boots = lambda state: state.has_Boots(player) + needs_boots_and_pearl = lambda state: state.has_Boots(player) and state.has_Pearl(player) + for spot in lw_boots_accessible_regions: + for location in world.get_region(spot, player).locations: + add_rule(world.get_location(location, player), needs_boots_and_pearl if world.mode[player] == 'inverted' else needs_boots, 'or') + for spot in dw_boots_accessible_regions: + for location in world.get_region(spot, player).locations: + add_rule(world.get_location(location, player), needs_boots if world.mode[player] == 'inverted' else needs_boots_and_pearl, 'or') + # bunny DMD rules + if world.mode[player] != 'inverted': + # set up some mirror-accessible dw entrances. + boots_and_mirror = lambda state: state.has_Boots(player) and state.has_Mirror(player) + add_rule(world.get_entrance('Dark Sanctuary Hint', player), boots_and_mirror, 'or') # should suffice to give us west dark world access + for spot in world.get_region('Dark Death Mountain (East Bottom)', player).locations: + add_rule(world.get_location(spot, player), boots_and_mirror, 'or') + # dw entrances accessible with mirror and hookshot + mirror_hookshot_accessible_dw_locations = [ + 'Pyramid Fairy', + 'Pyramid Entrance', + 'Pyramid Drop', + ] + mirror_hookshot_accessible_dw_locations.extend(world.get_region('Dark Death Mountain Ledge', player).locations) + for spot in mirror_hookshot_accessible_dw_locations: + add_rule(world.get_entrance(spot, player), lambda state: state.has_Boots(player) and state.has_Mirror(player) and state.has('Hookshot', player), 'or') + # dw entrances accessible with mirror and titans + boots_mirror_titans = lambda state: state.has_Boots(player) and state.has_Mirror(player) and state.can_lift_heavy_rocks(player) + add_rule(world.get_entrance('Mire Shed', player), boots_mirror_titans, 'or') + add_rule(world.get_location('Frog', player), boots_mirror_titans, 'or') + add_conditional_lamps(world, player) + + def open_rules(world, player): # softlock protection as you can reach the sewers small key door with a guard drop key set_rule(world.get_location('Hyrule Castle - Boomerang Chest', player), lambda state: state.has_key('Small Key (Escape)', player)) From acce83a8d8450662dc5cacd114b4a02d41fcabaa Mon Sep 17 00:00:00 2001 From: qadan Date: Fri, 3 Jan 2020 04:06:00 -0400 Subject: [PATCH 07/52] accidentally moved a thing --- Rules.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rules.py b/Rules.py index 41015113..dbcdd43b 100644 --- a/Rules.py +++ b/Rules.py @@ -359,6 +359,7 @@ def default_rules(world, player): set_rule(world.get_entrance('Kings Grave Mirror Spot', player), lambda state: state.has_Pearl(player) and state.has_Mirror(player)) # Caution: If king's grave is releaxed at all to account for reaching it via a two way cave's exit in insanity mode, then the bomb shop logic will need to be updated (that would involve create a small ledge-like Region for it) set_rule(world.get_entrance('Bonk Fairy (Light)', player), lambda state: state.has_Boots(player)) + set_rule(world.get_entrance('Bat Cave Drop Ledge', player), lambda state: state.has('Hammer', player)) set_rule(world.get_entrance('Lumberjack Tree Tree', player), lambda state: state.has_Boots(player) and state.has('Beat Agahnim 1', player)) set_rule(world.get_entrance('Bonk Rock Cave', player), lambda state: state.has_Boots(player)) set_rule(world.get_entrance('Desert Palace Stairs', player), lambda state: state.has('Book of Mudora', player)) @@ -626,7 +627,6 @@ def no_glitches_rules(world, player): set_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player) and (state.has('Hammer', player) or state.can_lift_rocks(player))) set_rule(world.get_entrance('Dark Lake Hylia Ledge Drop', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) else: - set_rule(world.get_entrance('Bat Cave Drop Ledge', player), lambda state: state.has('Hammer', player)) set_rule(world.get_entrance('Zoras River', player), lambda state: state.has_Pearl(player) and (state.has('Flippers', player) or state.can_lift_rocks(player))) set_rule(world.get_entrance('Lake Hylia Central Island Pier', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) # can be fake flippered to set_rule(world.get_entrance('Lake Hylia Island', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) From 12c5e3a3907ad44f97ef35dd4c48a2b3598bebd9 Mon Sep 17 00:00:00 2001 From: qadan Date: Fri, 3 Jan 2020 18:43:50 -0400 Subject: [PATCH 08/52] first pass at superbunny rules --- Rules.py | 75 ++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 60 insertions(+), 15 deletions(-) diff --git a/Rules.py b/Rules.py index dbcdd43b..5fb44d75 100644 --- a/Rules.py +++ b/Rules.py @@ -647,17 +647,33 @@ def no_glitches_rules(world, player): add_conditional_lamps(world, player) +DW_Entrances = ['Bumper Cave (Bottom)', + 'Superbunny Cave (Top)', + 'Superbunny Cave (Bottom)', + 'Hookshot Cave', + 'Bumper Cave (Top)', + 'Hookshot Cave Back Entrance', + 'Dark Death Mountain Ledge (East)', + 'Turtle Rock Isolated Ledge Entrance', + 'Thieves Town', + 'Skull Woods Final Section', + 'Ice Palace', + 'Misery Mire', + 'Palace of Darkness', + 'Swamp Palace', + 'Turtle Rock', + 'Dark Death Mountain Ledge (West)'] + +def check_is_dark_world(region): + for entrance in region.entrances: + if entrance.name in DW_Entrances: + return True + return False + + def add_conditional_lamps(world, player): # Light cones in standard depend on which world we actually are in, not which one the location would normally be # We add Lamp requirements only to those locations which lie in the dark world (or everything if open - DW_Entrances = ['Bumper Cave (Bottom)', 'Superbunny Cave (Top)', 'Superbunny Cave (Bottom)', 'Hookshot Cave', 'Bumper Cave (Top)', 'Hookshot Cave Back Entrance', 'Dark Death Mountain Ledge (East)', - 'Turtle Rock Isolated Ledge Entrance', 'Thieves Town', 'Skull Woods Final Section', 'Ice Palace', 'Misery Mire', 'Palace of Darkness', 'Swamp Palace', 'Turtle Rock', 'Dark Death Mountain Ledge (West)'] - - def check_is_dark_world(region): - for entrance in region.entrances: - if entrance.name in DW_Entrances: - return True - return False def add_conditional_lamp(spot, region, spottype='Location'): if spottype == 'Location': @@ -738,7 +754,6 @@ def overworld_glitches_rules(world, player): # couple other random spots set_rule(world.get_location('Bombos Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player) and (state.has_Mirror(player) or state.has_Boots(player))) set_rule(world.get_entrance('Dark Desert Teleporter', player), lambda state: (state.has('Ocarina', player) or state.has_Boots(player)) and state.can_lift_heavy_rocks(player)) - set_rule(world.get_entrance('South Hyrule Teleporter', player), lambda state: (state.has('Hammer', player) or state.has_Boots(player)) and state.can_lift_rocks(player)) set_rule(world.get_location('Zora\'s Ledge', player), lambda state: state.has_Boots(player)) add_rule(world.get_entrance('Ganons Tower', player), lambda state: state.has_Boots(player) and state.has_Pearl(player), 'or') needs_boots = lambda state: state.has_Boots(player) @@ -769,6 +784,32 @@ def overworld_glitches_rules(world, player): boots_mirror_titans = lambda state: state.has_Boots(player) and state.has_Mirror(player) and state.can_lift_heavy_rocks(player) add_rule(world.get_entrance('Mire Shed', player), boots_mirror_titans, 'or') add_rule(world.get_location('Frog', player), boots_mirror_titans, 'or') + + # all entrances you can't mirror bunny into + invalid_mirror_bunny_entrances_lw = [ + 'Bonk Rock Cave', + 'Bonk Fairy (Light)', + 'Blinds Hideout', + '50 Rupee Cave', + '20 Rupee Cave', + 'Checkerboard Cave', + 'Light Hype Fairy', + 'Waterfall of Wishing', + 'Light World Bomb Hut', + 'Mini Moldorm Cave', + 'Ice Rod Cave', + 'Hyrule Castle Secret Entrance Stairs', + 'Sanctuary Grave', + 'Kings Grave', + 'Tower of Hera', + ] + # also, you can do mini moldorm cave and spiral cave - but you need a sword + superbunny_mirror_sword = lambda state: state.has_Mirror(player) and state.has_sword(player) + mini_moldorm_cave = world.get_region('Mini Moldorm Cave', player) + if check_is_dark_world(mini_moldorm_cave): + for spot in mini_moldorm_cave.locations: + add_rule(world.get_location(spot, player), superbunny_mirror_sword, 'or') + add_rule(world.get_location('Spiral Cave', player), superbunny_mirror_sword, 'or') add_conditional_lamps(world, player) @@ -1249,6 +1290,7 @@ def set_inverted_big_bomb_rules(world, player): 'Dark Desert Hint', 'Dark Desert Fairy', 'Misery Mire'] + LW_bush_entrances = ['Bush Covered House', 'Light World Bomb Hut', 'Graveyard Cave'] @@ -1318,7 +1360,9 @@ def set_bunny_rules(world, player): 'Turtle Rock (Eye Bridge)', 'Sewers', 'Pyramid', 'Spiral Cave (Top)', 'Desert Palace Main (Inner)', 'Fairy Ascension Cave (Drop)'] bunny_accessible_locations = ['Link\'s Uncle', 'Sahasrahla', 'Sick Kid', 'Lost Woods Hideout', 'Lumberjack Tree', 'Checkerboard Cave', 'Potion Shop', 'Spectacle Rock Cave', 'Pyramid', 'Hype Cave - Generous Guy', 'Peg Cave', 'Bumper Cave Ledge', 'Dark Blacksmith Ruins'] - + # interiors that are accessible if you're in bunny state but have the mirror; OWG-only. + superbunny_accessible_locations = ['Waterfall of Wishing - Left', 'Waterfall of Wishing - Right', 'King\'s Tomb', 'Floodgate', 'Floodgate Chest', 'Cave 45', 'Bonk Rock Cave', 'Brewery', 'C-Shaped House', 'Chest Game', 'Mire Shed - Left', 'Mire Shed - Right', 'Secret Passage', 'Ice Rod Cave', 'Pyramid Fairy - Left', 'Pyramid Fairy - Right'] + invalid_mirror_bunny_entrances_dw = ['Skull Woods Final Section (Entrance)', 'Hype Cave', 'Bonk Fairy (Dark)', 'Thieves Town', 'Dark World Hammer Peg Cave', 'Brewery', 'Hookshot Cave', 'Hookshot Cave Exit (South)', 'Dark Lake Hylia Ledge Fairy', 'Dark Lake Hylia Ledge Spike Cave'] def path_to_access_rule(path, entrance): return lambda state: state.can_reach(entrance) and all(rule(state) for rule in path) @@ -1326,8 +1370,10 @@ def set_bunny_rules(world, player): def options_to_access_rule(options): return lambda state: any(rule(state) for rule in options) - def get_rule_to_add(region): + def get_rule_to_add(region, location = None): if not region.is_light_world: + if location in superbunny_accessible_locations and region.name not in invalid_mirror_bunny_entrances_dw: + return lambda state: (state.can_reach(region) and state.has_Mirror(player)) or state.has_Pearl(player) return lambda state: state.has_Pearl(player) # in this case we are mixed region. # we collect possible options. @@ -1351,7 +1397,7 @@ def set_bunny_rules(world, player): new_path = path + [entrance.access_rule] seen.add(new_region) if not new_region.is_light_world: - continue # we don't care about pure dark world entrances + continue # we don't care about pure dark world entrances in non-owg if new_region.is_dark_world: queue.append((new_region, new_path)) else: @@ -1379,7 +1425,7 @@ def set_bunny_rules(world, player): if location.name in bunny_accessible_locations: continue - add_rule(location, get_rule_to_add(location.parent_region)) + add_rule(location, get_rule_to_add(location.parent_region, location.name)) def set_inverted_bunny_rules(world, player): @@ -1388,8 +1434,7 @@ def set_inverted_bunny_rules(world, player): bunny_impassable_caves = ['Bumper Cave', 'Two Brothers House', 'Hookshot Cave', 'Skull Woods First Section (Right)', 'Skull Woods First Section (Left)', 'Skull Woods First Section (Top)', 'Turtle Rock (Entrance)', 'Turtle Rock (Second Section)', 'Turtle Rock (Big Chest)', 'Skull Woods Second Section (Drop)', 'Turtle Rock (Eye Bridge)', 'Sewers', 'Pyramid', 'Spiral Cave (Top)', 'Desert Palace Main (Inner)', 'Fairy Ascension Cave (Drop)', 'The Sky'] - bunny_accessible_locations = ['Link\'s Uncle', 'Sahasrahla', 'Sick Kid', 'Lost Woods Hideout', 'Lumberjack Tree', 'Checkerboard Cave', 'Potion Shop', 'Spectacle Rock Cave', 'Pyramid', 'Hype Cave - Generous Guy', 'Peg Cave', 'Bumper Cave Ledge', 'Dark Blacksmith Ruins', 'Bombos Tablet', 'Ether Tablet', 'Purple Chest'] - + bunny_acces1sible_locations = ['Link\'s Uncle', 'Sahasrahla', 'Sick Kid', 'Lost Woods Hideout', 'Lumberjack Tree', 'Checkerboard Cave', 'Potion Shop', 'Spectacle Rock Cave', 'Pyramid', 'Hype Cave - Generous Guy', 'Peg Cave', 'Bumper Cave Ledge', 'Dark Blacksmith Ruins', 'Bombos Tablet', 'Ether Tablet', 'Purple Chest'] def path_to_access_rule(path, entrance): return lambda state: state.can_reach(entrance) and all(rule(state) for rule in path) From f151b05b49335dce2926b0be0d9ac8e89519f35e Mon Sep 17 00:00:00 2001 From: qadan Date: Mon, 6 Jan 2020 12:53:38 -0400 Subject: [PATCH 09/52] accidentally a thing --- Rules.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rules.py b/Rules.py index 5fb44d75..735461c5 100644 --- a/Rules.py +++ b/Rules.py @@ -1434,7 +1434,7 @@ def set_inverted_bunny_rules(world, player): bunny_impassable_caves = ['Bumper Cave', 'Two Brothers House', 'Hookshot Cave', 'Skull Woods First Section (Right)', 'Skull Woods First Section (Left)', 'Skull Woods First Section (Top)', 'Turtle Rock (Entrance)', 'Turtle Rock (Second Section)', 'Turtle Rock (Big Chest)', 'Skull Woods Second Section (Drop)', 'Turtle Rock (Eye Bridge)', 'Sewers', 'Pyramid', 'Spiral Cave (Top)', 'Desert Palace Main (Inner)', 'Fairy Ascension Cave (Drop)', 'The Sky'] - bunny_acces1sible_locations = ['Link\'s Uncle', 'Sahasrahla', 'Sick Kid', 'Lost Woods Hideout', 'Lumberjack Tree', 'Checkerboard Cave', 'Potion Shop', 'Spectacle Rock Cave', 'Pyramid', 'Hype Cave - Generous Guy', 'Peg Cave', 'Bumper Cave Ledge', 'Dark Blacksmith Ruins', 'Bombos Tablet', 'Ether Tablet', 'Purple Chest'] + bunny_accessible_locations = ['Link\'s Uncle', 'Sahasrahla', 'Sick Kid', 'Lost Woods Hideout', 'Lumberjack Tree', 'Checkerboard Cave', 'Potion Shop', 'Spectacle Rock Cave', 'Pyramid', 'Hype Cave - Generous Guy', 'Peg Cave', 'Bumper Cave Ledge', 'Dark Blacksmith Ruins', 'Bombos Tablet', 'Ether Tablet', 'Purple Chest'] def path_to_access_rule(path, entrance): return lambda state: state.can_reach(entrance) and all(rule(state) for rule in path) From 62e84dfafd1a749d05762fafaaa4a03a08dc4d6a Mon Sep 17 00:00:00 2001 From: qadan Date: Mon, 6 Jan 2020 13:48:14 -0500 Subject: [PATCH 10/52] entrances and locations --- Rules.py | 130 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 93 insertions(+), 37 deletions(-) diff --git a/Rules.py b/Rules.py index 735461c5..4f5f4a10 100644 --- a/Rules.py +++ b/Rules.py @@ -713,57 +713,113 @@ def add_conditional_lamps(world, player): def overworld_glitches_rules(world, player): - # spots that are immediately accessible + # spots that are immediately accessible due to fake flippering set_rule(world.get_entrance('Hobo Bridge', player), lambda state: True) set_rule(world.get_region('Lake Hylia Central Island', player), lambda state: True) set_rule(world.get_entrance('Zoras River', player), lambda state: True) - # lw boots-accessible locations - lw_boots_accessible_regions = [ + + # boots-accessible stuff + lw_boots_accessible_entrances = [ 'Bat Cave Drop Ledge', + 'Bat Cave Drop Ledge Mirror Spot', + 'Lake Hylia Island Mirror Spot', + 'Desert Ledge Return Rocks', + 'Desert Ledge Mirror Spot', + 'Checkerboard Cave', + 'Old Man House Exit (Bottom)', + 'Desert Ledge (Northeast) Mirror Spot', + 'Death Mountain Return Cave Exit (East)', + 'Desert Palace Entrance (North) Rocks', + 'Desert Palace Entrance (North) Mirror Spot', + 'Flute Spot 1', + 'Broken Bridge (East)', + 'Death Mountain Drop', + 'Death Mountain Return Cave Exit (West)', + 'Old Man Cave Exit (East)', + 'Bumper Cave Ledge Mirror Spot', + 'Broken Bridge (West)', + 'East Death Mountain Drop', + 'Spiral Cave Ledge Drop', + 'Fairy Ascension Drop', + 'East Death Mountain (Top)', + 'East Death Mountain (Top) Mirror Spot', + 'Death Mountain (Top)', + 'Spectacle Rock Drop', + 'Spectacle Rock Mirror Spot', + 'Floating Island Mirror Spot', + 'Fairy Ascension Cave Exit (Top)', + 'Fairy Ascension Cave Exit (Bottom)', + 'Death Mountain Return Cave Exit (East)', + 'Spiral Cave Exit', + ] + lw_boots_accessible_locations = [ 'Lake Hylia Island', 'Desert Ledge', - 'Desert Ledge (Northeast)', - 'Desert Palace Lone Stairs', - 'Desert Palace Entrance (North) Spot', - 'Death Mountain', - 'Death Mountain Return Ledge', - 'East Death Mountain (Bottom)', - 'East Death Mountain (Top)', - 'Death Mountain (Top)', + 'Ether Tablet', 'Spectacle Rock', - 'Death Mountain Floating Island (Light World)', + 'Floating Island', ] - # dw boots-accessible regions - dw_boots_accessible_regions = [ - 'East Dark World', - 'Northeast Dark World', - 'West Dark World', - 'Hammer Peg Area', + dw_boots_accessible_entrances = [ + 'Northeast Dark World Broken Bridge Pass', + 'Death Mountain Return Cave Exit (West)', + 'Peg Area Rocks', + 'Grassy Lawn Pegs', + 'West Dark World Gap', + 'Bumper Cave Ledge Drop', + 'Turtle Rock Ledge Exit (West)', + 'Turtle Rock Isolated Ledge Exit', + 'Dark Desert Teleporter', + 'Turtle Rock Exit (Front)', + 'Turtle Rock Drop', + 'Floating Island Drop', + 'Turtle Rock Ledge Exit (East)', + 'Dark Death Mountain Drop (East)', + 'Village of Outcasts Drop', + 'Dark Lake Hylia Ledge', + 'Hype Cave', + 'Dark World Potion Shop', + 'Big Bomb Shop', + 'Archery Game', + 'Brewery', + 'C-Shaped House', + 'Chest Game', + 'Thieves Town', + 'Graveyard Ledge Mirror Spot', + 'Kings Grave Mirror Spot', + 'Bumper Cave Entrance Rock', + 'Red Shield Shop', + 'Dark Sanctuary Hint', + 'Fortune Teller (Dark)', + 'Dark World Lumberjack Shop', + ] + dw_boots_accessible_locations = [ + 'Catfish', + 'Frog', + 'Dark Blacksmith Ruins', 'Bumper Cave Ledge', - 'Dark Desert', - 'Dark Death Mountain (Top)', - 'Dark Death Mountain (East Bottom)', - 'Dark Death Mountain Ledge', - 'Death Mountain Floating Island (Dark World)', - 'Turtle Rock (Top)', ] # set up boots-accessible regions if world.mode[player] != 'inverted': - lw_boots_accessible_regions.append('Cave 45 Ledge') - lw_boots_accessible_regions.append('Graveyard Ledge') + lw_boots_accessible_entrances.append('Cave 45 Mirror Spot') + lw_boots_accessible_entrances.append('Graveyard Ledge Mirror Spot') # couple other random spots set_rule(world.get_location('Bombos Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player) and (state.has_Mirror(player) or state.has_Boots(player))) - set_rule(world.get_entrance('Dark Desert Teleporter', player), lambda state: (state.has('Ocarina', player) or state.has_Boots(player)) and state.can_lift_heavy_rocks(player)) + set_rule(world.get_entrance('Dark Desert Teleporter', player), lambda state: state.has('Ocarina', player) or (state.has_Boots(player) and state.can_lift_heavy_rocks(player))) set_rule(world.get_location('Zora\'s Ledge', player), lambda state: state.has_Boots(player)) add_rule(world.get_entrance('Ganons Tower', player), lambda state: state.has_Boots(player) and state.has_Pearl(player), 'or') + add_rule(world.get_entrance('East Death Mountain Teleporter', player), lambda state: state.can_lift_heavy_rocks(player) and state.has_Boots(player), 'or') + add_rule(world.get_entrance('Turtle Rock Teleporter', player), lambda state: state.has_Boots(player) and state.has('Hammer', player)) needs_boots = lambda state: state.has_Boots(player) needs_boots_and_pearl = lambda state: state.has_Boots(player) and state.has_Pearl(player) - for spot in lw_boots_accessible_regions: - for location in world.get_region(spot, player).locations: - add_rule(world.get_location(location, player), needs_boots_and_pearl if world.mode[player] == 'inverted' else needs_boots, 'or') - for spot in dw_boots_accessible_regions: - for location in world.get_region(spot, player).locations: - add_rule(world.get_location(location, player), needs_boots if world.mode[player] == 'inverted' else needs_boots_and_pearl, 'or') + for entrance in lw_boots_accessible_entrances: + add_rule(world.get_entrance(entrance, player), needs_boots_and_pearl if world.mode[player] == 'inverted' else needs_boots, 'or') + for location in lw_boots_accessible_locations: + add_rule(world.get_location(location, player), needs_boots_and_pearl if world.mode[player] == 'inverted' else needs_boots, 'or') + # no inverted rules here; no DMD bunny known so far + for entrance in dw_boots_accessible_entrances: + add_rule(world.get_entrance(entrance, player), needs_boots_and_pearl, 'or') + for location in dw_boots_accessible_locations: + add_rule(world.get_location(location, player), needs_boots_and_pearl, 'or') # bunny DMD rules if world.mode[player] != 'inverted': # set up some mirror-accessible dw entrances. @@ -779,13 +835,13 @@ def overworld_glitches_rules(world, player): ] mirror_hookshot_accessible_dw_locations.extend(world.get_region('Dark Death Mountain Ledge', player).locations) for spot in mirror_hookshot_accessible_dw_locations: - add_rule(world.get_entrance(spot, player), lambda state: state.has_Boots(player) and state.has_Mirror(player) and state.has('Hookshot', player), 'or') + add_rule(world.get_entrance(spot, player), lambda state: state.has_Mirror(player) and state.has('Hookshot', player), 'or') # dw entrances accessible with mirror and titans - boots_mirror_titans = lambda state: state.has_Boots(player) and state.has_Mirror(player) and state.can_lift_heavy_rocks(player) + boots_mirror_titans = lambda state: state.has_Mirror(player) and state.can_lift_heavy_rocks(player) add_rule(world.get_entrance('Mire Shed', player), boots_mirror_titans, 'or') add_rule(world.get_location('Frog', player), boots_mirror_titans, 'or') - # all entrances you can't mirror bunny into + # all entrances you can't mirror bunny into. @todo: use for inverted invalid_mirror_bunny_entrances_lw = [ 'Bonk Rock Cave', 'Bonk Fairy (Light)', @@ -1372,7 +1428,7 @@ def set_bunny_rules(world, player): def get_rule_to_add(region, location = None): if not region.is_light_world: - if location in superbunny_accessible_locations and region.name not in invalid_mirror_bunny_entrances_dw: + if world.logic[player] == 'owglitches' and location in superbunny_accessible_locations and region.name not in invalid_mirror_bunny_entrances_dw: return lambda state: (state.can_reach(region) and state.has_Mirror(player)) or state.has_Pearl(player) return lambda state: state.has_Pearl(player) # in this case we are mixed region. From c677a875f2a124bd0930467b2952e0587d24839b Mon Sep 17 00:00:00 2001 From: qadan Date: Thu, 9 Jan 2020 14:43:21 -0500 Subject: [PATCH 11/52] accidentally another thing --- Rules.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rules.py b/Rules.py index 4f5f4a10..5c2a7e72 100644 --- a/Rules.py +++ b/Rules.py @@ -860,7 +860,7 @@ def overworld_glitches_rules(world, player): 'Tower of Hera', ] # also, you can do mini moldorm cave and spiral cave - but you need a sword - superbunny_mirror_sword = lambda state: state.has_Mirror(player) and state.has_sword(player) + superbunny_mirror_sword = lambda state: state.has_Boots(player) and state.has_Mirror(player) and state.has_sword(player) mini_moldorm_cave = world.get_region('Mini Moldorm Cave', player) if check_is_dark_world(mini_moldorm_cave): for spot in mini_moldorm_cave.locations: From 4b7694b50f515a712aecbbc9047e82ecf8badbca Mon Sep 17 00:00:00 2001 From: qadan Date: Tue, 28 Jan 2020 18:19:07 -0400 Subject: [PATCH 12/52] updates --- BaseClasses.py | 3 +- ER_hint_reference.txt | 359 ------------------------------------------ EntranceRandomizer.py | 3 +- Main.py | 4 +- Mystery.py | 10 +- Rom.py | 11 +- Rules.py | 108 ++++--------- 7 files changed, 45 insertions(+), 453 deletions(-) delete mode 100644 ER_hint_reference.txt diff --git a/BaseClasses.py b/BaseClasses.py index 01752a0b..a8fac2a2 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -9,7 +9,7 @@ from Utils import int16_as_bytes class World(object): - def __init__(self, players, shuffle, logic, mode, swords, difficulty, difficulty_adjustments, timer, progressive, goal, algorithm, accessibility, shuffle_ganon, retro, custom, customitemarray, hints): + def __init__(self, players, shuffle, logic, mode, swords, difficulty, difficulty_adjustments, timer, progressive, goal, algorithm, accessibility, shuffle_ganon, retro, custom, customitemarray, hints, text): self.players = players self.teams = 1 self.shuffle = shuffle.copy() @@ -54,6 +54,7 @@ class World(object): self.dynamic_locations = [] self.spoiler = Spoiler(self) self.lamps_needed_for_dark_rooms = 1 + self.text = text for player in range(1, players + 1): def set_player_attr(attr, val): diff --git a/ER_hint_reference.txt b/ER_hint_reference.txt deleted file mode 100644 index da45c78f..00000000 --- a/ER_hint_reference.txt +++ /dev/null @@ -1,359 +0,0 @@ -Hint description: - -Hints will appear in the following ratios across the 15 telepathic tiles that have hints and the five storyteller locations: - -4 hints for inconvenient entrances. -4 hints for random entrances (this can by coincidence pick inconvenient entrances that aren't used for the first set of hints). -3 hints for inconvenient item locations. -5 hints for valuable items. -4 junk hints. - -In the vanilla, dungeonssimple, and dungeonsfull shuffles, the following ratios will be used instead: - -5 hints for inconvenient item locations. -8 hints for valuable items. -7 junk hints. - -In the simple, restricted, and restricted legacy shuffles, these are the ratios: - -2 hints for inconvenient entrances. -1 hint for an inconvenient dungeon entrance. -4 hints for random entrances (this can by coincidence pick inconvenient entrances that aren't used for the first set of hints). -3 hints for inconvenient item locations. -5 hints for valuable items. -5 junk hints. - -These hints will use the following format: - -Entrance hints go "[Entrance on overworld] leads to [interior]". - -Inconvenient item locations are a little more custom but amount to "[Location] has [item name]". The item name is literal and will specify which dungeon the dungeon specific items hail from (small key/big key/map/compass). - -The valuable items are of the format "[item name] can be found [location]". The item name is again literal, and the location text is taken from Ganon's silver arrow hints. Note that the way it works is that every unique valuable item that exists is considered independently, and you won't get multiple hints for the EXACT same item (so you can only get one hint for Progressive Sword no matter how many swords exist in the seed, but if swords are not progressive, you could get hints for both Master Sword and Tempered Sword). More copies of an item existing does not increase the probability of getting a hint for that particular item (you are equally likely to get a hint for a Progressive Sword as for the Hammer). Unlike the IR, item names are never obfuscated by "something unique", and there is no special bias for hints for GT Big Key or Pegasus Boots. - -Hint Locations: - -Eastern Palace room before Big Chest -Desert Palace bonk torch room -Tower of Hera entrance room -Tower of Hera Big Chest room -Castle Tower after dark rooms -Palace of Darkness before Bow section -Swamp Palace entryway -Thieves' Town upstairs -Ice Palace entrance -Ice Palace after first drop -Ice Palace tall ice floor room -Misery Mire cutscene room -Turtle Rock entrance -Spectacle Rock cave -Spiky Hint cave -PoD Bdlg NPC -Near PoD Storyteller (bug near bomb wall) -Dark Sanctuary Storyteller (long room with tables) -Near Mire Storyteller (feather duster in winding cave) -SE DW Storyteller (owl in winding cave) - -Inconvenient entrance list: - -Skull Woods Final -Ice Palace -Misery Mire -Turtle Rock -Ganon's Tower -Mimic Ledge -SW DM Foothills Cave (mirror from upper Bumper ledge) -Hammer Pegs (near purple chest) -Super Bomb cracked wall - -Inconvenient location list: - -Swamp left (two chests) -Mire left (two chests) -Hera basement -Eastern Palace Big Key chest (protected by anti-fairies) -Thieves' Town Big Chest -Ice Palace Big Chest -Ganon's Tower Big Chest -Purple Chest -Spike Cave -Magic Bat -Sahasrahla (Green Pendant) - -In the vanilla, dungeonssimple, and dungeonsfull shuffles, the following two locations are added to the inconvenient locations list: - -Graveyard Cave -Mimic Cave - -Valuable Items are simply all items that are shown on the pause subscreen (Y, B, or A sections) minus Silver Arrows and plus Triforce Pieces, Magic Upgrades (1/2 or 1/4), and the Single Arrow. If key shuffle is being used, you can additionally get hints for Small Keys or Big Keys but not hints for Maps or Compasses. - -While the exact verbage of location names and item names can be found in the source code, here's a copy for reference: - -Overworld Entrance naming: - -Turtle Rock: Turtle Rock Main -Misery Mire: Misery Mire -Ice Palace: Ice Palace -Skull Woods Final Section: The back of Skull Woods -Death Mountain Return Cave (West): The SW DM Foothills Cave -Mimic Cave: Mimic Ledge -Dark World Hammer Peg Cave: The rows of pegs -Pyramid Fairy: The crack on the pyramid -Eastern Palace: Eastern Palace -Elder House (East): Elder House -Elder House (West): Elder House -Two Brothers House (East): Eastern Quarreling Brothers' house -Old Man Cave (West): The lower DM entrance -Hyrule Castle Entrance (South): The ground level castle door -Thieves Town: Thieves' Town -Bumper Cave (Bottom): The lower Bumper Cave -Swamp Palace: Swamp Palace -Dark Death Mountain Ledge (West): The East dark DM connector ledge -Dark Death Mountain Ledge (East): The East dark DM connector ledge -Superbunny Cave (Top): The summit of dark DM cave -Superbunny Cave (Bottom): The base of east dark DM -Hookshot Cave: The rock on dark DM -Desert Palace Entrance (South): The book sealed passage -Tower of Hera: The Tower of Hera -Two Brothers House (West): The door near the race game -Old Man Cave (East): The SW-most cave on west DM -Old Man House (Bottom): A cave with a door on west DM -Old Man House (Top): The eastmost cave on west DM -Death Mountain Return Cave (East): The westmost cave on west DM -Spectacle Rock Cave Peak: The highest cave on west DM -Spectacle Rock Cave: The right ledge on west DM -Spectacle Rock Cave (Bottom): The left ledge on west DM -Paradox Cave (Bottom): The right paired cave on east DM -Paradox Cave (Middle): The southmost cave on east DM -Paradox Cave (Top): The east DM summit cave -Fairy Ascension Cave (Bottom): The east DM cave behind rocks -Fairy Ascension Cave (Top): The central ledge on east DM -Spiral Cave: The left ledge on east DM -Spiral Cave (Bottom): The SWmost cave on east DM -Palace of Darkness: Palace of Darkness -Hyrule Castle Entrance (West): The left castle door -Hyrule Castle Entrance (East): The right castle door -Agahnims Tower: The sealed castle door -Desert Palace Entrance (West): The westmost building in the desert -Desert Palace Entrance (North): The northmost cave in the desert -Blinds Hideout: Blind's old house -Lake Hylia Fairy: A cave NE of Lake Hylia -Light Hype Fairy: The cave south of your house -Desert Fairy: The cave near the desert -Chicken House: The chicken lady's house -Aginahs Cave: The open desert cave -Sahasrahlas Hut: The house near armos -Cave Shop (Lake Hylia): The cave NW Lake Hylia -Blacksmiths Hut: The old smithery -Sick Kids House: The central house in Kakariko -Lost Woods Gamble: A tree trunk door -Fortune Teller (Light): A building NE of Kakariko -Snitch Lady (East): A house guarded by a snitch -Snitch Lady (West): A house guarded by a snitch -Bush Covered House: A house with an uncut lawn -Tavern (Front): A building with a backdoor -Light World Bomb Hut: A Kakariko building with no door -Kakariko Shop: The old Kakariko shop -Mini Moldorm Cave: The cave south of Lake Hylia -Long Fairy Cave: The eastmost portal cave -Good Bee Cave: The open cave SE Lake Hylia -20 Rupee Cave: The rock SE Lake Hylia -50 Rupee Cave: The rock near the desert -Ice Rod Cave: The sealed cave SE Lake Hylia -Library: The old library -Potion Shop: The witch's building -Dam: The old dam -Lumberjack House: The lumberjack house -Lake Hylia Fortune Teller: The building NW Lake Hylia -Kakariko Gamble Game: The old Kakariko gambling den -Waterfall of Wishing: Going behind the waterfall -Capacity Upgrade: The cave on the island -Bonk Rock Cave: The rock pile near Sanctuary -Graveyard Cave: The graveyard ledge -Checkerboard Cave: The NE desert ledge -Cave 45: The ledge south of haunted grove -Kings Grave: The northeastmost grave -Bonk Fairy (Light): The rock pile near your home -Hookshot Fairy: A cave on east DM -Bonk Fairy (Dark): The rock pile near the old bomb shop -Dark Sanctuary Hint: The dark sanctuary cave -Dark Lake Hylia Fairy: The cave NE dark Lake Hylia -C-Shaped House: The NE house in Village of Outcasts -Big Bomb Shop: The old bomb shop -Dark Death Mountain Fairy: The SW cave on dark DM -Dark Lake Hylia Shop: The building NW dark Lake Hylia -Dark World Shop: The hammer sealed building -Red Shield Shop: The fenced in building -Mire Shed: The western hut in the mire -East Dark World Hint: The dark cave near the eastmost portal -Dark Desert Hint: The cave east of the mire -Spike Cave: The ledge cave on west dark DM -Palace of Darkness Hint: The building south of Kiki -Dark Lake Hylia Ledge Spike Cave: The rock SE dark Lake Hylia -Cave Shop (Dark Death Mountain): The base of east dark DM -Dark World Potion Shop: The building near the catfish -Archery Game: The old archery game -Dark World Lumberjack Shop: The northmost Dark World building -Hype Cave: The cave south of the old bomb shop -Brewery: The Village of Outcasts building with no door -Dark Lake Hylia Ledge Hint: The open cave SE dark Lake Hylia -Chest Game: The westmost building in the Village of Outcasts -Dark Desert Fairy: The eastern hut in the mire -Dark Lake Hylia Ledge Fairy: The sealed cave SE dark Lake Hylia -Fortune Teller (Dark): The building NE the Village of Outcasts -Sanctuary: Sanctuary -Lumberjack Tree Cave: The cave Behind Lumberjacks -Lost Woods Hideout Stump: The stump in Lost Woods -North Fairy Cave: The cave East of Graveyard -Bat Cave Cave: The cave in eastern Kakariko -Kakariko Well Cave: The cave in northern Kakariko -Hyrule Castle Secret Entrance Stairs: The tunnel near the castle -Skull Woods First Section Door: The southeastmost skull -Skull Woods Second Section Door (East): The central open skull -Skull Woods Second Section Door (West): The westmost open skull -Desert Palace Entrance (East): The eastern building in the desert -Turtle Rock Isolated Ledge Entrance: The isolated ledge on east dark DM -Bumper Cave (Top): The upper Bumper Cave -Hookshot Cave Back Entrance: The stairs on the floating island - -Destination Entrance Naming: - -Hyrule Castle: Hyrule Castle (all three entrances) -Eastern Palace: Eastern Palace -Desert Palace: Desert Palace (all four entrances, including final) -Tower of Hera: Tower of Hera -Palace of Darkness: Palace of Darkness -Swamp Palace: Swamp Palace -Skull Woods: Skull Woods (any entrance including final) -Thieves' Town: Thieves' Town -Ice Palace: Ice Palace -Misery Mire: Misery Mire -Turtle Rock: Turtle Rock (all four entrances) -Ganon's Tower: Ganon's Tower -Castle Tower: Agahnim's Tower -A connector: Paradox Cave, Spectacle Rock Cave, Hookshot Cave, Superbunny Cave, Spiral Cave, Old Man Fetch Cave, Old Man House, Elder House, Quarreling Brothers' House, Bumper Cave, DM Fairy Ascent Cave, DM Exit Cave -A bounty of five items: Mini-moldorm cave, Hype Cave, Blind's Hideout -Sahasrahla: Sahasrahla -A cave with two items: Mire hut, Waterfall Fairy, Pyramid Fairy -A fairy fountain: Any healer fairy cave, either bonk cave with four fairies, the "long fairy" cave -A common shop: Any shop that sells bombs by default -The rare shop: The shop that sells the Red Shield by default -The potion shop: Potion Shop -The bomb shop: Bomb Shop -A fortune teller: Any of the three fortune tellers -A house with a chest: Chicken Lady's house, C-House, Brewery -A cave with an item: Checkerboard cave, Hammer Pegs cave, Cave 45, Graveyard Ledge cave -A cave with a chest: Sanc Bonk Rock Cave, Cape Grave Cave, Ice Rod Cave, Aginah's Cave -The dam: Watergate -The sick kid: Sick Kid -The library: Library -Mimic Cave: Mimic Cave -Spike Cave: Spike Cave -A game of 16 chests: VoO chest game (for the item) -A storyteller: The four DW NPCs who charge 20 rupees for a hint as well as the PoD Bdlg guy who gives a free hint -A cave with some cash: 20 rupee cave, 50 rupee cave (both have thieves and some pots) -A game of chance: Gambling game (just for cash, no items) -A game of skill: Archery minigame -The queen of fairies: Capacity Upgrade Fairy -A drop's exit: Sanctuary, LW Thieves' Hideout, Kakariko Well, Magic Bat, Useless Fairy, Uncle Tunnel, Ganon drop exit -A restock room: The Kakariko bomb/arrow restock room -The tavern: The Kakariko tavern -The grass man: The Kakariko man with many beds -A cold bee: The "wrong side" of Ice Rod cave where you can get a Good Bee -Fairies deep in a cave: Hookshot Fairy - -Location naming reference: - -Mushroom: in the woods -Master Sword Pedestal: at the pedestal -Bottle Merchant: with a merchant -Stumpy: with tree boy -Flute Spot: underground -Digging Game: underground -Lake Hylia Island: on an island -Floating Island: on an island -Bumper Cave Ledge: on a ledge -Spectacle Rock: atop a rock -Maze Race: at the race -Desert Ledge: in the desert -Pyramid: on the pyramid -Catfish: with a catfish -Ether Tablet: at a monument -Bombos Tablet: at a monument -Hobo: with the hobo -Zora's Ledge: near Zora -King Zora: at a high price -Sunken Treasure: underwater -Floodgate Chest: in the dam -Blacksmith: with the smith -Purple Chest: from a box -Old Man: with the old man -Link's Uncle: with your uncle -Secret Passage: near your uncle -Kakariko Well (5 items): in a well -Lost Woods Hideout: near a thief -Lumberjack Tree: in a hole -Magic Bat: with the bat -Paradox Cave (7 items): in a cave with seven chests -Blind's Hideout (5 items): in a basement -Mini Moldorm Cave (5 items): near Moldorms -Hype Cave (4 back chests): near a bat-like man -Hype Cave - Generous Guy: with a bat-like man -Hookshot Cave (4 items): across pits -Sahasrahla's Hut (chests in back): near the elder -Sahasrahla: with the elder -Waterfall Fairy (2 items): near a fairy -Pyramid Fairy (2 items): near a fairy -Mire Shed (2 items): near sparks -Superbunny Cave (2 items): in a connection -Spiral Cave: in spiral cave -Kakariko Tavern: in the bar -Link's House: in your home -Sick Kid: with the sick -Library: near books -Potion Shop: near potions -Spike Cave: beyond spikes -Mimic Cave: in a cave of mimicry -Chest Game: as a prize -Chicken House: near poultry -Aginah's Cave: with Aginah -Ice Rod Cave: in a frozen cave -Brewery: alone in a home -C-Shaped House: alone in a home -Spectacle Rock Cave: alone in a cave -King's Tomb: alone in a cave -Cave 45: alone in a cave -Graveyard Cave: alone in a cave -Checkerboard Cave: alone in a cave -Bonk Rock Cave: alone in a cave -Peg Cave: alone in a cave -Sanctuary: in Sanctuary -Hyrule Castle - Boomerang Chest: in Hyrule Castle -Hyrule Castle - Map Chest: in Hyrule Castle -Hyrule Castle - Zelda's Chest: in Hyrule Castle -Sewers - Dark Cross: in the sewers -Sewers - Secret Room (3 items): in the sewers -Eastern Palace - Boss: with the Armos -Eastern Palace (otherwise, 5 items): in Eastern Palace -Desert Palace - Boss: with Lanmolas -Desert Palace (otherwise, 5 items): in Desert Palace -Tower of Hera - Boss: with Moldorm -Tower of Hera (otherwise, 5 items): in Tower of Hera -Castle Tower (2 items): in Castle Tower -Palace of Darkness - Boss: with Helmasaur King -Palace of Darkness (otherwise, 13 items): in Palace of Darkness -Swamp Palace - Boss: with Arrghus -Swamp Palace (otherwise, 9 items): in Swamp Palace -Skull Woods - Bridge Room: near Mothula -Skull Woods - Boss: with Mothula -Skull Woods (otherwise, 6 items): in Skull Woods -Thieves' Town - Boss: with Blind -Thieves' Town (otherwise, 7 items): in Thieves' Town -Ice Palace - Boss: with Kholdstare -Ice Palace (otherwise, 7 items): in Ice Palace -Misery Mire - Boss: with Vitreous -Misery Mire (otherwise, 7 items): in Misery Mire -Turtle Rock - Boss: with Trinexx -Turtle Rock (otherwise, 11 items): in Turtle Rock -Ganons Tower (after climb, 4 items): atop Ganon's Tower -Ganon's Tower (otherwise, 23 items): in Ganon's Tower \ No newline at end of file diff --git a/EntranceRandomizer.py b/EntranceRandomizer.py index 48630a28..696b277b 100755 --- a/EntranceRandomizer.py +++ b/EntranceRandomizer.py @@ -276,6 +276,7 @@ def parse_arguments(argv, no_defaults=False): parser.add_argument('--outputpath') parser.add_argument('--race', default=defval(False), action='store_true') parser.add_argument('--outputname') + parser.add_argument('--text', default=defval('text'), choices=['text', 'fantatext']) if multiargs.multi: for player in range(1, multiargs.multi + 1): @@ -296,7 +297,7 @@ def parse_arguments(argv, no_defaults=False): 'retro', 'accessibility', 'hints', 'beemizer', 'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots', 'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor', 'heartbeep', - 'remote_items']: + 'remote_items', 'text']: value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name) if player == 1: setattr(ret, name, {1: value}) diff --git a/Main.py b/Main.py index 62dc62a2..69bc6089 100644 --- a/Main.py +++ b/Main.py @@ -30,7 +30,7 @@ def main(args, seed=None): start = time.process_time() # initialize the world - world = World(args.multi, args.shuffle, args.logic, args.mode, args.swords, args.difficulty, args.item_functionality, args.timer, args.progressive, args.goal, args.algorithm, args.accessibility, args.shuffleganon, args.retro, args.custom, args.customitemarray, args.hints) + world = World(args.multi, args.shuffle, args.logic, args.mode, args.swords, args.difficulty, args.item_functionality, args.timer, args.progressive, args.goal, args.algorithm, args.accessibility, args.shuffleganon, args.retro, args.custom, args.customitemarray, args.hints, args.text) logger = logging.getLogger('') if seed is None: random.seed(None) @@ -230,7 +230,7 @@ def main(args, seed=None): def copy_world(world): # ToDo: Not good yet - ret = World(world.players, world.shuffle, world.logic, world.mode, world.swords, world.difficulty, world.difficulty_adjustments, world.timer, world.progressive, world.goal, world.algorithm, world.accessibility, world.shuffle_ganon, world.retro, world.custom, world.customitemarray, world.hints) + ret = World(world.players, world.shuffle, world.logic, world.mode, world.swords, world.difficulty, world.difficulty_adjustments, world.timer, world.progressive, world.goal, world.algorithm, world.accessibility, world.shuffle_ganon, world.retro, world.custom, world.customitemarray, world.hints, world.text) ret.teams = world.teams ret.player_names = copy.deepcopy(world.player_names) ret.remote_items = world.remote_items.copy() diff --git a/Mystery.py b/Mystery.py index 57be642b..25826a99 100644 --- a/Mystery.py +++ b/Mystery.py @@ -67,6 +67,7 @@ def main(): if path: if path not in weights_cache: weights_cache[path] = get_weights(path) + print(weights_cache[path]) print(f"P{player} Weights: {path} >> {weights_cache[path]['description']}") erargs = parse_arguments(['--multi', str(args.multi)]) @@ -83,7 +84,6 @@ def main(): erargs.enemizercli = args.enemizercli settings_cache = {k: (roll_settings(v) if args.samesettings else None) for k, v in weights_cache.items()} - for player in range(1, args.multi + 1): path = getattr(args, f'p{player}') if getattr(args, f'p{player}') else args.weights if path: @@ -102,11 +102,8 @@ def main(): def get_weights(path): try: - if urllib.parse.urlparse(path).scheme: - yaml = str(urllib.request.urlopen(path).read(), "utf-8") - else: - with open(path, 'rb') as f: - yaml = str(f.read(), "utf-8") + with open(path, 'rb') as f: + yaml = str(f.read(), "utf-8") except Exception as e: print('Failed to read weights (%s)' % e) return @@ -214,6 +211,7 @@ def roll_settings(weights): ret.heartbeep = get_choice('heartbeep', romweights) ret.ow_palettes = get_choice('ow_palettes', romweights) ret.uw_palettes = get_choice('uw_palettes', romweights) + ret.text = get_choice('text', romweights) return ret diff --git a/Rom.py b/Rom.py index b4f618a1..7ac5bcde 100644 --- a/Rom.py +++ b/Rom.py @@ -12,9 +12,8 @@ import subprocess from BaseClasses import CollectionState, ShopType, Region, Location from Dungeons import dungeon_music_addresses from Regions import location_table -from Text import MultiByteTextMapper, CompressedTextMapper, text_addresses, Credits, TextTable -from Text import Uncle_texts, Ganon1_texts, TavernMan_texts, Sahasrahla2_texts, Triforce_texts, Blind_texts, BombShop2_texts, junk_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 Text import MultiByteTextMapper, CompressedTextMapper, text_addresses, Credits from Utils import output_path, local_path, int16_as_bytes, int32_as_bytes, snes_to_pc from Items import ItemFactory from EntranceShuffle import door_addresses @@ -1535,6 +1534,12 @@ def write_string_to_rom(rom, target, string): def write_strings(rom, world, player, team): + if world.text[player] == 'text': + from Text import TextTable, Uncle_texts, Ganon1_texts, TavernMan_texts, Sahasrahla2_texts, Triforce_texts, Blind_texts, BombShop2_texts, junk_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 + elif world.text[player] == 'fantatext': + from FantaText import TextTable, Uncle_texts, Ganon1_texts, TavernMan_texts, Sahasrahla2_texts, Triforce_texts, Blind_texts, BombShop2_texts, junk_texts + from FantaText 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 tt = TextTable() tt.removeUnwantedText() diff --git a/Rules.py b/Rules.py index 3151f65b..fd6735f1 100644 --- a/Rules.py +++ b/Rules.py @@ -713,118 +713,61 @@ def add_conditional_lamps(world, player): def overworld_glitches_rules(world, player): - # spots that are immediately accessible - set_rule(world.get_entrance('Hobo Bridge', player), lambda state: True) - set_rule(world.get_region('Lake Hylia Central Island', player), lambda state: True) - set_rule(world.get_entrance('Zoras River', player), lambda state: True) - # lw boots-accessible locations - lw_boots_accessible_regions = [ - 'Bat Cave Drop Ledge', - 'Lake Hylia Island', - 'Desert Ledge', - 'Desert Ledge (Northeast)', - 'Desert Palace Lone Stairs', - 'Desert Palace Entrance (North) Spot', - 'Death Mountain', - 'Death Mountain Return Ledge', - 'East Death Mountain (Bottom)', - 'East Death Mountain (Top)', - 'Death Mountain (Top)', - 'Spectacle Rock', - 'Death Mountain Floating Island (Light World)', - ] - # dw boots-accessible regions - dw_boots_accessible_regions = [ - 'East Dark World', - 'Northeast Dark World', - 'West Dark World', - 'Hammer Peg Area', - 'Bumper Cave Ledge', - 'Dark Desert', - 'Dark Death Mountain (Top)', - 'Dark Death Mountain (East Bottom)', - 'Dark Death Mountain Ledge', - 'Death Mountain Floating Island (Dark World)', - 'Turtle Rock (Top)', - ] - # set up boots-accessible regions - if world.mode[player] != 'inverted': - lw_boots_accessible_regions.append('Cave 45 Ledge') - lw_boots_accessible_regions.append('Graveyard Ledge') - # couple other random spots - set_rule(world.get_location('Bombos Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player) and (state.has_Mirror(player) or state.has_Boots(player))) - set_rule(world.get_entrance('Dark Desert Teleporter', player), lambda state: (state.has('Ocarina', player) or state.has_Boots(player)) and state.can_lift_heavy_rocks(player)) - set_rule(world.get_entrance('South Hyrule Teleporter', player), lambda state: (state.has('Hammer', player) or state.has_Boots(player)) and state.can_lift_rocks(player)) - set_rule(world.get_location('Zora\'s Ledge', player), lambda state: state.has_Boots(player)) - add_rule(world.get_entrance('Ganons Tower', player), lambda state: state.has_Boots(player) and state.has_Pearl(player), 'or') - needs_boots = lambda state: state.has_Boots(player) - needs_boots_and_pearl = lambda state: state.has_Boots(player) and state.has_Pearl(player) - for spot in lw_boots_accessible_regions: - for location in world.get_region(spot, player).locations: - add_rule(world.get_location(location, player), needs_boots_and_pearl if world.mode[player] == 'inverted' else needs_boots, 'or') - for spot in dw_boots_accessible_regions: - for location in world.get_region(spot, player).locations: - add_rule(world.get_location(location, player), needs_boots if world.mode[player] == 'inverted' else needs_boots_and_pearl, 'or') # spots that are immediately accessible due to fake flippering set_rule(world.get_entrance('Hobo Bridge', player), lambda state: True) - set_rule(world.get_region('Lake Hylia Central Island', player), lambda state: True) set_rule(world.get_entrance('Zoras River', player), lambda state: True) + set_rule(world.get_entrance('Lake Hylia Island Mirror Spot', player), lambda state: True) + set_rule(world.get_entrance('Capacity Upgrade', player), lambda state: True) # boots-accessible stuff lw_boots_accessible_entrances = [ 'Bat Cave Drop Ledge', - 'Bat Cave Drop Ledge Mirror Spot', - 'Lake Hylia Island Mirror Spot', 'Desert Ledge Return Rocks', - 'Desert Ledge Mirror Spot', - 'Checkerboard Cave', - 'Old Man House Exit (Bottom)', - 'Desert Ledge (Northeast) Mirror Spot', - 'Death Mountain Return Cave Exit (East)', - 'Desert Palace Entrance (North) Rocks', - 'Desert Palace Entrance (North) Mirror Spot', + 'Desert Palace Entrance (West)', + 'Desert Palace Entrance (North)', 'Flute Spot 1', 'Broken Bridge (East)', 'Death Mountain Drop', - 'Death Mountain Return Cave Exit (West)', - 'Old Man Cave Exit (East)', - 'Bumper Cave Ledge Mirror Spot', + 'Old Man Cave (East)', + 'Old Man House (Bottom)', + 'Old Man House (Top)', + 'Death Mountain Return Cave (East)', + 'Spectacle Rock Cave', + 'Spectacle Rock Cave Peak', + 'Spectacle Rock Cave (Bottom)', 'Broken Bridge (West)', + 'Broken Bridge (East)', 'East Death Mountain Drop', 'Spiral Cave Ledge Drop', 'Fairy Ascension Drop', + 'Fairy Ascension Cave (Bottom)', 'East Death Mountain (Top)', - 'East Death Mountain (Top) Mirror Spot', 'Death Mountain (Top)', 'Spectacle Rock Drop', - 'Spectacle Rock Mirror Spot', - 'Floating Island Mirror Spot', - 'Fairy Ascension Cave Exit (Top)', - 'Fairy Ascension Cave Exit (Bottom)', - 'Death Mountain Return Cave Exit (East)', - 'Spiral Cave Exit', + 'Death Mountain Return Cave (West)', + 'Paradox Cave (Bottom)', + 'Paradox Cave (Middle)', + 'Hookshot Fairy', + 'Spiral Cave (Bottom)', + 'Paradox Cave (Top)', + 'Spiral Cave Ledge Access', + 'Fairy Ascension Ledge', ] lw_boots_accessible_locations = [ 'Lake Hylia Island', 'Desert Ledge', - 'Ether Tablet', 'Spectacle Rock', 'Floating Island', ] dw_boots_accessible_entrances = [ 'Northeast Dark World Broken Bridge Pass', - 'Death Mountain Return Cave Exit (West)', 'Peg Area Rocks', 'Grassy Lawn Pegs', 'West Dark World Gap', 'Bumper Cave Ledge Drop', - 'Turtle Rock Ledge Exit (West)', - 'Turtle Rock Isolated Ledge Exit', 'Dark Desert Teleporter', - 'Turtle Rock Exit (Front)', 'Turtle Rock Drop', 'Floating Island Drop', - 'Turtle Rock Ledge Exit (East)', 'Dark Death Mountain Drop (East)', 'Village of Outcasts Drop', 'Dark Lake Hylia Ledge', @@ -852,15 +795,18 @@ def overworld_glitches_rules(world, player): ] # set up boots-accessible regions if world.mode[player] != 'inverted': - lw_boots_accessible_entrances.append('Cave 45 Mirror Spot') - lw_boots_accessible_entrances.append('Graveyard Ledge Mirror Spot') + lw_boots_accessible_entrances.append('Cave 45') + lw_boots_accessible_entrances.append('Graveyard Cave') # couple other random spots set_rule(world.get_location('Bombos Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player) and (state.has_Mirror(player) or state.has_Boots(player))) + set_rule(world.get_location('Ether Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player) and (state.has_Mirror(player) or state.has_Boots(player))) set_rule(world.get_entrance('Dark Desert Teleporter', player), lambda state: state.has('Ocarina', player) or (state.has_Boots(player) and state.can_lift_heavy_rocks(player))) set_rule(world.get_location('Zora\'s Ledge', player), lambda state: state.has_Boots(player)) add_rule(world.get_entrance('Ganons Tower', player), lambda state: state.has_Boots(player) and state.has_Pearl(player), 'or') add_rule(world.get_entrance('East Death Mountain Teleporter', player), lambda state: state.can_lift_heavy_rocks(player) and state.has_Boots(player), 'or') - add_rule(world.get_entrance('Turtle Rock Teleporter', player), lambda state: state.has_Boots(player) and state.has('Hammer', player)) + add_rule(world.get_entrance('Turtle Rock Teleporter', player), lambda state: state.has_Boots(player) and state.has('Hammer', player), 'or') + add_rule(world.get_entrance('Checkerboard Cave', player), lambda state: state.has_Boots(player) and state.can_lift_rocks(player), 'or') + needs_boots = lambda state: state.has_Boots(player) needs_boots_and_pearl = lambda state: state.has_Boots(player) and state.has_Pearl(player) for entrance in lw_boots_accessible_entrances: From 766215f056b7f6621c6d576fef244909cc9099fe Mon Sep 17 00:00:00 2001 From: qadan Date: Tue, 28 Jan 2020 18:20:01 -0400 Subject: [PATCH 13/52] accidentally a thing --- ER_hint_reference.txt | 359 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 359 insertions(+) create mode 100644 ER_hint_reference.txt diff --git a/ER_hint_reference.txt b/ER_hint_reference.txt new file mode 100644 index 00000000..da45c78f --- /dev/null +++ b/ER_hint_reference.txt @@ -0,0 +1,359 @@ +Hint description: + +Hints will appear in the following ratios across the 15 telepathic tiles that have hints and the five storyteller locations: + +4 hints for inconvenient entrances. +4 hints for random entrances (this can by coincidence pick inconvenient entrances that aren't used for the first set of hints). +3 hints for inconvenient item locations. +5 hints for valuable items. +4 junk hints. + +In the vanilla, dungeonssimple, and dungeonsfull shuffles, the following ratios will be used instead: + +5 hints for inconvenient item locations. +8 hints for valuable items. +7 junk hints. + +In the simple, restricted, and restricted legacy shuffles, these are the ratios: + +2 hints for inconvenient entrances. +1 hint for an inconvenient dungeon entrance. +4 hints for random entrances (this can by coincidence pick inconvenient entrances that aren't used for the first set of hints). +3 hints for inconvenient item locations. +5 hints for valuable items. +5 junk hints. + +These hints will use the following format: + +Entrance hints go "[Entrance on overworld] leads to [interior]". + +Inconvenient item locations are a little more custom but amount to "[Location] has [item name]". The item name is literal and will specify which dungeon the dungeon specific items hail from (small key/big key/map/compass). + +The valuable items are of the format "[item name] can be found [location]". The item name is again literal, and the location text is taken from Ganon's silver arrow hints. Note that the way it works is that every unique valuable item that exists is considered independently, and you won't get multiple hints for the EXACT same item (so you can only get one hint for Progressive Sword no matter how many swords exist in the seed, but if swords are not progressive, you could get hints for both Master Sword and Tempered Sword). More copies of an item existing does not increase the probability of getting a hint for that particular item (you are equally likely to get a hint for a Progressive Sword as for the Hammer). Unlike the IR, item names are never obfuscated by "something unique", and there is no special bias for hints for GT Big Key or Pegasus Boots. + +Hint Locations: + +Eastern Palace room before Big Chest +Desert Palace bonk torch room +Tower of Hera entrance room +Tower of Hera Big Chest room +Castle Tower after dark rooms +Palace of Darkness before Bow section +Swamp Palace entryway +Thieves' Town upstairs +Ice Palace entrance +Ice Palace after first drop +Ice Palace tall ice floor room +Misery Mire cutscene room +Turtle Rock entrance +Spectacle Rock cave +Spiky Hint cave +PoD Bdlg NPC +Near PoD Storyteller (bug near bomb wall) +Dark Sanctuary Storyteller (long room with tables) +Near Mire Storyteller (feather duster in winding cave) +SE DW Storyteller (owl in winding cave) + +Inconvenient entrance list: + +Skull Woods Final +Ice Palace +Misery Mire +Turtle Rock +Ganon's Tower +Mimic Ledge +SW DM Foothills Cave (mirror from upper Bumper ledge) +Hammer Pegs (near purple chest) +Super Bomb cracked wall + +Inconvenient location list: + +Swamp left (two chests) +Mire left (two chests) +Hera basement +Eastern Palace Big Key chest (protected by anti-fairies) +Thieves' Town Big Chest +Ice Palace Big Chest +Ganon's Tower Big Chest +Purple Chest +Spike Cave +Magic Bat +Sahasrahla (Green Pendant) + +In the vanilla, dungeonssimple, and dungeonsfull shuffles, the following two locations are added to the inconvenient locations list: + +Graveyard Cave +Mimic Cave + +Valuable Items are simply all items that are shown on the pause subscreen (Y, B, or A sections) minus Silver Arrows and plus Triforce Pieces, Magic Upgrades (1/2 or 1/4), and the Single Arrow. If key shuffle is being used, you can additionally get hints for Small Keys or Big Keys but not hints for Maps or Compasses. + +While the exact verbage of location names and item names can be found in the source code, here's a copy for reference: + +Overworld Entrance naming: + +Turtle Rock: Turtle Rock Main +Misery Mire: Misery Mire +Ice Palace: Ice Palace +Skull Woods Final Section: The back of Skull Woods +Death Mountain Return Cave (West): The SW DM Foothills Cave +Mimic Cave: Mimic Ledge +Dark World Hammer Peg Cave: The rows of pegs +Pyramid Fairy: The crack on the pyramid +Eastern Palace: Eastern Palace +Elder House (East): Elder House +Elder House (West): Elder House +Two Brothers House (East): Eastern Quarreling Brothers' house +Old Man Cave (West): The lower DM entrance +Hyrule Castle Entrance (South): The ground level castle door +Thieves Town: Thieves' Town +Bumper Cave (Bottom): The lower Bumper Cave +Swamp Palace: Swamp Palace +Dark Death Mountain Ledge (West): The East dark DM connector ledge +Dark Death Mountain Ledge (East): The East dark DM connector ledge +Superbunny Cave (Top): The summit of dark DM cave +Superbunny Cave (Bottom): The base of east dark DM +Hookshot Cave: The rock on dark DM +Desert Palace Entrance (South): The book sealed passage +Tower of Hera: The Tower of Hera +Two Brothers House (West): The door near the race game +Old Man Cave (East): The SW-most cave on west DM +Old Man House (Bottom): A cave with a door on west DM +Old Man House (Top): The eastmost cave on west DM +Death Mountain Return Cave (East): The westmost cave on west DM +Spectacle Rock Cave Peak: The highest cave on west DM +Spectacle Rock Cave: The right ledge on west DM +Spectacle Rock Cave (Bottom): The left ledge on west DM +Paradox Cave (Bottom): The right paired cave on east DM +Paradox Cave (Middle): The southmost cave on east DM +Paradox Cave (Top): The east DM summit cave +Fairy Ascension Cave (Bottom): The east DM cave behind rocks +Fairy Ascension Cave (Top): The central ledge on east DM +Spiral Cave: The left ledge on east DM +Spiral Cave (Bottom): The SWmost cave on east DM +Palace of Darkness: Palace of Darkness +Hyrule Castle Entrance (West): The left castle door +Hyrule Castle Entrance (East): The right castle door +Agahnims Tower: The sealed castle door +Desert Palace Entrance (West): The westmost building in the desert +Desert Palace Entrance (North): The northmost cave in the desert +Blinds Hideout: Blind's old house +Lake Hylia Fairy: A cave NE of Lake Hylia +Light Hype Fairy: The cave south of your house +Desert Fairy: The cave near the desert +Chicken House: The chicken lady's house +Aginahs Cave: The open desert cave +Sahasrahlas Hut: The house near armos +Cave Shop (Lake Hylia): The cave NW Lake Hylia +Blacksmiths Hut: The old smithery +Sick Kids House: The central house in Kakariko +Lost Woods Gamble: A tree trunk door +Fortune Teller (Light): A building NE of Kakariko +Snitch Lady (East): A house guarded by a snitch +Snitch Lady (West): A house guarded by a snitch +Bush Covered House: A house with an uncut lawn +Tavern (Front): A building with a backdoor +Light World Bomb Hut: A Kakariko building with no door +Kakariko Shop: The old Kakariko shop +Mini Moldorm Cave: The cave south of Lake Hylia +Long Fairy Cave: The eastmost portal cave +Good Bee Cave: The open cave SE Lake Hylia +20 Rupee Cave: The rock SE Lake Hylia +50 Rupee Cave: The rock near the desert +Ice Rod Cave: The sealed cave SE Lake Hylia +Library: The old library +Potion Shop: The witch's building +Dam: The old dam +Lumberjack House: The lumberjack house +Lake Hylia Fortune Teller: The building NW Lake Hylia +Kakariko Gamble Game: The old Kakariko gambling den +Waterfall of Wishing: Going behind the waterfall +Capacity Upgrade: The cave on the island +Bonk Rock Cave: The rock pile near Sanctuary +Graveyard Cave: The graveyard ledge +Checkerboard Cave: The NE desert ledge +Cave 45: The ledge south of haunted grove +Kings Grave: The northeastmost grave +Bonk Fairy (Light): The rock pile near your home +Hookshot Fairy: A cave on east DM +Bonk Fairy (Dark): The rock pile near the old bomb shop +Dark Sanctuary Hint: The dark sanctuary cave +Dark Lake Hylia Fairy: The cave NE dark Lake Hylia +C-Shaped House: The NE house in Village of Outcasts +Big Bomb Shop: The old bomb shop +Dark Death Mountain Fairy: The SW cave on dark DM +Dark Lake Hylia Shop: The building NW dark Lake Hylia +Dark World Shop: The hammer sealed building +Red Shield Shop: The fenced in building +Mire Shed: The western hut in the mire +East Dark World Hint: The dark cave near the eastmost portal +Dark Desert Hint: The cave east of the mire +Spike Cave: The ledge cave on west dark DM +Palace of Darkness Hint: The building south of Kiki +Dark Lake Hylia Ledge Spike Cave: The rock SE dark Lake Hylia +Cave Shop (Dark Death Mountain): The base of east dark DM +Dark World Potion Shop: The building near the catfish +Archery Game: The old archery game +Dark World Lumberjack Shop: The northmost Dark World building +Hype Cave: The cave south of the old bomb shop +Brewery: The Village of Outcasts building with no door +Dark Lake Hylia Ledge Hint: The open cave SE dark Lake Hylia +Chest Game: The westmost building in the Village of Outcasts +Dark Desert Fairy: The eastern hut in the mire +Dark Lake Hylia Ledge Fairy: The sealed cave SE dark Lake Hylia +Fortune Teller (Dark): The building NE the Village of Outcasts +Sanctuary: Sanctuary +Lumberjack Tree Cave: The cave Behind Lumberjacks +Lost Woods Hideout Stump: The stump in Lost Woods +North Fairy Cave: The cave East of Graveyard +Bat Cave Cave: The cave in eastern Kakariko +Kakariko Well Cave: The cave in northern Kakariko +Hyrule Castle Secret Entrance Stairs: The tunnel near the castle +Skull Woods First Section Door: The southeastmost skull +Skull Woods Second Section Door (East): The central open skull +Skull Woods Second Section Door (West): The westmost open skull +Desert Palace Entrance (East): The eastern building in the desert +Turtle Rock Isolated Ledge Entrance: The isolated ledge on east dark DM +Bumper Cave (Top): The upper Bumper Cave +Hookshot Cave Back Entrance: The stairs on the floating island + +Destination Entrance Naming: + +Hyrule Castle: Hyrule Castle (all three entrances) +Eastern Palace: Eastern Palace +Desert Palace: Desert Palace (all four entrances, including final) +Tower of Hera: Tower of Hera +Palace of Darkness: Palace of Darkness +Swamp Palace: Swamp Palace +Skull Woods: Skull Woods (any entrance including final) +Thieves' Town: Thieves' Town +Ice Palace: Ice Palace +Misery Mire: Misery Mire +Turtle Rock: Turtle Rock (all four entrances) +Ganon's Tower: Ganon's Tower +Castle Tower: Agahnim's Tower +A connector: Paradox Cave, Spectacle Rock Cave, Hookshot Cave, Superbunny Cave, Spiral Cave, Old Man Fetch Cave, Old Man House, Elder House, Quarreling Brothers' House, Bumper Cave, DM Fairy Ascent Cave, DM Exit Cave +A bounty of five items: Mini-moldorm cave, Hype Cave, Blind's Hideout +Sahasrahla: Sahasrahla +A cave with two items: Mire hut, Waterfall Fairy, Pyramid Fairy +A fairy fountain: Any healer fairy cave, either bonk cave with four fairies, the "long fairy" cave +A common shop: Any shop that sells bombs by default +The rare shop: The shop that sells the Red Shield by default +The potion shop: Potion Shop +The bomb shop: Bomb Shop +A fortune teller: Any of the three fortune tellers +A house with a chest: Chicken Lady's house, C-House, Brewery +A cave with an item: Checkerboard cave, Hammer Pegs cave, Cave 45, Graveyard Ledge cave +A cave with a chest: Sanc Bonk Rock Cave, Cape Grave Cave, Ice Rod Cave, Aginah's Cave +The dam: Watergate +The sick kid: Sick Kid +The library: Library +Mimic Cave: Mimic Cave +Spike Cave: Spike Cave +A game of 16 chests: VoO chest game (for the item) +A storyteller: The four DW NPCs who charge 20 rupees for a hint as well as the PoD Bdlg guy who gives a free hint +A cave with some cash: 20 rupee cave, 50 rupee cave (both have thieves and some pots) +A game of chance: Gambling game (just for cash, no items) +A game of skill: Archery minigame +The queen of fairies: Capacity Upgrade Fairy +A drop's exit: Sanctuary, LW Thieves' Hideout, Kakariko Well, Magic Bat, Useless Fairy, Uncle Tunnel, Ganon drop exit +A restock room: The Kakariko bomb/arrow restock room +The tavern: The Kakariko tavern +The grass man: The Kakariko man with many beds +A cold bee: The "wrong side" of Ice Rod cave where you can get a Good Bee +Fairies deep in a cave: Hookshot Fairy + +Location naming reference: + +Mushroom: in the woods +Master Sword Pedestal: at the pedestal +Bottle Merchant: with a merchant +Stumpy: with tree boy +Flute Spot: underground +Digging Game: underground +Lake Hylia Island: on an island +Floating Island: on an island +Bumper Cave Ledge: on a ledge +Spectacle Rock: atop a rock +Maze Race: at the race +Desert Ledge: in the desert +Pyramid: on the pyramid +Catfish: with a catfish +Ether Tablet: at a monument +Bombos Tablet: at a monument +Hobo: with the hobo +Zora's Ledge: near Zora +King Zora: at a high price +Sunken Treasure: underwater +Floodgate Chest: in the dam +Blacksmith: with the smith +Purple Chest: from a box +Old Man: with the old man +Link's Uncle: with your uncle +Secret Passage: near your uncle +Kakariko Well (5 items): in a well +Lost Woods Hideout: near a thief +Lumberjack Tree: in a hole +Magic Bat: with the bat +Paradox Cave (7 items): in a cave with seven chests +Blind's Hideout (5 items): in a basement +Mini Moldorm Cave (5 items): near Moldorms +Hype Cave (4 back chests): near a bat-like man +Hype Cave - Generous Guy: with a bat-like man +Hookshot Cave (4 items): across pits +Sahasrahla's Hut (chests in back): near the elder +Sahasrahla: with the elder +Waterfall Fairy (2 items): near a fairy +Pyramid Fairy (2 items): near a fairy +Mire Shed (2 items): near sparks +Superbunny Cave (2 items): in a connection +Spiral Cave: in spiral cave +Kakariko Tavern: in the bar +Link's House: in your home +Sick Kid: with the sick +Library: near books +Potion Shop: near potions +Spike Cave: beyond spikes +Mimic Cave: in a cave of mimicry +Chest Game: as a prize +Chicken House: near poultry +Aginah's Cave: with Aginah +Ice Rod Cave: in a frozen cave +Brewery: alone in a home +C-Shaped House: alone in a home +Spectacle Rock Cave: alone in a cave +King's Tomb: alone in a cave +Cave 45: alone in a cave +Graveyard Cave: alone in a cave +Checkerboard Cave: alone in a cave +Bonk Rock Cave: alone in a cave +Peg Cave: alone in a cave +Sanctuary: in Sanctuary +Hyrule Castle - Boomerang Chest: in Hyrule Castle +Hyrule Castle - Map Chest: in Hyrule Castle +Hyrule Castle - Zelda's Chest: in Hyrule Castle +Sewers - Dark Cross: in the sewers +Sewers - Secret Room (3 items): in the sewers +Eastern Palace - Boss: with the Armos +Eastern Palace (otherwise, 5 items): in Eastern Palace +Desert Palace - Boss: with Lanmolas +Desert Palace (otherwise, 5 items): in Desert Palace +Tower of Hera - Boss: with Moldorm +Tower of Hera (otherwise, 5 items): in Tower of Hera +Castle Tower (2 items): in Castle Tower +Palace of Darkness - Boss: with Helmasaur King +Palace of Darkness (otherwise, 13 items): in Palace of Darkness +Swamp Palace - Boss: with Arrghus +Swamp Palace (otherwise, 9 items): in Swamp Palace +Skull Woods - Bridge Room: near Mothula +Skull Woods - Boss: with Mothula +Skull Woods (otherwise, 6 items): in Skull Woods +Thieves' Town - Boss: with Blind +Thieves' Town (otherwise, 7 items): in Thieves' Town +Ice Palace - Boss: with Kholdstare +Ice Palace (otherwise, 7 items): in Ice Palace +Misery Mire - Boss: with Vitreous +Misery Mire (otherwise, 7 items): in Misery Mire +Turtle Rock - Boss: with Trinexx +Turtle Rock (otherwise, 11 items): in Turtle Rock +Ganons Tower (after climb, 4 items): atop Ganon's Tower +Ganon's Tower (otherwise, 23 items): in Ganon's Tower \ No newline at end of file From d22ccdedb36abd786ef9f56070fa4560349f9621 Mon Sep 17 00:00:00 2001 From: qadan Date: Thu, 6 Feb 2020 12:20:50 -0400 Subject: [PATCH 14/52] some changes --- BaseClasses.py | 3 +-- EntranceRandomizer.py | 3 +-- Main.py | 4 ++-- Mystery.py | 1 - Rom.py | 8 ++----- Rules.py | 54 ++++++++++++++++++++----------------------- 6 files changed, 31 insertions(+), 42 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index a8fac2a2..01752a0b 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -9,7 +9,7 @@ from Utils import int16_as_bytes class World(object): - def __init__(self, players, shuffle, logic, mode, swords, difficulty, difficulty_adjustments, timer, progressive, goal, algorithm, accessibility, shuffle_ganon, retro, custom, customitemarray, hints, text): + def __init__(self, players, shuffle, logic, mode, swords, difficulty, difficulty_adjustments, timer, progressive, goal, algorithm, accessibility, shuffle_ganon, retro, custom, customitemarray, hints): self.players = players self.teams = 1 self.shuffle = shuffle.copy() @@ -54,7 +54,6 @@ class World(object): self.dynamic_locations = [] self.spoiler = Spoiler(self) self.lamps_needed_for_dark_rooms = 1 - self.text = text for player in range(1, players + 1): def set_player_attr(attr, val): diff --git a/EntranceRandomizer.py b/EntranceRandomizer.py index 696b277b..48630a28 100755 --- a/EntranceRandomizer.py +++ b/EntranceRandomizer.py @@ -276,7 +276,6 @@ def parse_arguments(argv, no_defaults=False): parser.add_argument('--outputpath') parser.add_argument('--race', default=defval(False), action='store_true') parser.add_argument('--outputname') - parser.add_argument('--text', default=defval('text'), choices=['text', 'fantatext']) if multiargs.multi: for player in range(1, multiargs.multi + 1): @@ -297,7 +296,7 @@ def parse_arguments(argv, no_defaults=False): 'retro', 'accessibility', 'hints', 'beemizer', 'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots', 'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor', 'heartbeep', - 'remote_items', 'text']: + 'remote_items']: value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name) if player == 1: setattr(ret, name, {1: value}) diff --git a/Main.py b/Main.py index 69bc6089..62dc62a2 100644 --- a/Main.py +++ b/Main.py @@ -30,7 +30,7 @@ def main(args, seed=None): start = time.process_time() # initialize the world - world = World(args.multi, args.shuffle, args.logic, args.mode, args.swords, args.difficulty, args.item_functionality, args.timer, args.progressive, args.goal, args.algorithm, args.accessibility, args.shuffleganon, args.retro, args.custom, args.customitemarray, args.hints, args.text) + world = World(args.multi, args.shuffle, args.logic, args.mode, args.swords, args.difficulty, args.item_functionality, args.timer, args.progressive, args.goal, args.algorithm, args.accessibility, args.shuffleganon, args.retro, args.custom, args.customitemarray, args.hints) logger = logging.getLogger('') if seed is None: random.seed(None) @@ -230,7 +230,7 @@ def main(args, seed=None): def copy_world(world): # ToDo: Not good yet - ret = World(world.players, world.shuffle, world.logic, world.mode, world.swords, world.difficulty, world.difficulty_adjustments, world.timer, world.progressive, world.goal, world.algorithm, world.accessibility, world.shuffle_ganon, world.retro, world.custom, world.customitemarray, world.hints, world.text) + ret = World(world.players, world.shuffle, world.logic, world.mode, world.swords, world.difficulty, world.difficulty_adjustments, world.timer, world.progressive, world.goal, world.algorithm, world.accessibility, world.shuffle_ganon, world.retro, world.custom, world.customitemarray, world.hints) ret.teams = world.teams ret.player_names = copy.deepcopy(world.player_names) ret.remote_items = world.remote_items.copy() diff --git a/Mystery.py b/Mystery.py index 25826a99..ff4410a8 100644 --- a/Mystery.py +++ b/Mystery.py @@ -211,7 +211,6 @@ def roll_settings(weights): ret.heartbeep = get_choice('heartbeep', romweights) ret.ow_palettes = get_choice('ow_palettes', romweights) ret.uw_palettes = get_choice('uw_palettes', romweights) - ret.text = get_choice('text', romweights) return ret diff --git a/Rom.py b/Rom.py index 7ac5bcde..b5817f24 100644 --- a/Rom.py +++ b/Rom.py @@ -14,6 +14,8 @@ from Dungeons import dungeon_music_addresses from Regions import location_table from Text import MultiByteTextMapper, CompressedTextMapper, text_addresses, Credits +from Text import TextTable, Uncle_texts, Ganon1_texts, TavernMan_texts, Sahasrahla2_texts, Triforce_texts, Blind_texts, BombShop2_texts, junk_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 output_path, local_path, int16_as_bytes, int32_as_bytes, snes_to_pc from Items import ItemFactory from EntranceShuffle import door_addresses @@ -1534,12 +1536,6 @@ def write_string_to_rom(rom, target, string): def write_strings(rom, world, player, team): - if world.text[player] == 'text': - from Text import TextTable, Uncle_texts, Ganon1_texts, TavernMan_texts, Sahasrahla2_texts, Triforce_texts, Blind_texts, BombShop2_texts, junk_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 - elif world.text[player] == 'fantatext': - from FantaText import TextTable, Uncle_texts, Ganon1_texts, TavernMan_texts, Sahasrahla2_texts, Triforce_texts, Blind_texts, BombShop2_texts, junk_texts - from FantaText 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 tt = TextTable() tt.removeUnwantedText() diff --git a/Rules.py b/Rules.py index fd6735f1..431237a8 100644 --- a/Rules.py +++ b/Rules.py @@ -793,6 +793,15 @@ def overworld_glitches_rules(world, player): 'Dark Blacksmith Ruins', 'Bumper Cave Ledge', ] + dw_bunny_accessible_locations = [ + 'Thieves Town', + 'Graveyard Ledge Mirror Spot', + 'Kings Grave Mirror Spot', + 'Bumper Cave Entrance Rock', + 'Brewery', + 'Village of Outcasts Pegs', + 'Village of Outcasts Eastern Rocks', + ] # set up boots-accessible regions if world.mode[player] != 'inverted': lw_boots_accessible_entrances.append('Cave 45') @@ -807,22 +816,25 @@ def overworld_glitches_rules(world, player): add_rule(world.get_entrance('Turtle Rock Teleporter', player), lambda state: state.has_Boots(player) and state.has('Hammer', player), 'or') add_rule(world.get_entrance('Checkerboard Cave', player), lambda state: state.has_Boots(player) and state.can_lift_rocks(player), 'or') + # ton of boots-accessible locations. needs_boots = lambda state: state.has_Boots(player) needs_boots_and_pearl = lambda state: state.has_Boots(player) and state.has_Pearl(player) for entrance in lw_boots_accessible_entrances: add_rule(world.get_entrance(entrance, player), needs_boots_and_pearl if world.mode[player] == 'inverted' else needs_boots, 'or') for location in lw_boots_accessible_locations: add_rule(world.get_location(location, player), needs_boots_and_pearl if world.mode[player] == 'inverted' else needs_boots, 'or') - # no inverted rules here; no DMD bunny known so far for entrance in dw_boots_accessible_entrances: - add_rule(world.get_entrance(entrance, player), needs_boots_and_pearl, 'or') + add_rule(world.get_entrance(entrance, player), needs_boots_and_pearl if world.mode[player] != 'inverted' else needs_boots, 'or') for location in dw_boots_accessible_locations: - add_rule(world.get_location(location, player), needs_boots_and_pearl, 'or') + add_rule(world.get_location(location, player), needs_boots_and_pearl if world.mode[player] != 'inverted' else needs_boots, 'or') + # bunny DMD rules if world.mode[player] != 'inverted': # set up some mirror-accessible dw entrances. boots_and_mirror = lambda state: state.has_Boots(player) and state.has_Mirror(player) - add_rule(world.get_entrance('Dark Sanctuary Hint', player), boots_and_mirror, 'or') # should suffice to give us west dark world access + for spot in world.get_region('West Dark World', player).locations: + if spot not in dw_bunny_accessible_locations: + add_rule(world.get_location(spot, player), boots_and_mirror, 'or') for spot in world.get_region('Dark Death Mountain (East Bottom)', player).locations: add_rule(world.get_location(spot, player), boots_and_mirror, 'or') # dw entrances accessible with mirror and hookshot @@ -839,31 +851,13 @@ def overworld_glitches_rules(world, player): add_rule(world.get_entrance('Mire Shed', player), boots_mirror_titans, 'or') add_rule(world.get_location('Frog', player), boots_mirror_titans, 'or') - # all entrances you can't mirror bunny into. @todo: use for inverted - invalid_mirror_bunny_entrances_lw = [ - 'Bonk Rock Cave', - 'Bonk Fairy (Light)', - 'Blinds Hideout', - '50 Rupee Cave', - '20 Rupee Cave', - 'Checkerboard Cave', - 'Light Hype Fairy', - 'Waterfall of Wishing', - 'Light World Bomb Hut', - 'Mini Moldorm Cave', - 'Ice Rod Cave', - 'Hyrule Castle Secret Entrance Stairs', - 'Sanctuary Grave', - 'Kings Grave', - 'Tower of Hera', - ] - # also, you can do mini moldorm cave and spiral cave - but you need a sword - superbunny_mirror_sword = lambda state: state.has_Boots(player) and state.has_Mirror(player) and state.has_sword(player) + # also, you can do mini moldorm cave and spiral cave - but we're going to consider it required to have a weapon that doesn't require magic and is guaranteed to kill. + superbunny_mirror_weapon = lambda state: state.has_Boots(player) and state.has_Mirror(player) and (state.has_sword(player) or state.has('Hammer', player)) mini_moldorm_cave = world.get_region('Mini Moldorm Cave', player) if check_is_dark_world(mini_moldorm_cave): for spot in mini_moldorm_cave.locations: - add_rule(world.get_location(spot, player), superbunny_mirror_sword, 'or') - add_rule(world.get_location('Spiral Cave', player), superbunny_mirror_sword, 'or') + add_rule(world.get_location(spot, player), superbunny_mirror_weapon, 'or') + add_rule(world.get_location('Spiral Cave', player), superbunny_mirror_weapon, 'or') add_conditional_lamps(world, player) @@ -1487,8 +1481,8 @@ def set_inverted_bunny_rules(world, player): # Note spiral cave may be technically passible, but it would be too absurd to require since OHKO mode is a thing. bunny_impassable_caves = ['Bumper Cave', 'Two Brothers House', 'Hookshot Cave', 'Skull Woods First Section (Right)', 'Skull Woods First Section (Left)', 'Skull Woods First Section (Top)', 'Turtle Rock (Entrance)', 'Turtle Rock (Second Section)', 'Turtle Rock (Big Chest)', 'Skull Woods Second Section (Drop)', 'Turtle Rock (Eye Bridge)', 'Sewers', 'Pyramid', 'Spiral Cave (Top)', 'Desert Palace Main (Inner)', 'Fairy Ascension Cave (Drop)', 'The Sky'] - bunny_accessible_locations = ['Link\'s Uncle', 'Sahasrahla', 'Sick Kid', 'Lost Woods Hideout', 'Lumberjack Tree', 'Checkerboard Cave', 'Potion Shop', 'Spectacle Rock Cave', 'Pyramid', 'Hype Cave - Generous Guy', 'Peg Cave', 'Bumper Cave Ledge', 'Dark Blacksmith Ruins', 'Bombos Tablet', 'Ether Tablet', 'Purple Chest'] + invalid_mirror_bunny_entrances_lw = ['Bonk Rock Cave', 'Bonk Fairy (Light)', 'Blinds Hideout', '50 Rupee Cave', '20 Rupee Cave', 'Checkerboard Cave', 'Light Hype Fairy', 'Waterfall of Wishing', 'Light World Bomb Hut', 'Mini Moldorm Cave', 'Ice Rod Cave', 'Hyrule Castle Secret Entrance Stairs', 'Sanctuary Grave', 'Kings Grave', 'Tower of Hera'] def path_to_access_rule(path, entrance): return lambda state: state.can_reach(entrance) and all(rule(state) for rule in path) @@ -1496,8 +1490,10 @@ def set_inverted_bunny_rules(world, player): def options_to_access_rule(options): return lambda state: any(rule(state) for rule in options) - def get_rule_to_add(region): + def get_rule_to_add(region, location = None): if not region.is_dark_world: + if world.logic[player] == 'owglitches' and location in bunny_accessible_locations and region.name not in invalid_mirror_bunny_entrances_lw: + return lambda state: (state.can_reach(region) and state.has_Mirror(player)) or state.has_Pearl(player) return lambda state: state.has_Pearl(player) # in this case we are mixed region. # we collect possible options. @@ -1549,6 +1545,6 @@ def set_inverted_bunny_rules(world, player): if location.name in bunny_accessible_locations: continue - add_rule(location, get_rule_to_add(location.parent_region)) + add_rule(location, get_rule_to_add(location.parent_region, location.name)) From 9521a0dbc9136479fbab0c1a6e850c2e56039e7f Mon Sep 17 00:00:00 2001 From: qadan Date: Thu, 6 Feb 2020 14:46:15 -0400 Subject: [PATCH 15/52] cleaned up bunny dw, bunny revival --- Rules.py | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/Rules.py b/Rules.py index 431237a8..83db00aa 100644 --- a/Rules.py +++ b/Rules.py @@ -765,7 +765,6 @@ def overworld_glitches_rules(world, player): 'Grassy Lawn Pegs', 'West Dark World Gap', 'Bumper Cave Ledge Drop', - 'Dark Desert Teleporter', 'Turtle Rock Drop', 'Floating Island Drop', 'Dark Death Mountain Drop (East)', @@ -786,6 +785,10 @@ def overworld_glitches_rules(world, player): 'Dark Sanctuary Hint', 'Fortune Teller (Dark)', 'Dark World Lumberjack Shop', + 'Misery Mire', + 'Mire Shed', + 'Dark Desert Hint', + 'Dark Desert Fairy', ] dw_boots_accessible_locations = [ 'Catfish', @@ -1401,7 +1404,7 @@ def set_inverted_big_bomb_rules(world, player): def set_bunny_rules(world, player): - + dungeon_exits = ['Desert Palace Exit (South)', 'Desert Palace Exit (West)', 'Desert Palace Exit (East)', 'Desert Palace Exit (North)', 'Eastern Palace Exit', 'Tower of Hera Exit', 'Thieves Town Exit', 'Skull Woods Final Section Exit', 'Ice Palace Exit', 'Misery Mire Exit', 'Palace of Darkness Exit', 'Swamp Palace Exit', 'Agahnims Tower Exit', 'Turtle Rock Ledge Exit (East)', 'Turtle Rock Exit (Front)', 'Turtle Rock Ledge Exit (West)', 'Turtle Rock Isolated Ledge Exit'] # regions for the exits of multi-entrace caves/drops that bunny cannot pass # Note spiral cave may be technically passible, but it would be too absurd to require since OHKO mode is a thing. bunny_impassable_caves = ['Bumper Cave', 'Two Brothers House', 'Hookshot Cave', 'Skull Woods First Section (Right)', 'Skull Woods First Section (Left)', 'Skull Woods First Section (Top)', 'Turtle Rock (Entrance)', 'Turtle Rock (Second Section)', 'Turtle Rock (Big Chest)', 'Skull Woods Second Section (Drop)', @@ -1445,7 +1448,14 @@ def set_bunny_rules(world, player): new_path = path + [entrance.access_rule] seen.add(new_region) if not new_region.is_light_world: - continue # we don't care about pure dark world entrances in non-owg + if world.logic[player] == 'owglitches': + if entrance in superbunny_accessible_locations and region.name not in invalid_mirror_bunny_entrances_dw: + possible_options.append(path_to_access_rule(new_path, entrance)) + for exit in new_region.exits: + if exit.name in dungeon_exits: + possible_options.append(path_to_access_rule(new_path, entrance)) + else: + continue if new_region.is_dark_world: queue.append((new_region, new_path)) else: @@ -1466,7 +1476,7 @@ def set_bunny_rules(world, player): if paradox_shop.is_dark_world: add_rule(paradox_shop.entrances[0], get_rule_to_add(paradox_shop)) - # Add requirements for all locations that are actually in the dark world, except those available to the bunny + # Add requirements for all locations that are actually in the dark world, except those available to the bunny, including dungeon revival for location in world.get_locations(): if location.player == player and location.parent_region.is_dark_world: @@ -1476,7 +1486,7 @@ def set_bunny_rules(world, player): add_rule(location, get_rule_to_add(location.parent_region, location.name)) def set_inverted_bunny_rules(world, player): - + dungeon_exits = ['Desert Palace Exit (South)', 'Desert Palace Exit (West)', 'Desert Palace Exit (East)', 'Desert Palace Exit (North)', 'Eastern Palace Exit', 'Tower of Hera Exit', 'Thieves Town Exit', 'Skull Woods Final Section Exit', 'Ice Palace Exit', 'Misery Mire Exit', 'Palace of Darkness Exit', 'Swamp Palace Exit', 'Inverted Agahnims Tower Exit', 'Turtle Rock Ledge Exit (East)', 'Turtle Rock Exit (Front)', 'Turtle Rock Ledge Exit (West)', 'Turtle Rock Isolated Ledge Exit'] # regions for the exits of multi-entrace caves/drops that bunny cannot pass # Note spiral cave may be technically passible, but it would be too absurd to require since OHKO mode is a thing. bunny_impassable_caves = ['Bumper Cave', 'Two Brothers House', 'Hookshot Cave', 'Skull Woods First Section (Right)', 'Skull Woods First Section (Left)', 'Skull Woods First Section (Top)', 'Turtle Rock (Entrance)', 'Turtle Rock (Second Section)', 'Turtle Rock (Big Chest)', 'Skull Woods Second Section (Drop)', @@ -1517,7 +1527,14 @@ def set_inverted_bunny_rules(world, player): new_path = path + [entrance.access_rule] seen.add(new_region) if not new_region.is_dark_world: - continue # we don't care about pure light world entrances + if world.logic[player] == 'owglitches': + if entrance in superbunny_accessible_locations and region.name not in invalid_mirror_bunny_entrances_lw: + possible_options.append(path_to_access_rule(new_path, entrance)) + for exit in new_region.exits: + if exit.name in dungeon_exits: + possible_options.append(path_to_access_rule(new_path, entrance)) + else: + continue if new_region.is_light_world: queue.append((new_region, new_path)) else: @@ -1538,7 +1555,7 @@ def set_inverted_bunny_rules(world, player): if paradox_shop.is_light_world: add_rule(paradox_shop.entrances[0], get_rule_to_add(paradox_shop)) - # Add requirements for all locations that are actually in the light world, except those available to the bunny + # Add requirements for all locations that are actually in the light world, except those available to the bunny, including dungeon revival for location in world.get_locations(): if location.player == player and location.parent_region.is_light_world: From 96c07eccc20a793154098f53dcbc85c4a6a983fe Mon Sep 17 00:00:00 2001 From: qadan Date: Thu, 6 Feb 2020 17:17:13 -0400 Subject: [PATCH 16/52] expanding some rules --- Rules.py | 55 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/Rules.py b/Rules.py index 83db00aa..2d476e36 100644 --- a/Rules.py +++ b/Rules.py @@ -39,6 +39,7 @@ def set_rules(world, player): if world.logic[player] == 'noglitches': no_glitches_rules(world, player) elif world.logic[player] == 'owglitches': + logging.getLogger('').info('There is a chance OWG has bugged edge case rulesets, especially in inverted. Definitely file a report on GitHub if you see anything strange.') overworld_glitches_rules(world, player) elif world.logic[player] == 'minorglitches': logging.getLogger('').info('Minor Glitches may be buggy still. No guarantee for proper logic checks.') @@ -735,6 +736,7 @@ def overworld_glitches_rules(world, player): 'Spectacle Rock Cave', 'Spectacle Rock Cave Peak', 'Spectacle Rock Cave (Bottom)', + 'Spectacle Rock Mirror Spot', 'Broken Bridge (West)', 'Broken Bridge (East)', 'East Death Mountain Drop', @@ -752,6 +754,16 @@ def overworld_glitches_rules(world, player): 'Paradox Cave (Top)', 'Spiral Cave Ledge Access', 'Fairy Ascension Ledge', + 'Cave 45 Mirror Spot', + 'Graveyard Ledge Mirror Spot', + 'Bumper Cave Ledge Mirror Spot', + 'Desert Ledge (Northeast) Mirror Spot', + 'Desert Ledge Mirror Spot', + 'Desert Palace Entrance (North) Mirror Spot', + 'East Death Mountain (Top) Mirror Spot', + 'Spiral Cave Mirror Spot', + 'Fairy Ascension Mirror Spot', + 'Floating Island Mirror Spot', ] lw_boots_accessible_locations = [ 'Lake Hylia Island', @@ -778,7 +790,6 @@ def overworld_glitches_rules(world, player): 'C-Shaped House', 'Chest Game', 'Thieves Town', - 'Graveyard Ledge Mirror Spot', 'Kings Grave Mirror Spot', 'Bumper Cave Entrance Rock', 'Red Shield Shop', @@ -796,7 +807,7 @@ def overworld_glitches_rules(world, player): 'Dark Blacksmith Ruins', 'Bumper Cave Ledge', ] - dw_bunny_accessible_locations = [ + dw_bunny_inaccessible_locations = [ 'Thieves Town', 'Graveyard Ledge Mirror Spot', 'Kings Grave Mirror Spot', @@ -804,6 +815,11 @@ def overworld_glitches_rules(world, player): 'Brewery', 'Village of Outcasts Pegs', 'Village of Outcasts Eastern Rocks', + 'Dark Lake Hylia Drop (South)', + 'Hype Cave', + 'Village of Outcasts Heavy Rock', + 'East Dark World Bridge', + 'Bonk Fairy (Dark)', ] # set up boots-accessible regions if world.mode[player] != 'inverted': @@ -831,13 +847,13 @@ def overworld_glitches_rules(world, player): for location in dw_boots_accessible_locations: add_rule(world.get_location(location, player), needs_boots_and_pearl if world.mode[player] != 'inverted' else needs_boots, 'or') - # bunny DMD rules + # bunny DMD rules. @todo: calculate and implement for inverted. if world.mode[player] != 'inverted': # set up some mirror-accessible dw entrances. boots_and_mirror = lambda state: state.has_Boots(player) and state.has_Mirror(player) - for spot in world.get_region('West Dark World', player).locations: - if spot not in dw_bunny_accessible_locations: - add_rule(world.get_location(spot, player), boots_and_mirror, 'or') + for spot in world.get_region('West Dark World', player).exits + world.get_region('South Dark World', player).exits: + if spot.name not in dw_bunny_inaccessible_locations: + add_rule(world.get_entrance(spot, player), boots_and_mirror, 'or') for spot in world.get_region('Dark Death Mountain (East Bottom)', player).locations: add_rule(world.get_location(spot, player), boots_and_mirror, 'or') # dw entrances accessible with mirror and hookshot @@ -854,13 +870,16 @@ def overworld_glitches_rules(world, player): add_rule(world.get_entrance('Mire Shed', player), boots_mirror_titans, 'or') add_rule(world.get_location('Frog', player), boots_mirror_titans, 'or') - # also, you can do mini moldorm cave and spiral cave - but we're going to consider it required to have a weapon that doesn't require magic and is guaranteed to kill. - superbunny_mirror_weapon = lambda state: state.has_Boots(player) and state.has_Mirror(player) and (state.has_sword(player) or state.has('Hammer', player)) + # also, you can do mini moldorm cave and spiral cave - but requiring a sword. + superbunny_mirror_weapon = lambda state: state.has_Mirror(player) and state.has_sword(player) mini_moldorm_cave = world.get_region('Mini Moldorm Cave', player) if check_is_dark_world(mini_moldorm_cave): for spot in mini_moldorm_cave.locations: add_rule(world.get_location(spot, player), superbunny_mirror_weapon, 'or') - add_rule(world.get_location('Spiral Cave', player), superbunny_mirror_weapon, 'or') + if check_is_dark_world(world.get_region('Spiral Cave (Top)', player)): + add_rule(world.get_location('Spiral Cave', player), superbunny_mirror_weapon, 'or') + + # add darkness condition. add_conditional_lamps(world, player) @@ -1404,6 +1423,7 @@ def set_inverted_big_bomb_rules(world, player): def set_bunny_rules(world, player): + # If you can get to a dungeon exit, you can bunny revive. dungeon_exits = ['Desert Palace Exit (South)', 'Desert Palace Exit (West)', 'Desert Palace Exit (East)', 'Desert Palace Exit (North)', 'Eastern Palace Exit', 'Tower of Hera Exit', 'Thieves Town Exit', 'Skull Woods Final Section Exit', 'Ice Palace Exit', 'Misery Mire Exit', 'Palace of Darkness Exit', 'Swamp Palace Exit', 'Agahnims Tower Exit', 'Turtle Rock Ledge Exit (East)', 'Turtle Rock Exit (Front)', 'Turtle Rock Ledge Exit (West)', 'Turtle Rock Isolated Ledge Exit'] # regions for the exits of multi-entrace caves/drops that bunny cannot pass # Note spiral cave may be technically passible, but it would be too absurd to require since OHKO mode is a thing. @@ -1422,15 +1442,17 @@ def set_bunny_rules(world, player): return lambda state: any(rule(state) for rule in options) def get_rule_to_add(region, location = None): + possible_options = [] if not region.is_light_world: if world.logic[player] == 'owglitches' and location in superbunny_accessible_locations and region.name not in invalid_mirror_bunny_entrances_dw: - return lambda state: (state.can_reach(region) and state.has_Mirror(player)) or state.has_Pearl(player) - return lambda state: state.has_Pearl(player) + possible_options.append(lambda state: state.has_Boots(player) and state.has_Mirror(player)) + else: + return lambda state: state.has_Pearl(player) # in this case we are mixed region. # we collect possible options. # The base option is having the moon pearl - possible_options = [lambda state: state.has_Pearl(player)] + possible_options.append(lambda state: state.has_Pearl(player)) # We will search entrances recursively until we find # one that leads to an exclusively light world region @@ -1486,6 +1508,7 @@ def set_bunny_rules(world, player): add_rule(location, get_rule_to_add(location.parent_region, location.name)) def set_inverted_bunny_rules(world, player): + # If you can get to a dungeon exit, you can bunny revive. dungeon_exits = ['Desert Palace Exit (South)', 'Desert Palace Exit (West)', 'Desert Palace Exit (East)', 'Desert Palace Exit (North)', 'Eastern Palace Exit', 'Tower of Hera Exit', 'Thieves Town Exit', 'Skull Woods Final Section Exit', 'Ice Palace Exit', 'Misery Mire Exit', 'Palace of Darkness Exit', 'Swamp Palace Exit', 'Inverted Agahnims Tower Exit', 'Turtle Rock Ledge Exit (East)', 'Turtle Rock Exit (Front)', 'Turtle Rock Ledge Exit (West)', 'Turtle Rock Isolated Ledge Exit'] # regions for the exits of multi-entrace caves/drops that bunny cannot pass # Note spiral cave may be technically passible, but it would be too absurd to require since OHKO mode is a thing. @@ -1501,15 +1524,17 @@ def set_inverted_bunny_rules(world, player): return lambda state: any(rule(state) for rule in options) def get_rule_to_add(region, location = None): + possible_options = [] if not region.is_dark_world: if world.logic[player] == 'owglitches' and location in bunny_accessible_locations and region.name not in invalid_mirror_bunny_entrances_lw: - return lambda state: (state.can_reach(region) and state.has_Mirror(player)) or state.has_Pearl(player) - return lambda state: state.has_Pearl(player) + possible_options.append(lambda state: state.has_Boots(player) and state.has_Mirror(player)) + else: + return lambda state: state.has_Pearl(player) # in this case we are mixed region. # we collect possible options. # The base option is having the moon pearl - possible_options = [lambda state: state.has_Pearl(player)] + possible_options.append(lambda state: state.has_Pearl(player)) # We will search entrances recursively until we find # one that leads to an exclusively dark world region From fd4f91144b0259b73665ae1babae64502f564fda Mon Sep 17 00:00:00 2001 From: qadan Date: Fri, 7 Feb 2020 13:13:13 -0400 Subject: [PATCH 17/52] probably still missing things --- Rules.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Rules.py b/Rules.py index 2d476e36..96cccf90 100644 --- a/Rules.py +++ b/Rules.py @@ -803,7 +803,6 @@ def overworld_glitches_rules(world, player): ] dw_boots_accessible_locations = [ 'Catfish', - 'Frog', 'Dark Blacksmith Ruins', 'Bumper Cave Ledge', ] @@ -834,6 +833,9 @@ def overworld_glitches_rules(world, player): add_rule(world.get_entrance('East Death Mountain Teleporter', player), lambda state: state.can_lift_heavy_rocks(player) and state.has_Boots(player), 'or') add_rule(world.get_entrance('Turtle Rock Teleporter', player), lambda state: state.has_Boots(player) and state.has('Hammer', player), 'or') add_rule(world.get_entrance('Checkerboard Cave', player), lambda state: state.has_Boots(player) and state.can_lift_rocks(player), 'or') + add_rule(world.get_entrance('South Hyrule Teleporter', player), lambda state: state.has_Boots(player) and state.can_lift_rocks(player), 'or') + else: + add_rule(world.get_entrance('South Dark World Teleporter', player), lambda state: state.has_Boots(player) and state.can_lift_rocks(player), 'or') # ton of boots-accessible locations. needs_boots = lambda state: state.has_Boots(player) @@ -847,6 +849,16 @@ def overworld_glitches_rules(world, player): for location in dw_boots_accessible_locations: add_rule(world.get_location(location, player), needs_boots_and_pearl if world.mode[player] != 'inverted' else needs_boots, 'or') + # standard dmd rules + wdw = world.get_region('West Dark World', player) + wdw.can_reach_private = lambda state: wdw.can_reach(state) or (needs_boots_and_pearl if world.mode[player] != 'inverted' else needs_boots) + sdw = world.get_region('South Dark World', player) + sdw.can_reach_private = lambda state: sdw.can_reach(state) or (needs_boots_and_pearl if world.mode[player] != 'inverted' else needs_boots) + dd = world.get_region('Dark Desert', player) + dd.can_reach_private = lambda state: dd.can_reach(state) or (needs_boots_and_pearl if world.mode[player] != 'inverted' else needs_boots) + edw = world.get_region('East Dark World', player) + edw.can_reach_private = lambda state: edw.can_reach(state) or (needs_boots_and_pearl if world.mode[player] != 'inverted' else needs_boots) + # bunny DMD rules. @todo: calculate and implement for inverted. if world.mode[player] != 'inverted': # set up some mirror-accessible dw entrances. From bcb509937aa8cc3249ae2eb5833c6291593c7692 Mon Sep 17 00:00:00 2001 From: qadan Date: Fri, 7 Feb 2020 15:15:30 -0400 Subject: [PATCH 18/52] more dmd stuff --- Rules.py | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/Rules.py b/Rules.py index 96cccf90..876da683 100644 --- a/Rules.py +++ b/Rules.py @@ -849,18 +849,21 @@ def overworld_glitches_rules(world, player): for location in dw_boots_accessible_locations: add_rule(world.get_location(location, player), needs_boots_and_pearl if world.mode[player] != 'inverted' else needs_boots, 'or') - # standard dmd rules - wdw = world.get_region('West Dark World', player) - wdw.can_reach_private = lambda state: wdw.can_reach(state) or (needs_boots_and_pearl if world.mode[player] != 'inverted' else needs_boots) - sdw = world.get_region('South Dark World', player) - sdw.can_reach_private = lambda state: sdw.can_reach(state) or (needs_boots_and_pearl if world.mode[player] != 'inverted' else needs_boots) - dd = world.get_region('Dark Desert', player) - dd.can_reach_private = lambda state: dd.can_reach(state) or (needs_boots_and_pearl if world.mode[player] != 'inverted' else needs_boots) - edw = world.get_region('East Dark World', player) - edw.can_reach_private = lambda state: edw.can_reach(state) or (needs_boots_and_pearl if world.mode[player] != 'inverted' else needs_boots) - - # bunny DMD rules. @todo: calculate and implement for inverted. + # standard dmd rules, also feat. bunny if world.mode[player] != 'inverted': + can_bunny_dmd = lambda state: world.get_region('Death Mountain').can_reach(state, player) and state.has_Mirror(player) + wdw = world.get_region('West Dark World', player) + wdw.can_reach_private = lambda state: wdw.can_reach(state) or (needs_boots_and_pearl or can_bunny_dmd) + sdw = world.get_region('South Dark World', player) + sdw.can_reach_private = lambda state: sdw.can_reach(state) or (needs_boots_and_pearl or can_bunny_dmd) + dd = world.get_region('Dark Desert', player) + dd.can_reach_private = lambda state: dd.can_reach(state) or needs_boots_and_pearl + nedw = world.get_region('Northeast Dark World', player) + nedw.can_reach_private = lambda state: nedw.can_reach(state) or (needs_boots_and_pearl or can_bunny_dmd) + edw = world.get_region('East Dark World', player) + edw.can_reach_private = lambda state: edw.can_reach(state) or needs_boots_and_pearl + edmb = world.get_region('Dark Death Mountain (East Bottom)', player) + edmb.can_reach_private = lambda state: edmb.can_reach(state) or can_bunny_dmd # set up some mirror-accessible dw entrances. boots_and_mirror = lambda state: state.has_Boots(player) and state.has_Mirror(player) for spot in world.get_region('West Dark World', player).exits + world.get_region('South Dark World', player).exits: @@ -880,6 +883,8 @@ def overworld_glitches_rules(world, player): # dw entrances accessible with mirror and titans boots_mirror_titans = lambda state: state.has_Boots(player) and state.has_Mirror(player) and state.can_lift_heavy_rocks(player) add_rule(world.get_entrance('Mire Shed', player), boots_mirror_titans, 'or') + # plus the mirror superbunny version + add_rule(world.get_entrance('Mire Shed', player), lambda state: state.has('Ocarina', player) and state.has_Mirror(player) and state.can_lift_heavy_rocks(player), 'or') add_rule(world.get_location('Frog', player), boots_mirror_titans, 'or') # also, you can do mini moldorm cave and spiral cave - but requiring a sword. From c20fe90c0f2abc7e3b13cd1fc77bc9c369fea6cc Mon Sep 17 00:00:00 2001 From: qadan Date: Sat, 8 Feb 2020 12:29:55 -0400 Subject: [PATCH 19/52] maybe broken stuff oh boy --- EntranceShuffle.py | 1 + OWGSets.py | 195 +++++++++++++++++++++++++++++++++++++ Regions.py | 5 +- Rules.py | 236 +++++++++++++-------------------------------- 4 files changed, 264 insertions(+), 173 deletions(-) create mode 100644 OWGSets.py diff --git a/EntranceShuffle.py b/EntranceShuffle.py index 49339ab2..028305e0 100644 --- a/EntranceShuffle.py +++ b/EntranceShuffle.py @@ -2922,6 +2922,7 @@ mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia Central ('Spiral Cave Mirror Spot', 'Spiral Cave Ledge'), ('Mimic Cave Mirror Spot', 'Mimic Cave Ledge'), ('Cave 45 Mirror Spot', 'Cave 45 Ledge'), + ('Bombos Tablet Mirror Spot', 'Bombos Tablet Ledge') ('Graveyard Ledge Mirror Spot', 'Graveyard Ledge'), ('Swamp Palace Moat', 'Swamp Palace (First Room)'), diff --git a/OWGSets.py b/OWGSets.py new file mode 100644 index 00000000..57b802f6 --- /dev/null +++ b/OWGSets.py @@ -0,0 +1,195 @@ +class OWGSets(self): + ''' + Helper class to deliver entrance/exit/region sets to OWG rules. + ''' + + def get_immediately_accessible_entrances(self): + ''' + Entrances that are available with no items at all. + + At this point, these are fake flipper spots. + ''' + return [ + 'Hobo Bridge', + 'Zoras River', + 'Lake Hylia Island Mirror Spot', + 'Capacity Upgrade', + ] + + def get_lw_boots_accessible_entrances(self, world, player): + ''' + Light World entrances that can be accessed with boots clips. + ''' + entrances = [ + 'Bat Cave Drop Ledge', + 'Desert Ledge Return Rocks', + 'Desert Palace Entrance (West)', + 'Desert Palace Entrance (North)', + 'Flute Spot 1', + 'Broken Bridge (East)', + 'Death Mountain Drop', + 'Old Man Cave (East)', + 'Old Man House (Bottom)', + 'Old Man House (Top)', + 'Death Mountain Return Cave (East)', + 'Spectacle Rock Cave', + 'Spectacle Rock Cave Peak', + 'Spectacle Rock Cave (Bottom)', + 'Spectacle Rock Mirror Spot', + 'Broken Bridge (West)', + 'Broken Bridge (East)', + 'East Death Mountain Drop', + 'Spiral Cave Ledge Drop', + 'Fairy Ascension Drop', + 'Fairy Ascension Cave (Bottom)', + 'East Death Mountain (Top)', + 'Death Mountain (Top)', + 'Spectacle Rock Drop', + 'Death Mountain Return Cave (West)', + 'Paradox Cave (Bottom)', + 'Paradox Cave (Middle)', + 'Hookshot Fairy', + 'Spiral Cave (Bottom)', + 'Paradox Cave (Top)', + 'Spiral Cave Ledge Access', + 'Fairy Ascension Ledge', + 'Cave 45 Mirror Spot', + 'Graveyard Ledge Mirror Spot', + 'Bumper Cave Ledge Mirror Spot', + 'Desert Ledge (Northeast) Mirror Spot', + 'Desert Ledge Mirror Spot', + 'Desert Palace Entrance (North) Mirror Spot', + 'East Death Mountain (Top) Mirror Spot', + 'Spiral Cave Mirror Spot', + 'Fairy Ascension Mirror Spot', + 'Floating Island Mirror Spot', + ] + + if world.mode[player] != 'inverted': + entrances.append('Cave 45') + entrances.append('Graveyard Cave') + + return entrances + + + def get_lw_boots_accessible_locations(self): + ''' + Light World locations that can be reached using boots clips. + ''' + return [ + 'Lake Hylia Island', + 'Desert Ledge', + 'Spectacle Rock', + 'Floating Island', + ] + + + def get_dw_boots_accessible_entrances(self): + ''' + Dark World entrances that can be accessed with boots clips. + ''' + return [ + 'Northeast Dark World Broken Bridge Pass', + 'Peg Area Rocks', + 'Grassy Lawn Pegs', + 'West Dark World Gap', + 'Bumper Cave Ledge Drop', + 'Turtle Rock Drop', + 'Floating Island Drop', + 'Dark Death Mountain Drop (East)', + 'Village of Outcasts Drop', + 'Dark Lake Hylia Ledge', + 'Hype Cave', + 'Dark World Potion Shop', + 'Big Bomb Shop', + 'Archery Game', + 'Brewery', + 'C-Shaped House', + 'Chest Game', + 'Thieves Town', + 'Kings Grave Mirror Spot', + 'Bumper Cave Entrance Rock', + 'Red Shield Shop', + 'Dark Sanctuary Hint', + 'Fortune Teller (Dark)', + 'Dark World Lumberjack Shop', + 'Misery Mire', + 'Mire Shed', + 'Dark Desert Hint', + 'Dark Desert Fairy', + ] + + + def get_dw_boots_accessible_locations(self): + ''' + Dark World locations accessible using boots clips. + ''' + return [ + 'Catfish', + 'Dark Blacksmith Ruins', + 'Bumper Cave Ledge', + ] + + + def get_dw_bunny_inaccessible_locations(self): + ''' + Locations that the bunny cannot access. + ''' + return [ + 'Thieves Town', + 'Graveyard Ledge Mirror Spot', + 'Kings Grave Mirror Spot', + 'Bumper Cave Entrance Rock', + 'Brewery', + 'Village of Outcasts Pegs', + 'Village of Outcasts Eastern Rocks', + 'Dark Lake Hylia Drop (South)', + 'Hype Cave', + 'Village of Outcasts Heavy Rock', + 'East Dark World Bridge', + 'Bonk Fairy (Dark)', + ] + + + def get_dmd_and_bunny_regions(self): + ''' + Dark World regions accessible using Link and Bunny DMD methods. + ''' + return [ + 'West Dark World', + 'South Dark World', + 'Northeast Dark World', + ] + + + def get_dmd_non_bunny_regions(self): + ''' + Dark World regions accessible using only Link DMD methods. + ''' + return [ + 'Dark Desert', + 'East Dark World', + ] + + + def get_mirror_hookshot_accessible_dw_locations(self, world, player): + ''' + Locations accessible potentially using weird mirror hookshot boots setups. + ''' + locations = [ + 'Pyramid Fairy', + 'Pyramid Entrance', + 'Pyramid Drop', + ] + locations.extend(world.get_region('Dark Death Mountain Ledge', player).locations) + return locations + + + def sword_required_superbunny_mirror_regions(self): + ''' + Cave regions that superbunny can get through - but only with a sword. + ''' + return [ + 'Mini Moldorm Cave', + 'Spiral Cave (Top)', + ] \ No newline at end of file diff --git a/Regions.py b/Regions.py index e46b21c1..679253e2 100644 --- a/Regions.py +++ b/Regions.py @@ -156,8 +156,9 @@ def create_regions(world, player): create_dw_region(player, 'Northeast Dark World', ['Catfish'], ['West Dark World Gap', 'Dark World Potion Shop', 'East Dark World Broken Bridge Pass']), create_cave_region(player, 'Palace of Darkness Hint', 'a storyteller'), create_cave_region(player, 'East Dark World Hint', 'a storyteller'), - create_dw_region(player, 'South Dark World', ['Stumpy', 'Digging Game', 'Bombos Tablet'], ['Dark Lake Hylia Drop (South)', 'Hype Cave', 'Swamp Palace', 'Village of Outcasts Heavy Rock', 'Maze Race Mirror Spot', - 'Cave 45 Mirror Spot', 'East Dark World Bridge', 'Big Bomb Shop', 'Archery Game', 'Bonk Fairy (Dark)', 'Dark Lake Hylia Shop']), + create_dw_region(player, 'South Dark World', ['Stumpy', 'Digging Game'], ['Dark Lake Hylia Drop (South)', 'Hype Cave', 'Swamp Palace', 'Village of Outcasts Heavy Rock', 'Maze Race Mirror Spot', + 'Cave 45 Mirror Spot', 'East Dark World Bridge', 'Big Bomb Shop', 'Archery Game', 'Bonk Fairy (Dark)', 'Dark Lake Hylia Shop', 'Bombos Tablet Mirror Spot']), + create_lw_region(player, 'Bombos Tablet Ledge', ['Bombos Tablet']) create_cave_region(player, 'Big Bomb Shop', 'the bomb shop'), create_cave_region(player, 'Archery Game', 'a game of skill'), create_dw_region(player, 'Dark Lake Hylia', None, ['Lake Hylia Island Mirror Spot', 'East Dark World Pier', 'Dark Lake Hylia Ledge']), diff --git a/Rules.py b/Rules.py index 876da683..bcf67999 100644 --- a/Rules.py +++ b/Rules.py @@ -1,5 +1,6 @@ import collections import logging +import OWGSets from BaseClasses import CollectionState @@ -405,7 +406,7 @@ def default_rules(world, player): set_rule(world.get_entrance('Hyrule Castle Ledge Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Hyrule Castle Main Gate', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Dark Lake Hylia Drop (East)', player), lambda state: (state.has_Pearl(player) and state.has('Flippers', player) or state.has_Mirror(player))) # Overworld Bunny Revival - set_rule(world.get_location('Bombos Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player) and state.has_Mirror(player)) + set_rule(world.get_location('Bombos Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player)) set_rule(world.get_entrance('Dark Lake Hylia Drop (South)', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) # ToDo any fake flipper set up? set_rule(world.get_entrance('Dark Lake Hylia Ledge Fairy', player), lambda state: state.has_Pearl(player)) # bomb required set_rule(world.get_entrance('Dark Lake Hylia Ledge Spike Cave', player), lambda state: state.can_lift_rocks(player) and state.has_Pearl(player)) @@ -418,6 +419,7 @@ def default_rules(world, player): set_rule(world.get_entrance('Skull Woods Second Section Hole', player), lambda state: state.has_Pearl(player)) # bunny cannot lift bush set_rule(world.get_entrance('Maze Race Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Cave 45 Mirror Spot', player), lambda state: state.has_Mirror(player)) + set_rule(world.get_entrance('Bombos Tablet Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('East Dark World Bridge', player), lambda state: state.has_Pearl(player) and state.has('Hammer', player)) set_rule(world.get_entrance('Lake Hylia Island Mirror Spot', player), lambda state: state.has_Pearl(player) and state.has_Mirror(player) and state.has('Flippers', player)) set_rule(world.get_entrance('Lake Hylia Central Island Mirror Spot', player), lambda state: state.has_Mirror(player)) @@ -714,117 +716,68 @@ def add_conditional_lamps(world, player): def overworld_glitches_rules(world, player): - # spots that are immediately accessible due to fake flippering - set_rule(world.get_entrance('Hobo Bridge', player), lambda state: True) - set_rule(world.get_entrance('Zoras River', player), lambda state: True) - set_rule(world.get_entrance('Lake Hylia Island Mirror Spot', player), lambda state: True) - set_rule(world.get_entrance('Capacity Upgrade', player), lambda state: True) + # @TODO: Waterfall fairy and Zora ledge could use some logic to determine + # if we can water walk and/or stored water walk in; currently it's omitted + # in case no interiors provide a water walk, but one could be kicking + # around. We could detect a path to determine if one can be stored. - # boots-accessible stuff - lw_boots_accessible_entrances = [ - 'Bat Cave Drop Ledge', - 'Desert Ledge Return Rocks', - 'Desert Palace Entrance (West)', - 'Desert Palace Entrance (North)', - 'Flute Spot 1', - 'Broken Bridge (East)', - 'Death Mountain Drop', - 'Old Man Cave (East)', - 'Old Man House (Bottom)', - 'Old Man House (Top)', - 'Death Mountain Return Cave (East)', - 'Spectacle Rock Cave', - 'Spectacle Rock Cave Peak', - 'Spectacle Rock Cave (Bottom)', - 'Spectacle Rock Mirror Spot', - 'Broken Bridge (West)', - 'Broken Bridge (East)', - 'East Death Mountain Drop', - 'Spiral Cave Ledge Drop', - 'Fairy Ascension Drop', - 'Fairy Ascension Cave (Bottom)', - 'East Death Mountain (Top)', - 'Death Mountain (Top)', - 'Spectacle Rock Drop', - 'Death Mountain Return Cave (West)', - 'Paradox Cave (Bottom)', - 'Paradox Cave (Middle)', - 'Hookshot Fairy', - 'Spiral Cave (Bottom)', - 'Paradox Cave (Top)', - 'Spiral Cave Ledge Access', - 'Fairy Ascension Ledge', - 'Cave 45 Mirror Spot', - 'Graveyard Ledge Mirror Spot', - 'Bumper Cave Ledge Mirror Spot', - 'Desert Ledge (Northeast) Mirror Spot', - 'Desert Ledge Mirror Spot', - 'Desert Palace Entrance (North) Mirror Spot', - 'East Death Mountain (Top) Mirror Spot', - 'Spiral Cave Mirror Spot', - 'Fairy Ascension Mirror Spot', - 'Floating Island Mirror Spot', - ] - lw_boots_accessible_locations = [ - 'Lake Hylia Island', - 'Desert Ledge', - 'Spectacle Rock', - 'Floating Island', - ] - dw_boots_accessible_entrances = [ - 'Northeast Dark World Broken Bridge Pass', - 'Peg Area Rocks', - 'Grassy Lawn Pegs', - 'West Dark World Gap', - 'Bumper Cave Ledge Drop', - 'Turtle Rock Drop', - 'Floating Island Drop', - 'Dark Death Mountain Drop (East)', - 'Village of Outcasts Drop', - 'Dark Lake Hylia Ledge', - 'Hype Cave', - 'Dark World Potion Shop', - 'Big Bomb Shop', - 'Archery Game', - 'Brewery', - 'C-Shaped House', - 'Chest Game', - 'Thieves Town', - 'Kings Grave Mirror Spot', - 'Bumper Cave Entrance Rock', - 'Red Shield Shop', - 'Dark Sanctuary Hint', - 'Fortune Teller (Dark)', - 'Dark World Lumberjack Shop', - 'Misery Mire', - 'Mire Shed', - 'Dark Desert Hint', - 'Dark Desert Fairy', - ] - dw_boots_accessible_locations = [ - 'Catfish', - 'Dark Blacksmith Ruins', - 'Bumper Cave Ledge', - ] - dw_bunny_inaccessible_locations = [ - 'Thieves Town', - 'Graveyard Ledge Mirror Spot', - 'Kings Grave Mirror Spot', - 'Bumper Cave Entrance Rock', - 'Brewery', - 'Village of Outcasts Pegs', - 'Village of Outcasts Eastern Rocks', - 'Dark Lake Hylia Drop (South)', - 'Hype Cave', - 'Village of Outcasts Heavy Rock', - 'East Dark World Bridge', - 'Bonk Fairy (Dark)', - ] - # set up boots-accessible regions + # Spots that are immediately accessible. + for entrance in OWGSets.get_immediately_accessible_entrances(): + set_rule(world.get_entrance(entrance, player), lambda state: True) + + # Boots-accessible locations. + needs_boots = lambda state: state.has_Boots(player) + needs_boots_and_pearl = lambda state: state.has_Boots(player) and state.has_Pearl(player) + for entrance in OWGSets.get_lw_boots_accessible_entrances(world, player): + add_rule(world.get_entrance(entrance, player), needs_boots_and_pearl if world.mode[player] == 'inverted' else needs_boots, 'or') + for location in OWGSets.get_lw_boots_accessible_locations(): + add_rule(world.get_location(location, player), needs_boots_and_pearl if world.mode[player] == 'inverted' else needs_boots, 'or') + for entrance in OWGSets.get_dw_boots_accessible_entrances(): + add_rule(world.get_entrance(entrance, player), needs_boots_and_pearl if world.mode[player] != 'inverted' else needs_boots, 'or') + for location in OWGSets.get_dw_boots_accessible_locations(): + add_rule(world.get_location(location, player), needs_boots_and_pearl if world.mode[player] != 'inverted' else needs_boots, 'or') + + # Boots-accessible regions due to DMD. + if world.mode[player] != 'inverted': + # DMD with and without bunny. + can_bunny_dmd = lambda state: world.get_region('Death Mountain').can_reach(state, player) and state.has_Mirror(player) + for dmd_bunny_region in OWGSets.get_dmd_and_bunny_regions(): + region = world.get_region(dmd_bunny_region, player) + region.can_reach_private = lambda state: region.can_reach(state) or (needs_boots_and_pearl or can_bunny_dmd) + for non_dmd_bunny_region in OWGSets.get_dmd_non_bunny_regions(): + region = world.get_region(non_dmd_bunny_region, player) + region.can_reach_private = lambda state: region.can_reach(state) or (needs_boots_and_pearl) + edmb = world.get_region('Dark Death Mountain (East Bottom)', player) + edmb.can_reach_private = lambda state: edmb.can_reach(state) or can_bunny_dmd + + # Set up some mirror-accessible DW entrances. + boots_and_mirror = lambda state: state.has_Boots(player) and state.has_Mirror(player) + for spot in world.get_region('West Dark World', player).exits + world.get_region('South Dark World', player).exits: + if spot.name not in OWGSets.get_dw_bunny_inaccessible_locations(): + add_rule(world.get_entrance(spot, player), boots_and_mirror, 'or') + for spot in world.get_region('Dark Death Mountain (East Bottom)', player).locations: + add_rule(world.get_location(spot, player), boots_and_mirror, 'or') + # DW entrances accessible with mirror and hookshot. + for spot in OWGSets.get_mirror_hookshot_accessible_dw_locations(world, player): + add_rule(world.get_entrance(spot, player), lambda state: state.has_Boots(player) and state.has_Mirror(player) and state.has('Hookshot', player), 'or') + # DW entrances accessible with mirror and titans. + boots_mirror_titans = lambda state: state.has_Boots(player) and state.has_Mirror(player) and state.can_lift_heavy_rocks(player) + add_rule(world.get_entrance('Mire Shed', player), boots_mirror_titans, 'or') + # Plus the mirror superbunny version. + add_rule(world.get_entrance('Mire Shed', player), lambda state: state.has('Ocarina', player) and state.has_Mirror(player) and state.can_lift_heavy_rocks(player), 'or') + add_rule(world.get_location('Frog', player), boots_mirror_titans, 'or') + + # Locations that you can superbunny mirror into, but need a sword to clear. + superbunny_mirror_weapon = lambda state: state.has_Mirror(player) and state.has_sword(player) + mini_moldorm_cave = world.get_region('Mini Moldorm Cave', player) + for superbunny_mirror_weapon_region in OWGSets.get_sword_required_superbunny_mirror_regions(): + region = world.get_region(superbunny_mirror_weapon_region, player) + if check_is_dark_world(region): + for spot in region.locations: + add_rule(world.get_location(spot, player), superbunny_mirror_weapon, 'or') + + # Regions that require the boots and some other stuff. if world.mode[player] != 'inverted': - lw_boots_accessible_entrances.append('Cave 45') - lw_boots_accessible_entrances.append('Graveyard Cave') - # couple other random spots set_rule(world.get_location('Bombos Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player) and (state.has_Mirror(player) or state.has_Boots(player))) set_rule(world.get_location('Ether Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player) and (state.has_Mirror(player) or state.has_Boots(player))) set_rule(world.get_entrance('Dark Desert Teleporter', player), lambda state: state.has('Ocarina', player) or (state.has_Boots(player) and state.can_lift_heavy_rocks(player))) @@ -837,66 +790,7 @@ def overworld_glitches_rules(world, player): else: add_rule(world.get_entrance('South Dark World Teleporter', player), lambda state: state.has_Boots(player) and state.can_lift_rocks(player), 'or') - # ton of boots-accessible locations. - needs_boots = lambda state: state.has_Boots(player) - needs_boots_and_pearl = lambda state: state.has_Boots(player) and state.has_Pearl(player) - for entrance in lw_boots_accessible_entrances: - add_rule(world.get_entrance(entrance, player), needs_boots_and_pearl if world.mode[player] == 'inverted' else needs_boots, 'or') - for location in lw_boots_accessible_locations: - add_rule(world.get_location(location, player), needs_boots_and_pearl if world.mode[player] == 'inverted' else needs_boots, 'or') - for entrance in dw_boots_accessible_entrances: - add_rule(world.get_entrance(entrance, player), needs_boots_and_pearl if world.mode[player] != 'inverted' else needs_boots, 'or') - for location in dw_boots_accessible_locations: - add_rule(world.get_location(location, player), needs_boots_and_pearl if world.mode[player] != 'inverted' else needs_boots, 'or') - - # standard dmd rules, also feat. bunny - if world.mode[player] != 'inverted': - can_bunny_dmd = lambda state: world.get_region('Death Mountain').can_reach(state, player) and state.has_Mirror(player) - wdw = world.get_region('West Dark World', player) - wdw.can_reach_private = lambda state: wdw.can_reach(state) or (needs_boots_and_pearl or can_bunny_dmd) - sdw = world.get_region('South Dark World', player) - sdw.can_reach_private = lambda state: sdw.can_reach(state) or (needs_boots_and_pearl or can_bunny_dmd) - dd = world.get_region('Dark Desert', player) - dd.can_reach_private = lambda state: dd.can_reach(state) or needs_boots_and_pearl - nedw = world.get_region('Northeast Dark World', player) - nedw.can_reach_private = lambda state: nedw.can_reach(state) or (needs_boots_and_pearl or can_bunny_dmd) - edw = world.get_region('East Dark World', player) - edw.can_reach_private = lambda state: edw.can_reach(state) or needs_boots_and_pearl - edmb = world.get_region('Dark Death Mountain (East Bottom)', player) - edmb.can_reach_private = lambda state: edmb.can_reach(state) or can_bunny_dmd - # set up some mirror-accessible dw entrances. - boots_and_mirror = lambda state: state.has_Boots(player) and state.has_Mirror(player) - for spot in world.get_region('West Dark World', player).exits + world.get_region('South Dark World', player).exits: - if spot.name not in dw_bunny_inaccessible_locations: - add_rule(world.get_entrance(spot, player), boots_and_mirror, 'or') - for spot in world.get_region('Dark Death Mountain (East Bottom)', player).locations: - add_rule(world.get_location(spot, player), boots_and_mirror, 'or') - # dw entrances accessible with mirror and hookshot - mirror_hookshot_accessible_dw_locations = [ - 'Pyramid Fairy', - 'Pyramid Entrance', - 'Pyramid Drop', - ] - mirror_hookshot_accessible_dw_locations.extend(world.get_region('Dark Death Mountain Ledge', player).locations) - for spot in mirror_hookshot_accessible_dw_locations: - add_rule(world.get_entrance(spot, player), lambda state: state.has_Boots(player) and state.has_Mirror(player) and state.has('Hookshot', player), 'or') - # dw entrances accessible with mirror and titans - boots_mirror_titans = lambda state: state.has_Boots(player) and state.has_Mirror(player) and state.can_lift_heavy_rocks(player) - add_rule(world.get_entrance('Mire Shed', player), boots_mirror_titans, 'or') - # plus the mirror superbunny version - add_rule(world.get_entrance('Mire Shed', player), lambda state: state.has('Ocarina', player) and state.has_Mirror(player) and state.can_lift_heavy_rocks(player), 'or') - add_rule(world.get_location('Frog', player), boots_mirror_titans, 'or') - - # also, you can do mini moldorm cave and spiral cave - but requiring a sword. - superbunny_mirror_weapon = lambda state: state.has_Mirror(player) and state.has_sword(player) - mini_moldorm_cave = world.get_region('Mini Moldorm Cave', player) - if check_is_dark_world(mini_moldorm_cave): - for spot in mini_moldorm_cave.locations: - add_rule(world.get_location(spot, player), superbunny_mirror_weapon, 'or') - if check_is_dark_world(world.get_region('Spiral Cave (Top)', player)): - add_rule(world.get_location('Spiral Cave', player), superbunny_mirror_weapon, 'or') - - # add darkness condition. + # Add darkness conditions. add_conditional_lamps(world, player) @@ -1531,7 +1425,7 @@ def set_inverted_bunny_rules(world, player): # Note spiral cave may be technically passible, but it would be too absurd to require since OHKO mode is a thing. bunny_impassable_caves = ['Bumper Cave', 'Two Brothers House', 'Hookshot Cave', 'Skull Woods First Section (Right)', 'Skull Woods First Section (Left)', 'Skull Woods First Section (Top)', 'Turtle Rock (Entrance)', 'Turtle Rock (Second Section)', 'Turtle Rock (Big Chest)', 'Skull Woods Second Section (Drop)', 'Turtle Rock (Eye Bridge)', 'Sewers', 'Pyramid', 'Spiral Cave (Top)', 'Desert Palace Main (Inner)', 'Fairy Ascension Cave (Drop)', 'The Sky'] - bunny_accessible_locations = ['Link\'s Uncle', 'Sahasrahla', 'Sick Kid', 'Lost Woods Hideout', 'Lumberjack Tree', 'Checkerboard Cave', 'Potion Shop', 'Spectacle Rock Cave', 'Pyramid', 'Hype Cave - Generous Guy', 'Peg Cave', 'Bumper Cave Ledge', 'Dark Blacksmith Ruins', 'Bombos Tablet', 'Ether Tablet', 'Purple Chest'] + bunny_accessible_locations = ['Link\'s Uncle', 'Sahasrahla', 'Sick Kid', 'Lost Woods Hideout', 'Lumberjack Tree', 'Checkerboard Cave', 'Potion Shop', 'Spectacle Rock Cave', 'Pyramid', 'Hype Cave - Generous Guy', 'Peg Cave', 'Bumper Cave Ledge', 'Dark Blacksmith Ruins', 'Bombos Tablet Ledge', 'Ether Tablet', 'Purple Chest'] invalid_mirror_bunny_entrances_lw = ['Bonk Rock Cave', 'Bonk Fairy (Light)', 'Blinds Hideout', '50 Rupee Cave', '20 Rupee Cave', 'Checkerboard Cave', 'Light Hype Fairy', 'Waterfall of Wishing', 'Light World Bomb Hut', 'Mini Moldorm Cave', 'Ice Rod Cave', 'Hyrule Castle Secret Entrance Stairs', 'Sanctuary Grave', 'Kings Grave', 'Tower of Hera'] def path_to_access_rule(path, entrance): From e919b2b066e6466d6c74715626628de661b697fb Mon Sep 17 00:00:00 2001 From: qadan Date: Sat, 8 Feb 2020 12:31:24 -0400 Subject: [PATCH 20/52] accidentally a thing --- EntranceShuffle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EntranceShuffle.py b/EntranceShuffle.py index 028305e0..fa07447d 100644 --- a/EntranceShuffle.py +++ b/EntranceShuffle.py @@ -2922,7 +2922,7 @@ mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia Central ('Spiral Cave Mirror Spot', 'Spiral Cave Ledge'), ('Mimic Cave Mirror Spot', 'Mimic Cave Ledge'), ('Cave 45 Mirror Spot', 'Cave 45 Ledge'), - ('Bombos Tablet Mirror Spot', 'Bombos Tablet Ledge') + ('Bombos Tablet Mirror Spot', 'Bombos Tablet Ledge'), ('Graveyard Ledge Mirror Spot', 'Graveyard Ledge'), ('Swamp Palace Moat', 'Swamp Palace (First Room)'), From 6cae0a1a4db95b3c31b1dc02948a74ab9e20d5f1 Mon Sep 17 00:00:00 2001 From: qadan Date: Sat, 8 Feb 2020 12:36:23 -0400 Subject: [PATCH 21/52] no real reason to make class, also using class wrong so theres that --- OWGSets.py | 347 ++++++++++++++++++++++++++--------------------------- 1 file changed, 173 insertions(+), 174 deletions(-) diff --git a/OWGSets.py b/OWGSets.py index 57b802f6..098e27a1 100644 --- a/OWGSets.py +++ b/OWGSets.py @@ -1,195 +1,194 @@ -class OWGSets(self): +''' +Helper functions to deliver entrance/exit/region sets to OWG rules. +''' + +def get_immediately_accessible_entrances(): ''' - Helper class to deliver entrance/exit/region sets to OWG rules. + Entrances that are available with no items at all. + + At this point, these are fake flipper spots. ''' + return [ + 'Hobo Bridge', + 'Zoras River', + 'Lake Hylia Island Mirror Spot', + 'Capacity Upgrade', + ] - def get_immediately_accessible_entrances(self): - ''' - Entrances that are available with no items at all. +def get_lw_boots_accessible_entrances(world, player): + ''' + Light World entrances that can be accessed with boots clips. + ''' + entrances = [ + 'Bat Cave Drop Ledge', + 'Desert Ledge Return Rocks', + 'Desert Palace Entrance (West)', + 'Desert Palace Entrance (North)', + 'Flute Spot 1', + 'Broken Bridge (East)', + 'Death Mountain Drop', + 'Old Man Cave (East)', + 'Old Man House (Bottom)', + 'Old Man House (Top)', + 'Death Mountain Return Cave (East)', + 'Spectacle Rock Cave', + 'Spectacle Rock Cave Peak', + 'Spectacle Rock Cave (Bottom)', + 'Spectacle Rock Mirror Spot', + 'Broken Bridge (West)', + 'Broken Bridge (East)', + 'East Death Mountain Drop', + 'Spiral Cave Ledge Drop', + 'Fairy Ascension Drop', + 'Fairy Ascension Cave (Bottom)', + 'East Death Mountain (Top)', + 'Death Mountain (Top)', + 'Spectacle Rock Drop', + 'Death Mountain Return Cave (West)', + 'Paradox Cave (Bottom)', + 'Paradox Cave (Middle)', + 'Hookshot Fairy', + 'Spiral Cave (Bottom)', + 'Paradox Cave (Top)', + 'Spiral Cave Ledge Access', + 'Fairy Ascension Ledge', + 'Cave 45 Mirror Spot', + 'Graveyard Ledge Mirror Spot', + 'Bumper Cave Ledge Mirror Spot', + 'Desert Ledge (Northeast) Mirror Spot', + 'Desert Ledge Mirror Spot', + 'Desert Palace Entrance (North) Mirror Spot', + 'East Death Mountain (Top) Mirror Spot', + 'Spiral Cave Mirror Spot', + 'Fairy Ascension Mirror Spot', + 'Floating Island Mirror Spot', + ] - At this point, these are fake flipper spots. - ''' - return [ - 'Hobo Bridge', - 'Zoras River', - 'Lake Hylia Island Mirror Spot', - 'Capacity Upgrade', - ] + if world.mode[player] != 'inverted': + entrances.append('Cave 45') + entrances.append('Graveyard Cave') - def get_lw_boots_accessible_entrances(self, world, player): - ''' - Light World entrances that can be accessed with boots clips. - ''' - entrances = [ - 'Bat Cave Drop Ledge', - 'Desert Ledge Return Rocks', - 'Desert Palace Entrance (West)', - 'Desert Palace Entrance (North)', - 'Flute Spot 1', - 'Broken Bridge (East)', - 'Death Mountain Drop', - 'Old Man Cave (East)', - 'Old Man House (Bottom)', - 'Old Man House (Top)', - 'Death Mountain Return Cave (East)', - 'Spectacle Rock Cave', - 'Spectacle Rock Cave Peak', - 'Spectacle Rock Cave (Bottom)', - 'Spectacle Rock Mirror Spot', - 'Broken Bridge (West)', - 'Broken Bridge (East)', - 'East Death Mountain Drop', - 'Spiral Cave Ledge Drop', - 'Fairy Ascension Drop', - 'Fairy Ascension Cave (Bottom)', - 'East Death Mountain (Top)', - 'Death Mountain (Top)', - 'Spectacle Rock Drop', - 'Death Mountain Return Cave (West)', - 'Paradox Cave (Bottom)', - 'Paradox Cave (Middle)', - 'Hookshot Fairy', - 'Spiral Cave (Bottom)', - 'Paradox Cave (Top)', - 'Spiral Cave Ledge Access', - 'Fairy Ascension Ledge', - 'Cave 45 Mirror Spot', - 'Graveyard Ledge Mirror Spot', - 'Bumper Cave Ledge Mirror Spot', - 'Desert Ledge (Northeast) Mirror Spot', - 'Desert Ledge Mirror Spot', - 'Desert Palace Entrance (North) Mirror Spot', - 'East Death Mountain (Top) Mirror Spot', - 'Spiral Cave Mirror Spot', - 'Fairy Ascension Mirror Spot', - 'Floating Island Mirror Spot', - ] - - if world.mode[player] != 'inverted': - entrances.append('Cave 45') - entrances.append('Graveyard Cave') - - return entrances + return entrances - def get_lw_boots_accessible_locations(self): - ''' - Light World locations that can be reached using boots clips. - ''' - return [ - 'Lake Hylia Island', - 'Desert Ledge', - 'Spectacle Rock', - 'Floating Island', - ] +def get_lw_boots_accessible_locations(): + ''' + Light World locations that can be reached using boots clips. + ''' + return [ + 'Lake Hylia Island', + 'Desert Ledge', + 'Spectacle Rock', + 'Floating Island', + ] - def get_dw_boots_accessible_entrances(self): - ''' - Dark World entrances that can be accessed with boots clips. - ''' - return [ - 'Northeast Dark World Broken Bridge Pass', - 'Peg Area Rocks', - 'Grassy Lawn Pegs', - 'West Dark World Gap', - 'Bumper Cave Ledge Drop', - 'Turtle Rock Drop', - 'Floating Island Drop', - 'Dark Death Mountain Drop (East)', - 'Village of Outcasts Drop', - 'Dark Lake Hylia Ledge', - 'Hype Cave', - 'Dark World Potion Shop', - 'Big Bomb Shop', - 'Archery Game', - 'Brewery', - 'C-Shaped House', - 'Chest Game', - 'Thieves Town', - 'Kings Grave Mirror Spot', - 'Bumper Cave Entrance Rock', - 'Red Shield Shop', - 'Dark Sanctuary Hint', - 'Fortune Teller (Dark)', - 'Dark World Lumberjack Shop', - 'Misery Mire', - 'Mire Shed', - 'Dark Desert Hint', - 'Dark Desert Fairy', - ] +def get_dw_boots_accessible_entrances(): + ''' + Dark World entrances that can be accessed with boots clips. + ''' + return [ + 'Northeast Dark World Broken Bridge Pass', + 'Peg Area Rocks', + 'Grassy Lawn Pegs', + 'West Dark World Gap', + 'Bumper Cave Ledge Drop', + 'Turtle Rock Drop', + 'Floating Island Drop', + 'Dark Death Mountain Drop (East)', + 'Village of Outcasts Drop', + 'Dark Lake Hylia Ledge', + 'Hype Cave', + 'Dark World Potion Shop', + 'Big Bomb Shop', + 'Archery Game', + 'Brewery', + 'C-Shaped House', + 'Chest Game', + 'Thieves Town', + 'Kings Grave Mirror Spot', + 'Bumper Cave Entrance Rock', + 'Red Shield Shop', + 'Dark Sanctuary Hint', + 'Fortune Teller (Dark)', + 'Dark World Lumberjack Shop', + 'Misery Mire', + 'Mire Shed', + 'Dark Desert Hint', + 'Dark Desert Fairy', + ] - def get_dw_boots_accessible_locations(self): - ''' - Dark World locations accessible using boots clips. - ''' - return [ - 'Catfish', - 'Dark Blacksmith Ruins', - 'Bumper Cave Ledge', - ] +def get_dw_boots_accessible_locations(): + ''' + Dark World locations accessible using boots clips. + ''' + return [ + 'Catfish', + 'Dark Blacksmith Ruins', + 'Bumper Cave Ledge', + ] - def get_dw_bunny_inaccessible_locations(self): - ''' - Locations that the bunny cannot access. - ''' - return [ - 'Thieves Town', - 'Graveyard Ledge Mirror Spot', - 'Kings Grave Mirror Spot', - 'Bumper Cave Entrance Rock', - 'Brewery', - 'Village of Outcasts Pegs', - 'Village of Outcasts Eastern Rocks', - 'Dark Lake Hylia Drop (South)', - 'Hype Cave', - 'Village of Outcasts Heavy Rock', - 'East Dark World Bridge', - 'Bonk Fairy (Dark)', - ] +def get_dw_bunny_inaccessible_locations(): + ''' + Locations that the bunny cannot access. + ''' + return [ + 'Thieves Town', + 'Graveyard Ledge Mirror Spot', + 'Kings Grave Mirror Spot', + 'Bumper Cave Entrance Rock', + 'Brewery', + 'Village of Outcasts Pegs', + 'Village of Outcasts Eastern Rocks', + 'Dark Lake Hylia Drop (South)', + 'Hype Cave', + 'Village of Outcasts Heavy Rock', + 'East Dark World Bridge', + 'Bonk Fairy (Dark)', + ] - def get_dmd_and_bunny_regions(self): - ''' - Dark World regions accessible using Link and Bunny DMD methods. - ''' - return [ - 'West Dark World', - 'South Dark World', - 'Northeast Dark World', - ] +def get_dmd_and_bunny_regions(): + ''' + Dark World regions accessible using Link and Bunny DMD methods. + ''' + return [ + 'West Dark World', + 'South Dark World', + 'Northeast Dark World', + ] - def get_dmd_non_bunny_regions(self): - ''' - Dark World regions accessible using only Link DMD methods. - ''' - return [ - 'Dark Desert', - 'East Dark World', - ] +def get_dmd_non_bunny_regions(): + ''' + Dark World regions accessible using only Link DMD methods. + ''' + return [ + 'Dark Desert', + 'East Dark World', + ] - def get_mirror_hookshot_accessible_dw_locations(self, world, player): - ''' - Locations accessible potentially using weird mirror hookshot boots setups. - ''' - locations = [ - 'Pyramid Fairy', - 'Pyramid Entrance', - 'Pyramid Drop', - ] - locations.extend(world.get_region('Dark Death Mountain Ledge', player).locations) - return locations +def get_mirror_hookshot_accessible_dw_locations(world, player): + ''' + Locations accessible potentially using weird mirror hookshot boots setups. + ''' + locations = [ + 'Pyramid Fairy', + 'Pyramid Entrance', + 'Pyramid Drop', + ] + locations.extend(world.get_region('Dark Death Mountain Ledge', player).locations) + return locations - def sword_required_superbunny_mirror_regions(self): - ''' - Cave regions that superbunny can get through - but only with a sword. - ''' - return [ - 'Mini Moldorm Cave', - 'Spiral Cave (Top)', - ] \ No newline at end of file +def sword_required_superbunny_mirror_regions(): + ''' + Cave regions that superbunny can get through - but only with a sword. + ''' + return [ + 'Mini Moldorm Cave', + 'Spiral Cave (Top)', + ] \ No newline at end of file From 5a3727510f1893829d60ef8b59eb2bc1af8223ba Mon Sep 17 00:00:00 2001 From: qadan Date: Sat, 8 Feb 2020 12:37:59 -0400 Subject: [PATCH 22/52] fix comma --- OWGSets.py | 4 ++-- Regions.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/OWGSets.py b/OWGSets.py index 57b802f6..e4ce8f76 100644 --- a/OWGSets.py +++ b/OWGSets.py @@ -1,4 +1,4 @@ -class OWGSets(self): +class OWGSets(object): ''' Helper class to deliver entrance/exit/region sets to OWG rules. ''' @@ -192,4 +192,4 @@ class OWGSets(self): return [ 'Mini Moldorm Cave', 'Spiral Cave (Top)', - ] \ No newline at end of file + ] diff --git a/Regions.py b/Regions.py index 679253e2..eefcc71c 100644 --- a/Regions.py +++ b/Regions.py @@ -158,7 +158,7 @@ def create_regions(world, player): create_cave_region(player, 'East Dark World Hint', 'a storyteller'), create_dw_region(player, 'South Dark World', ['Stumpy', 'Digging Game'], ['Dark Lake Hylia Drop (South)', 'Hype Cave', 'Swamp Palace', 'Village of Outcasts Heavy Rock', 'Maze Race Mirror Spot', 'Cave 45 Mirror Spot', 'East Dark World Bridge', 'Big Bomb Shop', 'Archery Game', 'Bonk Fairy (Dark)', 'Dark Lake Hylia Shop', 'Bombos Tablet Mirror Spot']), - create_lw_region(player, 'Bombos Tablet Ledge', ['Bombos Tablet']) + create_lw_region(player, 'Bombos Tablet Ledge', ['Bombos Tablet']), create_cave_region(player, 'Big Bomb Shop', 'the bomb shop'), create_cave_region(player, 'Archery Game', 'a game of skill'), create_dw_region(player, 'Dark Lake Hylia', None, ['Lake Hylia Island Mirror Spot', 'East Dark World Pier', 'Dark Lake Hylia Ledge']), From c6cf8c1ebe6678f2d9a58c4b67fce402032dcd55 Mon Sep 17 00:00:00 2001 From: qadan Date: Sat, 8 Feb 2020 15:18:17 -0400 Subject: [PATCH 23/52] fix bunny rules n stuff --- OWGSets.py | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ Rules.py | 45 +++++++++++++++++------------------- 2 files changed, 89 insertions(+), 24 deletions(-) diff --git a/OWGSets.py b/OWGSets.py index bb3a8515..1d21ee3f 100644 --- a/OWGSets.py +++ b/OWGSets.py @@ -192,3 +192,71 @@ def get_sword_required_superbunny_mirror_regions(): 'Mini Moldorm Cave', 'Spiral Cave (Top)', ] + + +def get_invalid_mirror_bunny_entrances_dw(): + ''' + Dark World entrances that can't be superbunny-mirrored into. + ''' + return [ + 'Skull Woods Final Section (Entrance)', + 'Hype Cave', + 'Bonk Fairy (Dark)', + 'Thieves Town', + 'Dark World Hammer Peg Cave', + 'Brewery', + 'Hookshot Cave', + 'Hookshot Cave Exit (South)', + 'Dark Lake Hylia Ledge Fairy', + 'Dark Lake Hylia Ledge Spike Cave', + ] + + +def get_invalid_mirror_bunny_entrances_lw(): + ''' + Light World entrances that can't be superbunny-mirrored into. + + A couple of these, like Blind's Hideout, are odd cases where the pixel + leading into the entrance prevents mirror superbunnying - generally due to + there being stairs there. + ''' + return [ + 'Bonk Rock Cave', + 'Bonk Fairy (Light)', + 'Blinds Hideout', + '50 Rupee Cave', + '20 Rupee Cave', + 'Checkerboard Cave', + 'Light Hype Fairy', + 'Waterfall of Wishing', + 'Light World Bomb Hut', + 'Mini Moldorm Cave', + 'Ice Rod Cave', + 'Hyrule Castle Secret Entrance Stairs', + 'Sanctuary Grave', + 'Kings Grave', + 'Tower of Hera', + ] + + +def get_superbunny_accessible_locations(): + ''' + Interior locations that can be accessed with superbunny state. + ''' + return [ + 'Waterfall of Wishing - Left', + 'Waterfall of Wishing - Right', + 'King\'s Tomb', 'Floodgate', + 'Floodgate Chest', + 'Cave 45', + 'Bonk Rock Cave', + 'Brewery', + 'C-Shaped House', + 'Chest Game', + 'Mire Shed - Left', + 'Mire Shed - Right', + 'Secret Passage', + 'Ice Rod Cave', + 'Pyramid Fairy - Left', + 'Pyramid Fairy - Right', + ] diff --git a/Rules.py b/Rules.py index bcf67999..c85e8fc2 100644 --- a/Rules.py +++ b/Rules.py @@ -1342,9 +1342,7 @@ def set_bunny_rules(world, player): 'Turtle Rock (Eye Bridge)', 'Sewers', 'Pyramid', 'Spiral Cave (Top)', 'Desert Palace Main (Inner)', 'Fairy Ascension Cave (Drop)'] bunny_accessible_locations = ['Link\'s Uncle', 'Sahasrahla', 'Sick Kid', 'Lost Woods Hideout', 'Lumberjack Tree', 'Checkerboard Cave', 'Potion Shop', 'Spectacle Rock Cave', 'Pyramid', 'Hype Cave - Generous Guy', 'Peg Cave', 'Bumper Cave Ledge', 'Dark Blacksmith Ruins'] - # interiors that are accessible if you're in bunny state but have the mirror; OWG-only. - superbunny_accessible_locations = ['Waterfall of Wishing - Left', 'Waterfall of Wishing - Right', 'King\'s Tomb', 'Floodgate', 'Floodgate Chest', 'Cave 45', 'Bonk Rock Cave', 'Brewery', 'C-Shaped House', 'Chest Game', 'Mire Shed - Left', 'Mire Shed - Right', 'Secret Passage', 'Ice Rod Cave', 'Pyramid Fairy - Left', 'Pyramid Fairy - Right'] - invalid_mirror_bunny_entrances_dw = ['Skull Woods Final Section (Entrance)', 'Hype Cave', 'Bonk Fairy (Dark)', 'Thieves Town', 'Dark World Hammer Peg Cave', 'Brewery', 'Hookshot Cave', 'Hookshot Cave Exit (South)', 'Dark Lake Hylia Ledge Fairy', 'Dark Lake Hylia Ledge Spike Cave'] + def path_to_access_rule(path, entrance): return lambda state: state.can_reach(entrance) and all(rule(state) for rule in path) @@ -1353,17 +1351,13 @@ def set_bunny_rules(world, player): return lambda state: any(rule(state) for rule in options) def get_rule_to_add(region, location = None): - possible_options = [] - if not region.is_light_world: - if world.logic[player] == 'owglitches' and location in superbunny_accessible_locations and region.name not in invalid_mirror_bunny_entrances_dw: - possible_options.append(lambda state: state.has_Boots(player) and state.has_Mirror(player)) - else: - return lambda state: state.has_Pearl(player) + if not region.is_light_world or not(world.logic[player] == 'owglitches' and location in OWGSets.get_superbunny_accessible_locations() and region.name not in invalid_mirror_bunny_entrances_dw): + return lambda state: state.has_Pearl(player) # in this case we are mixed region. # we collect possible options. # The base option is having the moon pearl - possible_options.append(lambda state: state.has_Pearl(player)) + possible_options = [lambda state: state.has_Pearl(player)] # We will search entrances recursively until we find # one that leads to an exclusively light world region @@ -1381,12 +1375,16 @@ def set_bunny_rules(world, player): new_path = path + [entrance.access_rule] seen.add(new_region) if not new_region.is_light_world: - if world.logic[player] == 'owglitches': - if entrance in superbunny_accessible_locations and region.name not in invalid_mirror_bunny_entrances_dw: - possible_options.append(path_to_access_rule(new_path, entrance)) + # For OWG, establish superbunny and revival rules. + if world.logic[player] == 'owglitches' and entrance.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(): + for location in entrance.connected_region.locations: + if location.name in OWGSets.get_superbunny_accessible_locations(): + possible_options.append(lambda state: state.can_reach(entrance) and all(rule(state) for rule in path) and state.has_Mirror(player)) + continue for exit in new_region.exits: if exit.name in dungeon_exits: possible_options.append(path_to_access_rule(new_path, entrance)) + continue else: continue if new_region.is_dark_world: @@ -1426,7 +1424,6 @@ def set_inverted_bunny_rules(world, player): bunny_impassable_caves = ['Bumper Cave', 'Two Brothers House', 'Hookshot Cave', 'Skull Woods First Section (Right)', 'Skull Woods First Section (Left)', 'Skull Woods First Section (Top)', 'Turtle Rock (Entrance)', 'Turtle Rock (Second Section)', 'Turtle Rock (Big Chest)', 'Skull Woods Second Section (Drop)', 'Turtle Rock (Eye Bridge)', 'Sewers', 'Pyramid', 'Spiral Cave (Top)', 'Desert Palace Main (Inner)', 'Fairy Ascension Cave (Drop)', 'The Sky'] bunny_accessible_locations = ['Link\'s Uncle', 'Sahasrahla', 'Sick Kid', 'Lost Woods Hideout', 'Lumberjack Tree', 'Checkerboard Cave', 'Potion Shop', 'Spectacle Rock Cave', 'Pyramid', 'Hype Cave - Generous Guy', 'Peg Cave', 'Bumper Cave Ledge', 'Dark Blacksmith Ruins', 'Bombos Tablet Ledge', 'Ether Tablet', 'Purple Chest'] - invalid_mirror_bunny_entrances_lw = ['Bonk Rock Cave', 'Bonk Fairy (Light)', 'Blinds Hideout', '50 Rupee Cave', '20 Rupee Cave', 'Checkerboard Cave', 'Light Hype Fairy', 'Waterfall of Wishing', 'Light World Bomb Hut', 'Mini Moldorm Cave', 'Ice Rod Cave', 'Hyrule Castle Secret Entrance Stairs', 'Sanctuary Grave', 'Kings Grave', 'Tower of Hera'] def path_to_access_rule(path, entrance): return lambda state: state.can_reach(entrance) and all(rule(state) for rule in path) @@ -1435,17 +1432,13 @@ def set_inverted_bunny_rules(world, player): return lambda state: any(rule(state) for rule in options) def get_rule_to_add(region, location = None): - possible_options = [] - if not region.is_dark_world: - if world.logic[player] == 'owglitches' and location in bunny_accessible_locations and region.name not in invalid_mirror_bunny_entrances_lw: - possible_options.append(lambda state: state.has_Boots(player) and state.has_Mirror(player)) - else: - return lambda state: state.has_Pearl(player) + if not region.is_dark_world or not (world.logic[player] == 'owglitches' and location in bunny_accessible_locations and region.name not in invalid_mirror_bunny_entrances_lw): + return lambda state: state.has_Pearl(player) # in this case we are mixed region. # we collect possible options. # The base option is having the moon pearl - possible_options.append(lambda state: state.has_Pearl(player)) + possible_options = [lambda state: state.has_Pearl(player)] # We will search entrances recursively until we find # one that leads to an exclusively dark world region @@ -1463,12 +1456,16 @@ def set_inverted_bunny_rules(world, player): new_path = path + [entrance.access_rule] seen.add(new_region) if not new_region.is_dark_world: - if world.logic[player] == 'owglitches': - if entrance in superbunny_accessible_locations and region.name not in invalid_mirror_bunny_entrances_lw: - possible_options.append(path_to_access_rule(new_path, entrance)) + # For OWG, establish superbunny and revival rules. + if world.logic[player] == 'owglitches' and entrance.name not in OWGSets.get_invalid_mirror_bunny_entrances_lw(): + for location in entrance.connected_region.locations: + if location.name in OWGSets.get_superbunny_accessible_locations(): + possible_options.append(lambda state: state.can_reach(entrance) and all(rule(state) for rule in path) and state.has_Mirror(player)) + continue for exit in new_region.exits: if exit.name in dungeon_exits: possible_options.append(path_to_access_rule(new_path, entrance)) + continue else: continue if new_region.is_light_world: From e4ab046027208a59d050984f4f18f324ed10d2f5 Mon Sep 17 00:00:00 2001 From: qadan Date: Sat, 8 Feb 2020 19:00:21 -0400 Subject: [PATCH 24/52] ensure inverted runs --- OWGSets.py | 48 +++++++++++++++++++++++++----------------------- Rules.py | 4 ++-- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/OWGSets.py b/OWGSets.py index 1d21ee3f..258d830d 100644 --- a/OWGSets.py +++ b/OWGSets.py @@ -2,18 +2,20 @@ Helper functions to deliver entrance/exit/region sets to OWG rules. ''' -def get_immediately_accessible_entrances(): +def get_immediately_accessible_entrances(world, player): ''' Entrances that are available with no items at all. At this point, these are fake flipper spots. ''' - return [ + entrances = [ 'Hobo Bridge', 'Zoras River', - 'Lake Hylia Island Mirror Spot', 'Capacity Upgrade', ] + if world.mode[player] != 'inverted': + entrances.append('Lake Hylia Island Mirror Spot') + return entrances def get_lw_boots_accessible_entrances(world, player): ''' @@ -24,7 +26,6 @@ def get_lw_boots_accessible_entrances(world, player): 'Desert Ledge Return Rocks', 'Desert Palace Entrance (West)', 'Desert Palace Entrance (North)', - 'Flute Spot 1', 'Broken Bridge (East)', 'Death Mountain Drop', 'Old Man Cave (East)', @@ -34,7 +35,6 @@ def get_lw_boots_accessible_entrances(world, player): 'Spectacle Rock Cave', 'Spectacle Rock Cave Peak', 'Spectacle Rock Cave (Bottom)', - 'Spectacle Rock Mirror Spot', 'Broken Bridge (West)', 'Broken Bridge (East)', 'East Death Mountain Drop', @@ -43,7 +43,6 @@ def get_lw_boots_accessible_entrances(world, player): 'Fairy Ascension Cave (Bottom)', 'East Death Mountain (Top)', 'Death Mountain (Top)', - 'Spectacle Rock Drop', 'Death Mountain Return Cave (West)', 'Paradox Cave (Bottom)', 'Paradox Cave (Middle)', @@ -51,23 +50,24 @@ def get_lw_boots_accessible_entrances(world, player): 'Spiral Cave (Bottom)', 'Paradox Cave (Top)', 'Spiral Cave Ledge Access', - 'Fairy Ascension Ledge', - 'Cave 45 Mirror Spot', - 'Graveyard Ledge Mirror Spot', 'Bumper Cave Ledge Mirror Spot', - 'Desert Ledge (Northeast) Mirror Spot', - 'Desert Ledge Mirror Spot', - 'Desert Palace Entrance (North) Mirror Spot', - 'East Death Mountain (Top) Mirror Spot', - 'Spiral Cave Mirror Spot', - 'Fairy Ascension Mirror Spot', 'Floating Island Mirror Spot', ] - if world.mode[player] != 'inverted': entrances.append('Cave 45') entrances.append('Graveyard Cave') - + entrances.append('Flute Spot 1') + entrances.append('Spectacle Rock Mirror Spot') + entrances.append('Spectacle Rock Drop') + entrances.append('Fairy Ascension Ledge') + entrances.append('Cave 45 Mirror Spot') + entrances.append('Graveyard Ledge Mirror Spot') + entrances.append('Desert Ledge (Northeast) Mirror Spot') + entrances.append('Desert Ledge Mirror Spot') + entrances.append('Desert Palace Entrance (North) Mirror Spot') + entrances.append('East Death Mountain (Top) Mirror Spot') + entrances.append('Spiral Cave Mirror Spot') + entrances.append('Fairy Ascension Mirror Spot') return entrances @@ -83,11 +83,11 @@ def get_lw_boots_accessible_locations(): ] -def get_dw_boots_accessible_entrances(): +def get_dw_boots_accessible_entrances(world, player): ''' Dark World entrances that can be accessed with boots clips. ''' - return [ + entrances = [ 'Northeast Dark World Broken Bridge Pass', 'Peg Area Rocks', 'Grassy Lawn Pegs', @@ -97,19 +97,15 @@ def get_dw_boots_accessible_entrances(): 'Floating Island Drop', 'Dark Death Mountain Drop (East)', 'Village of Outcasts Drop', - 'Dark Lake Hylia Ledge', 'Hype Cave', 'Dark World Potion Shop', - 'Big Bomb Shop', 'Archery Game', 'Brewery', 'C-Shaped House', 'Chest Game', 'Thieves Town', - 'Kings Grave Mirror Spot', 'Bumper Cave Entrance Rock', 'Red Shield Shop', - 'Dark Sanctuary Hint', 'Fortune Teller (Dark)', 'Dark World Lumberjack Shop', 'Misery Mire', @@ -117,6 +113,12 @@ def get_dw_boots_accessible_entrances(): 'Dark Desert Hint', 'Dark Desert Fairy', ] + if world.mode[player] != 'inverted': + entrances.append('Dark Lake Hylia Ledge') + entrances.append('Big Bomb Shop') + entrances.append('Kings Grave Mirror Spot') + entrances.append('Dark Sanctuary Hint') + return entrances def get_dw_boots_accessible_locations(): diff --git a/Rules.py b/Rules.py index c85e8fc2..d812b2fc 100644 --- a/Rules.py +++ b/Rules.py @@ -722,7 +722,7 @@ def overworld_glitches_rules(world, player): # around. We could detect a path to determine if one can be stored. # Spots that are immediately accessible. - for entrance in OWGSets.get_immediately_accessible_entrances(): + for entrance in OWGSets.get_immediately_accessible_entrances(world, player): set_rule(world.get_entrance(entrance, player), lambda state: True) # Boots-accessible locations. @@ -732,7 +732,7 @@ def overworld_glitches_rules(world, player): add_rule(world.get_entrance(entrance, player), needs_boots_and_pearl if world.mode[player] == 'inverted' else needs_boots, 'or') for location in OWGSets.get_lw_boots_accessible_locations(): add_rule(world.get_location(location, player), needs_boots_and_pearl if world.mode[player] == 'inverted' else needs_boots, 'or') - for entrance in OWGSets.get_dw_boots_accessible_entrances(): + for entrance in OWGSets.get_dw_boots_accessible_entrances(world, player): add_rule(world.get_entrance(entrance, player), needs_boots_and_pearl if world.mode[player] != 'inverted' else needs_boots, 'or') for location in OWGSets.get_dw_boots_accessible_locations(): add_rule(world.get_location(location, player), needs_boots_and_pearl if world.mode[player] != 'inverted' else needs_boots, 'or') From c10739e70c6dd36506ca47694188a73b9e3be07a Mon Sep 17 00:00:00 2001 From: qadan Date: Sat, 8 Feb 2020 19:17:34 -0400 Subject: [PATCH 25/52] fixing up some stuff I broke --- Mystery.py | 7 ++++--- Rom.py | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Mystery.py b/Mystery.py index ff4410a8..5a47cc9a 100644 --- a/Mystery.py +++ b/Mystery.py @@ -67,7 +67,6 @@ def main(): if path: if path not in weights_cache: weights_cache[path] = get_weights(path) - print(weights_cache[path]) print(f"P{player} Weights: {path} >> {weights_cache[path]['description']}") erargs = parse_arguments(['--multi', str(args.multi)]) @@ -102,8 +101,10 @@ def main(): def get_weights(path): try: - with open(path, 'rb') as f: - yaml = str(f.read(), "utf-8") + parsed_url = urllib.parse.urlparse(path) + if all(parsed_url.scheme, parsed_url.netloc, parsed_url.path): + with open(path, 'rb') as f: + yaml = str(f.read(), "utf-8") except Exception as e: print('Failed to read weights (%s)' % e) return diff --git a/Rom.py b/Rom.py index b5817f24..be8aed8c 100644 --- a/Rom.py +++ b/Rom.py @@ -12,9 +12,9 @@ import subprocess from BaseClasses import CollectionState, ShopType, Region, Location from Dungeons import dungeon_music_addresses from Regions import location_table - from Text import MultiByteTextMapper, CompressedTextMapper, text_addresses, Credits from Text import TextTable, Uncle_texts, Ganon1_texts, TavernMan_texts, Sahasrahla2_texts, Triforce_texts, Blind_texts, BombShop2_texts, junk_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 output_path, local_path, int16_as_bytes, int32_as_bytes, snes_to_pc from Items import ItemFactory From a8a12d14bafacfd5e678e9f663cdd55386d4d2d1 Mon Sep 17 00:00:00 2001 From: qadan Date: Sun, 9 Feb 2020 13:54:59 -0400 Subject: [PATCH 26/52] wip stuff --- OWGSets.py | 2 +- Rules.py | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/OWGSets.py b/OWGSets.py index 258d830d..743c24a8 100644 --- a/OWGSets.py +++ b/OWGSets.py @@ -159,7 +159,6 @@ def get_dmd_and_bunny_regions(): return [ 'West Dark World', 'South Dark World', - 'Northeast Dark World', ] @@ -170,6 +169,7 @@ def get_dmd_non_bunny_regions(): return [ 'Dark Desert', 'East Dark World', + 'Northeast Dark World', ] diff --git a/Rules.py b/Rules.py index d812b2fc..5c2225e2 100644 --- a/Rules.py +++ b/Rules.py @@ -740,7 +740,7 @@ def overworld_glitches_rules(world, player): # Boots-accessible regions due to DMD. if world.mode[player] != 'inverted': # DMD with and without bunny. - can_bunny_dmd = lambda state: world.get_region('Death Mountain').can_reach(state, player) and state.has_Mirror(player) + can_bunny_dmd = lambda state: state.has_Mirror(player) for dmd_bunny_region in OWGSets.get_dmd_and_bunny_regions(): region = world.get_region(dmd_bunny_region, player) region.can_reach_private = lambda state: region.can_reach(state) or (needs_boots_and_pearl or can_bunny_dmd) @@ -781,7 +781,6 @@ def overworld_glitches_rules(world, player): set_rule(world.get_location('Bombos Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player) and (state.has_Mirror(player) or state.has_Boots(player))) set_rule(world.get_location('Ether Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player) and (state.has_Mirror(player) or state.has_Boots(player))) set_rule(world.get_entrance('Dark Desert Teleporter', player), lambda state: state.has('Ocarina', player) or (state.has_Boots(player) and state.can_lift_heavy_rocks(player))) - set_rule(world.get_location('Zora\'s Ledge', player), lambda state: state.has_Boots(player)) add_rule(world.get_entrance('Ganons Tower', player), lambda state: state.has_Boots(player) and state.has_Pearl(player), 'or') add_rule(world.get_entrance('East Death Mountain Teleporter', player), lambda state: state.can_lift_heavy_rocks(player) and state.has_Boots(player), 'or') add_rule(world.get_entrance('Turtle Rock Teleporter', player), lambda state: state.has_Boots(player) and state.has('Hammer', player), 'or') From 08d908b9fc332469004021e8f757eb2f695fb54b Mon Sep 17 00:00:00 2001 From: qadan Date: Sun, 9 Feb 2020 15:06:55 -0400 Subject: [PATCH 27/52] fixing bunny dmd stuff --- Rules.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Rules.py b/Rules.py index 5c2225e2..e437cf73 100644 --- a/Rules.py +++ b/Rules.py @@ -740,7 +740,7 @@ def overworld_glitches_rules(world, player): # Boots-accessible regions due to DMD. if world.mode[player] != 'inverted': # DMD with and without bunny. - can_bunny_dmd = lambda state: state.has_Mirror(player) + can_bunny_dmd = lambda state: world.get_region('Death Mountain').can_reach(state) and state.has_Mirror(player) for dmd_bunny_region in OWGSets.get_dmd_and_bunny_regions(): region = world.get_region(dmd_bunny_region, player) region.can_reach_private = lambda state: region.can_reach(state) or (needs_boots_and_pearl or can_bunny_dmd) @@ -755,8 +755,7 @@ def overworld_glitches_rules(world, player): for spot in world.get_region('West Dark World', player).exits + world.get_region('South Dark World', player).exits: if spot.name not in OWGSets.get_dw_bunny_inaccessible_locations(): add_rule(world.get_entrance(spot, player), boots_and_mirror, 'or') - for spot in world.get_region('Dark Death Mountain (East Bottom)', player).locations: - add_rule(world.get_location(spot, player), boots_and_mirror, 'or') + add_rule(world.get_entrance('East Death Mountain Mirror Spot (Bottom)', player), boots_and_mirror, 'or') # DW entrances accessible with mirror and hookshot. for spot in OWGSets.get_mirror_hookshot_accessible_dw_locations(world, player): add_rule(world.get_entrance(spot, player), lambda state: state.has_Boots(player) and state.has_Mirror(player) and state.has('Hookshot', player), 'or') From 79339a5fdfa3bcb84e497c9193888b27cb0d3c25 Mon Sep 17 00:00:00 2001 From: qadan Date: Sun, 9 Feb 2020 15:14:15 -0400 Subject: [PATCH 28/52] thats not where that is --- Rules.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Rules.py b/Rules.py index e437cf73..df35303b 100644 --- a/Rules.py +++ b/Rules.py @@ -755,7 +755,6 @@ def overworld_glitches_rules(world, player): for spot in world.get_region('West Dark World', player).exits + world.get_region('South Dark World', player).exits: if spot.name not in OWGSets.get_dw_bunny_inaccessible_locations(): add_rule(world.get_entrance(spot, player), boots_and_mirror, 'or') - add_rule(world.get_entrance('East Death Mountain Mirror Spot (Bottom)', player), boots_and_mirror, 'or') # DW entrances accessible with mirror and hookshot. for spot in OWGSets.get_mirror_hookshot_accessible_dw_locations(world, player): add_rule(world.get_entrance(spot, player), lambda state: state.has_Boots(player) and state.has_Mirror(player) and state.has('Hookshot', player), 'or') @@ -765,6 +764,8 @@ def overworld_glitches_rules(world, player): # Plus the mirror superbunny version. add_rule(world.get_entrance('Mire Shed', player), lambda state: state.has('Ocarina', player) and state.has_Mirror(player) and state.can_lift_heavy_rocks(player), 'or') add_rule(world.get_location('Frog', player), boots_mirror_titans, 'or') + else: + add_rule(world.get_entrance('East Death Mountain Mirror Spot (Bottom)', player), boots_and_mirror, 'or') # Locations that you can superbunny mirror into, but need a sword to clear. superbunny_mirror_weapon = lambda state: state.has_Mirror(player) and state.has_sword(player) @@ -1377,6 +1378,7 @@ def set_bunny_rules(world, player): if world.logic[player] == 'owglitches' and entrance.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(): for location in entrance.connected_region.locations: if location.name in OWGSets.get_superbunny_accessible_locations(): + print(location.name) possible_options.append(lambda state: state.can_reach(entrance) and all(rule(state) for rule in path) and state.has_Mirror(player)) continue for exit in new_region.exits: From a5f585ce7cb02f798dba785108d1e2469c4dfe60 Mon Sep 17 00:00:00 2001 From: qadan Date: Sun, 9 Feb 2020 18:43:15 -0400 Subject: [PATCH 29/52] fix bunny logic --- OWGSets.py | 32 +++++++++++++++++++------------- Rules.py | 19 ++++++++++--------- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/OWGSets.py b/OWGSets.py index 743c24a8..cda65592 100644 --- a/OWGSets.py +++ b/OWGSets.py @@ -13,8 +13,6 @@ def get_immediately_accessible_entrances(world, player): 'Zoras River', 'Capacity Upgrade', ] - if world.mode[player] != 'inverted': - entrances.append('Lake Hylia Island Mirror Spot') return entrances def get_lw_boots_accessible_entrances(world, player): @@ -54,20 +52,9 @@ def get_lw_boots_accessible_entrances(world, player): 'Floating Island Mirror Spot', ] if world.mode[player] != 'inverted': - entrances.append('Cave 45') - entrances.append('Graveyard Cave') entrances.append('Flute Spot 1') - entrances.append('Spectacle Rock Mirror Spot') entrances.append('Spectacle Rock Drop') entrances.append('Fairy Ascension Ledge') - entrances.append('Cave 45 Mirror Spot') - entrances.append('Graveyard Ledge Mirror Spot') - entrances.append('Desert Ledge (Northeast) Mirror Spot') - entrances.append('Desert Ledge Mirror Spot') - entrances.append('Desert Palace Entrance (North) Mirror Spot') - entrances.append('East Death Mountain (Top) Mirror Spot') - entrances.append('Spiral Cave Mirror Spot') - entrances.append('Fairy Ascension Mirror Spot') return entrances @@ -173,6 +160,23 @@ def get_dmd_non_bunny_regions(): ] +def get_boots_accessible_regions_lw(): + ''' + Light World regions that can be accessed using boots clips. + ''' + return [ + 'Desert Ledge (Northeast)', + 'Desert Ledge', + 'Desert Palace Entrance (North) Spot', + 'Cave 45 Ledge', + 'Graveyard Ledge', + 'Lake Hylia Island', + 'Death Mountain', + 'Death Mountain Return Ledge', + 'Bombos Tablet Ledge', + ] + + def get_mirror_hookshot_accessible_dw_locations(world, player): ''' Locations accessible potentially using weird mirror hookshot boots setups. @@ -261,4 +265,6 @@ def get_superbunny_accessible_locations(): 'Ice Rod Cave', 'Pyramid Fairy - Left', 'Pyramid Fairy - Right', + 'Superbunny Cave - Top', + 'Superbunny Cave - Bottom', ] diff --git a/Rules.py b/Rules.py index df35303b..2d38ba38 100644 --- a/Rules.py +++ b/Rules.py @@ -737,10 +737,13 @@ def overworld_glitches_rules(world, player): for location in OWGSets.get_dw_boots_accessible_locations(): add_rule(world.get_location(location, player), needs_boots_and_pearl if world.mode[player] != 'inverted' else needs_boots, 'or') - # Boots-accessible regions due to DMD. + # Boots-accessible regions. if world.mode[player] != 'inverted': + for boots_accessible_region in OWGSets.get_boots_accessible_regions_lw(): + region = world.get_region(boots_accessible_region, player) + region.can_reach_private = lambda state: region.can_reach(state) or needs_boots # DMD with and without bunny. - can_bunny_dmd = lambda state: world.get_region('Death Mountain').can_reach(state) and state.has_Mirror(player) + can_bunny_dmd = lambda state: world.get_region('Death Mountain', player).can_reach(state) and state.has_Mirror(player) for dmd_bunny_region in OWGSets.get_dmd_and_bunny_regions(): region = world.get_region(dmd_bunny_region, player) region.can_reach_private = lambda state: region.can_reach(state) or (needs_boots_and_pearl or can_bunny_dmd) @@ -778,14 +781,10 @@ def overworld_glitches_rules(world, player): # Regions that require the boots and some other stuff. if world.mode[player] != 'inverted': - set_rule(world.get_location('Bombos Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player) and (state.has_Mirror(player) or state.has_Boots(player))) - set_rule(world.get_location('Ether Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player) and (state.has_Mirror(player) or state.has_Boots(player))) set_rule(world.get_entrance('Dark Desert Teleporter', player), lambda state: state.has('Ocarina', player) or (state.has_Boots(player) and state.can_lift_heavy_rocks(player))) add_rule(world.get_entrance('Ganons Tower', player), lambda state: state.has_Boots(player) and state.has_Pearl(player), 'or') add_rule(world.get_entrance('East Death Mountain Teleporter', player), lambda state: state.can_lift_heavy_rocks(player) and state.has_Boots(player), 'or') add_rule(world.get_entrance('Turtle Rock Teleporter', player), lambda state: state.has_Boots(player) and state.has('Hammer', player), 'or') - add_rule(world.get_entrance('Checkerboard Cave', player), lambda state: state.has_Boots(player) and state.can_lift_rocks(player), 'or') - add_rule(world.get_entrance('South Hyrule Teleporter', player), lambda state: state.has_Boots(player) and state.can_lift_rocks(player), 'or') else: add_rule(world.get_entrance('South Dark World Teleporter', player), lambda state: state.has_Boots(player) and state.can_lift_rocks(player), 'or') @@ -1350,7 +1349,7 @@ def set_bunny_rules(world, player): return lambda state: any(rule(state) for rule in options) def get_rule_to_add(region, location = None): - if not region.is_light_world or not(world.logic[player] == 'owglitches' and location in OWGSets.get_superbunny_accessible_locations() and region.name not in invalid_mirror_bunny_entrances_dw): + if not region.is_light_world and not (world.logic[player] == 'owglitches' and location in OWGSets.get_superbunny_accessible_locations() and region.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw()): return lambda state: state.has_Pearl(player) # in this case we are mixed region. # we collect possible options. @@ -1378,8 +1377,7 @@ def set_bunny_rules(world, player): if world.logic[player] == 'owglitches' and entrance.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(): for location in entrance.connected_region.locations: if location.name in OWGSets.get_superbunny_accessible_locations(): - print(location.name) - possible_options.append(lambda state: state.can_reach(entrance) and all(rule(state) for rule in path) and state.has_Mirror(player)) + possible_options.append(lambda state: path_to_access_rule(new_path, entrance) and state.has_Mirror(player)) continue for exit in new_region.exits: if exit.name in dungeon_exits: @@ -1413,6 +1411,9 @@ def set_bunny_rules(world, player): if location.name in bunny_accessible_locations: continue + if world.logic[player] == 'owglitches' and location.parent_region.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw() and location.name in OWGSets.get_superbunny_accessible_locations(): + add_rule(location, get_rule_to_add(location.parent_region, location.name)) + continue add_rule(location, get_rule_to_add(location.parent_region, location.name)) From 3e697f44dc2468cc9e4459e5014de0c11e0bf2e6 Mon Sep 17 00:00:00 2001 From: qadan Date: Sun, 9 Feb 2020 18:49:41 -0400 Subject: [PATCH 30/52] was moved for an earlier thing --- Rom.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Rom.py b/Rom.py index be8aed8c..4b22de66 100644 --- a/Rom.py +++ b/Rom.py @@ -12,8 +12,8 @@ import subprocess from BaseClasses import CollectionState, ShopType, Region, Location from Dungeons import dungeon_music_addresses from Regions import location_table -from Text import MultiByteTextMapper, CompressedTextMapper, text_addresses, Credits -from Text import TextTable, Uncle_texts, Ganon1_texts, TavernMan_texts, Sahasrahla2_texts, Triforce_texts, Blind_texts, BombShop2_texts, junk_texts +from Text import MultiByteTextMapper, CompressedTextMapper, text_addresses, Credits, TextTable +from Text import Uncle_texts, Ganon1_texts, TavernMan_texts, Sahasrahla2_texts, Triforce_texts, Blind_texts, BombShop2_texts, junk_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 output_path, local_path, int16_as_bytes, int32_as_bytes, snes_to_pc From 36333b3a491fe944835683b23ac4ef2e76183175 Mon Sep 17 00:00:00 2001 From: qadan Date: Sun, 9 Feb 2020 18:52:07 -0400 Subject: [PATCH 31/52] not sure where this went --- Rules.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Rules.py b/Rules.py index 2d38ba38..eb42967f 100644 --- a/Rules.py +++ b/Rules.py @@ -361,6 +361,7 @@ def default_rules(world, player): set_rule(world.get_entrance('Kings Grave Mirror Spot', player), lambda state: state.has_Pearl(player) and state.has_Mirror(player)) # Caution: If king's grave is releaxed at all to account for reaching it via a two way cave's exit in insanity mode, then the bomb shop logic will need to be updated (that would involve create a small ledge-like Region for it) set_rule(world.get_entrance('Bonk Fairy (Light)', player), lambda state: state.has_Boots(player)) + set_rule(world.get_entrance('Bat Cave Drop Ledge', player), lambda state: state.has('Hammer', player)) set_rule(world.get_entrance('Lumberjack Tree Tree', player), lambda state: state.has_Boots(player) and state.has('Beat Agahnim 1', player)) set_rule(world.get_entrance('Bonk Rock Cave', player), lambda state: state.has_Boots(player)) set_rule(world.get_entrance('Desert Palace Stairs', player), lambda state: state.has('Book of Mudora', player)) From 50687131e8c7ac0bf695122b6f6627573846e8f1 Mon Sep 17 00:00:00 2001 From: qadan Date: Sun, 9 Feb 2020 18:53:22 -0400 Subject: [PATCH 32/52] oh yeah --- Rules.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Rules.py b/Rules.py index eb42967f..2d38ba38 100644 --- a/Rules.py +++ b/Rules.py @@ -361,7 +361,6 @@ def default_rules(world, player): set_rule(world.get_entrance('Kings Grave Mirror Spot', player), lambda state: state.has_Pearl(player) and state.has_Mirror(player)) # Caution: If king's grave is releaxed at all to account for reaching it via a two way cave's exit in insanity mode, then the bomb shop logic will need to be updated (that would involve create a small ledge-like Region for it) set_rule(world.get_entrance('Bonk Fairy (Light)', player), lambda state: state.has_Boots(player)) - set_rule(world.get_entrance('Bat Cave Drop Ledge', player), lambda state: state.has('Hammer', player)) set_rule(world.get_entrance('Lumberjack Tree Tree', player), lambda state: state.has_Boots(player) and state.has('Beat Agahnim 1', player)) set_rule(world.get_entrance('Bonk Rock Cave', player), lambda state: state.has_Boots(player)) set_rule(world.get_entrance('Desert Palace Stairs', player), lambda state: state.has('Book of Mudora', player)) From 8d5fc3051e18429bacda0752a9e7b0313f826b8f Mon Sep 17 00:00:00 2001 From: qadan Date: Sun, 9 Feb 2020 18:57:55 -0400 Subject: [PATCH 33/52] adding to inverted --- Rules.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Rules.py b/Rules.py index 2d38ba38..01f51820 100644 --- a/Rules.py +++ b/Rules.py @@ -738,6 +738,7 @@ def overworld_glitches_rules(world, player): add_rule(world.get_location(location, player), needs_boots_and_pearl if world.mode[player] != 'inverted' else needs_boots, 'or') # Boots-accessible regions. + boots_and_mirror = lambda state: state.has_Boots(player) and state.has_Mirror(player) if world.mode[player] != 'inverted': for boots_accessible_region in OWGSets.get_boots_accessible_regions_lw(): region = world.get_region(boots_accessible_region, player) @@ -754,7 +755,6 @@ def overworld_glitches_rules(world, player): edmb.can_reach_private = lambda state: edmb.can_reach(state) or can_bunny_dmd # Set up some mirror-accessible DW entrances. - boots_and_mirror = lambda state: state.has_Boots(player) and state.has_Mirror(player) for spot in world.get_region('West Dark World', player).exits + world.get_region('South Dark World', player).exits: if spot.name not in OWGSets.get_dw_bunny_inaccessible_locations(): add_rule(world.get_entrance(spot, player), boots_and_mirror, 'or') @@ -1433,7 +1433,7 @@ def set_inverted_bunny_rules(world, player): return lambda state: any(rule(state) for rule in options) def get_rule_to_add(region, location = None): - if not region.is_dark_world or not (world.logic[player] == 'owglitches' and location in bunny_accessible_locations and region.name not in invalid_mirror_bunny_entrances_lw): + if not region.is_dark_world and not (world.logic[player] == 'owglitches' and location in bunny_accessible_locations and region.name not in invalid_mirror_bunny_entrances_lw): return lambda state: state.has_Pearl(player) # in this case we are mixed region. # we collect possible options. @@ -1461,7 +1461,7 @@ def set_inverted_bunny_rules(world, player): if world.logic[player] == 'owglitches' and entrance.name not in OWGSets.get_invalid_mirror_bunny_entrances_lw(): for location in entrance.connected_region.locations: if location.name in OWGSets.get_superbunny_accessible_locations(): - possible_options.append(lambda state: state.can_reach(entrance) and all(rule(state) for rule in path) and state.has_Mirror(player)) + possible_options.append(lambda state: path_to_access_rule(new_path, entrance) and state.has_Mirror(player)) continue for exit in new_region.exits: if exit.name in dungeon_exits: @@ -1495,6 +1495,9 @@ def set_inverted_bunny_rules(world, player): if location.name in bunny_accessible_locations: continue + if world.logic[player] == 'owglitches' and location.parent_region.name not in OWGSets.get_invalid_mirror_bunny_entrances_lw() and location.name in OWGSets.get_superbunny_accessible_locations(): + add_rule(location, get_rule_to_add(location.parent_region, location.name)) + continue add_rule(location, get_rule_to_add(location.parent_region, location.name)) From ce9ccac4d319cc6c51ba2cc22ad687243f2f3704 Mon Sep 17 00:00:00 2001 From: qadan Date: Sun, 9 Feb 2020 19:30:04 -0400 Subject: [PATCH 34/52] forgetting about mirror DMD --- OWGSets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OWGSets.py b/OWGSets.py index cda65592..3cdd1fc8 100644 --- a/OWGSets.py +++ b/OWGSets.py @@ -146,6 +146,7 @@ def get_dmd_and_bunny_regions(): return [ 'West Dark World', 'South Dark World', + 'East Dark World', ] @@ -155,7 +156,6 @@ def get_dmd_non_bunny_regions(): ''' return [ 'Dark Desert', - 'East Dark World', 'Northeast Dark World', ] From ff3b879a0292162d81c9b7cf18d387d04e21a24d Mon Sep 17 00:00:00 2001 From: qadan Date: Mon, 10 Feb 2020 00:38:55 -0400 Subject: [PATCH 35/52] more idiomatic, bugfix too --- BaseClasses.py | 13 +++++++++++++ Rules.py | 23 ++++++++++------------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 01752a0b..0ed5798b 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -536,6 +536,19 @@ class CollectionState(object): def has_turtle_rock_medallion(self, player): return self.has(self.world.required_medallions[player][1], player) + def can_boots_clip_lw(self, player): + if self.world.mode[player] == 'inverted': + return self.has_Boots(player) and self.has_Pearl(player) + return self.has_Boots(player) + + def can_boots_clip_dw(self, player): + if self.world.mode[player] != 'inverted': + return self.has_Boots(player) and self.has_Pearl(player) + return self.has_Boots(player) + + def can_bunny_dmd(self, player): + return self.world.get_region('Death Mountain', player).can_reach(self) and self.has_Mirror(player) + def collect(self, item, event=False, location=None): if location: self.locations_checked.add(location) diff --git a/Rules.py b/Rules.py index 01f51820..e12a8f4d 100644 --- a/Rules.py +++ b/Rules.py @@ -726,33 +726,30 @@ def overworld_glitches_rules(world, player): set_rule(world.get_entrance(entrance, player), lambda state: True) # Boots-accessible locations. - needs_boots = lambda state: state.has_Boots(player) - needs_boots_and_pearl = lambda state: state.has_Boots(player) and state.has_Pearl(player) for entrance in OWGSets.get_lw_boots_accessible_entrances(world, player): - add_rule(world.get_entrance(entrance, player), needs_boots_and_pearl if world.mode[player] == 'inverted' else needs_boots, 'or') + add_rule(world.get_entrance(entrance, player), lambda state: state.can_boots_clip_lw(player), 'or') for location in OWGSets.get_lw_boots_accessible_locations(): - add_rule(world.get_location(location, player), needs_boots_and_pearl if world.mode[player] == 'inverted' else needs_boots, 'or') + add_rule(world.get_location(location, player), lambda state: state.can_boots_clip_lw(player), 'or') for entrance in OWGSets.get_dw_boots_accessible_entrances(world, player): - add_rule(world.get_entrance(entrance, player), needs_boots_and_pearl if world.mode[player] != 'inverted' else needs_boots, 'or') + add_rule(world.get_entrance(entrance, player), lambda state: state.can_boots_clip_dw(player), 'or') for location in OWGSets.get_dw_boots_accessible_locations(): - add_rule(world.get_location(location, player), needs_boots_and_pearl if world.mode[player] != 'inverted' else needs_boots, 'or') + add_rule(world.get_location(location, player), lambda state: state.can_boots_clip_dw(player), 'or') # Boots-accessible regions. boots_and_mirror = lambda state: state.has_Boots(player) and state.has_Mirror(player) if world.mode[player] != 'inverted': for boots_accessible_region in OWGSets.get_boots_accessible_regions_lw(): region = world.get_region(boots_accessible_region, player) - region.can_reach_private = lambda state: region.can_reach(state) or needs_boots + region.can_reach_private = lambda state: region.can_reach(state) or state.has_Boots(player) # DMD with and without bunny. - can_bunny_dmd = lambda state: world.get_region('Death Mountain', player).can_reach(state) and state.has_Mirror(player) for dmd_bunny_region in OWGSets.get_dmd_and_bunny_regions(): region = world.get_region(dmd_bunny_region, player) - region.can_reach_private = lambda state: region.can_reach(state) or (needs_boots_and_pearl or can_bunny_dmd) + region.can_reach_private = lambda state: region.can_reach(state) or (state.can_boots_clip_dw(player) or state.can_bunny_dmd(player)) for non_dmd_bunny_region in OWGSets.get_dmd_non_bunny_regions(): region = world.get_region(non_dmd_bunny_region, player) - region.can_reach_private = lambda state: region.can_reach(state) or (needs_boots_and_pearl) + region.can_reach_private = lambda state: region.can_reach(state) or state.can_boots_clip_dw(player) edmb = world.get_region('Dark Death Mountain (East Bottom)', player) - edmb.can_reach_private = lambda state: edmb.can_reach(state) or can_bunny_dmd + edmb.can_reach_private = lambda state: edmb.can_reach(state) or state.can_bunny_dmd(player) # Set up some mirror-accessible DW entrances. for spot in world.get_region('West Dark World', player).exits + world.get_region('South Dark World', player).exits: @@ -1333,7 +1330,7 @@ def set_inverted_big_bomb_rules(world, player): def set_bunny_rules(world, player): # If you can get to a dungeon exit, you can bunny revive. - dungeon_exits = ['Desert Palace Exit (South)', 'Desert Palace Exit (West)', 'Desert Palace Exit (East)', 'Desert Palace Exit (North)', 'Eastern Palace Exit', 'Tower of Hera Exit', 'Thieves Town Exit', 'Skull Woods Final Section Exit', 'Ice Palace Exit', 'Misery Mire Exit', 'Palace of Darkness Exit', 'Swamp Palace Exit', 'Agahnims Tower Exit', 'Turtle Rock Ledge Exit (East)', 'Turtle Rock Exit (Front)', 'Turtle Rock Ledge Exit (West)', 'Turtle Rock Isolated Ledge Exit'] + dungeon_exits = ['Desert Palace Exit (South)', 'Desert Palace Exit (West)', 'Desert Palace Exit (East)', 'Desert Palace Exit (North)', 'Eastern Palace Exit', 'Tower of Hera Exit', 'Thieves Town Exit', 'Skull Woods Final Section Exit', 'Misery Mire Exit', 'Palace of Darkness Exit', 'Swamp Palace Exit', 'Agahnims Tower Exit', 'Turtle Rock Ledge Exit (East)', 'Turtle Rock Exit (Front)', 'Turtle Rock Ledge Exit (West)', 'Turtle Rock Isolated Ledge Exit'] # regions for the exits of multi-entrace caves/drops that bunny cannot pass # Note spiral cave may be technically passible, but it would be too absurd to require since OHKO mode is a thing. bunny_impassable_caves = ['Bumper Cave', 'Two Brothers House', 'Hookshot Cave', 'Skull Woods First Section (Right)', 'Skull Woods First Section (Left)', 'Skull Woods First Section (Top)', 'Turtle Rock (Entrance)', 'Turtle Rock (Second Section)', 'Turtle Rock (Big Chest)', 'Skull Woods Second Section (Drop)', @@ -1419,7 +1416,7 @@ def set_bunny_rules(world, player): def set_inverted_bunny_rules(world, player): # If you can get to a dungeon exit, you can bunny revive. - dungeon_exits = ['Desert Palace Exit (South)', 'Desert Palace Exit (West)', 'Desert Palace Exit (East)', 'Desert Palace Exit (North)', 'Eastern Palace Exit', 'Tower of Hera Exit', 'Thieves Town Exit', 'Skull Woods Final Section Exit', 'Ice Palace Exit', 'Misery Mire Exit', 'Palace of Darkness Exit', 'Swamp Palace Exit', 'Inverted Agahnims Tower Exit', 'Turtle Rock Ledge Exit (East)', 'Turtle Rock Exit (Front)', 'Turtle Rock Ledge Exit (West)', 'Turtle Rock Isolated Ledge Exit'] + dungeon_exits = ['Desert Palace Exit (South)', 'Desert Palace Exit (West)', 'Desert Palace Exit (East)', 'Desert Palace Exit (North)', 'Eastern Palace Exit', 'Tower of Hera Exit', 'Thieves Town Exit', 'Skull Woods Final Section Exit', 'Ice Palace Exit', 'Misery Mire Exit', 'Palace of Darkness Exit', 'Inverted Agahnims Tower Exit', 'Turtle Rock Ledge Exit (East)', 'Turtle Rock Exit (Front)', 'Turtle Rock Ledge Exit (West)', 'Turtle Rock Isolated Ledge Exit'] # regions for the exits of multi-entrace caves/drops that bunny cannot pass # Note spiral cave may be technically passible, but it would be too absurd to require since OHKO mode is a thing. bunny_impassable_caves = ['Bumper Cave', 'Two Brothers House', 'Hookshot Cave', 'Skull Woods First Section (Right)', 'Skull Woods First Section (Left)', 'Skull Woods First Section (Top)', 'Turtle Rock (Entrance)', 'Turtle Rock (Second Section)', 'Turtle Rock (Big Chest)', 'Skull Woods Second Section (Drop)', From 3ba3fcf2db9350f7699afa87f9481045ee27f523 Mon Sep 17 00:00:00 2001 From: qadan Date: Mon, 10 Feb 2020 01:02:27 -0400 Subject: [PATCH 36/52] dm room chest moved to global. ensuring base rules for owg --- Rules.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Rules.py b/Rules.py index e12a8f4d..38a8af61 100644 --- a/Rules.py +++ b/Rules.py @@ -41,6 +41,9 @@ def set_rules(world, player): no_glitches_rules(world, player) elif world.logic[player] == 'owglitches': logging.getLogger('').info('There is a chance OWG has bugged edge case rulesets, especially in inverted. Definitely file a report on GitHub if you see anything strange.') + # Initially setting no_glitches_rules to set the baseline rules for some + # entrances. The overworld_glitches_rules set is primarily additive. + no_glitches_rules(world, player) overworld_glitches_rules(world, player) elif world.logic[player] == 'minorglitches': logging.getLogger('').info('Minor Glitches may be buggy still. No guarantee for proper logic checks.') @@ -298,8 +301,11 @@ def global_rules(world, player): set_rule(world.get_location('Ganons Tower - Bob\'s Torch', player), lambda state: state.has_Boots(player)) set_rule(world.get_entrance('Ganons Tower (Tile Room)', player), lambda state: state.has('Cane of Somaria', player)) - set_rule(world.get_entrance('Ganons Tower (Hookshot Room)', player), lambda state: state.has('Hammer', player)) + set_rule(world.get_entrance('Ganons Tower (Hookshot Room)', player), lambda state: state.has('Hammer', player) and (state.has('Hookshot', player) or state.has_Boots(player))) + DMs_room_chests = ['Ganons Tower - DMs Room - Top Left', 'Ganons Tower - DMs Room - Top Right', 'Ganons Tower - DMs Room - Bottom Left', 'Ganons Tower - DMs Room - Bottom Right'] + for location in DMs_room_chests: + add_rule(world.get_location(location, player), lambda state: state.has('Hookshot', player)) set_rule(world.get_entrance('Ganons Tower (Map Room)', player), lambda state: state.has_key('Small Key (Ganons Tower)', player, 4) or (item_name(state, 'Ganons Tower - Map Chest', player) in [('Big Key (Ganons Tower)', player), ('Small Key (Ganons Tower)', player)] and state.has_key('Small Key (Ganons Tower)', player, 3))) if world.accessibility[player] != 'locations': set_always_allow(world.get_location('Ganons Tower - Map Chest', player), lambda state, item: item.name == 'Small Key (Ganons Tower)' and item.player == player and state.has_key('Small Key (Ganons Tower)', player, 3)) @@ -639,11 +645,7 @@ def no_glitches_rules(world, player): set_rule(world.get_entrance('Dark Lake Hylia Ledge Drop', player), lambda state: state.has('Flippers', player)) set_rule(world.get_entrance('East Dark World Pier', player), lambda state: state.has('Flippers', player)) - add_rule(world.get_entrance('Ganons Tower (Hookshot Room)', player), lambda state: state.has('Hookshot', player) or state.has_Boots(player)) add_rule(world.get_entrance('Ganons Tower (Double Switch Room)', player), lambda state: state.has('Hookshot', player)) - DMs_room_chests = ['Ganons Tower - DMs Room - Top Left', 'Ganons Tower - DMs Room - Top Right', 'Ganons Tower - DMs Room - Bottom Left', 'Ganons Tower - DMs Room - Bottom Right'] - for location in DMs_room_chests: - add_rule(world.get_location(location, player), lambda state: state.has('Hookshot', player)) set_rule(world.get_entrance('Paradox Cave Push Block Reverse', player), lambda state: False) # no glitches does not require block override set_rule(world.get_entrance('Paradox Cave Bomb Jump', player), lambda state: False) set_rule(world.get_entrance('Skull Woods First Section Bomb Jump', player), lambda state: False) From 8db19e544ea105b299e957948e4aed14f8902f1b Mon Sep 17 00:00:00 2001 From: qadan Date: Mon, 10 Feb 2020 09:55:06 -0400 Subject: [PATCH 37/52] bomb jump rules, don't redo lamp rules --- Rules.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Rules.py b/Rules.py index 38a8af61..d625bd7b 100644 --- a/Rules.py +++ b/Rules.py @@ -302,10 +302,6 @@ def global_rules(world, player): set_rule(world.get_location('Ganons Tower - Bob\'s Torch', player), lambda state: state.has_Boots(player)) set_rule(world.get_entrance('Ganons Tower (Tile Room)', player), lambda state: state.has('Cane of Somaria', player)) set_rule(world.get_entrance('Ganons Tower (Hookshot Room)', player), lambda state: state.has('Hammer', player) and (state.has('Hookshot', player) or state.has_Boots(player))) - - DMs_room_chests = ['Ganons Tower - DMs Room - Top Left', 'Ganons Tower - DMs Room - Top Right', 'Ganons Tower - DMs Room - Bottom Left', 'Ganons Tower - DMs Room - Bottom Right'] - for location in DMs_room_chests: - add_rule(world.get_location(location, player), lambda state: state.has('Hookshot', player)) set_rule(world.get_entrance('Ganons Tower (Map Room)', player), lambda state: state.has_key('Small Key (Ganons Tower)', player, 4) or (item_name(state, 'Ganons Tower - Map Chest', player) in [('Big Key (Ganons Tower)', player), ('Small Key (Ganons Tower)', player)] and state.has_key('Small Key (Ganons Tower)', player, 3))) if world.accessibility[player] != 'locations': set_always_allow(world.get_location('Ganons Tower - Map Chest', player), lambda state, item: item.name == 'Small Key (Ganons Tower)' and item.player == player and state.has_key('Small Key (Ganons Tower)', player, 3)) @@ -647,9 +643,16 @@ def no_glitches_rules(world, player): add_rule(world.get_entrance('Ganons Tower (Double Switch Room)', player), lambda state: state.has('Hookshot', player)) set_rule(world.get_entrance('Paradox Cave Push Block Reverse', player), lambda state: False) # no glitches does not require block override + forbid_bomb_jump_requirements(world, player) + add_conditional_lamps(world, player) + + +def forbid_bomb_jump_requirements(world, player): + DMs_room_chests = ['Ganons Tower - DMs Room - Top Left', 'Ganons Tower - DMs Room - Top Right', 'Ganons Tower - DMs Room - Bottom Left', 'Ganons Tower - DMs Room - Bottom Right'] + for location in DMs_room_chests: + add_rule(world.get_location(location, player), lambda state: state.has('Hookshot', player)) set_rule(world.get_entrance('Paradox Cave Bomb Jump', player), lambda state: False) set_rule(world.get_entrance('Skull Woods First Section Bomb Jump', player), lambda state: False) - add_conditional_lamps(world, player) DW_Entrances = ['Bumper Cave (Bottom)', @@ -787,9 +790,6 @@ def overworld_glitches_rules(world, player): else: add_rule(world.get_entrance('South Dark World Teleporter', player), lambda state: state.has_Boots(player) and state.can_lift_rocks(player), 'or') - # Add darkness conditions. - add_conditional_lamps(world, player) - def open_rules(world, player): # softlock protection as you can reach the sewers small key door with a guard drop key From 2b44792f70a5a92eb2e834d276a545e0af4252c2 Mon Sep 17 00:00:00 2001 From: qadan Date: Mon, 10 Feb 2020 16:54:09 -0400 Subject: [PATCH 38/52] better seed gen stuff --- Fill.py | 2 +- ItemList.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Fill.py b/Fill.py index 811df900..df533c5e 100644 --- a/Fill.py +++ b/Fill.py @@ -227,7 +227,7 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None # fill in gtower locations with trash first for player in range(1, world.players + 1): - if not gftower_trash or not world.ganonstower_vanilla[player]: + if not gftower_trash or not world.ganonstower_vanilla[player] or world.logic[player] == 'owglitches': continue gftower_trash_count = (random.randint(15, 50) if world.goal[player] == 'triforcehunt' else random.randint(0, 15)) diff --git a/ItemList.py b/ItemList.py index aa4eedae..6c2ecf15 100644 --- a/ItemList.py +++ b/ItemList.py @@ -398,6 +398,7 @@ def get_pool_core(progressive, shuffle, difficulty, timer, goal, mode, swords, r if logic in ['owglitches', 'nologic']: precollected_items.append('Pegasus Boots') pool.remove('Pegasus Boots') + pool.extend(['Rupees (20)']) if want_progressives(): pool.extend(progressivegloves) From aa569d1c3d4ddb93074101f139bc93582ad2800c Mon Sep 17 00:00:00 2001 From: qadan Date: Mon, 10 Feb 2020 23:54:35 -0400 Subject: [PATCH 39/52] rework as region connectors (inverted will be broken) --- BaseClasses.py | 13 +- ER_hint_reference.txt | 716 +++++++++++++++++++++--------------------- EntranceShuffle.py | 36 ++- OWGSets.py | 244 ++++---------- Regions.py | 32 +- Rules.py | 79 +++-- 6 files changed, 528 insertions(+), 592 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 0ed5798b..4d80b0ed 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -546,8 +546,17 @@ class CollectionState(object): return self.has_Boots(player) and self.has_Pearl(player) return self.has_Boots(player) - def can_bunny_dmd(self, player): - return self.world.get_region('Death Mountain', player).can_reach(self) and self.has_Mirror(player) + def can_get_glitched_speed_lw(self, player): + rules = [self.has_Boots(player), any([self.has('Hookshot', player), self.has_sword(player)])] + if self.world.mode[player] == 'inverted': + rules.append(self.has_Pearl(player)) + return all(rules) + + def can_get_glitched_speed_dw(self, player): + rules = [self.has_Boots(player), any([self.has('Hookshot', player), self.has_sword(player)])] + if self.world.mode[player] != 'inverted': + rules.append(self.has_Pearl(player)) + return all(rules) def collect(self, item, event=False, location=None): if location: diff --git a/ER_hint_reference.txt b/ER_hint_reference.txt index da45c78f..999fb436 100644 --- a/ER_hint_reference.txt +++ b/ER_hint_reference.txt @@ -1,359 +1,359 @@ -Hint description: - -Hints will appear in the following ratios across the 15 telepathic tiles that have hints and the five storyteller locations: - -4 hints for inconvenient entrances. -4 hints for random entrances (this can by coincidence pick inconvenient entrances that aren't used for the first set of hints). -3 hints for inconvenient item locations. -5 hints for valuable items. -4 junk hints. - -In the vanilla, dungeonssimple, and dungeonsfull shuffles, the following ratios will be used instead: - -5 hints for inconvenient item locations. -8 hints for valuable items. -7 junk hints. - -In the simple, restricted, and restricted legacy shuffles, these are the ratios: - -2 hints for inconvenient entrances. -1 hint for an inconvenient dungeon entrance. -4 hints for random entrances (this can by coincidence pick inconvenient entrances that aren't used for the first set of hints). -3 hints for inconvenient item locations. -5 hints for valuable items. -5 junk hints. - -These hints will use the following format: - -Entrance hints go "[Entrance on overworld] leads to [interior]". - -Inconvenient item locations are a little more custom but amount to "[Location] has [item name]". The item name is literal and will specify which dungeon the dungeon specific items hail from (small key/big key/map/compass). - -The valuable items are of the format "[item name] can be found [location]". The item name is again literal, and the location text is taken from Ganon's silver arrow hints. Note that the way it works is that every unique valuable item that exists is considered independently, and you won't get multiple hints for the EXACT same item (so you can only get one hint for Progressive Sword no matter how many swords exist in the seed, but if swords are not progressive, you could get hints for both Master Sword and Tempered Sword). More copies of an item existing does not increase the probability of getting a hint for that particular item (you are equally likely to get a hint for a Progressive Sword as for the Hammer). Unlike the IR, item names are never obfuscated by "something unique", and there is no special bias for hints for GT Big Key or Pegasus Boots. - -Hint Locations: - -Eastern Palace room before Big Chest -Desert Palace bonk torch room -Tower of Hera entrance room -Tower of Hera Big Chest room -Castle Tower after dark rooms -Palace of Darkness before Bow section -Swamp Palace entryway -Thieves' Town upstairs -Ice Palace entrance -Ice Palace after first drop -Ice Palace tall ice floor room -Misery Mire cutscene room -Turtle Rock entrance -Spectacle Rock cave -Spiky Hint cave -PoD Bdlg NPC -Near PoD Storyteller (bug near bomb wall) -Dark Sanctuary Storyteller (long room with tables) -Near Mire Storyteller (feather duster in winding cave) -SE DW Storyteller (owl in winding cave) - -Inconvenient entrance list: - -Skull Woods Final -Ice Palace -Misery Mire -Turtle Rock -Ganon's Tower -Mimic Ledge -SW DM Foothills Cave (mirror from upper Bumper ledge) -Hammer Pegs (near purple chest) -Super Bomb cracked wall - -Inconvenient location list: - -Swamp left (two chests) -Mire left (two chests) -Hera basement -Eastern Palace Big Key chest (protected by anti-fairies) -Thieves' Town Big Chest -Ice Palace Big Chest -Ganon's Tower Big Chest -Purple Chest -Spike Cave -Magic Bat -Sahasrahla (Green Pendant) - -In the vanilla, dungeonssimple, and dungeonsfull shuffles, the following two locations are added to the inconvenient locations list: - -Graveyard Cave -Mimic Cave - -Valuable Items are simply all items that are shown on the pause subscreen (Y, B, or A sections) minus Silver Arrows and plus Triforce Pieces, Magic Upgrades (1/2 or 1/4), and the Single Arrow. If key shuffle is being used, you can additionally get hints for Small Keys or Big Keys but not hints for Maps or Compasses. - -While the exact verbage of location names and item names can be found in the source code, here's a copy for reference: - -Overworld Entrance naming: - -Turtle Rock: Turtle Rock Main -Misery Mire: Misery Mire -Ice Palace: Ice Palace -Skull Woods Final Section: The back of Skull Woods -Death Mountain Return Cave (West): The SW DM Foothills Cave -Mimic Cave: Mimic Ledge -Dark World Hammer Peg Cave: The rows of pegs -Pyramid Fairy: The crack on the pyramid -Eastern Palace: Eastern Palace -Elder House (East): Elder House -Elder House (West): Elder House -Two Brothers House (East): Eastern Quarreling Brothers' house -Old Man Cave (West): The lower DM entrance -Hyrule Castle Entrance (South): The ground level castle door -Thieves Town: Thieves' Town -Bumper Cave (Bottom): The lower Bumper Cave -Swamp Palace: Swamp Palace -Dark Death Mountain Ledge (West): The East dark DM connector ledge -Dark Death Mountain Ledge (East): The East dark DM connector ledge -Superbunny Cave (Top): The summit of dark DM cave -Superbunny Cave (Bottom): The base of east dark DM -Hookshot Cave: The rock on dark DM -Desert Palace Entrance (South): The book sealed passage -Tower of Hera: The Tower of Hera -Two Brothers House (West): The door near the race game -Old Man Cave (East): The SW-most cave on west DM -Old Man House (Bottom): A cave with a door on west DM -Old Man House (Top): The eastmost cave on west DM -Death Mountain Return Cave (East): The westmost cave on west DM -Spectacle Rock Cave Peak: The highest cave on west DM -Spectacle Rock Cave: The right ledge on west DM -Spectacle Rock Cave (Bottom): The left ledge on west DM -Paradox Cave (Bottom): The right paired cave on east DM -Paradox Cave (Middle): The southmost cave on east DM -Paradox Cave (Top): The east DM summit cave -Fairy Ascension Cave (Bottom): The east DM cave behind rocks -Fairy Ascension Cave (Top): The central ledge on east DM -Spiral Cave: The left ledge on east DM -Spiral Cave (Bottom): The SWmost cave on east DM -Palace of Darkness: Palace of Darkness -Hyrule Castle Entrance (West): The left castle door -Hyrule Castle Entrance (East): The right castle door -Agahnims Tower: The sealed castle door -Desert Palace Entrance (West): The westmost building in the desert -Desert Palace Entrance (North): The northmost cave in the desert -Blinds Hideout: Blind's old house -Lake Hylia Fairy: A cave NE of Lake Hylia -Light Hype Fairy: The cave south of your house -Desert Fairy: The cave near the desert -Chicken House: The chicken lady's house -Aginahs Cave: The open desert cave -Sahasrahlas Hut: The house near armos -Cave Shop (Lake Hylia): The cave NW Lake Hylia -Blacksmiths Hut: The old smithery -Sick Kids House: The central house in Kakariko -Lost Woods Gamble: A tree trunk door -Fortune Teller (Light): A building NE of Kakariko -Snitch Lady (East): A house guarded by a snitch -Snitch Lady (West): A house guarded by a snitch -Bush Covered House: A house with an uncut lawn -Tavern (Front): A building with a backdoor -Light World Bomb Hut: A Kakariko building with no door -Kakariko Shop: The old Kakariko shop -Mini Moldorm Cave: The cave south of Lake Hylia -Long Fairy Cave: The eastmost portal cave -Good Bee Cave: The open cave SE Lake Hylia -20 Rupee Cave: The rock SE Lake Hylia -50 Rupee Cave: The rock near the desert -Ice Rod Cave: The sealed cave SE Lake Hylia -Library: The old library -Potion Shop: The witch's building -Dam: The old dam -Lumberjack House: The lumberjack house -Lake Hylia Fortune Teller: The building NW Lake Hylia -Kakariko Gamble Game: The old Kakariko gambling den -Waterfall of Wishing: Going behind the waterfall -Capacity Upgrade: The cave on the island -Bonk Rock Cave: The rock pile near Sanctuary -Graveyard Cave: The graveyard ledge -Checkerboard Cave: The NE desert ledge -Cave 45: The ledge south of haunted grove -Kings Grave: The northeastmost grave -Bonk Fairy (Light): The rock pile near your home -Hookshot Fairy: A cave on east DM -Bonk Fairy (Dark): The rock pile near the old bomb shop -Dark Sanctuary Hint: The dark sanctuary cave -Dark Lake Hylia Fairy: The cave NE dark Lake Hylia -C-Shaped House: The NE house in Village of Outcasts -Big Bomb Shop: The old bomb shop -Dark Death Mountain Fairy: The SW cave on dark DM -Dark Lake Hylia Shop: The building NW dark Lake Hylia -Dark World Shop: The hammer sealed building -Red Shield Shop: The fenced in building -Mire Shed: The western hut in the mire -East Dark World Hint: The dark cave near the eastmost portal -Dark Desert Hint: The cave east of the mire -Spike Cave: The ledge cave on west dark DM -Palace of Darkness Hint: The building south of Kiki -Dark Lake Hylia Ledge Spike Cave: The rock SE dark Lake Hylia -Cave Shop (Dark Death Mountain): The base of east dark DM -Dark World Potion Shop: The building near the catfish -Archery Game: The old archery game -Dark World Lumberjack Shop: The northmost Dark World building -Hype Cave: The cave south of the old bomb shop -Brewery: The Village of Outcasts building with no door -Dark Lake Hylia Ledge Hint: The open cave SE dark Lake Hylia -Chest Game: The westmost building in the Village of Outcasts -Dark Desert Fairy: The eastern hut in the mire -Dark Lake Hylia Ledge Fairy: The sealed cave SE dark Lake Hylia -Fortune Teller (Dark): The building NE the Village of Outcasts -Sanctuary: Sanctuary -Lumberjack Tree Cave: The cave Behind Lumberjacks -Lost Woods Hideout Stump: The stump in Lost Woods -North Fairy Cave: The cave East of Graveyard -Bat Cave Cave: The cave in eastern Kakariko -Kakariko Well Cave: The cave in northern Kakariko -Hyrule Castle Secret Entrance Stairs: The tunnel near the castle -Skull Woods First Section Door: The southeastmost skull -Skull Woods Second Section Door (East): The central open skull -Skull Woods Second Section Door (West): The westmost open skull -Desert Palace Entrance (East): The eastern building in the desert -Turtle Rock Isolated Ledge Entrance: The isolated ledge on east dark DM -Bumper Cave (Top): The upper Bumper Cave -Hookshot Cave Back Entrance: The stairs on the floating island - -Destination Entrance Naming: - -Hyrule Castle: Hyrule Castle (all three entrances) -Eastern Palace: Eastern Palace -Desert Palace: Desert Palace (all four entrances, including final) -Tower of Hera: Tower of Hera -Palace of Darkness: Palace of Darkness -Swamp Palace: Swamp Palace -Skull Woods: Skull Woods (any entrance including final) -Thieves' Town: Thieves' Town -Ice Palace: Ice Palace -Misery Mire: Misery Mire -Turtle Rock: Turtle Rock (all four entrances) -Ganon's Tower: Ganon's Tower -Castle Tower: Agahnim's Tower -A connector: Paradox Cave, Spectacle Rock Cave, Hookshot Cave, Superbunny Cave, Spiral Cave, Old Man Fetch Cave, Old Man House, Elder House, Quarreling Brothers' House, Bumper Cave, DM Fairy Ascent Cave, DM Exit Cave -A bounty of five items: Mini-moldorm cave, Hype Cave, Blind's Hideout -Sahasrahla: Sahasrahla -A cave with two items: Mire hut, Waterfall Fairy, Pyramid Fairy -A fairy fountain: Any healer fairy cave, either bonk cave with four fairies, the "long fairy" cave -A common shop: Any shop that sells bombs by default -The rare shop: The shop that sells the Red Shield by default -The potion shop: Potion Shop -The bomb shop: Bomb Shop -A fortune teller: Any of the three fortune tellers -A house with a chest: Chicken Lady's house, C-House, Brewery -A cave with an item: Checkerboard cave, Hammer Pegs cave, Cave 45, Graveyard Ledge cave -A cave with a chest: Sanc Bonk Rock Cave, Cape Grave Cave, Ice Rod Cave, Aginah's Cave -The dam: Watergate -The sick kid: Sick Kid -The library: Library -Mimic Cave: Mimic Cave -Spike Cave: Spike Cave -A game of 16 chests: VoO chest game (for the item) -A storyteller: The four DW NPCs who charge 20 rupees for a hint as well as the PoD Bdlg guy who gives a free hint -A cave with some cash: 20 rupee cave, 50 rupee cave (both have thieves and some pots) -A game of chance: Gambling game (just for cash, no items) -A game of skill: Archery minigame -The queen of fairies: Capacity Upgrade Fairy -A drop's exit: Sanctuary, LW Thieves' Hideout, Kakariko Well, Magic Bat, Useless Fairy, Uncle Tunnel, Ganon drop exit -A restock room: The Kakariko bomb/arrow restock room -The tavern: The Kakariko tavern -The grass man: The Kakariko man with many beds -A cold bee: The "wrong side" of Ice Rod cave where you can get a Good Bee -Fairies deep in a cave: Hookshot Fairy - -Location naming reference: - -Mushroom: in the woods -Master Sword Pedestal: at the pedestal -Bottle Merchant: with a merchant -Stumpy: with tree boy -Flute Spot: underground -Digging Game: underground -Lake Hylia Island: on an island -Floating Island: on an island -Bumper Cave Ledge: on a ledge -Spectacle Rock: atop a rock -Maze Race: at the race -Desert Ledge: in the desert -Pyramid: on the pyramid -Catfish: with a catfish -Ether Tablet: at a monument -Bombos Tablet: at a monument -Hobo: with the hobo -Zora's Ledge: near Zora -King Zora: at a high price -Sunken Treasure: underwater -Floodgate Chest: in the dam -Blacksmith: with the smith -Purple Chest: from a box -Old Man: with the old man -Link's Uncle: with your uncle -Secret Passage: near your uncle -Kakariko Well (5 items): in a well -Lost Woods Hideout: near a thief -Lumberjack Tree: in a hole -Magic Bat: with the bat -Paradox Cave (7 items): in a cave with seven chests -Blind's Hideout (5 items): in a basement -Mini Moldorm Cave (5 items): near Moldorms -Hype Cave (4 back chests): near a bat-like man -Hype Cave - Generous Guy: with a bat-like man -Hookshot Cave (4 items): across pits -Sahasrahla's Hut (chests in back): near the elder -Sahasrahla: with the elder -Waterfall Fairy (2 items): near a fairy -Pyramid Fairy (2 items): near a fairy -Mire Shed (2 items): near sparks -Superbunny Cave (2 items): in a connection -Spiral Cave: in spiral cave -Kakariko Tavern: in the bar -Link's House: in your home -Sick Kid: with the sick -Library: near books -Potion Shop: near potions -Spike Cave: beyond spikes -Mimic Cave: in a cave of mimicry -Chest Game: as a prize -Chicken House: near poultry -Aginah's Cave: with Aginah -Ice Rod Cave: in a frozen cave -Brewery: alone in a home -C-Shaped House: alone in a home -Spectacle Rock Cave: alone in a cave -King's Tomb: alone in a cave -Cave 45: alone in a cave -Graveyard Cave: alone in a cave -Checkerboard Cave: alone in a cave -Bonk Rock Cave: alone in a cave -Peg Cave: alone in a cave -Sanctuary: in Sanctuary -Hyrule Castle - Boomerang Chest: in Hyrule Castle -Hyrule Castle - Map Chest: in Hyrule Castle -Hyrule Castle - Zelda's Chest: in Hyrule Castle -Sewers - Dark Cross: in the sewers -Sewers - Secret Room (3 items): in the sewers -Eastern Palace - Boss: with the Armos -Eastern Palace (otherwise, 5 items): in Eastern Palace -Desert Palace - Boss: with Lanmolas -Desert Palace (otherwise, 5 items): in Desert Palace -Tower of Hera - Boss: with Moldorm -Tower of Hera (otherwise, 5 items): in Tower of Hera -Castle Tower (2 items): in Castle Tower -Palace of Darkness - Boss: with Helmasaur King -Palace of Darkness (otherwise, 13 items): in Palace of Darkness -Swamp Palace - Boss: with Arrghus -Swamp Palace (otherwise, 9 items): in Swamp Palace -Skull Woods - Bridge Room: near Mothula -Skull Woods - Boss: with Mothula -Skull Woods (otherwise, 6 items): in Skull Woods -Thieves' Town - Boss: with Blind -Thieves' Town (otherwise, 7 items): in Thieves' Town -Ice Palace - Boss: with Kholdstare -Ice Palace (otherwise, 7 items): in Ice Palace -Misery Mire - Boss: with Vitreous -Misery Mire (otherwise, 7 items): in Misery Mire -Turtle Rock - Boss: with Trinexx -Turtle Rock (otherwise, 11 items): in Turtle Rock -Ganons Tower (after climb, 4 items): atop Ganon's Tower +Hint description: + +Hints will appear in the following ratios across the 15 telepathic tiles that have hints and the five storyteller locations: + +4 hints for inconvenient entrances. +4 hints for random entrances (this can by coincidence pick inconvenient entrances that aren't used for the first set of hints). +3 hints for inconvenient item locations. +5 hints for valuable items. +4 junk hints. + +In the vanilla, dungeonssimple, and dungeonsfull shuffles, the following ratios will be used instead: + +5 hints for inconvenient item locations. +8 hints for valuable items. +7 junk hints. + +In the simple, restricted, and restricted legacy shuffles, these are the ratios: + +2 hints for inconvenient entrances. +1 hint for an inconvenient dungeon entrance. +4 hints for random entrances (this can by coincidence pick inconvenient entrances that aren't used for the first set of hints). +3 hints for inconvenient item locations. +5 hints for valuable items. +5 junk hints. + +These hints will use the following format: + +Entrance hints go "[Entrance on overworld] leads to [interior]". + +Inconvenient item locations are a little more custom but amount to "[Location] has [item name]". The item name is literal and will specify which dungeon the dungeon specific items hail from (small key/big key/map/compass). + +The valuable items are of the format "[item name] can be found [location]". The item name is again literal, and the location text is taken from Ganon's silver arrow hints. Note that the way it works is that every unique valuable item that exists is considered independently, and you won't get multiple hints for the EXACT same item (so you can only get one hint for Progressive Sword no matter how many swords exist in the seed, but if swords are not progressive, you could get hints for both Master Sword and Tempered Sword). More copies of an item existing does not increase the probability of getting a hint for that particular item (you are equally likely to get a hint for a Progressive Sword as for the Hammer). Unlike the IR, item names are never obfuscated by "something unique", and there is no special bias for hints for GT Big Key or Pegasus Boots. + +Hint Locations: + +Eastern Palace room before Big Chest +Desert Palace bonk torch room +Tower of Hera entrance room +Tower of Hera Big Chest room +Castle Tower after dark rooms +Palace of Darkness before Bow section +Swamp Palace entryway +Thieves' Town upstairs +Ice Palace entrance +Ice Palace after first drop +Ice Palace tall ice floor room +Misery Mire cutscene room +Turtle Rock entrance +Spectacle Rock cave +Spiky Hint cave +PoD Bdlg NPC +Near PoD Storyteller (bug near bomb wall) +Dark Sanctuary Storyteller (long room with tables) +Near Mire Storyteller (feather duster in winding cave) +SE DW Storyteller (owl in winding cave) + +Inconvenient entrance list: + +Skull Woods Final +Ice Palace +Misery Mire +Turtle Rock +Ganon's Tower +Mimic Ledge +SW DM Foothills Cave (mirror from upper Bumper ledge) +Hammer Pegs (near purple chest) +Super Bomb cracked wall + +Inconvenient location list: + +Swamp left (two chests) +Mire left (two chests) +Hera basement +Eastern Palace Big Key chest (protected by anti-fairies) +Thieves' Town Big Chest +Ice Palace Big Chest +Ganon's Tower Big Chest +Purple Chest +Spike Cave +Magic Bat +Sahasrahla (Green Pendant) + +In the vanilla, dungeonssimple, and dungeonsfull shuffles, the following two locations are added to the inconvenient locations list: + +Graveyard Cave +Mimic Cave + +Valuable Items are simply all items that are shown on the pause subscreen (Y, B, or A sections) minus Silver Arrows and plus Triforce Pieces, Magic Upgrades (1/2 or 1/4), and the Single Arrow. If key shuffle is being used, you can additionally get hints for Small Keys or Big Keys but not hints for Maps or Compasses. + +While the exact verbage of location names and item names can be found in the source code, here's a copy for reference: + +Overworld Entrance naming: + +Turtle Rock: Turtle Rock Main +Misery Mire: Misery Mire +Ice Palace: Ice Palace +Skull Woods Final Section: The back of Skull Woods +Death Mountain Return Cave (West): The SW DM Foothills Cave +Mimic Cave: Mimic Ledge +Dark World Hammer Peg Cave: The rows of pegs +Pyramid Fairy: The crack on the pyramid +Eastern Palace: Eastern Palace +Elder House (East): Elder House +Elder House (West): Elder House +Two Brothers House (East): Eastern Quarreling Brothers' house +Old Man Cave (West): The lower DM entrance +Hyrule Castle Entrance (South): The ground level castle door +Thieves Town: Thieves' Town +Bumper Cave (Bottom): The lower Bumper Cave +Swamp Palace: Swamp Palace +Dark Death Mountain Ledge (West): The East dark DM connector ledge +Dark Death Mountain Ledge (East): The East dark DM connector ledge +Superbunny Cave (Top): The summit of dark DM cave +Superbunny Cave (Bottom): The base of east dark DM +Hookshot Cave: The rock on dark DM +Desert Palace Entrance (South): The book sealed passage +Tower of Hera: The Tower of Hera +Two Brothers House (West): The door near the race game +Old Man Cave (East): The SW-most cave on west DM +Old Man House (Bottom): A cave with a door on west DM +Old Man House (Top): The eastmost cave on west DM +Death Mountain Return Cave (East): The westmost cave on west DM +Spectacle Rock Cave Peak: The highest cave on west DM +Spectacle Rock Cave: The right ledge on west DM +Spectacle Rock Cave (Bottom): The left ledge on west DM +Paradox Cave (Bottom): The right paired cave on east DM +Paradox Cave (Middle): The southmost cave on east DM +Paradox Cave (Top): The east DM summit cave +Fairy Ascension Cave (Bottom): The east DM cave behind rocks +Fairy Ascension Cave (Top): The central ledge on east DM +Spiral Cave: The left ledge on east DM +Spiral Cave (Bottom): The SWmost cave on east DM +Palace of Darkness: Palace of Darkness +Hyrule Castle Entrance (West): The left castle door +Hyrule Castle Entrance (East): The right castle door +Agahnims Tower: The sealed castle door +Desert Palace Entrance (West): The westmost building in the desert +Desert Palace Entrance (North): The northmost cave in the desert +Blinds Hideout: Blind's old house +Lake Hylia Fairy: A cave NE of Lake Hylia +Light Hype Fairy: The cave south of your house +Desert Fairy: The cave near the desert +Chicken House: The chicken lady's house +Aginahs Cave: The open desert cave +Sahasrahlas Hut: The house near armos +Cave Shop (Lake Hylia): The cave NW Lake Hylia +Blacksmiths Hut: The old smithery +Sick Kids House: The central house in Kakariko +Lost Woods Gamble: A tree trunk door +Fortune Teller (Light): A building NE of Kakariko +Snitch Lady (East): A house guarded by a snitch +Snitch Lady (West): A house guarded by a snitch +Bush Covered House: A house with an uncut lawn +Tavern (Front): A building with a backdoor +Light World Bomb Hut: A Kakariko building with no door +Kakariko Shop: The old Kakariko shop +Mini Moldorm Cave: The cave south of Lake Hylia +Long Fairy Cave: The eastmost portal cave +Good Bee Cave: The open cave SE Lake Hylia +20 Rupee Cave: The rock SE Lake Hylia +50 Rupee Cave: The rock near the desert +Ice Rod Cave: The sealed cave SE Lake Hylia +Library: The old library +Potion Shop: The witch's building +Dam: The old dam +Lumberjack House: The lumberjack house +Lake Hylia Fortune Teller: The building NW Lake Hylia +Kakariko Gamble Game: The old Kakariko gambling den +Waterfall of Wishing: Going behind the waterfall +Capacity Upgrade: The cave on the island +Bonk Rock Cave: The rock pile near Sanctuary +Graveyard Cave: The graveyard ledge +Checkerboard Cave: The NE desert ledge +Cave 45: The ledge south of haunted grove +Kings Grave: The northeastmost grave +Bonk Fairy (Light): The rock pile near your home +Hookshot Fairy: A cave on east DM +Bonk Fairy (Dark): The rock pile near the old bomb shop +Dark Sanctuary Hint: The dark sanctuary cave +Dark Lake Hylia Fairy: The cave NE dark Lake Hylia +C-Shaped House: The NE house in Village of Outcasts +Big Bomb Shop: The old bomb shop +Dark Death Mountain Fairy: The SW cave on dark DM +Dark Lake Hylia Shop: The building NW dark Lake Hylia +Dark World Shop: The hammer sealed building +Red Shield Shop: The fenced in building +Mire Shed: The western hut in the mire +East Dark World Hint: The dark cave near the eastmost portal +Dark Desert Hint: The cave east of the mire +Spike Cave: The ledge cave on west dark DM +Palace of Darkness Hint: The building south of Kiki +Dark Lake Hylia Ledge Spike Cave: The rock SE dark Lake Hylia +Cave Shop (Dark Death Mountain): The base of east dark DM +Dark World Potion Shop: The building near the catfish +Archery Game: The old archery game +Dark World Lumberjack Shop: The northmost Dark World building +Hype Cave: The cave south of the old bomb shop +Brewery: The Village of Outcasts building with no door +Dark Lake Hylia Ledge Hint: The open cave SE dark Lake Hylia +Chest Game: The westmost building in the Village of Outcasts +Dark Desert Fairy: The eastern hut in the mire +Dark Lake Hylia Ledge Fairy: The sealed cave SE dark Lake Hylia +Fortune Teller (Dark): The building NE the Village of Outcasts +Sanctuary: Sanctuary +Lumberjack Tree Cave: The cave Behind Lumberjacks +Lost Woods Hideout Stump: The stump in Lost Woods +North Fairy Cave: The cave East of Graveyard +Bat Cave Cave: The cave in eastern Kakariko +Kakariko Well Cave: The cave in northern Kakariko +Hyrule Castle Secret Entrance Stairs: The tunnel near the castle +Skull Woods First Section Door: The southeastmost skull +Skull Woods Second Section Door (East): The central open skull +Skull Woods Second Section Door (West): The westmost open skull +Desert Palace Entrance (East): The eastern building in the desert +Turtle Rock Isolated Ledge Entrance: The isolated ledge on east dark DM +Bumper Cave (Top): The upper Bumper Cave +Hookshot Cave Back Entrance: The stairs on the floating island + +Destination Entrance Naming: + +Hyrule Castle: Hyrule Castle (all three entrances) +Eastern Palace: Eastern Palace +Desert Palace: Desert Palace (all four entrances, including final) +Tower of Hera: Tower of Hera +Palace of Darkness: Palace of Darkness +Swamp Palace: Swamp Palace +Skull Woods: Skull Woods (any entrance including final) +Thieves' Town: Thieves' Town +Ice Palace: Ice Palace +Misery Mire: Misery Mire +Turtle Rock: Turtle Rock (all four entrances) +Ganon's Tower: Ganon's Tower +Castle Tower: Agahnim's Tower +A connector: Paradox Cave, Spectacle Rock Cave, Hookshot Cave, Superbunny Cave, Spiral Cave, Old Man Fetch Cave, Old Man House, Elder House, Quarreling Brothers' House, Bumper Cave, DM Fairy Ascent Cave, DM Exit Cave +A bounty of five items: Mini-moldorm cave, Hype Cave, Blind's Hideout +Sahasrahla: Sahasrahla +A cave with two items: Mire hut, Waterfall Fairy, Pyramid Fairy +A fairy fountain: Any healer fairy cave, either bonk cave with four fairies, the "long fairy" cave +A common shop: Any shop that sells bombs by default +The rare shop: The shop that sells the Red Shield by default +The potion shop: Potion Shop +The bomb shop: Bomb Shop +A fortune teller: Any of the three fortune tellers +A house with a chest: Chicken Lady's house, C-House, Brewery +A cave with an item: Checkerboard cave, Hammer Pegs cave, Cave 45, Graveyard Ledge cave +A cave with a chest: Sanc Bonk Rock Cave, Cape Grave Cave, Ice Rod Cave, Aginah's Cave +The dam: Watergate +The sick kid: Sick Kid +The library: Library +Mimic Cave: Mimic Cave +Spike Cave: Spike Cave +A game of 16 chests: VoO chest game (for the item) +A storyteller: The four DW NPCs who charge 20 rupees for a hint as well as the PoD Bdlg guy who gives a free hint +A cave with some cash: 20 rupee cave, 50 rupee cave (both have thieves and some pots) +A game of chance: Gambling game (just for cash, no items) +A game of skill: Archery minigame +The queen of fairies: Capacity Upgrade Fairy +A drop's exit: Sanctuary, LW Thieves' Hideout, Kakariko Well, Magic Bat, Useless Fairy, Uncle Tunnel, Ganon drop exit +A restock room: The Kakariko bomb/arrow restock room +The tavern: The Kakariko tavern +The grass man: The Kakariko man with many beds +A cold bee: The "wrong side" of Ice Rod cave where you can get a Good Bee +Fairies deep in a cave: Hookshot Fairy + +Location naming reference: + +Mushroom: in the woods +Master Sword Pedestal: at the pedestal +Bottle Merchant: with a merchant +Stumpy: with tree boy +Flute Spot: underground +Digging Game: underground +Lake Hylia Island: on an island +Floating Island: on an island +Bumper Cave Ledge: on a ledge +Spectacle Rock: atop a rock +Maze Race: at the race +Desert Ledge: in the desert +Pyramid: on the pyramid +Catfish: with a catfish +Ether Tablet: at a monument +Bombos Tablet: at a monument +Hobo: with the hobo +Zora's Ledge: near Zora +King Zora: at a high price +Sunken Treasure: underwater +Floodgate Chest: in the dam +Blacksmith: with the smith +Purple Chest: from a box +Old Man: with the old man +Link's Uncle: with your uncle +Secret Passage: near your uncle +Kakariko Well (5 items): in a well +Lost Woods Hideout: near a thief +Lumberjack Tree: in a hole +Magic Bat: with the bat +Paradox Cave (7 items): in a cave with seven chests +Blind's Hideout (5 items): in a basement +Mini Moldorm Cave (5 items): near Moldorms +Hype Cave (4 back chests): near a bat-like man +Hype Cave - Generous Guy: with a bat-like man +Hookshot Cave (4 items): across pits +Sahasrahla's Hut (chests in back): near the elder +Sahasrahla: with the elder +Waterfall Fairy (2 items): near a fairy +Pyramid Fairy (2 items): near a fairy +Mire Shed (2 items): near sparks +Superbunny Cave (2 items): in a connection +Spiral Cave: in spiral cave +Kakariko Tavern: in the bar +Link's House: in your home +Sick Kid: with the sick +Library: near books +Potion Shop: near potions +Spike Cave: beyond spikes +Mimic Cave: in a cave of mimicry +Chest Game: as a prize +Chicken House: near poultry +Aginah's Cave: with Aginah +Ice Rod Cave: in a frozen cave +Brewery: alone in a home +C-Shaped House: alone in a home +Spectacle Rock Cave: alone in a cave +King's Tomb: alone in a cave +Cave 45: alone in a cave +Graveyard Cave: alone in a cave +Checkerboard Cave: alone in a cave +Bonk Rock Cave: alone in a cave +Peg Cave: alone in a cave +Sanctuary: in Sanctuary +Hyrule Castle - Boomerang Chest: in Hyrule Castle +Hyrule Castle - Map Chest: in Hyrule Castle +Hyrule Castle - Zelda's Chest: in Hyrule Castle +Sewers - Dark Cross: in the sewers +Sewers - Secret Room (3 items): in the sewers +Eastern Palace - Boss: with the Armos +Eastern Palace (otherwise, 5 items): in Eastern Palace +Desert Palace - Boss: with Lanmolas +Desert Palace (otherwise, 5 items): in Desert Palace +Tower of Hera - Boss: with Moldorm +Tower of Hera (otherwise, 5 items): in Tower of Hera +Castle Tower (2 items): in Castle Tower +Palace of Darkness - Boss: with Helmasaur King +Palace of Darkness (otherwise, 13 items): in Palace of Darkness +Swamp Palace - Boss: with Arrghus +Swamp Palace (otherwise, 9 items): in Swamp Palace +Skull Woods - Bridge Room: near Mothula +Skull Woods - Boss: with Mothula +Skull Woods (otherwise, 6 items): in Skull Woods +Thieves' Town - Boss: with Blind +Thieves' Town (otherwise, 7 items): in Thieves' Town +Ice Palace - Boss: with Kholdstare +Ice Palace (otherwise, 7 items): in Ice Palace +Misery Mire - Boss: with Vitreous +Misery Mire (otherwise, 7 items): in Misery Mire +Turtle Rock - Boss: with Trinexx +Turtle Rock (otherwise, 11 items): in Turtle Rock +Ganons Tower (after climb, 4 items): atop Ganon's Tower Ganon's Tower (otherwise, 23 items): in Ganon's Tower \ No newline at end of file diff --git a/EntranceShuffle.py b/EntranceShuffle.py index fa07447d..d9c29422 100644 --- a/EntranceShuffle.py +++ b/EntranceShuffle.py @@ -2880,6 +2880,8 @@ mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia Central ('East Dark World River Pier', 'East Dark World'), ('West Dark World Gap', 'West Dark World'), ('East Dark World Broken Bridge Pass', 'East Dark World'), + ('Catfish Exit Rock', 'Northeast Dark World'), + ('Catfish Entrance Rock', 'Catfish'), ('Northeast Dark World Broken Bridge Pass', 'Northeast Dark World'), ('Bumper Cave Entrance Rock', 'Bumper Cave Entrance'), ('Bumper Cave Entrance Drop', 'West Dark World'), @@ -2985,7 +2987,39 @@ mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia Central ('Ganons Tower Moldorm Door', 'Ganons Tower (Moldorm)'), ('Ganons Tower Moldorm Gap', 'Agahnim 2'), ('Ganon Drop', 'Bottom of Pyramid'), - ('Pyramid Drop', 'East Dark World') + ('Pyramid Drop', 'East Dark World'), + ('Light World DMA Clip Spot', 'Death Mountain'), + ('Hera Ascent', 'Death Mountain (Top)'), + ('Spectacle Rock Clip Spot', 'Spectacle Rock'), + ('Death Mountain Return Ledge Clip Spot', 'Death Mountain Return Ledge'), + ('Death Mountain Glitched Bridge', 'East Death Mountain (Top)'), + ('Floating Island Clip Spot', 'Death Mountain Floating Island (Light World)'), + ('Dark Death Mountain Ledge Clip Spot', 'Dark Death Mountain Ledge'), + ('Zora Descent Clip Spot', 'Zoras River'), + ('Graveyard Ledge Clip Spot', 'Graveyard Ledge'), + ('Desert Northern Cliffs', 'Desert Ledge'), + ('Desert Northern Cliffs', 'Desert Ledge (Northeast)'), + ('Desert Northern Cliffs', 'Desert Palace Entrance (North) Spot'), + ('Lake Hylia Island Clip Spot', 'Lake Hylia Island'), + ('Dark World DMA Clip Spot', 'Dark Death Mountain (West Bottom)'), + ('Ganons Tower Ascent', 'Dark Death Mountain (Top)'), + ('Bumper Cave Ledge Clip Spot', 'Bumper Cave Ledge'), + ('Dark Death Mountain Glitched Bridge', 'Dark Death Mountain (Top)'), + ('Dark Death Mountain Bunny Descent Mirror Spot', 'Dark Death Mountain Bunny Descent Area'), + ('Hookshot Cave Island Clip Spot', 'Death Mountain Floating Island (Dark World)'), + ('Catfish Descent', 'Catfish'), + ('Dark Death Mountain Offset Mirror', 'East Dark World'), + ('Hammer Pegs River Clip Spot', 'Hammer Peg Area'), + ('Dark Lake Hylia Ledge Clip Spot', 'Dark Lake Hylia Ledge'), + ('Dark Desert Cliffs Clip Spot', 'Dark Desert'), + ('Bumper Cave Ledge Clip Drop', 'Bumper Cave Entrance'), + ('Death Mountain Return Ledge Clip Drop', 'Death Mountain Entrance'), + ('Bumper Cave Entrance Clip (Broken Camera)', 'Bumper Cave Entrance'), + ('Death Mountain Entrance Clip (Broken Camera)', 'Death Mountain Entrance'), + ('West Dark World Bunny Descent', 'West Dark World'), + ('Dark Death Mountain (East Bottom) Jump', 'Dark Death Mountain (East Bottom)'), + ('Bat Cave River Clip Spot', 'Bat Cave Drop Ledge'), + ('Turtle Rock (Top) Clip Spot', 'Turtle Rock (Top)'), ] inverted_mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia Central Island'), diff --git a/OWGSets.py b/OWGSets.py index 3cdd1fc8..b465a35b 100644 --- a/OWGSets.py +++ b/OWGSets.py @@ -11,184 +11,10 @@ def get_immediately_accessible_entrances(world, player): entrances = [ 'Hobo Bridge', 'Zoras River', - 'Capacity Upgrade', + 'Lake Hylia Central Island Pier', ] return entrances -def get_lw_boots_accessible_entrances(world, player): - ''' - Light World entrances that can be accessed with boots clips. - ''' - entrances = [ - 'Bat Cave Drop Ledge', - 'Desert Ledge Return Rocks', - 'Desert Palace Entrance (West)', - 'Desert Palace Entrance (North)', - 'Broken Bridge (East)', - 'Death Mountain Drop', - 'Old Man Cave (East)', - 'Old Man House (Bottom)', - 'Old Man House (Top)', - 'Death Mountain Return Cave (East)', - 'Spectacle Rock Cave', - 'Spectacle Rock Cave Peak', - 'Spectacle Rock Cave (Bottom)', - 'Broken Bridge (West)', - 'Broken Bridge (East)', - 'East Death Mountain Drop', - 'Spiral Cave Ledge Drop', - 'Fairy Ascension Drop', - 'Fairy Ascension Cave (Bottom)', - 'East Death Mountain (Top)', - 'Death Mountain (Top)', - 'Death Mountain Return Cave (West)', - 'Paradox Cave (Bottom)', - 'Paradox Cave (Middle)', - 'Hookshot Fairy', - 'Spiral Cave (Bottom)', - 'Paradox Cave (Top)', - 'Spiral Cave Ledge Access', - 'Bumper Cave Ledge Mirror Spot', - 'Floating Island Mirror Spot', - ] - if world.mode[player] != 'inverted': - entrances.append('Flute Spot 1') - entrances.append('Spectacle Rock Drop') - entrances.append('Fairy Ascension Ledge') - return entrances - - -def get_lw_boots_accessible_locations(): - ''' - Light World locations that can be reached using boots clips. - ''' - return [ - 'Lake Hylia Island', - 'Desert Ledge', - 'Spectacle Rock', - 'Floating Island', - ] - - -def get_dw_boots_accessible_entrances(world, player): - ''' - Dark World entrances that can be accessed with boots clips. - ''' - entrances = [ - 'Northeast Dark World Broken Bridge Pass', - 'Peg Area Rocks', - 'Grassy Lawn Pegs', - 'West Dark World Gap', - 'Bumper Cave Ledge Drop', - 'Turtle Rock Drop', - 'Floating Island Drop', - 'Dark Death Mountain Drop (East)', - 'Village of Outcasts Drop', - 'Hype Cave', - 'Dark World Potion Shop', - 'Archery Game', - 'Brewery', - 'C-Shaped House', - 'Chest Game', - 'Thieves Town', - 'Bumper Cave Entrance Rock', - 'Red Shield Shop', - 'Fortune Teller (Dark)', - 'Dark World Lumberjack Shop', - 'Misery Mire', - 'Mire Shed', - 'Dark Desert Hint', - 'Dark Desert Fairy', - ] - if world.mode[player] != 'inverted': - entrances.append('Dark Lake Hylia Ledge') - entrances.append('Big Bomb Shop') - entrances.append('Kings Grave Mirror Spot') - entrances.append('Dark Sanctuary Hint') - return entrances - - -def get_dw_boots_accessible_locations(): - ''' - Dark World locations accessible using boots clips. - ''' - return [ - 'Catfish', - 'Dark Blacksmith Ruins', - 'Bumper Cave Ledge', - ] - - -def get_dw_bunny_inaccessible_locations(): - ''' - Locations that the bunny cannot access. - ''' - return [ - 'Thieves Town', - 'Graveyard Ledge Mirror Spot', - 'Kings Grave Mirror Spot', - 'Bumper Cave Entrance Rock', - 'Brewery', - 'Village of Outcasts Pegs', - 'Village of Outcasts Eastern Rocks', - 'Dark Lake Hylia Drop (South)', - 'Hype Cave', - 'Village of Outcasts Heavy Rock', - 'East Dark World Bridge', - 'Bonk Fairy (Dark)', - ] - - -def get_dmd_and_bunny_regions(): - ''' - Dark World regions accessible using Link and Bunny DMD methods. - ''' - return [ - 'West Dark World', - 'South Dark World', - 'East Dark World', - ] - - -def get_dmd_non_bunny_regions(): - ''' - Dark World regions accessible using only Link DMD methods. - ''' - return [ - 'Dark Desert', - 'Northeast Dark World', - ] - - -def get_boots_accessible_regions_lw(): - ''' - Light World regions that can be accessed using boots clips. - ''' - return [ - 'Desert Ledge (Northeast)', - 'Desert Ledge', - 'Desert Palace Entrance (North) Spot', - 'Cave 45 Ledge', - 'Graveyard Ledge', - 'Lake Hylia Island', - 'Death Mountain', - 'Death Mountain Return Ledge', - 'Bombos Tablet Ledge', - ] - - -def get_mirror_hookshot_accessible_dw_locations(world, player): - ''' - Locations accessible potentially using weird mirror hookshot boots setups. - ''' - locations = [ - 'Pyramid Fairy', - 'Pyramid Entrance', - 'Pyramid Drop', - ] - locations.extend(world.get_region('Dark Death Mountain Ledge', player).locations) - return locations - def get_sword_required_superbunny_mirror_regions(): ''' @@ -268,3 +94,71 @@ def get_superbunny_accessible_locations(): 'Superbunny Cave - Top', 'Superbunny Cave - Bottom', ] + + +def get_boots_clip_exits_lw(): + ''' + Special Light World region exits that require boots clips. + ''' + return [ + 'Bat Cave River Clip Spot', + 'Light World DMA Clip Spot', + 'Hera Ascent', + 'Spectacle Rock Clip Spot', + 'Death Mountain Return Ledge Clip Spot', + 'Death Mountain Glitched Bridge', + 'Floating Island Clip Spot', + 'Zora Descent Clip Spot', + 'Graveyard Ledge Clip Spot', + 'Desert Northern Cliffs', + 'Lake Hylia Island Clip Spot', + 'Death Mountain Entrance Clip (Broken Camera)', + ] + + +def get_boots_clip_exits_dw(): + ''' + Special Dark World region exits that require boots clips. + ''' + return [ + 'Dark World DMA Clip Spot', + 'Ganons Tower Ascent', + 'Bumper Cave Ledge Clip Spot', + 'Dark Death Mountain Glitched Bridge', + 'Hookshot Cave Island Clip Spot', + 'Catfish Descent', + 'Hammer Pegs River Clip Spot', + 'Dark Lake Hylia Ledge Clip Spot', + 'Dark Desert Cliffs Clip Spot', + 'Bumper Cave Entrance Clip (Broken Camera)', + 'Turtle Rock (Top) Clip Spot', + ] + + +def get_glitched_speed_drops_lw(): + ''' + Light World drop-down ledges that require glitched speed. + ''' + return [ + 'Death Mountain Return Ledge Clip Drop', + ] + + +def get_glitched_speed_drops_dw(): + ''' + Dark World drop-down ledges that require glitched speed. + ''' + return [ + 'Dark Death Mountain Ledge Clip Spot', + 'Bumper Cave Ledge Clip Drop', + ] + + +def get_mirror_clip_spots_dw(): + ''' + Mirror shenanigans that are in logic even if the player is a bunny. + ''' + return [ + 'Dark Death Mountain Offset Mirror', + 'Dark Death Mountain Bunny Descent Mirror Spot', + ] diff --git a/Regions.py b/Regions.py index eefcc71c..cd20ecb0 100644 --- a/Regions.py +++ b/Regions.py @@ -14,7 +14,8 @@ def create_regions(world, player): 'Sanctuary', 'Sanctuary Grave', 'Death Mountain Entrance Rock', 'Flute Spot 1', 'Dark Desert Teleporter', 'East Hyrule Teleporter', 'South Hyrule Teleporter', 'Kakariko Teleporter', 'Elder House (East)', 'Elder House (West)', 'North Fairy Cave', 'North Fairy Cave Drop', 'Lost Woods Gamble', 'Snitch Lady (East)', 'Snitch Lady (West)', 'Tavern (Front)', 'Bush Covered House', 'Light World Bomb Hut', 'Kakariko Shop', 'Long Fairy Cave', 'Good Bee Cave', '20 Rupee Cave', 'Cave Shop (Lake Hylia)', 'Waterfall of Wishing', 'Hyrule Castle Main Gate', - 'Bonk Fairy (Light)', '50 Rupee Cave', 'Fortune Teller (Light)', 'Lake Hylia Fairy', 'Light Hype Fairy', 'Desert Fairy', 'Lumberjack House', 'Lake Hylia Fortune Teller', 'Kakariko Gamble Game', 'Top of Pyramid']), + 'Bonk Fairy (Light)', '50 Rupee Cave', 'Fortune Teller (Light)', 'Lake Hylia Fairy', 'Light Hype Fairy', 'Desert Fairy', 'Lumberjack House', 'Lake Hylia Fortune Teller', 'Kakariko Gamble Game', 'Top of Pyramid', + 'Light World DMA Clip Spot', 'Death Mountain Return Ledge Clip Spot', 'Desert Northern Cliffs', 'Lake Hylia Island Clip Spot', 'Death Mountain Entrance Clip (Broken Camera)', 'Bat Cave River Clip Spot']), create_lw_region(player, 'Death Mountain Entrance', None, ['Old Man Cave (West)', 'Death Mountain Entrance Drop']), create_lw_region(player, 'Lake Hylia Central Island', None, ['Capacity Upgrade', 'Lake Hylia Central Island Teleporter']), create_cave_region(player, 'Blinds Hideout', 'a bounty of five items', ["Blind\'s Hideout - Top", @@ -117,9 +118,9 @@ def create_regions(world, player): create_cave_region(player, 'Old Man Cave', 'a connector', ['Old Man'], ['Old Man Cave Exit (East)', 'Old Man Cave Exit (West)']), create_cave_region(player, 'Old Man House', 'a connector', None, ['Old Man House Exit (Bottom)', 'Old Man House Front to Back']), create_cave_region(player, 'Old Man House Back', 'a connector', None, ['Old Man House Exit (Top)', 'Old Man House Back to Front']), - create_lw_region(player, 'Death Mountain', None, ['Old Man Cave (East)', 'Old Man House (Bottom)', 'Old Man House (Top)', 'Death Mountain Return Cave (East)', 'Spectacle Rock Cave', 'Spectacle Rock Cave Peak', 'Spectacle Rock Cave (Bottom)', 'Broken Bridge (West)', 'Death Mountain Teleporter']), + create_lw_region(player, 'Death Mountain', None, ['Old Man Cave (East)', 'Old Man House (Bottom)', 'Old Man House (Top)', 'Death Mountain Return Cave (East)', 'Spectacle Rock Cave', 'Spectacle Rock Cave Peak', 'Spectacle Rock Cave (Bottom)', 'Broken Bridge (West)', 'Death Mountain Teleporter', 'Death Mountain Glitched Bridge', 'Graveyard Ledge Clip Spot', 'Hera Ascent']), create_cave_region(player, 'Death Mountain Return Cave', 'a connector', None, ['Death Mountain Return Cave Exit (West)', 'Death Mountain Return Cave Exit (East)']), - create_lw_region(player, 'Death Mountain Return Ledge', None, ['Death Mountain Return Ledge Drop', 'Death Mountain Return Cave (West)']), + create_lw_region(player, 'Death Mountain Return Ledge', None, ['Death Mountain Return Ledge Drop', 'Death Mountain Return Cave (West)', 'Death Mountain Return Ledge Clip Drop']), create_cave_region(player, 'Spectacle Rock Cave (Top)', 'a connector', ['Spectacle Rock Cave'], ['Spectacle Rock Cave Drop', 'Spectacle Rock Cave Exit (Top)']), create_cave_region(player, 'Spectacle Rock Cave (Bottom)', 'a connector', None, ['Spectacle Rock Cave Exit']), create_cave_region(player, 'Spectacle Rock Cave (Peak)', 'a connector', None, ['Spectacle Rock Cave Peak Drop', 'Spectacle Rock Cave Exit (Peak)']), @@ -136,7 +137,7 @@ def create_regions(world, player): ['Paradox Cave Push Block', 'Paradox Cave Bomb Jump']), create_cave_region(player, 'Paradox Cave', 'a connector', None, ['Paradox Cave Exit (Middle)', 'Paradox Cave Exit (Top)', 'Paradox Cave Drop']), create_cave_region(player, 'Light World Death Mountain Shop', 'a common shop'), - create_lw_region(player, 'East Death Mountain (Top)', None, ['Paradox Cave (Top)', 'Death Mountain (Top)', 'Spiral Cave Ledge Access', 'East Death Mountain Drop', 'Turtle Rock Teleporter', 'Fairy Ascension Ledge']), + create_lw_region(player, 'East Death Mountain (Top)', None, ['Paradox Cave (Top)', 'Death Mountain (Top)', 'Spiral Cave Ledge Access', 'East Death Mountain Drop', 'Turtle Rock Teleporter', 'Fairy Ascension Ledge', 'Floating Island Clip Spot', 'Zora Descent Clip Spot']), create_lw_region(player, 'Spiral Cave Ledge', None, ['Spiral Cave', 'Spiral Cave Ledge Drop']), create_cave_region(player, 'Spiral Cave (Top)', 'a connector', ['Spiral Cave'], ['Spiral Cave (top to bottom)', 'Spiral Cave Exit (Top)']), create_cave_region(player, 'Spiral Cave (Bottom)', 'a connector', None, ['Spiral Cave Exit']), @@ -145,19 +146,22 @@ def create_regions(world, player): create_cave_region(player, 'Fairy Ascension Cave (Drop)', 'a connector', None, ['Fairy Ascension Cave Pots']), create_cave_region(player, 'Fairy Ascension Cave (Top)', 'a connector', None, ['Fairy Ascension Cave Exit (Top)', 'Fairy Ascension Cave Drop']), create_lw_region(player, 'Fairy Ascension Ledge', None, ['Fairy Ascension Ledge Drop', 'Fairy Ascension Cave (Top)']), - create_lw_region(player, 'Death Mountain (Top)', ['Ether Tablet'], ['East Death Mountain (Top)', 'Tower of Hera', 'Death Mountain Drop']), + create_lw_region(player, 'Death Mountain (Top)', ['Ether Tablet'], ['East Death Mountain (Top)', 'Tower of Hera', 'Death Mountain Drop', 'Spectacle Rock Clip Spot']), create_lw_region(player, 'Spectacle Rock', ['Spectacle Rock'], ['Spectacle Rock Drop']), create_dungeon_region(player, 'Tower of Hera (Bottom)', 'Tower of Hera', ['Tower of Hera - Basement Cage', 'Tower of Hera - Map Chest'], ['Tower of Hera Small Key Door', 'Tower of Hera Big Key Door', 'Tower of Hera Exit']), create_dungeon_region(player, 'Tower of Hera (Basement)', 'Tower of Hera', ['Tower of Hera - Big Key Chest']), create_dungeon_region(player, 'Tower of Hera (Top)', 'Tower of Hera', ['Tower of Hera - Compass Chest', 'Tower of Hera - Big Chest', 'Tower of Hera - Boss', 'Tower of Hera - Prize']), create_dw_region(player, 'East Dark World', ['Pyramid'], ['Pyramid Fairy', 'South Dark World Bridge', 'Palace of Darkness', 'Dark Lake Hylia Drop (East)', 'Dark Lake Hylia Teleporter', - 'Hyrule Castle Ledge Mirror Spot', 'Dark Lake Hylia Fairy', 'Palace of Darkness Hint', 'East Dark World Hint', 'Pyramid Hole', 'Northeast Dark World Broken Bridge Pass']), - create_dw_region(player, 'Northeast Dark World', ['Catfish'], ['West Dark World Gap', 'Dark World Potion Shop', 'East Dark World Broken Bridge Pass']), + 'Hyrule Castle Ledge Mirror Spot', 'Dark Lake Hylia Fairy', 'Palace of Darkness Hint', 'East Dark World Hint', 'Pyramid Hole', 'Northeast Dark World Broken Bridge Pass', + 'Hammer Pegs River Clip Spot', 'Dark Lake Hylia Ledge Clip Spot']), + create_dw_region(player, 'Catfish', ['Catfish'], ['Catfish Exit Rock']), + create_dw_region(player, 'Northeast Dark World', None, ['West Dark World Gap', 'Dark World Potion Shop', 'East Dark World Broken Bridge Pass', 'Catfish Entrance Rock']), create_cave_region(player, 'Palace of Darkness Hint', 'a storyteller'), create_cave_region(player, 'East Dark World Hint', 'a storyteller'), create_dw_region(player, 'South Dark World', ['Stumpy', 'Digging Game'], ['Dark Lake Hylia Drop (South)', 'Hype Cave', 'Swamp Palace', 'Village of Outcasts Heavy Rock', 'Maze Race Mirror Spot', - 'Cave 45 Mirror Spot', 'East Dark World Bridge', 'Big Bomb Shop', 'Archery Game', 'Bonk Fairy (Dark)', 'Dark Lake Hylia Shop', 'Bombos Tablet Mirror Spot']), + 'Cave 45 Mirror Spot', 'East Dark World Bridge', 'Big Bomb Shop', 'Archery Game', 'Bonk Fairy (Dark)', 'Dark Lake Hylia Shop', + 'Bombos Tablet Mirror Spot', 'Dark Desert Cliffs Clip Spot']), create_lw_region(player, 'Bombos Tablet Ledge', ['Bombos Tablet']), create_cave_region(player, 'Big Bomb Shop', 'the bomb shop'), create_cave_region(player, 'Archery Game', 'a game of skill'), @@ -169,7 +173,8 @@ def create_regions(world, player): create_cave_region(player, 'Hype Cave', 'a bounty of five items', ['Hype Cave - Top', 'Hype Cave - Middle Right', 'Hype Cave - Middle Left', 'Hype Cave - Bottom', 'Hype Cave - Generous Guy']), create_dw_region(player, 'West Dark World', ['Frog'], ['Village of Outcasts Drop', 'East Dark World River Pier', 'Brewery', 'C-Shaped House', 'Chest Game', 'Thieves Town', 'Graveyard Ledge Mirror Spot', 'Kings Grave Mirror Spot', 'Bumper Cave Entrance Rock', - 'Skull Woods Forest', 'Village of Outcasts Pegs', 'Village of Outcasts Eastern Rocks', 'Red Shield Shop', 'Dark Sanctuary Hint', 'Fortune Teller (Dark)', 'Dark World Lumberjack Shop']), + 'Skull Woods Forest', 'Village of Outcasts Pegs', 'Village of Outcasts Eastern Rocks', 'Red Shield Shop', 'Dark Sanctuary Hint', 'Fortune Teller (Dark)', 'Dark World Lumberjack Shop', + 'Dark World DMA Clip Spot', 'Bumper Cave Ledge Clip Spot', 'Bumper Cave Entrance Clip (Broken Camera)']), create_dw_region(player, 'Dark Grassy Lawn', None, ['Grassy Lawn Pegs', 'Dark World Shop']), create_dw_region(player, 'Hammer Peg Area', ['Dark Blacksmith Ruins'], ['Bat Cave Drop Ledge Mirror Spot', 'Dark World Hammer Peg Cave', 'Peg Area Rocks']), create_dw_region(player, 'Bumper Cave Entrance', None, ['Bumper Cave (Bottom)', 'Bumper Cave Entrance Mirror Spot', 'Bumper Cave Entrance Drop']), @@ -186,7 +191,7 @@ def create_regions(world, player): create_cave_region(player, 'Red Shield Shop', 'the rare shop'), create_cave_region(player, 'Dark Sanctuary Hint', 'a storyteller'), create_cave_region(player, 'Bumper Cave', 'a connector', None, ['Bumper Cave Exit (Bottom)', 'Bumper Cave Exit (Top)']), - create_dw_region(player, 'Bumper Cave Ledge', ['Bumper Cave Ledge'], ['Bumper Cave Ledge Drop', 'Bumper Cave (Top)', 'Bumper Cave Ledge Mirror Spot']), + create_dw_region(player, 'Bumper Cave Ledge', ['Bumper Cave Ledge'], ['Bumper Cave Ledge Drop', 'Bumper Cave (Top)', 'Bumper Cave Ledge Mirror Spot', 'Bumper Cave Ledge Clip Drop']), create_dw_region(player, 'Skull Woods Forest', None, ['Skull Woods First Section Hole (East)', 'Skull Woods First Section Hole (West)', 'Skull Woods First Section Hole (North)', 'Skull Woods First Section Door', 'Skull Woods Second Section Door (East)']), create_dw_region(player, 'Skull Woods Forest (West)', None, ['Skull Woods Second Section Hole', 'Skull Woods Second Section Door (West)', 'Skull Woods Final Section']), @@ -194,9 +199,9 @@ def create_regions(world, player): 'Desert Palace Entrance (North) Mirror Spot', 'Dark Desert Hint', 'Dark Desert Fairy']), create_cave_region(player, 'Mire Shed', 'a cave with two chests', ['Mire Shed - Left', 'Mire Shed - Right']), create_cave_region(player, 'Dark Desert Hint', 'a storyteller'), - create_dw_region(player, 'Dark Death Mountain (West Bottom)', None, ['Spike Cave', 'Spectacle Rock Mirror Spot', 'Dark Death Mountain Fairy']), + create_dw_region(player, 'Dark Death Mountain (West Bottom)', None, ['Spike Cave', 'Spectacle Rock Mirror Spot', 'Dark Death Mountain Fairy', 'Ganons Tower Ascent', 'Dark Death Mountain Glitched Bridge', 'Dark Death Mountain Bunny Descent Mirror Spot', 'Dark Death Mountain Offset Mirror']), create_dw_region(player, 'Dark Death Mountain (Top)', None, ['Dark Death Mountain Drop (East)', 'Dark Death Mountain Drop (West)', 'Ganons Tower', 'Superbunny Cave (Top)', - 'Hookshot Cave', 'East Death Mountain (Top) Mirror Spot', 'Turtle Rock']), + 'Hookshot Cave', 'East Death Mountain (Top) Mirror Spot', 'Turtle Rock', 'Hookshot Cave Island Clip Spot', 'Catfish Descent', 'Dark Death Mountain Ledge Clip Spot', 'Turtle Rock (Top) Clip Spot']), create_dw_region(player, 'Dark Death Mountain Ledge', None, ['Dark Death Mountain Ledge (East)', 'Dark Death Mountain Ledge (West)', 'Mimic Cave Mirror Spot', 'Spiral Cave Mirror Spot']), create_dw_region(player, 'Dark Death Mountain Isolated Ledge', None, ['Isolated Ledge Mirror Spot', 'Turtle Rock Isolated Ledge Entrance']), create_dw_region(player, 'Dark Death Mountain (East Bottom)', None, ['Superbunny Cave (Bottom)', 'Cave Shop (Dark Death Mountain)', 'Fairy Ascension Mirror Spot']), @@ -291,7 +296,8 @@ def create_regions(world, player): create_dungeon_region(player, 'Agahnim 2', 'Ganon\'s Tower', ['Ganons Tower - Validation Chest', 'Agahnim 2'], None), create_cave_region(player, 'Pyramid', 'a drop\'s exit', ['Ganon'], ['Ganon Drop']), create_cave_region(player, 'Bottom of Pyramid', 'a drop\'s exit', None, ['Pyramid Exit']), - create_dw_region(player, 'Pyramid Ledge', None, ['Pyramid Entrance', 'Pyramid Drop']) + create_dw_region(player, 'Pyramid Ledge', None, ['Pyramid Entrance', 'Pyramid Drop']), + create_dw_region(player, 'Dark Death Mountain Bunny Descent Area', None, ['West Dark World Bunny Descent', 'Dark Death Mountain (East Bottom) Jump']), ] world.initialize_regions() diff --git a/Rules.py b/Rules.py index d625bd7b..094d9d8d 100644 --- a/Rules.py +++ b/Rules.py @@ -398,7 +398,8 @@ def default_rules(world, player): set_rule(world.get_entrance('Turtle Rock Teleporter', player), lambda state: state.can_lift_heavy_rocks(player) and state.has('Hammer', player)) set_rule(world.get_entrance('East Death Mountain (Top)', player), lambda state: state.has('Hammer', player)) - set_rule(world.get_location('Catfish', player), lambda state: state.can_lift_rocks(player)) + set_rule(world.get_entrance('Catfish Exit Rock', player), lambda state: state.can_lift_rocks(player)) + set_rule(world.get_entrance('Catfish Entrance Rock', player), lambda state: state.can_lift_rocks(player)) set_rule(world.get_entrance('Northeast Dark World Broken Bridge Pass', player), lambda state: state.has_Pearl(player) and (state.can_lift_rocks(player) or state.has('Hammer', player) or state.has('Flippers', player))) set_rule(world.get_entrance('East Dark World Broken Bridge Pass', player), lambda state: state.has_Pearl(player) and (state.can_lift_rocks(player) or state.has('Hammer', player))) set_rule(world.get_entrance('South Dark World Bridge', player), lambda state: state.has('Hammer', player) and state.has_Pearl(player)) @@ -467,6 +468,20 @@ def default_rules(world, player): set_rule(world.get_entrance('Ganons Tower', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player)) + +def forbid_overworld_glitches(world, player): + for exit in OWGSets.get_boots_clip_exits_lw(): + set_rule(world.get_entrance(exit, player), lambda state: False) + for exit in OWGSets.get_boots_clip_exits_dw(): + set_rule(world.get_entrance(exit, player), lambda state: False) + for exit in OWGSets.get_glitched_speed_drops_lw(): + set_rule(world.get_entrance(exit, player), lambda state: False) + for exit in OWGSets.get_glitched_speed_drops_dw(): + set_rule(world.get_entrance(exit, player), lambda state: False) + for exit in OWGSets.get_mirror_clip_spots_dw(): + set_rule(world.get_entrance(exit, player), lambda state: False) + + def inverted_rules(world, player): # s&q regions. link's house entrance is set to true so the filler knows the chest inside can always be reached world.get_region('Inverted Links House', player).can_reach_private = lambda state: True @@ -644,6 +659,7 @@ def no_glitches_rules(world, player): add_rule(world.get_entrance('Ganons Tower (Double Switch Room)', player), lambda state: state.has('Hookshot', player)) set_rule(world.get_entrance('Paradox Cave Push Block Reverse', player), lambda state: False) # no glitches does not require block override forbid_bomb_jump_requirements(world, player) + forbid_overworld_glitches(world, player) add_conditional_lamps(world, player) @@ -731,46 +747,22 @@ def overworld_glitches_rules(world, player): set_rule(world.get_entrance(entrance, player), lambda state: True) # Boots-accessible locations. - for entrance in OWGSets.get_lw_boots_accessible_entrances(world, player): - add_rule(world.get_entrance(entrance, player), lambda state: state.can_boots_clip_lw(player), 'or') - for location in OWGSets.get_lw_boots_accessible_locations(): - add_rule(world.get_location(location, player), lambda state: state.can_boots_clip_lw(player), 'or') - for entrance in OWGSets.get_dw_boots_accessible_entrances(world, player): - add_rule(world.get_entrance(entrance, player), lambda state: state.can_boots_clip_dw(player), 'or') - for location in OWGSets.get_dw_boots_accessible_locations(): - add_rule(world.get_location(location, player), lambda state: state.can_boots_clip_dw(player), 'or') + for entrance in OWGSets.get_boots_clip_exits_lw(): + set_rule(world.get_entrance(entrance, player), lambda state: state.can_boots_clip_lw(player)) + for entrance in OWGSets.get_boots_clip_exits_dw(): + set_rule(world.get_entrance(entrance, player), lambda state: state.can_boots_clip_dw(player)) - # Boots-accessible regions. - boots_and_mirror = lambda state: state.has_Boots(player) and state.has_Mirror(player) - if world.mode[player] != 'inverted': - for boots_accessible_region in OWGSets.get_boots_accessible_regions_lw(): - region = world.get_region(boots_accessible_region, player) - region.can_reach_private = lambda state: region.can_reach(state) or state.has_Boots(player) - # DMD with and without bunny. - for dmd_bunny_region in OWGSets.get_dmd_and_bunny_regions(): - region = world.get_region(dmd_bunny_region, player) - region.can_reach_private = lambda state: region.can_reach(state) or (state.can_boots_clip_dw(player) or state.can_bunny_dmd(player)) - for non_dmd_bunny_region in OWGSets.get_dmd_non_bunny_regions(): - region = world.get_region(non_dmd_bunny_region, player) - region.can_reach_private = lambda state: region.can_reach(state) or state.can_boots_clip_dw(player) - edmb = world.get_region('Dark Death Mountain (East Bottom)', player) - edmb.can_reach_private = lambda state: edmb.can_reach(state) or state.can_bunny_dmd(player) + # Glitched speed drops. + for drop in OWGSets.get_glitched_speed_drops_lw(): + set_rule(world.get_entrance(drop, player), lambda state: state.can_get_glitched_speed_lw(player)) + for drop in OWGSets.get_glitched_speed_drops_dw(): + set_rule(world.get_entrance(drop, player), lambda state: state.can_get_glitched_speed_dw(player)) + # Dark Death Mountain Ledge Clip Spot also accessible with mirror. + add_rule(world.get_entrance('Dark Death Mountain Ledge Clip Spot', player), lambda state: state.has_Mirror(player), 'or') - # Set up some mirror-accessible DW entrances. - for spot in world.get_region('West Dark World', player).exits + world.get_region('South Dark World', player).exits: - if spot.name not in OWGSets.get_dw_bunny_inaccessible_locations(): - add_rule(world.get_entrance(spot, player), boots_and_mirror, 'or') - # DW entrances accessible with mirror and hookshot. - for spot in OWGSets.get_mirror_hookshot_accessible_dw_locations(world, player): - add_rule(world.get_entrance(spot, player), lambda state: state.has_Boots(player) and state.has_Mirror(player) and state.has('Hookshot', player), 'or') - # DW entrances accessible with mirror and titans. - boots_mirror_titans = lambda state: state.has_Boots(player) and state.has_Mirror(player) and state.can_lift_heavy_rocks(player) - add_rule(world.get_entrance('Mire Shed', player), boots_mirror_titans, 'or') - # Plus the mirror superbunny version. - add_rule(world.get_entrance('Mire Shed', player), lambda state: state.has('Ocarina', player) and state.has_Mirror(player) and state.can_lift_heavy_rocks(player), 'or') - add_rule(world.get_location('Frog', player), boots_mirror_titans, 'or') - else: - add_rule(world.get_entrance('East Death Mountain Mirror Spot (Bottom)', player), boots_and_mirror, 'or') + # Mirror clip spots. + for clip_spot in OWGSets.get_mirror_clip_spots_dw(): + set_rule(world.get_entrance(clip_spot, player), lambda state: state.has_Mirror(player)) # Locations that you can superbunny mirror into, but need a sword to clear. superbunny_mirror_weapon = lambda state: state.has_Mirror(player) and state.has_sword(player) @@ -783,10 +775,11 @@ def overworld_glitches_rules(world, player): # Regions that require the boots and some other stuff. if world.mode[player] != 'inverted': - set_rule(world.get_entrance('Dark Desert Teleporter', player), lambda state: state.has('Ocarina', player) or (state.has_Boots(player) and state.can_lift_heavy_rocks(player))) - add_rule(world.get_entrance('Ganons Tower', player), lambda state: state.has_Boots(player) and state.has_Pearl(player), 'or') - add_rule(world.get_entrance('East Death Mountain Teleporter', player), lambda state: state.can_lift_heavy_rocks(player) and state.has_Boots(player), 'or') - add_rule(world.get_entrance('Turtle Rock Teleporter', player), lambda state: state.has_Boots(player) and state.has('Hammer', player), 'or') + set_rule(world.get_entrance('Dark Desert Teleporter', player), lambda state: state.has('Ocarina', player) or (state.can_boots_clip_dw(player) and state.can_lift_heavy_rocks(player))) + set_rule(world.get_entrance('Turtle Rock Teleporter', player), lambda state: (state.can_boots_clip_dw(player) or state.can_lift_heavy_rocks(player)) and state.has('Hammer', player)) + add_rule(world.get_entrance('Catfish Exit Rock', player), lambda state: state.can_boots_clip_dw(player), 'or') + add_rule(world.get_entrance('East Dark World Broken Bridge Pass', player), lambda state: state.can_boots_clip_dw(player), 'or') + add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_reach('Dark Death Mountain (West Bottom)', 'Region', player) and state.has_Mirror(player)) else: add_rule(world.get_entrance('South Dark World Teleporter', player), lambda state: state.has_Boots(player) and state.can_lift_rocks(player), 'or') From 722dfa2b69b6658fb0b74000e0eb01ccae66cb19 Mon Sep 17 00:00:00 2001 From: qadan Date: Tue, 11 Feb 2020 01:14:57 -0400 Subject: [PATCH 40/52] fixing up inverted too --- EntranceShuffle.py | 34 +++++++++++++++++++++++++++++++++- InvertedRegions.py | 27 +++++++++++++++++---------- OWGSets.py | 36 ++++++++++++++++++++++++++---------- Regions.py | 6 +++--- Rules.py | 24 +++++++++++++++--------- 5 files changed, 94 insertions(+), 33 deletions(-) diff --git a/EntranceShuffle.py b/EntranceShuffle.py index d9c29422..39e17dfd 100644 --- a/EntranceShuffle.py +++ b/EntranceShuffle.py @@ -3020,6 +3020,8 @@ mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia Central ('Dark Death Mountain (East Bottom) Jump', 'Dark Death Mountain (East Bottom)'), ('Bat Cave River Clip Spot', 'Bat Cave Drop Ledge'), ('Turtle Rock (Top) Clip Spot', 'Turtle Rock (Top)'), + ('Dark Death Mountain Descent', 'West Dark World'), + ('Bombos Tablet Clip Spot', 'Bombos Tablet Ledge'), ] inverted_mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia Central Island'), @@ -3080,6 +3082,8 @@ inverted_mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia ('West Dark World Gap', 'West Dark World'), ('East Dark World Broken Bridge Pass', 'East Dark World'), ('Northeast Dark World Broken Bridge Pass', 'Northeast Dark World'), + ('Catfish Exit Rock', 'Northeast Dark World'), + ('Catfish Entrance Rock', 'Catfish'), ('Bumper Cave Entrance Rock', 'Bumper Cave Entrance'), ('Bumper Cave Entrance Drop', 'West Dark World'), ('Bumper Cave Ledge Drop', 'West Dark World'), @@ -3234,7 +3238,35 @@ inverted_mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia ('Bush Covered Lawn Mirror Spot', 'Dark Grassy Lawn'), ('Bomb Hut Inner Bushes', 'Light World'), ('Bomb Hut Outer Bushes', 'Bomb Hut Area'), - ('Bomb Hut Mirror Spot', 'West Dark World')] + ('Bomb Hut Mirror Spot', 'West Dark World'), + ('Light World DMA Clip Spot', 'Death Mountain'), + ('Hera Ascent', 'Death Mountain (Top)'), + ('Death Mountain Return Ledge Clip Spot', 'Death Mountain Return Ledge'), + ('Death Mountain Glitched Bridge', 'East Death Mountain (Top)'), + ('Dark Death Mountain Ledge Clip Spot', 'Dark Death Mountain Ledge'), + ('Zora Descent Clip Spot', 'Zoras River'), + ('Desert Northern Cliffs', 'Desert Ledge'), + ('Desert Northern Cliffs', 'Desert Palace Entrance (North) Spot'), + ('Lake Hylia Island Clip Spot', 'Lake Hylia Island'), + ('Dark World DMA Clip Spot', 'Dark Death Mountain'), + ('Bumper Cave Ledge Clip Spot', 'Bumper Cave Ledge'), + ('Hookshot Cave Island Clip Spot', 'Death Mountain Floating Island (Dark World)'), + ('Catfish Descent', 'Catfish'), + ('Death Mountain Offset Mirror', 'Light World'), + ('Hammer Pegs River Clip Spot', 'Hammer Peg Area'), + ('Dark Lake Hylia Ledge Clip Spot', 'Dark Lake Hylia Ledge'), + ('Dark Desert Cliffs Clip Spot', 'Dark Desert'), + ('Bumper Cave Ledge Clip Drop', 'Bumper Cave Entrance'), + ('Death Mountain Return Ledge Clip Drop', 'Death Mountain Entrance'), + ('Bumper Cave Entrance Clip (Broken Camera)', 'Bumper Cave Entrance'), + ('Death Mountain Entrance Clip (Broken Camera)', 'Death Mountain Entrance'), + ('Light World Bunny Descent', 'Light World'), + ('East Death Mountain (Bottom) Jump', 'East Death Mountain (Bottom)'), + ('Bat Cave River Clip Spot', 'Bat Cave Drop Ledge'), + ('Turtle Rock (Top) Clip Spot', 'Turtle Rock (Top)'), + ('Dark Death Mountain Descent', 'West Dark World'), + ('Death Mountain Descent', 'Light World'), + ('Death Mountain Bunny Descent Mirror Spot', 'Death Mountain Bunny Descent Area')] # non-shuffled entrance links default_connections = [('Waterfall of Wishing', 'Waterfall of Wishing'), ("Blinds Hideout", "Blinds Hideout"), diff --git a/InvertedRegions.py b/InvertedRegions.py index cfbf5ed0..b8298bc0 100644 --- a/InvertedRegions.py +++ b/InvertedRegions.py @@ -18,7 +18,8 @@ def create_inverted_regions(world, player): 'Bonk Fairy (Light)', '50 Rupee Cave', 'Fortune Teller (Light)', 'Lake Hylia Fairy', 'Light Hype Fairy', 'Desert Fairy', 'Lumberjack House', 'Lake Hylia Fortune Teller', 'Kakariko Gamble Game', 'East Dark World Mirror Spot', 'West Dark World Mirror Spot', 'South Dark World Mirror Spot', 'Cave 45', 'Checkerboard Cave', 'Mire Mirror Spot', 'Hammer Peg Area Mirror Spot', 'Shopping Mall Mirror Spot', 'Skull Woods Mirror Spot', 'Inverted Pyramid Entrance','Hyrule Castle Entrance (South)', 'Secret Passage Outer Bushes', 'Bush Covered Lawn Outer Bushes', - 'Potion Shop Outer Bushes', 'Graveyard Cave Outer Bushes', 'Bomb Hut Outer Bushes']), + 'Potion Shop Outer Bushes', 'Graveyard Cave Outer Bushes', 'Bomb Hut Outer Bushes', 'Light World DMA Clip Spot', 'Death Mountain Return Ledge Clip Spot', 'Bat Cave River Clip Spot', + 'Desert Northern Cliffs', 'Lake Hylia Island Clip Spot', 'Death Mountain Entrance Clip (Broken Camera)']), create_lw_region(player, 'Bush Covered Lawn', None, ['Bush Covered House', 'Bush Covered Lawn Inner Bushes', 'Bush Covered Lawn Mirror Spot']), create_lw_region(player, 'Bomb Hut Area', None, ['Light World Bomb Hut', 'Bomb Hut Inner Bushes', 'Bomb Hut Mirror Spot']), create_lw_region(player, 'Hyrule Castle Secret Entrance Area', None, ['Hyrule Castle Secret Entrance Stairs', 'Secret Passage Inner Bushes']), @@ -125,9 +126,10 @@ def create_inverted_regions(world, player): create_cave_region(player, 'Old Man House', 'a connector', None, ['Old Man House Exit (Bottom)', 'Old Man House Front to Back']), create_cave_region(player, 'Old Man House Back', 'a connector', None, ['Old Man House Exit (Top)', 'Old Man House Back to Front']), create_lw_region(player, 'Death Mountain', None, ['Old Man Cave (East)', 'Old Man House (Bottom)', 'Old Man House (Top)', 'Death Mountain Return Cave (East)', 'Spectacle Rock Cave', - 'Spectacle Rock Cave Peak', 'Spectacle Rock Cave (Bottom)', 'Broken Bridge (West)', 'Death Mountain Mirror Spot']), + 'Spectacle Rock Cave Peak', 'Spectacle Rock Cave (Bottom)', 'Broken Bridge (West)', 'Death Mountain Mirror Spot', 'Death Mountain Bunny Descent Mirror Spot', + 'Death Mountain Offset Mirror', 'Hera Ascent', 'Death Mountain Glitched Bridge', 'Death Mountain Descent']), create_cave_region(player, 'Death Mountain Return Cave', 'a connector', None, ['Death Mountain Return Cave Exit (West)', 'Death Mountain Return Cave Exit (East)']), - create_lw_region(player, 'Death Mountain Return Ledge', None, ['Death Mountain Return Ledge Drop', 'Death Mountain Return Cave (West)', 'Bumper Cave Ledge Mirror Spot']), + create_lw_region(player, 'Death Mountain Return Ledge', None, ['Death Mountain Return Ledge Drop', 'Death Mountain Return Cave (West)', 'Bumper Cave Ledge Mirror Spot', 'Death Mountain Return Ledge Clip Drop']), create_cave_region(player, 'Spectacle Rock Cave (Top)', 'a connector', ['Spectacle Rock Cave'], ['Spectacle Rock Cave Drop', 'Spectacle Rock Cave Exit (Top)']), create_cave_region(player, 'Spectacle Rock Cave (Bottom)', 'a connector', None, ['Spectacle Rock Cave Exit']), create_cave_region(player, 'Spectacle Rock Cave (Peak)', 'a connector', None, ['Spectacle Rock Cave Peak Drop', 'Spectacle Rock Cave Exit (Peak)']), @@ -146,7 +148,7 @@ def create_inverted_regions(world, player): create_cave_region(player, 'Paradox Cave', 'a connector', None, ['Paradox Cave Exit (Middle)', 'Paradox Cave Exit (Top)', 'Paradox Cave Drop']), create_cave_region(player, 'Light World Death Mountain Shop', 'a common shop'), create_lw_region(player, 'East Death Mountain (Top)', ['Floating Island'], ['Paradox Cave (Top)', 'Death Mountain (Top)', 'Spiral Cave Ledge Access', 'East Death Mountain Drop', 'East Death Mountain Mirror Spot (Top)', 'Fairy Ascension Ledge Access', 'Mimic Cave Ledge Access', - 'Floating Island Mirror Spot']), + 'Floating Island Mirror Spot', 'Zora Descent Clip Spot']), create_lw_region(player, 'Spiral Cave Ledge', None, ['Spiral Cave', 'Spiral Cave Ledge Drop', 'Dark Death Mountain Ledge Mirror Spot (West)']), create_lw_region(player, 'Mimic Cave Ledge', None, ['Mimic Cave', 'Mimic Cave Ledge Drop', 'Dark Death Mountain Ledge Mirror Spot (East)']), create_cave_region(player, 'Spiral Cave (Top)', 'a connector', ['Spiral Cave'], ['Spiral Cave (top to bottom)', 'Spiral Cave Exit (Top)']), @@ -157,14 +159,16 @@ def create_inverted_regions(world, player): create_cave_region(player, 'Fairy Ascension Cave (Top)', 'a connector', None, ['Fairy Ascension Cave Exit (Top)', 'Fairy Ascension Cave Drop']), create_lw_region(player, 'Fairy Ascension Ledge', None, ['Fairy Ascension Ledge Drop', 'Fairy Ascension Cave (Top)', 'Laser Bridge Mirror Spot']), create_lw_region(player, 'Death Mountain (Top)', ['Ether Tablet', 'Spectacle Rock'], ['East Death Mountain (Top)', 'Tower of Hera', 'Death Mountain Drop', 'Death Mountain (Top) Mirror Spot']), - create_dw_region(player, 'Bumper Cave Ledge', ['Bumper Cave Ledge'], ['Bumper Cave Ledge Drop', 'Bumper Cave (Top)']), + create_dw_region(player, 'Bumper Cave Ledge', ['Bumper Cave Ledge'], ['Bumper Cave Ledge Drop', 'Bumper Cave (Top)', 'Bumper Cave Ledge Clip Drop']), create_dungeon_region(player, 'Tower of Hera (Bottom)', 'Tower of Hera', ['Tower of Hera - Basement Cage', 'Tower of Hera - Map Chest'], ['Tower of Hera Small Key Door', 'Tower of Hera Big Key Door', 'Tower of Hera Exit']), create_dungeon_region(player, 'Tower of Hera (Basement)', 'Tower of Hera', ['Tower of Hera - Big Key Chest']), create_dungeon_region(player, 'Tower of Hera (Top)', 'Tower of Hera', ['Tower of Hera - Compass Chest', 'Tower of Hera - Big Chest', 'Tower of Hera - Boss', 'Tower of Hera - Prize']), create_dw_region(player, 'East Dark World', ['Pyramid'], ['Pyramid Fairy', 'South Dark World Bridge', 'Palace of Darkness', 'Dark Lake Hylia Drop (East)', - 'Dark Lake Hylia Fairy', 'Palace of Darkness Hint', 'East Dark World Hint', 'Northeast Dark World Broken Bridge Pass', 'East Dark World Teleporter', 'EDW Flute']), - create_dw_region(player, 'Northeast Dark World', ['Catfish'], ['West Dark World Gap', 'Dark World Potion Shop', 'East Dark World Broken Bridge Pass', 'NEDW Flute', 'Dark Lake Hylia Teleporter']), + 'Dark Lake Hylia Fairy', 'Palace of Darkness Hint', 'East Dark World Hint', 'Northeast Dark World Broken Bridge Pass', 'East Dark World Teleporter', 'EDW Flute', + 'Hammer Pegs River Clip Spot', 'Dark Lake Hylia Ledge Clip Spot', 'Dark Desert Cliffs Clip Spot']), + create_dw_region(player, 'Catfish', ['Catfish'], ['Catfish Exit Rock']), + create_dw_region(player, 'Northeast Dark World', None, ['West Dark World Gap', 'Dark World Potion Shop', 'East Dark World Broken Bridge Pass', 'NEDW Flute', 'Dark Lake Hylia Teleporter', 'Catfish Entrance Rock']), create_cave_region(player, 'Palace of Darkness Hint', 'a storyteller'), create_cave_region(player, 'East Dark World Hint', 'a storyteller'), create_dw_region(player, 'South Dark World', ['Stumpy', 'Digging Game'], ['Dark Lake Hylia Drop (South)', 'Hype Cave', 'Swamp Palace', 'Village of Outcasts Heavy Rock', 'East Dark World Bridge', 'Inverted Links House', 'Archery Game', 'Bonk Fairy (Dark)', @@ -179,7 +183,7 @@ def create_inverted_regions(world, player): 'Hype Cave - Bottom', 'Hype Cave - Generous Guy']), create_dw_region(player, 'West Dark World', ['Frog'], ['Village of Outcasts Drop', 'East Dark World River Pier', 'Brewery', 'C-Shaped House', 'Chest Game', 'Thieves Town', 'Bumper Cave Entrance Rock', 'Skull Woods Forest', 'Village of Outcasts Pegs', 'Village of Outcasts Eastern Rocks', 'Red Shield Shop', 'Inverted Dark Sanctuary', 'Fortune Teller (Dark)', 'Dark World Lumberjack Shop', - 'West Dark World Teleporter', 'WDW Flute']), + 'West Dark World Teleporter', 'WDW Flute', 'Dark World DMA Clip Spot', 'Bumper Cave Ledge Clip Spot', 'Bumper Cave Entrance Clip (Broken Camera)']), create_dw_region(player, 'Dark Grassy Lawn', None, ['Grassy Lawn Pegs', 'Dark World Shop', 'Dark Grassy Lawn Flute']), create_dw_region(player, 'Hammer Peg Area', ['Dark Blacksmith Ruins'], ['Dark World Hammer Peg Cave', 'Peg Area Rocks', 'Hammer Peg Area Flute']), create_dw_region(player, 'Bumper Cave Entrance', None, ['Bumper Cave (Bottom)', 'Bumper Cave Entrance Drop']), @@ -204,7 +208,9 @@ def create_inverted_regions(world, player): create_cave_region(player, 'Mire Shed', 'a cave with two chests', ['Mire Shed - Left', 'Mire Shed - Right']), create_cave_region(player, 'Dark Desert Hint', 'a storyteller'), create_dw_region(player, 'Dark Death Mountain', None, ['Dark Death Mountain Drop (East)', 'Inverted Agahnims Tower', 'Superbunny Cave (Top)', 'Hookshot Cave', 'Turtle Rock', - 'Spike Cave', 'Dark Death Mountain Fairy', 'Dark Death Mountain Teleporter (West)', 'Turtle Rock Tail Drop', 'DDM Flute']), + 'Spike Cave', 'Dark Death Mountain Fairy', 'Dark Death Mountain Teleporter (West)', 'Turtle Rock Tail Drop', 'DDM Flute', + 'Dark Death Mountain Ledge Clip Spot', 'Hookshot Cave Island Clip Spot', 'Catfish Descent', 'Turtle Rock (Top) Clip Spot', + 'Dark Death Mountain Descent']), create_dw_region(player, 'Dark Death Mountain Ledge', None, ['Dark Death Mountain Ledge (East)', 'Dark Death Mountain Ledge (West)']), create_dw_region(player, 'Turtle Rock (Top)', None, ['Dark Death Mountain Teleporter (East)', 'Turtle Rock Drop']), create_dw_region(player, 'Dark Death Mountain Isolated Ledge', None, ['Turtle Rock Isolated Ledge Entrance']), @@ -297,7 +303,8 @@ def create_inverted_regions(world, player): create_dungeon_region(player, 'Agahnim 2', 'Ganon\'s Tower', ['Ganons Tower - Validation Chest', 'Agahnim 2'], None), create_cave_region(player, 'Pyramid', 'a drop\'s exit', ['Ganon'], ['Ganon Drop']), create_cave_region(player, 'Bottom of Pyramid', 'a drop\'s exit', None, ['Pyramid Exit']), - create_dw_region(player, 'Pyramid Ledge', None, ['Pyramid Drop']), # houlihan room exits here in inverted + create_dw_region(player, 'Pyramid Ledge', None, ['Pyramid Drop']), # houlihan room exits here in inverted + create_dw_region(player, 'Death Mountain Bunny Descent Area', None, ['Light World Bunny Descent', 'East Death Mountain (Bottom) Jump']), # to simplify flute connections create_cave_region(player, 'The Sky', 'A Dark Sky', None, ['DDM Landing','NEDW Landing', 'WDW Landing', 'SDW Landing', 'EDW Landing', 'DD Landing', 'DLHL Landing']) diff --git a/OWGSets.py b/OWGSets.py index b465a35b..bba90656 100644 --- a/OWGSets.py +++ b/OWGSets.py @@ -96,43 +96,50 @@ def get_superbunny_accessible_locations(): ] -def get_boots_clip_exits_lw(): +def get_boots_clip_exits_lw(inverted = False): ''' Special Light World region exits that require boots clips. ''' - return [ + exits = [ 'Bat Cave River Clip Spot', 'Light World DMA Clip Spot', 'Hera Ascent', - 'Spectacle Rock Clip Spot', 'Death Mountain Return Ledge Clip Spot', 'Death Mountain Glitched Bridge', - 'Floating Island Clip Spot', 'Zora Descent Clip Spot', - 'Graveyard Ledge Clip Spot', 'Desert Northern Cliffs', 'Lake Hylia Island Clip Spot', 'Death Mountain Entrance Clip (Broken Camera)', + 'Death Mountain Descent', ] + if not inverted: + exits.append('Spectacle Rock Clip Spot') + exits.append('Graveyard Ledge Clip Spot') + exits.append('Bombos Tablet Clip Spot') + exits.append('Floating Island Clip Spot') + return exits -def get_boots_clip_exits_dw(): +def get_boots_clip_exits_dw(inverted = False): ''' Special Dark World region exits that require boots clips. ''' - return [ + exits = [ 'Dark World DMA Clip Spot', - 'Ganons Tower Ascent', 'Bumper Cave Ledge Clip Spot', - 'Dark Death Mountain Glitched Bridge', 'Hookshot Cave Island Clip Spot', 'Catfish Descent', 'Hammer Pegs River Clip Spot', 'Dark Lake Hylia Ledge Clip Spot', 'Dark Desert Cliffs Clip Spot', 'Bumper Cave Entrance Clip (Broken Camera)', - 'Turtle Rock (Top) Clip Spot', + 'Dark Death Mountain Descent', ] + if not inverted: + exits.append('Ganons Tower Ascent') + exits.append('Dark Death Mountain Glitched Bridge') + exits.append('Turtle Rock (Top) Clip Spot') + return exits def get_glitched_speed_drops_lw(): @@ -162,3 +169,12 @@ def get_mirror_clip_spots_dw(): 'Dark Death Mountain Offset Mirror', 'Dark Death Mountain Bunny Descent Mirror Spot', ] + + +def get_mirror_clip_spots_lw(): + ''' + Inverted mirror shenanigans in logic even if the player is a bunny. + ''' + return [ + 'Death Mountain Bunny Descent Mirror Spot', + ] diff --git a/Regions.py b/Regions.py index cd20ecb0..2011b434 100644 --- a/Regions.py +++ b/Regions.py @@ -15,7 +15,7 @@ def create_regions(world, player): 'Elder House (East)', 'Elder House (West)', 'North Fairy Cave', 'North Fairy Cave Drop', 'Lost Woods Gamble', 'Snitch Lady (East)', 'Snitch Lady (West)', 'Tavern (Front)', 'Bush Covered House', 'Light World Bomb Hut', 'Kakariko Shop', 'Long Fairy Cave', 'Good Bee Cave', '20 Rupee Cave', 'Cave Shop (Lake Hylia)', 'Waterfall of Wishing', 'Hyrule Castle Main Gate', 'Bonk Fairy (Light)', '50 Rupee Cave', 'Fortune Teller (Light)', 'Lake Hylia Fairy', 'Light Hype Fairy', 'Desert Fairy', 'Lumberjack House', 'Lake Hylia Fortune Teller', 'Kakariko Gamble Game', 'Top of Pyramid', - 'Light World DMA Clip Spot', 'Death Mountain Return Ledge Clip Spot', 'Desert Northern Cliffs', 'Lake Hylia Island Clip Spot', 'Death Mountain Entrance Clip (Broken Camera)', 'Bat Cave River Clip Spot']), + 'Light World DMA Clip Spot', 'Death Mountain Return Ledge Clip Spot', 'Desert Northern Cliffs', 'Lake Hylia Island Clip Spot', 'Death Mountain Entrance Clip (Broken Camera)', 'Bat Cave River Clip Spot', 'Bombos Tablet Clip Spot']), create_lw_region(player, 'Death Mountain Entrance', None, ['Old Man Cave (West)', 'Death Mountain Entrance Drop']), create_lw_region(player, 'Lake Hylia Central Island', None, ['Capacity Upgrade', 'Lake Hylia Central Island Teleporter']), create_cave_region(player, 'Blinds Hideout', 'a bounty of five items', ["Blind\'s Hideout - Top", @@ -118,7 +118,7 @@ def create_regions(world, player): create_cave_region(player, 'Old Man Cave', 'a connector', ['Old Man'], ['Old Man Cave Exit (East)', 'Old Man Cave Exit (West)']), create_cave_region(player, 'Old Man House', 'a connector', None, ['Old Man House Exit (Bottom)', 'Old Man House Front to Back']), create_cave_region(player, 'Old Man House Back', 'a connector', None, ['Old Man House Exit (Top)', 'Old Man House Back to Front']), - create_lw_region(player, 'Death Mountain', None, ['Old Man Cave (East)', 'Old Man House (Bottom)', 'Old Man House (Top)', 'Death Mountain Return Cave (East)', 'Spectacle Rock Cave', 'Spectacle Rock Cave Peak', 'Spectacle Rock Cave (Bottom)', 'Broken Bridge (West)', 'Death Mountain Teleporter', 'Death Mountain Glitched Bridge', 'Graveyard Ledge Clip Spot', 'Hera Ascent']), + create_lw_region(player, 'Death Mountain', None, ['Old Man Cave (East)', 'Old Man House (Bottom)', 'Old Man House (Top)', 'Death Mountain Return Cave (East)', 'Spectacle Rock Cave', 'Spectacle Rock Cave Peak', 'Spectacle Rock Cave (Bottom)', 'Broken Bridge (West)', 'Death Mountain Teleporter', 'Death Mountain Glitched Bridge', 'Graveyard Ledge Clip Spot', 'Hera Ascent', 'Death Mountain Descent']), create_cave_region(player, 'Death Mountain Return Cave', 'a connector', None, ['Death Mountain Return Cave Exit (West)', 'Death Mountain Return Cave Exit (East)']), create_lw_region(player, 'Death Mountain Return Ledge', None, ['Death Mountain Return Ledge Drop', 'Death Mountain Return Cave (West)', 'Death Mountain Return Ledge Clip Drop']), create_cave_region(player, 'Spectacle Rock Cave (Top)', 'a connector', ['Spectacle Rock Cave'], ['Spectacle Rock Cave Drop', 'Spectacle Rock Cave Exit (Top)']), @@ -199,7 +199,7 @@ def create_regions(world, player): 'Desert Palace Entrance (North) Mirror Spot', 'Dark Desert Hint', 'Dark Desert Fairy']), create_cave_region(player, 'Mire Shed', 'a cave with two chests', ['Mire Shed - Left', 'Mire Shed - Right']), create_cave_region(player, 'Dark Desert Hint', 'a storyteller'), - create_dw_region(player, 'Dark Death Mountain (West Bottom)', None, ['Spike Cave', 'Spectacle Rock Mirror Spot', 'Dark Death Mountain Fairy', 'Ganons Tower Ascent', 'Dark Death Mountain Glitched Bridge', 'Dark Death Mountain Bunny Descent Mirror Spot', 'Dark Death Mountain Offset Mirror']), + create_dw_region(player, 'Dark Death Mountain (West Bottom)', None, ['Spike Cave', 'Spectacle Rock Mirror Spot', 'Dark Death Mountain Fairy', 'Ganons Tower Ascent', 'Dark Death Mountain Glitched Bridge', 'Dark Death Mountain Bunny Descent Mirror Spot', 'Dark Death Mountain Offset Mirror', 'Dark Death Mountain Descent']), create_dw_region(player, 'Dark Death Mountain (Top)', None, ['Dark Death Mountain Drop (East)', 'Dark Death Mountain Drop (West)', 'Ganons Tower', 'Superbunny Cave (Top)', 'Hookshot Cave', 'East Death Mountain (Top) Mirror Spot', 'Turtle Rock', 'Hookshot Cave Island Clip Spot', 'Catfish Descent', 'Dark Death Mountain Ledge Clip Spot', 'Turtle Rock (Top) Clip Spot']), create_dw_region(player, 'Dark Death Mountain Ledge', None, ['Dark Death Mountain Ledge (East)', 'Dark Death Mountain Ledge (West)', 'Mimic Cave Mirror Spot', 'Spiral Cave Mirror Spot']), diff --git a/Rules.py b/Rules.py index 094d9d8d..3f0c3672 100644 --- a/Rules.py +++ b/Rules.py @@ -470,16 +470,17 @@ def default_rules(world, player): def forbid_overworld_glitches(world, player): - for exit in OWGSets.get_boots_clip_exits_lw(): + for exit in OWGSets.get_boots_clip_exits_lw(world.mode[player] == 'inverted'): set_rule(world.get_entrance(exit, player), lambda state: False) - for exit in OWGSets.get_boots_clip_exits_dw(): + for exit in OWGSets.get_boots_clip_exits_dw(world.mode[player] == 'inverted'): set_rule(world.get_entrance(exit, player), lambda state: False) for exit in OWGSets.get_glitched_speed_drops_lw(): set_rule(world.get_entrance(exit, player), lambda state: False) for exit in OWGSets.get_glitched_speed_drops_dw(): set_rule(world.get_entrance(exit, player), lambda state: False) - for exit in OWGSets.get_mirror_clip_spots_dw(): - set_rule(world.get_entrance(exit, player), lambda state: False) + if world.mode[player] != 'inverted': + for exit in OWGSets.get_mirror_clip_spots_dw(): + set_rule(world.get_entrance(exit, player), lambda state: False) def inverted_rules(world, player): @@ -747,9 +748,9 @@ def overworld_glitches_rules(world, player): set_rule(world.get_entrance(entrance, player), lambda state: True) # Boots-accessible locations. - for entrance in OWGSets.get_boots_clip_exits_lw(): + for entrance in OWGSets.get_boots_clip_exits_lw(world.mode[player] == 'inverted'): set_rule(world.get_entrance(entrance, player), lambda state: state.can_boots_clip_lw(player)) - for entrance in OWGSets.get_boots_clip_exits_dw(): + for entrance in OWGSets.get_boots_clip_exits_dw(world.mode[player] == 'inverted'): set_rule(world.get_entrance(entrance, player), lambda state: state.can_boots_clip_dw(player)) # Glitched speed drops. @@ -758,11 +759,16 @@ def overworld_glitches_rules(world, player): for drop in OWGSets.get_glitched_speed_drops_dw(): set_rule(world.get_entrance(drop, player), lambda state: state.can_get_glitched_speed_dw(player)) # Dark Death Mountain Ledge Clip Spot also accessible with mirror. - add_rule(world.get_entrance('Dark Death Mountain Ledge Clip Spot', player), lambda state: state.has_Mirror(player), 'or') + if world.mode[player] != 'inverted': + add_rule(world.get_entrance('Dark Death Mountain Ledge Clip Spot', player), lambda state: state.has_Mirror(player), 'or') # Mirror clip spots. - for clip_spot in OWGSets.get_mirror_clip_spots_dw(): - set_rule(world.get_entrance(clip_spot, player), lambda state: state.has_Mirror(player)) + if world.mode[player] != 'inverted': + for clip_spot in OWGSets.get_mirror_clip_spots_dw(): + set_rule(world.get_entrance(clip_spot, player), lambda state: state.has_Mirror(player)) + else: + for clip_spot in OWGSets.get_mirror_clip_spots_lw(): + set_rule(world.get_entrance(clip_spot, player), lambda state: state.has_Mirror(player)) # Locations that you can superbunny mirror into, but need a sword to clear. superbunny_mirror_weapon = lambda state: state.has_Mirror(player) and state.has_sword(player) From 5c87e148c660ea40548c9ef64d14304fdb24d8e6 Mon Sep 17 00:00:00 2001 From: qadan Date: Tue, 11 Feb 2020 01:31:23 -0400 Subject: [PATCH 41/52] forgot a thing --- EntranceShuffle.py | 1 + 1 file changed, 1 insertion(+) diff --git a/EntranceShuffle.py b/EntranceShuffle.py index 39e17dfd..5911fb16 100644 --- a/EntranceShuffle.py +++ b/EntranceShuffle.py @@ -3021,6 +3021,7 @@ mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia Central ('Bat Cave River Clip Spot', 'Bat Cave Drop Ledge'), ('Turtle Rock (Top) Clip Spot', 'Turtle Rock (Top)'), ('Dark Death Mountain Descent', 'West Dark World'), + ('Death Mountain Descent', 'Light World'), ('Bombos Tablet Clip Spot', 'Bombos Tablet Ledge'), ] From f40516d04f910837f0dfa10e9c35fc7d10286115 Mon Sep 17 00:00:00 2001 From: qadan Date: Tue, 11 Feb 2020 01:57:36 -0400 Subject: [PATCH 42/52] missing cave 45 --- EntranceShuffle.py | 1 + OWGSets.py | 1 + Regions.py | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/EntranceShuffle.py b/EntranceShuffle.py index 5911fb16..70d03956 100644 --- a/EntranceShuffle.py +++ b/EntranceShuffle.py @@ -3023,6 +3023,7 @@ mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia Central ('Dark Death Mountain Descent', 'West Dark World'), ('Death Mountain Descent', 'Light World'), ('Bombos Tablet Clip Spot', 'Bombos Tablet Ledge'), + ('Cave 45 Clip Spot', 'Cave 45 Ledge'), ] inverted_mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia Central Island'), diff --git a/OWGSets.py b/OWGSets.py index bba90656..50796794 100644 --- a/OWGSets.py +++ b/OWGSets.py @@ -117,6 +117,7 @@ def get_boots_clip_exits_lw(inverted = False): exits.append('Graveyard Ledge Clip Spot') exits.append('Bombos Tablet Clip Spot') exits.append('Floating Island Clip Spot') + exits.append('Cave 45 Clip Spot') return exits diff --git a/Regions.py b/Regions.py index 2011b434..a8223752 100644 --- a/Regions.py +++ b/Regions.py @@ -15,7 +15,7 @@ def create_regions(world, player): 'Elder House (East)', 'Elder House (West)', 'North Fairy Cave', 'North Fairy Cave Drop', 'Lost Woods Gamble', 'Snitch Lady (East)', 'Snitch Lady (West)', 'Tavern (Front)', 'Bush Covered House', 'Light World Bomb Hut', 'Kakariko Shop', 'Long Fairy Cave', 'Good Bee Cave', '20 Rupee Cave', 'Cave Shop (Lake Hylia)', 'Waterfall of Wishing', 'Hyrule Castle Main Gate', 'Bonk Fairy (Light)', '50 Rupee Cave', 'Fortune Teller (Light)', 'Lake Hylia Fairy', 'Light Hype Fairy', 'Desert Fairy', 'Lumberjack House', 'Lake Hylia Fortune Teller', 'Kakariko Gamble Game', 'Top of Pyramid', - 'Light World DMA Clip Spot', 'Death Mountain Return Ledge Clip Spot', 'Desert Northern Cliffs', 'Lake Hylia Island Clip Spot', 'Death Mountain Entrance Clip (Broken Camera)', 'Bat Cave River Clip Spot', 'Bombos Tablet Clip Spot']), + 'Light World DMA Clip Spot', 'Death Mountain Return Ledge Clip Spot', 'Desert Northern Cliffs', 'Lake Hylia Island Clip Spot', 'Death Mountain Entrance Clip (Broken Camera)', 'Bat Cave River Clip Spot', 'Bombos Tablet Clip Spot', 'Cave 45 Clip Spot']), create_lw_region(player, 'Death Mountain Entrance', None, ['Old Man Cave (West)', 'Death Mountain Entrance Drop']), create_lw_region(player, 'Lake Hylia Central Island', None, ['Capacity Upgrade', 'Lake Hylia Central Island Teleporter']), create_cave_region(player, 'Blinds Hideout', 'a bounty of five items', ["Blind\'s Hideout - Top", From 720ce8c49280b936a7eca2266e69770459c7c0cb Mon Sep 17 00:00:00 2001 From: qadan Date: Tue, 11 Feb 2020 13:01:47 -0400 Subject: [PATCH 43/52] fixing dungeon bunny revive --- Rules.py | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/Rules.py b/Rules.py index 3f0c3672..0e79354d 100644 --- a/Rules.py +++ b/Rules.py @@ -1,7 +1,7 @@ import collections import logging import OWGSets -from BaseClasses import CollectionState +from BaseClasses import CollectionState, RegionType def set_rules(world, player): @@ -1330,8 +1330,6 @@ def set_inverted_big_bomb_rules(world, player): def set_bunny_rules(world, player): - # If you can get to a dungeon exit, you can bunny revive. - dungeon_exits = ['Desert Palace Exit (South)', 'Desert Palace Exit (West)', 'Desert Palace Exit (East)', 'Desert Palace Exit (North)', 'Eastern Palace Exit', 'Tower of Hera Exit', 'Thieves Town Exit', 'Skull Woods Final Section Exit', 'Misery Mire Exit', 'Palace of Darkness Exit', 'Swamp Palace Exit', 'Agahnims Tower Exit', 'Turtle Rock Ledge Exit (East)', 'Turtle Rock Exit (Front)', 'Turtle Rock Ledge Exit (West)', 'Turtle Rock Isolated Ledge Exit'] # regions for the exits of multi-entrace caves/drops that bunny cannot pass # Note spiral cave may be technically passible, but it would be too absurd to require since OHKO mode is a thing. bunny_impassable_caves = ['Bumper Cave', 'Two Brothers House', 'Hookshot Cave', 'Skull Woods First Section (Right)', 'Skull Woods First Section (Left)', 'Skull Woods First Section (Top)', 'Turtle Rock (Entrance)', 'Turtle Rock (Second Section)', 'Turtle Rock (Big Chest)', 'Skull Woods Second Section (Drop)', @@ -1347,8 +1345,14 @@ def set_bunny_rules(world, player): return lambda state: any(rule(state) for rule in options) def get_rule_to_add(region, location = None): - if not region.is_light_world and not (world.logic[player] == 'owglitches' and location in OWGSets.get_superbunny_accessible_locations() and region.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw()): + if world.logic[player] == 'owglitches' and not any([ + location in OWGSets.get_superbunny_accessible_locations() and region.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(), + region.type == RegionType.Dungeon and region.name != 'Swamp Palace (Entrance)', + not region.is_light_world]): return lambda state: state.has_Pearl(player) + elif world.logic[player] != 'owglitches' and not region.is_light_world: + return lambda state: state.has_Pearl(player) + # in this case we are mixed region. # we collect possible options. @@ -1377,16 +1381,12 @@ def set_bunny_rules(world, player): if location.name in OWGSets.get_superbunny_accessible_locations(): possible_options.append(lambda state: path_to_access_rule(new_path, entrance) and state.has_Mirror(player)) continue - for exit in new_region.exits: - if exit.name in dungeon_exits: - possible_options.append(path_to_access_rule(new_path, entrance)) - continue else: continue if new_region.is_dark_world: queue.append((new_region, new_path)) else: - # we have reached pure light world, so we have a new possible option + # we have reached pure light world or a dungeon, so we have a new possible option possible_options.append(path_to_access_rule(new_path, entrance)) return options_to_access_rule(possible_options) @@ -1416,8 +1416,6 @@ def set_bunny_rules(world, player): add_rule(location, get_rule_to_add(location.parent_region, location.name)) def set_inverted_bunny_rules(world, player): - # If you can get to a dungeon exit, you can bunny revive. - dungeon_exits = ['Desert Palace Exit (South)', 'Desert Palace Exit (West)', 'Desert Palace Exit (East)', 'Desert Palace Exit (North)', 'Eastern Palace Exit', 'Tower of Hera Exit', 'Thieves Town Exit', 'Skull Woods Final Section Exit', 'Ice Palace Exit', 'Misery Mire Exit', 'Palace of Darkness Exit', 'Inverted Agahnims Tower Exit', 'Turtle Rock Ledge Exit (East)', 'Turtle Rock Exit (Front)', 'Turtle Rock Ledge Exit (West)', 'Turtle Rock Isolated Ledge Exit'] # regions for the exits of multi-entrace caves/drops that bunny cannot pass # Note spiral cave may be technically passible, but it would be too absurd to require since OHKO mode is a thing. bunny_impassable_caves = ['Bumper Cave', 'Two Brothers House', 'Hookshot Cave', 'Skull Woods First Section (Right)', 'Skull Woods First Section (Left)', 'Skull Woods First Section (Top)', 'Turtle Rock (Entrance)', 'Turtle Rock (Second Section)', 'Turtle Rock (Big Chest)', 'Skull Woods Second Section (Drop)', @@ -1431,7 +1429,12 @@ def set_inverted_bunny_rules(world, player): return lambda state: any(rule(state) for rule in options) def get_rule_to_add(region, location = None): - if not region.is_dark_world and not (world.logic[player] == 'owglitches' and location in bunny_accessible_locations and region.name not in invalid_mirror_bunny_entrances_lw): + if world.logic[player] == 'owglitches' and not any([ + location in OWGSets.get_superbunny_accessible_locations() and region.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(), + region.type == RegionType.Dungeon and region.name != 'Swamp Palace (Entrance)', + not region.is_dark_world]): + return lambda state: state.has_Pearl(player) + elif world.logic[player] != 'owglitches' and not region.is_dark_world: return lambda state: state.has_Pearl(player) # in this case we are mixed region. # we collect possible options. @@ -1461,10 +1464,6 @@ def set_inverted_bunny_rules(world, player): if location.name in OWGSets.get_superbunny_accessible_locations(): possible_options.append(lambda state: path_to_access_rule(new_path, entrance) and state.has_Mirror(player)) continue - for exit in new_region.exits: - if exit.name in dungeon_exits: - possible_options.append(path_to_access_rule(new_path, entrance)) - continue else: continue if new_region.is_light_world: From 3533f8cbb3f3f7aabb0047ea9b05179b9c612023 Mon Sep 17 00:00:00 2001 From: qadan Date: Tue, 11 Feb 2020 14:11:50 -0400 Subject: [PATCH 44/52] non required exits --- EntranceShuffle.py | 12 ++++-------- InvertedRegions.py | 8 ++++---- OWGSets.py | 12 ------------ Regions.py | 8 ++++---- Rules.py | 4 ---- 5 files changed, 12 insertions(+), 32 deletions(-) diff --git a/EntranceShuffle.py b/EntranceShuffle.py index 70d03956..6be3f28f 100644 --- a/EntranceShuffle.py +++ b/EntranceShuffle.py @@ -3012,10 +3012,8 @@ mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia Central ('Hammer Pegs River Clip Spot', 'Hammer Peg Area'), ('Dark Lake Hylia Ledge Clip Spot', 'Dark Lake Hylia Ledge'), ('Dark Desert Cliffs Clip Spot', 'Dark Desert'), - ('Bumper Cave Ledge Clip Drop', 'Bumper Cave Entrance'), - ('Death Mountain Return Ledge Clip Drop', 'Death Mountain Entrance'), - ('Bumper Cave Entrance Clip (Broken Camera)', 'Bumper Cave Entrance'), - ('Death Mountain Entrance Clip (Broken Camera)', 'Death Mountain Entrance'), + ('Bumper Cave Ledge Clip Spot', 'Bumper Cave Entrance'), + ('Death Mountain Return Ledge Clip Spot', 'Death Mountain Entrance'), ('West Dark World Bunny Descent', 'West Dark World'), ('Dark Death Mountain (East Bottom) Jump', 'Dark Death Mountain (East Bottom)'), ('Bat Cave River Clip Spot', 'Bat Cave Drop Ledge'), @@ -3258,10 +3256,8 @@ inverted_mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia ('Hammer Pegs River Clip Spot', 'Hammer Peg Area'), ('Dark Lake Hylia Ledge Clip Spot', 'Dark Lake Hylia Ledge'), ('Dark Desert Cliffs Clip Spot', 'Dark Desert'), - ('Bumper Cave Ledge Clip Drop', 'Bumper Cave Entrance'), - ('Death Mountain Return Ledge Clip Drop', 'Death Mountain Entrance'), - ('Bumper Cave Entrance Clip (Broken Camera)', 'Bumper Cave Entrance'), - ('Death Mountain Entrance Clip (Broken Camera)', 'Death Mountain Entrance'), + ('Bumper Cave Ledge Clip Spot', 'Bumper Cave Entrance'), + ('Death Mountain Return Ledge Clip Spot', 'Death Mountain Entrance'), ('Light World Bunny Descent', 'Light World'), ('East Death Mountain (Bottom) Jump', 'East Death Mountain (Bottom)'), ('Bat Cave River Clip Spot', 'Bat Cave Drop Ledge'), diff --git a/InvertedRegions.py b/InvertedRegions.py index b8298bc0..37659cf4 100644 --- a/InvertedRegions.py +++ b/InvertedRegions.py @@ -19,7 +19,7 @@ def create_inverted_regions(world, player): 'East Dark World Mirror Spot', 'West Dark World Mirror Spot', 'South Dark World Mirror Spot', 'Cave 45', 'Checkerboard Cave', 'Mire Mirror Spot', 'Hammer Peg Area Mirror Spot', 'Shopping Mall Mirror Spot', 'Skull Woods Mirror Spot', 'Inverted Pyramid Entrance','Hyrule Castle Entrance (South)', 'Secret Passage Outer Bushes', 'Bush Covered Lawn Outer Bushes', 'Potion Shop Outer Bushes', 'Graveyard Cave Outer Bushes', 'Bomb Hut Outer Bushes', 'Light World DMA Clip Spot', 'Death Mountain Return Ledge Clip Spot', 'Bat Cave River Clip Spot', - 'Desert Northern Cliffs', 'Lake Hylia Island Clip Spot', 'Death Mountain Entrance Clip (Broken Camera)']), + 'Desert Northern Cliffs', 'Lake Hylia Island Clip Spot']), create_lw_region(player, 'Bush Covered Lawn', None, ['Bush Covered House', 'Bush Covered Lawn Inner Bushes', 'Bush Covered Lawn Mirror Spot']), create_lw_region(player, 'Bomb Hut Area', None, ['Light World Bomb Hut', 'Bomb Hut Inner Bushes', 'Bomb Hut Mirror Spot']), create_lw_region(player, 'Hyrule Castle Secret Entrance Area', None, ['Hyrule Castle Secret Entrance Stairs', 'Secret Passage Inner Bushes']), @@ -129,7 +129,7 @@ def create_inverted_regions(world, player): 'Spectacle Rock Cave Peak', 'Spectacle Rock Cave (Bottom)', 'Broken Bridge (West)', 'Death Mountain Mirror Spot', 'Death Mountain Bunny Descent Mirror Spot', 'Death Mountain Offset Mirror', 'Hera Ascent', 'Death Mountain Glitched Bridge', 'Death Mountain Descent']), create_cave_region(player, 'Death Mountain Return Cave', 'a connector', None, ['Death Mountain Return Cave Exit (West)', 'Death Mountain Return Cave Exit (East)']), - create_lw_region(player, 'Death Mountain Return Ledge', None, ['Death Mountain Return Ledge Drop', 'Death Mountain Return Cave (West)', 'Bumper Cave Ledge Mirror Spot', 'Death Mountain Return Ledge Clip Drop']), + create_lw_region(player, 'Death Mountain Return Ledge', None, ['Death Mountain Return Ledge Drop', 'Death Mountain Return Cave (West)', 'Bumper Cave Ledge Mirror Spot']), create_cave_region(player, 'Spectacle Rock Cave (Top)', 'a connector', ['Spectacle Rock Cave'], ['Spectacle Rock Cave Drop', 'Spectacle Rock Cave Exit (Top)']), create_cave_region(player, 'Spectacle Rock Cave (Bottom)', 'a connector', None, ['Spectacle Rock Cave Exit']), create_cave_region(player, 'Spectacle Rock Cave (Peak)', 'a connector', None, ['Spectacle Rock Cave Peak Drop', 'Spectacle Rock Cave Exit (Peak)']), @@ -159,7 +159,7 @@ def create_inverted_regions(world, player): create_cave_region(player, 'Fairy Ascension Cave (Top)', 'a connector', None, ['Fairy Ascension Cave Exit (Top)', 'Fairy Ascension Cave Drop']), create_lw_region(player, 'Fairy Ascension Ledge', None, ['Fairy Ascension Ledge Drop', 'Fairy Ascension Cave (Top)', 'Laser Bridge Mirror Spot']), create_lw_region(player, 'Death Mountain (Top)', ['Ether Tablet', 'Spectacle Rock'], ['East Death Mountain (Top)', 'Tower of Hera', 'Death Mountain Drop', 'Death Mountain (Top) Mirror Spot']), - create_dw_region(player, 'Bumper Cave Ledge', ['Bumper Cave Ledge'], ['Bumper Cave Ledge Drop', 'Bumper Cave (Top)', 'Bumper Cave Ledge Clip Drop']), + create_dw_region(player, 'Bumper Cave Ledge', ['Bumper Cave Ledge'], ['Bumper Cave Ledge Drop', 'Bumper Cave (Top)']), create_dungeon_region(player, 'Tower of Hera (Bottom)', 'Tower of Hera', ['Tower of Hera - Basement Cage', 'Tower of Hera - Map Chest'], ['Tower of Hera Small Key Door', 'Tower of Hera Big Key Door', 'Tower of Hera Exit']), create_dungeon_region(player, 'Tower of Hera (Basement)', 'Tower of Hera', ['Tower of Hera - Big Key Chest']), create_dungeon_region(player, 'Tower of Hera (Top)', 'Tower of Hera', ['Tower of Hera - Compass Chest', 'Tower of Hera - Big Chest', 'Tower of Hera - Boss', 'Tower of Hera - Prize']), @@ -183,7 +183,7 @@ def create_inverted_regions(world, player): 'Hype Cave - Bottom', 'Hype Cave - Generous Guy']), create_dw_region(player, 'West Dark World', ['Frog'], ['Village of Outcasts Drop', 'East Dark World River Pier', 'Brewery', 'C-Shaped House', 'Chest Game', 'Thieves Town', 'Bumper Cave Entrance Rock', 'Skull Woods Forest', 'Village of Outcasts Pegs', 'Village of Outcasts Eastern Rocks', 'Red Shield Shop', 'Inverted Dark Sanctuary', 'Fortune Teller (Dark)', 'Dark World Lumberjack Shop', - 'West Dark World Teleporter', 'WDW Flute', 'Dark World DMA Clip Spot', 'Bumper Cave Ledge Clip Spot', 'Bumper Cave Entrance Clip (Broken Camera)']), + 'West Dark World Teleporter', 'WDW Flute', 'Dark World DMA Clip Spot', 'Bumper Cave Ledge Clip Spot']), create_dw_region(player, 'Dark Grassy Lawn', None, ['Grassy Lawn Pegs', 'Dark World Shop', 'Dark Grassy Lawn Flute']), create_dw_region(player, 'Hammer Peg Area', ['Dark Blacksmith Ruins'], ['Dark World Hammer Peg Cave', 'Peg Area Rocks', 'Hammer Peg Area Flute']), create_dw_region(player, 'Bumper Cave Entrance', None, ['Bumper Cave (Bottom)', 'Bumper Cave Entrance Drop']), diff --git a/OWGSets.py b/OWGSets.py index 50796794..833507c8 100644 --- a/OWGSets.py +++ b/OWGSets.py @@ -109,7 +109,6 @@ def get_boots_clip_exits_lw(inverted = False): 'Zora Descent Clip Spot', 'Desert Northern Cliffs', 'Lake Hylia Island Clip Spot', - 'Death Mountain Entrance Clip (Broken Camera)', 'Death Mountain Descent', ] if not inverted: @@ -133,7 +132,6 @@ def get_boots_clip_exits_dw(inverted = False): 'Hammer Pegs River Clip Spot', 'Dark Lake Hylia Ledge Clip Spot', 'Dark Desert Cliffs Clip Spot', - 'Bumper Cave Entrance Clip (Broken Camera)', 'Dark Death Mountain Descent', ] if not inverted: @@ -143,22 +141,12 @@ def get_boots_clip_exits_dw(inverted = False): return exits -def get_glitched_speed_drops_lw(): - ''' - Light World drop-down ledges that require glitched speed. - ''' - return [ - 'Death Mountain Return Ledge Clip Drop', - ] - - def get_glitched_speed_drops_dw(): ''' Dark World drop-down ledges that require glitched speed. ''' return [ 'Dark Death Mountain Ledge Clip Spot', - 'Bumper Cave Ledge Clip Drop', ] diff --git a/Regions.py b/Regions.py index a8223752..4902498f 100644 --- a/Regions.py +++ b/Regions.py @@ -15,7 +15,7 @@ def create_regions(world, player): 'Elder House (East)', 'Elder House (West)', 'North Fairy Cave', 'North Fairy Cave Drop', 'Lost Woods Gamble', 'Snitch Lady (East)', 'Snitch Lady (West)', 'Tavern (Front)', 'Bush Covered House', 'Light World Bomb Hut', 'Kakariko Shop', 'Long Fairy Cave', 'Good Bee Cave', '20 Rupee Cave', 'Cave Shop (Lake Hylia)', 'Waterfall of Wishing', 'Hyrule Castle Main Gate', 'Bonk Fairy (Light)', '50 Rupee Cave', 'Fortune Teller (Light)', 'Lake Hylia Fairy', 'Light Hype Fairy', 'Desert Fairy', 'Lumberjack House', 'Lake Hylia Fortune Teller', 'Kakariko Gamble Game', 'Top of Pyramid', - 'Light World DMA Clip Spot', 'Death Mountain Return Ledge Clip Spot', 'Desert Northern Cliffs', 'Lake Hylia Island Clip Spot', 'Death Mountain Entrance Clip (Broken Camera)', 'Bat Cave River Clip Spot', 'Bombos Tablet Clip Spot', 'Cave 45 Clip Spot']), + 'Light World DMA Clip Spot', 'Death Mountain Return Ledge Clip Spot', 'Desert Northern Cliffs', 'Lake Hylia Island Clip Spot', 'Bat Cave River Clip Spot', 'Bombos Tablet Clip Spot', 'Cave 45 Clip Spot']), create_lw_region(player, 'Death Mountain Entrance', None, ['Old Man Cave (West)', 'Death Mountain Entrance Drop']), create_lw_region(player, 'Lake Hylia Central Island', None, ['Capacity Upgrade', 'Lake Hylia Central Island Teleporter']), create_cave_region(player, 'Blinds Hideout', 'a bounty of five items', ["Blind\'s Hideout - Top", @@ -120,7 +120,7 @@ def create_regions(world, player): create_cave_region(player, 'Old Man House Back', 'a connector', None, ['Old Man House Exit (Top)', 'Old Man House Back to Front']), create_lw_region(player, 'Death Mountain', None, ['Old Man Cave (East)', 'Old Man House (Bottom)', 'Old Man House (Top)', 'Death Mountain Return Cave (East)', 'Spectacle Rock Cave', 'Spectacle Rock Cave Peak', 'Spectacle Rock Cave (Bottom)', 'Broken Bridge (West)', 'Death Mountain Teleporter', 'Death Mountain Glitched Bridge', 'Graveyard Ledge Clip Spot', 'Hera Ascent', 'Death Mountain Descent']), create_cave_region(player, 'Death Mountain Return Cave', 'a connector', None, ['Death Mountain Return Cave Exit (West)', 'Death Mountain Return Cave Exit (East)']), - create_lw_region(player, 'Death Mountain Return Ledge', None, ['Death Mountain Return Ledge Drop', 'Death Mountain Return Cave (West)', 'Death Mountain Return Ledge Clip Drop']), + create_lw_region(player, 'Death Mountain Return Ledge', None, ['Death Mountain Return Ledge Drop', 'Death Mountain Return Cave (West)']), create_cave_region(player, 'Spectacle Rock Cave (Top)', 'a connector', ['Spectacle Rock Cave'], ['Spectacle Rock Cave Drop', 'Spectacle Rock Cave Exit (Top)']), create_cave_region(player, 'Spectacle Rock Cave (Bottom)', 'a connector', None, ['Spectacle Rock Cave Exit']), create_cave_region(player, 'Spectacle Rock Cave (Peak)', 'a connector', None, ['Spectacle Rock Cave Peak Drop', 'Spectacle Rock Cave Exit (Peak)']), @@ -174,7 +174,7 @@ def create_regions(world, player): 'Hype Cave - Bottom', 'Hype Cave - Generous Guy']), create_dw_region(player, 'West Dark World', ['Frog'], ['Village of Outcasts Drop', 'East Dark World River Pier', 'Brewery', 'C-Shaped House', 'Chest Game', 'Thieves Town', 'Graveyard Ledge Mirror Spot', 'Kings Grave Mirror Spot', 'Bumper Cave Entrance Rock', 'Skull Woods Forest', 'Village of Outcasts Pegs', 'Village of Outcasts Eastern Rocks', 'Red Shield Shop', 'Dark Sanctuary Hint', 'Fortune Teller (Dark)', 'Dark World Lumberjack Shop', - 'Dark World DMA Clip Spot', 'Bumper Cave Ledge Clip Spot', 'Bumper Cave Entrance Clip (Broken Camera)']), + 'Dark World DMA Clip Spot', 'Bumper Cave Ledge Clip Spot']), create_dw_region(player, 'Dark Grassy Lawn', None, ['Grassy Lawn Pegs', 'Dark World Shop']), create_dw_region(player, 'Hammer Peg Area', ['Dark Blacksmith Ruins'], ['Bat Cave Drop Ledge Mirror Spot', 'Dark World Hammer Peg Cave', 'Peg Area Rocks']), create_dw_region(player, 'Bumper Cave Entrance', None, ['Bumper Cave (Bottom)', 'Bumper Cave Entrance Mirror Spot', 'Bumper Cave Entrance Drop']), @@ -191,7 +191,7 @@ def create_regions(world, player): create_cave_region(player, 'Red Shield Shop', 'the rare shop'), create_cave_region(player, 'Dark Sanctuary Hint', 'a storyteller'), create_cave_region(player, 'Bumper Cave', 'a connector', None, ['Bumper Cave Exit (Bottom)', 'Bumper Cave Exit (Top)']), - create_dw_region(player, 'Bumper Cave Ledge', ['Bumper Cave Ledge'], ['Bumper Cave Ledge Drop', 'Bumper Cave (Top)', 'Bumper Cave Ledge Mirror Spot', 'Bumper Cave Ledge Clip Drop']), + create_dw_region(player, 'Bumper Cave Ledge', ['Bumper Cave Ledge'], ['Bumper Cave Ledge Drop', 'Bumper Cave (Top)', 'Bumper Cave Ledge Mirror Spot']), create_dw_region(player, 'Skull Woods Forest', None, ['Skull Woods First Section Hole (East)', 'Skull Woods First Section Hole (West)', 'Skull Woods First Section Hole (North)', 'Skull Woods First Section Door', 'Skull Woods Second Section Door (East)']), create_dw_region(player, 'Skull Woods Forest (West)', None, ['Skull Woods Second Section Hole', 'Skull Woods Second Section Door (West)', 'Skull Woods Final Section']), diff --git a/Rules.py b/Rules.py index 0e79354d..7fc6199f 100644 --- a/Rules.py +++ b/Rules.py @@ -474,8 +474,6 @@ def forbid_overworld_glitches(world, player): set_rule(world.get_entrance(exit, player), lambda state: False) for exit in OWGSets.get_boots_clip_exits_dw(world.mode[player] == 'inverted'): set_rule(world.get_entrance(exit, player), lambda state: False) - for exit in OWGSets.get_glitched_speed_drops_lw(): - set_rule(world.get_entrance(exit, player), lambda state: False) for exit in OWGSets.get_glitched_speed_drops_dw(): set_rule(world.get_entrance(exit, player), lambda state: False) if world.mode[player] != 'inverted': @@ -754,8 +752,6 @@ def overworld_glitches_rules(world, player): set_rule(world.get_entrance(entrance, player), lambda state: state.can_boots_clip_dw(player)) # Glitched speed drops. - for drop in OWGSets.get_glitched_speed_drops_lw(): - set_rule(world.get_entrance(drop, player), lambda state: state.can_get_glitched_speed_lw(player)) for drop in OWGSets.get_glitched_speed_drops_dw(): set_rule(world.get_entrance(drop, player), lambda state: state.can_get_glitched_speed_dw(player)) # Dark Death Mountain Ledge Clip Spot also accessible with mirror. From 8746cfcfb0cd9450757c43cd69db8ba7ed865230 Mon Sep 17 00:00:00 2001 From: qadan Date: Tue, 11 Feb 2020 18:41:07 -0400 Subject: [PATCH 45/52] forgot offset mirror clipping --- OWGSets.py | 1 + 1 file changed, 1 insertion(+) diff --git a/OWGSets.py b/OWGSets.py index 833507c8..1d68d21e 100644 --- a/OWGSets.py +++ b/OWGSets.py @@ -166,4 +166,5 @@ def get_mirror_clip_spots_lw(): ''' return [ 'Death Mountain Bunny Descent Mirror Spot', + 'Death Mountain Offset Mirror', ] From 4707c360075c74b06635230a1aa77bb109f664ff Mon Sep 17 00:00:00 2001 From: qadan Date: Wed, 12 Feb 2020 13:46:43 -0400 Subject: [PATCH 46/52] invalid glitch --- EntranceShuffle.py | 2 -- InvertedRegions.py | 2 +- OWGSets.py | 1 - Regions.py | 2 +- 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/EntranceShuffle.py b/EntranceShuffle.py index 6be3f28f..0cabb276 100644 --- a/EntranceShuffle.py +++ b/EntranceShuffle.py @@ -3006,7 +3006,6 @@ mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia Central ('Bumper Cave Ledge Clip Spot', 'Bumper Cave Ledge'), ('Dark Death Mountain Glitched Bridge', 'Dark Death Mountain (Top)'), ('Dark Death Mountain Bunny Descent Mirror Spot', 'Dark Death Mountain Bunny Descent Area'), - ('Hookshot Cave Island Clip Spot', 'Death Mountain Floating Island (Dark World)'), ('Catfish Descent', 'Catfish'), ('Dark Death Mountain Offset Mirror', 'East Dark World'), ('Hammer Pegs River Clip Spot', 'Hammer Peg Area'), @@ -3250,7 +3249,6 @@ inverted_mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia ('Lake Hylia Island Clip Spot', 'Lake Hylia Island'), ('Dark World DMA Clip Spot', 'Dark Death Mountain'), ('Bumper Cave Ledge Clip Spot', 'Bumper Cave Ledge'), - ('Hookshot Cave Island Clip Spot', 'Death Mountain Floating Island (Dark World)'), ('Catfish Descent', 'Catfish'), ('Death Mountain Offset Mirror', 'Light World'), ('Hammer Pegs River Clip Spot', 'Hammer Peg Area'), diff --git a/InvertedRegions.py b/InvertedRegions.py index 37659cf4..156d59c7 100644 --- a/InvertedRegions.py +++ b/InvertedRegions.py @@ -209,7 +209,7 @@ def create_inverted_regions(world, player): create_cave_region(player, 'Dark Desert Hint', 'a storyteller'), create_dw_region(player, 'Dark Death Mountain', None, ['Dark Death Mountain Drop (East)', 'Inverted Agahnims Tower', 'Superbunny Cave (Top)', 'Hookshot Cave', 'Turtle Rock', 'Spike Cave', 'Dark Death Mountain Fairy', 'Dark Death Mountain Teleporter (West)', 'Turtle Rock Tail Drop', 'DDM Flute', - 'Dark Death Mountain Ledge Clip Spot', 'Hookshot Cave Island Clip Spot', 'Catfish Descent', 'Turtle Rock (Top) Clip Spot', + 'Dark Death Mountain Ledge Clip Spot', 'Catfish Descent', 'Turtle Rock (Top) Clip Spot', 'Dark Death Mountain Descent']), create_dw_region(player, 'Dark Death Mountain Ledge', None, ['Dark Death Mountain Ledge (East)', 'Dark Death Mountain Ledge (West)']), create_dw_region(player, 'Turtle Rock (Top)', None, ['Dark Death Mountain Teleporter (East)', 'Turtle Rock Drop']), diff --git a/OWGSets.py b/OWGSets.py index 1d68d21e..dcf233fb 100644 --- a/OWGSets.py +++ b/OWGSets.py @@ -127,7 +127,6 @@ def get_boots_clip_exits_dw(inverted = False): exits = [ 'Dark World DMA Clip Spot', 'Bumper Cave Ledge Clip Spot', - 'Hookshot Cave Island Clip Spot', 'Catfish Descent', 'Hammer Pegs River Clip Spot', 'Dark Lake Hylia Ledge Clip Spot', diff --git a/Regions.py b/Regions.py index 4902498f..5a1b610c 100644 --- a/Regions.py +++ b/Regions.py @@ -201,7 +201,7 @@ def create_regions(world, player): create_cave_region(player, 'Dark Desert Hint', 'a storyteller'), create_dw_region(player, 'Dark Death Mountain (West Bottom)', None, ['Spike Cave', 'Spectacle Rock Mirror Spot', 'Dark Death Mountain Fairy', 'Ganons Tower Ascent', 'Dark Death Mountain Glitched Bridge', 'Dark Death Mountain Bunny Descent Mirror Spot', 'Dark Death Mountain Offset Mirror', 'Dark Death Mountain Descent']), create_dw_region(player, 'Dark Death Mountain (Top)', None, ['Dark Death Mountain Drop (East)', 'Dark Death Mountain Drop (West)', 'Ganons Tower', 'Superbunny Cave (Top)', - 'Hookshot Cave', 'East Death Mountain (Top) Mirror Spot', 'Turtle Rock', 'Hookshot Cave Island Clip Spot', 'Catfish Descent', 'Dark Death Mountain Ledge Clip Spot', 'Turtle Rock (Top) Clip Spot']), + 'Hookshot Cave', 'East Death Mountain (Top) Mirror Spot', 'Turtle Rock', 'Catfish Descent', 'Dark Death Mountain Ledge Clip Spot', 'Turtle Rock (Top) Clip Spot']), create_dw_region(player, 'Dark Death Mountain Ledge', None, ['Dark Death Mountain Ledge (East)', 'Dark Death Mountain Ledge (West)', 'Mimic Cave Mirror Spot', 'Spiral Cave Mirror Spot']), create_dw_region(player, 'Dark Death Mountain Isolated Ledge', None, ['Isolated Ledge Mirror Spot', 'Turtle Rock Isolated Ledge Entrance']), create_dw_region(player, 'Dark Death Mountain (East Bottom)', None, ['Superbunny Cave (Bottom)', 'Cave Shop (Dark Death Mountain)', 'Fairy Ascension Mirror Spot']), From 3d021356b8fb3b437064fa01d203c4955624fe8a Mon Sep 17 00:00:00 2001 From: qadan Date: Wed, 12 Feb 2020 19:48:36 -0400 Subject: [PATCH 47/52] hera and tr superbunny logic --- BaseClasses.py | 3 +++ Rules.py | 43 +++++++++++++++++++++++++++---------------- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 4d80b0ed..2f8ff5ba 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -552,6 +552,9 @@ class CollectionState(object): rules.append(self.has_Pearl(player)) return all(rules) + def can_superbunny_mirror_with_sword(self, player): + return self.has_Mirror(player) and self.has_sword(player) + def can_get_glitched_speed_dw(self, player): rules = [self.has_Boots(player), any([self.has('Hookshot', player), self.has_sword(player)])] if self.world.mode[player] != 'inverted': diff --git a/Rules.py b/Rules.py index 7fc6199f..197cb3e4 100644 --- a/Rules.py +++ b/Rules.py @@ -767,13 +767,12 @@ def overworld_glitches_rules(world, player): set_rule(world.get_entrance(clip_spot, player), lambda state: state.has_Mirror(player)) # Locations that you can superbunny mirror into, but need a sword to clear. - superbunny_mirror_weapon = lambda state: state.has_Mirror(player) and state.has_sword(player) mini_moldorm_cave = world.get_region('Mini Moldorm Cave', player) for superbunny_mirror_weapon_region in OWGSets.get_sword_required_superbunny_mirror_regions(): region = world.get_region(superbunny_mirror_weapon_region, player) if check_is_dark_world(region): for spot in region.locations: - add_rule(world.get_location(spot, player), superbunny_mirror_weapon, 'or') + add_rule(world.get_location(spot, player), lambda state: state.can_superbunny_mirror_with_sword(player), 'or') # Regions that require the boots and some other stuff. if world.mode[player] != 'inverted': @@ -1341,13 +1340,19 @@ def set_bunny_rules(world, player): return lambda state: any(rule(state) for rule in options) def get_rule_to_add(region, location = None): - if world.logic[player] == 'owglitches' and not any([ - location in OWGSets.get_superbunny_accessible_locations() and region.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(), - region.type == RegionType.Dungeon and region.name != 'Swamp Palace (Entrance)', - not region.is_light_world]): - return lambda state: state.has_Pearl(player) - elif world.logic[player] != 'owglitches' and not region.is_light_world: - return lambda state: state.has_Pearl(player) + if world.logic['player'] == 'owglitches': + if region.name == 'Tower of Hera (Bottom)' and region.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(): + return lambda state: state.can_superbunny_mirror_with_sword(player) or state.has_Pearl(player) + if region.name == 'Turtle Rock (Entrance)' and region.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(): + return lambda state: state.has_Mirror(player) or state.has_Pearl(player) + if not any([ + location in OWGSets.get_superbunny_accessible_locations() and region.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(), + region.type == RegionType.Dungeon and region.name != 'Swamp Palace (Entrance)', + not region.is_dark_world]): + return lambda state: state.has_Pearl(player) + else: + if not region.is_dark_world: + return lambda state: state.has_Pearl(player) # in this case we are mixed region. # we collect possible options. @@ -1425,13 +1430,19 @@ def set_inverted_bunny_rules(world, player): return lambda state: any(rule(state) for rule in options) def get_rule_to_add(region, location = None): - if world.logic[player] == 'owglitches' and not any([ - location in OWGSets.get_superbunny_accessible_locations() and region.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(), - region.type == RegionType.Dungeon and region.name != 'Swamp Palace (Entrance)', - not region.is_dark_world]): - return lambda state: state.has_Pearl(player) - elif world.logic[player] != 'owglitches' and not region.is_dark_world: - return lambda state: state.has_Pearl(player) + if world.logic['player'] == 'owglitches': + if region.name == 'Tower of Hera (Bottom)' and region.name not in OWGSets.get_invalid_mirror_bunny_entrances_lw(): + return lambda state: state.can_superbunny_mirror_with_sword(player) or state.has_Pearl(player) + if region.name == 'Turtle Rock (Entrance)' and region.name not in OWGSets.get_invalid_mirror_bunny_entrances_lw(): + return lambda state: state.has_Mirror(player) or state.has_Pearl(player) + if not any([ + location in OWGSets.get_superbunny_accessible_locations() and region.name not in OWGSets.get_invalid_mirror_bunny_entrances_lw(), + region.type == RegionType.Dungeon and region.name != 'Swamp Palace (Entrance)', + not region.is_dark_world]): + return lambda state: state.has_Pearl(player) + else: + if not region.is_dark_world: + return lambda state: state.has_Pearl(player) # in this case we are mixed region. # we collect possible options. From 43801e81107c2b2f31f9a01465bf0bda5ec27964 Mon Sep 17 00:00:00 2001 From: qadan Date: Wed, 12 Feb 2020 19:50:23 -0400 Subject: [PATCH 48/52] you goose --- Rules.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Rules.py b/Rules.py index 197cb3e4..74e7112d 100644 --- a/Rules.py +++ b/Rules.py @@ -1340,7 +1340,7 @@ def set_bunny_rules(world, player): return lambda state: any(rule(state) for rule in options) def get_rule_to_add(region, location = None): - if world.logic['player'] == 'owglitches': + if world.logic[player] == 'owglitches': if region.name == 'Tower of Hera (Bottom)' and region.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(): return lambda state: state.can_superbunny_mirror_with_sword(player) or state.has_Pearl(player) if region.name == 'Turtle Rock (Entrance)' and region.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(): @@ -1430,7 +1430,7 @@ def set_inverted_bunny_rules(world, player): return lambda state: any(rule(state) for rule in options) def get_rule_to_add(region, location = None): - if world.logic['player'] == 'owglitches': + if world.logic[player] == 'owglitches': if region.name == 'Tower of Hera (Bottom)' and region.name not in OWGSets.get_invalid_mirror_bunny_entrances_lw(): return lambda state: state.can_superbunny_mirror_with_sword(player) or state.has_Pearl(player) if region.name == 'Turtle Rock (Entrance)' and region.name not in OWGSets.get_invalid_mirror_bunny_entrances_lw(): From 2b2b97d18a7e05a2181c19e26fde630b6e48cbd0 Mon Sep 17 00:00:00 2001 From: qadan Date: Tue, 18 Feb 2020 20:28:33 -0400 Subject: [PATCH 49/52] fixing bunny revival and other bunny things --- OWGSets.py | 10 +++++++ Rules.py | 84 +++++++++++++++++++++++++++++++----------------------- 2 files changed, 58 insertions(+), 36 deletions(-) diff --git a/OWGSets.py b/OWGSets.py index dcf233fb..a1fdc93b 100644 --- a/OWGSets.py +++ b/OWGSets.py @@ -167,3 +167,13 @@ def get_mirror_clip_spots_lw(): 'Death Mountain Bunny Descent Mirror Spot', 'Death Mountain Offset Mirror', ] + + +def get_invalid_bunny_revival_dungeons(): + ''' + Dungeon regions that can't be bunny revived from. + ''' + return [ + 'Tower of Hera (Bottom)', + 'Swamp Palace (Entrance)', + ] \ No newline at end of file diff --git a/Rules.py b/Rules.py index 74e7112d..6f0a72ef 100644 --- a/Rules.py +++ b/Rules.py @@ -1339,15 +1339,14 @@ def set_bunny_rules(world, player): def options_to_access_rule(options): return lambda state: any(rule(state) for rule in options) - def get_rule_to_add(region, location = None): - if world.logic[player] == 'owglitches': - if region.name == 'Tower of Hera (Bottom)' and region.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(): + def get_rule_to_add(region, location = None, connecting_entrance = None): + if world.logic[player] == 'owglitches' and connecting_entrance != None: + if region.name == 'Tower of Hera (Bottom)' and connecting_entrance.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(): return lambda state: state.can_superbunny_mirror_with_sword(player) or state.has_Pearl(player) - if region.name == 'Turtle Rock (Entrance)' and region.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(): + if region.name == 'Turtle Rock (Entrance)' and connecting_entrance.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(): return lambda state: state.has_Mirror(player) or state.has_Pearl(player) if not any([ - location in OWGSets.get_superbunny_accessible_locations() and region.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(), - region.type == RegionType.Dungeon and region.name != 'Swamp Palace (Entrance)', + location != None and location.name in OWGSets.get_superbunny_accessible_locations() and connecting_entrance.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(), not region.is_dark_world]): return lambda state: state.has_Pearl(player) else: @@ -1405,16 +1404,24 @@ def set_bunny_rules(world, player): add_rule(paradox_shop.entrances[0], get_rule_to_add(paradox_shop)) # Add requirements for all locations that are actually in the dark world, except those available to the bunny, including dungeon revival - for location in world.get_locations(): - if location.player == player and location.parent_region.is_dark_world: - - if location.name in bunny_accessible_locations: - continue - if world.logic[player] == 'owglitches' and location.parent_region.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw() and location.name in OWGSets.get_superbunny_accessible_locations(): - add_rule(location, get_rule_to_add(location.parent_region, location.name)) - continue - - add_rule(location, get_rule_to_add(location.parent_region, location.name)) + for entrance in world.get_entrances(): + if entrance.player == player and entrance.parent_region.is_dark_world: + if world.logic[player] == 'owglitches': + if entrance.connected_region.type == RegionType.Dungeon: + if entrance.connected_region.name in OWGSets.get_invalid_bunny_revival_dungeons(): + add_rule(entrance, get_rule_to_add(entrance.connected_region, None, entrance)) + continue + if entrance.connected_region.name == 'Turtle Rock (Entrance)': + add_rule(world.get_entrance('Turtle Rock Entrance Gap', player), get_rule_to_add(entrance.connected_region, None, entrance)) + if entrance.name in OWGSets.get_invalid_mirror_bunny_entrances_dw(): + continue + for location in entrance.connected_region.locations: + if world.logic[player] == 'owglitches' and entrance.name in OWGSets.get_invalid_mirror_bunny_entrances_dw(): + add_rule(location, get_rule_to_add(entrance.connected_region, location, entrance)) + continue + if location.name in bunny_accessible_locations: + continue + add_rule(location, get_rule_to_add(entrance.connected_region, location)) def set_inverted_bunny_rules(world, player): # regions for the exits of multi-entrace caves/drops that bunny cannot pass @@ -1429,19 +1436,18 @@ def set_inverted_bunny_rules(world, player): def options_to_access_rule(options): return lambda state: any(rule(state) for rule in options) - def get_rule_to_add(region, location = None): - if world.logic[player] == 'owglitches': - if region.name == 'Tower of Hera (Bottom)' and region.name not in OWGSets.get_invalid_mirror_bunny_entrances_lw(): + def get_rule_to_add(region, location = None, connecting_entrance = None): + if world.logic[player] == 'owglitches' and connecting_entrance != None: + if region.name == 'Tower of Hera (Bottom)' and connecting_entrance.name not in OWGSets.get_invalid_mirror_bunny_entrances_lw(): return lambda state: state.can_superbunny_mirror_with_sword(player) or state.has_Pearl(player) - if region.name == 'Turtle Rock (Entrance)' and region.name not in OWGSets.get_invalid_mirror_bunny_entrances_lw(): + if region.name == 'Turtle Rock (Entrance)' and connecting_entrance.name not in OWGSets.get_invalid_mirror_bunny_entrances_lw(): return lambda state: state.has_Mirror(player) or state.has_Pearl(player) if not any([ - location in OWGSets.get_superbunny_accessible_locations() and region.name not in OWGSets.get_invalid_mirror_bunny_entrances_lw(), - region.type == RegionType.Dungeon and region.name != 'Swamp Palace (Entrance)', - not region.is_dark_world]): + location != None and location.name in OWGSets.get_superbunny_accessible_locations() and connecting_entrance.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(), + not region.is_light_world]): return lambda state: state.has_Pearl(player) else: - if not region.is_dark_world: + if not region.is_light_world: return lambda state: state.has_Pearl(player) # in this case we are mixed region. # we collect possible options. @@ -1494,15 +1500,21 @@ def set_inverted_bunny_rules(world, player): add_rule(paradox_shop.entrances[0], get_rule_to_add(paradox_shop)) # Add requirements for all locations that are actually in the light world, except those available to the bunny, including dungeon revival - for location in world.get_locations(): - if location.player == player and location.parent_region.is_light_world: - - if location.name in bunny_accessible_locations: - continue - if world.logic[player] == 'owglitches' and location.parent_region.name not in OWGSets.get_invalid_mirror_bunny_entrances_lw() and location.name in OWGSets.get_superbunny_accessible_locations(): - add_rule(location, get_rule_to_add(location.parent_region, location.name)) - continue - - add_rule(location, get_rule_to_add(location.parent_region, location.name)) - - + for entrance in world.get_entrances(): + if entrance.player == player and entrance.parent_region.is_light_world: + if world.logic[player] == 'owglitches': + if entrance.connected_region.type == RegionType.Dungeon: + if entrance.connected_region.name in OWGSets.get_invalid_bunny_revival_dungeons(): + add_rule(entrance, get_rule_to_add(entrance.connected_region, None, entrance)) + continue + if entrance.connected_region.name == 'Turtle Rock (Entrance)': + add_rule(world.get_entrance('Turtle Rock Entrance Gap', player), get_rule_to_add(entrance.connected_region, None, entrance)) + if entrance.name in OWGSets.get_invalid_mirror_bunny_entrances_lw(): + continue + for location in entrance.connected_region.locations: + if world.logic[player] == 'owglitches' and entrance.name in OWGSets.get_invalid_mirror_bunny_entrances_lw(): + add_rule(location, get_rule_to_add(entrance.connected_region, location, entrance)) + continue + if location.name in bunny_accessible_locations: + continue + add_rule(location, get_rule_to_add(entrance.connected_region, location)) \ No newline at end of file From 3015133abde58c1c5684c26fc1912fe2ec55b611 Mon Sep 17 00:00:00 2001 From: qadan Date: Wed, 19 Feb 2020 10:18:09 -0400 Subject: [PATCH 50/52] some copypasta goofs --- Rules.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Rules.py b/Rules.py index 6f0a72ef..2a2ef1df 100644 --- a/Rules.py +++ b/Rules.py @@ -1347,10 +1347,10 @@ def set_bunny_rules(world, player): return lambda state: state.has_Mirror(player) or state.has_Pearl(player) if not any([ location != None and location.name in OWGSets.get_superbunny_accessible_locations() and connecting_entrance.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(), - not region.is_dark_world]): + not region.is_light_world]): return lambda state: state.has_Pearl(player) else: - if not region.is_dark_world: + if not region.is_light_world: return lambda state: state.has_Pearl(player) # in this case we are mixed region. @@ -1444,10 +1444,10 @@ def set_inverted_bunny_rules(world, player): return lambda state: state.has_Mirror(player) or state.has_Pearl(player) if not any([ location != None and location.name in OWGSets.get_superbunny_accessible_locations() and connecting_entrance.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(), - not region.is_light_world]): + not region.is_dark_world]): return lambda state: state.has_Pearl(player) else: - if not region.is_light_world: + if not region.is_dark_world: return lambda state: state.has_Pearl(player) # in this case we are mixed region. # we collect possible options. @@ -1517,4 +1517,4 @@ def set_inverted_bunny_rules(world, player): continue if location.name in bunny_accessible_locations: continue - add_rule(location, get_rule_to_add(entrance.connected_region, location)) \ No newline at end of file + add_rule(location, get_rule_to_add(entrance.connected_region, location)) From ea4340b796090d07cf81779229240cfb771e5884 Mon Sep 17 00:00:00 2001 From: qadan Date: Wed, 19 Feb 2020 19:06:48 -0400 Subject: [PATCH 51/52] fixing mirror bunny stuff --- OWGSets.py | 1 + Rules.py | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/OWGSets.py b/OWGSets.py index a1fdc93b..cb445d2a 100644 --- a/OWGSets.py +++ b/OWGSets.py @@ -176,4 +176,5 @@ def get_invalid_bunny_revival_dungeons(): return [ 'Tower of Hera (Bottom)', 'Swamp Palace (Entrance)', + 'Turtle Rock (Entrance)', ] \ No newline at end of file diff --git a/Rules.py b/Rules.py index 2a2ef1df..ac36781e 100644 --- a/Rules.py +++ b/Rules.py @@ -1340,13 +1340,13 @@ def set_bunny_rules(world, player): return lambda state: any(rule(state) for rule in options) def get_rule_to_add(region, location = None, connecting_entrance = None): - if world.logic[player] == 'owglitches' and connecting_entrance != None: - if region.name == 'Tower of Hera (Bottom)' and connecting_entrance.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(): - return lambda state: state.can_superbunny_mirror_with_sword(player) or state.has_Pearl(player) - if region.name == 'Turtle Rock (Entrance)' and connecting_entrance.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(): + # In OWG, a location can potentially be superbunny-mirror accessible or + # bunny revival accessible. + if world.logic[player] == 'owglitches': + if region.name in OWGSets.get_invalid_bunny_revival_dungeons(): return lambda state: state.has_Mirror(player) or state.has_Pearl(player) if not any([ - location != None and location.name in OWGSets.get_superbunny_accessible_locations() and connecting_entrance.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(), + None not in [location, connecting_entrance] and location.name in OWGSets.get_superbunny_accessible_locations() and connecting_entrance.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(), not region.is_light_world]): return lambda state: state.has_Pearl(player) else: @@ -1437,13 +1437,13 @@ def set_inverted_bunny_rules(world, player): return lambda state: any(rule(state) for rule in options) def get_rule_to_add(region, location = None, connecting_entrance = None): - if world.logic[player] == 'owglitches' and connecting_entrance != None: - if region.name == 'Tower of Hera (Bottom)' and connecting_entrance.name not in OWGSets.get_invalid_mirror_bunny_entrances_lw(): - return lambda state: state.can_superbunny_mirror_with_sword(player) or state.has_Pearl(player) - if region.name == 'Turtle Rock (Entrance)' and connecting_entrance.name not in OWGSets.get_invalid_mirror_bunny_entrances_lw(): + # In OWG, a location can potentially be superbunny-mirror accessible or + # bunny revival accessible. + if world.logic[player] == 'owglitches': + if region.name in OWGSets.get_invalid_bunny_revival_dungeons(): return lambda state: state.has_Mirror(player) or state.has_Pearl(player) if not any([ - location != None and location.name in OWGSets.get_superbunny_accessible_locations() and connecting_entrance.name not in OWGSets.get_invalid_mirror_bunny_entrances_dw(), + None not in [location, connecting_entrance] and location.name in OWGSets.get_superbunny_accessible_locations() and connecting_entrance.name not in OWGSets.get_invalid_mirror_bunny_entrances_lw(), not region.is_dark_world]): return lambda state: state.has_Pearl(player) else: From 52982a5e13faea60124c1aca0e29c8ced37fc99a Mon Sep 17 00:00:00 2001 From: qadan Date: Wed, 26 Feb 2020 15:18:49 -0400 Subject: [PATCH 52/52] kings grave area, waterwalk regions --- EntranceShuffle.py | 2 ++ InvertedRegions.py | 2 +- OWGSets.py | 6 ++++-- Rules.py | 8 +++----- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/EntranceShuffle.py b/EntranceShuffle.py index 0cabb276..40e0551d 100644 --- a/EntranceShuffle.py +++ b/EntranceShuffle.py @@ -2997,6 +2997,7 @@ mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia Central ('Dark Death Mountain Ledge Clip Spot', 'Dark Death Mountain Ledge'), ('Zora Descent Clip Spot', 'Zoras River'), ('Graveyard Ledge Clip Spot', 'Graveyard Ledge'), + ('Graveyard Ledge Clip Spot', 'Kings Grave Area'), ('Desert Northern Cliffs', 'Desert Ledge'), ('Desert Northern Cliffs', 'Desert Ledge (Northeast)'), ('Desert Northern Cliffs', 'Desert Palace Entrance (North) Spot'), @@ -3026,6 +3027,7 @@ mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia Central inverted_mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia Central Island'), ('Lake Hylia Island', 'Lake Hylia Island'), ('Zoras River', 'Zoras River'), + ('Graveyard Ledge Clip Spot', 'Kings Grave Area'), ('Kings Grave Outer Rocks', 'Kings Grave Area'), ('Kings Grave Inner Rocks', 'Light World'), ('Kakariko Well (top to bottom)', 'Kakariko Well (bottom)'), diff --git a/InvertedRegions.py b/InvertedRegions.py index 156d59c7..b33a85e8 100644 --- a/InvertedRegions.py +++ b/InvertedRegions.py @@ -127,7 +127,7 @@ def create_inverted_regions(world, player): create_cave_region(player, 'Old Man House Back', 'a connector', None, ['Old Man House Exit (Top)', 'Old Man House Back to Front']), create_lw_region(player, 'Death Mountain', None, ['Old Man Cave (East)', 'Old Man House (Bottom)', 'Old Man House (Top)', 'Death Mountain Return Cave (East)', 'Spectacle Rock Cave', 'Spectacle Rock Cave Peak', 'Spectacle Rock Cave (Bottom)', 'Broken Bridge (West)', 'Death Mountain Mirror Spot', 'Death Mountain Bunny Descent Mirror Spot', - 'Death Mountain Offset Mirror', 'Hera Ascent', 'Death Mountain Glitched Bridge', 'Death Mountain Descent']), + 'Death Mountain Offset Mirror', 'Hera Ascent', 'Death Mountain Glitched Bridge', 'Death Mountain Descent', 'Graveyard Ledge Clip Spot']), create_cave_region(player, 'Death Mountain Return Cave', 'a connector', None, ['Death Mountain Return Cave Exit (West)', 'Death Mountain Return Cave Exit (East)']), create_lw_region(player, 'Death Mountain Return Ledge', None, ['Death Mountain Return Ledge Drop', 'Death Mountain Return Cave (West)', 'Bumper Cave Ledge Mirror Spot']), create_cave_region(player, 'Spectacle Rock Cave (Top)', 'a connector', ['Spectacle Rock Cave'], ['Spectacle Rock Cave Drop', 'Spectacle Rock Cave Exit (Top)']), diff --git a/OWGSets.py b/OWGSets.py index cb445d2a..6ab361d1 100644 --- a/OWGSets.py +++ b/OWGSets.py @@ -110,10 +110,12 @@ def get_boots_clip_exits_lw(inverted = False): 'Desert Northern Cliffs', 'Lake Hylia Island Clip Spot', 'Death Mountain Descent', + 'Graveyard Ledge Clip Spot', + # Also requires a waterwalk setup, but the point still remains. + 'Waterfall of Wishing', ] if not inverted: exits.append('Spectacle Rock Clip Spot') - exits.append('Graveyard Ledge Clip Spot') exits.append('Bombos Tablet Clip Spot') exits.append('Floating Island Clip Spot') exits.append('Cave 45 Clip Spot') @@ -177,4 +179,4 @@ def get_invalid_bunny_revival_dungeons(): 'Tower of Hera (Bottom)', 'Swamp Palace (Entrance)', 'Turtle Rock (Entrance)', - ] \ No newline at end of file + ] diff --git a/Rules.py b/Rules.py index ac36781e..3c89c949 100644 --- a/Rules.py +++ b/Rules.py @@ -736,11 +736,6 @@ def add_conditional_lamps(world, player): def overworld_glitches_rules(world, player): - # @TODO: Waterfall fairy and Zora ledge could use some logic to determine - # if we can water walk and/or stored water walk in; currently it's omitted - # in case no interiors provide a water walk, but one could be kicking - # around. We could detect a path to determine if one can be stored. - # Spots that are immediately accessible. for entrance in OWGSets.get_immediately_accessible_entrances(world, player): set_rule(world.get_entrance(entrance, player), lambda state: True) @@ -784,6 +779,9 @@ def overworld_glitches_rules(world, player): else: add_rule(world.get_entrance('South Dark World Teleporter', player), lambda state: state.has_Boots(player) and state.can_lift_rocks(player), 'or') + # Zora's Ledge via waterwalk setup. + add_rule(world.get_location('Zora\'s Ledge', player), lambda state: state.has_Boots(player), 'or') + def open_rules(world, player): # softlock protection as you can reach the sewers small key door with a guard drop key