From e38516f2436cb7c403da86d6d588b75644c8cdcf Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Sat, 14 Feb 2026 13:42:36 -0500 Subject: Refactored access reqs --- apworld/locations.py | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) (limited to 'apworld/locations.py') diff --git a/apworld/locations.py b/apworld/locations.py index 174a0dd..c92215e 100644 --- a/apworld/locations.py +++ b/apworld/locations.py @@ -1,7 +1,12 @@ from enum import Enum +from typing import TYPE_CHECKING -from BaseClasses import Location, Item +from BaseClasses import Location, Item, Region, CollectionState, Entrance from .items import Lingo2Item +from .rules import AccessRequirements + +if TYPE_CHECKING: + from . import Lingo2World class LetterPlacementType(Enum): @@ -10,13 +15,59 @@ class LetterPlacementType(Enum): FORCE = 2 +def get_required_regions(reqs: AccessRequirements, world: "Lingo2World", + regions: dict[str, Region] | None) -> list[Region]: + # Replace required rooms with regions for the top level requirement, which saves looking up the regions during rule + # checking. + if regions is not None: + return [regions[room_name] for room_name in reqs.rooms] + else: + return [world.multiworld.get_region(room_name, world.player) for room_name in reqs.rooms] + + class Lingo2Location(Location): game: str = "Lingo 2" + reqs: AccessRequirements | None + world: "Lingo2World" + required_regions: list[Region] + port_id: int goal: bool letter_placement_type: LetterPlacementType + @classmethod + def non_event_location(cls, world: "Lingo2World", code: int, region: Region): + result = cls(world.player, world.static_logic.location_id_to_name[code], code, region) + result.reqs = None + result.world = world + result.required_regions = [] + + return result + + @classmethod + def event_location(cls, world: "Lingo2World", name: str, region: Region): + result = cls(world.player, name, None, region) + result.reqs = None + result.world = world + result.required_regions = [] + + return result + + def set_access_rule(self, reqs: AccessRequirements, regions: dict[str, Region] | None): + self.reqs = reqs + self.required_regions = get_required_regions(reqs, self.world, regions) + self.access_rule = self._l2_access_rule + + def _l2_access_rule(self, state: CollectionState) -> bool: + if self.reqs is not None and not self.reqs.check_access(state, self.world): + return False + + if not all(state.can_reach(region) for region in self.required_regions): + return False + + return True + def set_up_letter_rule(self, lpt: LetterPlacementType): self.letter_placement_type = lpt self.item_rule = self._l2_item_rule @@ -31,3 +82,31 @@ class Lingo2Location(Location): return not item.is_letter return True + + +class Lingo2Entrance(Entrance): + reqs: AccessRequirements | None + world: "Lingo2World" + required_regions: list[Region] + + def __init__(self, world: "Lingo2World", description: str, region: Region): + super().__init__(world.player, description, region) + + self.reqs = None + self.world = world + self.required_regions = [] + + def set_access_rule(self, reqs: AccessRequirements, regions: dict[str, Region] | None): + self.reqs = reqs + self.required_regions = get_required_regions(reqs, self.world, regions) + self.access_rule = self._l2_access_rule + + def _l2_access_rule(self, state: CollectionState) -> bool: + if self.reqs is not None and not self.reqs.check_access(state, self.world): + return False + + if not all(state.can_reach(region) for region in self.required_regions): + return False + + return True + -- cgit 1.4.1