Skip to content

Latest commit

 

History

History
276 lines (214 loc) · 6.79 KB

File metadata and controls

276 lines (214 loc) · 6.79 KB

本地开发任务书:OSR-Engine 通用跑团规则引擎

任务编号:TRPG-LOCAL-2024
执行环境:本地 venv(已预配置)
交付形式:本地文件包 + 测试报告


1. 项目概述

开发一个通用 OSR 跑团引擎,核心目标:引擎层零业务逻辑,所有规则(种族、职业、技能)通过插件或 YAML 配置实现。


2. 执行环境(已搭建完成)

2.1 环境状态

  • Python:3.10+(已安装)
  • 包管理器uv(已安装)
  • 虚拟环境.venv/ 已创建(位于项目根目录,勿删)
  • 项目文件夹/home/user/osr-engine 已创建骨架

2.2 开工前激活环境

# Windows(已执行)
.venv\Scripts\activate

# 验证 Python 版本 (已执行)
python --version  # 应显示 3.10+

2.3 依赖安装(待执行)

uv add pyyaml pytest pytest-cov black ruff mypy

3. 项目结构(待创建目录)

/osr_trpg_engine/
├── engine/                 # 你负责的核心引擎代码
│   ├── __init__.py
│   ├── dice.py            # 骰子解析
│   ├── entity.py          # 角色实体 + 存读档
│   ├── source.py          # 数值来源抽象
│   └── yaml_source.py     # YAML 驱动
├── rules/                 # 业务规则示例
│   ├── __init__.py
│   ├── basic1981.py       # Moldvay Basic 规则
│   └── yaml/              # YAML 规则包
│       ├── human.yaml
│       └── fighter_l1.yaml
├── tests/                 # 测试用例(必须全覆盖)
│   ├── test_dice.py
│   ├── test_source.py
│   └── test_entity.py
├── cli.py                 # 可选命令行工具
└── save/                  # 存档目录(自动生成)

4. 开发任务清单

4.1 核心引擎模块(必须 100% 测试覆盖)

engine/dice.py

def roll(expr: str, variables: dict[str, int] | None = None) -> int:
    """
    解析并掷骰子表达式。
    语法:3d6, 1d20+5, d%, d4+str_mod+prof
    安全:禁止任意代码执行
    """

测试用例

assert roll("3d6") in range(3, 19)
assert roll("1d20+5") >= 6
assert roll("d20+mod", {"mod": 3}) in range(4, 24)

engine/source.py

class Source(ABC):
    @abstractmethod
    def priority(self) -> int: ...
    @abstractmethod
    def keys(self) -> list[str]: ...
    def get(self, key: str) -> Any: ...
    def mode(self, key: str) -> Literal["override", "add", "mul"]: ...

class CompositeSource(Source):
    def add(self, src: Source) -> None: ...
    def remove(self, src: Source) -> None: ...
    def get_final(self, key: str, default: Any = 0) -> Any: ...

叠加规则

  1. priority 降序排列
  2. override:直接替换当前值
  3. add:累加当前值
  4. mul:连乘当前值

测试用例

def test_priority_override():
    low = MockSource(10, {"str": 2}, {"str": "add"})
    high = MockSource(50, {"str": 18}, {"str": "override"})
    comp = CompositeSource()
    comp.add(low); comp.add(high)
    assert comp.get_final("str") == 18

engine/entity.py

class Entity:
    def __init__(self, rulebook: Any): ...
    def set(self, key: str, value: Any) -> Entity: ...
    def get(self, key: str, default: Any = 0) -> Any: ...
    def attach(self, src: Source) -> Entity: ...
    def detach(self, src: Source) -> Entity: ...
    def check(self, expr: str, difficulty: int | None = None) -> bool: ...
    def to_dict(self) -> dict[str, Any]: ...
    def save_json(self, path: str) -> None: ...
    @staticmethod
    def from_dict(rulebook: Any, data: dict[str, Any]) -> Entity: ...

engine/yaml_source.py

class YamlSource(Source):
    def __init__(self, yaml_path: str): ...

def load_yaml_folder(folder: str) -> list[YamlSource]: ...

YAML 格式

# rules/yaml/fighter_l1.yaml
name: Fighter L1
priority: 30
values:
  hd: 8
  to_hit: 1
modes:
  hd: override
  to_hit: add

4.2 规则示例

rules/basic1981.py 需提供完整 Moldvay Basic 角色创建逻辑


5. 代码风格规范(强制)

5.1 格式化

# 每次保存后执行
black engine/ rules/ tests/
ruff check --fix engine/ rules/ tests/
mypy --strict engine/

配置pyproject.toml 已内置

5.2 类型注解

  • 所有函数必须带完整类型注解
  • 使用 dict, list 原生类型

5.3 命名

  • 类:PascalCase
  • 函数/变量:snake_case
  • 常量:UPPER_SNAKE_CASE

5.4 注释

  • 复杂逻辑需行内注释
  • 公共类/函数必须有三引号文档

6. 测试标准

6.1 覆盖率

pytest --cov=engine --cov-report=html --cov-fail-under=95
  • 覆盖率 ≥ 95%
  • 所有分支必须测试

6.2 测试类别

  • 单元测试、集成测试、边界测试、异常测试

7. Code Review 自查清单

  • pytest 0 failed
  • 覆盖率 ≥ 95%
  • Black/Ruff/MyPy 零警告
  • 无调试代码
  • eval() 安全
  • 手动验证存档/读档

8. 步骤执行建议

步骤 1:实现骰子解析

  • 文件:engine/dice.py
  • 目标:让 roll("3d6+2") 能正确返回整数
  • 产出:通过 tests/test_dice.py 所有测试

步骤 2:实现数值来源

  • 文件:engine/source.py
  • 目标:CompositeSource 能按优先级叠加数值
  • 产出:通过 tests/test_source.py 所有测试

步骤 3:实现角色实体

  • 文件:engine/entity.py
  • 目标:Entity 能挂 Source、读写 base、存读档
  • 产出:通过 tests/test_entity.py 所有测试

步骤 4:实现 YAML 驱动

  • 文件:engine/yaml_source.py
  • 目标:能从 YAML 文件加载 Source
  • 产出:手动测试 load_yaml_folder() 返回正确列表

步骤 5:编写规则示例

  • 文件:rules/basic1981.py + rules/yaml/*.yaml
  • 目标:cli.py 能跑通 basic1981 角色创建
  • 产出:终端可看到生成的角色数据

步骤 6:集成测试

  • 文件:tests/test_integration.py
  • 目标:全流程测试覆盖率达 95%
  • 产出:htmlcov/index.html 报告

步骤 7:代码规范修正

  • 执行:black, ruff, mypy
  • 目标:零警告、零错误
  • 产出:代码整洁、类型安全

步骤 8:最终验证

  • 执行:./verify.sh(需自行创建)
  • 目标:所有检查通过
  • 产出:准备打包交付

9. 交付物

  1. 完整代码/home/user/osr-engine/ 目录
  2. 测试报告:覆盖率 HTML 文件 + 终端截图
  3. 验证脚本verify.sh 执行成功记录

10. 技术支持

  • 环境疑问:检查 .venv/ 是否激活
  • 测试失败:确保文件命名 test_*.py
  • 类型错误:运行 mypy engine/ 查看详情