Lingo: Add trap weights option (#2837)
This commit is contained in:
parent
11b32f17ab
commit
44988d430d
|
@ -6,7 +6,7 @@ from logging import warning
|
|||
from BaseClasses import Item, ItemClassification, Tutorial
|
||||
from worlds.AutoWorld import WebWorld, World
|
||||
from .datatypes import Room, RoomEntrance
|
||||
from .items import ALL_ITEM_TABLE, ITEMS_BY_GROUP, LingoItem
|
||||
from .items import ALL_ITEM_TABLE, ITEMS_BY_GROUP, TRAP_ITEMS, LingoItem
|
||||
from .locations import ALL_LOCATION_TABLE, LOCATIONS_BY_GROUP
|
||||
from .options import LingoOptions
|
||||
from .player_logic import LingoPlayerLogic
|
||||
|
@ -91,10 +91,23 @@ class LingoWorld(World):
|
|||
pool.append(self.create_item("Puzzle Skip"))
|
||||
|
||||
if traps:
|
||||
traps_list = ["Slowness Trap", "Iceland Trap", "Atbash Trap"]
|
||||
total_weight = sum(self.options.trap_weights.values())
|
||||
|
||||
for i in range(0, traps):
|
||||
pool.append(self.create_item(traps_list[i % len(traps_list)]))
|
||||
if total_weight == 0:
|
||||
raise Exception("Sum of trap weights must be at least one.")
|
||||
|
||||
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]
|
||||
for i in range(0, trap_difference):
|
||||
trap_counts[allowed_traps[i % len(allowed_traps)]] += 1
|
||||
|
||||
for name, count in trap_counts.items():
|
||||
for i in range(0, count):
|
||||
pool.append(self.create_item(name))
|
||||
|
||||
self.multiworld.itempool += pool
|
||||
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
from typing import Dict, List, NamedTuple, Optional, TYPE_CHECKING
|
||||
|
||||
from BaseClasses import Item, ItemClassification
|
||||
from .options import ShuffleDoors
|
||||
from .static_logic import DOORS_BY_ROOM, PROGRESSION_BY_ROOM, PROGRESSIVE_ITEMS, get_door_group_item_id, \
|
||||
get_door_item_id, get_progressive_item_id, get_special_item_id
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from . import LingoWorld
|
||||
|
||||
|
||||
class ItemData(NamedTuple):
|
||||
"""
|
||||
|
@ -19,20 +15,6 @@ class ItemData(NamedTuple):
|
|||
has_doors: bool
|
||||
painting_ids: List[str]
|
||||
|
||||
def should_include(self, world: "LingoWorld") -> bool:
|
||||
if self.mode == "colors":
|
||||
return world.options.shuffle_colors > 0
|
||||
elif self.mode == "doors":
|
||||
return world.options.shuffle_doors != ShuffleDoors.option_none
|
||||
elif self.mode == "complex door":
|
||||
return world.options.shuffle_doors == ShuffleDoors.option_complex
|
||||
elif self.mode == "door group":
|
||||
return world.options.shuffle_doors == ShuffleDoors.option_simple
|
||||
elif self.mode == "special":
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
class LingoItem(Item):
|
||||
"""
|
||||
|
@ -44,6 +26,8 @@ class LingoItem(Item):
|
|||
ALL_ITEM_TABLE: Dict[str, ItemData] = {}
|
||||
ITEMS_BY_GROUP: Dict[str, List[str]] = {}
|
||||
|
||||
TRAP_ITEMS: List[str] = ["Slowness Trap", "Iceland Trap", "Atbash Trap"]
|
||||
|
||||
|
||||
def load_item_data():
|
||||
global ALL_ITEM_TABLE, ITEMS_BY_GROUP
|
||||
|
@ -87,9 +71,7 @@ def load_item_data():
|
|||
"The Feeling of Being Lost": ItemClassification.filler,
|
||||
"Wanderlust": ItemClassification.filler,
|
||||
"Empty White Hallways": ItemClassification.filler,
|
||||
"Slowness Trap": ItemClassification.trap,
|
||||
"Iceland Trap": ItemClassification.trap,
|
||||
"Atbash Trap": ItemClassification.trap,
|
||||
**{trap_name: ItemClassification.trap for trap_name in TRAP_ITEMS},
|
||||
"Puzzle Skip": ItemClassification.useful,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
from dataclasses import dataclass
|
||||
|
||||
from Options import Toggle, Choice, DefaultOnToggle, Range, PerGameCommonOptions, StartInventoryPool
|
||||
from schema import And, Schema
|
||||
|
||||
from Options import Toggle, Choice, DefaultOnToggle, Range, PerGameCommonOptions, StartInventoryPool, OptionDict
|
||||
from worlds.lingo.items import TRAP_ITEMS
|
||||
|
||||
|
||||
class ShuffleDoors(Choice):
|
||||
|
@ -107,6 +110,14 @@ class TrapPercentage(Range):
|
|||
default = 20
|
||||
|
||||
|
||||
class TrapWeights(OptionDict):
|
||||
"""Specify the distribution of traps that should be placed into the pool.
|
||||
If you don't want a specific type of trap, set the weight to zero."""
|
||||
display_name = "Trap Weights"
|
||||
schema = Schema({trap_name: And(int, lambda n: n >= 0) for trap_name in TRAP_ITEMS})
|
||||
default = {trap_name: 1 for trap_name in TRAP_ITEMS}
|
||||
|
||||
|
||||
class PuzzleSkipPercentage(Range):
|
||||
"""Replaces junk items with puzzle skips, at the specified rate."""
|
||||
display_name = "Puzzle Skip Percentage"
|
||||
|
@ -134,6 +145,7 @@ class LingoOptions(PerGameCommonOptions):
|
|||
level_2_requirement: Level2Requirement
|
||||
early_color_hallways: EarlyColorHallways
|
||||
trap_percentage: TrapPercentage
|
||||
trap_weights: TrapWeights
|
||||
puzzle_skip_percentage: PuzzleSkipPercentage
|
||||
death_link: DeathLink
|
||||
start_inventory_from_pool: StartInventoryPool
|
||||
|
|
|
@ -2,7 +2,7 @@ from enum import Enum
|
|||
from typing import Dict, List, NamedTuple, Optional, Set, Tuple, TYPE_CHECKING
|
||||
|
||||
from .datatypes import Door, RoomAndDoor, RoomAndPanel
|
||||
from .items import ALL_ITEM_TABLE
|
||||
from .items import ALL_ITEM_TABLE, ItemData
|
||||
from .locations import ALL_LOCATION_TABLE, LocationClassification
|
||||
from .options import LocationChecks, ShuffleDoors, VictoryCondition
|
||||
from .static_logic import DOORS_BY_ROOM, PAINTINGS, PAINTING_ENTRANCES, PAINTING_EXITS, \
|
||||
|
@ -58,6 +58,21 @@ def should_split_progression(progression_name: str, world: "LingoWorld") -> Prog
|
|||
return ProgressiveItemBehavior.PROGRESSIVE
|
||||
|
||||
|
||||
def should_include_item(item: ItemData, world: "LingoWorld") -> bool:
|
||||
if item.mode == "colors":
|
||||
return world.options.shuffle_colors > 0
|
||||
elif item.mode == "doors":
|
||||
return world.options.shuffle_doors != ShuffleDoors.option_none
|
||||
elif item.mode == "complex door":
|
||||
return world.options.shuffle_doors == ShuffleDoors.option_complex
|
||||
elif item.mode == "door group":
|
||||
return world.options.shuffle_doors == ShuffleDoors.option_simple
|
||||
elif item.mode == "special":
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
class LingoPlayerLogic:
|
||||
"""
|
||||
Defines logic after a player's options have been applied
|
||||
|
@ -212,7 +227,7 @@ class LingoPlayerLogic:
|
|||
|
||||
# Instantiate all real items.
|
||||
for name, item in ALL_ITEM_TABLE.items():
|
||||
if item.should_include(world):
|
||||
if should_include_item(item, world):
|
||||
self.real_items.append(name)
|
||||
|
||||
# Calculate the requirements for the fake pilgrimage.
|
||||
|
|
Loading…
Reference in New Issue