This commit is contained in:
compiling
2021-04-21 18:40:54 +10:00
parent 30baec65af
commit 9852352027
6 changed files with 87 additions and 51 deletions

View File

@@ -111,7 +111,7 @@ class World(object):
set_player_attr('can_access_trock_front', None) set_player_attr('can_access_trock_front', None)
set_player_attr('can_access_trock_big_chest', None) set_player_attr('can_access_trock_big_chest', None)
set_player_attr('can_access_trock_middle', None) set_player_attr('can_access_trock_middle', None)
set_player_attr('fix_fake_world', logic not in ['owglitches', 'nologic'] or shuffle in ['crossed', 'insanity', 'madness_legacy']) set_player_attr('fix_fake_world', logic[player] not in ['owglitches', 'nologic'] or shuffle[player] in ['crossed', 'insanity', 'madness_legacy'])
set_player_attr('mapshuffle', False) set_player_attr('mapshuffle', False)
set_player_attr('compassshuffle', False) set_player_attr('compassshuffle', False)
set_player_attr('keyshuffle', False) set_player_attr('keyshuffle', False)
@@ -2216,7 +2216,7 @@ er_mode = {"vanilla": 0, "simple": 1, "restricted": 2, "full": 3, "crossed": 4,
"full_legacy": 9, "madness_legacy": 10, "insanity_legacy": 11, "dungeonsfull": 7, "dungeonssimple": 6} "full_legacy": 9, "madness_legacy": 10, "insanity_legacy": 11, "dungeonsfull": 7, "dungeonssimple": 6}
# byte 1: LLLW WSSR (logic, mode, sword, retro) # byte 1: LLLW WSSR (logic, mode, sword, retro)
logic_mode = {"noglitches": 0, "minorglitches": 1, "nologic": 2, "owg": 3, "majorglitches": 4} logic_mode = {"noglitches": 0, "minorglitches": 1, "nologic": 2, "owglitches": 3, "majorglitches": 4}
world_mode = {"open": 0, "standard": 1, "inverted": 2} world_mode = {"open": 0, "standard": 1, "inverted": 2}
sword_mode = {"random": 0, "assured": 1, "swordless": 2, "vanilla": 3} sword_mode = {"random": 0, "assured": 1, "swordless": 2, "vanilla": 3}

View File

@@ -1943,7 +1943,7 @@ def connect_mandatory_exits(world, entrances, caves, must_be_exits, player):
invalid_connections = Must_Exit_Invalid_Connections.copy() invalid_connections = Must_Exit_Invalid_Connections.copy()
invalid_cave_connections = defaultdict(set) invalid_cave_connections = defaultdict(set)
if world.logic in ['owglitches', 'nologic']: if world.logic[player] in ['owglitches', 'nologic']:
import OverworldGlitchRules import OverworldGlitchRules
for entrance in OverworldGlitchRules.get_non_mandatory_exits(world.mode == 'inverted'): for entrance in OverworldGlitchRules.get_non_mandatory_exits(world.mode == 'inverted'):
invalid_connections[entrance] = set() invalid_connections[entrance] = set()

View File

