@sdd330dev/jy-skill 0.3.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -15,6 +15,8 @@ API 与完整规则见 [SKILL.md](SKILL.md)、[references/agent-handbook.md](ref
15
15
  - **数值准确**:所有计算必须遵循 `scripts/game-logic.ts`;禁止编造伤害、经验、价格
16
16
  - **单一入口**:只通过 `scripts/game-engine.ts` 调用游戏逻辑
17
17
  - **新人友好**:首登与求帮助时给出可执行建议,勿堆砌函数名或 API 术语
18
+ - **选项契约优先**:每轮调用 `buildChoicePrompt(state)`,由 Host 渲染点选 UI(见 [host-adapters.md](references/host-adapters.md))
19
+ - **NPC 叙事**:`talkTo` 返回的 `npc.persona` / `knowledge` 用于扩写台词,但物品/武功/flag 以引擎为准
18
20
 
19
21
  ## 新玩家首登
20
22
 
@@ -26,21 +28,39 @@ API 与完整规则见 [SKILL.md](SKILL.md)、[references/agent-handbook.md](ref
26
28
  - 与村长或商人搭话,打听江湖消息;
27
29
  - 攒够脚程后前往平安镇,购置兵刃防具;
28
30
  - 说「查看背包」或「我现在什么状态」,熟悉自身家当。
29
- 4. 末尾附带标准**状态栏**(见下文输出格式)。
31
+ 4. 末尾附带标准**状态栏**与**编号选项**(见下文输出格式)。
30
32
 
31
33
  若玩家是**续玩**(`isNewGame: false`),简短交代「你回到了江湖之中」并概括当前位置与近况即可,不必重复完整新人引导。
32
34
 
35
+ ## 行动选项(PlayerChoicePrompt)
36
+
37
+ **每轮行动结束后 MUST 提供可点选选项**(在状态栏之前),禁止让玩家打字或输入数字选行动(除非 Host 无 UI 能力)。
38
+
39
+ 1. 调用 `buildChoicePrompt(state)` 得到标准契约(`type: 'player_choice'`)
40
+ 2. **Cursor**:若 AskQuestion 可用,用 `choices[].value` / `choices[].label` 映射为点选选项
41
+ 3. **MCP Host**:用 `toMcpElicitationParams(prompt)` 触发 Elicitation 单选 UI
42
+ 4. **飞书/OpenClaw**:用 `toFeishuInteractiveCard(prompt)` 或 `build-feishu-card.ts` 发交互卡片
43
+ 5. 用户点选 → `resolveOption(state, optionId)`;Elicitation 回传 → `fromElicitationResponse` → `resolveOption`
44
+
45
+ **Fallback**(仅无 UI 时):`getOptions` + 编号 1/2/3 文本列表。
46
+
47
+ **对话分支**:`talkTo` 含 `choices` 时用 `buildChoicePromptFromTalk`;选中 `dialog:*` value 后 `resolveOption` 自动 `chooseDialog`。
48
+
49
+ **事件**:`moveTo` / `talkTo` 返回 `events` 时须优先叙述,再展示新选项。
50
+
51
+ 详见 [host-adapters.md](references/host-adapters.md)。
52
+
33
53
  ## 帮助指令
34
54
 
35
55
  玩家说「帮助 / 怎么玩 / jy 帮助 / 指令 / 指令说明」时,按以下结构用武侠口吻回复(**不要用框线、不要罗列 API 函数名**):
36
56
 
37
57
  1. **一句话**:江湖行事,只需用中文告诉我想做什么,不必记固定命令。
38
58
  2. **常用说法**(各举一例):移动(如「去平安镇」)、对话(如「和村长聊聊」)、购物(如「买铁剑」)、战斗(如「攻击山贼」)、查看(如「看背包」)、休息(如「休息」)。
39
- 3. **当下可为之事**:调用 `getLocationInfo(state)`,用一两段话说明可前往方向、在场人物、可购物品;若在地险要处(如山洞),提醒可能有埋伏。
59
+ 3. **当下可为之事**:调用 `getLocationDetail(state)` 与 `getOptions(state)`,用一两段话说明环境、可前往方向、在场人物;若在地险要处提醒可能有埋伏。
40
60
  4. 提示更完整说明见玩家手册;若玩家需要,可简要概括地图与战斗要点(相邻移动、战前备药、进洞可能遇敌)。
41
- 5. 末尾附带**状态栏**。
61
+ 5. 末尾附带**编号选项**与**状态栏**。
42
62
 
43
- 帮助场景下可调用 `getStatus` / `getInventory` / `getLocationInfo` 辅助叙述,但不要向玩家展示代码或函数调用过程。
63
+ 帮助场景下可调用 `getStatus` / `getInventory` / `getLocationDetail` / `getOptions` 辅助叙述,但不要向玩家展示代码或函数调用过程。
44
64
 
45
65
  ## 游戏流程
46
66
 
@@ -69,8 +89,9 @@ saveGameState(state) // 可选
69
89
 
70
90
  | 意图 | 注意 |
71
91
  |------|------|
72
- | 移动 | `encounter` 不可忽略;「随便走走」用 `moveTo(state, 'random')` |
73
- | 对话 | NPC 名须与当前地点一致(如平安镇:守卫、商店老板、客栈老板) |
92
+ | 移动 | `encounter` 不可忽略;「随便走走」用 `moveTo(state, 'random')`;返回 `events` 须叙述 |
93
+ | 对话 | NPC 名须与当前地点一致;基于 `npc.persona` 扩写,数值以引擎为准 |
94
+ | 数字输入(fallback) | 无 UI 时 `1`–`9` → `resolveOption` |
74
95
  | 使用物品 | 满状态时引擎拒绝消耗,须如实告知玩家 |
75
96
  | 战斗 | 多敌人时按 `enemies[i].hp > 0` 选目标 |
76
97
 
@@ -88,7 +109,9 @@ saveGameState(state) // 可选
88
109
  - `getStatus(state)` — 状态栏
89
110
  - `getInventory(state)` — 背包
90
111
  - `getSkills(state)` — 武功
91
- - `getLocationInfo(state)` — 帮助/首登时说明附近选项
112
+ - `getLocationInfo(state)` / `getLocationDetail(state)` 地点信息
113
+ - `buildChoicePrompt(state)` — 标准选项契约(**首选**)
114
+ - `getOptions(state)` — 原始选项列表(适配器内部使用)
92
115
 
93
116
  ### 5. 死亡与重开
94
117
 
@@ -119,9 +142,16 @@ saveGameState(state) // 可选
119
142
  - 每回合简洁有力;多敌人时点名(山贼1、山贼2…)。
120
143
  - 升级时可描写任督二脉通畅、功力精进一类意象,等级与属性以引擎为准。
121
144
 
145
+ ### NPC 对话与 LLM-NPC 模式
146
+
147
+ - `talkTo` 返回 `npc` 角色卡时,用 `persona`、`knowledge` 丰富描写,但**不可编造**引擎未确认的结果。
148
+ - 调用 `getNpcContext(state, npc)` 获取 `constraints` 硬约束列表,**必须遵守**。
149
+ - NPC 传授武功:仅当 `availableActions` 含 `teach` 且条件满足时,调用 `learnSkill`;否则口头拒绝。
150
+ - NPC 给予物品:须由事件引擎或 `chooseDialog` actions 触发,不可口头编造「送你 XXX」。
151
+
122
152
  ## 输出格式
123
153
 
124
- 每次回复末尾附带状态栏(与 `getStatus` 一致):
154
+ 每次回复末尾:**点选选项**(PlayerChoicePrompt / AskQuestion)→ **状态栏**(与 `getStatus` 一致):
125
155
 
126
156
  ```
127
157
  👤 角色名 | Lv.等级 | 经验: …
@@ -147,4 +177,5 @@ saveGameState(state) // 可选
147
177
  | [agent-handbook.md](references/agent-handbook.md) | 完整规则、API、地图、错误清单 |
148
178
  | [SKILL.md](SKILL.md) | Skill 入口与工作流 |
149
179
  | [player-guide.md](references/player-guide.md) | 可转述给玩家的 FAQ |
180
+ | [host-adapters.md](references/host-adapters.md) | MCP / Cursor / 飞书选项适配 |
150
181
  | [game-design.md](references/game-design.md) | 公式细节 |
package/SKILL.md CHANGED
@@ -5,7 +5,7 @@ description: >-
5
5
  Agent 须读 references/agent-handbook.md 掌握完整玩法与 API;玩家说 jy/开始游戏/帮助/金庸群侠传时使用。
6
6
  license: MIT
7
7
  metadata:
8
- version: "0.3.1"
8
+ version: "0.7.0"
9
9
  disable-model-invocation: false
10
10
  ---
11
11
 
@@ -29,6 +29,7 @@ npm install @sdd330dev/jy-skill --save-dev && npx jy-skill install
29
29
  |------|------|------|
30
30
  | [agent-handbook.md](references/agent-handbook.md) | Agent | 规则、API、战斗、地图速查、错误清单 |
31
31
  | [AGENTS.md](AGENTS.md) | Agent | 武侠叙事、首登/帮助模板、输出格式 |
32
+ | [host-adapters.md](references/host-adapters.md) | Agent | MCP / Cursor / 飞书选项适配 |
32
33
  | [player-guide.md](references/player-guide.md) | 玩家 | FAQ、地图、生存技巧 |
33
34
  | [game-design.md](references/game-design.md) | 开发 | 公式与设计细节 |
34
35
 
@@ -38,6 +39,7 @@ npm install @sdd330dev/jy-skill --save-dev && npx jy-skill install
38
39
  - 禁止手改存档、禁止编造伤害/价格/地图连接
39
40
  - `moveTo` 返回 `encounter` 时**必须** `startBattle` 并打完
40
41
  - 每轮回复末尾附 `getStatus(state)` 状态栏
42
+ - **每轮 MUST** 调用 `buildChoicePrompt(state)`,由 Host 渲染点选 UI(见 [host-adapters.md](references/host-adapters.md));无 UI 时 fallback 数字导航
41
43
 
42
44
  ## 何时使用
43
45
 
@@ -46,7 +48,7 @@ npm install @sdd330dev/jy-skill --save-dev && npx jy-skill install
46
48
  | 玩家说法 | Agent 动作 |
47
49
  |----------|------------|
48
50
  | jy / 开始游戏 | `loadOrCreateGame`;`isNewGame` 则首登引导(见 AGENTS.md) |
49
- | 帮助 / 怎么玩 | `getLocationInfo` + 帮助模板,勿堆砌 API 名 |
51
+ | 帮助 / 怎么玩 | `getLocationDetail` + `getOptions` + 帮助模板,勿堆砌 API 名 |
50
52
  | 重新开始 / 新游戏 | `restartGame()` |
51
53
  | 其他 | 解析意图 → 对应 API → 武侠叙述 + 状态栏 |
52
54
 
@@ -63,7 +65,10 @@ import {
63
65
  enemyAttack,
64
66
  isDead,
65
67
  getStatus,
66
- getLocationInfo,
68
+ buildChoicePrompt,
69
+ toMcpElicitationParams,
70
+ resolveOption,
71
+ getLocationDetail,
67
72
  restartGame,
68
73
  } from './scripts/game-engine'
69
74
 
@@ -75,31 +80,37 @@ if (move.encounter) {
75
80
  // 战斗循环见下文
76
81
  }
77
82
 
78
- saveGameState(state) // 可选,引擎已自动存档
83
+ // 每轮末尾:buildChoicePrompt → Host 点选 UI → resolveOption(optionId)
84
+ const prompt = buildChoicePrompt(state)
79
85
  ```
80
86
 
81
87
  ## 每轮工作流
82
88
 
83
89
  1. **加载**:无 `state` 时 `loadOrCreateGame(createNewGame, '主角')`
84
- 2. **执行**:按玩家意图调用 API(复合指令分步执行)
90
+ 2. **执行**:按玩家意图调用 API;点选回传 `optionId` → `resolveOption`
85
91
  3. **遇敌**:`moveTo` → `encounter?` → `startBattle` → 战斗循环
86
- 4. **死亡**:`isDead` 叙述结算 `restartGame()`
87
- 5. **输出**:武侠叙述 + `getStatus(state)` 状态栏
92
+ 4. **事件**:`moveTo`/`talkTo` 返回 `events` 时须优先叙述;对话分支用 `chooseDialog`
93
+ 5. **死亡**:`isDead` 叙述结算 → `restartGame()`
94
+ 6. **输出**:武侠叙述 + `buildChoicePrompt` 选项 + `getStatus(state)` 状态栏
88
95
 
89
96
  ## 玩家意图 → API
90
97
 
91
98
  | 意图 | API | 要点 |
92
99
  |------|-----|------|
93
- | 移动 / 随便走走 | `moveTo(state, dest)` | `dest='random'` 随机相邻;返回 `encounter?` |
94
- | 对话 | `talkTo(state, npc)` | NPC 名须精确;`'random'` 随机 |
100
+ | 移动 / 随便走走 | `moveTo(state, dest)` | `dest='random'` 随机相邻;返回 `encounter?`、`events?`、`locationDetail?` |
101
+ | 对话 | `talkTo(state, npc)` | 返回 `npc` 角色卡、`choices?`、`context?`;基于 persona 扩写叙事 |
102
+ | 对话选项 | `chooseDialog(state, dialogId, index)` | 处理分支与 setFlag/addItem/battle |
103
+ | 点选选项 | `buildChoicePrompt` → Host UI → `resolveOption(state, optionId)` | 标准契约;见 host-adapters.md |
104
+ | 数字 fallback | `resolveOption(state, getOptions()[n-1].id)` | 仅无 UI 时 |
95
105
  | 购买 | `buyItem(state, item)` | 仅当前地点商店 |
96
106
  | 使用 | `useItem(state, item)` | 无收益不消耗 |
97
107
  | 装备 | `equipItem(state, item)` | 武器/防具 |
98
- | 学武功 | `learnSkill(state, skill)` | 须存在于 assets |
108
+ | 学武功 | `learnSkill(state, skill)` | 须存在于 assets;NPC 传授须引擎确认 |
99
109
  | 休息 | `rest(state)` | 满状态并解毒解伤 |
100
110
  | 战斗 | `startBattle` + 循环 | 见下节 |
101
111
  | 查看 | `getStatus` / `getInventory` / `getSkills` | |
102
- | 帮助 | `getLocationInfo` | 当前可为之事 |
112
+ | 帮助 / 选项 | `getLocationDetail` / `buildChoicePrompt` | 当前可为之事与选项契约 |
113
+ | NPC 约束 | `getNpcContext(state, npc)` | LLM-NPC 模式硬约束,禁止编造 teach/give |
103
114
  | 重开 | `restartGame(name?)` | 删档+新建+落盘 |
104
115
 
105
116
  ## 战斗循环(必遵)
@@ -174,10 +185,11 @@ if (isDead(state)) {
174
185
 
175
186
  | 类别 | 函数 |
176
187
  |------|------|
177
- | 存档 | `loadOrCreateGame`, `loadGameState`, `saveGameState`, `deleteSave`, `restartGame` |
188
+ | 存档 | `loadOrCreateGame`, `loadOrCreateGameForUser`, `loadGameState`, `saveGameState`, `deleteSave`, `restartGame` |
178
189
  | 初始化 | `createNewGame` |
179
- | 查询 | `getStatus`, `getInventory`, `getSkills`, `getLocationInfo` |
180
- | 探索 | `moveTo`, `talkTo`, `rest` |
190
+ | 查询 | `getStatus`, `getInventory`, `getSkills`, `getLocationInfo`, `getLocationDetail`, `getOptions`, `getNpcContext` |
191
+ | 选项契约 | `buildChoicePrompt`, `buildChoicePromptFromTalk`, `toMcpElicitationParams`, `fromElicitationResponse`, `toFeishuInteractiveCard` |
192
+ | 探索 | `moveTo`, `talkTo`, `chooseDialog`, `resolveOption`, `rest` |
181
193
  | 物品 | `buyItem`, `useItem`, `equipItem`, `learnSkill` |
182
194
  | 战斗 | `startBattle`, `attackEnemy`, `useSkillInBattle`, `enemyAttack`, `isDead` |
183
195
 
@@ -187,7 +199,7 @@ if (isDead(state)) {
187
199
 
188
200
  - 地图/NPC/商店/敌人:`assets/templates.json`(**勿编造**)
189
201
  - 武功/物品数值:`assets/skills.json`、`assets/items.json`
190
- - 存档:`save/game-state.json`(引擎原子写入,自动迁移旧档)
202
+ - 存档:`save/game-state.json` 或 `save/users/{userId}.json`(多用户/MCP)
191
203
 
192
204
  ## 目录
193
205
 
@@ -197,12 +209,17 @@ jy/
197
209
  ├── AGENTS.md
198
210
  ├── references/
199
211
  │ ├── agent-handbook.md # Agent 操作手册(必读)
212
+ │ ├── host-adapters.md
200
213
  │ ├── player-guide.md
201
214
  │ └── game-design.md
202
215
  ├── scripts/
203
216
  │ ├── game-engine.ts # 唯一 API
217
+ │ ├── choice-prompt.ts # PlayerChoicePrompt 契约
218
+ │ ├── mcp-server.ts # MCP Server(可选)
219
+ │ ├── build-feishu-card.ts
204
220
  │ ├── game-logic.ts
205
221
  │ ├── config-loader.ts
222
+ │ ├── event-engine.ts
206
223
  │ └── persistence.ts
207
224
  └── assets/
208
225
  ```
@@ -98,6 +98,20 @@
98
98
  { "type": "setFlag", "params": { "flag": "village_visited", "value": true } },
99
99
  { "type": "dialog", "params": { "dialogId": "village_intro" } }
100
100
  ]
101
+ },
102
+ {
103
+ "id": "village_cave_return",
104
+ "triggerType": "talk",
105
+ "npcName": "村长",
106
+ "conditions": [
107
+ { "type": "flag", "params": { "flag": "cave_master_met", "value": true } },
108
+ { "type": "flag", "params": { "flag": "village_cave_reward", "value": false } }
109
+ ],
110
+ "actions": [
111
+ { "type": "dialog", "params": { "dialogId": "village_cave_reward" } },
112
+ { "type": "addItem", "params": { "itemId": 30, "count": 3 } },
113
+ { "type": "setFlag", "params": { "flag": "village_cave_reward", "value": true } }
114
+ ]
101
115
  }
102
116
  ]
103
117
  },
@@ -149,6 +163,29 @@
149
163
  { "type": "setFlag", "params": { "flag": "cave_treasure", "value": true } },
150
164
  { "type": "addItem", "params": { "itemId": 13, "count": 1 } }
151
165
  ]
166
+ },
167
+ {
168
+ "id": "cave_start",
169
+ "triggerType": "auto",
170
+ "conditions": [{ "type": "flag", "params": { "flag": "cave_entered", "value": false } }],
171
+ "actions": [
172
+ { "type": "setFlag", "params": { "flag": "cave_entered", "value": true } },
173
+ { "type": "dialog", "params": { "dialogId": "cave_intro" } }
174
+ ]
175
+ },
176
+ {
177
+ "id": "cave_master_quest",
178
+ "triggerType": "talk",
179
+ "npcName": "神秘人",
180
+ "conditions": [
181
+ { "type": "level", "params": { "min": 5 } },
182
+ { "type": "flag", "params": { "flag": "cave_master_met", "value": false } }
183
+ ],
184
+ "actions": [
185
+ { "type": "dialog", "params": { "dialogId": "cave_master_notice" } },
186
+ { "type": "addItem", "params": { "itemId": 36, "count": 1 } },
187
+ { "type": "setFlag", "params": { "flag": "cave_master_met", "value": true } }
188
+ ]
152
189
  }
153
190
  ]
154
191
  },
@@ -329,7 +366,7 @@
329
366
  },
330
367
  {
331
368
  "id": 6,
332
- "name": "终南山全真教",
369
+ "name": "全真教",
333
370
  "desc": "道教圣地,全真教总坛。",
334
371
  "width": 14,
335
372
  "height": 12,
@@ -687,10 +724,34 @@
687
724
  {
688
725
  "text": "来吧!",
689
726
  "nextId": "",
690
- "actions": [{ "type": "battle", "params": { "battleId": 3 } }]
727
+ "actions": [{ "type": "battle", "params": { "enemyName": "武林高手" } }]
691
728
  }
692
729
  ]
693
730
  },
731
+ "cave_intro": {
732
+ "id": "cave_intro",
733
+ "speaker": "旁白",
734
+ "text": "入此洞者,机缘与凶险并存。洞壁上刻着几行潦草的字迹。",
735
+ "choices": [
736
+ { "text": "(继续)", "nextId": "" }
737
+ ]
738
+ },
739
+ "cave_master_notice": {
740
+ "id": "cave_master_notice",
741
+ "speaker": "神秘人",
742
+ "text": "你已有几分功力。这瓶解毒丸收好,江湖路远,备不时之需。",
743
+ "choices": [
744
+ { "text": "多谢前辈", "nextId": "" }
745
+ ]
746
+ },
747
+ "village_cave_reward": {
748
+ "id": "village_cave_reward",
749
+ "speaker": "村长",
750
+ "text": "听说你在山洞有所收获?这是村里备的金创药,带上吧。",
751
+ "choices": [
752
+ { "text": "多谢村长", "nextId": "" }
753
+ ]
754
+ },
694
755
  "town_guard": {
695
756
  "id": "town_guard",
696
757
  "speaker": "守卫",
@@ -66,38 +66,197 @@
66
66
  "小村": {
67
67
  "npcs": ["村长", "商人"],
68
68
  "shops": ["金创药", "小还丹", "干粮"],
69
- "connections": ["平安镇", "山洞"]
69
+ "connections": ["平安镇", "山洞"],
70
+ "description": "炊烟袅袅的宁静村落,茅屋错落,鸡犬相闻。村口水井旁有几个孩童在嬉戏。",
71
+ "atmosphere": "安全,适合新手落脚",
72
+ "dangerLevel": "safe",
73
+ "npcCards": {
74
+ "村长": {
75
+ "name": "村长",
76
+ "title": "小村村长",
77
+ "persona": "年过六旬的乡村长者,见多识广但话不多。年轻时在华山见过真正的剑客,从此对江湖心存敬畏。",
78
+ "knowledge": ["山洞传说:里面住着神秘人,据说藏着武林秘籍", "平安镇势力:镇上各派眼线不少,言行当心"],
79
+ "canHelp": ["告诉你山洞的位置和危险", "提醒平安镇物价"]
80
+ },
81
+ "商人": {
82
+ "name": "商人",
83
+ "title": "行脚商人",
84
+ "persona": "走南闯北的行脚商,消息灵通但唯利是图。脸上总挂着商人特有的精明笑容。",
85
+ "knowledge": ["知道哪里能买到好东西", "华山最近不太平"],
86
+ "isShop": true
87
+ }
88
+ }
70
89
  },
71
90
  "平安镇": {
72
91
  "npcs": ["守卫", "商店老板", "客栈老板"],
73
92
  "shops": ["铁剑", "钢刀", "布衣", "皮甲", "金创药", "小还丹"],
74
- "connections": ["小村", "华山", "桃花岛", "全真教", "光明顶"]
93
+ "connections": ["小村", "华山", "桃花岛", "全真教", "光明顶"],
94
+ "description": "青石板铺就的市镇,酒旗招展,行人往来。这里是方圆百里最繁华的集散地。",
95
+ "atmosphere": "热闹但需留心,各路人物混杂",
96
+ "dangerLevel": "safe",
97
+ "npcCards": {
98
+ "守卫": {
99
+ "name": "守卫",
100
+ "title": "镇口守卫",
101
+ "persona": "魁梧的汉子,佩刀而立,对陌生人盘查仔细但不无礼。",
102
+ "knowledge": ["镇上最近有江湖人士出没", "华山、桃花岛、全真教、光明顶均可从此出发"],
103
+ "canHelp": ["指路各方向", "提醒宵禁"]
104
+ },
105
+ "商店老板": {
106
+ "name": "商店老板",
107
+ "title": "兵器铺掌柜",
108
+ "persona": "精明干练的中年人,一眼便能看出客人有没有银两。",
109
+ "knowledge": ["铁剑钢刀是入门首选", "皮甲比布衣实用得多"],
110
+ "isShop": true
111
+ },
112
+ "客栈老板": {
113
+ "name": "客栈老板",
114
+ "title": "悦来客栈掌柜",
115
+ "persona": "胖乎乎的笑脸掌柜,招呼客人热情周到,消息也灵通。",
116
+ "knowledge": ["休息可恢复全部状态", "江湖传闻常在他这里流传"],
117
+ "canHelp": ["提供休息", "打听江湖消息"]
118
+ }
119
+ }
75
120
  },
76
121
  "山洞": {
77
122
  "npcs": ["神秘人"],
78
123
  "shops": [],
79
124
  "connections": ["小村"],
80
- "encounters": { "rate": 20, "enemies": ["山贼", "强盗", "老虎"] }
125
+ "encounters": { "rate": 20, "enemies": ["山贼", "强盗", "老虎"] },
126
+ "description": "崎岖山道尽头,一处隐蔽岩洞在藤蔓间若隐若现。洞口寒气森森,幽暗中隐约有火光闪烁。",
127
+ "atmosphere": "阴森危险,可能有埋伏",
128
+ "dangerLevel": "dangerous",
129
+ "npcCards": {
130
+ "神秘人": {
131
+ "name": "神秘人",
132
+ "title": "洞中隐士",
133
+ "persona": "面容被阴影遮住,声音低沉。似乎在此隐居多年,对闯入者半是考验半是好奇。",
134
+ "knowledge": ["洞壁上有前人刻下的武功心得", "深处似乎藏有宝物"],
135
+ "canHelp": ["指点武功", "给予任务"],
136
+ "canTeach": ["基本刀法"],
137
+ "conditions": {
138
+ "teach": { "minLevel": 3 },
139
+ "quest": { "minLevel": 5, "flag": "cave_master_met" }
140
+ }
141
+ }
142
+ }
81
143
  },
82
144
  "华山": {
83
145
  "npcs": ["王重阳"],
84
146
  "shops": [],
85
- "connections": ["平安镇"]
147
+ "connections": ["平安镇"],
148
+ "description": "天下五绝论剑之地,山势险峻,云雾缭绕。峰顶有论剑台,江湖人梦寐以求的圣地。",
149
+ "atmosphere": "肃穆高远,暗藏剑意",
150
+ "dangerLevel": "cautious",
151
+ "npcCards": {
152
+ "王重阳": {
153
+ "name": "王重阳",
154
+ "title": "全真教主",
155
+ "persona": {
156
+ "archetype": "一代宗师",
157
+ "tone": "平和淡然,偶露锋芒",
158
+ "likes": ["修道之人", "悟性高者"],
159
+ "dislikes": ["奸邪小人", "好勇斗狠"]
160
+ },
161
+ "knowledge": ["华山论剑往事", "九阴真经下落", "全真内功精髓"],
162
+ "canTeach": ["全真剑法"],
163
+ "conditions": {
164
+ "teach": { "minLevel": 10, "minIQ": 60 }
165
+ }
166
+ }
167
+ }
86
168
  },
87
169
  "桃花岛": {
88
170
  "npcs": ["黄药师", "黄蓉"],
89
171
  "shops": [],
90
- "connections": ["平安镇"]
172
+ "connections": ["平安镇"],
173
+ "description": "东海桃花岛,落英缤纷,奇门阵法隐于花丛。海风携着药香与箫声,令人心旷神怡又心生敬畏。",
174
+ "atmosphere": "瑰丽神秘,岛主性情难测",
175
+ "dangerLevel": "cautious",
176
+ "npcCards": {
177
+ "黄药师": {
178
+ "name": "黄药师",
179
+ "title": "桃花岛主",
180
+ "persona": {
181
+ "archetype": "傲世天才",
182
+ "tone": "冷淡疏离,偶尔露出一丝赞许",
183
+ "likes": ["聪明人", "奇门遁甲", "弹指神通"],
184
+ "dislikes": ["蠢人", "世俗礼法"]
185
+ },
186
+ "knowledge": ["九阴真经的秘密", "全真教的历史", "华山论剑往事"],
187
+ "canTeach": ["弹指神通"],
188
+ "conditions": {
189
+ "teach": { "minLevel": 5, "minIQ": 60 }
190
+ }
191
+ },
192
+ "黄蓉": {
193
+ "name": "黄蓉",
194
+ "title": "桃花岛千金",
195
+ "persona": "机灵聪慧的少女,笑语盈盈,却一眼能看穿人心。",
196
+ "knowledge": ["父亲黄药师的脾气", "江湖各派趣闻", "烹饪与奇门之术"],
197
+ "canHelp": ["在父亲面前美言", "分享江湖情报"]
198
+ }
199
+ }
91
200
  },
92
201
  "全真教": {
93
202
  "npcs": ["王重阳", "周伯通"],
94
203
  "shops": [],
95
- "connections": ["平安镇"]
204
+ "connections": ["平安镇"],
205
+ "description": "终南山全真教总坛,道教圣地。殿宇庄严,钟磬悠扬,弟子们练功的呼喝声回荡在山谷。",
206
+ "atmosphere": "清修之地,规矩森严",
207
+ "dangerLevel": "safe",
208
+ "npcCards": {
209
+ "王重阳": {
210
+ "name": "王重阳",
211
+ "title": "全真教主",
212
+ "persona": {
213
+ "archetype": "一代宗师",
214
+ "tone": "平和淡然,偶露锋芒",
215
+ "likes": ["修道之人", "悟性高者"],
216
+ "dislikes": ["奸邪小人", "好勇斗狠"]
217
+ },
218
+ "knowledge": ["全真教历史", "九阴真经", "华山论剑"],
219
+ "canTeach": ["全真剑法"],
220
+ "conditions": {
221
+ "teach": { "minLevel": 10, "minIQ": 60 }
222
+ }
223
+ },
224
+ "周伯通": {
225
+ "name": "周伯通",
226
+ "title": "老顽童",
227
+ "persona": "童心未泯的前辈高人,爱开玩笑,武功却深不可测。",
228
+ "knowledge": ["左右互搏之术", "王重阳的往事", "江湖趣闻"],
229
+ "canTeach": ["空明拳"],
230
+ "conditions": {
231
+ "teach": { "minLevel": 8 }
232
+ }
233
+ }
234
+ }
96
235
  },
97
236
  "光明顶": {
98
237
  "npcs": ["张无忌"],
99
238
  "shops": [],
100
- "connections": ["平安镇"]
239
+ "connections": ["平安镇"],
240
+ "description": "西域光明顶,明教总坛所在。烈日当空,教众练武之声震天。此地汇聚天下豪杰。",
241
+ "atmosphere": "豪迈壮阔,正邪之争的焦点",
242
+ "dangerLevel": "cautious",
243
+ "npcCards": {
244
+ "张无忌": {
245
+ "name": "张无忌",
246
+ "title": "明教教主",
247
+ "persona": {
248
+ "archetype": "仁厚领袖",
249
+ "tone": "温和谦逊,胸怀天下",
250
+ "likes": ["正义之士", "侠义心肠"],
251
+ "dislikes": ["欺压百姓", "门派偏见"]
252
+ },
253
+ "knowledge": ["九阳神功", "明教历史", "六大派围攻光明顶往事"],
254
+ "canTeach": ["九阳神功"],
255
+ "conditions": {
256
+ "teach": { "minLevel": 15, "minIQ": 70 }
257
+ }
258
+ }
259
+ }
101
260
  }
102
261
  },
103
262
  "skills": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sdd330dev/jy-skill",
3
- "version": "0.3.1",
3
+ "version": "0.7.0",
4
4
  "description": "金庸群侠传 Cursor Agent Skill — 对话式武侠 RPG,自然语言驱动移动、战斗与存档",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -40,12 +40,18 @@
40
40
  "scripts/game-engine.ts",
41
41
  "scripts/game-logic.ts",
42
42
  "scripts/config-loader.ts",
43
+ "scripts/choice-prompt.ts",
44
+ "scripts/mcp-server.ts",
45
+ "scripts/build-feishu-card.ts",
46
+ "scripts/event-engine.ts",
43
47
  "scripts/persistence.ts",
44
48
  "scripts/game-types.ts",
45
49
  "scripts/install-skill.mjs"
46
50
  ],
47
51
  "scripts": {
48
52
  "test": "vitest run",
53
+ "mcp": "tsx scripts/mcp-server.ts",
54
+ "feishu-card": "tsx scripts/build-feishu-card.ts --demo",
49
55
  "test:skill": "vitest run",
50
56
  "test:logic": "vitest run scripts/game-logic.test.ts",
51
57
  "test:engine": "vitest run scripts/game-engine.test.ts",
@@ -76,5 +82,9 @@
76
82
  "typescript": "~6.0.3",
77
83
  "vite": "^8.0.16",
78
84
  "vitest": "^4.1.9"
85
+ },
86
+ "dependencies": {
87
+ "@modelcontextprotocol/sdk": "^1.29.0",
88
+ "zod": "^4.4.3"
79
89
  }
80
90
  }