ALTTP: Updates and refactors to multi-tracker and player tracker. (#3183)

* ALTTP: Massive game tracker update.

* Adds dropdowns separated by region for each location and its checked status.
* Adds Bombs for bombless start seeds.
* Adds Triforce Pieces to track.
* Update icon image URLs to match in-game closer.
* Fix issue with grouped progressive items.

* Couple missed points.

* Another edge case with details being refreshed.

* Remove old commented out CSS

* Consolidate a table and move an erroneous location in wrong region.

* ALTTP: Updates and refactors to multi-tracker and player tracker.

* Removed some missed commented out code.

* Add triforce to prepare inventory logic.
This commit is contained in:
Zach Parks
2024-04-20 17:29:41 -05:00
committed by GitHub
parent 0a1ce5b7d8
commit 532cff1334
3 changed files with 318 additions and 515 deletions

View File

@@ -1,7 +1,7 @@
import datetime
import collections
from dataclasses import dataclass
from typing import Any, Callable, Dict, List, Optional, Set, Tuple
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, NamedTuple
from uuid import UUID
from flask import render_template
@@ -456,210 +456,111 @@ if "Factorio" in network_data_package["games"]:
_multiworld_trackers["Factorio"] = render_Factorio_multiworld_tracker
if "A Link to the Past" in network_data_package["games"]:
# Mapping from non-progressive item to progressive name and max level.
non_progressive_items = {
"Fighter Sword": ("Progressive Sword", 1),
"Master Sword": ("Progressive Sword", 2),
"Tempered Sword": ("Progressive Sword", 3),
"Golden Sword": ("Progressive Sword", 4),
"Power Glove": ("Progressive Glove", 1),
"Titans Mitts": ("Progressive Glove", 2),
"Bow": ("Progressive Bow", 1),
"Silver Bow": ("Progressive Bow", 2),
"Blue Mail": ("Progressive Mail", 1),
"Red Mail": ("Progressive Mail", 2),
"Blue Shield": ("Progressive Shield", 1),
"Red Shield": ("Progressive Shield", 2),
"Mirror Shield": ("Progressive Shield", 3),
}
progressive_item_max = {
"Progressive Sword": 4,
"Progressive Glove": 2,
"Progressive Bow": 2,
"Progressive Mail": 2,
"Progressive Shield": 3,
}
bottle_items = [
"Bottle",
"Bottle (Bee)",
"Bottle (Blue Potion)",
"Bottle (Fairy)",
"Bottle (Good Bee)",
"Bottle (Green Potion)",
"Bottle (Red Potion)",
]
known_regions = [
"Light World", "Dark World", "Hyrule Castle", "Agahnims Tower", "Eastern Palace", "Desert Palace",
"Tower of Hera", "Palace of Darkness", "Swamp Palace", "Thieves Town", "Skull Woods", "Ice Palace",
"Misery Mire", "Turtle Rock", "Ganons Tower"
]
class RegionCounts(NamedTuple):
total: int
checked: int
def prepare_inventories(team: int, player: int, inventory: collections.Counter[str], tracker_data: TrackerData):
for item, (prog_item, level) in non_progressive_items.items():
if item in inventory:
inventory[prog_item] = min(max(inventory[prog_item], level), progressive_item_max[prog_item])
for bottle in bottle_items:
inventory["Bottles"] = min(inventory["Bottles"] + inventory[bottle], 4)
if "Progressive Bow (Alt)" in inventory:
inventory["Progressive Bow"] += inventory["Progressive Bow (Alt)"]
inventory["Progressive Bow"] = min(inventory["Progressive Bow"], progressive_item_max["Progressive Bow"])
# Highlight 'bombs' if we received any bomb upgrades in bombless start.
# In race mode, we'll just assume bombless start for simplicity.
if tracker_data.get_slot_data(team, player).get("bombless_start", True):
inventory["Bombs"] = sum(count for item, count in inventory.items() if item.startswith("Bomb Upgrade"))
else:
inventory["Bombs"] = 1
# Triforce item if we meet goal.
if tracker_data.get_room_client_statuses()[team, player] == ClientStatus.CLIENT_GOAL:
inventory["Triforce"] = 1
def render_ALinkToThePast_multiworld_tracker(tracker_data: TrackerData, enabled_trackers: List[str]):
# Helper objects.
alttp_id_lookup = tracker_data.item_name_to_id["A Link to the Past"]
inventories: Dict[Tuple[int, int], collections.Counter[str]] = {
(team, player): collections.Counter({
tracker_data.item_id_to_name["A Link to the Past"][code]: count
for code, count in tracker_data.get_player_inventory_counts(team, player).items()
})
for team, players in tracker_data.get_all_players().items()
for player in players if tracker_data.get_slot_info(team, player).game == "A Link to the Past"
}
multi_items = {
alttp_id_lookup[name]
for name in ("Progressive Sword", "Progressive Bow", "Bottle", "Progressive Glove", "Triforce Piece")
}
links = {
"Bow": "Progressive Bow",
"Silver Arrows": "Progressive Bow",
"Silver Bow": "Progressive Bow",
"Progressive Bow (Alt)": "Progressive Bow",
"Bottle (Red Potion)": "Bottle",
"Bottle (Green Potion)": "Bottle",
"Bottle (Blue Potion)": "Bottle",
"Bottle (Fairy)": "Bottle",
"Bottle (Bee)": "Bottle",
"Bottle (Good Bee)": "Bottle",
"Fighter Sword": "Progressive Sword",
"Master Sword": "Progressive Sword",
"Tempered Sword": "Progressive Sword",
"Golden Sword": "Progressive Sword",
"Power Glove": "Progressive Glove",
"Titans Mitts": "Progressive Glove",
}
links = {alttp_id_lookup[key]: alttp_id_lookup[value] for key, value in links.items()}
levels = {
"Fighter Sword": 1,
"Master Sword": 2,
"Tempered Sword": 3,
"Golden Sword": 4,
"Power Glove": 1,
"Titans Mitts": 2,
"Bow": 1,
"Silver Bow": 2,
"Triforce Piece": 90,
}
tracking_names = [
"Progressive Sword", "Progressive Bow", "Book of Mudora", "Hammer", "Hookshot", "Magic Mirror", "Flute",
"Pegasus Boots", "Progressive Glove", "Flippers", "Moon Pearl", "Blue Boomerang", "Red Boomerang",
"Bug Catching Net", "Cape", "Shovel", "Lamp", "Mushroom", "Magic Powder", "Cane of Somaria",
"Cane of Byrna", "Fire Rod", "Ice Rod", "Bombos", "Ether", "Quake", "Bottle", "Triforce Piece", "Triforce",
]
default_locations = {
"Light World": {
1572864, 1572865, 60034, 1572867, 1572868, 60037, 1572869, 1572866, 60040, 59788, 60046, 60175,
1572880, 60049, 60178, 1572883, 60052, 60181, 1572885, 60055, 60184, 191256, 60058, 60187, 1572884,
1572886, 1572887, 1572906, 60202, 60205, 59824, 166320, 1010170, 60208, 60211, 60214, 60217, 59836,
60220, 60223, 59839, 1573184, 60226, 975299, 1573188, 1573189, 188229, 60229, 60232, 1573193,
1573194, 60235, 1573187, 59845, 59854, 211407, 60238, 59857, 1573185, 1573186, 1572882, 212328,
59881, 59761, 59890, 59770, 193020, 212605
},
"Dark World": {
59776, 59779, 975237, 1572870, 60043, 1572881, 60190, 60193, 60196, 60199, 60840, 1573190, 209095,
1573192, 1573191, 60241, 60244, 60247, 60250, 59884, 59887, 60019, 60022, 60028, 60031
},
"Desert Palace": {1573216, 59842, 59851, 59791, 1573201, 59830},
"Eastern Palace": {1573200, 59827, 59893, 59767, 59833, 59773},
"Hyrule Castle": {60256, 60259, 60169, 60172, 59758, 59764, 60025, 60253},
"Agahnims Tower": {60082, 60085},
"Tower of Hera": {1573218, 59878, 59821, 1573202, 59896, 59899},
"Swamp Palace": {60064, 60067, 60070, 59782, 59785, 60073, 60076, 60079, 1573204, 60061},
"Thieves Town": {59905, 59908, 59911, 59914, 59917, 59920, 59923, 1573206},
"Skull Woods": {59809, 59902, 59848, 59794, 1573205, 59800, 59803, 59806},
"Ice Palace": {59872, 59875, 59812, 59818, 59860, 59797, 1573207, 59869},
"Misery Mire": {60001, 60004, 60007, 60010, 60013, 1573208, 59866, 59998},
"Turtle Rock": {59938, 59941, 59944, 1573209, 59947, 59950, 59953, 59956, 59926, 59929, 59932, 59935},
"Palace of Darkness": {
59968, 59971, 59974, 59977, 59980, 59983, 59986, 1573203, 59989, 59959, 59992, 59962, 59995,
59965
},
"Ganons Tower": {
60160, 60163, 60166, 60088, 60091, 60094, 60097, 60100, 60103, 60106, 60109, 60112, 60115, 60118,
60121, 60124, 60127, 1573217, 60130, 60133, 60136, 60139, 60142, 60145, 60148, 60151, 60157
},
"Total": set()
}
key_only_locations = {
"Light World": set(),
"Dark World": set(),
"Desert Palace": {0x140031, 0x14002b, 0x140061, 0x140028},
"Eastern Palace": {0x14005b, 0x140049},
"Hyrule Castle": {0x140037, 0x140034, 0x14000d, 0x14003d},
"Agahnims Tower": {0x140061, 0x140052},
"Tower of Hera": set(),
"Swamp Palace": {0x140019, 0x140016, 0x140013, 0x140010, 0x14000a},
"Thieves Town": {0x14005e, 0x14004f},
"Skull Woods": {0x14002e, 0x14001c},
"Ice Palace": {0x140004, 0x140022, 0x140025, 0x140046},
"Misery Mire": {0x140055, 0x14004c, 0x140064},
"Turtle Rock": {0x140058, 0x140007},
"Palace of Darkness": set(),
"Ganons Tower": {0x140040, 0x140043, 0x14003a, 0x14001f},
"Total": set()
}
location_to_area = {}
for area, locations in default_locations.items():
for location in locations:
location_to_area[location] = area
for area, locations in key_only_locations.items():
for location in locations:
location_to_area[location] = area
# Translate non-progression items to progression items for tracker simplicity.
for (team, player), inventory in inventories.items():
prepare_inventories(team, player, inventory, tracker_data)
checks_in_area = {area: len(checks) for area, checks in default_locations.items()}
checks_in_area["Total"] = 216
ordered_areas = (
"Light World", "Dark World", "Hyrule Castle", "Agahnims Tower", "Eastern Palace", "Desert Palace",
"Tower of Hera", "Palace of Darkness", "Swamp Palace", "Skull Woods", "Thieves Town", "Ice Palace",
"Misery Mire", "Turtle Rock", "Ganons Tower", "Total"
)
player_checks_in_area = {
regions: Dict[Tuple[int, int], Dict[str, RegionCounts]] = {
(team, player): {
area_name: len(tracker_data._multidata["checks_in_area"][player][area_name])
if area_name != "Total" else tracker_data._multidata["checks_in_area"][player]["Total"]
for area_name in ordered_areas
region_name: RegionCounts(
total=len(tracker_data._multidata["checks_in_area"][player][region_name]),
checked=sum(
1 for location in tracker_data._multidata["checks_in_area"][player][region_name]
if location in tracker_data.get_player_checked_locations(team, player)
),
)
for region_name in known_regions
}
for team, players in tracker_data.get_all_slots().items()
for player in players
if tracker_data.get_slot_info(team, player).type != SlotType.group and
tracker_data.get_slot_info(team, player).game == "A Link to the Past"
for team, players in tracker_data.get_all_players().items()
for player in players if tracker_data.get_slot_info(team, player).game == "A Link to the Past"
}
tracking_ids = []
for item in tracking_names:
tracking_ids.append(alttp_id_lookup[item])
# Can't wait to get this into the apworld. Oof.
from worlds.alttp import Items
small_key_ids = {}
big_key_ids = {}
ids_small_key = {}
ids_big_key = {}
for item_name, data in Items.item_table.items():
if "Key" in item_name:
area = item_name.split("(")[1][:-1]
if "Small" in item_name:
small_key_ids[area] = data[2]
ids_small_key[data[2]] = area
else:
big_key_ids[area] = data[2]
ids_big_key[data[2]] = area
def _get_location_table(checks_table: dict) -> dict:
loc_to_area = {}
for area, locations in checks_table.items():
if area == "Total":
continue
for location in locations:
loc_to_area[location] = area
return loc_to_area
player_location_to_area = {
(team, player): _get_location_table(tracker_data._multidata["checks_in_area"][player])
for team, players in tracker_data.get_all_slots().items()
for player in players
if tracker_data.get_slot_info(team, player).type != SlotType.group and
tracker_data.get_slot_info(team, player).game == "A Link to the Past"
}
checks_done: Dict[TeamPlayer, Dict[str: int]] = {
(team, player): {location_name: 0 for location_name in default_locations}
for team, players in tracker_data.get_all_slots().items()
for player in players
if tracker_data.get_slot_info(team, player).type != SlotType.group and
tracker_data.get_slot_info(team, player).game == "A Link to the Past"
}
inventories: Dict[TeamPlayer, Dict[int, int]] = {}
player_big_key_locations = {(player): set() for player in tracker_data.get_all_slots()[0]}
player_small_key_locations = {player: set() for player in tracker_data.get_all_slots()[0]}
group_big_key_locations = set()
group_key_locations = set()
for (team, player), locations in checks_done.items():
# Check if game complete.
if tracker_data.get_player_client_status(team, player) == ClientStatus.CLIENT_GOAL:
inventories[team, player][106] = 1 # Triforce
# Count number of locations checked.
for location in tracker_data.get_player_checked_locations(team, player):
checks_done[team, player][player_location_to_area[team, player][location]] += 1
checks_done[team, player]["Total"] += 1
# Count keys.
for location, (item, receiving, _) in tracker_data.get_player_locations(team, player).items():
if item in ids_big_key:
player_big_key_locations[receiving].add(ids_big_key[item])
elif item in ids_small_key:
player_small_key_locations[receiving].add(ids_small_key[item])
# Iterate over received items and build inventory/key counts.
inventories[team, player] = collections.Counter()
for network_item in tracker_data.get_player_received_items(team, player):
target_item = links.get(network_item.item, network_item.item)
if network_item.item in levels: # non-progressive
inventories[team, player][target_item] = (max(inventories[team, player][target_item], levels[network_item.item]))
else:
inventories[team, player][target_item] += 1
group_key_locations |= player_small_key_locations[player]
group_big_key_locations |= player_big_key_locations[player]
# Get a totals count.
for player, player_regions in regions.items():
total = 0
checked = 0
for region, region_counts in player_regions.items():
total += region_counts.total
checked += region_counts.checked
regions[player]["Total"] = RegionCounts(total, checked)
return render_template(
"multitracker__ALinkToThePast.html",
@@ -682,16 +583,8 @@ if "A Link to the Past" in network_data_package["games"]:
item_id_to_name=tracker_data.item_id_to_name,
location_id_to_name=tracker_data.location_id_to_name,
inventories=inventories,
tracking_names=tracking_names,
tracking_ids=tracking_ids,
multi_items=multi_items,
checks_done=checks_done,
ordered_areas=ordered_areas,
checks_in_area=player_checks_in_area,
key_locations=group_key_locations,
big_key_locations=group_big_key_locations,
small_key_ids=small_key_ids,
big_key_ids=big_key_ids,
regions=regions,
known_regions=known_regions,
)
def render_ALinkToThePast_tracker(tracker_data: TrackerData, team: int, player: int) -> str:
@@ -700,161 +593,26 @@ if "A Link to the Past" in network_data_package["games"]:
for code, count in tracker_data.get_player_inventory_counts(team, player).items()
})
# Mapping from non-progressive item to progressive name and max level.
non_progressive_items = {
"Fighter Sword": ("Progressive Sword", 1),
"Master Sword": ("Progressive Sword", 2),
"Tempered Sword": ("Progressive Sword", 3),
"Golden Sword": ("Progressive Sword", 4),
"Power Glove": ("Progressive Glove", 1),
"Titans Mitts": ("Progressive Glove", 2),
"Bow": ("Progressive Bow", 1),
"Silver Bow": ("Progressive Bow", 2),
"Blue Mail": ("Progressive Mail", 1),
"Red Mail": ("Progressive Mail", 2),
"Blue Shield": ("Progressive Shield", 1),
"Red Shield": ("Progressive Shield", 2),
"Mirror Shield": ("Progressive Shield", 3),
}
progressive_item_max = {
"Progressive Sword": 4,
"Progressive Glove": 2,
"Progressive Bow": 2,
"Progressive Mail": 2,
"Progressive Shield": 3,
}
bottle_items = [
"Bottle",
"Bottle (Bee)",
"Bottle (Blue Potion)",
"Bottle (Fairy)",
"Bottle (Good Bee)",
"Bottle (Green Potion)",
"Bottle (Red Potion)",
]
# Translate non-progression items to progression items for tracker simplicity.
for item, (prog_item, level) in non_progressive_items.items():
if item in inventory:
inventory[prog_item] = min(max(inventory[prog_item], level), progressive_item_max[prog_item])
for bottle in bottle_items:
inventory["Bottles"] = min(inventory["Bottles"] + inventory[bottle], 4)
if "Progressive Bow (Alt)" in inventory:
inventory["Progressive Bow"] += inventory["Progressive Bow (Alt)"]
inventory["Progressive Bow"] = min(inventory["Progressive Bow"], progressive_item_max["Progressive Bow"])
# Highlight 'bombs' if we received any bomb upgrades in bombless start.
# In race mode, we'll just assume bombless start for simplicity.
if tracker_data.get_slot_data(team, player).get("bombless_start", True):
inventory["Bombs"] = sum(count for item, count in inventory.items() if item.startswith("Bomb Upgrade"))
else:
inventory["Bombs"] = 1
known_regions = {
"Light World": {
0x180013, 0x02eb18, 0x18014a, 0x180145, 0x033d68, 0x00eb0f, 0x00eb12, 0x00eb15, 0x00eb18, 0x00eb1b,
0x02df45, 0x00e971, 0x0ee1c3, 0x180149, 0x00e9b0, 0x00e9d1, 0x00e97a, 0x00e98c, 0x00e9bc, 0x00e9ce,
0x00e9e9, 0x00e9f2, 0x00ea82, 0x00ea85, 0x00ea88, 0x02f1fc, 0x00ea8e, 0x00ea91, 0x00ea94, 0x00ea97,
0x00ea9a, 0x18002a, 0x180015, 0x0339cf, 0x033e7d, 0x180000, 0x180001, 0x180003, 0x180004, 0x180005,
0x00eb42, 0x00eb45, 0x00eb48, 0x00eb4b, 0x180010, 0x00eb4e, 0x00eb3f, 0x180012, 0x180014, 0x180144,
0x180142, 0x180143, 0x0289b0, 0x0f69fa, 0x180002, 0x00eb2a, 0x00eb2d, 0x00eb30, 0x00eb33, 0x00eb36,
0x00eb39, 0x00eb3c, 0x00e9bf, 0x180016, 0x180017, 0x180140, 0x180141, 0x00e9c5, 0x400018, 0x400019,
0x40001a, 0x400015, 0x400016, 0x400017, 0x400012, 0x400013, 0x400014, 0x40001b, 0x40001c, 0x40001d,
0x400022, 0x400023, 0x400024, 0x400025, 0x400021, 0x40001e, 0x40001f,
},
"Dark World": {
0x180147, 0x0ee185, 0x0330c7, 0x180148, 0x00eb1e, 0x00eb21, 0x00eb24, 0x00eb27, 0x180011, 0x180006,
0x00e980, 0x00e983, 0x00e9ec, 0x00e9ef, 0x00eda8, 0x180146, 0x00ea73, 0x00ea76, 0x00ea7c, 0x00ea7f,
0x00ea8b, 0x00eb51, 0x00eb54, 0x00eb5a, 0x00eb57, 0x400000, 0x400001, 0x400002, 0x400006, 0x400007,
0x400008, 0x400009, 0x40000a, 0x40000b, 0x40000f, 0x400010, 0x400011, 0x400003, 0x400004, 0x400005,
0x40000c, 0x40000d, 0x40000e,
},
"Hyrule Castle": {
0x00e974, 0x00eb0c, 0x00eb09, 0x00e96e, 0x00eb5d, 0x00eb60, 0x00eb63, 0x00ea79, 0x140037, 0x140034,
0x14000d, 0x14003d,
},
"Agahnims Tower": {
0x00eab5, 0x00eab2, 0x140061, 0x140052,
},
"Eastern Palace": {
0x00e977, 0x00e97d, 0x00e9b3, 0x00e9b9, 0x00e9f5, 0x180150, 0x14005b, 0x140049,
},
"Desert Palace": {
0x00e98f, 0x180160, 0x00e9b6, 0x00e9cb, 0x00e9c2, 0x180151, 0x140031, 0x14002b, 0x140028,
},
"Tower of Hera": {
0x180162, 0x00e9ad, 0x00e9e6, 0x00e9fb, 0x00e9f8, 0x180152
},
"Palace of Darkness": {
0x00ea5b, 0x00ea3d, 0x00ea49, 0x00ea37, 0x00ea3a, 0x00ea52, 0x00ea43, 0x00ea4c, 0x00ea4f, 0x00ea55,
0x00ea58, 0x00ea40, 0x00ea46, 0x180153,
},
"Swamp Palace": {
0x00ea9d, 0x00e986, 0x00e989, 0x00eaa0, 0x00eaa6, 0x00eaa3, 0x00eaa9, 0x00eaac, 0x00eaaf, 0x180154,
0x140019, 0x140016, 0x140013, 0x140010, 0x14000a,
},
"Thieves' Town": {
0x00ea04, 0x00ea01, 0x00ea07, 0x00ea0a, 0x00ea0d, 0x00ea10, 0x00ea13, 0x180156, 0x14005e, 0x14004f,
},
"Skull Woods": {
0x00e992, 0x00e99b, 0x00e998, 0x00e9a1, 0x00e9c8, 0x00e99e, 0x00e9fe, 0x180155, 0x14002e, 0x14001c,
},
"Ice Palace": {
0x00e9d4, 0x00e995, 0x00e9aa, 0x00e9e3, 0x00e9e0, 0x00e9a4, 0x00e9dd, 0x180157, 0x140004, 0x140022,
0x140025, 0x140046,
},
"Misery Mire": {
0x00ea67, 0x00ea6a, 0x00ea5e, 0x00ea61, 0x00e9da, 0x00ea64, 0x00ea6d, 0x180158, 0x140055, 0x14004c,
0x140064,
},
"Turtle Rock": {
0x00ea22, 0x00ea1c, 0x00ea1f, 0x00ea16, 0x00ea25, 0x00ea19, 0x00ea34, 0x00ea31, 0x00ea2e, 0x00ea2b,
0x00ea28, 0x180159, 0x140058, 0x140007,
},
"Ganons Tower": {
0x180161, 0x00ead9, 0x00eadc, 0x00eae2, 0x00eae5, 0x00eae8, 0x00eaeb, 0x00eaee, 0x00eab8, 0x00eabb,
0x00eabe, 0x00eac1, 0x00ead3, 0x00ead0, 0x00eac4, 0x00eac7, 0x00eaca, 0x00eacd, 0x00eadf, 0x00eadf,
0x00ead6, 0x00eaf4, 0x00eaf7, 0x00eaf1, 0x00eafd, 0x00eb00, 0x00eb03, 0x00eb06, 0x140040, 0x140043,
0x14003a, 0x14001f,
},
}
prepare_inventories(team, player, inventory, tracker_data)
regions = {
"Light World": {"checked": 0, "locations": []},
"Dark World": {"checked": 0, "locations": []},
"Hyrule Castle": {"checked": 0, "locations": []},
"Agahnims Tower": {"checked": 0, "locations": []},
"Eastern Palace": {"checked": 0, "locations": []},
"Desert Palace": {"checked": 0, "locations": []},
"Tower of Hera": {"checked": 0, "locations": []},
"Palace of Darkness": {"checked": 0, "locations": []},
"Skull Woods": {"checked": 0, "locations": []},
"Thieves' Town": {"checked": 0, "locations": []},
"Swamp Palace": {"checked": 0, "locations": []},
"Ice Palace": {"checked": 0, "locations": []},
"Misery Mire": {"checked": 0, "locations": []},
"Turtle Rock": {"checked": 0, "locations": []},
"Ganons Tower": {"checked": 0, "locations": []},
"Unknown": {"checked": 0, "locations": []},
region_name: {
"checked": sum(
1 for location in tracker_data._multidata["checks_in_area"][player][region_name]
if location in tracker_data.get_player_checked_locations(team, player)
),
"locations": [
(
tracker_data.location_id_to_name["A Link to the Past"][location],
location in tracker_data.get_player_checked_locations(team, player)
)
for location in tracker_data._multidata["checks_in_area"][player][region_name]
],
}
for region_name in known_regions
}
for location in tracker_data.get_player_locations(team, player):
location_name = tracker_data.location_id_to_name["A Link to the Past"][location]
location_checked = location in tracker_data.get_player_checked_locations(team, player)
for region, region_locations in known_regions.items():
if location in region_locations:
regions[region]["locations"].append((location_name, location_checked))
regions[region]["checked"] += 1 if location_checked else 0
break
else:
# New or missed location in the tables above. Add it to an "unknown region", so it's not forgotten.
regions["Unknown"]["locations"].append((location_name, location_checked))
regions["Unknown"]["checked"] += 1 if location_checked else 0
# Sort locations in regions by name
for region in regions:
regions[region]["locations"].sort()
@@ -867,6 +625,7 @@ if "A Link to the Past" in network_data_package["games"]:
inventory=inventory,
player_name=tracker_data.get_player_name(team, player),
regions=regions,
known_regions=known_regions,
)
_multiworld_trackers["A Link to the Past"] = render_ALinkToThePast_multiworld_tracker