summary refs log tree commit diff stats
path: root/apworld/player_logic.py
diff options
context:
space:
mode:
Diffstat (limited to 'apworld/player_logic.py')
-rw-r--r--apworld/player_logic.py30
1 files changed, 25 insertions, 5 deletions
diff --git a/apworld/player_logic.py b/apworld/player_logic.py index 7209ee5..c2850d5 100644 --- a/apworld/player_logic.py +++ b/apworld/player_logic.py
@@ -63,6 +63,7 @@ class Lingo2PlayerLogic:
63 world: "Lingo2World" 63 world: "Lingo2World"
64 64
65 locations_by_room: dict[int, list[PlayerLocation]] 65 locations_by_room: dict[int, list[PlayerLocation]]
66 item_by_door: dict[int, str]
66 67
67 panel_reqs: dict[int, AccessRequirements] 68 panel_reqs: dict[int, AccessRequirements]
68 proxy_reqs: dict[int, dict[str, AccessRequirements]] 69 proxy_reqs: dict[int, dict[str, AccessRequirements]]
@@ -73,19 +74,25 @@ class Lingo2PlayerLogic:
73 def __init__(self, world: "Lingo2World"): 74 def __init__(self, world: "Lingo2World"):
74 self.world = world 75 self.world = world
75 self.locations_by_room = {} 76 self.locations_by_room = {}
77 self.item_by_door = {}
76 self.panel_reqs = dict() 78 self.panel_reqs = dict()
77 self.proxy_reqs = dict() 79 self.proxy_reqs = dict()
78 self.door_reqs = dict() 80 self.door_reqs = dict()
79 self.real_items = list() 81 self.real_items = list()
80 82
83 # We iterate through the doors in two parts because it is essential that we determine which doors are shuffled
84 # before we calculate any access requirements.
85 for door in world.static_logic.objects.doors:
86 if door.type in [data_pb2.DoorType.STANDARD, data_pb2.DoorType.ITEM_ONLY] and self.world.options.shuffle_doors:
87 door_item_name = self.world.static_logic.get_door_item_name(door.id)
88 self.item_by_door[door.id] = door_item_name
89 self.real_items.append(door_item_name)
90
81 for door in world.static_logic.objects.doors: 91 for door in world.static_logic.objects.doors:
82 if door.type in [data_pb2.DoorType.STANDARD, data_pb2.DoorType.LOCATION_ONLY]: 92 if door.type in [data_pb2.DoorType.STANDARD, data_pb2.DoorType.LOCATION_ONLY]:
83 self.locations_by_room.setdefault(door.room_id, []).append(PlayerLocation(door.ap_id, 93 self.locations_by_room.setdefault(door.room_id, []).append(PlayerLocation(door.ap_id,
84 self.get_door_reqs(door.id))) 94 self.get_door_reqs(door.id)))
85 95
86 if door.type in [data_pb2.DoorType.STANDARD, data_pb2.DoorType.ITEM_ONLY] and self.world.options.shuffle_doors:
87 self.real_items.append(self.world.static_logic.get_door_item_name(door.id))
88
89 for letter in world.static_logic.objects.letters: 96 for letter in world.static_logic.objects.letters:
90 self.locations_by_room.setdefault(letter.room_id, []).append(PlayerLocation(letter.ap_id, 97 self.locations_by_room.setdefault(letter.room_id, []).append(PlayerLocation(letter.ap_id,
91 AccessRequirements())) 98 AccessRequirements()))
@@ -127,7 +134,7 @@ class Lingo2PlayerLogic:
127 reqs.symbols.add(symbol) 134 reqs.symbols.add(symbol)
128 135
129 if panel.HasField("required_door"): 136 if panel.HasField("required_door"):
130 door_reqs = self.get_door_reqs(panel.required_door) 137 door_reqs = self.get_door_open_reqs(panel.required_door)
131 reqs.merge(door_reqs) 138 reqs.merge(door_reqs)
132 139
133 if panel.HasField("required_room"): 140 if panel.HasField("required_room"):
@@ -135,6 +142,8 @@ class Lingo2PlayerLogic:
135 142
136 return reqs 143 return reqs
137 144
145 # This gets/calculates the requirements described by the door object. This is most notably used as the requirements
146 # for clearing a location, or opening a door when the door is not shuffled.
138 def get_door_reqs(self, door_id: int) -> AccessRequirements: 147 def get_door_reqs(self, door_id: int) -> AccessRequirements:
139 if door_id not in self.door_reqs: 148 if door_id not in self.door_reqs:
140 self.door_reqs[door_id] = self.calculate_door_reqs(door_id) 149 self.door_reqs[door_id] = self.calculate_door_reqs(door_id)
@@ -161,7 +170,18 @@ class Lingo2PlayerLogic:
161 reqs.rooms.add(self.world.static_logic.get_room_region_name(room)) 170 reqs.rooms.add(self.world.static_logic.get_room_region_name(room))
162 171
163 for sub_door_id in door.doors: 172 for sub_door_id in door.doors:
164 sub_reqs = self.get_door_reqs(sub_door_id) 173 sub_reqs = self.get_door_open_reqs(sub_door_id)
165 reqs.merge(sub_reqs) 174 reqs.merge(sub_reqs)
166 175
167 return reqs 176 return reqs
177
178 # This gets the requirements to open a door within the world. When a door is shuffled, this means having the item
179 # that acts as the door's key.
180 def get_door_open_reqs(self, door_id: int) -> AccessRequirements:
181 if door_id in self.item_by_door:
182 reqs = AccessRequirements()
183 reqs.items.add(self.item_by_door.get(door_id))
184
185 return reqs
186 else:
187 return self.get_door_reqs(door_id)