mirror of
https://github.com/ArchipelagoMW/Archipelago.git
synced 2026-10-09 00:13:04 -07:00
115 lines
4.4 KiB
Python
115 lines
4.4 KiB
Python
from __future__ import annotations
|
|
|
|
import re
|
|
|
|
import Utils
|
|
from BaseClasses import CollectionState, Location
|
|
from NetUtils import JSONMessagePart
|
|
from . import StardewValleyWorld
|
|
from .logic.logic import StardewLogic
|
|
from .stardew_rule.rule_explain import explain, ExplainMode, RuleExplanation
|
|
|
|
|
|
def cmd_explain(world: StardewValleyWorld, target_name: str, state: CollectionState) -> list[JSONMessagePart]:
|
|
logic = world.logic
|
|
|
|
if target_name.startswith("item "):
|
|
is_item_explain = True
|
|
target_name = target_name[len("item "):]
|
|
else:
|
|
is_item_explain = False
|
|
|
|
if target_name.startswith("missing "):
|
|
expected = True
|
|
target_name = target_name[len("missing "):]
|
|
elif target_name.startswith("how "):
|
|
expected = False
|
|
target_name = target_name[len("how "):]
|
|
else:
|
|
expected = None
|
|
|
|
possible_answers = logic.registry.item_rules.keys() if is_item_explain else world.get_all_location_names()
|
|
result, usable, response = Utils.get_intended_text(target_name, possible_answers)
|
|
if usable:
|
|
if is_item_explain:
|
|
rule = logic.has(result)
|
|
else:
|
|
rule = logic.region.can_reach_location(result)
|
|
expl = explain(rule, state, expected=expected, mode=ExplainMode.CLIENT)
|
|
world.previous_explanation = expl
|
|
return parse_explanation(expl)
|
|
else:
|
|
return [{"type": "color", "color": "salmon", "text": response}]
|
|
|
|
|
|
def cmd_more(world: StardewValleyWorld, index: str, state: CollectionState) -> list[JSONMessagePart]:
|
|
logic = world.logic
|
|
|
|
if world.previous_explanation is None:
|
|
return [{"type": "color", "color": "salmon", "text": "No previous explanation found"}]
|
|
|
|
try:
|
|
expl = world.previous_explanation.more(int(index))
|
|
except (ValueError, IndexError):
|
|
return [{"type": "text", "text": "Which previous rule do you want to be explained?"}]
|
|
|
|
world.previous_explanation = expl
|
|
return parse_explanation(expl)
|
|
|
|
|
|
def parse_explanation(explanation: RuleExplanation) -> list[list[JSONMessagePart]]:
|
|
# Split the explanation in parts, by isolating all the delimiters, being \(, \), & , -> , | , \d+x , \[ , \] , \(\w+\), \n\s*
|
|
result_regex = r"\s*(\(|\)| & | -> | \| |\d+x | \[|\](?: ->)?\s*| \(\w+\)|\n)"
|
|
splits = re.split(result_regex, str(explanation).strip())
|
|
|
|
messages = []
|
|
contents = []
|
|
content_length = 0
|
|
for s in splits:
|
|
if len(s) == 0:
|
|
continue
|
|
|
|
content_length += len(s)
|
|
|
|
if s == "True":
|
|
messages.append({"type": "color", "color": "green", "text": s})
|
|
elif s == "False":
|
|
messages.append({"type": "color", "color": "salmon", "text": s})
|
|
elif s.startswith("Reach Location "):
|
|
messages.append({"type": "text", "text": "Reach Location "})
|
|
messages.append({"type": "location_name", "text": s[15:]})
|
|
elif s.startswith("Reach Entrance "):
|
|
messages.append({"type": "text", "text": "Reach Entrance "})
|
|
messages.append({"type": "entrance_name", "text": s[15:]})
|
|
elif s.startswith("Reach Region "):
|
|
messages.append({"type": "text", "text": "Reach Region "})
|
|
messages.append({"type": "color", "color": "yellow", "text": s[13:]})
|
|
elif s.startswith("Received event "):
|
|
messages.append({"type": "text", "text": "Received event "})
|
|
messages.append({"type": "item_name", "text": s[15:]})
|
|
elif s.startswith("Received "):
|
|
messages.append({"type": "text", "text": "Received "})
|
|
messages.append({"type": "item_name", "flags": 0b001, "text": s[9:]})
|
|
elif s.startswith("Has "):
|
|
if s[4].isdigit():
|
|
messages.append({"type": "text", "text": "Has "})
|
|
digit_end = re.search(r"\D", s[4:])
|
|
digit = s[4:4 + digit_end.start()]
|
|
messages.append({"type": "color", "color": "cyan", "text": digit})
|
|
messages.append({"type": "text", "text": s[4 + digit_end.start():]})
|
|
|
|
else:
|
|
messages.append({"text": s, "type": "text"})
|
|
else:
|
|
messages.append({"text": s, "type": "text"})
|
|
|
|
if content_length > 5000 and s.endswith("\n"):
|
|
contents[-1]["text"] = contents[-1]["text"][:-1]
|
|
messages.append(contents)
|
|
contents = []
|
|
content_length = 0
|
|
|
|
messages.append(contents)
|
|
|
|
return messages
|