about summary refs log tree commit diff stats
path: root/apworld/locations.py
diff options
context:
space:
mode:
Diffstat (limited to 'apworld/locations.py')
-rw-r--r--apworld/locations.py106
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 @@
1from BaseClasses import Location 1from enum import Enum
2from typing import TYPE_CHECKING
3
4from BaseClasses import Location, Item, Region, CollectionState, Entrance
5from .items import Lingo2Item
6from .rules import AccessRequirements
7
8if TYPE_CHECKING:
9 from . import Lingo2World
10
11
12class LetterPlacementType(Enum):
13 ANY = 0
14 DISALLOW = 1
15 FORCE = 2
16
17
18def 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
4class Lingo2Location(Location): 28class 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
87class 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