Skip to content

Commit 49555c1

Browse files
hatkirbyEmilyV99
authored andcommitted
Lingo: Pre-compile datafile to improve loading time (ArchipelagoMW#2829)
1 parent 5ef1f76 commit 49555c1

13 files changed

+626
-515
lines changed

worlds/lingo/__init__.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55

66
from BaseClasses import Item, ItemClassification, Tutorial
77
from worlds.AutoWorld import WebWorld, World
8+
from .datatypes import Room, RoomEntrance
89
from .items import ALL_ITEM_TABLE, LingoItem
910
from .locations import ALL_LOCATION_TABLE
1011
from .options import LingoOptions
1112
from .player_logic import LingoPlayerLogic
1213
from .regions import create_regions
13-
from .static_logic import Room, RoomEntrance
1414

1515

1616
class LingoWebWorld(WebWorld):
@@ -100,9 +100,9 @@ def create_item(self, name: str) -> Item:
100100
item = ALL_ITEM_TABLE[name]
101101

102102
classification = item.classification
103-
if hasattr(self, "options") and self.options.shuffle_paintings and len(item.painting_ids) > 0\
104-
and len(item.door_ids) == 0 and all(painting_id not in self.player_logic.painting_mapping
105-
for painting_id in item.painting_ids)\
103+
if hasattr(self, "options") and self.options.shuffle_paintings and len(item.painting_ids) > 0 \
104+
and not item.has_doors and all(painting_id not in self.player_logic.painting_mapping
105+
for painting_id in item.painting_ids) \
106106
and "pilgrim_painting2" not in item.painting_ids:
107107
# If this is a "door" that just moves one or more paintings, and painting shuffle is on and those paintings
108108
# go nowhere, then this item should not be progression. The Pilgrim Room painting is special and needs to be

worlds/lingo/data/README.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# lingo data
2+
3+
The source of truth for the Lingo randomizer is (currently) the LL1.yaml and ids.yaml files located here. These files are used by the generator, the game client, and the tracker, in order to have logic that is consistent across them all.
4+
5+
The generator does not actually read in the yaml files. Instead, a compiled datafile called generated.dat is also located in this directory. If you update LL1.yaml and/or ids.yaml, you must also regenerate the datafile using `python worlds/lingo/utils/pickle_static_data.py`. A unit test will fail if you don't.

worlds/lingo/data/generated.dat

127 KB
Binary file not shown.

worlds/lingo/datatypes.py

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
from typing import List, NamedTuple, Optional
2+
3+
4+
class RoomAndDoor(NamedTuple):
5+
room: Optional[str]
6+
door: str
7+
8+
9+
class RoomAndPanel(NamedTuple):
10+
room: Optional[str]
11+
panel: str
12+
13+
14+
class RoomEntrance(NamedTuple):
15+
room: str # source room
16+
door: Optional[RoomAndDoor]
17+
painting: bool
18+
19+
20+
class Room(NamedTuple):
21+
name: str
22+
entrances: List[RoomEntrance]
23+
24+
25+
class Door(NamedTuple):
26+
name: str
27+
item_name: str
28+
location_name: Optional[str]
29+
panels: Optional[List[RoomAndPanel]]
30+
skip_location: bool
31+
skip_item: bool
32+
has_doors: bool
33+
painting_ids: List[str]
34+
event: bool
35+
group: Optional[str]
36+
include_reduce: bool
37+
junk_item: bool
38+
39+
40+
class Panel(NamedTuple):
41+
required_rooms: List[str]
42+
required_doors: List[RoomAndDoor]
43+
required_panels: List[RoomAndPanel]
44+
colors: List[str]
45+
check: bool
46+
event: bool
47+
exclude_reduce: bool
48+
achievement: bool
49+
non_counting: bool
50+
51+
52+
class Painting(NamedTuple):
53+
id: str
54+
room: str
55+
enter_only: bool
56+
exit_only: bool
57+
required: bool
58+
required_when_no_doors: bool
59+
required_door: Optional[RoomAndDoor]
60+
disable: bool
61+
req_blocked: bool
62+
req_blocked_when_no_doors: bool
63+
64+
65+
class Progression(NamedTuple):
66+
item_name: str
67+
index: int

worlds/lingo/items.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class ItemData(NamedTuple):
1616
code: int
1717
classification: ItemClassification
1818
mode: Optional[str]
19-
door_ids: List[str]
19+
has_doors: bool
2020
painting_ids: List[str]
2121

2222
def should_include(self, world: "LingoWorld") -> bool:
@@ -61,19 +61,19 @@ def load_item_data():
6161
door_mode = "doors"
6262
else:
6363
door_mode = "complex door"
64-
door_groups.setdefault(door.group, []).extend(door.door_ids)
64+
door_groups.setdefault(door.group, [])
6565

6666
if room_name in PROGRESSION_BY_ROOM and door_name in PROGRESSION_BY_ROOM[room_name]:
6767
door_mode = "special"
6868

6969
ALL_ITEM_TABLE[door.item_name] = \
7070
ItemData(get_door_item_id(room_name, door_name),
7171
ItemClassification.filler if door.junk_item else ItemClassification.progression, door_mode,
72-
door.door_ids, door.painting_ids)
72+
door.has_doors, door.painting_ids)
7373

