The Witness: Hint distribution changes, added locations, misc fixes (#1785)
Changes:
* Hints should feel a lot less same-y now ("Priority hints" are no longer always hints in disguise)
* Keep Hedge Mazes 1-3 and Pressure Plates 1-3 are added as locations in all settings
* Desert Final Room Hexagonal & Desert Final Room Bent 3 are added as locations
* Entries in exclude_locations that are referring to panels are now sent through slot data. This means they can be pre-skipped on the client side.
Fixes:
* Logic error in the Stoneworks that led to more restrictive seeds than necessary
* Logic error for Theater Flowers EP that led to more restrictive seeds than necessary
* Fixed crash in plando when "item" is a dict with weights
* Spoiler log locations were in random order per region, now they are consistent
			
			
This commit is contained in:
		
							parent
							
								
									afe9e12ef4
								
							
						
					
					
						commit
						845502ad39
					
				|  | @ -264,7 +264,7 @@ Quarry Stoneworks Upper Floor (Quarry Stoneworks) - Quarry Stoneworks Middle Flo | ||||||
| 158141 - 0x014E9 (Upper Row 8) - 0x03686 - Colored Squares & Eraser | 158141 - 0x014E9 (Upper Row 8) - 0x03686 - Colored Squares & Eraser | ||||||
| 158142 - 0x03677 (Stair Control) - True - Colored Squares & Eraser | 158142 - 0x03677 (Stair Control) - True - Colored Squares & Eraser | ||||||
| Door - 0x0368A (Stairs) - 0x03677 | Door - 0x0368A (Stairs) - 0x03677 | ||||||
| 158143 - 0x3C125 (Control Room Left) - 0x0367C - Black/White Squares & Dots & Eraser | 158143 - 0x3C125 (Control Room Left) - 0x014E9 - Black/White Squares & Dots & Eraser | ||||||
| 158144 - 0x0367C (Control Room Right) - 0x014E9 - Colored Squares & Dots & Eraser | 158144 - 0x0367C (Control Room Right) - 0x014E9 - Colored Squares & Dots & Eraser | ||||||
| 159411 - 0x0069D (Ramp EP) - 0x03676 & 0x275FF - True | 159411 - 0x0069D (Ramp EP) - 0x03676 & 0x275FF - True | ||||||
| 159413 - 0x00614 (Lift EP) - 0x275FF & 0x03675 - True | 159413 - 0x00614 (Lift EP) - 0x275FF & 0x03675 - True | ||||||
|  |  | ||||||
|  | @ -264,7 +264,7 @@ Quarry Stoneworks Upper Floor (Quarry Stoneworks) - Quarry Stoneworks Middle Flo | ||||||
| 158141 - 0x014E9 (Upper Row 8) - 0x03686 - Squares & Colored Squares & Eraser & Stars & Stars + Same Colored Symbol | 158141 - 0x014E9 (Upper Row 8) - 0x03686 - Squares & Colored Squares & Eraser & Stars & Stars + Same Colored Symbol | ||||||
| 158142 - 0x03677 (Stair Control) - True - Squares & Colored Squares & Eraser | 158142 - 0x03677 (Stair Control) - True - Squares & Colored Squares & Eraser | ||||||
| Door - 0x0368A (Stairs) - 0x03677 | Door - 0x0368A (Stairs) - 0x03677 | ||||||
| 158143 - 0x3C125 (Control Room Left) - 0x0367C - Squares & Black/White Squares & Dots & Full Dots & Eraser | 158143 - 0x3C125 (Control Room Left) - 0x014E9 - Squares & Black/White Squares & Dots & Full Dots & Eraser | ||||||
| 158144 - 0x0367C (Control Room Right) - 0x014E9 - Squares & Colored Squares & Triangles & Eraser & Stars & Stars + Same Colored Symbol | 158144 - 0x0367C (Control Room Right) - 0x014E9 - Squares & Colored Squares & Triangles & Eraser & Stars & Stars + Same Colored Symbol | ||||||
| 159411 - 0x0069D (Ramp EP) - 0x03676 & 0x275FF - True | 159411 - 0x0069D (Ramp EP) - 0x03676 & 0x275FF - True | ||||||
| 159413 - 0x00614 (Lift EP) - 0x275FF & 0x03675 - True | 159413 - 0x00614 (Lift EP) - 0x275FF & 0x03675 - True | ||||||
|  |  | ||||||
|  | @ -15,7 +15,7 @@ Tutorial (Tutorial) - Outside Tutorial - 0x03629: | ||||||
| 158006 - 0x0A3B2 (Back Right) - True - True | 158006 - 0x0A3B2 (Back Right) - True - True | ||||||
| 158007 - 0x03629 (Gate Open) - 0x002C2 & 0x0A3B5 & 0x0A3B2 - True | 158007 - 0x03629 (Gate Open) - 0x002C2 & 0x0A3B5 & 0x0A3B2 - True | ||||||
| 158008 - 0x03505 (Gate Close) - 0x2FAF6 & 0x03629 - True | 158008 - 0x03505 (Gate Close) - 0x2FAF6 & 0x03629 - True | ||||||
| 158009 - 0x0C335 (Pillar) - True - Triangles - True | 158009 - 0x0C335 (Pillar) - True - Triangles | ||||||
| 158010 - 0x0C373 (Patio Floor) - 0x0C335 - Dots | 158010 - 0x0C373 (Patio Floor) - 0x0C335 - Dots | ||||||
| 159512 - 0x33530 (Cloud EP) - True - True | 159512 - 0x33530 (Cloud EP) - True - True | ||||||
| 159513 - 0x33600 (Patio Flowers EP) - 0x0C373 - True | 159513 - 0x33600 (Patio Flowers EP) - 0x0C373 - True | ||||||
|  | @ -264,7 +264,7 @@ Quarry Stoneworks Upper Floor (Quarry Stoneworks) - Quarry Stoneworks Middle Flo | ||||||
| 158141 - 0x014E9 (Upper Row 8) - 0x03686 - Colored Squares & Eraser | 158141 - 0x014E9 (Upper Row 8) - 0x03686 - Colored Squares & Eraser | ||||||
| 158142 - 0x03677 (Stair Control) - True - Colored Squares & Eraser | 158142 - 0x03677 (Stair Control) - True - Colored Squares & Eraser | ||||||
| Door - 0x0368A (Stairs) - 0x03677 | Door - 0x0368A (Stairs) - 0x03677 | ||||||
| 158143 - 0x3C125 (Control Room Left) - 0x0367C - Black/White Squares & Dots & Eraser | 158143 - 0x3C125 (Control Room Left) - 0x014E9 - Black/White Squares & Dots & Eraser | ||||||
| 158144 - 0x0367C (Control Room Right) - 0x014E9 - Colored Squares & Dots & Eraser | 158144 - 0x0367C (Control Room Right) - 0x014E9 - Colored Squares & Dots & Eraser | ||||||
| 159411 - 0x0069D (Ramp EP) - 0x03676 & 0x275FF - True | 159411 - 0x0069D (Ramp EP) - 0x03676 & 0x275FF - True | ||||||
| 159413 - 0x00614 (Lift EP) - 0x275FF & 0x03675 - True | 159413 - 0x00614 (Lift EP) - 0x275FF & 0x03675 - True | ||||||
|  |  | ||||||
|  | @ -62,11 +62,11 @@ class WitnessWorld(World): | ||||||
|             'item_id_to_door_hexes': self.static_items.ITEM_ID_TO_DOOR_HEX_ALL, |             'item_id_to_door_hexes': self.static_items.ITEM_ID_TO_DOOR_HEX_ALL, | ||||||
|             'door_hexes_in_the_pool': self.items.DOORS, |             'door_hexes_in_the_pool': self.items.DOORS, | ||||||
|             'symbols_not_in_the_game': self.items.SYMBOLS_NOT_IN_THE_GAME, |             'symbols_not_in_the_game': self.items.SYMBOLS_NOT_IN_THE_GAME, | ||||||
|             'disabled_panels': self.player_logic.COMPLETELY_DISABLED_CHECKS, |             'disabled_panels': list(self.player_logic.COMPLETELY_DISABLED_CHECKS), | ||||||
|             'log_ids_to_hints': self.log_ids_to_hints, |             'log_ids_to_hints': self.log_ids_to_hints, | ||||||
|             'progressive_item_lists': self.items.MULTI_LISTS_BY_CODE, |             'progressive_item_lists': self.items.MULTI_LISTS_BY_CODE, | ||||||
|             'obelisk_side_id_to_EPs': self.static_logic.OBELISK_SIDE_ID_TO_EP_HEXES, |             'obelisk_side_id_to_EPs': self.static_logic.OBELISK_SIDE_ID_TO_EP_HEXES, | ||||||
|             'precompleted_puzzles': {int(h, 16) for h in self.player_logic.PRECOMPLETED_LOCATIONS}, |             'precompleted_puzzles': [int(h, 16) for h in self.player_logic.EXCLUDED_LOCATIONS], | ||||||
|             'entity_to_name': self.static_logic.ENTITY_ID_TO_NAME, |             'entity_to_name': self.static_logic.ENTITY_ID_TO_NAME, | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -143,14 +143,19 @@ class WitnessWorld(World): | ||||||
| 
 | 
 | ||||||
|         for v in self.multiworld.plando_items[self.player]: |         for v in self.multiworld.plando_items[self.player]: | ||||||
|             if v.get("from_pool", True): |             if v.get("from_pool", True): | ||||||
|                 plandoed_items.update({self.items_by_name[i] for i in v.get("items", dict()).keys() |                 for item_key in {"item", "items"}: | ||||||
|                                        if i in self.items_by_name}) |                     if item_key in v: | ||||||
|                 if "item" in v and v["item"] in self.items_by_name: |                         if type(v[item_key]) is str: | ||||||
|                     plandoed_items.add(self.items_by_name[v["item"]]) |                             plandoed_items.add(v[item_key]) | ||||||
|  |                         elif type(v[item_key]) is dict: | ||||||
|  |                             plandoed_items.update(item for item, weight in v[item_key].items() if weight) | ||||||
|  |                         else: | ||||||
|  |                             # Other type of iterable | ||||||
|  |                             plandoed_items.update(v[item_key]) | ||||||
| 
 | 
 | ||||||
|         for symbol in self.items.GOOD_ITEMS: |         for symbol in self.items.GOOD_ITEMS: | ||||||
|             item = self.items_by_name[symbol] |             item = self.items_by_name[symbol] | ||||||
|             if item in pool and item not in plandoed_items: |             if item in pool and symbol not in plandoed_items: | ||||||
|                 # for now, any item that is mentioned in any plando option, even if it's a list of items, is ineligible. |                 # for now, any item that is mentioned in any plando option, even if it's a list of items, is ineligible. | ||||||
|                 # Hopefully, in the future, plando gets resolved before create_items. |                 # Hopefully, in the future, plando gets resolved before create_items. | ||||||
|                 # I could also partially resolve lists myself, but this could introduce errors if not done carefully. |                 # I could also partially resolve lists myself, but this could introduce errors if not done carefully. | ||||||
|  | @ -255,7 +260,7 @@ class WitnessWorld(World): | ||||||
| 
 | 
 | ||||||
|             self.multiworld.per_slot_randoms[self.player].shuffle(audio_logs) |             self.multiworld.per_slot_randoms[self.player].shuffle(audio_logs) | ||||||
| 
 | 
 | ||||||
|             duplicates = len(audio_logs) // hint_amount |             duplicates = min(3, len(audio_logs) // hint_amount) | ||||||
| 
 | 
 | ||||||
|             for _ in range(0, hint_amount): |             for _ in range(0, hint_amount): | ||||||
|                 hint = generated_hints.pop(0) |                 hint = generated_hints.pop(0) | ||||||
|  |  | ||||||
|  | @ -96,31 +96,30 @@ joke_hints = [ | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def get_always_hint_items(multiworld: MultiWorld, player: int): | def get_always_hint_items(multiworld: MultiWorld, player: int): | ||||||
|     priority = [ |     always = [ | ||||||
|         "Boat", |         "Boat", | ||||||
|         "Mountain Bottom Floor Final Room Entry (Door)", |  | ||||||
|         "Caves Mountain Shortcut (Door)", |  | ||||||
|         "Caves Swamp Shortcut (Door)", |  | ||||||
|         "Caves Exits to Main Island", |         "Caves Exits to Main Island", | ||||||
|         "Progressive Dots", |         "Progressive Dots", | ||||||
|     ] |     ] | ||||||
| 
 | 
 | ||||||
|     difficulty = get_option_value(multiworld, player, "puzzle_randomization") |     difficulty = get_option_value(multiworld, player, "puzzle_randomization") | ||||||
|     discards = is_option_enabled(multiworld, player, "shuffle_discarded_panels") |     discards = is_option_enabled(multiworld, player, "shuffle_discarded_panels") | ||||||
|  |     wincon = get_option_value(multiworld, player, "victory_condition") | ||||||
| 
 | 
 | ||||||
|     if discards: |     if discards: | ||||||
|         if difficulty == 1: |         if difficulty == 1: | ||||||
|             priority.append("Arrows") |             always.append("Arrows") | ||||||
|         else: |         else: | ||||||
|             priority.append("Triangles") |             always.append("Triangles") | ||||||
| 
 | 
 | ||||||
|     return priority |     if wincon == 0: | ||||||
|  |         always.append("Mountain Bottom Floor Final Room Entry (Door)") | ||||||
|  | 
 | ||||||
|  |     return always | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def get_always_hint_locations(multiworld: MultiWorld, player: int): | def get_always_hint_locations(multiworld: MultiWorld, player: int): | ||||||
|     return { |     return { | ||||||
|         "Swamp Purple Underwater", |  | ||||||
|         "Shipwreck Vault Box", |  | ||||||
|         "Challenge Vault Box", |         "Challenge Vault Box", | ||||||
|         "Mountain Bottom Floor Discard", |         "Mountain Bottom Floor Discard", | ||||||
|         "Theater Eclipse EP", |         "Theater Eclipse EP", | ||||||
|  | @ -131,6 +130,8 @@ def get_always_hint_locations(multiworld: MultiWorld, player: int): | ||||||
| 
 | 
 | ||||||
| def get_priority_hint_items(multiworld: MultiWorld, player: int): | def get_priority_hint_items(multiworld: MultiWorld, player: int): | ||||||
|     priority = { |     priority = { | ||||||
|  |         "Caves Mountain Shortcut (Door)", | ||||||
|  |         "Caves Swamp Shortcut (Door)", | ||||||
|         "Negative Shapers", |         "Negative Shapers", | ||||||
|         "Sound Dots", |         "Sound Dots", | ||||||
|         "Colored Dots", |         "Colored Dots", | ||||||
|  | @ -157,16 +158,18 @@ def get_priority_hint_items(multiworld: MultiWorld, player: int): | ||||||
|         if get_option_value(multiworld, player, "doors") >= 2: |         if get_option_value(multiworld, player, "doors") >= 2: | ||||||
|             priority.add("Desert Laser") |             priority.add("Desert Laser") | ||||||
|             lasers.remove("Desert Laser") |             lasers.remove("Desert Laser") | ||||||
|             priority.update(multiworld.per_slot_randoms[player].sample(lasers, 2)) |             priority.update(multiworld.per_slot_randoms[player].sample(lasers, 5)) | ||||||
| 
 | 
 | ||||||
|         else: |         else: | ||||||
|             priority.update(multiworld.per_slot_randoms[player].sample(lasers, 3)) |             priority.update(multiworld.per_slot_randoms[player].sample(lasers, 6)) | ||||||
| 
 | 
 | ||||||
|     return priority |     return priority | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def get_priority_hint_locations(multiworld: MultiWorld, player: int): | def get_priority_hint_locations(multiworld: MultiWorld, player: int): | ||||||
|     return { |     return { | ||||||
|  |         "Swamp Purple Underwater", | ||||||
|  |         "Shipwreck Vault Box", | ||||||
|         "Town RGB Room Left", |         "Town RGB Room Left", | ||||||
|         "Town RGB Room Right", |         "Town RGB Room Right", | ||||||
|         "Treehouse Green Bridge 7", |         "Treehouse Green Bridge 7", | ||||||
|  | @ -264,7 +267,8 @@ def make_hints(multiworld: MultiWorld, player: int, hint_amount: int): | ||||||
| 
 | 
 | ||||||
|     multiworld.per_slot_randoms[player].shuffle(hints)  # shuffle always hint order in case of low hint amount |     multiworld.per_slot_randoms[player].shuffle(hints)  # shuffle always hint order in case of low hint amount | ||||||
| 
 | 
 | ||||||
|     next_random_hint_is_item = multiworld.per_slot_randoms[player].randint(0, 2) |     remaining_hints = hint_amount - len(hints) | ||||||
|  |     priority_hint_amount = int(max(0.0, min(len(priority_hint_pairs) / 2, remaining_hints / 2))) | ||||||
| 
 | 
 | ||||||
|     prog_items_in_this_world = sorted(list(prog_items_in_this_world)) |     prog_items_in_this_world = sorted(list(prog_items_in_this_world)) | ||||||
|     locations_in_this_world = sorted(list(loc_in_this_world)) |     locations_in_this_world = sorted(list(loc_in_this_world)) | ||||||
|  | @ -272,18 +276,21 @@ def make_hints(multiworld: MultiWorld, player: int, hint_amount: int): | ||||||
|     multiworld.per_slot_randoms[player].shuffle(prog_items_in_this_world) |     multiworld.per_slot_randoms[player].shuffle(prog_items_in_this_world) | ||||||
|     multiworld.per_slot_randoms[player].shuffle(locations_in_this_world) |     multiworld.per_slot_randoms[player].shuffle(locations_in_this_world) | ||||||
| 
 | 
 | ||||||
|  |     priority_hint_list = list(priority_hint_pairs.items()) | ||||||
|  |     multiworld.per_slot_randoms[player].shuffle(priority_hint_list) | ||||||
|  |     for _ in range(0, priority_hint_amount): | ||||||
|  |         next_priority_hint = priority_hint_list.pop() | ||||||
|  |         loc = next_priority_hint[0] | ||||||
|  |         item = next_priority_hint[1] | ||||||
|  | 
 | ||||||
|  |         if item[1]: | ||||||
|  |             hints.append((f"{item[0]} can be found at {loc}.", item[2])) | ||||||
|  |         else: | ||||||
|  |             hints.append((f"{loc} contains {item[0]}.", item[2])) | ||||||
|  | 
 | ||||||
|  |     next_random_hint_is_item = multiworld.per_slot_randoms[player].randint(0, 2) | ||||||
|  | 
 | ||||||
|     while len(hints) < hint_amount: |     while len(hints) < hint_amount: | ||||||
|         if priority_hint_pairs: |  | ||||||
|             loc = multiworld.per_slot_randoms[player].choice(list(priority_hint_pairs.keys())) |  | ||||||
|             item = priority_hint_pairs[loc] |  | ||||||
|             del priority_hint_pairs[loc] |  | ||||||
| 
 |  | ||||||
|             if item[1]: |  | ||||||
|                 hints.append((f"{item[0]} can be found at {loc}.", item[2])) |  | ||||||
|             else: |  | ||||||
|                 hints.append((f"{loc} contains {item[0]}.", item[2])) |  | ||||||
|             continue |  | ||||||
| 
 |  | ||||||
|         if next_random_hint_is_item: |         if next_random_hint_is_item: | ||||||
|             if not prog_items_in_this_world: |             if not prog_items_in_this_world: | ||||||
|                 next_random_hint_is_item = not next_random_hint_is_item |                 next_random_hint_is_item = not next_random_hint_is_item | ||||||
|  |  | ||||||
|  | @ -143,11 +143,11 @@ class WitnessPlayerItems: | ||||||
|         self.PROGRESSION_TABLE = dict() |         self.PROGRESSION_TABLE = dict() | ||||||
| 
 | 
 | ||||||
|         self.ITEM_ID_TO_DOOR_HEX = dict() |         self.ITEM_ID_TO_DOOR_HEX = dict() | ||||||
|         self.DOORS = set() |         self.DOORS = list() | ||||||
| 
 | 
 | ||||||
|         self.PROG_ITEM_AMOUNTS = defaultdict(lambda: 1) |         self.PROG_ITEM_AMOUNTS = defaultdict(lambda: 1) | ||||||
| 
 | 
 | ||||||
|         self.SYMBOLS_NOT_IN_THE_GAME = set() |         self.SYMBOLS_NOT_IN_THE_GAME = list() | ||||||
| 
 | 
 | ||||||
|         self.EXTRA_AMOUNTS = { |         self.EXTRA_AMOUNTS = { | ||||||
|             "Functioning Brain": 1, |             "Functioning Brain": 1, | ||||||
|  | @ -162,7 +162,7 @@ class WitnessPlayerItems: | ||||||
|             if item[0] not in logic.PROG_ITEMS_ACTUALLY_IN_THE_GAME: |             if item[0] not in logic.PROG_ITEMS_ACTUALLY_IN_THE_GAME: | ||||||
|                 del self.ITEM_TABLE[item[0]] |                 del self.ITEM_TABLE[item[0]] | ||||||
|                 if item in StaticWitnessLogic.ALL_SYMBOL_ITEMS: |                 if item in StaticWitnessLogic.ALL_SYMBOL_ITEMS: | ||||||
|                     self.SYMBOLS_NOT_IN_THE_GAME.add(StaticWitnessItems.ALL_ITEM_TABLE[item[0]].code) |                     self.SYMBOLS_NOT_IN_THE_GAME.append(StaticWitnessItems.ALL_ITEM_TABLE[item[0]].code) | ||||||
|             else: |             else: | ||||||
|                 if item[0] in StaticWitnessLogic.PROGRESSIVE_TO_ITEMS: |                 if item[0] in StaticWitnessLogic.PROGRESSIVE_TO_ITEMS: | ||||||
|                     self.PROG_ITEM_AMOUNTS[item[0]] = len(logic.MULTI_LISTS[item[0]]) |                     self.PROG_ITEM_AMOUNTS[item[0]] = len(logic.MULTI_LISTS[item[0]]) | ||||||
|  | @ -178,7 +178,7 @@ class WitnessPlayerItems: | ||||||
|         for entity_hex, items in logic.DOOR_ITEMS_BY_ID.items(): |         for entity_hex, items in logic.DOOR_ITEMS_BY_ID.items(): | ||||||
|             entity_hex_int = int(entity_hex, 16) |             entity_hex_int = int(entity_hex, 16) | ||||||
| 
 | 
 | ||||||
|             self.DOORS.add(entity_hex_int) |             self.DOORS.append(entity_hex_int) | ||||||
| 
 | 
 | ||||||
|             for item in items: |             for item in items: | ||||||
|                 item_id = StaticWitnessItems.ALL_ITEM_TABLE[item].code |                 item_id = StaticWitnessItems.ALL_ITEM_TABLE[item].code | ||||||
|  |  | ||||||
|  | @ -43,6 +43,8 @@ class StaticWitnessLocations: | ||||||
|         "Desert Light Room 3", |         "Desert Light Room 3", | ||||||
|         "Desert Pond Room 5", |         "Desert Pond Room 5", | ||||||
|         "Desert Flood Room 6", |         "Desert Flood Room 6", | ||||||
|  |         "Desert Final Hexagonal", | ||||||
|  |         "Desert Final Bent 3", | ||||||
|         "Desert Laser Panel", |         "Desert Laser Panel", | ||||||
| 
 | 
 | ||||||
|         "Quarry Stoneworks Lower Row 6", |         "Quarry Stoneworks Lower Row 6", | ||||||
|  | @ -61,7 +63,13 @@ class StaticWitnessLocations: | ||||||
|         "Shadows Near 5", |         "Shadows Near 5", | ||||||
|         "Shadows Laser Panel", |         "Shadows Laser Panel", | ||||||
| 
 | 
 | ||||||
|  |         "Keep Hedge Maze 1", | ||||||
|  |         "Keep Hedge Maze 2", | ||||||
|  |         "Keep Hedge Maze 3", | ||||||
|         "Keep Hedge Maze 4", |         "Keep Hedge Maze 4", | ||||||
|  |         "Keep Pressure Plates 1", | ||||||
|  |         "Keep Pressure Plates 2", | ||||||
|  |         "Keep Pressure Plates 3", | ||||||
|         "Keep Pressure Plates 4", |         "Keep Pressure Plates 4", | ||||||
|         "Keep Discard", |         "Keep Discard", | ||||||
|         "Keep Laser Panel Hedges", |         "Keep Laser Panel Hedges", | ||||||
|  |  | ||||||
|  | @ -296,21 +296,21 @@ class WitnessPlayerLogic: | ||||||
|         elif get_option_value(world, player, "shuffle_EPs") == 1:  # Individual EPs |         elif get_option_value(world, player, "shuffle_EPs") == 1:  # Individual EPs | ||||||
|             adjustment_linesets_in_order.append(["Disabled Locations:"] + get_ep_obelisks()[1:]) |             adjustment_linesets_in_order.append(["Disabled Locations:"] + get_ep_obelisks()[1:]) | ||||||
| 
 | 
 | ||||||
|         else:  # Obelisk Sides |         yaml_disabled_eps = [] | ||||||
|             yaml_disabled_eps = [] |  | ||||||
| 
 | 
 | ||||||
|             for yaml_disabled_location in self.YAML_DISABLED_LOCATIONS: |         for yaml_disabled_location in self.YAML_DISABLED_LOCATIONS: | ||||||
|                 if yaml_disabled_location not in StaticWitnessLogic.CHECKS_BY_NAME: |             if yaml_disabled_location not in StaticWitnessLogic.CHECKS_BY_NAME: | ||||||
|                     continue |                 continue | ||||||
| 
 | 
 | ||||||
|                 loc_obj = StaticWitnessLogic.CHECKS_BY_NAME[yaml_disabled_location] |             loc_obj = StaticWitnessLogic.CHECKS_BY_NAME[yaml_disabled_location] | ||||||
| 
 |  | ||||||
|                 if loc_obj["panelType"] != "EP": |  | ||||||
|                     continue |  | ||||||
| 
 | 
 | ||||||
|  |             if loc_obj["panelType"] == "EP" and get_option_value(world, player, "shuffle_EPs") == 2: | ||||||
|                 yaml_disabled_eps.append(loc_obj["checkHex"]) |                 yaml_disabled_eps.append(loc_obj["checkHex"]) | ||||||
| 
 | 
 | ||||||
|             adjustment_linesets_in_order.append(["Precompleted Locations:"] + yaml_disabled_eps) |             if loc_obj["panelType"] in {"EP", "General"}: | ||||||
|  |                 self.EXCLUDED_LOCATIONS.add(loc_obj["checkHex"]) | ||||||
|  | 
 | ||||||
|  |         adjustment_linesets_in_order.append(["Precompleted Locations:"] + yaml_disabled_eps) | ||||||
| 
 | 
 | ||||||
|         for adjustment_lineset in adjustment_linesets_in_order: |         for adjustment_lineset in adjustment_linesets_in_order: | ||||||
|             current_adjustment_type = None |             current_adjustment_type = None | ||||||
|  | @ -430,6 +430,7 @@ class WitnessPlayerLogic: | ||||||
|         self.ALWAYS_EVENT_HEX_CODES = set() |         self.ALWAYS_EVENT_HEX_CODES = set() | ||||||
|         self.COMPLETELY_DISABLED_CHECKS = set() |         self.COMPLETELY_DISABLED_CHECKS = set() | ||||||
|         self.PRECOMPLETED_LOCATIONS = set() |         self.PRECOMPLETED_LOCATIONS = set() | ||||||
|  |         self.EXCLUDED_LOCATIONS = set() | ||||||
|         self.ADDED_CHECKS = set() |         self.ADDED_CHECKS = set() | ||||||
|         self.VICTORY_LOCATION = "0x0356B" |         self.VICTORY_LOCATION = "0x0356B" | ||||||
|         self.EVENT_ITEM_NAMES = { |         self.EVENT_ITEM_NAMES = { | ||||||
|  |  | ||||||
|  | @ -141,14 +141,19 @@ class WitnessLogic(LogicMixin): | ||||||
|                         and self.can_reach("Windmill Interior to Theater", "Entrance", player) |                         and self.can_reach("Windmill Interior to Theater", "Entrance", player) | ||||||
|                     ) |                     ) | ||||||
| 
 | 
 | ||||||
|                     exit_to_town = self.can_reach("Theater to Town", "Entrance", player) |                     theater_from_town = ( | ||||||
|                     entrance_to_town = ( |                         self.can_reach("Town to Windmill Interior", "Entrance", player) | ||||||
|                             self.can_reach("Town to Windmill Interior", "Entrance", player) |                         and self.can_reach("Windmill Interior to Theater", "Entrance", player) | ||||||
|                             and self.can_reach("Windmill Interior to Theater", "Entrance", player) |                         or self.can_reach("Theater to Town", "Entrance", player) | ||||||
|                     ) |                     ) | ||||||
|                     tunnels_to_town = self.can_reach("Tunnels to Town", "Entrance", player) |  | ||||||
| 
 | 
 | ||||||
|                     if not (direct_access or (exit_to_town or entrance_to_town) and tunnels_to_town): |                     tunnels_from_town = ( | ||||||
|  |                         self.can_reach("Tunnels to Windmill Interior", "Entrance", player) | ||||||
|  |                         and self.can_reach("Town to Windmill Interior", "Entrance", player) | ||||||
|  |                         or self.can_reach("Tunnels to Town", "Entrance", player) | ||||||
|  |                     ) | ||||||
|  | 
 | ||||||
|  |                     if not (direct_access or theater_from_town and tunnels_from_town): | ||||||
|                         valid_option = False |                         valid_option = False | ||||||
|                         break |                         break | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -84,8 +84,6 @@ Disabled Locations: | ||||||
| 0x0070F (Second Row 2) | 0x0070F (Second Row 2) | ||||||
| 0x0087D (Second Row 3) | 0x0087D (Second Row 3) | ||||||
| 0x002C7 (Second Row 4) | 0x002C7 (Second Row 4) | ||||||
| 0x15ADD (River Outside Vault) |  | ||||||
| 0x03702 (River Vault Box) |  | ||||||
| 0x17CAA (Monastery Shortcut Panel) | 0x17CAA (Monastery Shortcut Panel) | ||||||
| 0x0C2A4 (Bunker Entry) | 0x0C2A4 (Bunker Entry) | ||||||
| 0x17C79 (Tinted Glass Door) | 0x17C79 (Tinted Glass Door) | ||||||
|  |  | ||||||
|  | @ -57,7 +57,7 @@ class StaticWitnessLogicObj: | ||||||
|                         "panels": parse_lambda(required_panel_lambda) |                         "panels": parse_lambda(required_panel_lambda) | ||||||
|                     } |                     } | ||||||
| 
 | 
 | ||||||
|                     current_region["panels"].add(check_hex) |                     current_region["panels"].append(check_hex) | ||||||
|                     continue |                     continue | ||||||
| 
 | 
 | ||||||
|                 required_item_lambda = line_split.pop(0) |                 required_item_lambda = line_split.pop(0) | ||||||
|  | @ -117,7 +117,7 @@ class StaticWitnessLogicObj: | ||||||
|                 self.CHECKS_BY_NAME[self.CHECKS_BY_HEX[check_hex]["checkName"]] = self.CHECKS_BY_HEX[check_hex] |                 self.CHECKS_BY_NAME[self.CHECKS_BY_HEX[check_hex]["checkName"]] = self.CHECKS_BY_HEX[check_hex] | ||||||
|                 self.STATIC_DEPENDENT_REQUIREMENTS_BY_HEX[check_hex] = requirement |                 self.STATIC_DEPENDENT_REQUIREMENTS_BY_HEX[check_hex] = requirement | ||||||
| 
 | 
 | ||||||
|                 current_region["panels"].add(check_hex) |                 current_region["panels"].append(check_hex) | ||||||
| 
 | 
 | ||||||
|     def __init__(self, file_path="WitnessLogic.txt"): |     def __init__(self, file_path="WitnessLogic.txt"): | ||||||
|         # All regions with a list of panels in them and the connections to other regions, before logic adjustments |         # All regions with a list of panels in them and the connections to other regions, before logic adjustments | ||||||
|  |  | ||||||
|  | @ -106,7 +106,7 @@ def define_new_region(region_string): | ||||||
|     region_obj = { |     region_obj = { | ||||||
|         "name": region_name, |         "name": region_name, | ||||||
|         "shortName": region_name_simple, |         "shortName": region_name_simple, | ||||||
|         "panels": set() |         "panels": list() | ||||||
|     } |     } | ||||||
|     return region_obj, options |     return region_obj, options | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue