The Witness: Panel Hunt Plando (#3549)

* Add panel hunt plando option

* Keys are strs

* oops

* better message

* ,

* this doesn ot need to be here

* don't replace pre picked panels

* Update options.py

* rebase error

* rebase error

* oops

* Mypy

* ruff

* another rebase error

* actually this is a stupid change too

* bring over that change™️

* Update entity_hunt.py

* Update entity_hunt.py

* Update entity_hunt.py
This commit is contained in:
NewSoupVi 2024-12-12 19:42:14 +01:00 committed by GitHub
parent f5e3677ef1
commit d7736950cd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 59 additions and 12 deletions

View File

@ -1,5 +1,5 @@
from collections import defaultdict from collections import defaultdict
from logging import debug from logging import debug, warning
from pprint import pformat from pprint import pformat
from typing import TYPE_CHECKING, Dict, List, Set, Tuple from typing import TYPE_CHECKING, Dict, List, Set, Tuple
@ -48,6 +48,8 @@ class EntityHuntPicker:
self.PRE_PICKED_HUNT_ENTITIES = pre_picked_entities.copy() self.PRE_PICKED_HUNT_ENTITIES = pre_picked_entities.copy()
self.HUNT_ENTITIES: Set[str] = set() self.HUNT_ENTITIES: Set[str] = set()
self._add_plandoed_hunt_panels_to_pre_picked()
self.ALL_ELIGIBLE_ENTITIES, self.ELIGIBLE_ENTITIES_PER_AREA = self._get_eligible_panels() self.ALL_ELIGIBLE_ENTITIES, self.ELIGIBLE_ENTITIES_PER_AREA = self._get_eligible_panels()
def pick_panel_hunt_panels(self, total_amount: int) -> Set[str]: def pick_panel_hunt_panels(self, total_amount: int) -> Set[str]:
@ -69,24 +71,51 @@ class EntityHuntPicker:
return self.HUNT_ENTITIES return self.HUNT_ENTITIES
def _entity_is_eligible(self, panel_hex: str) -> bool: def _entity_is_eligible(self, panel_hex: str, plando: bool = False) -> bool:
""" """
Determine whether an entity is eligible for entity hunt based on player options. Determine whether an entity is eligible for entity hunt based on player options.
""" """
panel_obj = static_witness_logic.ENTITIES_BY_HEX[panel_hex] panel_obj = static_witness_logic.ENTITIES_BY_HEX[panel_hex]
return ( if not self.player_logic.solvability_guaranteed(panel_hex) or panel_hex in self.player_logic.EXCLUDED_ENTITIES:
self.player_logic.solvability_guaranteed(panel_hex) if plando:
and panel_hex not in self.player_logic.EXCLUDED_ENTITIES warning(f"Panel {panel_obj['checkName']} is disabled / excluded and thus not eligible for panel hunt.")
and not ( return False
# Due to an edge case, Discards have to be on in disable_non_randomized even if Discard Shuffle is off.
# However, I don't think they should be hunt panels in this case. return plando or not (
self.player_options.disable_non_randomized_puzzles # Due to an edge case, Discards have to be on in disable_non_randomized even if Discard Shuffle is off.
and not self.player_options.shuffle_discarded_panels # However, I don't think they should be hunt panels in this case.
and panel_obj["locationType"] == "Discard" self.player_options.disable_non_randomized_puzzles
) and not self.player_options.shuffle_discarded_panels
and panel_obj["locationType"] == "Discard"
) )
def _add_plandoed_hunt_panels_to_pre_picked(self) -> None:
"""
Add panels the player explicitly specified to be included in panel hunt to the pre picked hunt panels.
Output a warning if a panel could not be added for some reason.
"""
# Plandoed hunt panels should be in random order, but deterministic by seed, so we sort, then shuffle
panels_to_plando = sorted(self.player_options.panel_hunt_plando.value)
self.random.shuffle(panels_to_plando)
for location_name in panels_to_plando:
entity_hex = static_witness_logic.ENTITIES_BY_NAME[location_name]["entity_hex"]
if entity_hex in self.PRE_PICKED_HUNT_ENTITIES:
continue
if self._entity_is_eligible(entity_hex, plando=True):
if len(self.PRE_PICKED_HUNT_ENTITIES) == self.player_options.panel_hunt_total:
warning(
f"Panel {location_name} could not be plandoed as a hunt panel for {self.player_name}'s world, "
f"because it would exceed their panel hunt total."
)
continue
self.PRE_PICKED_HUNT_ENTITIES.add(entity_hex)
def _get_eligible_panels(self) -> Tuple[List[str], Dict[str, Set[str]]]: def _get_eligible_panels(self) -> Tuple[List[str], Dict[str, Set[str]]]:
""" """
There are some entities that are not allowed for panel hunt for various technical of gameplay reasons. There are some entities that are not allowed for panel hunt for various technical of gameplay reasons.
@ -215,6 +244,10 @@ class EntityHuntPicker:
if good_entity in self.HUNT_ENTITIES or good_entity not in self.ALL_ELIGIBLE_ENTITIES: if good_entity in self.HUNT_ENTITIES or good_entity not in self.ALL_ELIGIBLE_ENTITIES:
continue continue
# ... and it's not a forced pick that should stay the same ...
if bad_entitiy in self.PRE_PICKED_HUNT_ENTITIES:
continue
# ... replace the bad entity with the good entity. # ... replace the bad entity with the good entity.
self.HUNT_ENTITIES.remove(bad_entitiy) self.HUNT_ENTITIES.remove(bad_entitiy)
self.HUNT_ENTITIES.add(good_entity) self.HUNT_ENTITIES.add(good_entity)

