From e994be11f64de279b42b838d3cd5801859472b2b Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sat, 16 Oct 2021 13:47:55 -0500 Subject: [PATCH] Added new Lite (fka. Beginner) ER mode --- BaseClasses.py | 4 +- EntranceShuffle.py | 51 ++++++++++++++++++- ItemList.py | 2 +- Rom.py | 2 +- Rules.py | 2 +- mystery_example.yml | 1 + resources/app/cli/args.json | 1 + resources/app/cli/lang/en.json | 8 ++- resources/app/gui/lang/en.json | 1 + .../app/gui/randomize/entrando/widgets.json | 1 + 10 files changed, 65 insertions(+), 8 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index ab033715..efe3adf6 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -120,7 +120,7 @@ class World(object): set_player_attr('can_access_trock_front', None) set_player_attr('can_access_trock_big_chest', None) set_player_attr('can_access_trock_middle', None) - set_player_attr('fix_fake_world', logic[player] not in ['owglitches', 'nologic'] or shuffle[player] in ['crossed', 'insanity', 'madness_legacy']) + set_player_attr('fix_fake_world', logic[player] not in ['owglitches', 'nologic'] or shuffle[player] in ['lite', 'crossed', 'insanity', 'madness_legacy']) set_player_attr('mapshuffle', False) set_player_attr('compassshuffle', False) set_player_attr('keyshuffle', False) @@ -2950,7 +2950,7 @@ class Pot(object): # byte 0: DDOO OEEE (DR, OR, ER) dr_mode = {"basic": 1, "crossed": 2, "vanilla": 0} or_mode = {"vanilla": 0, "parallel": 1, "full": 1} -er_mode = {"vanilla": 0, "simple": 1, "restricted": 3, "full": 3, "crossed": 4, "insanity": 5, "dungeonsfull": 7, "dungeonssimple": 7} +er_mode = {"vanilla": 0, "simple": 1, "restricted": 2, "full": 3, "lite": 4, "crossed": 5, "insanity": 6, "dungeonsfull": 7, "dungeonssimple": 8} # byte 1: LLLW WSSR (logic, mode, sword, retro) logic_mode = {"noglitches": 0, "minorglitches": 1, "nologic": 2, "owglitches": 3, "majorglitches": 4} diff --git a/EntranceShuffle.py b/EntranceShuffle.py index b92f35fc..36e4b394 100644 --- a/EntranceShuffle.py +++ b/EntranceShuffle.py @@ -366,6 +366,44 @@ def link_entrances(world, player): dw_entrances = [e for e in dw_entrances if e in entrance_pool] connect_caves(world, lw_entrances, dw_entrances, caves, player) + # place remaining doors + connect_doors(world, list(entrance_pool), list(exit_pool), player) + elif world.shuffle[player] == 'lite': + for entrancename, exitname in default_connections + ([] if world.shopsanity[player] else default_shop_connections): + connect_logical(world, entrancename, exitname, player, False) + + # place bomb shop + bomb_shop = 'Big Bomb Shop' if invFlag == (0x2c in world.owswaps[player][0] and world.owMixed[player]) else 'Links House' + connect_entrance(world, bomb_shop, 'Big Bomb Shop', player) + + suppress_spoiler = False + + # place links house + links_house = place_links_house(world, sectors, player) + + # shuffle dungeons + full_shuffle_dungeons(world, Dungeon_Exits, player) + + # shuffle dropdowns + scramble_holes(world, player) + + # place old man, has limited options + connector_entrances = [e for e in list(zip(*default_connector_connections))[0] if e in entrance_pool] + place_old_man(world, list(connector_entrances), player) + + caves = list(Cave_Exits + Cave_Three_Exits + Old_Man_House) + + # place connectors in inaccessible regions + connector_entrances = [e for e in connector_entrances if e in entrance_pool] + connect_inaccessible_regions(world, connector_entrances, [], caves, player) + + # shuffle remaining connectors + connector_entrances = [e for e in connector_entrances if e in entrance_pool] + connect_caves(world, connector_entrances, [], caves, player) + + # place blacksmith, has limited options + place_blacksmith(world, links_house, player) + # place remaining doors connect_doors(world, list(entrance_pool), list(exit_pool), player) elif world.shuffle[player] == 'crossed': @@ -1171,6 +1209,13 @@ def full_shuffle_dungeons(world, Dungeon_Exits, player): random.shuffle(ledge) lw_must_exit.append(ledge.pop()) lw_related.extend(ledge) + if world.shuffle[player] == 'lite': + lw_entrances.extend(dw_entrances) + lw_must_exit.extend(dw_must_exit) + lw_related.extend(dw_related) + dw_entrances = list() + dw_must_exit = list() + dw_related = list() random.shuffle(lw_must_exit) random.shuffle(dw_must_exit) @@ -1231,6 +1276,8 @@ def place_links_house(world, sectors, player): return entrances links_house_doors = [i for i in get_link_candidates() if i in entrance_pool] + if world.shuffle[player] == 'lite': + links_house_doors = [e for e in links_house_doors if e in list(zip(*(default_item_connections + (default_shop_connections if world.shopsanity[player] else []))))[0]] links_house = random.choice(links_house_doors) connect_two_way(world, links_house, 'Links House Exit', player) return links_house @@ -1304,6 +1351,8 @@ def place_old_man(world, pool, player): else: region_name = 'West Dark Death Mountain (Top)' old_man_entrances = list(build_accessible_entrance_list(world, region_name, player, [], False, True, True)) + if world.shuffle[player] == 'lite': + old_man_entrances = [e for e in old_man_entrances if e in pool] random.shuffle(old_man_entrances) old_man_exit = None while not old_man_exit: @@ -1400,7 +1449,7 @@ def connect_inaccessible_regions(world, lw_entrances, dw_entrances, caves, playe connect_inaccessible_regions(world, lw_entrances, dw_entrances, caves, player) # connect one connector at a time to ensure multiple connectors aren't assigned to the same inaccessible set of regions - if world.shuffle[player] in ['crossed', 'insanity']: + if world.shuffle[player] in ['lite', 'crossed', 'insanity']: combined_must_exit_regions = list(must_exit_regions + otherworld_must_exit_regions) if len(combined_must_exit_regions) > 0: random.shuffle(combined_must_exit_regions) diff --git a/ItemList.py b/ItemList.py index ff6c2188..5d135ff9 100644 --- a/ItemList.py +++ b/ItemList.py @@ -709,7 +709,7 @@ def balance_prices(world, player): def check_hints(world, player): - if world.shuffle[player] in ['simple', 'restricted', 'full', 'crossed', 'insanity']: + if world.shuffle[player] in ['simple', 'restricted', 'full', 'lite', 'crossed', 'insanity']: for shop, location_list in shop_to_location_table.items(): if shop in ['Capacity Upgrade', 'Light World Death Mountain Shop', 'Potion Shop']: continue # near the queen, near potions, and near 7 chests are fine diff --git a/Rom.py b/Rom.py index 074ec8fc..c9e4ffa5 100644 --- a/Rom.py +++ b/Rom.py @@ -1601,7 +1601,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): rom.write_bytes(0x02F539, [0xEA, 0xEA, 0xEA, 0xEA, 0xEA] if world.powder_patch_required[player] else [0xAD, 0xBF, 0x0A, 0xF0, 0x4F]) # allow smith into multi-entrance caves in appropriate shuffles - if world.shuffle[player] in ['restricted', 'full', 'crossed', 'insanity'] or (world.shuffle[player] == 'simple' and world.mode[player] == 'inverted'): + if world.shuffle[player] in ['restricted', 'full', 'lite', 'crossed', 'insanity'] or (world.shuffle[player] == 'simple' and world.mode[player] == 'inverted'): rom.write_byte(0x18004C, 0x01) # set correct flag for hera basement item diff --git a/Rules.py b/Rules.py index 3f606755..382194cb 100644 --- a/Rules.py +++ b/Rules.py @@ -844,7 +844,7 @@ def ow_rules(world, player): if world.mode[player] != 'inverted': set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has('Cape', player) or state.has_beam_sword(player) or state.has('Beat Agahnim 1', player)) # barrier gets removed after killing agahnim, relevant for entrance shuffle set_rule(world.get_entrance('GT Entry Approach', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player)) - set_rule(world.get_entrance('GT Entry Leave', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player) or state.world.shuffle[player] in ('restricted', 'full', 'crossed', 'insanity')) + set_rule(world.get_entrance('GT Entry Leave', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player) or state.world.shuffle[player] in ('restricted', 'full', 'lite', 'crossed', 'insanity')) else: set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player)) diff --git a/mystery_example.yml b/mystery_example.yml index f9e276a6..ce1e56ca 100644 --- a/mystery_example.yml +++ b/mystery_example.yml @@ -46,6 +46,7 @@ simple: 2 restricted: 2 full: 2 + lite: 2 crossed: 3 insanity: 1 shufflelinks: diff --git a/resources/app/cli/args.json b/resources/app/cli/args.json index edbb11f0..bdb8eb83 100644 --- a/resources/app/cli/args.json +++ b/resources/app/cli/args.json @@ -146,6 +146,7 @@ "simple", "restricted", "full", + "lite", "crossed", "insanity", "dungeonsfull", diff --git a/resources/app/cli/lang/en.json b/resources/app/cli/lang/en.json index c4ff9781..a8ca7e1a 100644 --- a/resources/app/cli/lang/en.json +++ b/resources/app/cli/lang/en.json @@ -173,14 +173,18 @@ ], "shuffle": [ "Select Entrance Shuffling Algorithm. (default: %(default)s)", - "Full: Mix cave and dungeon entrances freely while limiting", - " multi-entrance caves to one world.", "Simple: Shuffle Dungeon Entrances/Exits between each other", " and keep all 4-entrance dungeons confined to one", " location. All caves outside of death mountain are", " shuffled in pairs and matched by original type.", "Restricted: Use Dungeons shuffling from Simple but freely", " connect remaining entrances.", + "Full: Mix cave and dungeon entrances freely while limiting", + " multi-entrance caves to one world.", + "Lite: Entrances are put into separate pools based on their", + " vanilla location. Dungeons, dropdowns, connector caves,", + " and locations that have an item are shuffled from", + " individual pools. Non-item locations remain vanilla.", "Crossed: Mix cave and dungeon entrances freely while allowing", " caves to cross between worlds.", "Insanity: Decouple entrances and exits from each other and", diff --git a/resources/app/gui/lang/en.json b/resources/app/gui/lang/en.json index 8544efff..63ddc4ab 100644 --- a/resources/app/gui/lang/en.json +++ b/resources/app/gui/lang/en.json @@ -140,6 +140,7 @@ "randomizer.entrance.entranceshuffle.simple": "Simple", "randomizer.entrance.entranceshuffle.restricted": "Restricted", "randomizer.entrance.entranceshuffle.full": "Full", + "randomizer.entrance.entranceshuffle.lite": "Lite", "randomizer.entrance.entranceshuffle.crossed": "Crossed", "randomizer.entrance.entranceshuffle.insanity": "Insanity", "randomizer.entrance.entranceshuffle.restricted_legacy": "Restricted (Legacy)", diff --git a/resources/app/gui/randomize/entrando/widgets.json b/resources/app/gui/randomize/entrando/widgets.json index ffeeb976..0a392da3 100644 --- a/resources/app/gui/randomize/entrando/widgets.json +++ b/resources/app/gui/randomize/entrando/widgets.json @@ -10,6 +10,7 @@ "simple", "restricted", "full", + "lite", "crossed", "insanity", "dungeonsfull",