Witness: apworld support (#1885)
This commit is contained in:
parent
7a4e903906
commit
46b13e0b53
|
@ -1,6 +1,6 @@
|
||||||
import os
|
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:
|
class StaticWitnessLogicObj:
|
||||||
|
@ -8,116 +8,112 @@ class StaticWitnessLogicObj:
|
||||||
"""
|
"""
|
||||||
Reads the logic file and does the initial population of data structures
|
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():
|
if line[-1] == ":":
|
||||||
line = line.strip()
|
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 == "":
|
line_split = line.split(" - ")
|
||||||
continue
|
|
||||||
|
|
||||||
if line[-1] == ":":
|
location_id = line_split.pop(0)
|
||||||
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(" - ")
|
check_name_full = line_split.pop(0)
|
||||||
|
|
||||||
location_id = line_split.pop(0)
|
check_hex = check_name_full[0:7]
|
||||||
|
check_name = check_name_full[9:-1]
|
||||||
|
|
||||||
check_name_full = line_split.pop(0)
|
required_panel_lambda = line_split.pop(0)
|
||||||
|
|
||||||
check_hex = check_name_full[0:7]
|
full_check_name = current_region["shortName"] + " " + check_name
|
||||||
check_name = check_name_full[9:-1]
|
|
||||||
|
|
||||||
required_panel_lambda = line_split.pop(0)
|
|
||||||
|
|
||||||
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": 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"].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
|
|
||||||
|
|
||||||
|
if location_id == "Door" or location_id == "Laser":
|
||||||
self.CHECKS_BY_HEX[check_hex] = {
|
self.CHECKS_BY_HEX[check_hex] = {
|
||||||
"checkName": full_check_name,
|
"checkName": full_check_name,
|
||||||
"checkHex": check_hex,
|
"checkHex": check_hex,
|
||||||
"region": current_region,
|
"region": current_region,
|
||||||
"id": int(location_id),
|
"id": None,
|
||||||
"panelType": location_type
|
"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.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)
|
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"):
|
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
|
||||||
|
@ -166,48 +162,45 @@ class StaticWitnessLogic:
|
||||||
Parses currently defined items from WitnessItems.txt
|
Parses currently defined items from WitnessItems.txt
|
||||||
"""
|
"""
|
||||||
|
|
||||||
path = os.path.join(os.path.dirname(__file__), "WitnessItems.txt")
|
lines = get_items()
|
||||||
with open(path, "r", encoding="utf-8") as file:
|
current_set = self.ALL_SYMBOL_ITEMS
|
||||||
current_set = self.ALL_SYMBOL_ITEMS
|
|
||||||
|
|
||||||
for line in file.readlines():
|
for line in lines:
|
||||||
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
|
||||||
|
|
||||||
if line == "Progression:":
|
line_split = line.split(" - ")
|
||||||
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"))
|
||||||
if current_set is self.ALL_USEFULS:
|
elif current_set is self.ALL_DOOR_ITEMS:
|
||||||
current_set.add((line_split[1], int(line_split[0]), line_split[2] == "True"))
|
new_door = (line_split[1], int(line_split[0]), frozenset(line_split[2].split(",")))
|
||||||
elif current_set is self.ALL_DOOR_ITEMS:
|
current_set.add(new_door)
|
||||||
new_door = (line_split[1], int(line_split[0]), frozenset(line_split[2].split(",")))
|
self.ALL_DOOR_ITEMS_AS_DICT[line_split[1]] = new_door
|
||||||
current_set.add(new_door)
|
else:
|
||||||
self.ALL_DOOR_ITEMS_AS_DICT[line_split[1]] = new_door
|
if len(line_split) > 2:
|
||||||
else:
|
progressive_items = line_split[2].split(",")
|
||||||
if len(line_split) > 2:
|
for i, value in enumerate(progressive_items):
|
||||||
progressive_items = line_split[2].split(",")
|
self.ITEMS_TO_PROGRESSIVE[value] = line_split[1]
|
||||||
for i, value in enumerate(progressive_items):
|
self.PROGRESSIVE_TO_ITEMS[line_split[1]] = 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])))
|
current_set.add((line_split[1], int(line_split[0])))
|
||||||
|
continue
|
||||||
|
current_set.add((line_split[1], int(line_split[0])))
|
||||||
|
|
||||||
@lazy
|
@lazy
|
||||||
def sigma_expert(self) -> StaticWitnessLogicObj:
|
def sigma_expert(self) -> StaticWitnessLogicObj:
|
||||||
|
|
|
@ -3,7 +3,7 @@ from Utils import cache_argsless
|
||||||
from itertools import accumulate
|
from itertools import accumulate
|
||||||
from typing import *
|
from typing import *
|
||||||
from fractions import Fraction
|
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:
|
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 @@ class lazy(object):
|
||||||
|
|
||||||
|
|
||||||
def get_adjustment_file(adjustment_file):
|
def get_adjustment_file(adjustment_file):
|
||||||
path = os.path.join(os.path.dirname(__file__), adjustment_file)
|
data = get_data(__name__, adjustment_file).decode('utf-8')
|
||||||
|
return [line.strip() for line in data.split("\n")]
|
||||||
with open(path) as f:
|
|
||||||
return [line.strip() for line in f.readlines()]
|
|
||||||
|
|
||||||
|
|
||||||
@cache_argsless
|
@cache_argsless
|
||||||
|
@ -226,3 +224,33 @@ def get_ep_no_mountain():
|
||||||
@cache_argsless
|
@cache_argsless
|
||||||
def get_ep_no_videos():
|
def get_ep_no_videos():
|
||||||
return get_adjustment_file("settings/EP_Shuffle/EP_Videos.txt")
|
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)
|
||||||
|
|
Loading…
Reference in New Issue