# -*- coding: utf-8 -*- """语义词典:condition/grant kind -> 真实 ID/形态。外置 ir_dictionary.json, 编译器与(M5)Web 后端共读。新增查表类 kind 只改 JSON,零代码改动。 form 决定 grant 编译串形态: money -> "{id},{value}" (银两;正给负扣) item -> "{item},{value}" (道具,item 由 grant 指定 drop_item_data ID) friend -> "{target},{id},{value}" (友好度,需 target NPC slot) join -> roleActionCode "{code}={target}"(入门,需 target) """ import json import os _DICT_PATH = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "ir_dictionary.json") class CompileError(Exception): pass class Dictionary(object): def __init__(self, data): self.conditions = data.get("conditions", {}) self.grants = data.get("grants", {}) # ---- 查询 ---- def is_known_cond(self, kind): return kind in self.conditions def is_known_grant(self, kind): return kind in self.grants def cond_spec(self, kind): return self.conditions.get(kind) def grant_spec(self, kind): return self.grants.get(kind) def grant_needs_target(self, kind): spec = self.grants.get(kind) or {} return bool(spec.get("needs_target")) # ---- 编译 ---- def compile_cond(self, c): """condition -> condition 字段字符串。""" if not c: return "" kind = c.get("kind") spec = self.conditions.get(kind) if not spec: raise CompileError("不支持的 condition kind: %r" % kind) op = c.get("op") ops = spec.get("ops", {}) if op not in ops: raise CompileError("condition %r 不支持比较符 %r" % (kind, op)) return "%s,%s,%s" % (spec["id"], ops[op], c["value"]) def compile_grants(self, grants): """grants -> (resultRewardIds 串, roleActionCode 串)。""" rewards, rac = [], "" for g in grants or []: k = g.get("kind") spec = self.grants.get(k) if not spec: raise CompileError("不支持的 grant kind: %r" % k) form = spec.get("form") if form == "money": rewards.append("%s,%s" % (spec["id"], g["value"])) elif form == "item": rewards.append("%s,%s" % (g["item"], g["value"])) elif form == "friend": rewards.append("%s,%s,%s" % (g["target"], spec["id"], g["value"])) elif form == "join": rac = "%s=%s" % (spec["code"], g["target"]) else: raise CompileError("grant kind %r 的 form %r 未实现" % (k, form)) return ";".join(rewards), rac _cached = None def load_dictionary(path=None): """加载词典(默认缓存同目录 ir_dictionary.json)。""" global _cached if path is None: if _cached is None: with open(_DICT_PATH, encoding="utf-8") as f: _cached = Dictionary(json.load(f)) return _cached with open(path, encoding="utf-8") as f: return Dictionary(json.load(f))