diff options
Diffstat (limited to 'apworld/locations.py')
| -rw-r--r-- | apworld/locations.py | 81 |
1 files changed, 80 insertions, 1 deletions
| 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 @@ | |||
| 1 | from enum import Enum | 1 | from enum import Enum |
| 2 | from typing import TYPE_CHECKING | ||
| 2 | 3 | ||
| 3 | from BaseClasses import Location, Item | 4 | from BaseClasses import Location, Item, Region, CollectionState, Entrance |
| 4 | from .items import Lingo2Item | 5 | from .items import Lingo2Item |
| 6 | from .rules import AccessRequirements | ||
| 7 | |||
| 8 | if TYPE_CHECKING: | ||
| 9 | from . import Lingo2World | ||
| 5 | 10 | ||
| 6 | 11 | ||
| 7 | class LetterPlacementType(Enum): | 12 | class LetterPlacementType(Enum): |
| @@ -10,13 +15,59 @@ class LetterPlacementType(Enum): | |||
| 10 | FORCE = 2 | 15 | FORCE = 2 |
| 11 | 16 | ||
| 12 | 17 | ||
| 18 | def get_required_regions(reqs: AccessRequirements, world: "Lingo2World", | ||
| 19 | regions: dict[str, Region] | None) -> list[Region]: | ||
| 20 | # Replace required rooms with regions for the top level requirement, which saves looking up the regions during rule | ||
| 21 | # checking. | ||
| 22 | if regions is not None: | ||
| 23 | return [regions[room_name] for room_name in reqs.rooms] | ||
| 24 | else: | ||
| 25 | return [world.multiworld.get_region(room_name, world.player) for room_name in reqs.rooms] | ||
| 26 | |||
| 27 | |||
| 13 | class Lingo2Location(Location): | 28 | class Lingo2Location(Location): |
| 14 | game: str = "Lingo 2" | 29 | game: str = "Lingo 2" |
| 15 | 30 | ||
| 31 | reqs: AccessRequirements | None | ||
| 32 | world: "Lingo2World" | ||
| 33 | required_regions: list[Region] | ||
| 34 | |||
| 16 | port_id: int | 35 | port_id: int |
| 17 | goal: bool | 36 | goal: bool |
| 18 | letter_placement_type: LetterPlacementType | 37 | letter_placement_type: LetterPlacementType |
| 19 | 38 | ||
| 39 | @classmethod | ||
| 40 | def non_event_location(cls, world: "Lingo2World", code: int, region: Region): | ||
| 41 | result = cls(world.player, world.static_logic.location_id_to_name[code], code, region) | ||
| 42 | result.reqs = None | ||
| 43 | result.world = world | ||
| 44 | result.required_regions = [] | ||
| 45 | |||
| 46 | return result | ||
| 47 | |||
| 48 | @classmethod | ||
| 49 | def event_location(cls, world: "Lingo2World", name: str, region: Region): | ||
| 50 | result = cls(world.player, name, None, region) | ||
| 51 | result.reqs = None | ||
| 52 | result.world = world | ||
| 53 | result.required_regions = [] | ||
| 54 | |||
| 55 | return result | ||
| 56 | |||
| 57 | def set_access_rule(self, reqs: AccessRequirements, regions: dict[str, Region] | None): | ||
| 58 | self.reqs = reqs | ||
| 59 | self.required_regions = get_required_regions(reqs, self.world, regions) | ||
| 60 | self.access_rule = self._l2_access_rule | ||
| 61 | |||
| 62 | def _l2_access_rule(self, state: CollectionState) -> bool: | ||
| 63 | if self.reqs is not None and not self.reqs.check_access(state, self.world): | ||
| 64 | return False | ||
| 65 | |||
| 66 | if not all(state.can_reach(region) for region in self.required_regions): | ||
| 67 | return False | ||
| 68 | |||
| 69 | return True | ||
| 70 | |||
| 20 | def set_up_letter_rule(self, lpt: LetterPlacementType): | 71 | def set_up_letter_rule(self, lpt: LetterPlacementType): |
| 21 | self.letter_placement_type = lpt | 72 | self.letter_placement_type = lpt |
| 22 | self.item_rule = self._l2_item_rule | 73 | self.item_rule = self._l2_item_rule |
| @@ -31,3 +82,31 @@ class Lingo2Location(Location): | |||
| 31 | return not item.is_letter | 82 | return not item.is_letter |
| 32 | 83 | ||
| 33 | return True | 84 | return True |
| 85 | |||
| 86 | |||
| 87 | class Lingo2Entrance(Entrance): | ||
| 88 | reqs: AccessRequirements | None | ||
| 89 | world: "Lingo2World" | ||
| 90 | required_regions: list[Region] | ||
| 91 | |||
| 92 | def __init__(self, world: "Lingo2World", description: str, region: Region): | ||
| 93 | super().__init__(world.player, description, region) | ||
| 94 | |||
| 95 | self.reqs = None | ||
| 96 | self.world = world | ||
| 97 | self.required_regions = [] | ||
| 98 | |||
| 99 | def set_access_rule(self, reqs: AccessRequirements, regions: dict[str, Region] | None): | ||
| 100 | self.reqs = reqs | ||
| 101 | self.required_regions = get_required_regions(reqs, self.world, regions) | ||
| 102 | self.access_rule = self._l2_access_rule | ||
| 103 | |||
| 104 | def _l2_access_rule(self, state: CollectionState) -> bool: | ||
| 105 | if self.reqs is not None and not self.reqs.check_access(state, self.world): | ||
| 106 | return False | ||
| 107 | |||
| 108 | if not all(state.can_reach(region) for region in self.required_regions): | ||
| 109 | return False | ||
| 110 | |||
| 111 | return True | ||
| 112 | |||
