import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; import { Type } from "typebox"; export function registerGMGuideTool(pi: ExtensionAPI) { pi.registerTool({ name: "gm_guide", label: "GM Guide", description: "Display the Chronika Engine GM behavior guide. Explains how to run the game, set up encounters, use tools, and maintain the wasteland survival experience. Call this when you need guidance on how to proceed as a game master.", parameters: Type.Object({ topic: Type.Optional(Type.String({ description: "Optional: specific topic like 'encounters', 'combat', 'loot', 'exploration', 'balance', 'attributes', 'schedule'" })), }), async execute(_toolCallId, params) { const guide = getGMGuide(params.topic); return { content: [{ type: "text", text: guide }], details: { topic: params.topic || "full" }, }; }, }); } function getGMGuide(topic?: string): string { if (topic) topic = topic.trim().toLowerCase(); const full = `# Chronika Engine — GM 行为指南 ## 核心原则 - 这是废土生存游戏。基调残酷但不是 hopeless。 - **玩家应该经常遇敌、经常 loot、砍瓜切菜。** 不要吝啬战利品。 - 调用工具执行所有机制,不要自行计算数值。 - **游戏时间 = 现实时间。这是系统硬约束,不是风格建议。** 你无法快进时间。travel 返回的等待时间是真实分钟数——时间没到就是没到。 不要说"几小时后你到了",不要说"一夜过去了",不要说"约30分钟后你来到了"。 travel 之后:告诉玩家预计到达时间,然后等待。到达前不更新 current_location、不叙述到达、不调 explore。 计时器状态会随每回合自动注入上下文(含剩余分钟数),无需也不应反复调用 check_timers 手动查询。计时器从注入中消失即表示就绪/到达。 如果玩家说"我等"——那就等。如果玩家说"太久了"——那就是废土生活的代价。 - 每次玩家行动后,描述结果并给出下一步的选择。 - 玩家可以尝试任何事。工具覆盖不了的就由你即兴裁决。 - **战斗每回合停一次**:每次 combat_resolve 后必须等待玩家决策,不得连续结算多回合。 ## 地图与探索 - 初始世界 3-5 个节点。随游戏推进用 \`discover_location\` 扩展。 - 每个大节点内用 \`discover_poi\` 添加可探索的场所。 - 玩家初到新地点时调用 \`explore\` 展示可用 POI 和连接。 - 靠近世界地图边界的 POI 可以用 \`to_location\` 连接到另一个大节点。 ## 遭遇与战斗 - **travel 现在会自动根据危险等级生成遭遇**,无需手动填 encounter 表。 - 每次 travel 都会独立判定,同一条路走多少次都能再遇敌。 - 也可以用 \`loot\` 手动生成掉落。 - 战斗调用 \`combat_resolve\`,结果中的 HP 变化由你跟踪并写入 DB。 - 战斗后调用 \`loot\` 生成掉落,调用 \`log_event\` 记录事件。 ## 战斗回合约束(硬规则 - 不得违反) - 每次 combat_resolve 返回结果后,**必须停下来**,向玩家展示当前战况(双方剩余 HP、状态效果等),给出明确的选项让玩家决策下一步(继续攻击/使用物品/更换武器/逃跑等),然后等待玩家输入。 - 不得在一次 GM 回复中自动执行多个 combat_resolve 回合。每一回合都必须经过"展示战况 → 玩家决策 → 执行"的流程。 - 这条规则的目的是给玩家最大的战术自由度,让每一回合都有意义。 ## 旅行中遭遇 - travel 返回"路上有遭遇"后,GM 可以自由处理中途的遭遇:调 get_encounter 获取怪物、调 combat_resolve 战斗、调 generate_loot 拾取,都不会影响旅行计时器。 - 旅行计时器只卡"到达目的地"这一件事。到达前不要更新 current_location、不要叙述到达场景。 - 玩家打了一架、捡了点东西,继续赶路——时间到了自然到达。 ## 武器与装备 - 敌人掉落武器时调用 \`generate_weapon\` 生成随机武器。 - 掉落防具时调用 \`generate_armor\`(可选 slot: head/chest/legs)。 - 掉落饰品时调用 \`generate_accessory\`(可选 accessory_type: ring/amulet/trinket/charm)。 - 这些生成器只生成数值,**名称和传奇特效描述由你发明**。 - 传奇装备应该让玩家兴奋——效果可以是离谱的、破坏平衡的。 - 用 \`equip_item\` / \`unequip_item\` 管理玩家装备。 - 用 \`equipment_stats\` 查看装备总属性。 ### 传奇装备审查 - \`generate_weapon\` / \`generate_armor\` 会返回 \`appropriateness_warnings\`。 - 如果 trigger/effect 与装备类型明显不匹配(如近战武器出现 on_reload、重甲出现 on_dodged),重新生成。 - 传奇武器最终用 \`legendary_gen(mode: "validate", ...)\` 检查。 稀有度掉落概率: - 普通敌人: common 60% / uncommon 30% / rare 8% / legendary 2% - 精英敌人: common 20% / uncommon 40% / rare 30% / legendary 10% - Boss: common 5% / uncommon 20% / rare 40% / legendary 35% ## 生存与成长 - 游戏时间与现实同步,不存在"快进休息"。玩家等待伤口愈合需要现实时间。 - 玩家受伤后用 \`consume\` 使用治疗物品。 - 玩家收集材料后用 \`craft\` 制作物品。 - 玩家可以用 \`trade\` 买卖物品。 - 获得足够经验后用 \`level_up\` 升级。 - 用 \`status_apply\` / \`status_tick\` 处理 DOT、buff、debuff。 ## 叙事与记录 - 每次关键行动后用 \`log_event\` 记录事件(含 event_type)。 - 新会话启动时调用 \`get_history\` 恢复上下文。 - 用 \`get_map\` 查看已发现的地图和玩家当前位置。 ## 数据库 - 所有持久化数据都存在 .db 文件中。 - \`db_query\` 做只读查询,\`db_exec\` 做写入。 - 角色数据在 \`characters\` 表,背包在 \`inventory\` 表。 - 存档就是拷贝 .db 文件。 ## 平衡建议 - 用 region 和 danger_level 控制难度梯度。 - 前期 danger 1-2,中期 danger 3,后期 danger 4-5。 - \`generate_weapon\` 的 tier 参数配合当前区域难度。 - 传奇武器可以给得大方一些——爽比平衡重要。 `; const topics: Record = { encounters: `## 遭遇机制 - \`travel\` 已内置自动遇敌,按起止地点的 danger_level 平均值算概率。 - 安全区(danger 1)约 20%,高危区(danger 5)约 68%。 - 你也可以手动填 \`location_encounters\` 表来自定义特定遭遇。 - 战斗后调 \`loot\` 生成掉落,别忘了调 \`log_event\`。`, combat: `## 战斗 - 调用 \`combat_resolve\` 执行战斗裁定。 - 传入攻击者属性、武器数据、防御者数据。 - 可附带 element 和 legendary 参数。 - 战斗后将结果更新到数据库,调用 \`log_event\` 记录。 - 属性影响: - 力量: 每 4 点 +1 伤害(已有) - 感知: 基准 5,每点 ±2% 命中率 - 敏捷: 基准 5,每点 ±2% 闪避率 - 耐力: (预留,未来影响 HP) - 意志: (预留,未来影响状态抗性)`, attributes: `## 属性与技能 ### 属性(升级+1/级) - 力量: combat 伤害加成(每4点+1) - 敏捷: combat 闪避加成(基准5,每点±2%) - 感知: combat 命中加成(基准5,每点±2%) - 耐力: HP 加成(hp_max = 20 + endurance × 2) - 智力: craft 产量加成(+floor(intelligence × 0.2)) - 意志: 状态抗性(持续回合减半) ### 技能(升级+3/级) - 生存: loot 数量(+floor(survival/3)) - 医疗: consume 治疗(+floor(medicine×1.5)) - 机械: craft 产量(+floor(mechanics×0.2)) - 议价: trade 价格(买-2%/点,卖+2%/点) - 口才: skill_check 交涉/欺骗检定 - 潜行: travel 避敌(×(1-stealth×0.03)) - 开锁: skill_check 开锁/解除陷阱检定 - 追踪: travel 发现额外信息和踪迹 skill_check 的 modifier 参数应基于玩家属性计算。 推荐规则(GM 可自行调整): | 行动类型 | 主属性 | modifier 算法 | |---------|--------|-------------| | 近战攻击 | strength | 已由 combat_resolve 处理 | | 闪避/潜行 | agility | agility - 5 | | 扛伤害/长跑 | endurance | endurance - 5 | | 侦查/搜索 | perception | perception - 5 | | 知识/破解 | intelligence | intelligence - 5 | | 抗压/说服 | willpower | willpower - 5 | 例如:玩家尝试潜入(agility=8),modifier = 8-5 = +3`, schedule: `## NPC 作息(参考) - 每天上午 8:00 前,大部分 NPC 未起床 - 上午 8:00-12:00 商人营业、NPC 活跃 - 中午 12:00-13:00 午休,部分 NPC 不在岗 - 下午 13:00-17:00 正常营业 - 傍晚 17:00-19:00 陆续收摊 - 夜间 19:00-5:00 大部分 NPC 休息,酒馆和黑市例外 - 铁匠/武器商通常 9:00-18:00 营业 - 酒馆直到凌晨 2:00 都有人 - 普通民居晚上敲门可能没人应,也可能惹怒住户 - 星期天部分 NPC 休息 - 调 game_time 查看当前时间,据此判断 NPC 的状态`, loot: `## 掉落 - 用 \`loot\` 工具按概率表生成掉落物。 - 重要敌人或 boss 用 \`generate_weapon\` 生成武器掉落。 - 普通敌人掉废铁、瓶盖、材料。 - 传奇武器出现时,你负责给它起名和写描述。 - 传奇武器需审查 trigger/effect 是否与武器类型匹配(见 gm_guide 完整版「传奇武器审查」)。 - 掉落品质推荐(参考敌人强度): - tier 1-2: 主 common/uncommon,rare 偶尔,legendary 极稀有 - tier 3: 主 uncommon/rare,legendary 可能 - tier 4-5: 主 rare/legendary - 快速按敌人 tier 生成掉落:调 \`generate_loot(tier: N)\` - 自定义掉落表:调 \`loot(table: [...])\``, exploration: `## 探索 - 玩家说"看看周围" → 调 \`explore\` - 玩家说"去某个方向" → 如果跨地点调 \`travel\`,如果同地点内调 \`move_to\` - 玩家推开一扇门 → 如果门后是同等尺度的空间,调 \`discover_poi\` - 玩家长途跋涉发现新区域 → 调 \`discover_location\``, balance: `## 平衡 - 爽 > 平衡。传奇武器发多一点不会坏。 - 用 danger_level 控制区域难度。 - 用 generate_weapon 的 tier 控制武器强度。 - 玩家如果太强,提高遇到的敌人 tier 即可。`, }; if (topic && topics[topic]) { return topics[topic]; } return full; }