from enum import Enum from typing import TYPE_CHECKING 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): ANY = 0 DISALLOW = 1 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 def _l2_item_rule(self, item: Item) -> bool: if not isinstance(item, Lingo2Item): return True if self.letter_placement_type == LetterPlacementType.FORCE: return item.is_letter elif self.letter_placement_type == LetterPlacementType.DISALLOW: 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