通用游戏数值计算框架 — DAG 公式引擎 + 声明式 UI 渲染 + 搜索枚举引擎
Project description
calc-framework — 通用伤害计算框架
适配任意 RPG 游戏的公式可配置伤害计算框架。 公式写在 DAG JSON 中,无需改代码即可调整乘区顺序、增删乘区、修改计算逻辑。
架构总览
┌─────────────────────────────────────────────┐
│ 适配包 (AdapterPackage) │
│ ┌──────────┐ ┌──────────┐ ┌───────────┐ │
│ │ meta.json│ │ dag/* │ │ ui/* │ │
│ │ │ │ .dag.json│ │ layout.json│ │
│ └──────────┘ └──────────┘ └───────────┘ │
└──────────────────────┬──────────────────────┘
│ 加载
┌──────────────────────▼──────────────────────┐
│ 框架核心 (calc_framework) │
│ │
│ ┌─────────────┐ ┌──────────────────┐ │
│ │ DAG 引擎 │ │ DataContext │ │
│ │ 9 种节点类型 │ │ 标准上下文 │ │
│ │ 拓扑排序 │ │ make_context() │ │
│ │ 子图展开 │ │ DataContextLoader│ │
│ │ AST 沙箱 │ │ (抽象基类) │ │
│ └─────────────┘ └──────────────────┘ │
│ │
│ ┌─────────────┐ ┌──────────────────┐ │
│ │ ComputeSheet│ │ 日志系统 │ │
│ │ 自动渲染输入 │ │ setup_logging() │ │
│ │ 实时求值 │ │ get_logger() │ │
│ └─────────────┘ └──────────────────┘ │
└──────────────────────────────────────────────┘
快速开始
from calc_framework.config.adapter import AdapterPackage
from calc_framework.data.loader import DataContextLoader
from calc_framework.data.context import make_context
# 1. 加载适配包
pkg = AdapterPackage("path/to/game-adapter")
# 2. 构建数据上下文
ctx = make_context(
character={"基础攻击": 100, "力量": 50},
weapon={"基础攻击": 40},
computed={"最终攻击力": 140},
)
# 3. 求值
result = pkg.dag_service.evaluate(ctx)
print(result.outputs)
核心模块
DAG 引擎 — calc_framework.dag
| 模块 | 职责 |
|---|---|
schema.py |
9 种节点类型(const/var/unary/binary/condition/expr/user_input/call) |
engine.py |
拓扑排序 + 节点求值 + 默认值回退 |
subgraph.py |
call 节点内联展开 |
sandbox.py |
AST 解析 + 白名单校验 + 安全求值 |
serializer.py |
DAG JSON ↔ DAGGraph(加载时自动展开模板引用) |
service.py |
DAGService 统一入口 |
templates.py |
可复用公式模板库(5 内置模板,支持 "template" 字段引用) |
配置/加载层 — calc_framework.config
| 模块 | 职责 |
|---|---|
adapter.py |
适配包加载器(meta.json → DAGService) |
manager.py |
适配器管理器(发现/缓存/加载多个适配包) |
搜索/枚举引擎 — calc_framework.search
| 模块 | 职责 |
|---|---|
tracker.py |
Top-N 结果追踪(通用泛型) |
cancel.py |
搜索取消令牌(超量/主动取消) |
parallel.py |
并行执行器(进度回调、Top-N、取消) |
result.py |
通用搜索结果类型 |
适用于任何需要遍历大量候选并保留最优结果的场景(配装搜索、参数枚举、伤害最大化等)。
插件系统 — calc_framework.plugin
| 模块 | 职责 |
|---|---|
base.py |
BasePlugin / PluginMeta 基类 |
registry.py |
PluginRegistry 全局注册表 |
builtin.py |
3 内置插件(crit_handler / dodge_handler / distance_decay) |
发布/分享 — calc_framework.publish
| 模块 | 职责 |
|---|---|
schema.py |
JSON Schema 校验(validate_package) |
catalog.py |
静态 HTML 目录生成(build_catalog) |
数据层 — calc_framework.data
| 模块 | 职责 |
|---|---|
context.py |
DataContext TypedDict + make_context 工厂 |
loader.py |
DataContextLoader 抽象基类 |
schema.py |
四层数据契约(EntitySchema / SkillSchema / SegmentSchema) |
attr_schema.py |
属性声明 Schema — 适配器声明字段结构,框架自动构建 DataContext(resolve/validate) |
UI 层 — calc_framework.ui
| 模块 | 职责 |
|---|---|
compute_sheet.py |
声明式计算表 QWidget,从 DAG + layout.json 自动渲染 |
controls.py |
infer_control 根据变量声明推断控件类型 |
layout.py |
Layout/Section 排版定义 |
format.py |
数值格式化 |
配置层 — calc_framework.config
| 模块 | 职责 |
|---|---|
adapter.py |
AdapterPackage 加载 meta.json + DAG |
适配包结构
一个完整的游戏适配包:
my-game-adapter/
├── meta.json # 元信息
├── attr_schema.json # 属性声明 Schema(可选)
├── dag/ # DAG 公式定义
│ └── main.dag.json
└── ui/ # UI 排版定义
└── layout.json
meta.json 示例:
{
"name": "我的游戏伤害计算",
"game": "我的游戏",
"version": "1.0.0",
"schema_version": "dag-v1",
"entry_dag": "dag/main.dag.json"
}
也可引用 attr_schema.json 和自定义函数:
{
"name": "卡牌RPG伤害计算",
"game": "经典卡牌RPG(示例)",
"version": "1.0.0",
"schema_version": "dag-v1",
"entry_dag": "card_rpg.dag.json",
"attr_schema": "attr_schema.json",
"functions": {
"clamp": "functions.py"
}
}
适配器示例
终末地(15 乘区)
framework/games/endfield/ — 真实游戏完整适配器。
卡牌RPG(攻击-防御公式)
framework/adapters/card_rpg/ — 示例适配器,证明框架跨品类通用。
framework/adapters/card_rpg/
├── meta.json # 适配器元信息
├── attr_schema.json # 属性声明(ATK/DEF/crit_rate/crit_dmg)
├── card_rpg.dag.json # DAG 公式(attack - def × 0.5 + crit)
├── functions.py # 自定义函数(clamp)
├── loader.py # CardRPGLoader(DataContextLoader 实现)
└── ui/layout.json # ComputeSheet 排版
from calc_framework.config.adapter import AdapterPackage
# 加载卡牌RPG适配器
pkg = AdapterPackage("framework/adapters/card_rpg")
# 构建上下文并求值
ctx = {
"character": {"ATK": 100, "crit_rate": 0.05, "crit_dmg": 0.5},
"weapon": {"ATK_bonus": 15},
"enemy": {"DEF": 60},
"user_input": {"skill_mult": 1.0, "is_crit": True},
}
result = pkg.dag_service.evaluate(ctx)
print(result.outputs)
# {"总攻击力": 115.0, "基础伤害": 85.0, "暴击倍率": 1.5, "最终伤害": 127.5}
构建 DAG 公式
DAG JSON 是框架的核心配置。一个完整 DAG 包含:
{
"schema_version": "dag-v1",
"name": "伤害计算",
"variables": {
"character.基础攻击": {
"type": "float",
"source": "character",
"description": "角色基础攻击力"
}
},
"subgraphs": {
"final_attack": { "nodes": { ... }, "outputs": { ... } }
},
"nodes": {
"base_atk": {
"type": "var",
"path": "character.基础攻击"
},
"total_atk": {
"type": "binary",
"op": "+",
"lhs": "base_atk",
"rhs": "weapon_atk"
}
},
"outputs": {
"最终攻击力": { "node": "total_atk", "label": "最终攻击力" }
}
}
DAG 模板
框架内置 5 个通用公式模板(defense_reduction、crit_multiplier、clamp_to_range、percent_of、attribute_scaling),可在 DAG JSON 中直接引用:
{
"def_reduc": {
"template": "defense_reduction",
"bindings": {
"defense": "enemy_def",
"scale": "const_0_5"
}
}
}
加载时自动展开为完整节点。也可通过 register_template() 注册自定义模板。
日志
from calc_framework.logging import setup_logging, get_logger
from calc_framework.data.attr_schema import AttributeSchema
# 在应用入口调用一次
setup_logging(level="INFO", log_file="calc.log")
# 在各模块获取 logger
logger = get_logger(__name__)
logger.info("DAG 求值完成")
# 加载属性 Schema
schema = AttributeSchema.from_file("attr_schema.json")
ctx = schema.resolve(raw_data)
errors = schema.validate(ctx)
环境变量控制:CALC_FRAMEWORK_LOG_LEVEL(默认 WARNING)、CALC_FRAMEWORK_LOG_FILE。
游戏启动器
通过 calc_framework.launcher 可交互选择适配包并启动 ComputeSheet GUI:
# 交互选择
python -m calc_framework.launcher
# 直接指定
python -m calc_framework.launcher "终末地计算器(Calc Framework)"
适配器搜索路径由 CALC_ADAPTERS_DIR 环境变量控制(默认 framework/adapters/)。
发布 Catalog
python -c "from calc_framework.publish import build_catalog; build_catalog('dist')"
生成 dist/index.html,可部署到 GitHub Pages 作为社区适配器市场。
开发与测试
测试
cd framework
python -m pytest tests/ -q # 293 passed
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file calc_framework-0.3.0.tar.gz.
File metadata
- Download URL: calc_framework-0.3.0.tar.gz
- Upload date:
- Size: 141.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
389339b970dbcab518a71231047c5b799acd932f17f375145061ad4effc0f3c7
|
|
| MD5 |
55c7952bf19958846da81c3eebe1e422
|
|
| BLAKE2b-256 |
41a85bc8d7093e0a74edb6669bb4cc3bd9de959ab92a32bd7e774d4cb6e55b95
|
File details
Details for the file calc_framework-0.3.0-py3-none-any.whl.
File metadata
- Download URL: calc_framework-0.3.0-py3-none-any.whl
- Upload date:
- Size: 189.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
840e5d0add6596a7289252a70e98d3a473521d775ea85a7423db3cb4fded376e
|
|
| MD5 |
27d4283633f22fbb1ab3a454512784b6
|
|
| BLAKE2b-256 |
5751e954610db8c2c11a99afb62dd52a87175aa1996eb851897232c4bdb46f86
|