View File

@ -5,6 +5,7 @@ from schema import And, Schema
from Options import ( from Options import (
Choice, Choice,
DefaultOnToggle, DefaultOnToggle,
LocationSet,
OptionDict, OptionDict,
OptionError, OptionError,
OptionGroup, OptionGroup,
@ -17,6 +18,7 @@ from Options import (
from .data import static_logic as static_witness_logic from .data import static_logic as static_witness_logic
from .data.item_definition_classes import ItemCategory, WeightedItemDefinition from .data.item_definition_classes import ItemCategory, WeightedItemDefinition
from .entity_hunt import ALL_HUNTABLE_PANELS
class DisableNonRandomizedPuzzles(Toggle): class DisableNonRandomizedPuzzles(Toggle):
@ -268,6 +270,16 @@ class PanelHuntDiscourageSameAreaFactor(Range):
default = 40 default = 40
class PanelHuntPlando(LocationSet):
"""
Specify specific hunt panels you want for your panel hunt game.
"""
display_name = "Panel Hunt Plando"
valid_keys = [static_witness_logic.ENTITIES_BY_HEX[panel_hex]["checkName"] for panel_hex in ALL_HUNTABLE_PANELS]
class PuzzleRandomization(Choice): class PuzzleRandomization(Choice):
""" """
Puzzles in this randomizer are randomly generated. This option changes the difficulty/types of puzzles. Puzzles in this randomizer are randomly generated. This option changes the difficulty/types of puzzles.
@ -477,6 +489,7 @@ class TheWitnessOptions(PerGameCommonOptions):
panel_hunt_required_percentage: PanelHuntRequiredPercentage panel_hunt_required_percentage: PanelHuntRequiredPercentage
panel_hunt_postgame: PanelHuntPostgame panel_hunt_postgame: PanelHuntPostgame
panel_hunt_discourage_same_area_factor: PanelHuntDiscourageSameAreaFactor panel_hunt_discourage_same_area_factor: PanelHuntDiscourageSameAreaFactor
panel_hunt_plando: PanelHuntPlando
early_caves: EarlyCaves early_caves: EarlyCaves
early_symbol_item: EarlySymbolItem early_symbol_item: EarlySymbolItem
elevators_come_to_you: ElevatorsComeToYou elevators_come_to_you: ElevatorsComeToYou
@ -505,6 +518,7 @@ witness_option_groups = [
PanelHuntTotal, PanelHuntTotal,
PanelHuntPostgame, PanelHuntPostgame,
PanelHuntDiscourageSameAreaFactor, PanelHuntDiscourageSameAreaFactor,
PanelHuntPlando,
], start_collapsed=True), ], start_collapsed=True),
OptionGroup("Locations", [ OptionGroup("Locations", [
ShuffleDiscardedPanels, ShuffleDiscardedPanels,