diff options
Diffstat (limited to 'apworld/player_logic.py')
| -rw-r--r-- | apworld/player_logic.py | 30 |
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) | ||
