about summary refs log tree commit diff stats
path: root/apworld
diff options
context:
space:
mode:
Diffstat (limited to 'apworld')
-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
4 files changed, 39 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