New Rule Completeness Validator by calcitem/sanmill
npx skills add https://github.com/calcitem/sanmill --skill 'New Rule Completeness Validator'当向 Sanmill 添加新的游戏规则或规则变体时,你需要修改多个文件(通常是 70-80 个文件,包括约 60 个本地化文件)。此技能提供了一个完整性检查清单,以确保不会遗漏任何必要的代码更改。
参考文档:docs/guides/ADDING_NEW_GAME_RULES.md
Sanmill 是基于配置的,而非基于继承。规则变体以数据形式表达(C++ 中的
Rule,Flutter 中的RuleSettings),并在运行时切换。任何新机制都必须通过布尔值/参数来控制,以便现有变体保持原样且运行快速。
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
src/rule.cppRULES[] 数组末尾添加了新规则定义name - 规则名称(最多 32 个字符)description - 规则描述(最多 512 个字符)pieceCount, flyPieceCount, piecesAtLeastCounthasDiagonalLines - 是否存在对角线mayFly, nMoveRule 等)示例结构:
{
"Your Rule Name",
"Short description",
9, 3, 3, // pieceCount, flyPieceCount, piecesAtLeastCount
false, // hasDiagonalLines
MillFormationActionInPlacingPhase::removeOpponentsPieceFromBoard,
/*mayMoveInPlacingPhase*/ false,
/*isDefenderMoveFirst*/ false,
/*mayRemoveMultiple*/ false,
// ... 其他字段
kDefaultCaptureRuleConfig, // custodian
kDefaultCaptureRuleConfig, // intervention
kDefaultCaptureRuleConfig, // leap
/*mayFly*/ true,
/*nMoveRule*/ 100,
/*endgameNMoveRule*/ 100,
/*threefoldRepetitionRule*/ true
}
src/rule.hN_RULES 常量(以匹配新的 RULES[] 长度)Rule 结构体添加了新字段?// 例如,如果原来是 11,现在应该是 12
constexpr auto N_RULES = 12;
lib/rule_settings/models/rule_settings.dartRuleSet 枚举添加了新的规则变体值RuleSettings 子类(例如,YourNewVariantRuleSettings)Rule 结构体一一对应ruleSetDescriptions 映射ruleSetProperties 映射示例:
enum RuleSet {
// ... 现有变体
yourNewVariant, // 新增
}
class YourNewVariantRuleSettings extends RuleSettings {
const YourNewVariantRuleSettings({
// 所有参数必须与 C++ Rule 字段匹配
}) : super(/* ... */);
}
lib/rule_settings/widgets/modals/rule_set_modal.dartRadioListTile 或类似的 UI 组件用于选择新规则RuleSet 枚举值rule_settings_page.dart 中标记为“实验性”?lib/l10n/intl_*.arb(约 60 个文件)intl_en.arb - 添加了英文翻译intl_zh_CN.arb - 添加了简体中文翻译intl_*.arb 文件 - 至少复制了英文版本flutter gen-l10n 以生成本地化代码关键字符串:
src/position.cpp(C++ 端)if (!rule.yourFeature) return fastPath();
// 新逻辑
lib/game_page/services/engine/position.dart(Flutter 端)position.cpp 中的逻辑_putPiece, _movePiece, _removePiece 相关逻辑重要:用户可见的游戏逻辑必须在 C++ 和 Dart 中对称实现。走法生成仅由 C++ 处理。
src/movegen.cppsrc/mills.cpplib/game_page/services/engine/engine.dartRule 结构体增加了新字段setRuleOptions() 方法中添加了逻辑以发送新参数src/ucioption.cppRule 结构体增加了新字段on_change 处理程序以将值应用到全局 rule 对象示例:
// ucioption.cpp
{"YourNewOption", "false", "bool", {}, on_your_new_option}
void on_your_new_option(Option &o) {
rule.yourNewField = o.get<bool>();
}
何时扩展 FEN:仅当你必须持久化无法从棋盘重新计算的动态状态时。
preferredRemoveTarget)hasDiagonalLines 等)mayFly, mayRemoveMultiple)src/position.h, src/position.cppposition.h 中添加了新字段fen() 方法中添加了导出逻辑set() 方法中添加了解析逻辑lib/game_page/services/engine/position.dart_getFen() 导出逻辑setFen() 解析逻辑tests/test_position.cpp, Flutter 集成测试src/evaluate.cppsrc/search.cpptests/test_*.cppset_rule(i) 正确加载新规则)tests/test_position.cpp)make test 以确保所有测试通过运行测试:
cd src
make build all
make test
_putPiece, _movePiece, _removePiece运行测试:
cd src/ui/flutter_app
flutter test
make benchmark)# 格式化所有代码
./format.sh
cd src/ui/flutter_app
flutter gen-l10n
# C++ 构建
cd src
make build all
# Flutter 构建(选择一个平台测试)
cd ../src/ui/flutter_app
flutter build apk # Android
# 或
flutter build ios # iOS
# 或
flutter build windows # Windows
docs/guides/ADDING_NEW_GAME_RULES.md(如果需要)提交 PR 前,确认以下所有事项:
RULES[] 有新条目,N_RULES 已递增RuleSet 枚举和 RuleSettings 子类与 C++ 匹配Rule 字段,引擎选项已更新src/rule.h 和 src/rule.cppsrc/position.cpp, src/movegen.cpp 等src/ucioption.cpprule_settings.dart(枚举 + 子类 + 映射)rule_set_modal.dart(UI 选择)position.dartengine.dart 的 setRuleOptions()intl_en.arb 和 intl_zh_CN.arbflutter gen-l10nN_RULES
src/rule.h 中的 N_RULES 与 RULES[] 长度匹配RuleSettings 字段与 Rule 结构体一一对应ucioption.cpp 中添加相应的选项和处理程序position.dart 镜像 position.cpp 逻辑RULES[] 中的其他规则作为模板参考docs/guides/ADDING_NEW_GAME_RULES.md - 添加规则的官方指南(必读)src/rule.h - Rule 结构体定义src/rule.cpp - RULES[] 数组src/position.h/.cpp - 游戏位置和逻辑src/movegen.cpp - 走法生成src/ucioption.cpp - UCI 选项src/mills.cpp - 成行判定逻辑include/config.h - 默认配置(很少修改)lib/rule_settings/models/rule_settings.dart - 规则模型lib/rule_settings/widgets/modals/rule_set_modal.dart - UI 选择lib/game_page/services/engine/position.dart - 位置镜像lib/game_page/services/engine/engine.dart - 引擎通信lib/l10n/intl_*.arb - 本地化文件tests/test_*.cpp - C++ 单元测试test/ - Flutter 单元和 widget 测试integration_test/ - Flutter 集成测试验证结果应清晰报告:
✓ [完成] 核心文件修改
✓ src/rule.cpp - RULES[] 已添加
✓ src/rule.h - N_RULES 已递增
✓ rule_settings.dart - RuleSet 枚举已添加
...
⚠ [警告] 条件文件修改
✓ src/position.cpp - 逻辑已更新
✗ position.dart - 逻辑未镜像(需要修复)
...
✓ [完成] 测试验证
✓ C++ 测试全部通过 (25/25)
✓ Flutter 测试全部通过 (42/42)
...
✗ [失败] 本地化
✓ intl_en.arb - 已更新
✓ intl_zh_CN.arb - 已更新
✗ 其他 ARB 文件 - 未更新(需要完成)
...
📊 完成度:75% (15/20 项检查通过)
💡 建议:优先修复 position.dart 镜像和本地化
添加新的游戏规则是一项系统性的工作,需要 C++ 引擎和 Flutter UI 之间的仔细协调。使用此检查清单可确保:
记住:如有疑问,请参考 docs/guides/ADDING_NEW_GAME_RULES.md 和现有的规则实现。
每周安装量
0
代码仓库
GitHub 星标数
189
首次出现
1970年1月1日
安全审计
When adding a new game rule or rule variant to Sanmill, you need to modify multiple files (typically 70-80 files, including ~60 localization files). This skill provides a completeness checklist to ensure no necessary code changes are missed.
Reference : docs/guides/ADDING_NEW_GAME_RULES.md
Sanmill is configuration-based , not inheritance-based. Rule variants are expressed as data (
Rulein C++,RuleSettingsin Flutter) and toggled at runtime. Any new mechanics must be gated by booleans/params so existing variants remain untouched and fast.
src/rule.cppRULES[] arrayname - Rule name (max 32 chars)description - Rule description (max 512 chars)pieceCount, flyPieceCount, piecesAtLeastCounthasDiagonalLines - Whether diagonal lines existmayFly, nMoveRule, etc.)Example structure :
{
"Your Rule Name",
"Short description",
9, 3, 3, // pieceCount, flyPieceCount, piecesAtLeastCount
false, // hasDiagonalLines
MillFormationActionInPlacingPhase::removeOpponentsPieceFromBoard,
/*mayMoveInPlacingPhase*/ false,
/*isDefenderMoveFirst*/ false,
/*mayRemoveMultiple*/ false,
// ... other fields
kDefaultCaptureRuleConfig, // custodian
kDefaultCaptureRuleConfig, // intervention
kDefaultCaptureRuleConfig, // leap
/*mayFly*/ true,
/*nMoveRule*/ 100,
/*endgameNMoveRule*/ 100,
/*threefoldRepetitionRule*/ true
}
src/rule.hIncremented N_RULES constant (to match new RULES[] length)
If new parameters needed, added new fields to Rule struct?
// e.g., if it was 11, now it should be 12 constexpr auto N_RULES = 12;
lib/rule_settings/models/rule_settings.dartRuleSet enumRuleSettings subclass (e.g., YourNewVariantRuleSettings)Rule structruleSetDescriptions map with descriptionruleSetProperties map with default property instanceExample :
enum RuleSet {
// ... existing variants
yourNewVariant, // new
}
class YourNewVariantRuleSettings extends RuleSettings {
const YourNewVariantRuleSettings({
// All params must match C++ Rule fields
}) : super(/* ... */);
}
lib/rule_settings/widgets/modals/rule_set_modal.dartRadioListTile or similar UI component for selecting new ruleRuleSet enum valuerule_settings_page.dart?lib/l10n/intl_*.arb (~60 files)intl_en.arb - Added English translationsintl_zh_CN.arb - Added Simplified Chinese translationsintl_*.arb files - At least copied English versionflutter gen-l10n to generate localization codeKey strings :
src/position.cpp (C++ side)Must modify : If new rule changes placement, movement, or capture logic
Used conditional guards for performance:
if (!rule.yourFeature) return fastPath();
// new logic
Handled all edge cases
lib/game_page/services/engine/position.dart (Flutter side)position.cpp_putPiece, _movePiece, _removePiece related logicImportant : User-visible game logic must be symmetrically implemented in both C++ and Dart. Move generation (movegen) is C++ only.
src/movegen.cppsrc/mills.cpplib/game_page/services/engine/engine.dartRule struct gained new fieldssetRuleOptions() method to send new parameterssrc/ucioption.cppRule struct gained new fieldson_change handlers to apply values to global rule objectExample :
// ucioption.cpp
{"YourNewOption", "false", "bool", {}, on_your_new_option}
void on_your_new_option(Option &o) {
rule.yourNewField = o.get<bool>();
}
When to extend FEN : Only when you must persist dynamic state that cannot be recomputed from the board.
preferredRemoveTarget)hasDiagonalLines, etc.)mayFly, mayRemoveMultiple)src/position.h, src/position.cppposition.hfen() methodset() methodlib/game_page/services/engine/position.dart_getFen() export logicsetFen() parsing logictests/test_position.cpp, Flutter integration testssrc/evaluate.cppsrc/search.cpptests/test_*.cppset_rule(i) correctly loads new rule)tests/test_position.cpp)make test to ensure all tests passRun tests :
cd src
make build all
make test
_putPiece, _movePiece, _removePieceRun tests :
cd src/ui/flutter_app
flutter test
make benchmark)# Format all code
./format.sh
cd src/ui/flutter_app
flutter gen-l10n
# C++ build
cd src
make build all
# Flutter build (pick a platform to test)
cd ../src/ui/flutter_app
flutter build apk # Android
# or
flutter build ios # iOS
# or
flutter build windows # Windows
docs/guides/ADDING_NEW_GAME_RULES.md (if needed)Before submitting PR, confirm all of the following:
RULES[] has new entry, N_RULES incrementedRuleSet enum and RuleSettings subclass match C++Rule fields added, engine options updatedsrc/rule.h and src/rule.cppsrc/position.cpp, src/movegen.cpp, etc.src/ucioption.cpprule_settings.dart (enum + subclass + mappings)rule_set_modal.dart (UI selection)position.dartengine.dart's setRuleOptions()intl_en.arb and intl_zh_CN.arbflutter gen-l10nForgot to incrementN_RULES
N_RULES in src/rule.h matches RULES[] lengthC++ and Flutter fields don't match
RuleSettings fields match Rule struct 1-to-1Missing UCI options
ucioption.cppRULES[] as templatesdocs/guides/ADDING_NEW_GAME_RULES.md - Official guide for adding rules (must read)src/rule.h - Rule struct definitionsrc/rule.cpp - RULES[] arraysrc/position.h/.cpp - Game position and logicsrc/movegen.cpp - Move generationsrc/ucioption.cpp - UCI optionssrc/mills.cpp - Mill formation logicinclude/config.h - Default config (rarely modified)lib/rule_settings/models/rule_settings.dart - Rule modelslib/rule_settings/widgets/modals/rule_set_modal.dart - UI selectionlib/game_page/services/engine/position.dart - Position mirrorlib/game_page/services/engine/engine.dart - Engine communicationlib/l10n/intl_*.arb - Localization filestests/test_*.cpp - C++ unit teststest/ - Flutter unit and widget testsintegration_test/ - Flutter integration testsValidation results should be reported clearly:
✓ [Complete] Core File Modifications
✓ src/rule.cpp - RULES[] added
✓ src/rule.h - N_RULES incremented
✓ rule_settings.dart - RuleSet enum added
...
⚠ [Warning] Conditional File Modifications
✓ src/position.cpp - Logic updated
✗ position.dart - Logic not mirrored (needs fix)
...
✓ [Complete] Test Validation
✓ C++ tests all passed (25/25)
✓ Flutter tests all passed (42/42)
...
✗ [Failed] Localization
✓ intl_en.arb - Updated
✓ intl_zh_CN.arb - Updated
✗ Other ARB files - Not updated (needs completion)
...
📊 Completion: 75% (15/20 checks passed)
💡 Recommendation: Priority fix position.dart mirror and localization
Adding a new game rule is a systematic effort requiring careful coordination between the C++ engine and Flutter UI. Using this checklist ensures:
Remember : When in doubt, refer to docs/guides/ADDING_NEW_GAME_RULES.md and existing rule implementations.
Weekly Installs
0
Repository
GitHub Stars
189
First Seen
Jan 1, 1970
Security Audits
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
106,200 周安装
Didn't mirror game logic to Dart
position.dart mirrors position.cpp logicIncomplete localization
Performance regression
Over-extended FEN