Add logic for including nologic seeds in multiworlds (overworld glitch rules)
nologic seeds are generated as beatable only with no progression balancing, where it is assumed the player can always win no matter where items are placed. Add superbunny and dungeon revival to minor glitch ruleset.
This commit is contained in:
parent
ec49fa026b
commit
1594d82fb2
|
@ -372,7 +372,7 @@ class World(object):
|
|||
|
||||
def has_beaten_game(self, state, player: Union[None, int] = None):
|
||||
if player:
|
||||
return state.has('Triforce', player)
|
||||
return state.has('Triforce', player) or state.world.logic[player] == 'nologic'
|
||||
else:
|
||||
return all((self.has_beaten_game(state, p) for p in range(1, self.players + 1)))
|
||||
|
||||
|
@ -953,8 +953,7 @@ class Location(object):
|
|||
self.player = player
|
||||
|
||||
def can_fill(self, state: CollectionState, item: Item, check_access=True) -> bool:
|
||||
return self.always_allow(state, item) or (self.parent_region.can_fill(item) and self.item_rule(item) and (
|
||||
not check_access or self.can_reach(state)))
|
||||
return self.parent_region.can_fill(item) and (not check_access or self.always_allow(state, item) or (self.item_rule(item) and self.can_reach(state)))
|
||||
|
||||
def can_reach(self, state: CollectionState) -> bool:
|
||||
if self.parent_region.can_reach(state) and self.access_rule(state):
|
||||
|
|
39
Rules.py
39
Rules.py
|
@ -11,13 +11,16 @@ def set_rules(world, player):
|
|||
if world.logic[player] == 'nologic':
|
||||
logging.getLogger('').info(
|
||||
'WARNING! Seeds generated under this logic often require major glitches and may be impossible!')
|
||||
if world.players == 1:
|
||||
world.get_region('Menu', player).can_reach_private = lambda state: True
|
||||
no_logic_rules(world, player)
|
||||
for exit in world.get_region('Menu', player).exits:
|
||||
exit.hide_path = True
|
||||
return
|
||||
|
||||
crossover_logic(world, player)
|
||||
else:
|
||||
# Set access rules according to max glitches for multiworld progression. Set accessibility to none, and shuffle assuming the no logic players can always win
|
||||
world.accessibility[player] = 'none'
|
||||
world.progression_balancing[player] = False
|
||||
|
||||
global_rules(world, player)
|
||||
|
||||
|
@ -36,7 +39,7 @@ def set_rules(world, player):
|
|||
|
||||
if world.logic[player] == 'noglitches':
|
||||
no_glitches_rules(world, player)
|
||||
elif world.logic[player] == 'owglitches':
|
||||
elif world.logic[player] in ['owglitches', 'nologic']:
|
||||
# Initially setting no_glitches_rules to set the baseline rules for some
|
||||
# entrances. The overworld_glitches_rules set is primarily additive.
|
||||
no_glitches_rules(world, player)
|
||||
|
@ -57,7 +60,7 @@ def set_rules(world, player):
|
|||
|
||||
if world.mode[player] != 'inverted':
|
||||
set_big_bomb_rules(world, player)
|
||||
if world.logic[player] == 'owglitches' and world.shuffle not in ('insanity', 'insanity_legacy'):
|
||||
if world.logic[player] in ['owglitches', 'nologic'] and world.shuffle not in ('insanity', 'insanity_legacy'):
|
||||
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')
|
||||
else:
|
||||
|
@ -69,13 +72,13 @@ def set_rules(world, player):
|
|||
|
||||
# GT Entrance may be required for Turtle Rock for OWG and < 7 required
|
||||
ganons_tower = world.get_entrance('Inverted Ganons Tower' if world.mode[player] == 'inverted' else 'Ganons Tower', player)
|
||||
if world.crystals_needed_for_gt[player] == 7 and not (world.logic[player] == 'owglitches' and world.mode[player] != 'inverted'):
|
||||
if world.crystals_needed_for_gt[player] == 7 and not (world.logic[player] in ['owglitches', 'nologic'] and world.mode[player] != 'inverted'):
|
||||
set_rule(ganons_tower, lambda state: False)
|
||||
|
||||
set_trock_key_rules(world, player)
|
||||
|
||||
set_rule(ganons_tower, lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player))
|
||||
if world.mode[player] != 'inverted' and world.logic[player] == 'owglitches':
|
||||
if world.mode[player] != 'inverted' and world.logic[player] in ['owglitches', 'nologic']:
|
||||
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[player] == 'inverted')
|
||||
|
@ -162,18 +165,6 @@ non_crossover_items = (item_name_groups["Small Keys"] | item_name_groups["Big Ke
|
|||
"Small Key (Universal)"}
|
||||
|
||||
|
||||
def crossover_logic(world, player):
|
||||
""" Simple and not graceful solution to logic loops if you mix no logic and logic.
|
||||
Making it so that logical progression cannot be placed in no logic worlds."""
|
||||
no_logic_players = set()
|
||||
for other_player in world.player_ids:
|
||||
if world.logic[other_player] == 'nologic':
|
||||
no_logic_players.add(other_player)
|
||||
if no_logic_players:
|
||||
for location in world.get_locations():
|
||||
if location.player in no_logic_players:
|
||||
forbid_items(location, non_crossover_items, player)
|
||||
|
||||
def global_rules(world, player):
|
||||
# ganon can only carry triforce
|
||||
add_item_rule(world.get_location('Ganon', player), lambda item: item.name == 'Triforce' and item.player == player)
|
||||
|
@ -1407,8 +1398,8 @@ def set_bunny_rules(world: World, player: int, inverted: bool):
|
|||
def get_rule_to_add(region, location = None, connecting_entrance = None):
|
||||
# In OWG, a location can potentially be superbunny-mirror accessible or
|
||||
# bunny revival accessible.
|
||||
if world.logic[player] == 'owglitches':
|
||||
if region.name == 'Swamp Palace (Entrance)':
|
||||
if world.logic[player] in ['minorglitches', 'owglitches', 'nologic']:
|
||||
if region.name == 'Swamp Palace (Entrance)': # Need to 0hp revive - not in logic
|
||||
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)
|
||||
|
@ -1446,8 +1437,8 @@ def set_bunny_rules(world: World, player: int, inverted: bool):
|
|||
new_path = path + [entrance.access_rule]
|
||||
seen.add(new_region)
|
||||
if not is_link(new_region):
|
||||
# For OWG, establish superbunny and revival rules.
|
||||
if world.logic[player] == 'owglitches' and entrance.name not in OverworldGlitchRules.get_invalid_bunny_revival_dungeons():
|
||||
# For glitch rulesets, establish superbunny and revival rules.
|
||||
if world.logic[player] in ['minorglitches', 'owglitches', 'nologic'] and entrance.name not in OverworldGlitchRules.get_invalid_bunny_revival_dungeons():
|
||||
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))
|
||||
elif (region.name in OverworldGlitchRules.get_boots_required_superbunny_mirror_regions()
|
||||
|
@ -1485,7 +1476,7 @@ def set_bunny_rules(world: World, player: int, inverted: bool):
|
|||
# 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():
|
||||
if entrance.player == player and is_bunny(entrance.connected_region):
|
||||
if world.logic[player] == 'owglitches':
|
||||
if world.logic[player] in ['minorglitches', 'owglitches', 'nologic'] :
|
||||
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():
|
||||
add_rule(entrance, get_rule_to_add(entrance.connected_region, None, entrance))
|
||||
|
@ -1493,7 +1484,7 @@ def set_bunny_rules(world: World, player: int, inverted: bool):
|
|||
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))
|
||||
for location in entrance.connected_region.locations:
|
||||
if world.logic[player] == 'owglitches' and entrance.name in OverworldGlitchRules.get_invalid_mirror_bunny_entrances():
|
||||
if world.logic[player] in ['minorglitches', 'owglitches', 'nologic'] and entrance.name in OverworldGlitchRules.get_invalid_mirror_bunny_entrances():
|
||||
continue
|
||||
if location.name in bunny_accessible_locations:
|
||||
continue
|
||||
|
|
Loading…
Reference in New Issue