Bunny impassible rules for doorways

This commit is contained in:
aerinon
2020-02-12 14:19:29 -07:00
parent d0369fe1c6
commit 6bd05982ae
6 changed files with 180 additions and 65 deletions

155
Rules.py
View File

@@ -1,6 +1,7 @@
import logging
from BaseClasses import CollectionState, RegionType
from BaseClasses import CollectionState, RegionType, DoorType
from Regions import key_only_locations
from RoomData import DoorKind
from collections import deque
@@ -1252,7 +1253,7 @@ def set_inverted_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('Inverted 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):
return state.has('Hammer', player)
@@ -1313,23 +1314,18 @@ def set_bunny_rules(world, player):
# 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', 'Two Brothers House', 'Hookshot Cave',
'Pyramid', 'Spiral Cave (Top)', 'Fairy Ascension Cave (Drop)']
# todo: bunny impassable caves
# sewers drop may or may not be - maybe just new terminology
# desert pots are impassible by bunny - need rules for those transitions
# skull woods drops tend to soft lock bunny
# tr too - dark ride, chest gap, entrance gap, pots in lazy eyes, etc
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', 'Dark Blacksmith Ruins']
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', 'Dark Blacksmith Ruins']
def path_to_access_rule(path, entrance):
return lambda state: state.can_reach(entrance) and all(rule(state) for rule in path)
return lambda state: state.can_reach(entrance) and all(rule_func(state) for rule_func in path)
def options_to_access_rule(options):
return lambda state: any(rule(state) for rule in options)
return lambda state: any(rule_func(state) for rule_func in options)
def get_rule_to_add(region):
if not region.is_light_world:
def get_rule_to_add(start_region):
if not start_region.is_light_world:
return lambda state: state.has_Pearl(player)
# in this case we are mixed region.
# we collect possible options.
@@ -1342,8 +1338,8 @@ def set_bunny_rules(world, player):
# for each such entrance a new option is added 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 = deque([(region, [])])
seen = {start_region}
queue = deque([(start_region, [])])
while queue:
(current, path) = queue.popleft()
for entrance in current.entrances:
@@ -1353,7 +1349,7 @@ def set_bunny_rules(world, player):
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
continue # we don't care about pure dark world entrances
if new_region.is_dark_world:
queue.append((new_region, new_path))
else:
@@ -1367,13 +1363,25 @@ def set_bunny_rules(world, player):
if not region.is_dark_world:
continue
rule = get_rule_to_add(region)
for exit in region.exits:
add_rule(exit, rule)
for ext in region.exits:
add_rule(ext, rule)
paradox_shop = world.get_region('Light World Death Mountain Shop', player)
if paradox_shop.is_dark_world:
add_rule(paradox_shop.entrances[0], get_rule_to_add(paradox_shop))
for ent_name in bunny_impassible_doors:
bunny_exit = world.get_entrance(ent_name, player)
if bunny_exit.parent_region.is_dark_world:
add_rule(bunny_exit, get_rule_to_add(bunny_exit.parent_region))
doors_to_check = [x for x in world.doors if x.player == player and x not in bunny_impassible_doors]
doors_to_check = [x for x in doors_to_check if x.type in [DoorType.Normal, DoorType.Interior] and not x.blocked]
for door in doors_to_check:
room = world.get_room(door.roomIndex, player)
if door.entrance.parent_region.is_dark_world and room.kind(door) in [DoorKind.Dashable, DoorKind.Bombable, DoorKind.Hidden]:
add_rule(door.entrance, get_rule_to_add(door.entrance.parent_region))
# 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 location.player == player and location.parent_region.is_dark_world:
@@ -1383,29 +1391,26 @@ def set_bunny_rules(world, player):
add_rule(location, get_rule_to_add(location.parent_region))
def set_inverted_bunny_rules(world, player):
# 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.
bunny_impassable_caves = ['Bumper Cave', 'Two Brothers House', 'Hookshot Cave',
'Pyramid', 'Spiral Cave (Top)', 'Fairy Ascension Cave (Drop)', 'The Sky']
# todo: bunny impassable caves
# sewers drop may or may not be - maybe just new terminology
# desert pots are impassible by bunny - need rules for those transitions
# skull woods drops tend to soft lock bunny
# tr too - dark ride, chest gap, entrance gap, pots in lazy eyes, etc
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', 'Dark Blacksmith Ruins', 'Bombos Tablet', 'Ether Tablet', 'Purple Chest']
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', 'Dark Blacksmith Ruins',
'Bombos Tablet', 'Ether Tablet', 'Purple Chest']
def path_to_access_rule(path, entrance):
return lambda state: state.can_reach(entrance) and all(rule(state) for rule in path)
return lambda state: state.can_reach(entrance) and all(rule_func(state) for rule_func in path)
def options_to_access_rule(options):
return lambda state: any(rule(state) for rule in options)
return lambda state: any(rule_func(state) for rule_func in options)
def get_rule_to_add(region):
if not region.is_dark_world:
def get_rule_to_add(start_region):
if not start_region.is_dark_world:
return lambda state: state.has_Pearl(player)
# in this case we are mixed region.
# we collect possible options.
@@ -1418,8 +1423,8 @@ def set_inverted_bunny_rules(world, player):
# for each such entrance a new option is added 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 = deque([(region, [])])
seen = {start_region}
queue = deque([(start_region, [])])
while queue:
(current, path) = queue.popleft()
for entrance in current.entrances:
@@ -1429,7 +1434,7 @@ def set_inverted_bunny_rules(world, player):
new_path = path + [entrance.access_rule]
seen.add(new_region)
if not new_region.is_dark_world:
continue # we don't care about pure light world entrances
continue # we don't care about pure light world entrances
if new_region.is_light_world:
queue.append((new_region, new_path))
else:
@@ -1443,13 +1448,25 @@ def set_inverted_bunny_rules(world, player):
if not region.is_light_world:
continue
rule = get_rule_to_add(region)
for exit in region.exits:
add_rule(exit, rule)
for ext in region.exits:
add_rule(ext, rule)
paradox_shop = world.get_region('Light World Death Mountain Shop', player)
if paradox_shop.is_light_world:
add_rule(paradox_shop.entrances[0], get_rule_to_add(paradox_shop))
for ent_name in bunny_impassible_doors:
bunny_exit = world.get_entrance(ent_name, player)
if bunny_exit.parent_region.is_light_world:
add_rule(bunny_exit, get_rule_to_add(bunny_exit.parent_region))
doors_to_check = [x for x in world.doors if x.player == player and x not in bunny_impassible_doors]
doors_to_check = [x for x in doors_to_check if x.type in [DoorType.Normal, DoorType.Interior] and not x.blocked]
for door in doors_to_check:
room = world.get_room(door.roomIndex, player)
if door.entrance.parent_region.is_light_world and room.kind(door) in [DoorKind.Dashable, DoorKind.Bombable, DoorKind.Hidden]:
add_rule(door.entrance, get_rule_to_add(door.entrance.parent_region))
# Add requirements for all locations that are actually in the light world, except those available to the bunny
for location in world.get_locations():
if location.player == player and location.parent_region.is_light_world:
@@ -1460,6 +1477,72 @@ def set_inverted_bunny_rules(world, player):
add_rule(location, get_rule_to_add(location.parent_region))
bunny_impassible_doors = {
'Hyrule Dungeon Armory S', 'Hyrule Dungeon Armory ES', 'Sewers Secret Room Push Block', 'Sewers Pull Switch S',
'Eastern Lobby N', 'Eastern Courtyard Ledge W', 'Eastern Courtyard Ledge E', 'Eastern Pot Switch SE',
'Eastern Map Balcony Hook Path', 'Eastern Stalfos Spawn ES', 'Eastern Stalfos Spawn NW',
'Eastern Hint Tile Push Block', 'Eastern Darkness S', 'Eastern Darkness NE', 'Eastern Darkness Up Stairs',
'Eastern Attic Start WS', 'Eastern Single Eyegore NE', 'Eastern Duo Eyegores NE', 'Desert Main Lobby Left Path',
'Desert Main Lobby Right Path', 'Desert Left Alcove Path', 'Desert Right Alcove Path', 'Desert Compass NW',
'Desert West Lobby NW', 'Desert Back Lobby NW', 'Desert Four Statues NW', 'Desert Four Statues ES',
'Desert Beamos Hall WS', 'Desert Beamos Hall NE', 'Desert Wall Slide NW', 'Hera Lobby Down Stairs',
'Hera Lobby Key Stairs', 'Hera Lobby Up Stairs', 'Hera Tile Room EN', 'Hera Tridorm SE', 'Hera Beetles WS',
'Hera 4F Down Stairs', 'Tower Gold Knights SW', 'Tower Dark Maze EN', 'Tower Dark Pits ES', 'Tower Dark Archers WN',
'Tower Red Spears WN', 'Tower Red Guards EN', 'Tower Red Guards SW', 'Tower Circle of Pots NW', 'Tower Altar NW',
'PoD Left Cage SW', 'PoD Middle Cage SE', 'PoD Pit Room Bomb Hole', 'PoD Pit Room Block Path N',
'PoD Pit Room Block Path S', 'PoD Stalfos Basement Warp', 'PoD Arena Main SW', 'PoD Arena Main Crystal Path',
'PoD Arena Bonk Path', 'PoD Arena Crystal Path', 'PoD Sexy Statue NW', 'PoD Map Balcony Drop Down',
'PoD Mimics 1 NW', 'PoD Warp Hint Warp', 'PoD Falling Bridge Path N', 'PoD Falling Bridge Path S',
'PoD Mimics 2 NW', 'PoD Bow Statue Down Ladder', 'PoD Dark Pegs Up Ladder', 'PoD Dark Pegs WN',
'PoD Turtle Party ES', 'PoD Turtle Party NW', 'PoD Callback Warp', 'Swamp Lobby Moat', 'Swamp Entrance Moat',
'Swamp Trench 1 Approach Swim Depart', 'Swamp Trench 1 Approach Key', 'Swamp Trench 1 Key Approach',
'Swamp Trench 1 Key Ledge Depart', 'Swamp Trench 1 Departure Approach', 'Swamp Trench 1 Departure Key',
'Swamp Hub Hook Path', 'Swamp Compass Donut Push Block',
'Swamp Shortcut Blue Barrier', 'Swamp Trench 2 Pots Blue Barrier', 'Swamp Trench 2 Pots Wet',
'Swamp Trench 2 Departure Wet', 'Swamp West Shallows Push Blocks', 'Swamp West Ledge Hook Path',
'Swamp Barrier Ledge Hook Path', 'Swamp Attic Left Pit', 'Swamp Attic Right Pit', 'Swamp Push Statue NW',
'Swamp Push Statue NE', 'Swamp Drain Right Switch', 'Swamp Waterway NE', 'Swamp Waterway N', 'Swamp Waterway NW',
'Skull Pot Circle WN', 'Skull Pot Circle Star Path', 'Skull Pull Switch S', 'Skull Big Chest N',
'Skull Big Chest Hookpath', 'Skull 2 East Lobby NW', 'Skull Back Drop Star Path', 'Skull 2 West Lobby NW',
'Skull 3 Lobby EN', 'Skull Star Pits SW', 'Skull Star Pits ES', 'Skull Torch Room WN', 'Skull Vines NW',
'Thieves Conveyor Maze EN', 'Thieves Triple Bypass EN', 'Thieves Triple Bypass SE', 'Thieves Triple Bypass WN',
'Thieves Hellway Blue Barrier', 'Thieves Hellway Crystal Blue Barrier', 'Thieves Attic ES',
'Thieves Basement Block Path', 'Thieves Blocked Entry Path', 'Thieves Conveyor Bridge Block Path',
'Thieves Conveyor Block Path', 'Ice Lobby WS', 'Ice Cross Left Push Block', 'Ice Cross Bottom Push Block Left',
'Ice Cross Bottom Push Block Right', 'Ice Cross Right Push Block Top', 'Ice Cross Right Push Block Bottom',
'Ice Cross Top Push Block Bottom', 'Ice Cross Top Push Block Right', 'Ice Bomb Drop Hole', 'Ice Pengator Switch WS',
'Ice Pengator Switch ES', 'Ice Big Key Push Block', 'Ice Stalfos Hint SE', 'Ice Bomb Jump EN',
'Ice Pengator Trap NE', 'Ice Hammer Block ES', 'Ice Tongue Pull WS', 'Ice Freezors Bomb Hole', 'Ice Tall Hint WS',
'Ice Hookshot Ledge Path', 'Ice Hookshot Balcony Path', 'Ice Many Pots SW', 'Ice Many Pots WS',
'Ice Crystal Right Blue Hole', 'Ice Crystal Left Blue Barrier', 'Ice Big Chest Landing Push Blocks',
'Ice Backwards Room Hole', 'Ice Switch Room SE', 'Ice Antechamber NE', 'Ice Antechamber Hole', 'Mire Lobby Gap',
'Mire Post-Gap Gap', 'Mire 2 NE', 'Mire Hub Upper Blue Barrier', 'Mire Hub Lower Blue Barrier',
'Mire Hub Right Blue Barrier', 'Mire Hub Top Blue Barrier', 'Mire Falling Bridge WN',
'Mire Map Spike Side Blue Barrier', 'Mire Map Spot Blue Barrier', 'Mire Crystal Dead End Left Barrier',
'Mire Crystal Dead End Right Barrier', 'Mire Cross ES', 'Mire Hidden Shooters Block Path S',
'Mire Hidden Shooters Block Path N', 'Mire Left Bridge Hook Path', 'Mire Fishbone Blue Barrier',
'Mire South Fish Blue Barrier', 'Mire Tile Room NW', 'Mire Compass Blue Barrier', 'Mire Attic Hint Hole',
'Mire Dark Shooters SW', 'Mire Crystal Mid Blue Barrier', 'Mire Crystal Left Blue Barrier', 'TR Main Lobby Gap',
'TR Lobby Ledge Gap', 'TR Hub SW', 'TR Hub SE', 'TR Hub ES', 'TR Hub EN', 'TR Hub NW', 'TR Hub NE', 'TR Torches NW',
'TR Pokey 2 EN', 'TR Pokey 2 ES', 'TR Twin Pokeys SW', 'TR Twin Pokeys EN', 'TR Big Chest Gap',
'TR Big Chest Entrance Gap', 'TR Lazy Eyes ES', 'TR Tongue Pull WS', 'TR Tongue Pull NE', 'TR Dark Ride Up Stairs',
'TR Dark Ride SW', 'TR Crystal Maze Forwards Path', 'TR Crystal Maze Blue Path', 'TR Crystal Maze Cane Path',
'TR Final Abyss South Stairs', 'TR Final Abyss NW', 'GT Hope Room EN', 'GT Blocked Stairs Block Path',
'GT Bob\'s Room Hole', 'GT Speed Torch SE', 'GT Speed Torch South Path', 'GT Speed Torch North Path',
'GT Crystal Conveyor NE', 'GT Crystal Conveyor WN', 'GT Conveyor Cross EN', 'GT Conveyor Cross WN',
'GT Hookshot East-North Path', 'GT Hookshot East-South Path', 'GT Hookshot North-East Path',
'GT Hookshot North-South Path', 'GT Hookshot South-East Path', 'GT Hookshot South-North Path',
'GT Hookshot Platform Blue Barrier', 'GT Hookshot Entry Blue Barrier', 'GT Double Switch Blue Path',
'GT Double Switch Key Blue Path', 'GT Double Switch Blue Barrier', 'GT Double Switch Transition Blue',
'GT Firesnake Room Hook Path', 'GT Falling Bridge WN', 'GT Falling Bridge WS', 'GT Ice Armos NE', 'GT Ice Armos WS',
'GT Crystal Paths SW', 'GT Mimics 1 NW', 'GT Mimics 1 ES', 'GT Mimics 2 WS', 'GT Mimics 2 NE',
'GT Hidden Spikes EN', 'GT Cannonball Bridge SE', 'GT Gauntlet 1 WN', 'GT Gauntlet 2 EN', 'GT Gauntlet 2 SW',
'GT Gauntlet 3 NW', 'GT Gauntlet 3 SW', 'GT Gauntlet 4 NW', 'GT Gauntlet 4 SW', 'GT Gauntlet 5 NW',
'GT Gauntlet 5 WS', 'GT Lanmolas 2 ES', 'GT Lanmolas 2 NW', 'GT Wizzrobes 1 SW', 'GT Wizzrobes 2 SE',
'GT Wizzrobes 2 NE', 'GT Torch Cross ES', 'GT Falling Torches NE', 'GT Moldorm Gap', 'GT Validation Block Path'
}
def add_key_logic_rules(world, player):
key_logic = world.key_logic[player]
for d_name, d_logic in key_logic.items():