From 1af6edf7930a32b9614ba913192b3b93acdbfa7a Mon Sep 17 00:00:00 2001 From: LLCoolDave Date: Mon, 17 Jul 2017 22:29:32 +0200 Subject: [PATCH] Update crystal placing logic to consider implications of --shuffleganon option. --- EntranceShuffle.py | 32 ++++++++++---------------------- Main.py | 36 ++++++++++++++++++++++++++++++------ 2 files changed, 40 insertions(+), 28 deletions(-) diff --git a/EntranceShuffle.py b/EntranceShuffle.py index 35d3a03a..cfd6b36e 100644 --- a/EntranceShuffle.py +++ b/EntranceShuffle.py @@ -1,5 +1,7 @@ import random +# ToDo: With shuffle_ganon option, prevent gtower from linking to an exit only location through a 2 entrance cave. + def link_entrances(world): ret = [] @@ -41,7 +43,7 @@ def link_entrances(world): dungeon_exits.append(('Hyrule Castle Exit (South)', 'Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)')) lw_entrances.append('Hyrule Castle Entrance (South)') - if world.goal == 'ganon': + if not world.shuffle_ganon: ret.append(connect_two_way(world, 'Ganons Tower', 'Ganons Tower Exit')) else: dw_entrances.append('Ganons Tower') @@ -119,12 +121,9 @@ def link_entrances(world): bomb_shop_doors.extend(blacksmith_doors) # place dam and pyramid fairy, have limited options - # ToDo Dam might be behind fat fairy if we later check for this when placing crystal 5 and 6 random.shuffle(bomb_shop_doors) bomb_shop = bomb_shop_doors.pop() ret.append(connect_entrance(world, bomb_shop, 'Big Bomb Shop')) - dam = bomb_shop_doors.pop() - ret.append(connect_entrance(world, dam, 'Dam')) single_doors.extend(bomb_shop_doors) # tavern back door cannot be shuffled yet @@ -180,12 +179,9 @@ def link_entrances(world): bomb_shop_doors.extend(blacksmith_doors) # place dam and pyramid fairy, have limited options - # ToDo Dam might be behind fat fairy if we later check for this when placing crystal 5 and 6 random.shuffle(bomb_shop_doors) bomb_shop = bomb_shop_doors.pop() ret.append(connect_entrance(world, bomb_shop, 'Big Bomb Shop')) - dam = bomb_shop_doors.pop() - ret.append(connect_entrance(world, dam, 'Dam')) single_doors.extend(bomb_shop_doors) # tavern back door cannot be shuffled yet @@ -217,7 +213,7 @@ def link_entrances(world): caves.append(('Hyrule Castle Exit (South)', 'Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)')) lw_entrances.append('Hyrule Castle Entrance (South)') - if world.goal == 'ganon': + if not world.shuffle_ganon: ret.append(connect_two_way(world, 'Ganons Tower', 'Ganons Tower Exit')) else: dw_entrances.append('Ganons Tower') @@ -261,12 +257,9 @@ def link_entrances(world): bomb_shop_doors.extend(blacksmith_doors) # place dam and pyramid fairy, have limited options - # ToDo Dam might be behind fat fairy if we later check for this when placing crystal 5 and 6 random.shuffle(bomb_shop_doors) bomb_shop = bomb_shop_doors.pop() ret.append(connect_entrance(world, bomb_shop, 'Big Bomb Shop')) - dam = bomb_shop_doors.pop() - ret.append(connect_entrance(world, dam, 'Dam')) single_doors.extend(bomb_shop_doors) # tavern back door cannot be shuffled yet @@ -325,7 +318,7 @@ def link_entrances(world): hole_targets.append(('Hyrule Castle Secret Entrance Exit', 'Hyrule Castle Secret Entrance')) lw_entrances.append('Hyrule Castle Secret Entrance Stairs') - if world.goal == 'ganon': + if not world.shuffle_ganon: ret.append(connect_two_way(world, 'Ganons Tower', 'Ganons Tower Exit')) ret.append(connect_two_way(world, 'Pyramid Entrance', 'Pyramid Exit')) ret.append(connect_entrance(world, 'Pyramid Hole', 'Pyramid')) @@ -507,12 +500,9 @@ def link_entrances(world): bomb_shop_doors.extend(blacksmith_doors) # place dam and pyramid fairy, have limited options - # ToDo Dam might be behind fat fairy if we later check for this when placing crystal 5 and 6 random.shuffle(bomb_shop_doors) bomb_shop = bomb_shop_doors.pop() ret.append(connect_entrance(world, bomb_shop, 'Big Bomb Shop')) - dam = bomb_shop_doors.pop() - ret.append(connect_entrance(world, dam, 'Dam')) single_doors.extend(bomb_shop_doors) # tavern back door cannot be shuffled yet @@ -557,7 +547,7 @@ def link_entrances(world): entrances.append('Hyrule Castle Secret Entrance Stairs') caves.append('Hyrule Castle Secret Entrance Exit') - if world.goal == 'ganon': + if not world.shuffle_ganon: ret.append(connect_two_way(world, 'Ganons Tower', 'Ganons Tower Exit')) ret.append(connect_two_way(world, 'Pyramid Entrance', 'Pyramid Exit')) ret.append(connect_entrance(world, 'Pyramid Hole', 'Pyramid')) @@ -652,12 +642,9 @@ def link_entrances(world): bomb_shop_doors.extend(blacksmith_doors) # place dam and pyramid fairy, have limited options - # ToDo Dam might be behind fat fairy if we later check for this when placing crystal 5 and 6 random.shuffle(bomb_shop_doors) bomb_shop = bomb_shop_doors.pop() ret.append(connect_entrance(world, bomb_shop, 'Big Bomb Shop')) - dam = bomb_shop_doors.pop() - ret.append(connect_entrance(world, dam, 'Dam')) single_doors.extend(bomb_shop_doors) # tavern back door cannot be shuffled yet @@ -750,7 +737,7 @@ def scramble_holes(world): ('Lumberjack Tree Exit', 'Lumberjack Tree (top)'), ('Sanctuary Exit', 'Sewer Drop')] - if world.goal == 'ganon': + if not world.shuffle_ganon: ret.append(connect_two_way(world, 'Pyramid Entrance', 'Pyramid Exit')) ret.append(connect_entrance(world, 'Pyramid Hole', 'Pyramid')) else: @@ -883,7 +870,7 @@ def simple_shuffle_dungeons(world): dungeon_entrances = ['Eastern Palace', 'Tower of Hera', 'Thieves Town', 'Skull Woods Final Section', 'Palace of Darkness', 'Ice Palace', 'Misery Mire', 'Swamp Palace'] dungeon_exits = ['Eastern Palace Exit', 'Tower of Hera Exit', 'Thieves Town Exit', 'Skull Woods Final Section Exit', 'Dark Palace Exit', 'Ice Palace Exit', 'Misery Mire Exit', 'Swamp Palace Exit'] - if world.goal == 'ganon': + if not world.shuffle_ganon: ret.append(connect_two_way(world, 'Ganons Tower', 'Ganons Tower Exit')) else: dungeon_entrances.append('Ganons Tower') @@ -1179,7 +1166,8 @@ Single_Cave_Targets = ['Thiefs Hut', 'Dark World Shop', 'Lumberjack House', 'Fortune Teller (Light)', - 'Kakariko Gamble Game'] + 'Kakariko Gamble Game', + 'Dam'] # these are connections that cannot be shuffled and always exist. They link together separate parts of the world we need to divide into regions mandatory_connections = [('Links House', 'Links House'), # unshuffled. For now diff --git a/Main.py b/Main.py index 868ecb1d..370a3a18 100644 --- a/Main.py +++ b/Main.py @@ -483,11 +483,35 @@ def generate_itempool(world): world.itempool.append(ItemFactory('Magic Upgrade (1/2)')) # distribute crystals - crystals = ItemFactory(['Green Pendant', 'Red Pendant', 'Blue Pendant', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7']) - crystal_locations = [world.get_location('Armos - Pendant'), world.get_location('Lanmolas - Pendant'), world.get_location('Moldorm - Pendant'), world.get_location('Helmasaur - Crystal'), - world.get_location('Blind - Crystal'), world.get_location('Mothula - Crystal'), world.get_location('Arrghus - Crystal'), world.get_location('Kholdstare - Crystal'), - world.get_location('Vitreous - Crystal'), world.get_location('Trinexx - Crystal')] + crystals = ItemFactory(['Green Pendant', 'Red Pendant', 'Blue Pendant']) + crystal_locations = [world.get_location('Trinexx - Crystal')] random.shuffle(crystals) + if world.shuffle_ganon: + # ensure that no crystal gets locked inside of ganons tower location as that is unsolvable + for region, crystallocation in [('Eastern Palace', 'Armos - Pendant'), ('Desert Palace North', 'Lanmolas - Pendant'), ('Tower of Hera (Bottom)', 'Moldorm - Pendant'), + ('Dark Palace (Entrance)', 'Helmasaur - Crystal'), ('Thieves Town (Entrance)', 'Blind - Crystal'), ('Skull Woods Final Section (Entrance)', 'Mothula - Crystal'), + ('Swamp Palace (Entrance)', 'Arrghus - Crystal'), ('Ice Palace (Entrance)', 'Kholdstare - Crystal'), ('Misery Mire (Entrance)', 'Vitreous - Crystal')]: + if world.get_entrance('Ganons Tower').connected_region.name == region: + # can't place a crystal here + world.push_item(world.get_location(crystallocation), crystals.pop(), False) + else: + crystal_locations.append(world.get_location(crystallocation)) + else: + crystal_locations += [world.get_location('Armos - Pendant'), world.get_location('Lanmolas - Pendant'), world.get_location('Moldorm - Pendant'), world.get_location('Helmasaur - Crystal'), + world.get_location('Blind - Crystal'), world.get_location('Mothula - Crystal'), world.get_location('Arrghus - Crystal'), world.get_location('Kholdstare - Crystal'), + world.get_location('Vitreous - Crystal')] + + crystals.extend(ItemFactory(['Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 7'])) + random.shuffle(crystals) + + # check if dam is behind pyramid fairy, if so, swamp can't hold a crystal + if world.get_entrance('Pyramid Fairy').connected_region.name == 'Dam': + crystallocation = crystal_locations.pop(crystal_locations.index(world.get_location('Arrghus - Crystal'))) + world.push_item(world.get_location(crystallocation), crystals.pop(), False) + + crystals.extend(ItemFactory(['Crystal 5', 'Crystal 6'])) + random.shuffle(crystals) + for location, crystal in zip(crystal_locations, crystals): world.push_item(location, crystal, False) location.event = True @@ -518,8 +542,6 @@ def copy_world(world): for entrance in region.entrances: ret.get_entrance(entrance.name).connect(ret.get_region(region.name)) - set_rules(ret) - # fill locations for location in world.get_locations(): if location.item is not None: @@ -536,6 +558,8 @@ def copy_world(world): # copy progress items in state ret.state.prog_items = list(world.state.prog_items) + set_rules(ret) + return ret