fix(key logic): typo
fix(bunny logic): multiple paths considered
This commit is contained in:
@@ -1800,7 +1800,7 @@ def imp_locations_factory(world, player):
|
|||||||
imp_locations = ['Agahnim 1', 'Agahnim 2', 'Attic Cracked Floor', 'Suspicious Maiden']
|
imp_locations = ['Agahnim 1', 'Agahnim 2', 'Attic Cracked Floor', 'Suspicious Maiden']
|
||||||
if world.mode[player] == 'standard':
|
if world.mode[player] == 'standard':
|
||||||
imp_locations.append('Zelda Pickup')
|
imp_locations.append('Zelda Pickup')
|
||||||
imp_locations.append('Zelda Dropoff')
|
imp_locations.append('Zelda Drop Off')
|
||||||
return imp_locations
|
return imp_locations
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
2
Main.py
2
Main.py
@@ -34,7 +34,7 @@ from source.overworld.EntranceShuffle2 import link_entrances_new
|
|||||||
from source.tools.BPS import create_bps_from_data
|
from source.tools.BPS import create_bps_from_data
|
||||||
from source.classes.CustomSettings import CustomSettings
|
from source.classes.CustomSettings import CustomSettings
|
||||||
|
|
||||||
version_number = '1.2.0.21'
|
version_number = '1.2.0.22'
|
||||||
version_branch = '-u'
|
version_branch = '-u'
|
||||||
__version__ = f'{version_number}{version_branch}'
|
__version__ = f'{version_number}{version_branch}'
|
||||||
|
|
||||||
|
|||||||
@@ -109,6 +109,10 @@ These are now independent of retro mode and have three options: None, Random, an
|
|||||||
|
|
||||||
# Bug Fixes and Notes
|
# Bug Fixes and Notes
|
||||||
|
|
||||||
|
* * 1.2.0.22u
|
||||||
|
* Fixed logic issues:
|
||||||
|
* Self-locking key not allowed in Sanctuary in standard (typo fixed)
|
||||||
|
* More advanced bunny-walking logic in dungeons (multiple paths considred)
|
||||||
* 1.2.0.21u
|
* 1.2.0.21u
|
||||||
* Fix that should force items needed for leaving Zelda's cell to before the throne room, so S&Q isn't mandatory
|
* Fix that should force items needed for leaving Zelda's cell to before the throne room, so S&Q isn't mandatory
|
||||||
* Small fix for Tavern Shuffle (thanks Catobat)
|
* Small fix for Tavern Shuffle (thanks Catobat)
|
||||||
|
|||||||
71
Rules.py
71
Rules.py
@@ -101,16 +101,20 @@ def mirrorless_path_to_castle_courtyard(world, player):
|
|||||||
else:
|
else:
|
||||||
queue.append((entrance.connected_region, new_path))
|
queue.append((entrance.connected_region, new_path))
|
||||||
|
|
||||||
|
|
||||||
def set_rule(spot, rule):
|
def set_rule(spot, rule):
|
||||||
spot.access_rule = rule
|
spot.access_rule = rule
|
||||||
|
|
||||||
|
|
||||||
def set_defeat_dungeon_boss_rule(location):
|
def set_defeat_dungeon_boss_rule(location):
|
||||||
# Lambda required to defer evaluation of dungeon.boss since it will change later if boos shuffle is used
|
# Lambda required to defer evaluation of dungeon.boss since it will change later if boos shuffle is used
|
||||||
set_rule(location, lambda state: location.parent_region.dungeon.boss.can_defeat(state))
|
set_rule(location, lambda state: location.parent_region.dungeon.boss.can_defeat(state))
|
||||||
|
|
||||||
|
|
||||||
def set_always_allow(spot, rule):
|
def set_always_allow(spot, rule):
|
||||||
spot.always_allow = rule
|
spot.always_allow = rule
|
||||||
|
|
||||||
|
|
||||||
def add_rule(spot, rule, combine='and'):
|
def add_rule(spot, rule, combine='and'):
|
||||||
old_rule = spot.access_rule
|
old_rule = spot.access_rule
|
||||||
if combine == 'or':
|
if combine == 'or':
|
||||||
@@ -140,22 +144,26 @@ def forbid_item(location, item, player):
|
|||||||
old_rule = location.item_rule
|
old_rule = location.item_rule
|
||||||
location.item_rule = lambda i: (i.name != item or i.player != player) and old_rule(i)
|
location.item_rule = lambda i: (i.name != item or i.player != player) and old_rule(i)
|
||||||
|
|
||||||
|
|
||||||
def add_item_rule(location, rule):
|
def add_item_rule(location, rule):
|
||||||
old_rule = location.item_rule
|
old_rule = location.item_rule
|
||||||
location.item_rule = lambda item: rule(item) and old_rule(item)
|
location.item_rule = lambda item: rule(item) and old_rule(item)
|
||||||
|
|
||||||
|
|
||||||
def item_in_locations(state, item, player, locations):
|
def item_in_locations(state, item, player, locations):
|
||||||
for location in locations:
|
for location in locations:
|
||||||
if item_name(state, location[0], location[1]) == (item, player):
|
if item_name(state, location[0], location[1]) == (item, player):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def item_name(state, location, player):
|
def item_name(state, location, player):
|
||||||
location = state.world.get_location(location, player)
|
location = state.world.get_location(location, player)
|
||||||
if location.item is None:
|
if location.item is None:
|
||||||
return None
|
return None
|
||||||
return (location.item.name, location.item.player)
|
return (location.item.name, location.item.player)
|
||||||
|
|
||||||
|
|
||||||
def global_rules(world, player):
|
def global_rules(world, player):
|
||||||
# ganon can only carry triforce
|
# ganon can only carry triforce
|
||||||
add_item_rule(world.get_location('Ganon', player), lambda item: item.name == 'Triforce' and item.player == player)
|
add_item_rule(world.get_location('Ganon', player), lambda item: item.name == 'Triforce' and item.player == player)
|
||||||
@@ -811,7 +819,7 @@ def bomb_rules(world, player):
|
|||||||
('TR Tongue Pull WS', True),
|
('TR Tongue Pull WS', True),
|
||||||
('TR Twin Pokeys NW', False),
|
('TR Twin Pokeys NW', False),
|
||||||
]
|
]
|
||||||
for killdoor,bombable in easy_kill_rooms:
|
for killdoor, bombable in easy_kill_rooms:
|
||||||
if bombable:
|
if bombable:
|
||||||
add_rule(world.get_entrance(killdoor, player), lambda state: (state.can_use_bombs(player) or state.can_kill_most_things(player)))
|
add_rule(world.get_entrance(killdoor, player), lambda state: (state.can_use_bombs(player) or state.can_kill_most_things(player)))
|
||||||
else:
|
else:
|
||||||
@@ -832,21 +840,21 @@ def bomb_rules(world, player):
|
|||||||
('Hyrule Castle - Map Guard Key Drop', True),
|
('Hyrule Castle - Map Guard Key Drop', True),
|
||||||
('Hyrule Castle - Boomerang Guard Key Drop', True),
|
('Hyrule Castle - Boomerang Guard Key Drop', True),
|
||||||
('Hyrule Castle - Key Rat Key Drop', True),
|
('Hyrule Castle - Key Rat Key Drop', True),
|
||||||
# ('Hyrule Castle - Big Key Drop', True), # Pots are available
|
# ('Hyrule Castle - Big Key Drop', True), # Pots are available
|
||||||
# ('Eastern Palace - Dark Eyegore Key Drop', True), # Pots are available
|
# ('Eastern Palace - Dark Eyegore Key Drop', True), # Pots are available
|
||||||
('Castle Tower - Dark Archer Key Drop', True),
|
('Castle Tower - Dark Archer Key Drop', True),
|
||||||
# ('Castle Tower - Circle of Pots Key Drop', True), # Pots are available
|
# ('Castle Tower - Circle of Pots Key Drop', True), # Pots are available
|
||||||
# ('Skull Woods - Spike Corner Key Drop', True), # Pots are available
|
# ('Skull Woods - Spike Corner Key Drop', True), # Pots are available
|
||||||
('Ice Palace - Jelly Key Drop', True),
|
('Ice Palace - Jelly Key Drop', True),
|
||||||
('Ice Palace - Conveyor Key Drop', True),
|
('Ice Palace - Conveyor Key Drop', True),
|
||||||
('Misery Mire - Conveyor Crystal Key Drop', True),
|
('Misery Mire - Conveyor Crystal Key Drop', True),
|
||||||
('Turtle Rock - Pokey 1 Key Drop', True),
|
('Turtle Rock - Pokey 1 Key Drop', True),
|
||||||
('Turtle Rock - Pokey 2 Key Drop', True),
|
('Turtle Rock - Pokey 2 Key Drop', True),
|
||||||
# ('Ganons Tower - Mini Helmasaur Key Drop', True) # Pots are available
|
# ('Ganons Tower - Mini Helmasaur Key Drop', True) # Pots are available
|
||||||
('Castle Tower - Room 03', True), # Two spring soliders
|
('Castle Tower - Room 03', True), # Two spring soliders
|
||||||
('Ice Palace - Compass Chest', True) # Pengators
|
('Ice Palace - Compass Chest', True) # Pengators
|
||||||
]
|
]
|
||||||
for location,bombable in enemy_kill_drops:
|
for location, bombable in enemy_kill_drops:
|
||||||
if bombable:
|
if bombable:
|
||||||
add_rule(world.get_location(location, player), lambda state: state.can_use_bombs(player) or state.can_kill_most_things(player))
|
add_rule(world.get_location(location, player), lambda state: state.can_use_bombs(player) or state.can_kill_most_things(player))
|
||||||
else:
|
else:
|
||||||
@@ -865,10 +873,10 @@ def bomb_rules(world, player):
|
|||||||
'PoD Warp Hint SE', 'PoD Jelly Hall NW', 'PoD Jelly Hall NE', 'PoD Mimics 1 SW',
|
'PoD Warp Hint SE', 'PoD Jelly Hall NW', 'PoD Jelly Hall NE', 'PoD Mimics 1 SW',
|
||||||
'Thieves Ambush E', 'Thieves Rail Ledge W',
|
'Thieves Ambush E', 'Thieves Rail Ledge W',
|
||||||
'TR Dash Room NW', 'TR Crystaroller SW', 'TR Dash Room ES',
|
'TR Dash Room NW', 'TR Crystaroller SW', 'TR Dash Room ES',
|
||||||
'GT Four Torches NW','GT Fairy Abyss SW'
|
'GT Four Torches NW', 'GT Fairy Abyss SW'
|
||||||
]
|
]
|
||||||
dungeon_bombable = ['PoD Map Balcony WS', 'PoD Arena Ledge ES', 'PoD Dark Maze E', 'PoD Big Chest Balcony W',
|
dungeon_bombable = ['PoD Map Balcony WS', 'PoD Arena Ledge ES', 'PoD Dark Maze E', 'PoD Big Chest Balcony W',
|
||||||
'Swamp Pot Row WN','Swamp Map Ledge EN', 'Swamp Hammer Switch WN', 'Swamp Hub Dead Ledge EN', 'Swamp Waterway N', 'Swamp I S',
|
'Swamp Pot Row WN', 'Swamp Map Ledge EN', 'Swamp Hammer Switch WN', 'Swamp Hub Dead Ledge EN', 'Swamp Waterway N', 'Swamp I S',
|
||||||
'Skull Pot Circle WN', 'Skull Pull Switch EN', 'Skull Big Key EN', 'Skull Lone Pot WN',
|
'Skull Pot Circle WN', 'Skull Pull Switch EN', 'Skull Big Key EN', 'Skull Lone Pot WN',
|
||||||
'Thieves Rail Ledge NW', 'Thieves Pot Alcove Bottom SW',
|
'Thieves Rail Ledge NW', 'Thieves Pot Alcove Bottom SW',
|
||||||
'Ice Bomb Drop Hole', 'Ice Freezors Bomb Hole',
|
'Ice Bomb Drop Hole', 'Ice Freezors Bomb Hole',
|
||||||
@@ -1109,17 +1117,20 @@ def forbid_bomb_jump_requirements(world, player):
|
|||||||
set_rule(world.get_entrance('Paradox Cave Bomb Jump', player), lambda state: False)
|
set_rule(world.get_entrance('Paradox Cave Bomb Jump', player), lambda state: False)
|
||||||
set_rule(world.get_entrance('Ice Island To East Pier', player), lambda state: False)
|
set_rule(world.get_entrance('Ice Island To East Pier', player), lambda state: False)
|
||||||
|
|
||||||
|
|
||||||
# Light cones in standard depend on which world we actually are in, not which one the location would normally be
|
# 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
|
# 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)',
|
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)']
|
'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):
|
def check_is_dark_world(region):
|
||||||
for entrance in region.entrances:
|
for entrance in region.entrances:
|
||||||
if entrance.name in DW_Entrances:
|
if entrance.name in DW_Entrances:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def add_conditional_lamps(world, player):
|
def add_conditional_lamps(world, player):
|
||||||
def add_conditional_lamp(spot, region, spottype='Location'):
|
def add_conditional_lamp(spot, region, spottype='Location'):
|
||||||
if spottype == 'Location':
|
if spottype == 'Location':
|
||||||
@@ -1262,6 +1273,7 @@ std_kill_doors_if_trapped = {
|
|||||||
# 'Ice Lobby S' # can melt rule is sufficient
|
# 'Ice Lobby S' # can melt rule is sufficient
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def add_connection(parent_name, target_name, entrance_name, world, player):
|
def add_connection(parent_name, target_name, entrance_name, world, player):
|
||||||
parent = world.get_region(parent_name, player)
|
parent = world.get_region(parent_name, player)
|
||||||
target = world.get_region(target_name, player)
|
target = world.get_region(target_name, player)
|
||||||
@@ -1326,6 +1338,7 @@ def standard_rules(world, player):
|
|||||||
|
|
||||||
def check_rule_list(state, r_list):
|
def check_rule_list(state, r_list):
|
||||||
return True if len(r_list) <= 0 else r_list[0](state) and check_rule_list(state, r_list[1:])
|
return True if len(r_list) <= 0 else r_list[0](state) and check_rule_list(state, r_list[1:])
|
||||||
|
|
||||||
rule_list, debug_path = find_rules_for_zelda_delivery(world, player)
|
rule_list, debug_path = find_rules_for_zelda_delivery(world, player)
|
||||||
set_rule(world.get_entrance('Hyrule Castle Throne Room Tapestry', player),
|
set_rule(world.get_entrance('Hyrule Castle Throne Room Tapestry', player),
|
||||||
lambda state: state.has('Zelda Herself', player) and check_rule_list(state, rule_list))
|
lambda state: state.has('Zelda Herself', player) and check_rule_list(state, rule_list))
|
||||||
@@ -1502,7 +1515,7 @@ def set_big_bomb_rules(world, player):
|
|||||||
|
|
||||||
set_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_reach('East Dark World', 'Region', player) and state.can_reach('Big Bomb Shop', 'Region', player) and state.has('Crystal 5', player) and state.has('Crystal 6', player))
|
set_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_reach('East Dark World', 'Region', player) and state.can_reach('Big Bomb Shop', 'Region', player) and state.has('Crystal 5', player) and state.has('Crystal 6', player))
|
||||||
|
|
||||||
#crossing peg bridge starting from the southern dark world
|
# crossing peg bridge starting from the southern dark world
|
||||||
def cross_peg_bridge(state):
|
def cross_peg_bridge(state):
|
||||||
return state.has('Hammer', player) and state.has_Pearl(player)
|
return state.has('Hammer', player) and state.has_Pearl(player)
|
||||||
|
|
||||||
@@ -1524,28 +1537,28 @@ def set_big_bomb_rules(world, player):
|
|||||||
# G = Glove
|
# G = Glove
|
||||||
|
|
||||||
if bombshop_entrance.name in Normal_LW_entrances:
|
if bombshop_entrance.name in Normal_LW_entrances:
|
||||||
#1. basic routes
|
# 1. basic routes
|
||||||
#2. Can reach Eastern dark world some other way, mirror, get bomb, return to mirror spot, walk to pyramid: Needs mirror
|
# 2. Can reach Eastern dark world some other way, mirror, get bomb, return to mirror spot, walk to pyramid: Needs mirror
|
||||||
# -> M or BR
|
# -> M or BR
|
||||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: basic_routes(state) or state.has_Mirror(player))
|
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: basic_routes(state) or state.has_Mirror(player))
|
||||||
elif bombshop_entrance.name in LW_walkable_entrances:
|
elif bombshop_entrance.name in LW_walkable_entrances:
|
||||||
#1. Mirror then basic routes
|
# 1. Mirror then basic routes
|
||||||
# -> M and BR
|
# -> M and BR
|
||||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player) and basic_routes(state))
|
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player) and basic_routes(state))
|
||||||
elif bombshop_entrance.name in Northern_DW_entrances:
|
elif bombshop_entrance.name in Northern_DW_entrances:
|
||||||
#1. Mirror and basic routes
|
# 1. Mirror and basic routes
|
||||||
#2. Go to south DW and then cross peg bridge: Need Mitts and hammer and moon pearl
|
# 2. Go to south DW and then cross peg bridge: Need Mitts and hammer and moon pearl
|
||||||
# -> (Mitts and CPB) or (M and BR)
|
# -> (Mitts and CPB) or (M and BR)
|
||||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_lift_heavy_rocks(player) and cross_peg_bridge(state)) or (state.has_Mirror(player) and basic_routes(state)))
|
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_lift_heavy_rocks(player) and cross_peg_bridge(state)) or (state.has_Mirror(player) and basic_routes(state)))
|
||||||
elif bombshop_entrance.name == 'Bumper Cave (Bottom)':
|
elif bombshop_entrance.name == 'Bumper Cave (Bottom)':
|
||||||
#1. Mirror and Lift rock and basic_routes
|
# 1. Mirror and Lift rock and basic_routes
|
||||||
#2. Mirror and Flute and basic routes (can make difference if accessed via insanity or w/ mirror from connector, and then via hyrule castle gate, because no gloves are needed in that case)
|
# 2. Mirror and Flute and basic routes (can make difference if accessed via insanity or w/ mirror from connector, and then via hyrule castle gate, because no gloves are needed in that case)
|
||||||
#3. Go to south DW and then cross peg bridge: Need Mitts and hammer and moon pearl
|
# 3. Go to south DW and then cross peg bridge: Need Mitts and hammer and moon pearl
|
||||||
# -> (Mitts and CPB) or (((G or Flute) and M) and BR))
|
# -> (Mitts and CPB) or (((G or Flute) and M) and BR))
|
||||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_lift_heavy_rocks(player) and cross_peg_bridge(state)) or (((state.can_lift_rocks(player) or state.can_flute(player)) and state.has_Mirror(player)) and basic_routes(state)))
|
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_lift_heavy_rocks(player) and cross_peg_bridge(state)) or (((state.can_lift_rocks(player) or state.can_flute(player)) and state.has_Mirror(player)) and basic_routes(state)))
|
||||||
elif bombshop_entrance.name in Southern_DW_entrances:
|
elif bombshop_entrance.name in Southern_DW_entrances:
|
||||||
#1. Mirror and enter via gate: Need mirror and Aga1
|
# 1. Mirror and enter via gate: Need mirror and Aga1
|
||||||
#2. cross peg bridge: Need hammer and moon pearl
|
# 2. cross peg bridge: Need hammer and moon pearl
|
||||||
# -> CPB or (M and A)
|
# -> CPB or (M and A)
|
||||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: cross_peg_bridge(state) or (state.has_Mirror(player) and state.has('Beat Agahnim 1', player)))
|
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: cross_peg_bridge(state) or (state.has_Mirror(player) and state.has('Beat Agahnim 1', player)))
|
||||||
elif bombshop_entrance.name in Isolated_DW_entrances:
|
elif bombshop_entrance.name in Isolated_DW_entrances:
|
||||||
@@ -1809,7 +1822,6 @@ def set_inverted_big_bomb_rules(world, player):
|
|||||||
|
|
||||||
|
|
||||||
def set_bunny_rules(world, player, inverted):
|
def set_bunny_rules(world, player, inverted):
|
||||||
|
|
||||||
# regions for the exits of multi-entrace caves/drops that bunny cannot pass
|
# 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.
|
# 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 (top)', 'Bumper Cave (bottom)', 'Two Brothers House',
|
bunny_impassable_caves = ['Bumper Cave (top)', 'Bumper Cave (bottom)', 'Two Brothers House',
|
||||||
@@ -1848,13 +1860,14 @@ def set_bunny_rules(world, player, inverted):
|
|||||||
return region.is_light_world
|
return region.is_light_world
|
||||||
else:
|
else:
|
||||||
return region.is_dark_world
|
return region.is_dark_world
|
||||||
|
|
||||||
def is_link(region):
|
def is_link(region):
|
||||||
if inverted:
|
if inverted:
|
||||||
return region.is_dark_world
|
return region.is_dark_world
|
||||||
else:
|
else:
|
||||||
return region.is_light_world
|
return region.is_light_world
|
||||||
|
|
||||||
def get_rule_to_add(region, location = None, connecting_entrance = None):
|
def get_rule_to_add(region, location=None, connecting_entrance=None):
|
||||||
# In OWG, a location can potentially be superbunny-mirror accessible or
|
# In OWG, a location can potentially be superbunny-mirror accessible or
|
||||||
# bunny revival accessible.
|
# bunny revival accessible.
|
||||||
if world.logic[player] == 'owglitches':
|
if world.logic[player] == 'owglitches':
|
||||||
@@ -1877,16 +1890,15 @@ def set_bunny_rules(world, player, inverted):
|
|||||||
# for each such entrance a new option is added that consist of:
|
# for each such entrance a new option is added that consist of:
|
||||||
# a) being able to reach it, and
|
# a) being able to reach it, and
|
||||||
# b) being able to access all entrances from there to `region`
|
# b) being able to access all entrances from there to `region`
|
||||||
seen = {region}
|
queue = deque([(region, [], {region})])
|
||||||
queue = deque([(region, [])])
|
|
||||||
while queue:
|
while queue:
|
||||||
(current, path) = queue.popleft()
|
(current, path, seen) = queue.popleft()
|
||||||
for entrance in current.entrances:
|
for entrance in current.entrances:
|
||||||
new_region = entrance.parent_region
|
new_region = entrance.parent_region
|
||||||
if new_region.type in (RegionType.Cave, RegionType.Dungeon) and new_region in seen:
|
if new_region.type in (RegionType.Cave, RegionType.Dungeon) and new_region in seen:
|
||||||
continue
|
continue
|
||||||
new_path = path + [entrance.access_rule]
|
new_path = path + [entrance.access_rule]
|
||||||
seen.add(new_region)
|
new_seen = seen.union({new_region})
|
||||||
if not is_link(new_region):
|
if not is_link(new_region):
|
||||||
if world.logic[player] == 'owglitches':
|
if world.logic[player] == 'owglitches':
|
||||||
if region.type == RegionType.Dungeon and new_region.type != RegionType.Dungeon:
|
if region.type == RegionType.Dungeon and new_region.type != RegionType.Dungeon:
|
||||||
@@ -1923,7 +1935,7 @@ def set_bunny_rules(world, player, inverted):
|
|||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
if is_bunny(new_region):
|
if is_bunny(new_region):
|
||||||
queue.append((new_region, new_path))
|
queue.append((new_region, new_path, new_seen))
|
||||||
else:
|
else:
|
||||||
# we have reached pure light world, so we have a new possible option
|
# we have reached pure light world, so we have a new possible option
|
||||||
possible_options.append(path_to_access_rule(new_path, entrance))
|
possible_options.append(path_to_access_rule(new_path, entrance))
|
||||||
@@ -1975,7 +1987,6 @@ drop_dungeon_entrances = {
|
|||||||
"Skull Back Drop"
|
"Skull Back Drop"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bunny_revivable_entrances = {
|
bunny_revivable_entrances = {
|
||||||
"Sewers Pull Switch", "TR Dash Room", "Swamp Boss", "Hera Boss",
|
"Sewers Pull Switch", "TR Dash Room", "Swamp Boss", "Hera Boss",
|
||||||
"Tower Agahnim 1", "Ice Lobby", "Sewers Rat Path", "PoD Falling Bridge",
|
"Tower Agahnim 1", "Ice Lobby", "Sewers Rat Path", "PoD Falling Bridge",
|
||||||
@@ -2227,7 +2238,7 @@ def create_key_rule(small_key_name, player, keys):
|
|||||||
|
|
||||||
def create_key_rule_allow_small(small_key_name, player, keys, location):
|
def create_key_rule_allow_small(small_key_name, player, keys, location):
|
||||||
loc = location.name
|
loc = location.name
|
||||||
return lambda state: state.has_sm_key(small_key_name, player, keys) or (item_name(state, loc, player) in [(small_key_name, player)] and state.has_sm_key(small_key_name, player, keys-1))
|
return lambda state: state.has_sm_key(small_key_name, player, keys) or (item_name(state, loc, player) in [(small_key_name, player)] and state.has_sm_key(small_key_name, player, keys - 1))
|
||||||
|
|
||||||
|
|
||||||
def create_key_rule_bk_exception(small_key_name, big_key_name, player, keys, bk_keys, bk_locs):
|
def create_key_rule_bk_exception(small_key_name, big_key_name, player, keys, bk_keys, bk_locs):
|
||||||
@@ -2238,7 +2249,7 @@ def create_key_rule_bk_exception(small_key_name, big_key_name, player, keys, bk_
|
|||||||
def create_key_rule_bk_exception_or_allow(small_key_name, big_key_name, player, keys, location, bk_keys, bk_locs):
|
def create_key_rule_bk_exception_or_allow(small_key_name, big_key_name, player, keys, location, bk_keys, bk_locs):
|
||||||
loc = location.name
|
loc = location.name
|
||||||
chest_names = [x.name for x in bk_locs]
|
chest_names = [x.name for x in bk_locs]
|
||||||
return lambda state: (state.has_sm_key(small_key_name, player, keys) and not item_in_locations(state, big_key_name, player, zip(chest_names, [player] * len(chest_names)))) or (item_name(state, loc, player) in [(small_key_name, player)] and state.has_sm_key(small_key_name, player, keys-1)) or (item_in_locations(state, big_key_name, player, zip(chest_names, [player] * len(chest_names))) and state.has_sm_key(small_key_name, player, bk_keys))
|
return lambda state: (state.has_sm_key(small_key_name, player, keys) and not item_in_locations(state, big_key_name, player, zip(chest_names, [player] * len(chest_names)))) or (item_name(state, loc, player) in [(small_key_name, player)] and state.has_sm_key(small_key_name, player, keys - 1)) or (item_in_locations(state, big_key_name, player, zip(chest_names, [player] * len(chest_names))) and state.has_sm_key(small_key_name, player, bk_keys))
|
||||||
|
|
||||||
|
|
||||||
def create_advanced_key_rule(key_logic, player, rule):
|
def create_advanced_key_rule(key_logic, player, rule):
|
||||||
|
|||||||
Reference in New Issue
Block a user