@@ -254,7 +254,7 @@ def generate_itempool(world, player):
(pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) = make_custom_item_pool(world.progressive, world.shuffle[player], world.difficulty[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.retro[player], world.customitemarray) (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) = make_custom_item_pool(world.progressive, world.shuffle[player], world.difficulty[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.retro[player], world.customitemarray)
world.rupoor_cost = min(world.customitemarray[player]["rupoorcost"], 9999) world.rupoor_cost = min(world.customitemarray[player]["rupoorcost"], 9999)
else: else:
(pool, placed_items, precollected_items, clock_mode, lamps_needed_for_dark_rooms) = get_pool_core(world.progressive, world.shuffle[player], world.difficulty[player], world.treasure_hunt_total[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.retro[player], world.doorShuffle[player]) (pool, placed_items, precollected_items, clock_mode, lamps_needed_for_dark_rooms) = get_pool_core(world.progressive, world.shuffle[player], world.difficulty[player], world.treasure_hunt_total[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.retro[player], world.doorShuffle[player], world.logic[player])
if player in world.pool_adjustment.keys(): if player in world.pool_adjustment.keys():
amt = world.pool_adjustment[player] amt = world.pool_adjustment[player]
@@ -622,7 +622,7 @@ shop_transfer = {'Red Potion': 'Rupees (50)', 'Bee': 'Rupees (5)', 'Blue Potion'
} }
def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer, goal, mode, swords, retro, door_shuffle): def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer, goal, mode, swords, retro, door_shuffle, logic):
pool = [] pool = []
placed_items = {} placed_items = {}
precollected_items = [] precollected_items = []
@@ -877,9 +877,10 @@ def test():
for swords in ['random', 'assured', 'swordless', 'vanilla']: for swords in ['random', 'assured', 'swordless', 'vanilla']:
for progressive in ['on', 'off']: for progressive in ['on', 'off']:
for shuffle in ['full', 'insanity_legacy']: for shuffle in ['full', 'insanity_legacy']:
for logic in ['noglitches', 'minorglitches', 'owglitches', 'nologic']:
for retro in [True, False]: for retro in [True, False]:
for door_shuffle in ['basic', 'crossed', 'vanilla']: for door_shuffle in ['basic', 'crossed', 'vanilla']:
out = get_pool_core(progressive, shuffle, difficulty, timer, goal, mode, swords, retro, door_shuffle) out = get_pool_core(progressive, shuffle, difficulty, 30, timer, goal, mode, swords, retro, door_shuffle, logic)
count = len(out[0]) + len(out[1]) count = len(out[0]) + len(out[1])
correct_count = total_items_to_place correct_count = total_items_to_place

View File

@@ -18,7 +18,7 @@ invalid_key_rooms = {
} }
vanilla_pots = { vanilla_pots = {
2: [Pot(80, 6, PotItem.Nothing, 'Sewers Yet More Rats'), Pot(80, 8, PotItem.Nothing, 'Sewers Yet More Rats'), Pot(44, 8, PotItem.Nothing, 'Sewers Yet More Rats'), Pot(44, 10, PotItem.Nothing, 'Sewers Yet More Rats')], 2: [Pot(80, 6, PotItem.Nothing, '`Sewers Yet More Rats`'), Pot(80, 8, PotItem.Nothing, 'Sewers Yet More Rats'), Pot(44, 8, PotItem.Nothing, 'Sewers Yet More Rats'), Pot(44, 10, PotItem.Nothing, 'Sewers Yet More Rats')],
4: [Pot(162, 25, PotItem.Nothing, 'TR Dash Room'), Pot(152, 25, PotItem.Nothing, 'TR Dash Room'), Pot(152, 22, PotItem.Nothing, 'TR Dash Room'), Pot(162, 22, PotItem.Nothing, 'TR Dash Room'), Pot(204, 19, PotItem.Bomb, 'TR Tongue Pull'), 4: [Pot(162, 25, PotItem.Nothing, 'TR Dash Room'), Pot(152, 25, PotItem.Nothing, 'TR Dash Room'), Pot(152, 22, PotItem.Nothing, 'TR Dash Room'), Pot(162, 22, PotItem.Nothing, 'TR Dash Room'), Pot(204, 19, PotItem.Bomb, 'TR Tongue Pull'),
Pot(240, 19, PotItem.Bomb, 'TR Tongue Pull')], Pot(240, 19, PotItem.Bomb, 'TR Tongue Pull')],
9: [Pot(12, 4, PotItem.OneRupee, 'PoD Shooter Room'), Pot(48, 4, PotItem.Heart, 'PoD Shooter Room'), Pot(12, 12, PotItem.Switch, 'PoD Shooter Room')], 9: [Pot(12, 4, PotItem.OneRupee, 'PoD Shooter Room'), Pot(48, 4, PotItem.Heart, 'PoD Shooter Room'), Pot(12, 12, PotItem.Switch, 'PoD Shooter Room')],

View File

@@ -1,3 +1,4 @@
import collections
import logging import logging
from collections import deque from collections import deque
@@ -35,7 +36,7 @@ def set_rules(world, player):
no_glitches_rules(world, player) no_glitches_rules(world, player)
elif world.logic[player] == 'minorglitches': elif world.logic[player] == 'minorglitches':
logging.getLogger('').info('Minor Glitches may be buggy still. No guarantee for proper logic checks.') logging.getLogger('').info('Minor Glitches may be buggy still. No guarantee for proper logic checks.')
elif world.logic == 'owglitches': elif world.logic[player] == 'owglitches':
logging.getLogger('').info('There is a chance OWG has bugged edge case rulesets, especially in inverted. Definitely file a report on GitHub if you see anything strange.') logging.getLogger('').info('There is a chance OWG has bugged edge case rulesets, especially in inverted. Definitely file a report on GitHub if you see anything strange.')
# Initially setting no_glitches_rules to set the baseline rules for some # Initially setting no_glitches_rules to set the baseline rules for some
# entrances. The overworld_glitches_rules set is primarily additive. # entrances. The overworld_glitches_rules set is primarily additive.
@@ -56,7 +57,7 @@ def set_rules(world, player):
if world.mode[player] != 'inverted': if world.mode[player] != 'inverted':
set_big_bomb_rules(world, player) set_big_bomb_rules(world, player)
if world.logic == 'owglitches' and world.shuffle not in ('insanity', 'insanity_legacy'): if world.logic[player] == 'owglitches' and world.shuffle[player] not in ('insanity', 'insanity_legacy'):
path_to_courtyard = mirrorless_path_to_castle_courtyard(world, player) path_to_courtyard = mirrorless_path_to_castle_courtyard(world, player)
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.world.get_entrance('Dark Death Mountain Offset Mirror', player).can_reach(state) and all(rule(state) for rule in path_to_courtyard), 'or') add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.world.get_entrance('Dark Death Mountain Offset Mirror', player).can_reach(state) and all(rule(state) for rule in path_to_courtyard), 'or')
else: else:
@@ -66,15 +67,9 @@ def set_rules(world, player):
if not world.swamp_patch_required[player]: if not world.swamp_patch_required[player]:
add_rule(world.get_entrance('Swamp Lobby Moat', player), lambda state: state.has_Mirror(player)) add_rule(world.get_entrance('Swamp Lobby Moat', player), lambda state: state.has_Mirror(player))
if world.mode[player] != 'inverted': set_bunny_rules(world, player, world.mode[player] == 'inverted')
set_bunny_rules(world, player)
else:
set_inverted_bunny_rules(world, player)
set_trock_key_rules(world, player) if world.mode[player] != 'inverted' and world.logic[player] == 'owglitches':
set_rule(ganons_tower, lambda state: state.has_crystals(world.crystals_needed_for_gt, player))
if world.mode != 'inverted' and world.logic == 'owglitches':
add_rule(world.get_entrance('Ganons Tower', player), lambda state: state.world.get_entrance('Ganons Tower Ascent', player).can_reach(state), 'or') add_rule(world.get_entrance('Ganons Tower', player), lambda state: state.world.get_entrance('Ganons Tower Ascent', player).can_reach(state), 'or')
set_bunny_rules(world, player, world.mode == 'inverted') set_bunny_rules(world, player, world.mode == 'inverted')
@@ -1475,20 +1470,21 @@ def set_bunny_rules(world, player, inverted):
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 == 'owglitches': if world.logic[player] == 'owglitches':
# TODO: Fix dungeon revive logic for door rando if region.type != RegionType.Dungeon \
if region.name == 'Swamp Palace (Entrance)': and (((location is None or location.name not in OverworldGlitchRules.get_superbunny_accessible_locations())
return lambda state: state.has_Pearl(player)
if region.name == 'Tower of Hera (Bottom)': # Need to hit the crystal switch
return lambda state: state.has_Mirror(player) and state.has_sword(player) or state.has_Pearl(player)
if region.name in OverworldGlitchRules.get_invalid_bunny_revival_dungeons():
return lambda state: state.has_Mirror(player) or state.has_Pearl(player)
if region.type == RegionType.Dungeon:
return lambda state: True
if (((location is None or location.name not in OverworldGlitchRules.get_superbunny_accessible_locations())
or (connecting_entrance is not None and connecting_entrance.name in OverworldGlitchRules.get_invalid_bunny_revival_dungeons())) or (connecting_entrance is not None and connecting_entrance.name in OverworldGlitchRules.get_invalid_bunny_revival_dungeons()))
and not is_link(region)): and not is_link(region)):
return lambda state: state.has_Pearl(player) return lambda state: state.has_Pearl(player)
# TODO: Fix dungeon revive logic for door rando
# if region.name == 'Swamp Palace (Entrance)':
# return lambda state: state.has_Pearl(player)
# if region.name == 'Tower of Hera (Bottom)': # Need to hit the crystal switch
# return lambda state: state.has_Mirror(player) and state.has_sword(player) or state.has_Pearl(player)
# if region.name in OverworldGlitchRules.get_invalid_bunny_revival_dungeons():
# return lambda state: state.has_Mirror(player) or state.has_Pearl(player)
# if region.type == RegionType.Dungeon:
# return lambda state: True
else: else:
if not is_link(region): if not is_link(region):
return lambda state: state.has_Pearl(player) return lambda state: state.has_Pearl(player)
@@ -1500,12 +1496,12 @@ def set_bunny_rules(world, player, inverted):
possible_options = [lambda state: state.has_Pearl(player)] possible_options = [lambda state: state.has_Pearl(player)]
# We will search entrances recursively until we find # We will search entrances recursively until we find
# one that leads to an exclusively dark world region # one that leads to an exclusively light world region
# 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 = {start_region} seen = {region}
queue = deque([(start_region, [])]) queue = deque([(region, [])])
while queue: while queue:
(current, path) = queue.popleft() (current, path) = queue.popleft()
for entrance in current.entrances: for entrance in current.entrances:
@@ -1516,7 +1512,7 @@ def set_bunny_rules(world, player, inverted):
seen.add(new_region) seen.add(new_region)
if not is_link(new_region): if not is_link(new_region):
# For OWG, establish superbunny and revival rules. # For OWG, establish superbunny and revival rules.
if world.logic == 'owglitches' and entrance.name not in OverworldGlitchRules.get_invalid_bunny_revival_dungeons(): if world.logic[player] == 'owglitches' and entrance.name not in OverworldGlitchRules.get_invalid_bunny_revival_dungeons():
if region.name in OverworldGlitchRules.get_sword_required_superbunny_mirror_regions(): if region.name in OverworldGlitchRules.get_sword_required_superbunny_mirror_regions():
possible_options.append(lambda state: path_to_access_rule(new_path, entrance) and state.has_Mirror(player) and state.has_sword(player)) possible_options.append(lambda state: path_to_access_rule(new_path, entrance) and state.has_Mirror(player) and state.has_sword(player))
elif (region.name in OverworldGlitchRules.get_boots_required_superbunny_mirror_regions() elif (region.name in OverworldGlitchRules.get_boots_required_superbunny_mirror_regions()
@@ -1534,7 +1530,7 @@ def set_bunny_rules(world, player, inverted):
if is_bunny(new_region): if is_bunny(new_region):
queue.append((new_region, new_path)) queue.append((new_region, new_path))
else: else:
# we have reached pure dark 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))
return options_to_access_rule(possible_options) return options_to_access_rule(possible_options)
@@ -1553,7 +1549,7 @@ def set_bunny_rules(world, player, inverted):
for ent_name in bunny_impassible_doors: for ent_name in bunny_impassible_doors:
bunny_exit = world.get_entrance(ent_name, player) bunny_exit = world.get_entrance(ent_name, player)
if bunny_exit.parent_region.is_light_world: if is_bunny(bunny_exit.parent_region):
add_rule(bunny_exit, get_rule_to_add(bunny_exit.parent_region)) 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 world.doors if x.player == player and x not in bunny_impassible_doors]
@@ -1566,7 +1562,7 @@ def set_bunny_rules(world, player, inverted):
# Add requirements for all locations that are actually in the dark world, except those available to the bunny, including dungeon revival # Add requirements for all locations that are actually in the dark world, except those available to the bunny, including dungeon revival
for entrance in world.get_entrances(): for entrance in world.get_entrances():
if entrance.player == player and is_bunny(entrance.connected_region): if entrance.player == player and is_bunny(entrance.connected_region):
if world.logic == 'owglitches': if world.logic[player] == 'owglitches':
if entrance.connected_region.type == RegionType.Dungeon: if entrance.connected_region.type == RegionType.Dungeon:
if entrance.parent_region.type != RegionType.Dungeon and entrance.connected_region.name in OverworldGlitchRules.get_invalid_bunny_revival_dungeons(): if entrance.parent_region.type != RegionType.Dungeon and entrance.connected_region.name in OverworldGlitchRules.get_invalid_bunny_revival_dungeons():
add_rule(entrance, get_rule_to_add(entrance.connected_region, None, entrance)) add_rule(entrance, get_rule_to_add(entrance.connected_region, None, entrance))
@@ -1574,12 +1570,50 @@ def set_bunny_rules(world, player, inverted):
if entrance.connected_region.name == 'Turtle Rock (Entrance)': if entrance.connected_region.name == 'Turtle Rock (Entrance)':
add_rule(world.get_entrance('Turtle Rock Entrance Gap', player), get_rule_to_add(entrance.connected_region, None, entrance)) add_rule(world.get_entrance('Turtle Rock Entrance Gap', player), get_rule_to_add(entrance.connected_region, None, entrance))
for location in entrance.connected_region.locations: for location in entrance.connected_region.locations:
if world.logic == 'owglitches' and entrance.name in OverworldGlitchRules.get_invalid_mirror_bunny_entrances(): if world.logic[player] == 'owglitches' and entrance.name in OverworldGlitchRules.get_invalid_mirror_bunny_entrances():
continue continue
if location.name in bunny_accessible_locations: if location.name in bunny_accessible_locations:
continue continue
add_rule(location, get_rule_to_add(entrance.connected_region, location)) add_rule(location, get_rule_to_add(entrance.connected_region, location))
bunny_revivable_entrances = {
"Sewers Pull Switch", "TR Dash Room", "Swamp Boss", "Hera Boss",
"Tower Agahnim 1", "Ice Lobby", "Sewers Rat Path", "PoD Falling Bridge",
"PoD Harmless Hellway", "PoD Mimics 2", "Ice Cross Bottom", "GT Agahnim 2",
"Sewers Water", "TR Lazy Eyes", "TR Big Chest", "Swamp Push Statue",
"PoD Arena Main", "PoD Arena Bridge", "PoD Map Balcony", "Sewers Dark Cross",
"Desert Boss", "Swamp Hub", "Skull Spike Corner", "PoD Pit Room",
"PoD Conveyor", "GT Crystal Circles", "Sewers Behind Tapestry",
"Desert Tiles 2", "Skull Star Pits", "Hyrule Castle West Hall",
"Hyrule Castle Throne Room", "Hyrule Castle East Hall", "Skull 2 West Lobby",
"Skull 2 East Lobby", "Skull Pot Prison", "Skull 1 Lobby", "Skull Map Room",
"Skull 3 Lobby", "PoD Boss", "GT Hidden Spikes", "GT Gauntlet 3",
"Ice Spike Cross", "Hyrule Castle West Lobby", "Hyrule Castle Lobby",
"Hyrule Castle East Lobby", "Desert Back Lobby", "Hyrule Dungeon Armory Main",
"Hyrule Dungeon North Abyss", "Desert Sandworm Corner", "Desert Dead End",
"Desert North Hall", "Desert Arrow Pot Corner", "GT DMs Room",
"GT Petting Zoo", "Ice Tall Hint", "Desert West Lobby", "Desert Main Lobby",
"Desert East Lobby", "GT Big Chest", "GT Bob\'s Room", "GT Speed Torch",
"Mire Boss", "GT Conveyor Bridge", "Mire Lobby", "Eastern Darkness",
"Ice Many Pots", "Mire South Fish", "Mire Right Bridge", "Mire Left Bridge",
"TR Boss", "Eastern Hint Tile Blocked Path", "Thieves Spike Switch",
"Thieves Boss", "Mire Spike Barrier", "Mire Cross", "Mire Hidden Shooters",
"Mire Spikes", "TR Final Abyss", "TR Dark Ride", "TR Pokey 1", "TR Tile Room",
"TR Roller Room", "Eastern Cannonball", "Thieves Hallway", "Ice Switch Room",
"Mire Tile Room", "Mire Conveyor Crystal", "Mire Hub", "TR Dash Bridge",
"TR Hub", "Eastern Boss", "Eastern Lobby", "Thieves Ambush",
"Thieves BK Corner", "TR Eye Bridge", "Thieves Lobby", "Tower Lobby",
}
# Revive as superbunny or use superbunny to get the item in a dead end
superbunny_revivable_entrances = {
"TR Main Lobby", "Sanctuary", "Thieves Pot Alcove Bottom"
}
superbunny_sword_revivable_entrances = {
"Hera Lobby"
}
bunny_impassible_doors = { bunny_impassible_doors = {
'Hyrule Dungeon Armory S', 'Hyrule Dungeon Armory ES', 'Sewers Secret Room Push Block', 'Sewers Pull Switch S', '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 Lobby N', 'Eastern Courtyard Ledge W', 'Eastern Courtyard Ledge E', 'Eastern Pot Switch SE',

View File

@@ -17,6 +17,7 @@
"choices": [ "choices": [
"noglitches", "noglitches",
"minorglitches", "minorglitches",
"owglitches",
"nologic" "nologic"
] ]
}, },