| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  | """
 | 
					
						
							|  |  |  | Parses the WitnessLogic.txt logic file into useful data structures. | 
					
						
							|  |  |  | This is the heart of the randomization. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | In WitnessLogic.txt we have regions defined with their connections: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Region Name (Short name) - Connected Region 1 - Connection Requirement 1 - Connected Region 2... | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | And then panels in that region with the hex code used in the game | 
					
						
							|  |  |  | previous panels that are required to turn them on, as well as the symbols they require: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 0x##### (Panel Name) - Required Panels - Required Items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | On __init__, the base logic is read and all panels are given Location IDs. | 
					
						
							|  |  |  | When the world has parsed its options, a second function is called to finalize the logic. | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import copy | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  | from typing import Set, Dict | 
					
						
							|  |  |  | from logging import warning | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  | from BaseClasses import MultiWorld | 
					
						
							|  |  |  | from .static_logic import StaticWitnessLogic | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  | from .utils import define_new_region, get_disable_unrandomized_list, parse_lambda, get_early_utm_list, \ | 
					
						
							|  |  |  |     get_symbol_shuffle_list, get_door_panel_shuffle_list, get_doors_complex_list, get_doors_max_list, \ | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |     get_doors_simple_list, get_laser_shuffle, get_ep_all_individual, get_ep_obelisks, get_ep_easy, get_ep_no_eclipse, \ | 
					
						
							|  |  |  |     get_ep_no_caves, get_ep_no_mountain, get_ep_no_videos | 
					
						
							| 
									
										
										
										
											2022-06-16 03:04:45 +02:00
										 |  |  | from .Options import is_option_enabled, get_option_value, the_witness_options | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class WitnessPlayerLogic: | 
					
						
							|  |  |  |     """WITNESS LOGIC CLASS""" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def reduce_req_within_region(self, panel_hex): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Panels in this game often only turn on when other panels are solved. | 
					
						
							|  |  |  |         Those other panels may have different item requirements. | 
					
						
							|  |  |  |         It would be slow to recursively check solvability each time. | 
					
						
							|  |  |  |         This is why we reduce the item dependencies within the region. | 
					
						
							|  |  |  |         Panels outside of the same region will still be checked manually. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-06 16:23:13 +01:00
										 |  |  |         if panel_hex in self.COMPLETELY_DISABLED_CHECKS or panel_hex in self.PRECOMPLETED_LOCATIONS: | 
					
						
							| 
									
										
										
										
											2022-08-22 05:50:01 +02:00
										 |  |  |             return frozenset() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-09 04:13:52 +02:00
										 |  |  |         check_obj = self.REFERENCE_LOGIC.CHECKS_BY_HEX[panel_hex] | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         these_items = frozenset({frozenset()}) | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |         if check_obj["id"]: | 
					
						
							|  |  |  |             these_items = self.DEPENDENT_REQUIREMENTS_BY_HEX[panel_hex]["items"] | 
					
						
							| 
									
										
										
										
											2022-06-16 03:04:45 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         these_items = frozenset({ | 
					
						
							| 
									
										
										
										
											2022-10-09 04:13:52 +02:00
										 |  |  |             subset.intersection(self.THEORETICAL_ITEMS_NO_MULTI) | 
					
						
							| 
									
										
										
										
											2022-06-16 03:04:45 +02:00
										 |  |  |             for subset in these_items | 
					
						
							|  |  |  |         }) | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-09 04:13:52 +02:00
										 |  |  |         for subset in these_items: | 
					
						
							|  |  |  |             self.PROG_ITEMS_ACTUALLY_IN_THE_GAME_NO_MULTI.update(subset) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |         if panel_hex in self.DOOR_ITEMS_BY_ID: | 
					
						
							|  |  |  |             door_items = frozenset({frozenset([item]) for item in self.DOOR_ITEMS_BY_ID[panel_hex]}) | 
					
						
							| 
									
										
										
										
											2022-06-16 03:04:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |             all_options = set() | 
					
						
							| 
									
										
										
										
											2022-06-16 03:04:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-09 04:13:52 +02:00
										 |  |  |             for dependentItem in door_items: | 
					
						
							|  |  |  |                 self.PROG_ITEMS_ACTUALLY_IN_THE_GAME_NO_MULTI.update(dependentItem) | 
					
						
							|  |  |  |                 for items_option in these_items: | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |                     all_options.add(items_option.union(dependentItem)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-18 04:20:59 +02:00
										 |  |  |             if panel_hex != "0x28A0D": | 
					
						
							|  |  |  |                 return frozenset(all_options) | 
					
						
							|  |  |  |             else:  # 0x28A0D depends on another entity for *non-power* reasons -> This dependency needs to be preserved | 
					
						
							|  |  |  |                 these_items = all_options | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         these_panels = self.DEPENDENT_REQUIREMENTS_BY_HEX[panel_hex]["panels"] | 
					
						
							| 
									
										
										
										
											2022-06-16 03:04:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |         these_panels = frozenset({panels - self.PRECOMPLETED_LOCATIONS for panels in these_panels}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-16 03:04:45 +02:00
										 |  |  |         if these_panels == frozenset({frozenset()}): | 
					
						
							|  |  |  |             return these_items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         all_options = set() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |         for option in these_panels: | 
					
						
							|  |  |  |             dependent_items_for_option = frozenset({frozenset()}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for option_panel in option: | 
					
						
							| 
									
										
										
										
											2022-10-09 04:13:52 +02:00
										 |  |  |                 dep_obj = self.REFERENCE_LOGIC.CHECKS_BY_HEX.get(option_panel) | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-22 05:50:01 +02:00
										 |  |  |                 if option_panel in self.COMPLETELY_DISABLED_CHECKS: | 
					
						
							|  |  |  |                     new_items = frozenset() | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |                 elif option_panel in {"7 Lasers", "11 Lasers", "PP2 Weirdness", "Theater to Tunnels"}: | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |                     new_items = frozenset({frozenset([option_panel])}) | 
					
						
							|  |  |  |                 # If a panel turns on when a panel in a different region turns on, | 
					
						
							|  |  |  |                 # the latter panel will be an "event panel", unless it ends up being | 
					
						
							|  |  |  |                 # a location itself. This prevents generation failures. | 
					
						
							|  |  |  |                 elif dep_obj["region"]["name"] != check_obj["region"]["name"]: | 
					
						
							|  |  |  |                     new_items = frozenset({frozenset([option_panel])}) | 
					
						
							|  |  |  |                     self.EVENT_PANELS_FROM_PANELS.add(option_panel) | 
					
						
							| 
									
										
										
										
											2022-06-16 03:04:45 +02:00
										 |  |  |                 elif option_panel in self.ALWAYS_EVENT_NAMES_BY_HEX.keys(): | 
					
						
							|  |  |  |                     new_items = frozenset({frozenset([option_panel])}) | 
					
						
							|  |  |  |                     self.EVENT_PANELS_FROM_PANELS.add(option_panel) | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |                 else: | 
					
						
							|  |  |  |                     new_items = self.reduce_req_within_region(option_panel) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 updated_items = set() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 for items_option in dependent_items_for_option: | 
					
						
							|  |  |  |                     for items_option2 in new_items: | 
					
						
							|  |  |  |                         updated_items.add(items_option.union(items_option2)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 dependent_items_for_option = updated_items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for items_option in these_items: | 
					
						
							|  |  |  |                 for dependentItem in dependent_items_for_option: | 
					
						
							|  |  |  |                     all_options.add(items_option.union(dependentItem)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return frozenset(all_options) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def make_single_adjustment(self, adj_type, line): | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |         from . import StaticWitnessItems | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |         """Makes a single logic adjustment based on additional logic file""" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |         if adj_type == "Items": | 
					
						
							| 
									
										
										
										
											2022-10-09 04:13:52 +02:00
										 |  |  |             line_split = line.split(" - ") | 
					
						
							|  |  |  |             item = line_split[0] | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-09 04:13:52 +02:00
										 |  |  |             if item not in StaticWitnessItems.ALL_ITEM_TABLE: | 
					
						
							|  |  |  |                 raise RuntimeError("Item \"" + item + "\" does not exit.") | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-09 04:13:52 +02:00
										 |  |  |             self.THEORETICAL_ITEMS.add(item) | 
					
						
							|  |  |  |             self.THEORETICAL_ITEMS_NO_MULTI.update(StaticWitnessLogic.PROGRESSIVE_TO_ITEMS.get(item, [item])) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if item in StaticWitnessLogic.ALL_DOOR_ITEMS_AS_DICT: | 
					
						
							|  |  |  |                 panel_hexes = StaticWitnessLogic.ALL_DOOR_ITEMS_AS_DICT[item][2] | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |                 for panel_hex in panel_hexes: | 
					
						
							| 
									
										
										
										
											2022-10-09 04:13:52 +02:00
										 |  |  |                     self.DOOR_ITEMS_BY_ID.setdefault(panel_hex, set()).add(item) | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if adj_type == "Remove Items": | 
					
						
							| 
									
										
										
										
											2022-10-09 04:13:52 +02:00
										 |  |  |             self.THEORETICAL_ITEMS.discard(line) | 
					
						
							|  |  |  |             for i in StaticWitnessLogic.PROGRESSIVE_TO_ITEMS.get(line, [line]): | 
					
						
							|  |  |  |                 self.THEORETICAL_ITEMS_NO_MULTI.discard(i) | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if line in StaticWitnessLogic.ALL_DOOR_ITEMS_AS_DICT: | 
					
						
							|  |  |  |                 panel_hexes = StaticWitnessLogic.ALL_DOOR_ITEMS_AS_DICT[line][2] | 
					
						
							|  |  |  |                 for panel_hex in panel_hexes: | 
					
						
							|  |  |  |                     if panel_hex in self.DOOR_ITEMS_BY_ID: | 
					
						
							|  |  |  |                         self.DOOR_ITEMS_BY_ID[panel_hex].discard(line) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if adj_type == "Starting Inventory": | 
					
						
							|  |  |  |             self.STARTING_INVENTORY.add(line) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |         if adj_type == "Event Items": | 
					
						
							|  |  |  |             line_split = line.split(" - ") | 
					
						
							|  |  |  |             hex_set = line_split[1].split(",") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for hex_code in hex_set: | 
					
						
							|  |  |  |                 self.ALWAYS_EVENT_NAMES_BY_HEX[hex_code] = line_split[0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             """
 | 
					
						
							|  |  |  |             Should probably do this differently... | 
					
						
							|  |  |  |             Events right now depend on a panel. | 
					
						
							|  |  |  |             That seems bad. | 
					
						
							|  |  |  |             """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             to_remove = set() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for hex_code, event_name in self.ALWAYS_EVENT_NAMES_BY_HEX.items(): | 
					
						
							|  |  |  |                 if hex_code not in hex_set and event_name == line_split[0]: | 
					
						
							|  |  |  |                     to_remove.add(hex_code) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for remove in to_remove: | 
					
						
							|  |  |  |                 del self.ALWAYS_EVENT_NAMES_BY_HEX[remove] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if adj_type == "Requirement Changes": | 
					
						
							|  |  |  |             line_split = line.split(" - ") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             requirement = { | 
					
						
							|  |  |  |                 "panels": parse_lambda(line_split[1]), | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |             if len(line_split) > 2: | 
					
						
							|  |  |  |                 required_items = parse_lambda(line_split[2]) | 
					
						
							|  |  |  |                 items_actually_in_the_game = {item[0] for item in StaticWitnessLogic.ALL_SYMBOL_ITEMS} | 
					
						
							|  |  |  |                 required_items = frozenset( | 
					
						
							|  |  |  |                     subset.intersection(items_actually_in_the_game) | 
					
						
							|  |  |  |                     for subset in required_items | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 requirement["items"] = required_items | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |             self.DEPENDENT_REQUIREMENTS_BY_HEX[line_split[0]] = requirement | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if adj_type == "Disabled Locations": | 
					
						
							| 
									
										
										
										
											2022-06-16 03:04:45 +02:00
										 |  |  |             panel_hex = line[:7] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             self.COMPLETELY_DISABLED_CHECKS.add(panel_hex) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if adj_type == "Region Changes": | 
					
						
							|  |  |  |             new_region_and_options = define_new_region(line + ":") | 
					
						
							|  |  |  |              | 
					
						
							|  |  |  |             self.CONNECTIONS_BY_REGION_NAME[new_region_and_options[0]["name"]] = new_region_and_options[1] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if adj_type == "Added Locations": | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |             if "0x" in line: | 
					
						
							|  |  |  |                 line = StaticWitnessLogic.CHECKS_BY_HEX[line]["checkName"] | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |             self.ADDED_CHECKS.add(line) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |         if adj_type == "Precompleted Locations": | 
					
						
							|  |  |  |             self.PRECOMPLETED_LOCATIONS.add(line) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |     def make_options_adjustments(self, world, player): | 
					
						
							|  |  |  |         """Makes logic adjustments based on options""" | 
					
						
							|  |  |  |         adjustment_linesets_in_order = [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-16 03:04:45 +02:00
										 |  |  |         if get_option_value(world, player, "victory_condition") == 0: | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |             self.VICTORY_LOCATION = "0x3D9A9" | 
					
						
							| 
									
										
										
										
											2022-06-16 03:04:45 +02:00
										 |  |  |         elif get_option_value(world, player, "victory_condition") == 1: | 
					
						
							|  |  |  |             self.VICTORY_LOCATION = "0x0356B" | 
					
						
							|  |  |  |         elif get_option_value(world, player, "victory_condition") == 2: | 
					
						
							|  |  |  |             self.VICTORY_LOCATION = "0x09F7F" | 
					
						
							|  |  |  |         elif get_option_value(world, player, "victory_condition") == 3: | 
					
						
							|  |  |  |             self.VICTORY_LOCATION = "0xFFF00" | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-22 05:50:01 +02:00
										 |  |  |         if get_option_value(world, player, "challenge_lasers") <= 7: | 
					
						
							|  |  |  |             adjustment_linesets_in_order.append([ | 
					
						
							|  |  |  |                 "Requirement Changes:", | 
					
						
							|  |  |  |                 "0xFFF00 - 11 Lasers - True", | 
					
						
							|  |  |  |             ]) | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if is_option_enabled(world, player, "disable_non_randomized_puzzles"): | 
					
						
							|  |  |  |             adjustment_linesets_in_order.append(get_disable_unrandomized_list()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-16 03:04:45 +02:00
										 |  |  |         if is_option_enabled(world, player, "shuffle_symbols") or "shuffle_symbols" not in the_witness_options.keys(): | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |             adjustment_linesets_in_order.append(get_symbol_shuffle_list()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |         if get_option_value(world, player, "EP_difficulty") == 0: | 
					
						
							|  |  |  |             adjustment_linesets_in_order.append(get_ep_easy()) | 
					
						
							|  |  |  |         elif get_option_value(world, player, "EP_difficulty") == 1: | 
					
						
							|  |  |  |             adjustment_linesets_in_order.append(get_ep_no_eclipse()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not is_option_enabled(world, player, "shuffle_vault_boxes"): | 
					
						
							|  |  |  |             adjustment_linesets_in_order.append(get_ep_no_videos()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         doors = get_option_value(world, player, "shuffle_doors") >= 2 | 
					
						
							|  |  |  |         earlyutm = is_option_enabled(world, player, "early_secret_area") | 
					
						
							|  |  |  |         victory = get_option_value(world, player, "victory_condition") | 
					
						
							|  |  |  |         mount_lasers = get_option_value(world, player, "mountain_lasers") | 
					
						
							|  |  |  |         chal_lasers = get_option_value(world, player, "challenge_lasers") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         excluse_postgame = not is_option_enabled(world, player, "shuffle_postgame") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if excluse_postgame and not (earlyutm or doors): | 
					
						
							|  |  |  |             adjustment_linesets_in_order.append(get_ep_no_caves()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         mountain_enterable_from_top = victory == 0 or victory == 1 or (victory == 3 and chal_lasers > mount_lasers) | 
					
						
							|  |  |  |         if excluse_postgame and not mountain_enterable_from_top: | 
					
						
							|  |  |  |             adjustment_linesets_in_order.append(get_ep_no_mountain()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |         if get_option_value(world, player, "shuffle_doors") == 1: | 
					
						
							|  |  |  |             adjustment_linesets_in_order.append(get_door_panel_shuffle_list()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if get_option_value(world, player, "shuffle_doors") == 2: | 
					
						
							|  |  |  |             adjustment_linesets_in_order.append(get_doors_simple_list()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if get_option_value(world, player, "shuffle_doors") == 3: | 
					
						
							|  |  |  |             adjustment_linesets_in_order.append(get_doors_complex_list()) | 
					
						
							| 
									
										
										
										
											2022-06-16 03:04:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |         if get_option_value(world, player, "shuffle_doors") == 4: | 
					
						
							|  |  |  |             adjustment_linesets_in_order.append(get_doors_max_list()) | 
					
						
							| 
									
										
										
										
											2022-06-16 03:04:45 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if is_option_enabled(world, player, "early_secret_area"): | 
					
						
							|  |  |  |             adjustment_linesets_in_order.append(get_early_utm_list()) | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |         for item in self.YAML_ADDED_ITEMS: | 
					
						
							|  |  |  |             adjustment_linesets_in_order.append(["Items:", item]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |         if is_option_enabled(world, player, "shuffle_lasers"): | 
					
						
							|  |  |  |             adjustment_linesets_in_order.append(get_laser_shuffle()) | 
					
						
							| 
									
										
										
										
											2022-06-16 03:04:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |         if get_option_value(world, player, "shuffle_EPs") == 0:  # No EP Shuffle | 
					
						
							|  |  |  |             adjustment_linesets_in_order.append(["Disabled Locations:"] + get_ep_all_individual()[1:]) | 
					
						
							|  |  |  |             adjustment_linesets_in_order.append(["Disabled Locations:"] + get_ep_obelisks()[1:]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         elif get_option_value(world, player, "shuffle_EPs") == 1:  # Individual EPs | 
					
						
							|  |  |  |             adjustment_linesets_in_order.append(["Disabled Locations:"] + get_ep_obelisks()[1:]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         else:  # Obelisk Sides | 
					
						
							|  |  |  |             yaml_disabled_eps = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for yaml_disabled_location in self.YAML_DISABLED_LOCATIONS: | 
					
						
							|  |  |  |                 if yaml_disabled_location not in StaticWitnessLogic.CHECKS_BY_NAME: | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 loc_obj = StaticWitnessLogic.CHECKS_BY_NAME[yaml_disabled_location] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if loc_obj["panelType"] != "EP": | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 yaml_disabled_eps.append(loc_obj["checkHex"]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             adjustment_linesets_in_order.append(["Precompleted Locations:"] + yaml_disabled_eps) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |         for adjustment_lineset in adjustment_linesets_in_order: | 
					
						
							|  |  |  |             current_adjustment_type = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for line in adjustment_lineset: | 
					
						
							|  |  |  |                 if len(line) == 0: | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if line[-1] == ":": | 
					
						
							|  |  |  |                     current_adjustment_type = line[:-1] | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 self.make_single_adjustment(current_adjustment_type, line) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def make_dependency_reduced_checklist(self): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Turns dependent check set into semi-independent check set | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for check_hex in self.DEPENDENT_REQUIREMENTS_BY_HEX.keys(): | 
					
						
							|  |  |  |             indep_requirement = self.reduce_req_within_region(check_hex) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             self.REQUIREMENTS_BY_HEX[check_hex] = indep_requirement | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-09 04:13:52 +02:00
										 |  |  |         for item in self.PROG_ITEMS_ACTUALLY_IN_THE_GAME_NO_MULTI: | 
					
						
							|  |  |  |             if item not in self.THEORETICAL_ITEMS: | 
					
						
							|  |  |  |                 corresponding_multi = StaticWitnessLogic.ITEMS_TO_PROGRESSIVE[item] | 
					
						
							|  |  |  |                 self.PROG_ITEMS_ACTUALLY_IN_THE_GAME.add(corresponding_multi) | 
					
						
							|  |  |  |                 multi_list = StaticWitnessLogic.PROGRESSIVE_TO_ITEMS[StaticWitnessLogic.ITEMS_TO_PROGRESSIVE[item]] | 
					
						
							|  |  |  |                 multi_list = [item for item in multi_list if item in self.PROG_ITEMS_ACTUALLY_IN_THE_GAME_NO_MULTI] | 
					
						
							|  |  |  |                 self.MULTI_AMOUNTS[item] = multi_list.index(item) + 1 | 
					
						
							|  |  |  |                 self.MULTI_LISTS[corresponding_multi] = multi_list | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 self.PROG_ITEMS_ACTUALLY_IN_THE_GAME.add(item) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |     def make_event_item_pair(self, panel): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Makes a pair of an event panel and its event item | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |         action = " Opened" if StaticWitnessLogic.CHECKS_BY_HEX[panel]["panelType"] == "Door" else " Solved" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         name = StaticWitnessLogic.CHECKS_BY_HEX[panel]["checkName"] + action | 
					
						
							|  |  |  |         if panel not in self.EVENT_ITEM_NAMES: | 
					
						
							|  |  |  |             if StaticWitnessLogic.CHECKS_BY_HEX[panel]["panelType"] == "EP": | 
					
						
							|  |  |  |                 obelisk = StaticWitnessLogic.CHECKS_BY_HEX[StaticWitnessLogic.EP_TO_OBELISK_SIDE[panel]]["checkName"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 self.EVENT_ITEM_NAMES[panel] = obelisk + " - " + StaticWitnessLogic.CHECKS_BY_HEX[panel]["checkName"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 warning("Panel \"" + name + "\" does not have an associated event name.") | 
					
						
							|  |  |  |                 self.EVENT_ITEM_NAMES[panel] = name + " Event" | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |         pair = (name, self.EVENT_ITEM_NAMES[panel]) | 
					
						
							|  |  |  |         return pair | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def make_event_panel_lists(self): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Special event panel data structures | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.ALWAYS_EVENT_NAMES_BY_HEX[self.VICTORY_LOCATION] = "Victory" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |         for region_name, connections in self.CONNECTIONS_BY_REGION_NAME.items(): | 
					
						
							|  |  |  |             for connection in connections: | 
					
						
							|  |  |  |                 for panel_req in connection[1]: | 
					
						
							|  |  |  |                     for panel in panel_req: | 
					
						
							|  |  |  |                         if panel == "TrueOneWay": | 
					
						
							|  |  |  |                             continue | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-09 04:13:52 +02:00
										 |  |  |                         if self.REFERENCE_LOGIC.CHECKS_BY_HEX[panel]["region"]["name"] != region_name: | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |                             self.EVENT_PANELS_FROM_REGIONS.add(panel) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.EVENT_PANELS.update(self.EVENT_PANELS_FROM_PANELS) | 
					
						
							|  |  |  |         self.EVENT_PANELS.update(self.EVENT_PANELS_FROM_REGIONS) | 
					
						
							| 
									
										
										
										
											2022-06-16 03:04:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |         for always_hex, always_item in self.ALWAYS_EVENT_NAMES_BY_HEX.items(): | 
					
						
							|  |  |  |             self.ALWAYS_EVENT_HEX_CODES.add(always_hex) | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |             self.EVENT_PANELS.add(always_hex) | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |             self.EVENT_ITEM_NAMES[always_hex] = always_item | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |         for panel in self.EVENT_PANELS: | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |             pair = self.make_event_item_pair(panel) | 
					
						
							|  |  |  |             self.EVENT_ITEM_PAIRS[pair[0]] = pair[1] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |     def __init__(self, world: MultiWorld, player: int, disabled_locations: Set[str], start_inv: Dict[str, int]): | 
					
						
							|  |  |  |         self.YAML_DISABLED_LOCATIONS = disabled_locations | 
					
						
							|  |  |  |         self.YAML_ADDED_ITEMS = start_inv | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |         self.EVENT_PANELS_FROM_PANELS = set() | 
					
						
							|  |  |  |         self.EVENT_PANELS_FROM_REGIONS = set() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-09 04:13:52 +02:00
										 |  |  |         self.THEORETICAL_ITEMS = set() | 
					
						
							|  |  |  |         self.THEORETICAL_ITEMS_NO_MULTI = set() | 
					
						
							|  |  |  |         self.MULTI_AMOUNTS = dict() | 
					
						
							|  |  |  |         self.MULTI_LISTS = dict() | 
					
						
							|  |  |  |         self.PROG_ITEMS_ACTUALLY_IN_THE_GAME_NO_MULTI = set() | 
					
						
							| 
									
										
										
										
											2022-06-16 03:04:45 +02:00
										 |  |  |         self.PROG_ITEMS_ACTUALLY_IN_THE_GAME = set() | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |         self.DOOR_ITEMS_BY_ID = dict() | 
					
						
							|  |  |  |         self.STARTING_INVENTORY = set() | 
					
						
							| 
									
										
										
										
											2022-06-16 03:04:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-09 04:13:52 +02:00
										 |  |  |         self.DIFFICULTY = get_option_value(world, player, "puzzle_randomization") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if self.DIFFICULTY == 0: | 
					
						
							|  |  |  |             self.REFERENCE_LOGIC = StaticWitnessLogic.sigma_normal | 
					
						
							|  |  |  |         elif self.DIFFICULTY == 1: | 
					
						
							|  |  |  |             self.REFERENCE_LOGIC = StaticWitnessLogic.sigma_expert | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |         elif self.DIFFICULTY == 2: | 
					
						
							|  |  |  |             self.REFERENCE_LOGIC = StaticWitnessLogic.vanilla | 
					
						
							| 
									
										
										
										
											2022-10-09 04:13:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.CONNECTIONS_BY_REGION_NAME = copy.copy(self.REFERENCE_LOGIC.STATIC_CONNECTIONS_BY_REGION_NAME) | 
					
						
							|  |  |  |         self.DEPENDENT_REQUIREMENTS_BY_HEX = copy.copy(self.REFERENCE_LOGIC.STATIC_DEPENDENT_REQUIREMENTS_BY_HEX) | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |         self.REQUIREMENTS_BY_HEX = dict() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Determining which panels need to be events is a difficult process. | 
					
						
							|  |  |  |         # At the end, we will have EVENT_ITEM_PAIRS for all the necessary ones. | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |         self.EVENT_PANELS = set() | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |         self.EVENT_ITEM_PAIRS = dict() | 
					
						
							|  |  |  |         self.ALWAYS_EVENT_HEX_CODES = set() | 
					
						
							|  |  |  |         self.COMPLETELY_DISABLED_CHECKS = set() | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |         self.PRECOMPLETED_LOCATIONS = set() | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |         self.ADDED_CHECKS = set() | 
					
						
							|  |  |  |         self.VICTORY_LOCATION = "0x0356B" | 
					
						
							|  |  |  |         self.EVENT_ITEM_NAMES = { | 
					
						
							| 
									
										
										
										
											2022-09-18 04:20:59 +02:00
										 |  |  |             "0x09D9B": "Monastery Shutters Open", | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |             "0x193A6": "Monastery Laser Panel Activates", | 
					
						
							|  |  |  |             "0x00037": "Monastery Branch Panels Activate", | 
					
						
							|  |  |  |             "0x0A079": "Access to Bunker Laser", | 
					
						
							|  |  |  |             "0x0A3B5": "Door to Tutorial Discard Opens", | 
					
						
							| 
									
										
										
										
											2022-07-28 23:43:35 +02:00
										 |  |  |             "0x00139": "Keep Hedges 1 Knowledge", | 
					
						
							|  |  |  |             "0x019DC": "Keep Hedges 2 Knowledge", | 
					
						
							|  |  |  |             "0x019E7": "Keep Hedges 3 Knowledge", | 
					
						
							| 
									
										
										
										
											2023-03-03 00:08:24 +01:00
										 |  |  |             "0x01A0F": "Keep Hedges 4 Knowledge", | 
					
						
							|  |  |  |             "0x033EA": "Pressure Plates 1 Knowledge", | 
					
						
							|  |  |  |             "0x01BE9": "Pressure Plates 2 Knowledge", | 
					
						
							|  |  |  |             "0x01CD3": "Pressure Plates 3 Knowledge", | 
					
						
							|  |  |  |             "0x01D3F": "Pressure Plates 4 Knowledge", | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |             "0x09F7F": "Mountain Access", | 
					
						
							| 
									
										
										
										
											2023-02-07 03:12:47 +01:00
										 |  |  |             "0x0367C": "Quarry Laser Stoneworks Requirement Met", | 
					
						
							| 
									
										
										
										
											2022-09-18 04:20:59 +02:00
										 |  |  |             "0x009A1": "Swamp Between Bridges Far 1 Activates", | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |             "0x00006": "Swamp Cyan Water Drains", | 
					
						
							| 
									
										
										
										
											2022-09-18 04:20:59 +02:00
										 |  |  |             "0x00990": "Swamp Between Bridges Near Row 1 Activates", | 
					
						
							|  |  |  |             "0x0A8DC": "Intro 6 Activates", | 
					
						
							|  |  |  |             "0x0000A": "Swamp Beyond Rotating Bridge 1 Access", | 
					
						
							|  |  |  |             "0x09E86": "Mountain Floor 2 Blue Bridge Access", | 
					
						
							|  |  |  |             "0x09ED8": "Mountain Floor 2 Yellow Bridge Access", | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |             "0x0A3D0": "Quarry Laser Boathouse Requirement Met", | 
					
						
							|  |  |  |             "0x00596": "Swamp Red Water Drains", | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |             "0x00E3A": "Swamp Purple Water Drains", | 
					
						
							| 
									
										
										
										
											2022-06-16 03:04:45 +02:00
										 |  |  |             "0x0343A": "Door to Symmetry Island Powers On", | 
					
						
							| 
									
										
										
										
											2022-09-18 04:20:59 +02:00
										 |  |  |             "0xFFF00": "Mountain Bottom Floor Discard Turns On", | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |             "0x17CA6": "All Boat Panels Turn On", | 
					
						
							|  |  |  |             "0x17CDF": "All Boat Panels Turn On", | 
					
						
							|  |  |  |             "0x09DB8": "All Boat Panels Turn On", | 
					
						
							|  |  |  |             "0x17C95": "All Boat Panels Turn On", | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |             "0x0A054": "Couch EP solvable", | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |             "0x03BB0": "Town Church Lattice Vision From Outside", | 
					
						
							| 
									
										
										
										
											2022-09-18 04:20:59 +02:00
										 |  |  |             "0x28AC1": "Town Wooden Rooftop Turns On", | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |             "0x28A69": "Town Tower 1st Door Opens", | 
					
						
							|  |  |  |             "0x28ACC": "Town Tower 2nd Door Opens", | 
					
						
							|  |  |  |             "0x28AD9": "Town Tower 3rd Door Opens", | 
					
						
							|  |  |  |             "0x28B39": "Town Tower 4th Door Opens", | 
					
						
							| 
									
										
										
										
											2023-02-07 03:12:47 +01:00
										 |  |  |             "0x03675": "Quarry Stoneworks Ramp Activation From Above", | 
					
						
							|  |  |  |             "0x03679": "Quarry Stoneworks Lift Lowering While Standing On It", | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |             "0x2FAF6": "Tutorial Gate Secret Solution Knowledge", | 
					
						
							| 
									
										
										
										
											2022-09-18 04:20:59 +02:00
										 |  |  |             "0x079DF": "Town Tall Hexagonal Turns On", | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |             "0x17DA2": "Right Orange Bridge Fully Extended", | 
					
						
							| 
									
										
										
										
											2022-09-18 04:20:59 +02:00
										 |  |  |             "0x19B24": "Shadows Intro Patterns Visible", | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |             "0x2700B": "Open Door to Treehouse Laser House", | 
					
						
							|  |  |  |             "0x00055": "Orchard Apple Trees 4 Turns On", | 
					
						
							| 
									
										
										
										
											2022-08-11 15:57:33 +02:00
										 |  |  |             "0x17DDB": "Left Orange Bridge Fully Extended", | 
					
						
							| 
									
										
										
										
											2022-08-22 05:50:01 +02:00
										 |  |  |             "0x03535": "Shipwreck Video Pattern Knowledge", | 
					
						
							|  |  |  |             "0x03542": "Mountain Video Pattern Knowledge", | 
					
						
							|  |  |  |             "0x0339E": "Desert Video Pattern Knowledge", | 
					
						
							|  |  |  |             "0x03481": "Tutorial Video Pattern Knowledge", | 
					
						
							|  |  |  |             "0x03702": "Jungle Video Pattern Knowledge", | 
					
						
							|  |  |  |             "0x0356B": "Challenge Video Pattern Knowledge", | 
					
						
							| 
									
										
										
										
											2022-09-18 04:20:59 +02:00
										 |  |  |             "0x0A15F": "Desert Laser Panel Shutters Open (1)", | 
					
						
							|  |  |  |             "0x012D7": "Desert Laser Panel Shutters Open (2)", | 
					
						
							| 
									
										
										
										
											2022-10-09 04:13:52 +02:00
										 |  |  |             "0x03613": "Treehouse Orange Bridge 13 Turns On", | 
					
						
							|  |  |  |             "0x17DEC": "Treehouse Laser House Access Requirement", | 
					
						
							|  |  |  |             "0x03C08": "Town Church Entry Opens", | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |             "0x17D02": "Windmill Blades Spinning", | 
					
						
							|  |  |  |             "0x0A0C9": "Cargo Box EP completable", | 
					
						
							|  |  |  |             "0x09E39": "Pink Light Bridge Extended", | 
					
						
							|  |  |  |             "0x17CC4": "Rails EP available", | 
					
						
							|  |  |  |             "0x2896A": "Bridge Underside EP available", | 
					
						
							|  |  |  |             "0x00064": "First Tunnel EP visible", | 
					
						
							|  |  |  |             "0x03553": "Tutorial Video EPs availble", | 
					
						
							|  |  |  |             "0x17C79": "Bunker Door EP available", | 
					
						
							| 
									
										
										
										
											2023-02-07 03:12:47 +01:00
										 |  |  |             "0x275FF": "Stoneworks Light EPs available", | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |             "0x17E2B": "Remaining Purple Sand EPs available", | 
					
						
							|  |  |  |             "0x03852": "Ramp EPs requirement", | 
					
						
							|  |  |  |             "0x334D8": "RGB panels & EPs solvable", | 
					
						
							|  |  |  |             "0x03750": "Left Garden EP available", | 
					
						
							|  |  |  |             "0x03C0C": "RGB Flowers EP requirement", | 
					
						
							|  |  |  |             "0x01CD5": "Pressure Plates 3 EP requirement", | 
					
						
							|  |  |  |             "0x3865F": "Ramp EPs access requirement", | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.ALWAYS_EVENT_NAMES_BY_HEX = { | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |             "0x00509": "Symmetry Laser Activation", | 
					
						
							|  |  |  |             "0x012FB": "Desert Laser Activation", | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |             "0x09F98": "Desert Laser Redirection", | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |             "0x01539": "Quarry Laser Activation", | 
					
						
							|  |  |  |             "0x181B3": "Shadows Laser Activation", | 
					
						
							|  |  |  |             "0x014BB": "Keep Laser Activation", | 
					
						
							|  |  |  |             "0x17C65": "Monastery Laser Activation", | 
					
						
							|  |  |  |             "0x032F9": "Town Laser Activation", | 
					
						
							|  |  |  |             "0x00274": "Jungle Laser Activation", | 
					
						
							|  |  |  |             "0x0C2B2": "Bunker Laser Activation", | 
					
						
							|  |  |  |             "0x00BF6": "Swamp Laser Activation", | 
					
						
							|  |  |  |             "0x028A4": "Treehouse Laser Activation", | 
					
						
							| 
									
										
										
										
											2022-06-16 03:04:45 +02:00
										 |  |  |             "0x09F7F": "Mountaintop Trap Door Turns On", | 
					
						
							|  |  |  |             "0x17C34": "Mountain Access", | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.make_options_adjustments(world, player) | 
					
						
							|  |  |  |         self.make_dependency_reduced_checklist() | 
					
						
							|  |  |  |         self.make_event_panel_lists() |