diff options
Diffstat (limited to 'apworld/tracker.py')
| -rw-r--r-- | apworld/tracker.py | 47 |
1 files changed, 44 insertions, 3 deletions
| diff --git a/apworld/tracker.py b/apworld/tracker.py index cf2dbe1..a84c3f8 100644 --- a/apworld/tracker.py +++ b/apworld/tracker.py | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | from typing import TYPE_CHECKING | 1 | from typing import TYPE_CHECKING, Iterator |
| 2 | 2 | ||
| 3 | from BaseClasses import MultiWorld, CollectionState, ItemClassification | 3 | from BaseClasses import MultiWorld, CollectionState, ItemClassification, Region, Entrance |
| 4 | from NetUtils import NetworkItem | 4 | from NetUtils import NetworkItem |
| 5 | from . import Lingo2World, Lingo2Item | 5 | from . import Lingo2World, Lingo2Item |
| 6 | from .regions import connect_ports_from_ut | 6 | from .regions import connect_ports_from_ut |
| @@ -22,6 +22,7 @@ class Tracker: | |||
| 22 | checked_locations: set[int] | 22 | checked_locations: set[int] |
| 23 | accessible_locations: set[int] | 23 | accessible_locations: set[int] |
| 24 | accessible_worldports: set[int] | 24 | accessible_worldports: set[int] |
| 25 | goal_accessible: bool | ||
| 25 | 26 | ||
| 26 | state: CollectionState | 27 | state: CollectionState |
| 27 | 28 | ||
| @@ -31,6 +32,7 @@ class Tracker: | |||
| 31 | self.checked_locations = set() | 32 | self.checked_locations = set() |
| 32 | self.accessible_locations = set() | 33 | self.accessible_locations = set() |
| 33 | self.accessible_worldports = set() | 34 | self.accessible_worldports = set() |
| 35 | self.goal_accessible = False | ||
| 34 | 36 | ||
| 35 | def setup_slot(self, slot_data): | 37 | def setup_slot(self, slot_data): |
| 36 | Lingo2World.for_tracker = True | 38 | Lingo2World.for_tracker = True |
| @@ -45,7 +47,10 @@ class Tracker: | |||
| 45 | self.world.create_regions() | 47 | self.world.create_regions() |
| 46 | 48 | ||
| 47 | if self.world.options.shuffle_worldports: | 49 | if self.world.options.shuffle_worldports: |
| 48 | port_pairings = {int(fp): int(tp) for fp, tp in slot_data["port_pairings"].items()} | 50 | port_pairings = { |
| 51 | self.world.static_logic.port_id_by_ap_id[int(fp)]: self.world.static_logic.port_id_by_ap_id[int(tp)] | ||
| 52 | for fp, tp in slot_data["port_pairings"].items() | ||
| 53 | } | ||
| 49 | connect_ports_from_ut(port_pairings, self.world) | 54 | connect_ports_from_ut(port_pairings, self.world) |
| 50 | 55 | ||
| 51 | self.refresh_state() | 56 | self.refresh_state() |
| @@ -91,9 +96,11 @@ class Tracker: | |||
| 91 | PLAYER_NUM), prevent_sweep=True) | 96 | PLAYER_NUM), prevent_sweep=True) |
| 92 | 97 | ||
| 93 | self.state.sweep_for_advancements() | 98 | self.state.sweep_for_advancements() |
| 99 | self.state.update_reachable_regions(PLAYER_NUM) | ||
| 94 | 100 | ||
| 95 | self.accessible_locations = set() | 101 | self.accessible_locations = set() |
| 96 | self.accessible_worldports = set() | 102 | self.accessible_worldports = set() |
| 103 | self.goal_accessible = False | ||
| 97 | 104 | ||
| 98 | for region in self.state.reachable_regions[PLAYER_NUM]: | 105 | for region in self.state.reachable_regions[PLAYER_NUM]: |
| 99 | for location in region.locations: | 106 | for location in region.locations: |
| @@ -104,3 +111,37 @@ class Tracker: | |||
| 104 | elif hasattr(location, "port_id"): | 111 | elif hasattr(location, "port_id"): |
| 105 | if location.port_id not in self.manager.worldports: | 112 | if location.port_id not in self.manager.worldports: |
| 106 | self.accessible_worldports.add(location.port_id) | 113 | self.accessible_worldports.add(location.port_id) |
| 114 | elif hasattr(location, "goal") and location.goal: | ||
| 115 | if not self.manager.goaled: | ||
| 116 | self.goal_accessible = True | ||
| 117 | |||
| 118 | def get_path_to_location(self, location_id: int) -> list[str] | None: | ||
| 119 | location_name = self.world.location_id_to_name.get(location_id) | ||
| 120 | location = self.multiworld.get_location(location_name, PLAYER_NUM) | ||
| 121 | return self.get_logical_path(location.parent_region) | ||
| 122 | |||
| 123 | def get_path_to_port(self, port_id: int) -> list[str] | None: | ||
| 124 | port = self.world.static_logic.objects.ports[port_id] | ||
| 125 | region_name = self.world.static_logic.get_room_region_name(port.room_id) | ||
| 126 | region = self.multiworld.get_region(region_name, PLAYER_NUM) | ||
| 127 | return self.get_logical_path(region) | ||
| 128 | |||
| 129 | def get_path_to_goal(self): | ||
| 130 | room_id = self.world.player_logic.goal_room_id | ||
| 131 | region_name = self.world.static_logic.get_room_region_name(room_id) | ||
| 132 | region = self.multiworld.get_region(region_name, PLAYER_NUM) | ||
| 133 | return self.get_logical_path(region) | ||
| 134 | |||
| 135 | def get_logical_path(self, region: Region) -> list[str] | None: | ||
| 136 | if region not in self.state.path: | ||
| 137 | return None | ||
| 138 | |||
| 139 | def flist_to_iter(path_value) -> Iterator[str]: | ||
| 140 | while path_value: | ||
| 141 | region_or_entrance, path_value = path_value | ||
| 142 | yield region_or_entrance | ||
| 143 | |||
| 144 | reversed_path = self.state.path.get(region) | ||
| 145 | flat_path = reversed(list(map(str, flist_to_iter(reversed_path)))) | ||
| 146 | |||
| 147 | return list(flat_path)[1::2] | ||
