1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
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
|