diff --git a/ItemList.py b/ItemList.py index ffe775df..69d5a327 100644 --- a/ItemList.py +++ b/ItemList.py @@ -35,7 +35,7 @@ Difficulty = namedtuple('Difficulty', 'progressivesword', 'basicsword', 'basicbow', 'timedohko', 'timedother', 'triforcehunt', 'triforce_pieces_required', 'retro', 'extras', 'progressive_sword_limit', 'progressive_shield_limit', - 'progressive_armor_limit', 'progressive_bottle_limit', + 'progressive_armor_limit', 'progressive_bottle_limit', 'progressive_bow_limit', 'heart_piece_limit', 'boss_heart_container_limit']) total_items_to_place = 153 @@ -136,7 +136,7 @@ def generate_itempool(world, player): world.push_item(world.get_location('Ganon', player), ItemFactory('Nothing', player), False) else: world.push_item(world.get_location('Ganon', player), ItemFactory('Triforce', player), False) - + if world.goal in ['triforcehunt']: if world.mode == 'inverted': region = world.get_region('Light World',player) @@ -153,7 +153,7 @@ def generate_itempool(world, player): world.push_item(loc, ItemFactory('Triforce', player), False) loc.event = True loc.locked = True - + world.get_location('Ganon', player).event = True world.get_location('Ganon', player).locked = True world.push_item(world.get_location('Agahnim 1', player), ItemFactory('Beat Agahnim 1', player), False) @@ -181,16 +181,41 @@ def generate_itempool(world, player): 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, world.difficulty, world.timer, world.goal, world.mode, world.swords, world.retro) - world.itempool += ItemFactory(pool, player) + for item in precollected_items: world.push_precollected(ItemFactory(item, player)) + + if world.mode == 'standard' and not world.state.has_blunt_weapon(player) and "Link's Uncle" not in placed_items: + found_sword = False + found_bow = False + possible_weapons = [] + for item in pool: + if item in ['Progressive Sword', 'Fighter Sword', 'Master Sword', 'Tempered Sword', 'Golden Sword']: + if not found_sword and world.swords != 'swordless': + found_sword = True + possible_weapons.append(item) + if item in ['Progressive Bow', 'Bow'] and not found_bow: + found_bow = True + possible_weapons.append(item) + if item in ['Hammer', 'Bombs (10)', 'Fire Rod', 'Cane of Somaria', 'Cane of Byrna']: + if item not in possible_weapons: + possible_weapons.append(item) + starting_weapon = random.choice(possible_weapons) + placed_items["Link's Uncle"] = starting_weapon + pool.remove(starting_weapon) + for (location, item) in placed_items.items(): world.push_item(world.get_location(location, player), ItemFactory(item, player), False) world.get_location(location, player).event = True world.get_location(location, player).locked = True + + world.itempool += ItemFactory(pool, player) + world.lamps_needed_for_dark_rooms = lamps_needed_for_dark_rooms + if clock_mode is not None: world.clock_mode = clock_mode + if treasure_hunt_count is not None: world.treasure_hunt_count = treasure_hunt_count if treasure_hunt_icon is not None: @@ -235,7 +260,7 @@ take_any_locations = [ def set_up_take_anys(world, player): if world.mode == 'inverted' and 'Dark Sanctuary Hint' in take_any_locations: take_any_locations.remove('Dark Sanctuary Hint') - + regions = random.sample(take_any_locations, 5) old_man_take_any = Region("Old Man Sword Cave", RegionType.Cave, 'the sword cave', player) diff --git a/Rom.py b/Rom.py index dc1c7286..c8dcec01 100644 --- a/Rom.py +++ b/Rom.py @@ -998,6 +998,11 @@ def patch_rom(world, player, rom): rom.write_bytes(0x180185, [0,0,70]) # Uncle respawn refills (magic, bombs, arrows) rom.write_bytes(0x180188, [0,0,10]) # Zelda respawn refills (magic, bombs, arrows) rom.write_bytes(0x18018B, [0,0,10]) # Mantle respawn refills (magic, bombs, arrows) + elif uncle_location.item is not None and uncle_location.item.name in ['Bombs (10)']: + rom.write_byte(0x18004E, 2) # Escape Fill (bombs) + rom.write_bytes(0x180185, [0,50,0]) # Uncle respawn refills (magic, bombs, arrows) + rom.write_bytes(0x180188, [0,3,0]) # Zelda respawn refills (magic, bombs, arrows) + rom.write_bytes(0x18018B, [0,3,0]) # Mantle respawn refills (magic, bombs, arrows) elif uncle_location.item is not None and uncle_location.item.name in ['Cane of Somaria', 'Cane of Byrna', 'Fire Rod']: rom.write_byte(0x18004E, 4) # Escape Fill (magic) rom.write_bytes(0x180185, [0x80,0,0]) # Uncle respawn refills (magic, bombs, arrows) diff --git a/Rules.py b/Rules.py index 0a3acfed..3c2bc18c 100644 --- a/Rules.py +++ b/Rules.py @@ -696,9 +696,6 @@ def no_glitches_rules(world, player): def open_rules(world, player): # softlock protection as you can reach the sewers small key door with a guard drop key - forbid_item(world.get_location('Hyrule Castle - Boomerang Chest', player), 'Small Key (Escape)', player) - forbid_item(world.get_location('Hyrule Castle - Zelda\'s Chest', player), 'Small Key (Escape)', player) - set_rule(world.get_location('Hyrule Castle - Boomerang Chest', player), lambda state: state.has_key('Small Key (Escape)', player)) set_rule(world.get_location('Hyrule Castle - Zelda\'s Chest', player), lambda state: state.has_key('Small Key (Escape)', player)) @@ -723,32 +720,11 @@ def swordless_rules(world, player): set_rule(world.get_entrance('Misery Mire', player), lambda state: state.has_misery_mire_medallion(player)) # sword not required to use medallion for opening in swordless (!) set_rule(world.get_location('Bombos Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has('Hammer', player)) -def standard_rules(world, player): - add_rule(world.get_entrance('Sewers Door', player), lambda state: state.can_kill_most_things(player)) +def standard_rules(world, player): set_rule(world.get_entrance('Hyrule Castle Exit (East)', player), lambda state: state.can_reach('Sanctuary', 'Region', player)) set_rule(world.get_entrance('Hyrule Castle Exit (West)', player), lambda state: state.can_reach('Sanctuary', 'Region', player)) - # ensures the required weapon for escape lands on uncle (unless player has it pre-equipped) - add_rule(world.get_location('Secret Passage', player), lambda state: state.can_kill_most_things(player)) - add_rule(world.get_location('Hyrule Castle - Map Chest', player), lambda state: state.can_kill_most_things(player)) - - def uncle_item_rule(item): - copy_state = CollectionState(world) - copy_state.collect(item) - copy_state.sweep_for_events() - return copy_state.can_reach('Sanctuary', 'Region', player) - - add_item_rule(world.get_location('Link\'s Uncle', player), uncle_item_rule) - - # easiest way to enforce key placement not relevant for open - set_rule(world.get_location('Sewers - Dark Cross', player), lambda state: state.can_kill_most_things(player)) - - set_rule(world.get_location('Hyrule Castle - Boomerang Chest', player), lambda state: state.can_kill_most_things(player)) - set_rule(world.get_location('Hyrule Castle - Zelda\'s Chest', player), lambda state: state.can_kill_most_things(player)) - - - def set_trock_key_rules(world, player): @@ -1191,7 +1167,7 @@ def set_inverted_big_bomb_rules(world, player): 'Dark Desert Hint', 'Dark Desert Fairy', 'Misery Mire'] - LW_bush_entrances = ['Bush Covered House', + LW_bush_entrances = ['Bush Covered House', 'Light World Bomb Hut', 'Graveyard Cave']