diff --git a/worlds/lingo/__init__.py b/worlds/lingo/__init__.py index 05509a39..c27aaed7 100644 --- a/worlds/lingo/__init__.py +++ b/worlds/lingo/__init__.py @@ -3,7 +3,7 @@ Archipelago init file for Lingo """ from logging import warning -from BaseClasses import CollectionState, Item, ItemClassification, Tutorial +from BaseClasses import CollectionState, Item, ItemClassification, Tutorial, Location, LocationProgressType from Options import OptionError from worlds.AutoWorld import WebWorld, World from .datatypes import Room, RoomEntrance @@ -80,10 +80,6 @@ class LingoWorld(World): for item in self.player_logic.real_items: state.collect(self.create_item(item), True) - # Exception to the above: a forced good item is not considered a "real item", but needs to be here anyway. - if self.player_logic.forced_good_item != "": - state.collect(self.create_item(self.player_logic.forced_good_item), True) - all_locations = self.multiworld.get_locations(self.player) state.sweep_for_advancements(locations=all_locations) @@ -105,11 +101,6 @@ class LingoWorld(World): def create_items(self): pool = [self.create_item(name) for name in self.player_logic.real_items] - if self.player_logic.forced_good_item != "": - new_item = self.create_item(self.player_logic.forced_good_item) - location_obj = self.multiworld.get_location("Second Room - Good Luck", self.player) - location_obj.place_locked_item(new_item) - item_difference = len(self.player_logic.real_locations) - len(pool) if item_difference: trap_percentage = self.options.trap_percentage @@ -138,7 +129,7 @@ class LingoWorld(World): trap_counts = {name: int(weight * traps / total_weight) for name, weight in self.options.trap_weights.items()} - + trap_difference = traps - sum(trap_counts.values()) if trap_difference > 0: allowed_traps = [name for name in TRAP_ITEMS if self.options.trap_weights[name] > 0] @@ -169,6 +160,30 @@ class LingoWorld(World): def set_rules(self): self.multiworld.completion_condition[self.player] = lambda state: state.has("Victory", self.player) + def place_good_item(self, progitempool: list[Item], fill_locations: list[Location]): + if len(self.player_logic.good_item_options) == 0: + return + + good_location = self.get_location("Second Room - Good Luck") + if good_location.progress_type == LocationProgressType.EXCLUDED or good_location not in fill_locations: + return + + good_items = list(filter(lambda progitem: progitem.player == self.player and + progitem.name in self.player_logic.good_item_options, progitempool)) + + if len(good_items) == 0: + return + + good_item = self.random.choice(good_items) + good_location.place_locked_item(good_item) + + progitempool.remove(good_item) + fill_locations.remove(good_location) + + def fill_hook(self, progitempool: list[Item], usefulitempool: list[Item], filleritempool: list[Item], + fill_locations: list[Location]): + self.place_good_item(progitempool, fill_locations) + def fill_slot_data(self): slot_options = [ "death_link", "victory_condition", "shuffle_colors", "shuffle_doors", "shuffle_paintings", "shuffle_panels", diff --git a/worlds/lingo/player_logic.py b/worlds/lingo/player_logic.py index 83217d73..9363dfed 100644 --- a/worlds/lingo/player_logic.py +++ b/worlds/lingo/player_logic.py @@ -95,7 +95,7 @@ class LingoPlayerLogic: painting_mapping: Dict[str, str] - forced_good_item: str + good_item_options: List[str] panel_reqs: Dict[str, Dict[str, AccessRequirements]] door_reqs: Dict[str, Dict[str, AccessRequirements]] @@ -151,7 +151,7 @@ class LingoPlayerLogic: self.mastery_location = "" self.level_2_location = "" self.painting_mapping = {} - self.forced_good_item = "" + self.good_item_options = [] self.panel_reqs = {} self.door_reqs = {} self.mastery_reqs = [] @@ -344,23 +344,23 @@ class LingoPlayerLogic: # Starting Room - Back Right Door gives access to OPEN and DEAD END. # Starting Room - Exit Door gives access to OPEN and TRACE. - good_item_options: List[str] = ["Starting Room - Back Right Door", "Second Room - Exit Door"] + self.good_item_options = ["Starting Room - Back Right Door", "Second Room - Exit Door"] if not color_shuffle: if not world.options.enable_pilgrimage: # HOT CRUST and THIS. - good_item_options.append("Pilgrim Room - Sun Painting") + self.good_item_options.append("Pilgrim Room - Sun Painting") if world.options.group_doors: # WELCOME BACK, CLOCKWISE, and DRAWL + RUNS. - good_item_options.append("Welcome Back Doors") + self.good_item_options.append("Welcome Back Doors") else: # WELCOME BACK and CLOCKWISE. - good_item_options.append("Welcome Back Area - Shortcut to Starting Room") + self.good_item_options.append("Welcome Back Area - Shortcut to Starting Room") if world.options.group_doors: # Color hallways access (NOTE: reconsider when sunwarp shuffling exists). - good_item_options.append("Rhyme Room Doors") + self.good_item_options.append("Rhyme Room Doors") # When painting shuffle is off, most Starting Room paintings give color hallways access. The Wondrous's # painting does not, but it gives access to SHRINK and WELCOME BACK. @@ -376,30 +376,7 @@ class LingoPlayerLogic: continue pdoor = DOORS_BY_ROOM[painting_obj.required_door.room][painting_obj.required_door.door] - good_item_options.append(pdoor.item_name) - - # Copied from The Witness -- remove any plandoed items from the possible good items set. - for v in world.multiworld.plando_items[world.player]: - if v.get("from_pool", True): - for item_key in {"item", "items"}: - if item_key in v: - if type(v[item_key]) is str: - if v[item_key] in good_item_options: - good_item_options.remove(v[item_key]) - elif type(v[item_key]) is dict: - for item, weight in v[item_key].items(): - if weight and item in good_item_options: - good_item_options.remove(item) - else: - # Other type of iterable - for item in v[item_key]: - if item in good_item_options: - good_item_options.remove(item) - - if len(good_item_options) > 0: - self.forced_good_item = world.random.choice(good_item_options) - self.real_items.remove(self.forced_good_item) - self.real_locations.remove("Second Room - Good Luck") + self.good_item_options.append(pdoor.item_name) def randomize_paintings(self, world: "LingoWorld") -> bool: self.painting_mapping.clear()