The Witness: Shuffle Dog (#3425)
* Town Pet the Dog * Add shuffle dog to options presets * I cri evritim * I guess it's as good a time as any * :( * fix the soft conflict * add all the shuffle dog options to some of the unit tests bc why not * Laser Panels are just 'General' now, I'm pretty sure * Could I really call it allsanity?
This commit is contained in:
parent
6efa065867
commit
e61d521ba8
|
@ -189,12 +189,13 @@ class WitnessWorld(World):
|
||||||
event_locations.append(location_obj)
|
event_locations.append(location_obj)
|
||||||
|
|
||||||
# Place other locked items
|
# Place other locked items
|
||||||
dog_puzzle_skip = self.create_item("Puzzle Skip")
|
|
||||||
self.get_location("Town Pet the Dog").place_locked_item(dog_puzzle_skip)
|
|
||||||
|
|
||||||
self.own_itempool.append(dog_puzzle_skip)
|
if self.options.shuffle_dog == "puzzle_skip":
|
||||||
|
dog_puzzle_skip = self.create_item("Puzzle Skip")
|
||||||
|
self.get_location("Town Pet the Dog").place_locked_item(dog_puzzle_skip)
|
||||||
|
|
||||||
self.items_placed_early.append("Puzzle Skip")
|
self.own_itempool.append(dog_puzzle_skip)
|
||||||
|
self.items_placed_early.append("Puzzle Skip")
|
||||||
|
|
||||||
if self.options.early_symbol_item:
|
if self.options.early_symbol_item:
|
||||||
# Pick an early item to place on the tutorial gate.
|
# Pick an early item to place on the tutorial gate.
|
||||||
|
@ -213,7 +214,7 @@ class WitnessWorld(World):
|
||||||
self.own_itempool.append(gate_item)
|
self.own_itempool.append(gate_item)
|
||||||
self.items_placed_early.append(random_early_item)
|
self.items_placed_early.append(random_early_item)
|
||||||
|
|
||||||
# There are some really restrictive settings in The Witness.
|
# There are some really restrictive options in The Witness.
|
||||||
# They are rarely played, but when they are, we add some extra sphere 1 locations.
|
# They are rarely played, but when they are, we add some extra sphere 1 locations.
|
||||||
# This is done both to prevent generation failures, but also to make the early game less linear.
|
# This is done both to prevent generation failures, but also to make the early game less linear.
|
||||||
# Only sweeps for events because having this behavior be random based on Tutorial Gate would be strange.
|
# Only sweeps for events because having this behavior be random based on Tutorial Gate would be strange.
|
||||||
|
@ -221,11 +222,14 @@ class WitnessWorld(World):
|
||||||
state = CollectionState(self.multiworld)
|
state = CollectionState(self.multiworld)
|
||||||
state.sweep_for_advancements(locations=event_locations)
|
state.sweep_for_advancements(locations=event_locations)
|
||||||
|
|
||||||
num_early_locs = sum(1 for loc in self.multiworld.get_reachable_locations(state, self.player) if loc.address)
|
num_early_locs = sum(
|
||||||
|
1 for loc in self.multiworld.get_reachable_locations(state, self.player)
|
||||||
|
if loc.address and not loc.item
|
||||||
|
)
|
||||||
|
|
||||||
# Adjust the needed size for sphere 1 based on how restrictive the settings are in terms of items
|
# Adjust the needed size for sphere 1 based on how restrictive the options are in terms of items
|
||||||
|
|
||||||
needed_size = 3
|
needed_size = 2
|
||||||
needed_size += self.options.puzzle_randomization == "sigma_expert"
|
needed_size += self.options.puzzle_randomization == "sigma_expert"
|
||||||
needed_size += self.options.shuffle_symbols
|
needed_size += self.options.shuffle_symbols
|
||||||
needed_size += self.options.shuffle_doors > 0
|
needed_size += self.options.shuffle_doors > 0
|
||||||
|
|
|
@ -104,6 +104,8 @@ GENERAL_LOCATIONS = {
|
||||||
"Town RGB House Upstairs Right",
|
"Town RGB House Upstairs Right",
|
||||||
"Town RGB House Sound Room Right",
|
"Town RGB House Sound Room Right",
|
||||||
|
|
||||||
|
"Town Pet the Dog",
|
||||||
|
|
||||||
"Windmill Theater Entry Panel",
|
"Windmill Theater Entry Panel",
|
||||||
"Theater Exit Left Panel",
|
"Theater Exit Left Panel",
|
||||||
"Theater Exit Right Panel",
|
"Theater Exit Right Panel",
|
||||||
|
|
|
@ -147,6 +147,9 @@ class StaticWitnessLogicObj:
|
||||||
elif "EP" in entity_name:
|
elif "EP" in entity_name:
|
||||||
entity_type = "EP"
|
entity_type = "EP"
|
||||||
location_type = "EP"
|
location_type = "EP"
|
||||||
|
elif "Pet the Dog" in entity_name:
|
||||||
|
entity_type = "Event"
|
||||||
|
location_type = "Good Boi"
|
||||||
elif entity_hex.startswith("0xFF"):
|
elif entity_hex.startswith("0xFF"):
|
||||||
entity_type = "Event"
|
entity_type = "Event"
|
||||||
location_type = None
|
location_type = None
|
||||||
|
|
|
@ -19,7 +19,7 @@ class WitnessPlayerLocations:
|
||||||
def __init__(self, world: "WitnessWorld", player_logic: WitnessPlayerLogic) -> None:
|
def __init__(self, world: "WitnessWorld", player_logic: WitnessPlayerLogic) -> None:
|
||||||
"""Defines locations AFTER logic changes due to options"""
|
"""Defines locations AFTER logic changes due to options"""
|
||||||
|
|
||||||
self.PANEL_TYPES_TO_SHUFFLE = {"General", "Laser"}
|
self.PANEL_TYPES_TO_SHUFFLE = {"General", "Good Boi"}
|
||||||
self.CHECK_LOCATIONS = static_witness_locations.GENERAL_LOCATIONS.copy()
|
self.CHECK_LOCATIONS = static_witness_locations.GENERAL_LOCATIONS.copy()
|
||||||
|
|
||||||
if world.options.shuffle_discarded_panels:
|
if world.options.shuffle_discarded_panels:
|
||||||
|
@ -53,10 +53,6 @@ class WitnessPlayerLocations:
|
||||||
if static_witness_logic.ENTITIES_BY_NAME[ch]["locationType"] in self.PANEL_TYPES_TO_SHUFFLE
|
if static_witness_logic.ENTITIES_BY_NAME[ch]["locationType"] in self.PANEL_TYPES_TO_SHUFFLE
|
||||||
}
|
}
|
||||||
|
|
||||||
dog_hex = static_witness_logic.ENTITIES_BY_NAME["Town Pet the Dog"]["entity_hex"]
|
|
||||||
dog_id = static_witness_locations.ALL_LOCATIONS_TO_ID["Town Pet the Dog"]
|
|
||||||
self.CHECK_PANELHEX_TO_ID[dog_hex] = dog_id
|
|
||||||
|
|
||||||
self.CHECK_PANELHEX_TO_ID = dict(
|
self.CHECK_PANELHEX_TO_ID = dict(
|
||||||
sorted(self.CHECK_PANELHEX_TO_ID.items(), key=lambda item: item[1])
|
sorted(self.CHECK_PANELHEX_TO_ID.items(), key=lambda item: item[1])
|
||||||
)
|
)
|
||||||
|
|
|
@ -129,12 +129,18 @@ class ShuffleEnvironmentalPuzzles(Choice):
|
||||||
option_obelisk_sides = 2
|
option_obelisk_sides = 2
|
||||||
|
|
||||||
|
|
||||||
class ShuffleDog(Toggle):
|
class ShuffleDog(Choice):
|
||||||
"""
|
"""
|
||||||
Adds petting the Town dog into the location pool.
|
Adds petting the dog statue in Town into the location pool.
|
||||||
|
Alternatively, you can force it to be a Puzzle Skip.
|
||||||
"""
|
"""
|
||||||
display_name = "Pet the Dog"
|
display_name = "Pet the Dog"
|
||||||
|
|
||||||
|
option_off = 0
|
||||||
|
option_puzzle_skip = 1
|
||||||
|
option_random_item = 2
|
||||||
|
default = 1
|
||||||
|
|
||||||
|
|
||||||
class EnvironmentalPuzzlesDifficulty(Choice):
|
class EnvironmentalPuzzlesDifficulty(Choice):
|
||||||
"""
|
"""
|
||||||
|
@ -424,6 +430,7 @@ class TheWitnessOptions(PerGameCommonOptions):
|
||||||
laser_hints: LaserHints
|
laser_hints: LaserHints
|
||||||
death_link: DeathLink
|
death_link: DeathLink
|
||||||
death_link_amnesty: DeathLinkAmnesty
|
death_link_amnesty: DeathLinkAmnesty
|
||||||
|
shuffle_dog: ShuffleDog
|
||||||
|
|
||||||
|
|
||||||
witness_option_groups = [
|
witness_option_groups = [
|
||||||
|
@ -471,5 +478,8 @@ witness_option_groups = [
|
||||||
ElevatorsComeToYou,
|
ElevatorsComeToYou,
|
||||||
DeathLink,
|
DeathLink,
|
||||||
DeathLinkAmnesty,
|
DeathLinkAmnesty,
|
||||||
|
]),
|
||||||
|
OptionGroup("Silly Options", [
|
||||||
|
ShuffleDog,
|
||||||
])
|
])
|
||||||
]
|
]
|
||||||
|
|
|
@ -215,7 +215,7 @@ class WitnessPlayerItems:
|
||||||
item = self.item_data[item_name]
|
item = self.item_data[item_name]
|
||||||
if isinstance(item.definition, ProgressiveItemDefinition):
|
if isinstance(item.definition, ProgressiveItemDefinition):
|
||||||
# Note: we need to reference the static table here rather than the player-specific one because the child
|
# Note: we need to reference the static table here rather than the player-specific one because the child
|
||||||
# items were removed from the pool when we pruned out all progression items not in the settings.
|
# items were removed from the pool when we pruned out all progression items not in the options.
|
||||||
output[cast(int, item.ap_code)] = [cast(int, static_witness_items.ITEM_DATA[child_item].ap_code)
|
output[cast(int, item.ap_code)] = [cast(int, static_witness_items.ITEM_DATA[child_item].ap_code)
|
||||||
for child_item in item.definition.child_item_names]
|
for child_item in item.definition.child_item_names]
|
||||||
return output
|
return output
|
||||||
|
|
|
@ -609,6 +609,9 @@ class WitnessPlayerLogic:
|
||||||
adjustment_linesets_in_order.append(get_complex_doors())
|
adjustment_linesets_in_order.append(get_complex_doors())
|
||||||
adjustment_linesets_in_order.append(get_complex_additional_panels())
|
adjustment_linesets_in_order.append(get_complex_additional_panels())
|
||||||
|
|
||||||
|
if not world.options.shuffle_dog:
|
||||||
|
adjustment_linesets_in_order.append(["Disabled Locations:", "0xFFF80 (Town Pet the Dog)"])
|
||||||
|
|
||||||
if world.options.shuffle_boat:
|
if world.options.shuffle_boat:
|
||||||
adjustment_linesets_in_order.append(get_boat())
|
adjustment_linesets_in_order.append(get_boat())
|
||||||
|
|
||||||
|
@ -890,7 +893,7 @@ class WitnessPlayerLogic:
|
||||||
)
|
)
|
||||||
|
|
||||||
def determine_unrequired_entities(self, world: "WitnessWorld") -> None:
|
def determine_unrequired_entities(self, world: "WitnessWorld") -> None:
|
||||||
"""Figure out which major items are actually useless in this world's settings"""
|
"""Figure out which major items are actually useless in this world's options"""
|
||||||
|
|
||||||
# Gather quick references to relevant options
|
# Gather quick references to relevant options
|
||||||
eps_shuffled = world.options.shuffle_EPs
|
eps_shuffled = world.options.shuffle_EPs
|
||||||
|
|
|
@ -37,6 +37,8 @@ witness_option_presets: Dict[str, Dict[str, Any]] = {
|
||||||
"laser_hints": LaserHints.default,
|
"laser_hints": LaserHints.default,
|
||||||
"death_link": DeathLink.default,
|
"death_link": DeathLink.default,
|
||||||
"death_link_amnesty": DeathLinkAmnesty.default,
|
"death_link_amnesty": DeathLinkAmnesty.default,
|
||||||
|
|
||||||
|
"shuffle_dog": ShuffleDog.default,
|
||||||
},
|
},
|
||||||
|
|
||||||
# For relative beginners who want to move to the next step.
|
# For relative beginners who want to move to the next step.
|
||||||
|
@ -73,6 +75,8 @@ witness_option_presets: Dict[str, Dict[str, Any]] = {
|
||||||
"laser_hints": LaserHints.default,
|
"laser_hints": LaserHints.default,
|
||||||
"death_link": DeathLink.default,
|
"death_link": DeathLink.default,
|
||||||
"death_link_amnesty": DeathLinkAmnesty.default,
|
"death_link_amnesty": DeathLinkAmnesty.default,
|
||||||
|
|
||||||
|
"shuffle_dog": ShuffleDog.default,
|
||||||
},
|
},
|
||||||
|
|
||||||
# Allsanity but without the BS (no expert, no tedious EPs).
|
# Allsanity but without the BS (no expert, no tedious EPs).
|
||||||
|
@ -109,5 +113,7 @@ witness_option_presets: Dict[str, Dict[str, Any]] = {
|
||||||
"laser_hints": LaserHints.default,
|
"laser_hints": LaserHints.default,
|
||||||
"death_link": DeathLink.default,
|
"death_link": DeathLink.default,
|
||||||
"death_link_amnesty": DeathLinkAmnesty.default,
|
"death_link_amnesty": DeathLinkAmnesty.default,
|
||||||
|
|
||||||
|
"shuffle_dog": ShuffleDog.option_random_item,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ class TestExpertNonRandomizedEPs(WitnessTestBase):
|
||||||
"victory_condition": "challenge",
|
"victory_condition": "challenge",
|
||||||
"shuffle_discarded_panels": False,
|
"shuffle_discarded_panels": False,
|
||||||
"shuffle_boat": False,
|
"shuffle_boat": False,
|
||||||
|
"shuffle_dog": "off",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,6 +25,7 @@ class TestVanillaAutoElevatorsPanels(WitnessTestBase):
|
||||||
"early_caves": True,
|
"early_caves": True,
|
||||||
"shuffle_vault_boxes": True,
|
"shuffle_vault_boxes": True,
|
||||||
"mountain_lasers": 11,
|
"mountain_lasers": 11,
|
||||||
|
"shuffle_dog": "puzzle_skip",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,6 +48,7 @@ class TestMaxEntityShuffle(WitnessTestBase):
|
||||||
"obelisk_keys": True,
|
"obelisk_keys": True,
|
||||||
"shuffle_lasers": "anywhere",
|
"shuffle_lasers": "anywhere",
|
||||||
"victory_condition": "mountain_box_long",
|
"victory_condition": "mountain_box_long",
|
||||||
|
"shuffle_dog": "random_item",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue