93 lines
2.8 KiB
Python
93 lines
2.8 KiB
Python
"""内置符文集合。
|
|
|
|
对齐酒馆核心子集(``char`` / ``user`` / ``original`` / ``random`` / ``roll`` /
|
|
``getvar``)+ 魂镜扩展(辰正时态宏,复用 ``time_sense.TemporalSnapshot``)。
|
|
全部为纯函数解析器,不做 IO 或代码执行。
|
|
|
|
注:酒馆的 ``pick``(不重复随机)与 ``setvar``(写变量)需要跨调用状态,
|
|
不在无状态渲染层实现;如需,由调用方在 ``MacroContext.variables`` 维护后注入。
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import random
|
|
import re
|
|
|
|
from app.modules.macros.engine import MacroRegistry, MacroResolver
|
|
from app.modules.macros.types import MacroContext
|
|
|
|
|
|
def _char(_args: list[str], ctx: MacroContext) -> str:
|
|
return ctx.char_name or ""
|
|
|
|
|
|
def _user(_args: list[str], ctx: MacroContext) -> str:
|
|
return ctx.user_name or ""
|
|
|
|
|
|
def _original(_args: list[str], ctx: MacroContext) -> str:
|
|
return ctx.original or ""
|
|
|
|
|
|
def _random(args: list[str], _ctx: MacroContext) -> str:
|
|
if not args:
|
|
return ""
|
|
return random.choice(args)
|
|
|
|
|
|
def _roll(args: list[str], _ctx: MacroContext) -> str:
|
|
"""``{{roll:NdM}}`` 或 ``{{roll:dM}}`` → N 个 M 面骰求和。非法规格原样返回。"""
|
|
spec = (args[0] if args else "1d6").strip().casefold()
|
|
match = re.fullmatch(r"(?P<n>\d*)d(?P<sides>\d+)", spec)
|
|
if match is None:
|
|
return spec
|
|
count = int(match.group("n") or 1)
|
|
sides = int(match.group("sides"))
|
|
if count < 1 or sides < 1:
|
|
return spec
|
|
return str(sum(random.randint(1, sides) for _ in range(count)))
|
|
|
|
|
|
def _getvar(args: list[str], ctx: MacroContext) -> str:
|
|
return ctx.variables.get(args[0], "") if args else ""
|
|
|
|
|
|
def _snapshot_field(field: str) -> MacroResolver:
|
|
"""从辰正快照取字段;快照未注入时返回空串。"""
|
|
|
|
def _resolve(_args: list[str], ctx: MacroContext) -> str:
|
|
snap = ctx.snapshot
|
|
if snap is None:
|
|
return ""
|
|
value = getattr(snap, field, None)
|
|
return "" if value is None else str(value)
|
|
|
|
return _resolve
|
|
|
|
|
|
# 辰正时态宏名 → TemporalSnapshot 字段(魂镜扩展)
|
|
_TIME_MACROS: tuple[tuple[str, str], ...] = (
|
|
("date", "solar_date"),
|
|
("time", "local_time"),
|
|
("day_period", "day_period"),
|
|
("shichen", "shichen"),
|
|
("season", "season"),
|
|
("solar_term", "solar_term"),
|
|
("weekday", "weekday"),
|
|
)
|
|
|
|
|
|
def build_default_registry() -> MacroRegistry:
|
|
"""构造默认符文注册表。"""
|
|
reg = MacroRegistry()
|
|
reg.register("char", _char)
|
|
reg.register("bot", _char) # 酒馆别名
|
|
reg.register("user", _user)
|
|
reg.register("original", _original)
|
|
reg.register("random", _random)
|
|
reg.register("roll", _roll)
|
|
reg.register("getvar", _getvar)
|
|
for name, field in _TIME_MACROS:
|
|
reg.register(name, _snapshot_field(field))
|
|
return reg
|