Skip to content

Commit

Permalink
The Witness: Panel Hunt Mode (#3265)
Browse files Browse the repository at this point in the history
* Add panel hunt options

* Make sure all panels are either solvable or disabled in panel hunt

* Pick huntable panels

* Discards in disable non randomized

* Set up panel hunt requirement

* Panel hunt functional

* Make it so an event can have multiple names

* Panel hunt with events

* Add hunt entities to slot data

* ruff

* add to hint data, no client sneding yet

* encode panel hunt amount in compact hint data

* Remove print statement

* my b

* consistent

* meh

* additions for lcient

* Nah

* Victory panels ineligible for panel hunt

* Panel Hunt Postgame option

* cleanup

* Add data generation file

* pull out set

* always disable gate ep in panel hunt

* Disallow certain challenge panels from being panel hunt panels

* Make panelhuntpostgame its own function, so it can be called even if normal postgame is enabled

* disallow PP resets from panel hunt

* Disable challenge timer and elevetor start respectively in disable hunt postgame

* Fix panelhunt postgame

* lol

* When you test that the bug is fixed but not that the non-bug is not unfixed

* Prevent Obelisks from being panel hunt panels

* Make picking panels for panel hunt a bit more sophisticated, if less random

* Better function maybe ig

* Ok maybe that was a bit too much

* Give advanced players some control over panel hunt

* lint

* correct the logic for amount to pick

* decided the jingle thing was dumb, I'll figure sth out client side. Same area discouragement is now a configurable factor, and the logic has been significantly rewritten

* comment

* Make the option visible

* Safety

* Change assert slightly

* We do a little logging

* number tweak & we do a lil logging

* we do a little more logging

* Ruff

* Panel Hunt Option Group

* Idk how that got here

* Update worlds/witness/options.py

Co-authored-by: Exempt-Medic <[email protected]>

* Update worlds/witness/__init__.py

Co-authored-by: Exempt-Medic <[email protected]>

* remove merge error

* Update worlds/witness/player_logic.py

Co-authored-by: Exempt-Medic <[email protected]>

* True

* Don't have underwater sliding bridge when you have above water sliding bridge

* These are not actually connected lol

* get rid of unnecessary variable

* Refactor compact hint function again

* lint

* Pull out Entity Hunt Picking into its own class, split it into many functions. Kept a lot of the comments tho

* forgot to actually add the new file

* some more refactoring & docstrings

* consistent naming

* flip elif change

* Comment about naming

* Make static eligible panels a constant I can refer back to

* slight formatting change

* pull out options-based eligibility into its own function

* better text and stuff

* lint

* this is not necessary

* capitalisation

* Fix same area discouragement 0

* Simplify data file generation

* Simplify data file generation

* prevent div 0

* Add Vault Boxes -> Vault Panels to replacements

* Update options.py

* Update worlds/witness/entity_hunt.py

Co-authored-by: Exempt-Medic <[email protected]>

* Update entity_hunt.py

* Fix some events not working

* assert

* remove now unused function

* lint

* Lasers Activate, Lasers don't Solve

* lint

* oops

* mypy

* lint

* Add simple panel hunt unit test

* Add Panel Hunt Tests

* Add more Panel Hunt Tests

* Disallow Box Short for normal panel hunt

---------

Co-authored-by: Exempt-Medic <[email protected]>
  • Loading branch information
NewSoupVi and Exempt-Medic authored Aug 19, 2024
1 parent c010c8c commit f253dff
Show file tree
Hide file tree
Showing 16 changed files with 751 additions and 117 deletions.
25 changes: 18 additions & 7 deletions worlds/witness/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from .data import static_logic as static_witness_logic
from .data.item_definition_classes import DoorItemDefinition, ItemData
from .data.utils import get_audio_logs
from .hints import CompactItemData, create_all_hints, make_compact_hint_data, make_laser_hints
from .hints import CompactHintData, create_all_hints, make_compact_hint_data, make_laser_hints
from .locations import WitnessPlayerLocations
from .options import TheWitnessOptions, witness_option_groups
from .player_items import WitnessItem, WitnessPlayerItems
Expand Down Expand Up @@ -68,12 +68,14 @@ class WitnessWorld(World):
player_items: WitnessPlayerItems
player_regions: WitnessPlayerRegions

log_ids_to_hints: Dict[int, CompactItemData]
laser_ids_to_hints: Dict[int, CompactItemData]
log_ids_to_hints: Dict[int, CompactHintData]
laser_ids_to_hints: Dict[int, CompactHintData]

items_placed_early: List[str]
own_itempool: List[WitnessItem]

panel_hunt_required_count: int

def _get_slot_data(self) -> Dict[str, Any]:
return {
"seed": self.random.randrange(0, 1000000),
Expand All @@ -83,12 +85,14 @@ def _get_slot_data(self) -> Dict[str, Any]:
"door_hexes_in_the_pool": self.player_items.get_door_ids_in_pool(),
"symbols_not_in_the_game": self.player_items.get_symbol_ids_not_in_pool(),
"disabled_entities": [int(h, 16) for h in self.player_logic.COMPLETELY_DISABLED_ENTITIES],
"hunt_entities": [int(h, 16) for h in self.player_logic.HUNT_ENTITIES],
"log_ids_to_hints": self.log_ids_to_hints,
"laser_ids_to_hints": self.laser_ids_to_hints,
"progressive_item_lists": self.player_items.get_progressive_item_ids_in_pool(),
"obelisk_side_id_to_EPs": static_witness_logic.OBELISK_SIDE_ID_TO_EP_HEXES,
"precompleted_puzzles": [int(h, 16) for h in self.player_logic.EXCLUDED_LOCATIONS],
"entity_to_name": static_witness_logic.ENTITY_ID_TO_NAME,
"panel_hunt_required_absolute": self.panel_hunt_required_count
}

def determine_sufficient_progression(self) -> None:
Expand Down Expand Up @@ -151,6 +155,13 @@ def generate_early(self) -> None:
if self.options.shuffle_lasers == "local":
self.options.local_items.value |= self.item_name_groups["Lasers"]

if self.options.victory_condition == "panel_hunt":
total_panels = self.options.panel_hunt_total
required_percentage = self.options.panel_hunt_required_percentage
self.panel_hunt_required_count = round(total_panels * required_percentage / 100)
else:
self.panel_hunt_required_count = 0

def create_regions(self) -> None:
self.player_regions.create_regions(self, self.player_logic)

Expand All @@ -169,7 +180,7 @@ def create_regions(self) -> None:

for event_location in self.player_locations.EVENT_LOCATION_TABLE:
item_obj = self.create_item(
self.player_logic.EVENT_ITEM_PAIRS[event_location]
self.player_logic.EVENT_ITEM_PAIRS[event_location][0]
)
location_obj = self.get_location(event_location)
location_obj.place_locked_item(item_obj)
Expand All @@ -192,7 +203,7 @@ def create_regions(self) -> None:
]
if early_items:
random_early_item = self.random.choice(early_items)
if self.options.puzzle_randomization == "sigma_expert":
if self.options.puzzle_randomization == "sigma_expert" or self.options.victory_condition == "panel_hunt":
# In Expert, only tag the item as early, rather than forcing it onto the gate.
self.multiworld.local_early_items[self.player][random_early_item] = 1
else:
Expand Down Expand Up @@ -305,8 +316,8 @@ def create_items(self) -> None:
self.options.local_items.value.add(item_name)

