Fix minimal accessibility failures (#726)

This commit is contained in:
Alchav 2022-09-29 13:59:57 -04:00 committed by GitHub
parent e6a4925f0c
commit 885c8d3fcc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 4 deletions

View File

@ -531,7 +531,7 @@ class MultiWorld():
beatable_fulfilled = False
def location_conditition(location: Location):
def location_condition(location: Location):
"""Determine if this location has to be accessible, location is already filtered by location_relevant"""
if location.player in players["minimal"]:
return False
@ -548,7 +548,7 @@ class MultiWorld():
def all_done():
"""Check if all access rules are fulfilled"""
if beatable_fulfilled:
if any(location_conditition(location) for location in locations):
if any(location_condition(location) for location in locations):
return False # still locations required to be collected
return True

44
Fill.py
View File

@ -4,9 +4,10 @@ import collections
import itertools
from collections import Counter, deque
from BaseClasses import CollectionState, Location, LocationProgressType, MultiWorld, Item
from BaseClasses import CollectionState, Location, LocationProgressType, MultiWorld, Item, ItemClassification
from worlds.AutoWorld import call_all
from worlds.generic.Rules import add_item_rule
class FillError(RuntimeError):
@ -209,6 +210,34 @@ def fast_fill(world: MultiWorld,
return item_pool[placing:], fill_locations[placing:]
def accessibility_corrections(world: MultiWorld, state: CollectionState, locations, pool=[]):
maximum_exploration_state = sweep_from_pool(state, pool)
minimal_players = {player for player in world.player_ids if world.accessibility[player] == "minimal"}
unreachable_locations = [location for location in world.get_locations() if location.player in minimal_players and
not location.can_reach(maximum_exploration_state)]
for location in unreachable_locations:
if (location.item is not None and location.item.advancement and location.address is not None and not
location.locked and location.item.player not in minimal_players):
pool.append(location.item)
state.remove(location.item)
location.item = None
location.event = False
if location in state.events:
state.events.remove(location)
locations.append(location)
if pool:
fill_restrictive(world, state, locations, pool)
def inaccessible_location_rules(world: MultiWorld, state: CollectionState, locations):
maximum_exploration_state = sweep_from_pool(state, [])
unreachable_locations = [location for location in locations if not location.can_reach(maximum_exploration_state)]
for location in unreachable_locations:
add_item_rule(location, lambda item: not ((item.classification & 0b0011) and
world.accessibility[item.player] != 'minimal'))
def distribute_items_restrictive(world: MultiWorld) -> None:
fill_locations = sorted(world.get_unfilled_locations())
world.random.shuffle(fill_locations)
@ -239,7 +268,15 @@ def distribute_items_restrictive(world: MultiWorld) -> None:
defaultlocations = locations[LocationProgressType.DEFAULT]
excludedlocations = locations[LocationProgressType.EXCLUDED]
fill_restrictive(world, world.state, prioritylocations, progitempool, lock=True)
prioritylocations_lock = prioritylocations.copy()
fill_restrictive(world, world.state, prioritylocations, progitempool)
accessibility_corrections(world, world.state, prioritylocations, progitempool)
for location in prioritylocations_lock:
if location.item:
location.locked = True
if prioritylocations:
defaultlocations = prioritylocations + defaultlocations
@ -248,6 +285,9 @@ def distribute_items_restrictive(world: MultiWorld) -> None:
if progitempool:
raise FillError(
f'Not enough locations for progress items. There are {len(progitempool)} more items than locations')
accessibility_corrections(world, world.state, defaultlocations)
inaccessible_location_rules(world, world.state, defaultlocations)
remaining_fill(world, excludedlocations, filleritempool)
if excludedlocations: