diff options
Diffstat (limited to 'apworld/locations.py')
| -rw-r--r-- | apworld/locations.py | 106 |
1 files changed, 105 insertions, 1 deletions
| diff --git a/apworld/locations.py b/apworld/locations.py index 3d619dc..c92215e 100644 --- a/apworld/locations.py +++ b/apworld/locations.py | |||
| @@ -1,8 +1,112 @@ | |||
| 1 | from BaseClasses import Location | 1 | from enum import Enum |
| 2 | from typing import TYPE_CHECKING | ||
| 3 | |||
| 4 | from BaseClasses import Location, Item, Region, CollectionState, Entrance | ||
| 5 | from .items import Lingo2Item | ||
| 6 | from .rules import AccessRequirements | ||
| 7 | |||
| 8 | if TYPE_CHECKING: | ||
| 9 | from . import Lingo2World | ||
| 10 | |||
| 11 | |||
| 12 | class LetterPlacementType(Enum): | ||
| 13 | ANY = 0 | ||
| 14 | DISALLOW = 1 | ||
| 15 | FORCE = 2 | ||
| 16 | |||
| 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] | ||
| 2 | 26 | ||
| 3 | 27 | ||
| 4 | class Lingo2Location(Location): | 28 | class Lingo2Location(Location): |
| 5 | game: str = "Lingo 2" | 29 | game: str = "Lingo 2" |
| 6 | 30 | ||
| 31 | reqs: AccessRequirements | None | ||
| 32 | world: "Lingo2World" | ||
| 33 | required_regions: list[Region] | ||
| 34 | |||
| 7 | port_id: int | 35 | port_id: int |
| 8 | goal: bool | 36 | goal: bool |
| 37 | letter_placement_type: LetterPlacementType | ||
| 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 | |||
| 71 | def set_up_letter_rule(self, lpt: LetterPlacementType): | ||
| 72 | self.letter_placement_type = lpt | ||
| 73 | self.item_rule = self._l2_item_rule | ||
| 74 | |||
| 75 | def _l2_item_rule(self, item: Item) -> bool: | ||
| 76 | if not isinstance(item, Lingo2Item): | ||
| 77 | return True | ||
| 78 | |||
| 79 | if self.letter_placement_type == LetterPlacementType.FORCE: | ||
| 80 | return item.is_letter | ||
| 81 | elif self.letter_placement_type == LetterPlacementType.DISALLOW: | ||
| 82 | return not item.is_letter | ||
| 83 | |||
| 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 | |||
