about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorStar Rauchenberger <fefferburbia@gmail.com>2025-09-13 11:34:49 -0400
committerStar Rauchenberger <fefferburbia@gmail.com>2025-09-13 11:34:49 -0400
commitc456854263be17264aeb8446986bc401d3921f33 (patch)
treea5c26c985f3f8dc1270f06f36ecc1dcb85385e6b
parentc909a4f022d252dc0da6b30c64e76cdfe9537460 (diff)
downloadlingo2-archipelago-c456854263be17264aeb8446986bc401d3921f33.tar.gz
lingo2-archipelago-c456854263be17264aeb8446986bc401d3921f33.tar.bz2
lingo2-archipelago-c456854263be17264aeb8446986bc401d3921f33.zip
Added anti collectable traps
-rw-r--r--apworld/__init__.py17
-rw-r--r--apworld/items.py2
-rw-r--r--apworld/options.py11
-rw-r--r--apworld/static_logic.py12
-rw-r--r--data/ids.yaml26
-rw-r--r--data/metadata.txtpb27
6 files changed, 92 insertions, 3 deletions
diff --git a/apworld/__init__.py b/apworld/__init__.py index 54f870f..8b2e42e 100644 --- a/apworld/__init__.py +++ b/apworld/__init__.py
@@ -3,7 +3,7 @@ Archipelago init file for Lingo 2
3""" 3"""
4from BaseClasses import ItemClassification, Item, Tutorial 4from BaseClasses import ItemClassification, Item, Tutorial
5from worlds.AutoWorld import WebWorld, World 5from worlds.AutoWorld import WebWorld, World
6from .items import Lingo2Item 6from .items import Lingo2Item, ANTI_COLLECTABLE_TRAPS
7from .options import Lingo2Options 7from .options import Lingo2Options
8from .player_logic import Lingo2PlayerLogic 8from .player_logic import Lingo2PlayerLogic
9from .regions import create_regions 9from .regions import create_regions
@@ -62,6 +62,20 @@ class Lingo2World(World):
62 total_locations = sum(len(locs) for locs in self.player_logic.locations_by_room.values()) 62 total_locations = sum(len(locs) for locs in self.player_logic.locations_by_room.values())
63 63
64 item_difference = total_locations - len(pool) 64 item_difference = total_locations - len(pool)
65
66 if self.options.trap_percentage > 0:
67 num_traps = int(item_difference * self.options.trap_percentage / 100)
68 item_difference = item_difference - num_traps
69
70 trap_names = []
71 trap_weights = []
72 for letter_name, weight in self.static_logic.letter_weights.items():
73 trap_names.append(f"Anti {letter_name}")
74 trap_weights.append(weight)
75
76 bad_letters = self.random.choices(trap_names, weights=trap_weights, k=num_traps)
77 pool += [self.create_item(trap_name) for trap_name in bad_letters]
78
65 for i in range(0, item_difference): 79 for i in range(0, item_difference):
66 pool.append(self.create_item(self.get_filler_item_name())) 80 pool.append(self.create_item(self.get_filler_item_name()))
67 81
@@ -69,6 +83,7 @@ class Lingo2World(World):
69 83
70 def create_item(self, name: str) -> Item: 84 def create_item(self, name: str) -> Item:
71 return Lingo2Item(name, ItemClassification.filler if name == self.get_filler_item_name() else 85 return Lingo2Item(name, ItemClassification.filler if name == self.get_filler_item_name() else
86 ItemClassification.trap if name in ANTI_COLLECTABLE_TRAPS else
72 ItemClassification.progression, 87 ItemClassification.progression,
73 self.item_name_to_id.get(name), self.player) 88 self.item_name_to_id.get(name), self.player)
74 89
diff --git a/apworld/items.py b/apworld/items.py index 32568a3..28158c3 100644 --- a/apworld/items.py +++ b/apworld/items.py
@@ -27,3 +27,5 @@ SYMBOL_ITEMS: dict[data_pb2.PuzzleSymbol, str] = {
27 data_pb2.PuzzleSymbol.LINGO: "Lingo Symbol", 27 data_pb2.PuzzleSymbol.LINGO: "Lingo Symbol",
28 data_pb2.PuzzleSymbol.QUESTION: "Question Symbol", 28 data_pb2.PuzzleSymbol.QUESTION: "Question Symbol",
29} 29}
30
31ANTI_COLLECTABLE_TRAPS: list[str] = [f"Anti {letter}" for letter in "ABCDEFGHIJKLMNOPQRSTUVWXYZ"]
diff --git a/apworld/options.py b/apworld/options.py index 4f0b32a..52d2034 100644 --- a/apworld/options.py +++ b/apworld/options.py
@@ -1,6 +1,6 @@
1from dataclasses import dataclass 1from dataclasses import dataclass
2 2
3from Options import PerGameCommonOptions, Toggle, Choice, DefaultOnToggle 3from Options import PerGameCommonOptions, Toggle, Choice, DefaultOnToggle, Range
4 4
5 5
6class ShuffleDoors(DefaultOnToggle): 6class ShuffleDoors(DefaultOnToggle):
@@ -126,6 +126,14 @@ class VictoryCondition(Choice):
126 option_white_ending = 12 126 option_white_ending = 12
127 127
128 128
129class TrapPercentage(Range):
130 """Replaces junk items with traps, at the specified rate."""
131 display_name = "Trap Percentage"
132 range_start = 0
133 range_end = 100
134 default = 0
135
136
129@dataclass 137@dataclass
130class Lingo2Options(PerGameCommonOptions): 138class Lingo2Options(PerGameCommonOptions):
131 shuffle_doors: ShuffleDoors 139 shuffle_doors: ShuffleDoors
@@ -137,3 +145,4 @@ class Lingo2Options(PerGameCommonOptions):
137 cyan_door_behavior: CyanDoorBehavior 145 cyan_door_behavior: CyanDoorBehavior
138 daedalus_roof_access: DaedalusRoofAccess 146 daedalus_roof_access: DaedalusRoofAccess
139 victory_condition: VictoryCondition 147 victory_condition: VictoryCondition
148 trap_percentage: TrapPercentage
diff --git a/apworld/static_logic.py b/apworld/static_logic.py index 1017ec7..2700601 100644 --- a/apworld/static_logic.py +++ b/apworld/static_logic.py
@@ -1,5 +1,5 @@
1from .generated import data_pb2 as data_pb2 1from .generated import data_pb2 as data_pb2
2from .items import SYMBOL_ITEMS 2from .items import SYMBOL_ITEMS, ANTI_COLLECTABLE_TRAPS
3import pkgutil 3import pkgutil
4 4
5class Lingo2StaticLogic: 5class Lingo2StaticLogic:
@@ -12,11 +12,14 @@ class Lingo2StaticLogic:
12 item_name_groups: dict[str, list[str]] 12 item_name_groups: dict[str, list[str]]
13 location_name_groups: dict[str, list[str]] 13 location_name_groups: dict[str, list[str]]
14 14
15 letter_weights: dict[str, int]
16
15 def __init__(self): 17 def __init__(self):
16 self.item_id_to_name = {} 18 self.item_id_to_name = {}
17 self.location_id_to_name = {} 19 self.location_id_to_name = {}
18 self.item_name_groups = {} 20 self.item_name_groups = {}
19 self.location_name_groups = {} 21 self.location_name_groups = {}
22 self.letter_weights = {}
20 23
21 file = pkgutil.get_data(__name__, "generated/data.binpb") 24 file = pkgutil.get_data(__name__, "generated/data.binpb")
22 self.objects = data_pb2.AllObjects() 25 self.objects = data_pb2.AllObjects()
@@ -68,9 +71,16 @@ class Lingo2StaticLogic:
68 for symbol_name in SYMBOL_ITEMS.values(): 71 for symbol_name in SYMBOL_ITEMS.values():
69 self.item_id_to_name[self.objects.special_ids[symbol_name]] = symbol_name 72 self.item_id_to_name[self.objects.special_ids[symbol_name]] = symbol_name
70 73
74 for trap_name in ANTI_COLLECTABLE_TRAPS:
75 self.item_id_to_name[self.objects.special_ids[trap_name]] = trap_name
76
71 self.item_name_to_id = {name: ap_id for ap_id, name in self.item_id_to_name.items()} 77 self.item_name_to_id = {name: ap_id for ap_id, name in self.item_id_to_name.items()}
72 self.location_name_to_id = {name: ap_id for ap_id, name in self.location_id_to_name.items()} 78 self.location_name_to_id = {name: ap_id for ap_id, name in self.location_id_to_name.items()}
73 79
80 for panel in self.objects.panels:
81 for letter in panel.answer.upper():
82 self.letter_weights[letter] = self.letter_weights.get(letter, 0) + 1
83
74 def get_door_item_name(self, door: data_pb2.Door) -> str: 84 def get_door_item_name(self, door: data_pb2.Door) -> str:
75 return f"{self.get_map_object_map_name(door)} - {door.name}" 85 return f"{self.get_map_object_map_name(door)} - {door.name}"
76 86
diff --git a/data/ids.yaml b/data/ids.yaml index 2eba46a..2358b67 100644 --- a/data/ids.yaml +++ b/data/ids.yaml
@@ -3842,6 +3842,32 @@ special:
3842 A Job Well Done: 1160 3842 A Job Well Done: 1160
3843 Age Symbol: 2791 3843 Age Symbol: 2791
3844 Anagram Symbol: 2792 3844 Anagram Symbol: 2792
3845 Anti A: 2814
3846 Anti B: 2815
3847 Anti C: 2816
3848 Anti D: 2817
3849 Anti E: 2818
3850 Anti F: 2819
3851 Anti G: 2820
3852 Anti H: 2821
3853 Anti I: 2822
3854 Anti J: 2823
3855 Anti K: 2824
3856 Anti L: 2825
3857 Anti M: 2826
3858 Anti N: 2827
3859 Anti O: 2828
3860 Anti P: 2829
3861 Anti Q: 2830
3862 Anti R: 2831
3863 Anti S: 2832
3864 Anti T: 2833
3865 Anti U: 2834
3866 Anti V: 2835
3867 Anti W: 2836
3868 Anti X: 2837
3869 Anti Y: 2838
3870 Anti Z: 2839
3845 Boxes Symbol: 2793 3871 Boxes Symbol: 2793
3846 Cross Symbol: 2794 3872 Cross Symbol: 2794
3847 Eval Symbol: 2795 3873 Eval Symbol: 2795
diff --git a/data/metadata.txtpb b/data/metadata.txtpb index 57255e6..8b53601 100644 --- a/data/metadata.txtpb +++ b/data/metadata.txtpb
@@ -21,3 +21,30 @@ special_names: "Stars Symbol"
21special_names: "Sun Symbol" 21special_names: "Sun Symbol"
22special_names: "Sweet Symbol" 22special_names: "Sweet Symbol"
23special_names: "Zero Symbol" 23special_names: "Zero Symbol"
24# Anti collectable traps
25special_names: "Anti A"
26special_names: "Anti B"
27special_names: "Anti C"
28special_names: "Anti D"
29special_names: "Anti E"
30special_names: "Anti F"
31special_names: "Anti G"
32special_names: "Anti H"
33special_names: "Anti I"
34special_names: "Anti J"
35special_names: "Anti K"
36special_names: "Anti L"
37special_names: "Anti M"
38special_names: "Anti N"
39special_names: "Anti O"
40special_names: "Anti P"
41special_names: "Anti Q"
42special_names: "Anti R"
43special_names: "Anti S"
44special_names: "Anti T"
45special_names: "Anti U"
46special_names: "Anti V"
47special_names: "Anti W"
48special_names: "Anti X"
49special_names: "Anti Y"
50special_names: "Anti Z"