diff --git a/worlds/alttp/Rules.py b/worlds/alttp/Rules.py index e6c5f15a..09c63aca 100644 --- a/worlds/alttp/Rules.py +++ b/worlds/alttp/Rules.py @@ -4,7 +4,7 @@ from typing import Iterator, Set from BaseClasses import Entrance, MultiWorld from worlds.generic.Rules import (add_item_rule, add_rule, forbid_item, - item_in_locations, location_item_name, set_rule, allow_self_locking_items) + item_name_in_location_names, location_item_name, set_rule, allow_self_locking_items) from . import OverworldGlitchRules from .Bosses import GanonDefeatRule @@ -305,7 +305,7 @@ def global_rules(world, player): set_rule(world.get_location('Ice Palace - Big Chest', player), lambda state: state.has('Big Key (Ice Palace)', player)) set_rule(world.get_entrance('Ice Palace (Kholdstare)', player), lambda state: can_lift_rocks(state, player) and state.has('Hammer', player) and state.has('Big Key (Ice Palace)', player) and (state._lttp_has_key('Small Key (Ice Palace)', player, 2) or (state.has('Cane of Somaria', player) and state._lttp_has_key('Small Key (Ice Palace)', player, 1)))) set_rule(world.get_entrance('Ice Palace (East)', player), lambda state: (state.has('Hookshot', player) or ( - item_in_locations(state, 'Big Key (Ice Palace)', player, [('Ice Palace - Spike Room', player), ('Ice Palace - Big Key Chest', player), ('Ice Palace - Map Chest', player)]) and state._lttp_has_key('Small Key (Ice Palace)', player))) and (state.multiworld.can_take_damage[player] or state.has('Hookshot', player) or state.has('Cape', player) or state.has('Cane of Byrna', player))) + item_name_in_location_names(state, 'Big Key (Ice Palace)', player, [('Ice Palace - Spike Room', player), ('Ice Palace - Big Key Chest', player), ('Ice Palace - Map Chest', player)]) and state._lttp_has_key('Small Key (Ice Palace)', player))) and (state.multiworld.can_take_damage[player] or state.has('Hookshot', player) or state.has('Cape', player) or state.has('Cane of Byrna', player))) set_rule(world.get_entrance('Ice Palace (East Top)', player), lambda state: can_lift_rocks(state, player) and state.has('Hammer', player)) set_rule(world.get_entrance('Misery Mire Entrance Gap', player), lambda state: (state.has('Pegasus Boots', player) or state.has('Hookshot', player)) and (has_sword(state, player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Hammer', player) or state.has('Cane of Somaria', player) or can_shoot_arrows(state, player))) # need to defeat wizzrobes, bombs don't work ... @@ -381,17 +381,17 @@ def global_rules(world, player): #The actual requirements for these rooms to avoid key-lock set_rule(world.get_location('Ganons Tower - Firesnake Room', player), lambda state: state._lttp_has_key('Small Key (Ganons Tower)', player, 3) or (( - item_in_locations(state, 'Big Key (Ganons Tower)', player, zip(randomizer_room_chests, [player] * len(randomizer_room_chests))) or item_in_locations(state, 'Small Key (Ganons Tower)', player, [('Ganons Tower - Firesnake Room', player)])) and state._lttp_has_key('Small Key (Ganons Tower)', player, 2))) + item_name_in_location_names(state, 'Big Key (Ganons Tower)', player, zip(randomizer_room_chests, [player] * len(randomizer_room_chests))) or item_name_in_location_names(state, 'Small Key (Ganons Tower)', player, [('Ganons Tower - Firesnake Room', player)])) and state._lttp_has_key('Small Key (Ganons Tower)', player, 2))) for location in randomizer_room_chests: set_rule(world.get_location(location, player), lambda state: state._lttp_has_key('Small Key (Ganons Tower)', player, 4) or ( - item_in_locations(state, 'Big Key (Ganons Tower)', player, zip(randomizer_room_chests, [player] * len(randomizer_room_chests))) and state._lttp_has_key('Small Key (Ganons Tower)', player, 3))) + item_name_in_location_names(state, 'Big Key (Ganons Tower)', player, zip(randomizer_room_chests, [player] * len(randomizer_room_chests))) and state._lttp_has_key('Small Key (Ganons Tower)', player, 3))) # Once again it is possible to need more than 3 keys... set_rule(world.get_entrance('Ganons Tower (Tile Room) Key Door', player), lambda state: state._lttp_has_key('Small Key (Ganons Tower)', player, 3) and state.has('Fire Rod', player)) # Actual requirements for location in compass_room_chests: set_rule(world.get_location(location, player), lambda state: state.has('Fire Rod', player) and (state._lttp_has_key('Small Key (Ganons Tower)', player, 4) or ( - item_in_locations(state, 'Big Key (Ganons Tower)', player, zip(compass_room_chests, [player] * len(compass_room_chests))) and state._lttp_has_key('Small Key (Ganons Tower)', player, 3)))) + item_name_in_location_names(state, 'Big Key (Ganons Tower)', player, zip(compass_room_chests, [player] * len(compass_room_chests))) and state._lttp_has_key('Small Key (Ganons Tower)', player, 3)))) set_rule(world.get_location('Ganons Tower - Big Chest', player), lambda state: state.has('Big Key (Ganons Tower)', player)) @@ -919,7 +919,7 @@ def set_trock_key_rules(world, player): else: # Middle to front requires 2 keys if the back is locked, otherwise 4 set_rule(world.get_entrance('Turtle Rock (Chain Chomp Room) (South)', player), lambda state: state._lttp_has_key('Small Key (Turtle Rock)', player, 2) - if item_in_locations(state, 'Big Key (Turtle Rock)', player, front_locked_locations) + if item_name_in_location_names(state, 'Big Key (Turtle Rock)', player, front_locked_locations) else state._lttp_has_key('Small Key (Turtle Rock)', player, 4)) # Front to middle requires 2 keys (if the middle is accessible then these doors can be avoided, otherwise no keys can be wasted) diff --git a/worlds/generic/Rules.py b/worlds/generic/Rules.py index fb783edb..520ad225 100644 --- a/worlds/generic/Rules.py +++ b/worlds/generic/Rules.py @@ -140,14 +140,22 @@ def add_item_rule(location: "BaseClasses.Location", rule: ItemRule, combine: str location.item_rule = lambda item: rule(item) or old_rule(item) -def item_in_locations(state: "BaseClasses.CollectionState", item: str, player: int, - locations: typing.Sequence["BaseClasses.Location"]) -> bool: - for location in locations: +def item_name_in_location_names(state: "BaseClasses.CollectionState", item: str, player: int, + location_name_player_pairs: typing.Sequence[typing.Tuple[str, int]]) -> bool: + for location in location_name_player_pairs: if location_item_name(state, location[0], location[1]) == (item, player): return True return False +def item_name_in_locations(item: str, player: int, + locations: typing.Sequence["BaseClasses.Location"]) -> bool: + for location in locations: + if location.item and location.item.name == item and location.item.player == player: + return True + return False + + def location_item_name(state: "BaseClasses.CollectionState", location: str, player: int) -> \ typing.Optional[typing.Tuple[str, int]]: location = state.multiworld.get_location(location, player)