| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  | import os | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-09 04:13:52 +02:00
										 |  |  | from .utils import define_new_region, parse_lambda, lazy | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-09 04:13:52 +02:00
										 |  |  | class StaticWitnessLogicObj: | 
					
						
							|  |  |  |     def read_logic_file(self, file_path="WitnessLogic.txt"): | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |         """
 | 
					
						
							|  |  |  |         Reads the logic file and does the initial population of data structures | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2022-10-09 04:13:52 +02:00
										 |  |  |         path = os.path.join(os.path.dirname(__file__), file_path) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |         with open(path, "r", encoding="utf-8") as file: | 
					
						
							| 
									
										
										
										
											2022-06-16 03:04:45 +02:00
										 |  |  |             current_region = dict() | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |             counter = 0 | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             for line in file.readlines(): | 
					
						
							|  |  |  |                 line = line.strip() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if line == "": | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |                 if line[-1] == ":": | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |                     new_region_and_connections = define_new_region(line) | 
					
						
							|  |  |  |                     current_region = new_region_and_connections[0] | 
					
						
							|  |  |  |                     region_name = current_region["name"] | 
					
						
							|  |  |  |                     self.ALL_REGIONS_BY_NAME[region_name] = current_region | 
					
						
							|  |  |  |                     self.STATIC_CONNECTIONS_BY_REGION_NAME[region_name] = new_region_and_connections[1] | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 line_split = line.split(" - ") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |                 location_id = line_split.pop(0) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |                 check_name_full = line_split.pop(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 check_hex = check_name_full[0:7] | 
					
						
							|  |  |  |                 check_name = check_name_full[9:-1] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 required_panel_lambda = line_split.pop(0) | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |                 full_check_name = current_region["shortName"] + " " + check_name | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |                 if location_id == "Door" or location_id == "Laser": | 
					
						
							|  |  |  |                     self.CHECKS_BY_HEX[check_hex] = { | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |                         "checkName": full_check_name, | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |                         "checkHex": check_hex, | 
					
						
							|  |  |  |                         "region": current_region, | 
					
						
							|  |  |  |                         "id": None, | 
					
						
							|  |  |  |                         "panelType": location_id | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     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] = { | 
					
						
							|  |  |  |                         "panels": parse_lambda(required_panel_lambda) | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     current_region["panels"].add(check_hex) | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |                 required_item_lambda = line_split.pop(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 laser_names = { | 
					
						
							|  |  |  |                     "Laser", | 
					
						
							|  |  |  |                     "Laser Hedges", | 
					
						
							|  |  |  |                     "Laser Pressure Plates", | 
					
						
							|  |  |  |                     "Desert Laser Redirect" | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 is_vault_or_video = "Vault" in check_name or "Video" in check_name | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if "Discard" in check_name: | 
					
						
							|  |  |  |                     location_type = "Discard" | 
					
						
							|  |  |  |                 elif is_vault_or_video or check_name == "Tutorial Gate Close": | 
					
						
							|  |  |  |                     location_type = "Vault" | 
					
						
							|  |  |  |                 elif check_name in laser_names: | 
					
						
							|  |  |  |                     location_type = "Laser" | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |                 elif "Obelisk Side" in check_name: | 
					
						
							|  |  |  |                     location_type = "Obelisk Side" | 
					
						
							|  |  |  |                     full_check_name = check_name | 
					
						
							|  |  |  |                 elif "EP" in check_name: | 
					
						
							|  |  |  |                     location_type = "EP" | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |                 else: | 
					
						
							|  |  |  |                     location_type = "General" | 
					
						
							| 
									
										
										
										
											2022-06-16 03:04:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |                 required_items = parse_lambda(required_item_lambda) | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |                 required_panels = parse_lambda(required_panel_lambda) | 
					
						
							| 
									
										
										
										
											2022-06-16 03:04:45 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 required_items = frozenset(required_items) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |                 requirement = { | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |                     "panels": required_panels, | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |                     "items": required_items | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |                 if location_type == "Obelisk Side": | 
					
						
							|  |  |  |                     eps = set(list(required_panels)[0]) | 
					
						
							|  |  |  |                     eps -= {"Theater to Tunnels"} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     eps_ints = {int(h, 16) for h in eps} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     self.OBELISK_SIDE_ID_TO_EP_HEXES[int(check_hex, 16)] = eps_ints | 
					
						
							|  |  |  |                     for ep_hex in eps: | 
					
						
							|  |  |  |                         self.EP_TO_OBELISK_SIDE[ep_hex] = check_hex | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |                 self.CHECKS_BY_HEX[check_hex] = { | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |                     "checkName": full_check_name, | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |                     "checkHex": check_hex, | 
					
						
							|  |  |  |                     "region": current_region, | 
					
						
							| 
									
										
										
										
											2022-07-17 12:56:22 +02:00
										 |  |  |                     "id": int(location_id), | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |                     "panelType": location_type | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-10 07:58:00 +01:00
										 |  |  |                 self.ENTITY_ID_TO_NAME[check_hex] = full_check_name | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |                 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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 current_region["panels"].add(check_hex) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-09 04:13:52 +02:00
										 |  |  |     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 | 
					
						
							|  |  |  |         self.ALL_REGIONS_BY_NAME = dict() | 
					
						
							|  |  |  |         self.STATIC_CONNECTIONS_BY_REGION_NAME = dict() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.CHECKS_BY_HEX = dict() | 
					
						
							|  |  |  |         self.CHECKS_BY_NAME = dict() | 
					
						
							|  |  |  |         self.STATIC_DEPENDENT_REQUIREMENTS_BY_HEX = dict() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |         self.OBELISK_SIDE_ID_TO_EP_HEXES = dict() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.EP_TO_OBELISK_SIDE = dict() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-10 07:58:00 +01:00
										 |  |  |         self.ENTITY_ID_TO_NAME = dict() | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-09 04:13:52 +02:00
										 |  |  |         self.read_logic_file(file_path) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class StaticWitnessLogic: | 
					
						
							|  |  |  |     ALL_SYMBOL_ITEMS = set() | 
					
						
							|  |  |  |     ITEMS_TO_PROGRESSIVE = dict() | 
					
						
							|  |  |  |     PROGRESSIVE_TO_ITEMS = dict() | 
					
						
							|  |  |  |     ALL_DOOR_ITEMS = set() | 
					
						
							|  |  |  |     ALL_DOOR_ITEMS_AS_DICT = dict() | 
					
						
							|  |  |  |     ALL_USEFULS = set() | 
					
						
							|  |  |  |     ALL_TRAPS = set() | 
					
						
							|  |  |  |     ALL_BOOSTS = set() | 
					
						
							|  |  |  |     CONNECTIONS_TO_SEVER_BY_DOOR_HEX = dict() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ALL_REGIONS_BY_NAME = dict() | 
					
						
							|  |  |  |     STATIC_CONNECTIONS_BY_REGION_NAME = dict() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |     OBELISK_SIDE_ID_TO_EP_HEXES = dict() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-09 04:13:52 +02:00
										 |  |  |     CHECKS_BY_HEX = dict() | 
					
						
							|  |  |  |     CHECKS_BY_NAME = dict() | 
					
						
							|  |  |  |     STATIC_DEPENDENT_REQUIREMENTS_BY_HEX = dict() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |     EP_TO_OBELISK_SIDE = dict() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-10 07:58:00 +01:00
										 |  |  |     ENTITY_ID_TO_NAME = dict() | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-09 04:13:52 +02:00
										 |  |  |     def parse_items(self): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Parses currently defined items from WitnessItems.txt | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         path = os.path.join(os.path.dirname(__file__), "WitnessItems.txt") | 
					
						
							|  |  |  |         with open(path, "r", encoding="utf-8") as file: | 
					
						
							|  |  |  |             current_set = self.ALL_SYMBOL_ITEMS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for line in file.readlines(): | 
					
						
							|  |  |  |                 line = line.strip() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if line == "Progression:": | 
					
						
							|  |  |  |                     current_set = self.ALL_SYMBOL_ITEMS | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  |                 if line == "Boosts:": | 
					
						
							|  |  |  |                     current_set = self.ALL_BOOSTS | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  |                 if line == "Traps:": | 
					
						
							|  |  |  |                     current_set = self.ALL_TRAPS | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  |                 if line == "Usefuls:": | 
					
						
							|  |  |  |                     current_set = self.ALL_USEFULS | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  |                 if line == "Doors:": | 
					
						
							|  |  |  |                     current_set = self.ALL_DOOR_ITEMS | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  |                 if line == "": | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 line_split = line.split(" - ") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if current_set is self.ALL_USEFULS: | 
					
						
							|  |  |  |                     current_set.add((line_split[1], int(line_split[0]), line_split[2] == "True")) | 
					
						
							|  |  |  |                 elif current_set is self.ALL_DOOR_ITEMS: | 
					
						
							|  |  |  |                     new_door = (line_split[1], int(line_split[0]), frozenset(line_split[2].split(","))) | 
					
						
							|  |  |  |                     current_set.add(new_door) | 
					
						
							|  |  |  |                     self.ALL_DOOR_ITEMS_AS_DICT[line_split[1]] = new_door | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     if len(line_split) > 2: | 
					
						
							|  |  |  |                         progressive_items = line_split[2].split(",") | 
					
						
							|  |  |  |                         for i, value in enumerate(progressive_items): | 
					
						
							|  |  |  |                             self.ITEMS_TO_PROGRESSIVE[value] = line_split[1] | 
					
						
							|  |  |  |                         self.PROGRESSIVE_TO_ITEMS[line_split[1]] = progressive_items | 
					
						
							|  |  |  |                         current_set.add((line_split[1], int(line_split[0]))) | 
					
						
							|  |  |  |                         continue | 
					
						
							|  |  |  |                     current_set.add((line_split[1], int(line_split[0]))) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @lazy | 
					
						
							|  |  |  |     def sigma_expert(self) -> StaticWitnessLogicObj: | 
					
						
							|  |  |  |         return StaticWitnessLogicObj("WitnessLogicExpert.txt") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @lazy | 
					
						
							|  |  |  |     def sigma_normal(self) -> StaticWitnessLogicObj: | 
					
						
							|  |  |  |         return StaticWitnessLogicObj("WitnessLogic.txt") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |     @lazy | 
					
						
							|  |  |  |     def vanilla(self) -> StaticWitnessLogicObj: | 
					
						
							|  |  |  |         return StaticWitnessLogicObj("WitnessLogicVanilla.txt") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-29 00:42:11 +02:00
										 |  |  |     def __init__(self): | 
					
						
							|  |  |  |         self.parse_items() | 
					
						
							| 
									
										
										
										
											2022-10-09 04:13:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.ALL_REGIONS_BY_NAME.update(self.sigma_normal.ALL_REGIONS_BY_NAME) | 
					
						
							|  |  |  |         self.STATIC_CONNECTIONS_BY_REGION_NAME.update(self.sigma_normal.STATIC_CONNECTIONS_BY_REGION_NAME) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.CHECKS_BY_HEX.update(self.sigma_normal.CHECKS_BY_HEX) | 
					
						
							|  |  |  |         self.CHECKS_BY_NAME.update(self.sigma_normal.CHECKS_BY_NAME) | 
					
						
							|  |  |  |         self.STATIC_DEPENDENT_REQUIREMENTS_BY_HEX.update(self.sigma_normal.STATIC_DEPENDENT_REQUIREMENTS_BY_HEX) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-01 21:18:07 +01:00
										 |  |  |         self.OBELISK_SIDE_ID_TO_EP_HEXES.update(self.sigma_normal.OBELISK_SIDE_ID_TO_EP_HEXES) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.EP_TO_OBELISK_SIDE.update(self.sigma_normal.EP_TO_OBELISK_SIDE) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-10 07:58:00 +01:00
										 |  |  |         self.ENTITY_ID_TO_NAME.update(self.sigma_normal.ENTITY_ID_TO_NAME) |