Timespinner: Make RisingTidesOverrides consistent with normal yaml behaviour. (#1474)

* Make RisingTidesOverrides consistent with normal yaml behaviour.

* Each of the options can be either string directly specifying the option, or dictionary.
* If dictionary, ensure that at least one of the options is greater than zero.

* Made keys optional

* A lot less copy/pasta.

---------

Co-authored-by: Jarno Westhof <jarnowesthof@gmail.com>
This commit is contained in:
CaitSith2 2023-02-22 17:11:27 -08:00 committed by GitHub
parent 0eb66957b1
commit cb3d40624c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 48 additions and 45 deletions

View File

@ -1,7 +1,7 @@
from typing import Dict, Union, List
from BaseClasses import MultiWorld
from Options import Toggle, DefaultOnToggle, DeathLink, Choice, Range, Option, OptionDict, OptionList
from schema import Schema, And, Optional
from schema import Schema, And, Optional, Or
class StartWithJewelryBox(Toggle):
@ -308,47 +308,44 @@ class RisingTides(Toggle):
display_name = "Rising Tides"
def rising_tide_option(location: str, with_save_point_option: bool = False) -> Dict[Optional, Or]:
if with_save_point_option:
return {
Optional(location): Or(
And({
Optional("Dry"): And(int, lambda n: n >= 0),
Optional("Flooded"): And(int, lambda n: n >= 0),
Optional("FloodedWithSavePointAvailable"): And(int, lambda n: n >= 0)
}, lambda d: any(v > 0 for v in d.values())),
"Dry",
"Flooded",
"FloodedWithSavePointAvailable")
}
else:
return {
Optional(location): Or(
And({
Optional("Dry"): And(int, lambda n: n >= 0),
Optional("Flooded"): And(int, lambda n: n >= 0)
}, lambda d: any(v > 0 for v in d.values())),
"Dry",
"Flooded")
}
class RisingTidesOverrides(OptionDict):
"""Odds for specific areas to be flooded or drained, only has effect when RisingTides is on.
Areas that are not specified will roll with the default 33% chance of getting flooded or drained"""
schema = Schema({
Optional("Xarion"): {
"Dry": And(int, lambda n: n >= 0),
"Flooded": And(int, lambda n: n >= 0)
},
Optional("Maw"): {
"Dry": And(int, lambda n: n >= 0),
"Flooded": And(int, lambda n: n >= 0)
},
Optional("AncientPyramidShaft"): {
"Dry": And(int, lambda n: n >= 0),
"Flooded": And(int, lambda n: n >= 0)
},
Optional("Sandman"): {
"Dry": And(int, lambda n: n >= 0),
"Flooded": And(int, lambda n: n >= 0)
},
Optional("CastleMoat"): {
"Dry": And(int, lambda n: n >= 0),
"Flooded": And(int, lambda n: n >= 0)
},
Optional("CastleBasement"): {
"Dry": And(int, lambda n: n >= 0),
"FloodedWithSavePointAvailable": And(int, lambda n: n >= 0),
"Flooded": And(int, lambda n: n >= 0)
},
Optional("CastleCourtyard"): {
"Dry": And(int, lambda n: n >= 0),
"Flooded": And(int, lambda n: n >= 0)
},
Optional("LakeDesolation"): {
"Dry": And(int, lambda n: n >= 0),
"Flooded": And(int, lambda n: n >= 0)
},
Optional("LakeSerene"): {
"Dry": And(int, lambda n: n >= 0),
"Flooded": And(int, lambda n: n >= 0)
}
**rising_tide_option("Xarion"),
**rising_tide_option("Maw"),
**rising_tide_option("AncientPyramidShaft"),
**rising_tide_option("Sandman"),
**rising_tide_option("CastleMoat"),
**rising_tide_option("CastleBasement", with_save_point_option=True),
**rising_tide_option("CastleCourtyard"),
**rising_tide_option("LakeDesolation"),
**rising_tide_option("LakeSerene")
})
display_name = "Rising Tides Overrides"
default = {

View File

@ -21,7 +21,7 @@ class PreCalculatedWeights:
dry_lake_serene: bool
def __init__(self, world: MultiWorld, player: int):
weights_overrrides: Dict[str, Dict[str, int]] = self.get_flood_weights_overrides(world, player)
weights_overrrides: Dict[str, Union[str, Dict[str, int]]] = self.get_flood_weights_overrides(world, player)
self.flood_basement, self.flood_basement_high = \
self.roll_flood_setting_with_available_save(world, player, weights_overrrides, "CastleBasement")
@ -87,8 +87,8 @@ class PreCalculatedWeights:
)
@staticmethod
def get_flood_weights_overrides( world: MultiWorld, player: int) -> Dict[str, int]:
weights_overrides_option: Union[int, Dict[str, Dict[str, int]]] = \
def get_flood_weights_overrides( world: MultiWorld, player: int) -> Dict[str, Union[str, Dict[str, int]]]:
weights_overrides_option: Union[int, Dict[str, Union[str, Dict[str, int]]]] = \
get_option_value(world, player, "RisingTidesOverrides")
if weights_overrides_option == 0:
@ -97,26 +97,32 @@ class PreCalculatedWeights:
return weights_overrides_option
@staticmethod
def roll_flood_setting(world: MultiWorld, player: int, weights: Dict[str, Dict[str, int]], key: str) -> bool:
def roll_flood_setting(world: MultiWorld, player: int, weights: Dict[str, Union[Dict[str, int], str]], key: str) -> bool:
if not world or not is_option_enabled(world, player, "RisingTides"):
return False
weights = weights[key] if key in weights else { "Dry": 67, "Flooded": 33 }
result: str = world.random.choices(list(weights.keys()), weights=list(map(int, weights.values())))[0]
if isinstance(weights, dict):
result: str = world.random.choices(list(weights.keys()), weights=list(map(int, weights.values())))[0]
else:
result: str = weights
return result == "Flooded"
@staticmethod
def roll_flood_setting_with_available_save(world: MultiWorld, player: int,
weights: Dict[str, Dict[str, int]], key: str) -> Tuple[bool, bool]:
weights: Dict[str, Union[Dict[str, int], str]], key: str) -> Tuple[bool, bool]:
if not world or not is_option_enabled(world, player, "RisingTides"):
return False, False
weights = weights[key] if key in weights else {"Dry": 66, "Flooded": 17, "FloodedWithSavePointAvailable": 17}
result: str = world.random.choices(list(weights.keys()), weights=list(map(int, weights.values())))[0]
if isinstance(weights, dict):
result: str = world.random.choices(list(weights.keys()), weights=list(map(int, weights.values())))[0]
else:
result: str = weights
if result == "Dry":
return False, False