diff --git a/worlds/witness/static_logic.py b/worlds/witness/static_logic.py index 92a89c0351e5..66277547515a 100644 --- a/worlds/witness/static_logic.py +++ b/worlds/witness/static_logic.py @@ -1,6 +1,6 @@ import os -from .utils import define_new_region, parse_lambda, lazy +from .utils import define_new_region, parse_lambda, lazy, get_logic_file, get_items class StaticWitnessLogicObj: @@ -8,116 +8,112 @@ def read_logic_file(self, file_path="WitnessLogic.txt"): """ Reads the logic file and does the initial population of data structures """ - path = os.path.join(os.path.dirname(__file__), file_path) + lines = get_logic_file(file_path) - with open(path, "r", encoding="utf-8") as file: - current_region = dict() + current_region = dict() + counter = 0 - counter = 0 + for line in lines: + if line == "": + continue - for line in file.readlines(): - line = line.strip() + if line[-1] == ":": + 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 - if line == "": - continue - - if line[-1] == ":": - 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(" - ") - - location_id = line_split.pop(0) - - 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) + line_split = line.split(" - ") - full_check_name = current_region["shortName"] + " " + check_name + location_id = line_split.pop(0) - if location_id == "Door" or location_id == "Laser": - self.CHECKS_BY_HEX[check_hex] = { - "checkName": full_check_name, - "checkHex": check_hex, - "region": current_region, - "id": None, - "panelType": location_id - } + check_name_full = line_split.pop(0) - 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"].append(check_hex) - continue - - 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" - elif "Obelisk Side" in check_name: - location_type = "Obelisk Side" - full_check_name = check_name - elif "EP" in check_name: - location_type = "EP" - else: - location_type = "General" - - required_items = parse_lambda(required_item_lambda) - required_panels = parse_lambda(required_panel_lambda) - - required_items = frozenset(required_items) - - requirement = { - "panels": required_panels, - "items": required_items - } + check_hex = check_name_full[0:7] + check_name = check_name_full[9:-1] - if location_type == "Obelisk Side": - eps = set(list(required_panels)[0]) - eps -= {"Theater to Tunnels"} + required_panel_lambda = line_split.pop(0) - 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 + full_check_name = current_region["shortName"] + " " + check_name + if location_id == "Door" or location_id == "Laser": self.CHECKS_BY_HEX[check_hex] = { "checkName": full_check_name, "checkHex": check_hex, "region": current_region, - "id": int(location_id), - "panelType": location_type + "id": None, + "panelType": location_id } - self.ENTITY_ID_TO_NAME[check_hex] = full_check_name - 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] = { + "panels": parse_lambda(required_panel_lambda) + } current_region["panels"].append(check_hex) + continue + + 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" + elif "Obelisk Side" in check_name: + location_type = "Obelisk Side" + full_check_name = check_name + elif "EP" in check_name: + location_type = "EP" + else: + location_type = "General" + + required_items = parse_lambda(required_item_lambda) + required_panels = parse_lambda(required_panel_lambda) + + required_items = frozenset(required_items) + + requirement = { + "panels": required_panels, + "items": required_items + } + + 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 + + self.CHECKS_BY_HEX[check_hex] = { + "checkName": full_check_name, + "checkHex": check_hex, + "region": current_region, + "id": int(location_id), + "panelType": location_type + } + + self.ENTITY_ID_TO_NAME[check_hex] = full_check_name + + 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"].append(check_hex) 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 @@ -166,48 +162,45 @@ 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 + lines = get_items() + current_set = self.ALL_SYMBOL_ITEMS + + for line in lines: + 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: diff --git a/worlds/witness/utils.py b/worlds/witness/utils.py index 8148a15be763..c53436968b26 100644 --- a/worlds/witness/utils.py +++ b/worlds/witness/utils.py @@ -3,7 +3,7 @@ from itertools import accumulate from typing import * from fractions import Fraction -from collections import Counter +from pkgutil import get_data def make_warning_string(any_j: bool, any_u: bool, any_d: bool, all_j: bool, all_u: bool, all_d: bool) -> str: @@ -142,10 +142,8 @@ def __get__(self, instance, class_): def get_adjustment_file(adjustment_file): - path = os.path.join(os.path.dirname(__file__), adjustment_file) - - with open(path) as f: - return [line.strip() for line in f.readlines()] + data = get_data(__name__, adjustment_file).decode('utf-8') + return [line.strip() for line in data.split("\n")] @cache_argsless @@ -225,4 +223,34 @@ def get_ep_no_mountain(): @cache_argsless def get_ep_no_videos(): - return get_adjustment_file("settings/EP_Shuffle/EP_Videos.txt") \ No newline at end of file + return get_adjustment_file("settings/EP_Shuffle/EP_Videos.txt") + + +@cache_argsless +def get_sigma_normal_logic(): + return get_adjustment_file("WitnessLogic.txt") + + +@cache_argsless +def get_sigma_expert_logic(): + return get_adjustment_file("WitnessLogicExpert.txt") + + +@cache_argsless +def get_vanilla_logic(): + return get_adjustment_file("WitnessLogicVanilla.txt") + + +@cache_argsless +def get_items(): + return get_adjustment_file("WitnessItems.txt") + + +def get_logic_file(filepath: str): + if filepath == "WitnessLogic.txt": + return get_sigma_normal_logic() + if filepath == "WitnessLogicExpert.txt": + return get_sigma_expert_logic() + if filepath == "WitnessLogicVanilla.txt": + return get_vanilla_logic + return get_adjustment_file(filepath)