Skip to content

Commit

Permalink
The Witness: Panel Hunt Plando (#3549)
Browse files Browse the repository at this point in the history
* 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:tm:

* Update entity_hunt.py

* Update entity_hunt.py

* Update entity_hunt.py
NewSoupVi authored Dec 12, 2024
1 parent f5e3677 commit d773695
Showing 2 changed files with 59 additions and 12 deletions.
57 changes: 45 additions & 12 deletions worlds/witness/entity_hunt.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from collections import defaultdict
from logging import debug
from logging import debug, warning
from pprint import pformat
from typing import TYPE_CHECKING, Dict, List, Set, Tuple

@@ -48,6 +48,8 @@ def __init__(self, player_logic: "WitnessPlayerLogic", world: "WitnessWorld",
self.PRE_PICKED_HUNT_ENTITIES = pre_picked_entities.copy()
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()

def pick_panel_hunt_panels(self, total_amount: int) -> Set[str]:
@@ -69,24 +71,51 @@ def pick_panel_hunt_panels(self, total_amount: int) -> Set[str]:

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.
"""
panel_obj = static_witness_logic.ENTITIES_BY_HEX[panel_hex]

return (
self.player_logic.solvability_guaranteed(panel_hex)
and panel_hex not in self.player_logic.EXCLUDED_ENTITIES
and not (
# 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.
self.player_options.disable_non_randomized_puzzles
and not self.player_options.shuffle_discarded_panels
and panel_obj["locationType"] == "Discard"
)
if not self.player_logic.solvability_guaranteed(panel_hex) or panel_hex in self.player_logic.EXCLUDED_ENTITIES:
if plando:
warning(f"Panel {panel_obj['checkName']} is disabled / excluded and thus not eligible for panel hunt.")
return False

return plando or not (
# 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.
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]]]:
"""
There are some entities that are not allowed for panel hunt for various technical of gameplay reasons.
@@ -215,6 +244,10 @@ def _replace_unfair_hunt_entities_with_good_hunt_entities(self) -> None:
if good_entity in self.HUNT_ENTITIES or good_entity not in self.ALL_ELIGIBLE_ENTITIES:
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.
self.HUNT_ENTITIES.remove(bad_entitiy)
self.HUNT_ENTITIES.add(good_entity)
14 changes: 14 additions & 0 deletions worlds/witness/options.py
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
from Options import (
Choice,
DefaultOnToggle,
LocationSet,
OptionDict,
OptionError,
OptionGroup,
@@ -17,6 +18,7 @@

from .data import static_logic as static_witness_logic
from .data.item_definition_classes import ItemCategory, WeightedItemDefinition
from .entity_hunt import ALL_HUNTABLE_PANELS


class DisableNonRandomizedPuzzles(Toggle):
@@ -268,6 +270,16 @@ class PanelHuntDiscourageSameAreaFactor(Range):
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):
"""
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_postgame: PanelHuntPostgame
panel_hunt_discourage_same_area_factor: PanelHuntDiscourageSameAreaFactor
panel_hunt_plando: PanelHuntPlando
early_caves: EarlyCaves
early_symbol_item: EarlySymbolItem
elevators_come_to_you: ElevatorsComeToYou
@@ -505,6 +518,7 @@ class TheWitnessOptions(PerGameCommonOptions):
PanelHuntTotal,
PanelHuntPostgame,
PanelHuntDiscourageSameAreaFactor,
PanelHuntPlando,
], start_collapsed=True),
OptionGroup("Locations", [
ShuffleDiscardedPanels,

0 comments on commit d773695

Please sign in to comment.