7474
for group, group_door_ids in door_groups.items():
7575
ALL_ITEM_TABLE[group] = ItemData(get_door_group_item_id(group),
76-
ItemClassification.progression, "door group", group_door_ids, [])
76+
ItemClassification.progression, "door group", True, [])
7777

7878
special_items: Dict[str, ItemClassification] = {
7979
":)": ItemClassification.filler,
@@ -88,11 +88,11 @@ def load_item_data():
8888

8989
for item_name, classification in special_items.items():
9090
ALL_ITEM_TABLE[item_name] = ItemData(get_special_item_id(item_name), classification,
91-
"special", [], [])
91+
"special", False, [])
9292

9393
for item_name in PROGRESSIVE_ITEMS:
9494
ALL_ITEM_TABLE[item_name] = ItemData(get_progressive_item_id(item_name),
95-
ItemClassification.progression, "special", [], [])
95+
ItemClassification.progression, "special", False, [])
9696

9797

9898
# Initialize the item data at module scope.

worlds/lingo/locations.py

+2-9
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
from typing import Dict, List, NamedTuple
33

44
from BaseClasses import Location
5-
from .static_logic import DOORS_BY_ROOM, PANELS_BY_ROOM, RoomAndPanel, get_door_location_id, get_panel_location_id
5+
from .datatypes import RoomAndPanel
6+
from .static_logic import DOORS_BY_ROOM, PANELS_BY_ROOM, get_door_location_id, get_panel_location_id
67

78

89
class LocationClassification(Flag):
@@ -20,14 +21,6 @@ class LocationData(NamedTuple):
2021
panels: List[RoomAndPanel]
2122
classification: LocationClassification
2223

23-
def panel_ids(self):
24-
ids = set()
25-
for panel in self.panels:
26-
effective_room = self.room if panel.room is None else panel.room
27-
panel_data = PANELS_BY_ROOM[effective_room][panel.panel]
28-
ids = ids | set(panel_data.internal_ids)
29-
return ids
30-
3124

3225
class LingoLocation(Location):
3326
"""

worlds/lingo/player_logic.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
from enum import Enum
22
from typing import Dict, List, NamedTuple, Optional, Set, Tuple, TYPE_CHECKING
33

4+
from .datatypes import Door, RoomAndDoor, RoomAndPanel
45
from .items import ALL_ITEM_TABLE
56
from .locations import ALL_LOCATION_TABLE, LocationClassification
67
from .options import LocationChecks, ShuffleDoors, VictoryCondition
7-
from .static_logic import DOORS_BY_ROOM, Door, PAINTINGS, PAINTINGS_BY_ROOM, PAINTING_ENTRANCES, PAINTING_EXITS, \
8-
PANELS_BY_ROOM, PROGRESSION_BY_ROOM, REQUIRED_PAINTING_ROOMS, REQUIRED_PAINTING_WHEN_NO_DOORS_ROOMS, RoomAndDoor, \
9-
RoomAndPanel
8+
from .static_logic import DOORS_BY_ROOM, PAINTINGS, PAINTING_ENTRANCES, PAINTING_EXITS, \
9+
PANELS_BY_ROOM, PROGRESSION_BY_ROOM, REQUIRED_PAINTING_ROOMS, REQUIRED_PAINTING_WHEN_NO_DOORS_ROOMS
1010

1111
if TYPE_CHECKING:
1212
from . import LingoWorld
@@ -279,8 +279,9 @@ def __init__(self, world: "LingoWorld"):
279279

280280
# When painting shuffle is off, most Starting Room paintings give color hallways access. The Wondrous's
281281
# painting does not, but it gives access to SHRINK and WELCOME BACK.
282-
for painting_obj in PAINTINGS_BY_ROOM["Starting Room"]:
283-
if not painting_obj.enter_only or painting_obj.required_door is None:
282+
for painting_obj in PAINTINGS.values():
283+
if not painting_obj.enter_only or painting_obj.required_door is None\
284+
or painting_obj.room != "Starting Room":
284285
continue
285286

286287
# If painting shuffle is on, we only want to consider paintings that actually go somewhere.

worlds/lingo/regions.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
from typing import Dict, Optional, TYPE_CHECKING
22

33
from BaseClasses import Entrance, ItemClassification, Region
4+
from .datatypes import Room, RoomAndDoor
45
from .items import LingoItem
56
from .locations import LingoLocation
67
from .player_logic import LingoPlayerLogic
78
from .rules import lingo_can_use_entrance, make_location_lambda
8-
from .static_logic import ALL_ROOMS, PAINTINGS, Room, RoomAndDoor
9+
from .static_logic import ALL_ROOMS, PAINTINGS
910

1011
if TYPE_CHECKING:
1112
from . import LingoWorld

worlds/lingo/rules.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from typing import TYPE_CHECKING
22

33
from BaseClasses import CollectionState
4+
from .datatypes import RoomAndDoor
45
from .player_logic import AccessRequirements, LingoPlayerLogic, PlayerLocation
5-
from .static_logic import PROGRESSION_BY_ROOM, PROGRESSIVE_ITEMS, RoomAndDoor
6+
from .static_logic import PROGRESSION_BY_ROOM, PROGRESSIVE_ITEMS
67

78
if TYPE_CHECKING:
89
from . import LingoWorld

0 commit comments

Comments
 (0)