Add cross world bunny logic
This commit is contained in:
parent
a0237e0863
commit
f39886579a
|
@ -562,6 +562,7 @@ class Region(object):
|
|||
self.dungeon = None
|
||||
self.world = None
|
||||
self.is_light_world = False # will be set aftermaking connections.
|
||||
self.is_dark_world = False
|
||||
self.spot_type = 'Region'
|
||||
self.hint_text = 'Hyrule'
|
||||
self.recursion_count = 0
|
||||
|
|
1
Main.py
1
Main.py
|
@ -154,6 +154,7 @@ def copy_world(world):
|
|||
for region in world.regions:
|
||||
copied_region = ret.get_region(region.name)
|
||||
copied_region.is_light_world = region.is_light_world
|
||||
copied_region.is_dark_world = region.is_dark_world
|
||||
for entrance in region.entrances:
|
||||
ret.get_entrance(entrance.name).connect(copied_region)
|
||||
|
||||
|
|
28
Regions.py
28
Regions.py
|
@ -298,22 +298,30 @@ def _create_region(name, type, locations=None, exits=None):
|
|||
ret.locations.append(Location(location, address, crystal, hint_text, ret))
|
||||
return ret
|
||||
|
||||
|
||||
def mark_light_world_regions(world):
|
||||
# Note that in "inanity" shuffle this code may mark some dark world locations as being in light world. That is fine because this flag
|
||||
# is only used for bunny logic, and you start with a Moon pearl immediately availible in Insanity shuffle.
|
||||
|
||||
# Exclude entrances that represent connections from the light world to the dark world
|
||||
excluded_entrances = set(['Top of Pyramid', 'Lake Hylia Central Island Teleporter', 'Dark Desert Teleporter', 'East Hyrule Teleporter', 'South Hyrule Teleporter', 'Kakariko Teleporter', 'Death Mountain Teleporter', 'East Death Mountain Teleporter', 'Turtle Rock Teleporter'])
|
||||
|
||||
starting_regions = ['Links House', 'Cave 45 Ledge', 'Graveyard Ledge', 'Mimic Cave Ledge', 'Death Mountain Floating Island (Light World)', 'Desert Ledge', 'Desert Ledge (Northeast)', 'Lake Hylia Island', 'Spectacle Rock', 'Death Mountain Return Ledge', 'Hyrule Castle Ledge', 'Maze Race Ledge']
|
||||
queue = collections.deque([world.get_region(region) for region in starting_regions])
|
||||
# cross world caves may have some sections marked as both in_light_world, and in_dark_work.
|
||||
# That is ok. the bunny logic will check for this case and incorporate special rules.
|
||||
queue = collections.deque(region for region in world.regions if region.type == RegionType.LightWorld)
|
||||
seen = set(queue)
|
||||
while queue:
|
||||
current = queue.popleft()
|
||||
current.is_light_world = True
|
||||
for exit in current.exits:
|
||||
if exit.name in excluded_entrances:
|
||||
if exit.connected_region.type == RegionType.DarkWorld:
|
||||
# Don't venture into the dark world
|
||||
continue
|
||||
if exit.connected_region not in seen:
|
||||
seen.add(exit.connected_region)
|
||||
queue.append(exit.connected_region)
|
||||
|
||||
queue = collections.deque(region for region in world.regions if region.type == RegionType.DarkWorld)
|
||||
seen = set(queue)
|
||||
while queue:
|
||||
current = queue.popleft()
|
||||
current.is_dark_world = True
|
||||
for exit in current.exits:
|
||||
if exit.connected_region.type == RegionType.LightWorld:
|
||||
# Don't venture into the light world
|
||||
continue
|
||||
if exit.connected_region not in seen:
|
||||
seen.add(exit.connected_region)
|
||||
|
|
55
Rules.py
55
Rules.py
|
@ -1,3 +1,4 @@
|
|||
import collections
|
||||
import logging
|
||||
|
||||
|
||||
|
@ -749,25 +750,65 @@ def set_bunny_rules(world):
|
|||
|
||||
bunny_accessible_locations = ['Link\'s Uncle', 'Sahasrahla', 'Sick Kid', 'Lost Woods Hideout', 'Lumberjack Tree', 'Checkerboard Cave', 'Potion Shop', 'Spectacle Rock Cave', 'Pyramid', 'Hype Cave - Generous Guy', 'Peg Cave', 'Bumper Cave Ledge']
|
||||
|
||||
if not world.get_region('Dam').is_light_world:
|
||||
if world.get_region('Dam').is_dark_world:
|
||||
# if Dam is is dark world, then it is required to have the pearl to get the sunken item
|
||||
add_rule(world.get_location('Sunken Treasure'), lambda state: state.has_Pearl())
|
||||
# similarly we need perl to get across the swamp palace moat
|
||||
add_rule(world.get_entrance('Swamp Palace Moat'), lambda state: state.has_Pearl())
|
||||
|
||||
# Add pearl requirements for bunny-impassible caves if they occur in the dark world
|
||||
def path_to_access_rule(path, entrance):
|
||||
return lambda state: state.can_reach(entrance) and all(rule(state) for rule in path)
|
||||
|
||||
def options_to_access_rule(options):
|
||||
return lambda state: any(rule(state) for rule in options)
|
||||
|
||||
def get_rule_to_add(region):
|
||||
if not region.is_light_world:
|
||||
return lambda state: state.has_Pearl()
|
||||
# in this case we are mixed region.
|
||||
# we collect possible options.
|
||||
|
||||
# The base option is having the moon pearl
|
||||
possible_options = [lambda state: state.has_Pearl()]
|
||||
|
||||
# We will search entrances recursively until we find
|
||||
# one that leads to an exclusively light world region
|
||||
# for each such entrance a new option ios aded that consist of:
|
||||
# a) being able to reach it, and
|
||||
# b) being able to access all entrances from there to `region`
|
||||
seen = set([region])
|
||||
queue = collections.deque([(region, [])])
|
||||
while queue:
|
||||
(current, path) = queue.popleft()
|
||||
for entrance in current.entrances:
|
||||
new_region = entrance.parent_region
|
||||
if new_region in seen:
|
||||
continue
|
||||
new_path = path + [entrance.access_rule]
|
||||
seen.add(new_region)
|
||||
if not new_region.is_light_world:
|
||||
continue # we don't care about pure dark world entrances
|
||||
if new_region.is_dark_world:
|
||||
queue.append((new_region, new_path))
|
||||
else:
|
||||
# we have reached pure light world, so we have a new possible option
|
||||
possible_options.append(path_to_access_rule(new_path, entrance))
|
||||
return options_to_access_rule(possible_options)
|
||||
|
||||
# Add requirements for bunny-impassible caves if they occur in the dark world
|
||||
for region in [world.get_region(name) for name in bunny_impassable_caves]:
|
||||
|
||||
if region.is_light_world:
|
||||
if not region.is_dark_world:
|
||||
continue
|
||||
rule = get_rule_to_add(region)
|
||||
for exit in region.exits:
|
||||
add_rule(exit, lambda state: state.has_Pearl())
|
||||
add_rule(exit, rule)
|
||||
|
||||
# Add a moon pearl requirement for all locations that are actually in the dark world, except those available to the bunny
|
||||
# Add requirements for all locations that are actually in the dark world, except those available to the bunny
|
||||
for location in world.get_locations():
|
||||
if not location.parent_region.is_light_world:
|
||||
if location.parent_region.is_dark_world:
|
||||
|
||||
if location.name in bunny_accessible_locations:
|
||||
continue
|
||||
|
||||
add_rule(location, lambda state: state.has_Pearl())
|
||||
add_rule(location, get_rule_to_add(location.parent_region))
|
||||
|
|
Loading…
Reference in New Issue