This commit is contained in:
bridge
2025-10-16 00:43:31 +08:00
parent 4295145934
commit 9d9d9737e5
9 changed files with 117 additions and 21 deletions

64
src/classes/effect.py Normal file
View File

@@ -0,0 +1,64 @@
from __future__ import annotations
import json
import ast
from typing import Any
def load_effect_from_str(value: object) -> dict[str, Any]:
"""
解析 effects 字符串为 dict
- 支持 JSON 格式(双引号)
- 支持 Python 字面量(单引号,如 {'k': ['v']})
- value 为 None/空字符串/'nan' 时返回 {}
- 解析非 dict 则返回 {}
"""
if value is None:
return {}
if isinstance(value, dict):
return value
s = str(value).strip()
if not s or s == "nan":
return {}
try:
obj = json.loads(s)
return obj if isinstance(obj, dict) else {}
except Exception:
try:
obj = ast.literal_eval(s)
return obj if isinstance(obj, dict) else {}
except Exception:
return {}
def _merge_effects(base: dict[str, object], addition: dict[str, object]) -> dict[str, object]:
"""
合并两个 effects 字典:
- list 型(如 legal_actions做去重并集
- 数值型:相加
- 其他:后者覆盖前者
返回新字典,不修改原对象。
"""
if not base and not addition:
return {}
merged: dict[str, object] = dict(base) if base else {}
for key, val in (addition or {}).items():
if key in merged:
old = merged[key]
if isinstance(old, list) and isinstance(val, list):
# 去重并集,保持相对顺序
seen: set[object] = set()
result: list[object] = []
for x in old + val:
if x in seen:
continue
seen.add(x)
result.append(x)
merged[key] = result
elif isinstance(old, (int, float)) and isinstance(val, (int, float)):
merged[key] = old + val
else:
merged[key] = val
else:
merged[key] = val
return merged