def fill_slot_data(self) -> Dict[str, Any]:
self.log_ids_to_hints: Dict[int, CompactItemData] = {}
self.laser_ids_to_hints: Dict[int, CompactItemData] = {}
self.log_ids_to_hints: Dict[int, CompactHintData] = {}
self.laser_ids_to_hints: Dict[int, CompactHintData] = {}

already_hinted_locations = set()

Expand Down
6 changes: 6 additions & 0 deletions worlds/witness/data/settings/Entity_Hunt.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Requirement Changes:
0x03629 - Entity Hunt - True
0x03505 - 0x03629 - True

New Connections:
Tutorial - Outside Tutorial - True
4 changes: 4 additions & 0 deletions worlds/witness/data/static_locations.py
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,10 @@
"Mountain Bottom Floor Discard",
}

GENERAL_LOCATION_HEXES = {
static_witness_logic.ENTITIES_BY_NAME[entity_name]["entity_hex"] for entity_name in GENERAL_LOCATIONS
}

OBELISK_SIDES = {
"Desert Obelisk Side 1",
"Desert Obelisk Side 2",
Expand Down
23 changes: 18 additions & 5 deletions worlds/witness/data/static_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ def read_logic_file(self, lines: List[str]) -> None:
"region": None,
"id": None,
"entityType": location_id,
"locationType": None,
"area": current_area,
}

Expand All @@ -127,19 +128,30 @@ def read_logic_file(self, lines: List[str]) -> None:
"Laser Hedges",
"Laser Pressure Plates",
}
is_vault_or_video = "Vault" in entity_name or "Video" in entity_name

if "Discard" in entity_name:
entity_type = "Panel"
location_type = "Discard"
elif is_vault_or_video or entity_name == "Tutorial Gate Close":
elif "Vault" in entity_name:
entity_type = "Panel"
location_type = "Vault"
elif entity_name in laser_names:
location_type = "Laser"
entity_type = "Laser"
location_type = None
elif "Obelisk Side" in entity_name:
entity_type = "Obelisk Side"
location_type = "Obelisk Side"
elif "Obelisk" in entity_name:
entity_type = "Obelisk"
location_type = None
elif "EP" in entity_name:
entity_type = "EP"
location_type = "EP"
elif entity_hex.startswith("0xFF"):
entity_type = "Event"
location_type = None
else:
entity_type = "Panel"
location_type = "General"

required_items = parse_lambda(required_item_lambda)
Expand All @@ -152,7 +164,7 @@ def read_logic_file(self, lines: List[str]) -> None:
"items": required_items
}

if location_type == "Obelisk Side":
if entity_type == "Obelisk Side":
eps = set(next(iter(required_panels)))
eps -= {"Theater to Tunnels"}

Expand All @@ -167,7 +179,8 @@ def read_logic_file(self, lines: List[str]) -> None:
"entity_hex": entity_hex,
"region": current_region,
"id": int(location_id),
"entityType": location_type,
"entityType": entity_type,
"locationType": location_type,
"area": current_area,
}

Expand Down
4 changes: 4 additions & 0 deletions worlds/witness/data/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,10 @@ def get_elevators_come_to_you() -> List[str]:
return get_adjustment_file("settings/Door_Shuffle/Elevators_Come_To_You.txt")


def get_entity_hunt() -> List[str]:
return get_adjustment_file("settings/Entity_Hunt.txt")


def get_sigma_normal_logic() -> List[str]:
return get_adjustment_file("WitnessLogic.txt")

Expand Down
Loading

0 comments on commit f253dff

Please sign in to comment.