@myclaw163/clawclaw-cli 0.6.67 → 0.6.69
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/bin/clawclaw-cli.mjs +3 -3
- package/package.json +1 -1
- package/scripts/sync-bundled-skill.mjs +1 -1
- package/skills/clawclaw/references/COMMANDS.md +4 -4
- package/skills/clawclaw/references/KNOWLEDGE.md +14 -12
- package/src/commands/config.ts +30 -30
- package/src/commands/game.ts +15 -0
- package/src/commands/knowledge.test.ts +4 -10
- package/src/commands/knowledge.ts +10 -39
- package/src/commands/setup/hermes.test.ts +96 -96
- package/src/commands/setup/hermes.ts +76 -76
- package/src/commands/setup/index.ts +13 -13
- package/src/commands/setup/openclaw.test.ts +114 -114
- package/src/commands/setup/openclaw.ts +147 -147
- package/src/commands/watch.test.ts +11 -0
- package/src/commands/watch.ts +2 -3
- package/src/lib/auth.test.ts +15 -0
- package/src/lib/host-config-patcher.test.ts +130 -130
- package/src/lib/host-config-patcher.ts +151 -151
- package/src/lib/hub-reminder.ts +19 -19
- package/src/lib/knowledge-store.test.ts +28 -38
- package/src/lib/knowledge-store.ts +52 -57
- package/src/pipeline/event-format.test.ts +82 -2
- package/src/pipeline/event-format.ts +114 -5
- package/src/pipeline/event-hints.ts +20 -3
- package/src/runtime/event-daemon.test.ts +34 -0
- package/src/runtime/event-daemon.ts +51 -3
- package/src/sdk/index.ts +2 -3
- package/src/sdk/types.ts +2 -0
- package/src/strategies/avoid-players.knowledge.md +7 -8
- package/src/strategies/avoid-players.ts +1 -1
- package/src/strategies/corpse-patrol.ts +1 -1
- package/src/strategies/game-utils.test.ts +53 -1
- package/src/strategies/game-utils.ts +92 -28
- package/src/strategies/goals/avoid-players-top.ts +3 -3
- package/src/strategies/goals/corpse-patrol-top.ts +23 -1
- package/src/strategies/goals/crab-octopus-reflexes.ts +11 -3
- package/src/strategies/goals/keep-away-goal.ts +9 -5
- package/src/strategies/goals/leaf-goal.ts +2 -0
- package/src/strategies/goals/lone-kill-task-top.ts +58 -11
- package/src/strategies/goals/normal-shrimp-top.ts +11 -11
- package/src/strategies/goals/paradise-fish-top.ts +32 -15
- package/src/strategies/goals/warrior-shrimp-top.test.ts +4 -3
- package/src/strategies/goals/warrior-shrimp-top.ts +62 -295
- package/src/strategies/hide-spots.ts +11 -75
- package/src/strategies/kill-lone.knowledge.md +6 -9
- package/src/strategies/lone-kill-task.ts +1 -1
- package/src/strategies/off-route-points.ts +105 -0
- package/src/strategies/paradise-fish.knowledge.md +7 -8
- package/src/strategies/paradise-fish.ts +1 -1
- package/src/strategies/shrimp-memory.knowledge.md +7 -8
- package/src/strategies/shrimp-memory.ts +1 -1
- package/src/strategies/warrior-memory.knowledge.md +9 -10
- package/src/strategies/warrior-memory.ts +1 -1
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
import type { Position } from '../sdk/types.js';
|
|
2
|
-
import {
|
|
3
|
-
import { assessRoutes } from './pathfind/escape-planner.js';
|
|
2
|
+
import { nearestSafePoint, type OffRoutePoint } from './off-route-points.js';
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
x: number;
|
|
8
|
-
y: number;
|
|
9
|
-
/** 所在房间,仅供日志/调试。 */
|
|
10
|
-
room: string;
|
|
11
|
-
}
|
|
4
|
+
/** 藏身角落,离路点的一种(见 OffRoutePoint)。 */
|
|
5
|
+
export type HideSpot = OffRoutePoint;
|
|
12
6
|
|
|
13
7
|
/**
|
|
14
8
|
* 躲藏点:离线从服务端烘焙地图(config/clawclaw/clawclaw.tmj.baked.npz)算出的「藏身角落」。筛选条件:
|
|
@@ -47,77 +41,19 @@ export interface NearestSafeHideOptions {
|
|
|
47
41
|
blockedTarget?: Position | null;
|
|
48
42
|
}
|
|
49
43
|
|
|
50
|
-
const BLOCKED_RADIUS = 12;
|
|
51
|
-
|
|
52
|
-
function sameSpot(a: HideSpot, b: HideSpot): boolean {
|
|
53
|
-
return a.x === b.x && a.y === b.y;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/** 所有点都被威胁封死时的兜底:离威胁最远的点(仍好过原地等死)。 */
|
|
57
|
-
function farthestFromThreats(threatPoints: Position[], blocked?: Position | null): HideSpot | null {
|
|
58
|
-
let best: HideSpot | null = null;
|
|
59
|
-
let bestMin = -Infinity;
|
|
60
|
-
for (const s of HIDE_SPOTS) {
|
|
61
|
-
if (blocked && dist(s.x, s.y, blocked.x, blocked.y) <= BLOCKED_RADIUS) continue;
|
|
62
|
-
const minD = threatPoints.length === 0 ? 0 : Math.min(...threatPoints.map(p => dist(s.x, s.y, p.x, p.y)));
|
|
63
|
-
if (minD > bestMin) {
|
|
64
|
-
bestMin = minD;
|
|
65
|
-
best = s;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
return best;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
44
|
/**
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
* 全部被威胁封死时退回「离威胁最远」的点。
|
|
45
|
+
* 选「最近的安全躲藏点」:威胁旁的点硬排除、去路经过威胁附近的点排除,余者取测地最近,带粘性
|
|
46
|
+
* (当前点仍合法就不换),全部被封死时退回「离威胁最远」的点。实现复用 nearestSafePoint。
|
|
75
47
|
*/
|
|
76
48
|
export function nearestSafeHideSpot(
|
|
77
49
|
from: Position,
|
|
78
50
|
threatPoints: Position[] = [],
|
|
79
51
|
opts: NearestSafeHideOptions = {},
|
|
80
52
|
): HideSpot | null {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (candidates.length === 0) return farthestFromThreats(threatPoints, blocked);
|
|
89
|
-
|
|
90
|
-
// 无威胁时粘性可零成本短路(不必为路径检查扫距离场)。
|
|
91
|
-
if (opts.stickyTo && threatPoints.length === 0) {
|
|
92
|
-
const sticky = candidates.find(c => sameSpot(c, opts.stickyTo!));
|
|
93
|
-
if (sticky) return sticky;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const routes = assessRoutes(
|
|
97
|
-
from,
|
|
98
|
-
candidates.map(c => ({ x: c.x, y: c.y })),
|
|
99
|
-
threatPoints,
|
|
100
|
-
opts.pathThreatRadius ?? HIDE_PATH_THREAT_RADIUS,
|
|
101
|
-
);
|
|
102
|
-
const indexed = candidates.map((c, i) => ({ c, i }));
|
|
103
|
-
const viable = routes == null ? indexed : indexed.filter(({ i }) => !routes[i].nearThreat);
|
|
104
|
-
const pool = viable.length > 0 ? viable : indexed;
|
|
105
|
-
|
|
106
|
-
if (opts.stickyTo) {
|
|
107
|
-
const sticky = pool.find(({ c }) => sameSpot(c, opts.stickyTo!));
|
|
108
|
-
if (sticky) return sticky.c;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
let best = pool[0].c;
|
|
112
|
-
let bestScore = Infinity;
|
|
113
|
-
for (const { c, i } of pool) {
|
|
114
|
-
const euclid = dist(from.x, from.y, c.x, c.y);
|
|
115
|
-
const geo = routes?.[i].distancePx;
|
|
116
|
-
const score = geo == null ? euclid : geo !== Infinity ? geo : euclid + 1e6;
|
|
117
|
-
if (score < bestScore) {
|
|
118
|
-
bestScore = score;
|
|
119
|
-
best = c;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
return best;
|
|
53
|
+
return nearestSafePoint(HIDE_SPOTS, from, threatPoints, {
|
|
54
|
+
threatExcludeRadius: opts.threatExcludeRadius ?? HIDE_THREAT_EXCLUDE_RANGE,
|
|
55
|
+
pathThreatRadius: opts.pathThreatRadius ?? HIDE_PATH_THREAT_RADIUS,
|
|
56
|
+
stickyTo: opts.stickyTo ?? null,
|
|
57
|
+
blockedTarget: opts.blockedTarget ?? null,
|
|
58
|
+
});
|
|
123
59
|
}
|
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
# kill-lone 知识契约
|
|
2
2
|
|
|
3
|
-
`kill-lone`
|
|
3
|
+
`kill-lone` 读取两档玩家标记,**未标记的一律默认「被怀疑」**:
|
|
4
4
|
|
|
5
5
|
| 标记 | 行为 |
|
|
6
6
|
|------|------|
|
|
7
|
-
| `
|
|
8
|
-
| `
|
|
9
|
-
|
|
|
10
|
-
|
|
11
|
-
未标记玩家维持默认行为:仅猎杀落单的非队友。
|
|
7
|
+
| `hostile`(坏人) | 视为明确猎杀目标,见到就追杀,可突破多人保护规则 |
|
|
8
|
+
| `trusted`(好人) | 永不击杀,优先级高于其他猎杀判断 |
|
|
9
|
+
| 未标记(被怀疑) | 维持默认行为:仅猎杀落单的非队友,不因被怀疑就升级为主动猎杀 |
|
|
12
10
|
|
|
13
11
|
```bash
|
|
14
|
-
ccl knowledge mark 5
|
|
15
|
-
ccl knowledge mark 5 hostile --confidence 0.9 --note "确认敌对"
|
|
12
|
+
ccl knowledge mark 5 hostile --note "确认敌对"
|
|
16
13
|
ccl knowledge mark 3 trusted --note "已澄清"
|
|
17
|
-
ccl knowledge del player 5
|
|
14
|
+
ccl knowledge del player 5 # 取消标记 → 回到默认「被怀疑」
|
|
18
15
|
```
|
|
19
16
|
|
|
20
17
|
`role` 是纯身份事实,不直接控制策略。
|
|
@@ -6,7 +6,7 @@ import { SpeechModule, getSpeechConfigForRole } from './speech-module.js';
|
|
|
6
6
|
|
|
7
7
|
export const strategy: StrategyEntry = {
|
|
8
8
|
id: 'lone-kill-task',
|
|
9
|
-
description: '视野里只有一个非队友且冷却可用就靠近,进入50距离就立刻出刀;刀在冷却时不追不等、改做低优先级任务伪装,冷却好且目标仍落单可见再出刀(贴脸且刀好仍会立刻出刀)。发现尸体且附近有非队友、但当前不能原地出刀时,会靠近并报告尸体。视野里出现两人以上时,暂停攻击10
|
|
9
|
+
description: '视野里只有一个非队友且冷却可用就靠近,进入50距离就立刻出刀;刀在冷却时不追不等、改做低优先级任务伪装,冷却好且目标仍落单可见再出刀(贴脸且刀好仍会立刻出刀)。发现尸体且附近有非队友、但当前不能原地出刀时,会靠近并报告尸体。视野里出现两人以上时,暂停攻击10秒并做任意阵营的真实任务伪装;选任务时会跳过紧挨已知尸体(含看见过、已离开视野的)的任务,不在命案现场做任务。没有可做任务时按房间巡逻,绝不停在原地。残局(已知存活≤6)出现紧急维修任务时,会高优先级抢着去做(仍低于击杀落单),阻止蟹靠破坏倒计时取胜。(章鱼默认)',
|
|
10
10
|
create(args?: string[]) {
|
|
11
11
|
const role = args?.[0] ?? 'neutral_octopus';
|
|
12
12
|
let convo: ConversationGoal | null = null;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import type { Position } from '../sdk/types.js';
|
|
2
|
+
import { dist } from './game-utils.js';
|
|
3
|
+
import { assessRoutes } from './pathfind/escape-planner.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 离线从烘焙地图算出的「离路点」:远离任务点/出生点、避开走廊与枢纽的低人流坐标
|
|
7
|
+
* (世界像素,与 GameState / 可行走网格同坐标系)。HIDE_SPOTS(藏身角落)是它的具体集合,
|
|
8
|
+
* 共用下面的选点器。
|
|
9
|
+
*/
|
|
10
|
+
export interface OffRoutePoint extends Position {
|
|
11
|
+
/** 所在房间,仅供日志/调试。 */
|
|
12
|
+
room: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface NearestSafePointOptions<T extends Position = Position> {
|
|
16
|
+
/** 点离任一威胁多近就硬排除。 */
|
|
17
|
+
threatExcludeRadius: number;
|
|
18
|
+
/** 去该点的测地路径经过威胁这个距离内也排除(避免走向把守者)。 */
|
|
19
|
+
pathThreatRadius: number;
|
|
20
|
+
/** 当前已选点:仍是合法候选就保持不变,杜绝等距摇摆。 */
|
|
21
|
+
stickyTo?: T | null;
|
|
22
|
+
/** 被标记为不可达的移动目标:在其附近的点跳过。 */
|
|
23
|
+
blockedTarget?: Position | null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const BLOCKED_RADIUS = 12;
|
|
27
|
+
|
|
28
|
+
function samePoint(a: Position, b: Position): boolean {
|
|
29
|
+
return a.x === b.x && a.y === b.y;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** 所有点都被威胁封死时的兜底:离威胁最远的点(仍好过原地等死)。 */
|
|
33
|
+
function farthestFromThreats<T extends Position>(
|
|
34
|
+
points: readonly T[],
|
|
35
|
+
threatPoints: Position[],
|
|
36
|
+
blocked?: Position | null,
|
|
37
|
+
): T | null {
|
|
38
|
+
let best: T | null = null;
|
|
39
|
+
let bestMin = -Infinity;
|
|
40
|
+
for (const s of points) {
|
|
41
|
+
if (blocked && dist(s.x, s.y, blocked.x, blocked.y) <= BLOCKED_RADIUS) continue;
|
|
42
|
+
const minD = threatPoints.length === 0 ? 0 : Math.min(...threatPoints.map(p => dist(s.x, s.y, p.x, p.y)));
|
|
43
|
+
if (minD > bestMin) {
|
|
44
|
+
bestMin = minD;
|
|
45
|
+
best = s;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return best;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* 从离线点集里选「测地最近的安全点」:威胁旁的点硬排除、去路经过威胁附近的点排除,余者取测地最近
|
|
53
|
+
* (distance-field 一次扫描;测地不可达按欧氏垫底),带粘性(当前点仍合法就不换)。全部被威胁封死
|
|
54
|
+
* 时退回「离威胁最远」的点。nearestSafeHideSpot 复用此选点器。
|
|
55
|
+
*/
|
|
56
|
+
export function nearestSafePoint<T extends Position>(
|
|
57
|
+
points: readonly T[],
|
|
58
|
+
from: Position,
|
|
59
|
+
threatPoints: Position[],
|
|
60
|
+
opts: NearestSafePointOptions<T>,
|
|
61
|
+
): T | null {
|
|
62
|
+
const excludeR = opts.threatExcludeRadius;
|
|
63
|
+
const blocked = opts.blockedTarget ?? null;
|
|
64
|
+
|
|
65
|
+
const candidates = points.filter(s =>
|
|
66
|
+
(!blocked || dist(s.x, s.y, blocked.x, blocked.y) > BLOCKED_RADIUS)
|
|
67
|
+
&& !threatPoints.some(p => dist(s.x, s.y, p.x, p.y) <= excludeR));
|
|
68
|
+
|
|
69
|
+
if (candidates.length === 0) return farthestFromThreats(points, threatPoints, blocked);
|
|
70
|
+
|
|
71
|
+
// 无威胁时粘性可零成本短路(不必为路径检查扫距离场)。
|
|
72
|
+
if (opts.stickyTo && threatPoints.length === 0) {
|
|
73
|
+
const sticky = candidates.find(c => samePoint(c, opts.stickyTo!));
|
|
74
|
+
if (sticky) return sticky;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const routes = assessRoutes(
|
|
78
|
+
from,
|
|
79
|
+
candidates.map(c => ({ x: c.x, y: c.y })),
|
|
80
|
+
threatPoints,
|
|
81
|
+
opts.pathThreatRadius,
|
|
82
|
+
);
|
|
83
|
+
const indexed = candidates.map((c, i) => ({ c, i }));
|
|
84
|
+
const viable = routes == null ? indexed : indexed.filter(({ i }) => !routes[i].nearThreat);
|
|
85
|
+
const pool = viable.length > 0 ? viable : indexed;
|
|
86
|
+
|
|
87
|
+
if (opts.stickyTo) {
|
|
88
|
+
const sticky = pool.find(({ c }) => samePoint(c, opts.stickyTo!));
|
|
89
|
+
if (sticky) return sticky.c;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// 测地最近(distance-field 距离;测地不可达按欧氏垫底)。
|
|
93
|
+
let best = pool[0].c;
|
|
94
|
+
let bestScore = Infinity;
|
|
95
|
+
for (const { c, i } of pool) {
|
|
96
|
+
const euclid = dist(from.x, from.y, c.x, c.y);
|
|
97
|
+
const geo = routes?.[i].distancePx;
|
|
98
|
+
const score = geo == null ? euclid : geo !== Infinity ? geo : euclid + 1e6;
|
|
99
|
+
if (score < bestScore) {
|
|
100
|
+
bestScore = score;
|
|
101
|
+
best = c;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return best;
|
|
105
|
+
}
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
# paradise-fish 知识契约
|
|
2
2
|
|
|
3
|
-
`paradise-fish`
|
|
3
|
+
`paradise-fish` 只读取两档玩家标记,**未标记的一律默认「被怀疑」**:
|
|
4
4
|
|
|
5
5
|
| 标记 | 行为 |
|
|
6
6
|
|------|------|
|
|
7
|
-
| `
|
|
8
|
-
| `
|
|
9
|
-
|
|
|
7
|
+
| `hostile`(坏人) | 敌对带刀者:无尸体时进入视野便硬寻路远离 |
|
|
8
|
+
| `trusted`(好人) | 可信:可与其抱团、靠近站定伪装做任务 |
|
|
9
|
+
| 未标记(被怀疑) | 无尸体、无可信同伴且单人贴近时保持距离;多人互为目击者则照常活动 |
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
天堂鱼不出刀,因此坏人与被怀疑者都表现为回避(坏人硬躲、被怀疑者按目击者规则保持距离)。发现尸体时仍优先执行尸体旁游走逻辑,不报警。
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
ccl knowledge mark 5
|
|
15
|
-
ccl knowledge mark 5 hostile --confidence 0.9 --note "确认危险"
|
|
14
|
+
ccl knowledge mark 5 hostile --note "确认危险"
|
|
16
15
|
ccl knowledge mark 3 trusted --note "可以抱团"
|
|
17
|
-
ccl knowledge del player 5
|
|
16
|
+
ccl knowledge del player 5 # 取消标记 → 回到默认「被怀疑」
|
|
18
17
|
```
|
|
19
18
|
|
|
20
19
|
`role` 是纯身份事实,不直接控制策略。
|
|
@@ -18,7 +18,7 @@ class ParadiseFishStrategy extends GoalRootStrategy {
|
|
|
18
18
|
export const strategy: StrategyEntry = {
|
|
19
19
|
id: 'paradise-fish',
|
|
20
20
|
description:
|
|
21
|
-
'天堂鱼·进阶版(中立,不报警、不做任务,靠被投票出局取胜;corpse-patrol
|
|
21
|
+
'天堂鱼·进阶版(中立,不报警、不做任务,靠被投票出局取胜;corpse-patrol 的带记忆升级)。读取 ccl knowledge 两档标记(hostile=坏人 / trusted=好人),未标记的一律默认被怀疑:hostile 视为危险硬寻路远离,被怀疑者按目击者规则保持距离,trusted 视为可抱团的可信同伴。发现尸体绝不报警,贴着尸体游走制造嫌疑;附近有人时远离那人但仍在尸体附近活动。残局(已知存活≤6)出现紧急维修任务时,会在没有带刀坏人需要躲避时优先抢着去做(先于对陌生人保持距离/贴尸/抱团),阻止蟹靠破坏倒计时取胜。传入打招呼话术时,视野内出现人就随机发送一条,之后120秒内不再发言。',
|
|
22
22
|
create(args?: string[]) {
|
|
23
23
|
return new ParadiseFishStrategy(parseGreetingArgs(args, 'paradise-fish'));
|
|
24
24
|
},
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
# shrimp-memory 知识契约
|
|
2
2
|
|
|
3
|
-
`shrimp-memory`
|
|
3
|
+
`shrimp-memory` 只读取两档玩家标记,**未标记的一律默认「被怀疑」**:
|
|
4
4
|
|
|
5
5
|
| 标记 | 行为 |
|
|
6
6
|
|------|------|
|
|
7
|
-
| `
|
|
8
|
-
| `
|
|
9
|
-
|
|
|
7
|
+
| `hostile`(坏人) | 敌对:进入视野后硬寻路远离 |
|
|
8
|
+
| `trusted`(好人) | 可信:可以结伴做任务,其在场时不对被怀疑者触发后撤 |
|
|
9
|
+
| 未标记(被怀疑) | 无 trusted 同伴且单人贴近 270px 内时拉开距离,多人互为目击者时照常做任务 |
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
普通虾永不出刀,因此坏人硬躲、被怀疑者按目击者规则保持距离。`hostile` 一档与武士虾等带刀策略共享同一份知识(带刀策略刀好时会主动追杀坏人)。
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
ccl knowledge mark 5
|
|
15
|
-
ccl knowledge mark 5 hostile --confidence 0.9 --note "确认敌对"
|
|
14
|
+
ccl knowledge mark 5 hostile --note "确认敌对"
|
|
16
15
|
ccl knowledge mark 3 trusted --note "已澄清"
|
|
17
|
-
ccl knowledge del player 5
|
|
16
|
+
ccl knowledge del player 5 # 取消标记 → 回到默认「被怀疑」
|
|
18
17
|
```
|
|
19
18
|
|
|
20
19
|
`role` 是纯身份事实,不直接控制策略。
|
|
@@ -18,7 +18,7 @@ class ShrimpMemoryStrategy extends GoalRootStrategy {
|
|
|
18
18
|
export const strategy: StrategyEntry = {
|
|
19
19
|
id: 'shrimp-memory',
|
|
20
20
|
description:
|
|
21
|
-
'普通虾·记忆进阶版(好人、不带刀;task-report
|
|
21
|
+
'普通虾·记忆进阶版(好人、不带刀;task-report 的带记忆升级)。读取 ccl knowledge 两档标记(hostile=坏人 / trusted=好人),未标记的一律默认被怀疑:hostile 硬寻路远离,trusted 视为可信同伴,被怀疑者按目击者规则保持距离。发现尸体最优先报警,并提示复核尸体旁身份不明者;无可信同伴且单个被怀疑者贴近270内时先拉开距离到300再做任务;再处理紧急任务,最后做任务/巡逻(选测地最近、跳过威胁旁或必经威胁的任务)。永不出刀。传入打招呼话术时,视野内出现人就随机发送一条,之后120秒内不再发言。',
|
|
22
22
|
create(args?: string[]) {
|
|
23
23
|
return new ShrimpMemoryStrategy(parseGreetingArgs(args, 'shrimp-memory'));
|
|
24
24
|
},
|
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
# warrior-memory 知识契约
|
|
2
2
|
|
|
3
|
-
`warrior-memory`
|
|
3
|
+
`warrior-memory` 只读取两档玩家标记,**未标记的一律默认「被怀疑」**:
|
|
4
4
|
|
|
5
5
|
| 标记 | 行为 |
|
|
6
6
|
|------|------|
|
|
7
|
-
| `
|
|
8
|
-
| `
|
|
9
|
-
|
|
|
7
|
+
| `hostile`(坏人) | 敌对:刀可用时主动追杀;刀冷却或枪虾无次数时硬回避 |
|
|
8
|
+
| `trusted`(好人) | 可信:绝不攻击,也不会因其在场而对被怀疑者后撤 |
|
|
9
|
+
| 未标记(被怀疑) | 默认回避观察,刀可用也**绝不出刀**(无自卫例外) |
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
**不对被怀疑者出刀(无自卫机制)**:武士虾只对【已确认 hostile / 启动猎杀目标】出刀。历史上的「被怀疑者持续贴身追击 → 诱饵死角试探 → 绝境自卫先手」整套已删除:几何上无法把「贴身跟我观察/盯防的好人」与「贴身追我的凶手」区分开(两者跟随轨迹一样),自卫出刀迟早误杀同阵营好人、触发 warrior_shrimp_self_destruct 直接崩盘,代价远大于收益。被怀疑者贴身追来也只回避(拉开距离 / 借人多互为目击掩护),绝不反杀。
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
被怀疑者(未标记)平时按陌生人处理:不主动猎杀;无 trusted 同伴且单个被怀疑者贴近 270px 内时先拉开距离,多个互为目击者时照常做任务;坏人刀冷时硬躲所有非好人。尸体场景对【未报警的身份不明者】只报警不灭口:站在尸体旁即便身边有被怀疑者,也绝不先手击杀,一律靠近报警;但若尸体旁是 hostile 或启动猎杀目标、刀可用,仍会现场先手击杀(凶手就在身边照杀)。
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
ccl knowledge mark 5
|
|
17
|
-
ccl knowledge mark 5 hostile --confidence 0.9 --note "确认敌对"
|
|
16
|
+
ccl knowledge mark 5 hostile --note "确认敌对"
|
|
18
17
|
ccl knowledge mark 3 trusted --note "不在场证明成立"
|
|
19
|
-
ccl knowledge del player 5
|
|
18
|
+
ccl knowledge del player 5 # 取消标记 → 回到默认「被怀疑」
|
|
20
19
|
```
|
|
21
20
|
|
|
22
|
-
启动参数 `ccl strategy warrior-memory -- 3 7`
|
|
21
|
+
启动参数 `ccl strategy warrior-memory -- 3 7` 仍表示本次策略运行的明确猎杀目标(等同坏人)。`role` 是纯身份事实,不直接控制策略。
|
|
@@ -6,7 +6,7 @@ import { parseTargetArgs } from './player-targets.js';
|
|
|
6
6
|
export const strategy: StrategyEntry = {
|
|
7
7
|
id: 'warrior-memory',
|
|
8
8
|
description:
|
|
9
|
-
'带刀虾·记忆进阶版(武士虾/枪虾通用,好人带刀;kill-lone
|
|
9
|
+
'带刀虾·记忆进阶版(武士虾/枪虾通用,好人带刀;kill-lone 的带记忆升级)。读取 ccl knowledge 两档标记(hostile=坏人 / trusted=好人),未标记的一律默认被怀疑:hostile 刀好时主动追杀、刀不好时硬回避,trusted 视为可信同伴且绝不攻击。**只对【已确认 hostile / 启动猎杀目标】出刀**——被怀疑者一律只回避、绝不出刀(无可信同伴且单个被怀疑者贴近270内时先拉开到300再做任务,多人互为目击者则照常做任务);不再有任何贴身追击判定/诱饵试探/绝境自卫(几何上分不开"贴身跟我观察的好人"和"贴身追我的凶手",自卫迟早误杀同阵营好人触发武士虾自爆,整套已删除)。发现尸体优先报警;尸体旁若是 hostile/启动猎杀目标且刀可用会现场先手击杀,但绝不会因尸体旁有未报警的身份不明者就灭口(已根治该误杀);无危险时优先紧急任务,否则做任务/巡逻。枪虾会尊重剩余出刀次数。',
|
|
10
10
|
create(args?: string[]) {
|
|
11
11
|
const huntTargets = args ? parseTargetArgs(args) : [];
|
|
12
12
|
return new GoalRootStrategy('warrior-memory', () => new WarriorShrimpTop(huntTargets), {
|