@agents-uni/zhenhuan 0.1.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/DESIGN.md +198 -0
- package/LICENSE +21 -0
- package/README.en.md +547 -0
- package/README.md +549 -0
- package/dist/cli/index.d.ts +4 -0
- package/dist/cli/index.js +253 -0
- package/dist/competition/elo.d.ts +62 -0
- package/dist/competition/elo.js +146 -0
- package/dist/competition/horse-race.d.ts +72 -0
- package/dist/competition/horse-race.js +110 -0
- package/dist/competition/index.d.ts +6 -0
- package/dist/competition/index.js +3 -0
- package/dist/competition/season.d.ts +68 -0
- package/dist/competition/season.js +150 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +21 -0
- package/dist/orchestrator/index.d.ts +142 -0
- package/dist/orchestrator/index.js +268 -0
- package/dist/palace/ceremonies.d.ts +55 -0
- package/dist/palace/ceremonies.js +263 -0
- package/dist/palace/cold-palace.d.ts +41 -0
- package/dist/palace/cold-palace.js +106 -0
- package/dist/palace/dynamics.d.ts +52 -0
- package/dist/palace/dynamics.js +192 -0
- package/dist/palace/ranks.d.ts +31 -0
- package/dist/palace/ranks.js +46 -0
- package/dist/palace/resources.d.ts +55 -0
- package/dist/palace/resources.js +146 -0
- package/dist/server/index.d.ts +14 -0
- package/dist/server/index.js +202 -0
- package/dist/server/routes/index.d.ts +6 -0
- package/dist/server/routes/index.js +287 -0
- package/package.json +66 -0
- package/universe.yaml +365 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Palace Ceremonies - 宫廷典礼
|
|
3
|
+
*
|
|
4
|
+
* Handles formal palace events: court assemblies, selections,
|
|
5
|
+
* promotions, demotions, and eliminations.
|
|
6
|
+
*/
|
|
7
|
+
import type { AgentRegistry, EventBus } from '@agents-uni/core';
|
|
8
|
+
import type { AgentDefinition } from '@agents-uni/core';
|
|
9
|
+
export interface CeremonyResult {
|
|
10
|
+
type: 'court_assembly' | 'selection' | 'promotion' | 'demotion' | 'elimination';
|
|
11
|
+
timestamp: string;
|
|
12
|
+
participants: string[];
|
|
13
|
+
outcomes: CeremonyOutcome[];
|
|
14
|
+
narrative: string;
|
|
15
|
+
}
|
|
16
|
+
export interface CeremonyOutcome {
|
|
17
|
+
agentId: string;
|
|
18
|
+
action: string;
|
|
19
|
+
details: Record<string, unknown>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Manages formal palace ceremonies and rituals.
|
|
23
|
+
*/
|
|
24
|
+
export declare class PalaceCeremonies {
|
|
25
|
+
private registry;
|
|
26
|
+
private events;
|
|
27
|
+
private ceremonyHistory;
|
|
28
|
+
constructor(registry: AgentRegistry, events: EventBus);
|
|
29
|
+
/**
|
|
30
|
+
* Conduct monthly court assembly (朝会).
|
|
31
|
+
* Reviews rankings and triggers promotions/demotions.
|
|
32
|
+
*/
|
|
33
|
+
conductCourtAssembly(agentPerformances: Map<string, number>, eloRatings: Map<string, number>): Promise<CeremonyResult>;
|
|
34
|
+
/**
|
|
35
|
+
* Conduct selection ceremony (选秀) for new consorts.
|
|
36
|
+
*/
|
|
37
|
+
conductSelection(newAgents: AgentDefinition[]): Promise<CeremonyResult>;
|
|
38
|
+
/**
|
|
39
|
+
* Conduct promotion ceremony (晋升典礼).
|
|
40
|
+
*/
|
|
41
|
+
conductPromotion(agentId: string, newRankLevel: number): Promise<CeremonyResult>;
|
|
42
|
+
/**
|
|
43
|
+
* Conduct demotion (贬谪).
|
|
44
|
+
*/
|
|
45
|
+
conductDemotion(agentId: string, newRankLevel: number): Promise<CeremonyResult>;
|
|
46
|
+
/**
|
|
47
|
+
* Conduct elimination (打入冷宫).
|
|
48
|
+
*/
|
|
49
|
+
conductElimination(agentId: string): Promise<CeremonyResult>;
|
|
50
|
+
/** Get ceremony history */
|
|
51
|
+
getHistory(): CeremonyResult[];
|
|
52
|
+
/** Extract a numeric rank level from an agent definition */
|
|
53
|
+
private extractRankLevel;
|
|
54
|
+
private generateCourtNarrative;
|
|
55
|
+
}
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Palace Ceremonies - 宫廷典礼
|
|
3
|
+
*
|
|
4
|
+
* Handles formal palace events: court assemblies, selections,
|
|
5
|
+
* promotions, demotions, and eliminations.
|
|
6
|
+
*/
|
|
7
|
+
import { getRankByLevel, getRankByTitle, getNextRank, getPreviousRank, canPromote, isRankFull } from './ranks.js';
|
|
8
|
+
/**
|
|
9
|
+
* Manages formal palace ceremonies and rituals.
|
|
10
|
+
*/
|
|
11
|
+
export class PalaceCeremonies {
|
|
12
|
+
registry;
|
|
13
|
+
events;
|
|
14
|
+
ceremonyHistory;
|
|
15
|
+
constructor(registry, events) {
|
|
16
|
+
this.registry = registry;
|
|
17
|
+
this.events = events;
|
|
18
|
+
this.ceremonyHistory = [];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Conduct monthly court assembly (朝会).
|
|
22
|
+
* Reviews rankings and triggers promotions/demotions.
|
|
23
|
+
*/
|
|
24
|
+
async conductCourtAssembly(agentPerformances, eloRatings) {
|
|
25
|
+
const outcomes = [];
|
|
26
|
+
const participants = [];
|
|
27
|
+
// Evaluate each active consort
|
|
28
|
+
const citizens = this.registry.getAll().filter(c => c.status === 'active' || c.status === 'idle');
|
|
29
|
+
for (const citizen of citizens) {
|
|
30
|
+
const agentId = citizen.definition.id;
|
|
31
|
+
participants.push(agentId);
|
|
32
|
+
const performance = agentPerformances.get(agentId) ?? 50;
|
|
33
|
+
const elo = eloRatings.get(agentId) ?? 1200;
|
|
34
|
+
const currentRankLevel = this.extractRankLevel(citizen.definition);
|
|
35
|
+
// Check for promotion eligibility
|
|
36
|
+
if (performance >= 75 && canPromote(currentRankLevel, elo)) {
|
|
37
|
+
const nextRank = getNextRank(currentRankLevel);
|
|
38
|
+
if (nextRank) {
|
|
39
|
+
// Count current occupants at next rank
|
|
40
|
+
const occupantsAtNextRank = citizens.filter(c => this.extractRankLevel(c.definition) === nextRank.level).length;
|
|
41
|
+
if (!isRankFull(nextRank.level, occupantsAtNextRank)) {
|
|
42
|
+
outcomes.push({
|
|
43
|
+
agentId,
|
|
44
|
+
action: 'promotion_eligible',
|
|
45
|
+
details: {
|
|
46
|
+
currentLevel: currentRankLevel,
|
|
47
|
+
targetLevel: nextRank.level,
|
|
48
|
+
targetTitle: nextRank.title,
|
|
49
|
+
elo,
|
|
50
|
+
performance,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Check for demotion
|
|
57
|
+
if (performance < 30 && currentRankLevel > 1) {
|
|
58
|
+
const prevRank = getPreviousRank(currentRankLevel);
|
|
59
|
+
if (prevRank) {
|
|
60
|
+
outcomes.push({
|
|
61
|
+
agentId,
|
|
62
|
+
action: 'demotion_recommended',
|
|
63
|
+
details: {
|
|
64
|
+
currentLevel: currentRankLevel,
|
|
65
|
+
targetLevel: prevRank.level,
|
|
66
|
+
targetTitle: prevRank.title,
|
|
67
|
+
performance,
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const result = {
|
|
74
|
+
type: 'court_assembly',
|
|
75
|
+
timestamp: new Date().toISOString(),
|
|
76
|
+
participants,
|
|
77
|
+
outcomes,
|
|
78
|
+
narrative: this.generateCourtNarrative(outcomes),
|
|
79
|
+
};
|
|
80
|
+
this.ceremonyHistory.push(result);
|
|
81
|
+
await this.events.emitSimple('custom', participants, result.narrative, { ceremonyType: 'court_assembly', outcomeCount: outcomes.length });
|
|
82
|
+
return result;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Conduct selection ceremony (选秀) for new consorts.
|
|
86
|
+
*/
|
|
87
|
+
async conductSelection(newAgents) {
|
|
88
|
+
const outcomes = [];
|
|
89
|
+
const participants = [];
|
|
90
|
+
for (const agent of newAgents) {
|
|
91
|
+
try {
|
|
92
|
+
this.registry.register(agent);
|
|
93
|
+
this.registry.setStatus(agent.id, 'idle');
|
|
94
|
+
participants.push(agent.id);
|
|
95
|
+
outcomes.push({
|
|
96
|
+
agentId: agent.id,
|
|
97
|
+
action: 'selected',
|
|
98
|
+
details: {
|
|
99
|
+
name: agent.name,
|
|
100
|
+
role: agent.role.title,
|
|
101
|
+
rank: agent.rank,
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
await this.events.emitSimple('agent.joined', [agent.id], `${agent.name}通过选秀入宫,初封${agent.role.title}`, { agentId: agent.id });
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
outcomes.push({
|
|
108
|
+
agentId: agent.id,
|
|
109
|
+
action: 'selection_failed',
|
|
110
|
+
details: {
|
|
111
|
+
reason: error instanceof Error ? error.message : 'Unknown error',
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const result = {
|
|
117
|
+
type: 'selection',
|
|
118
|
+
timestamp: new Date().toISOString(),
|
|
119
|
+
participants,
|
|
120
|
+
outcomes,
|
|
121
|
+
narrative: `选秀大典:${newAgents.length}位秀女参选,${outcomes.filter(o => o.action === 'selected').length}位入选。`,
|
|
122
|
+
};
|
|
123
|
+
this.ceremonyHistory.push(result);
|
|
124
|
+
return result;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Conduct promotion ceremony (晋升典礼).
|
|
128
|
+
*/
|
|
129
|
+
async conductPromotion(agentId, newRankLevel) {
|
|
130
|
+
const citizen = this.registry.get(agentId);
|
|
131
|
+
if (!citizen) {
|
|
132
|
+
throw new Error(`Agent "${agentId}" not found`);
|
|
133
|
+
}
|
|
134
|
+
const newRank = getRankByLevel(newRankLevel);
|
|
135
|
+
if (!newRank) {
|
|
136
|
+
throw new Error(`Invalid rank level: ${newRankLevel}`);
|
|
137
|
+
}
|
|
138
|
+
const oldRankLevel = this.extractRankLevel(citizen.definition);
|
|
139
|
+
const oldRank = getRankByLevel(oldRankLevel);
|
|
140
|
+
// Update the agent's role title and rank
|
|
141
|
+
citizen.definition.role.title = newRank.title;
|
|
142
|
+
citizen.definition.rank = newRankLevel * 10;
|
|
143
|
+
const outcome = {
|
|
144
|
+
agentId,
|
|
145
|
+
action: 'promoted',
|
|
146
|
+
details: {
|
|
147
|
+
oldRank: oldRank?.title ?? '未知',
|
|
148
|
+
oldLevel: oldRankLevel,
|
|
149
|
+
newRank: newRank.title,
|
|
150
|
+
newLevel: newRankLevel,
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
const narrative = `晋升典礼:${citizen.definition.name}由${oldRank?.title ?? '未知'}晋升为${newRank.title},恩泽浩荡。`;
|
|
154
|
+
await this.events.emitSimple('agent.promoted', [agentId], narrative, outcome.details);
|
|
155
|
+
const result = {
|
|
156
|
+
type: 'promotion',
|
|
157
|
+
timestamp: new Date().toISOString(),
|
|
158
|
+
participants: [agentId],
|
|
159
|
+
outcomes: [outcome],
|
|
160
|
+
narrative,
|
|
161
|
+
};
|
|
162
|
+
this.ceremonyHistory.push(result);
|
|
163
|
+
return result;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Conduct demotion (贬谪).
|
|
167
|
+
*/
|
|
168
|
+
async conductDemotion(agentId, newRankLevel) {
|
|
169
|
+
const citizen = this.registry.get(agentId);
|
|
170
|
+
if (!citizen) {
|
|
171
|
+
throw new Error(`Agent "${agentId}" not found`);
|
|
172
|
+
}
|
|
173
|
+
const newRank = getRankByLevel(newRankLevel);
|
|
174
|
+
if (!newRank) {
|
|
175
|
+
throw new Error(`Invalid rank level: ${newRankLevel}`);
|
|
176
|
+
}
|
|
177
|
+
const oldRankLevel = this.extractRankLevel(citizen.definition);
|
|
178
|
+
const oldRank = getRankByLevel(oldRankLevel);
|
|
179
|
+
citizen.definition.role.title = newRank.title;
|
|
180
|
+
citizen.definition.rank = newRankLevel * 10;
|
|
181
|
+
const outcome = {
|
|
182
|
+
agentId,
|
|
183
|
+
action: 'demoted',
|
|
184
|
+
details: {
|
|
185
|
+
oldRank: oldRank?.title ?? '未知',
|
|
186
|
+
oldLevel: oldRankLevel,
|
|
187
|
+
newRank: newRank.title,
|
|
188
|
+
newLevel: newRankLevel,
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
const narrative = `贬谪旨意:${citizen.definition.name}由${oldRank?.title ?? '未知'}贬为${newRank.title},以儆效尤。`;
|
|
192
|
+
await this.events.emitSimple('agent.demoted', [agentId], narrative, outcome.details);
|
|
193
|
+
const result = {
|
|
194
|
+
type: 'demotion',
|
|
195
|
+
timestamp: new Date().toISOString(),
|
|
196
|
+
participants: [agentId],
|
|
197
|
+
outcomes: [outcome],
|
|
198
|
+
narrative,
|
|
199
|
+
};
|
|
200
|
+
this.ceremonyHistory.push(result);
|
|
201
|
+
return result;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Conduct elimination (打入冷宫).
|
|
205
|
+
*/
|
|
206
|
+
async conductElimination(agentId) {
|
|
207
|
+
const citizen = this.registry.get(agentId);
|
|
208
|
+
if (!citizen) {
|
|
209
|
+
throw new Error(`Agent "${agentId}" not found`);
|
|
210
|
+
}
|
|
211
|
+
this.registry.setStatus(agentId, 'suspended');
|
|
212
|
+
const outcome = {
|
|
213
|
+
agentId,
|
|
214
|
+
action: 'eliminated',
|
|
215
|
+
details: {
|
|
216
|
+
name: citizen.definition.name,
|
|
217
|
+
formerRank: citizen.definition.role.title,
|
|
218
|
+
},
|
|
219
|
+
};
|
|
220
|
+
const narrative = `${citizen.definition.name}被打入冷宫,昔日荣华尽失。`;
|
|
221
|
+
await this.events.emitSimple('agent.suspended', [agentId], narrative, outcome.details);
|
|
222
|
+
const result = {
|
|
223
|
+
type: 'elimination',
|
|
224
|
+
timestamp: new Date().toISOString(),
|
|
225
|
+
participants: [agentId],
|
|
226
|
+
outcomes: [outcome],
|
|
227
|
+
narrative,
|
|
228
|
+
};
|
|
229
|
+
this.ceremonyHistory.push(result);
|
|
230
|
+
return result;
|
|
231
|
+
}
|
|
232
|
+
/** Get ceremony history */
|
|
233
|
+
getHistory() {
|
|
234
|
+
return [...this.ceremonyHistory];
|
|
235
|
+
}
|
|
236
|
+
/** Extract a numeric rank level from an agent definition */
|
|
237
|
+
extractRankLevel(definition) {
|
|
238
|
+
// Derive level from rank value (rank / 10), or look up by title
|
|
239
|
+
if (definition.rank !== undefined) {
|
|
240
|
+
const level = Math.round(definition.rank / 10);
|
|
241
|
+
if (level >= 1 && level <= 8)
|
|
242
|
+
return level;
|
|
243
|
+
}
|
|
244
|
+
// Fallback: match by title
|
|
245
|
+
const match = getRankByTitle(definition.role.title);
|
|
246
|
+
return match?.level ?? 1;
|
|
247
|
+
}
|
|
248
|
+
generateCourtNarrative(outcomes) {
|
|
249
|
+
const promotions = outcomes.filter(o => o.action === 'promotion_eligible');
|
|
250
|
+
const demotions = outcomes.filter(o => o.action === 'demotion_recommended');
|
|
251
|
+
const parts = ['朝会已毕。'];
|
|
252
|
+
if (promotions.length > 0) {
|
|
253
|
+
parts.push(`${promotions.length}人表现优异,可堪晋升。`);
|
|
254
|
+
}
|
|
255
|
+
if (demotions.length > 0) {
|
|
256
|
+
parts.push(`${demotions.length}人表现不佳,建议贬谪。`);
|
|
257
|
+
}
|
|
258
|
+
if (promotions.length === 0 && demotions.length === 0) {
|
|
259
|
+
parts.push('众妃嫔表现平稳,无需调整品级。');
|
|
260
|
+
}
|
|
261
|
+
return parts.join('');
|
|
262
|
+
}
|
|
263
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cold Palace (冷宫) - Elimination Zone
|
|
3
|
+
*
|
|
4
|
+
* Manages agents who have been banished from the palace.
|
|
5
|
+
* Some may be rehabilitated, others permanently eliminated.
|
|
6
|
+
*/
|
|
7
|
+
import type { AgentRegistry, EventBus } from '@agents-uni/core';
|
|
8
|
+
export interface ColdPalaceInmate {
|
|
9
|
+
agentId: string;
|
|
10
|
+
name: string;
|
|
11
|
+
reason: string;
|
|
12
|
+
banishedAt: string;
|
|
13
|
+
/** Duration in milliseconds. Undefined means indefinite. */
|
|
14
|
+
duration?: number;
|
|
15
|
+
/** When the sentence expires */
|
|
16
|
+
expiresAt?: string;
|
|
17
|
+
status: 'serving' | 'rehabilitated' | 'eliminated';
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The Cold Palace - where disgraced consorts are banished.
|
|
21
|
+
*/
|
|
22
|
+
export declare class ColdPalace {
|
|
23
|
+
private inmates;
|
|
24
|
+
private registry;
|
|
25
|
+
private events;
|
|
26
|
+
constructor(registry: AgentRegistry, events: EventBus);
|
|
27
|
+
/** Banish an agent to the cold palace */
|
|
28
|
+
banish(agentId: string, reason: string, durationMs?: number): Promise<boolean>;
|
|
29
|
+
/** Rehabilitate an agent from the cold palace */
|
|
30
|
+
rehabilitate(agentId: string): Promise<boolean>;
|
|
31
|
+
/** Permanently eliminate an agent */
|
|
32
|
+
eliminate(agentId: string): Promise<boolean>;
|
|
33
|
+
/** Get all current inmates (those still serving) */
|
|
34
|
+
getInmates(): ColdPalaceInmate[];
|
|
35
|
+
/** Get all records (including rehabilitated and eliminated) */
|
|
36
|
+
getAllRecords(): ColdPalaceInmate[];
|
|
37
|
+
/** Check if any inmates have served their time and can be paroled */
|
|
38
|
+
checkParole(): ColdPalaceInmate[];
|
|
39
|
+
/** Check if an agent is currently in the cold palace */
|
|
40
|
+
isInColdPalace(agentId: string): boolean;
|
|
41
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cold Palace (冷宫) - Elimination Zone
|
|
3
|
+
*
|
|
4
|
+
* Manages agents who have been banished from the palace.
|
|
5
|
+
* Some may be rehabilitated, others permanently eliminated.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* The Cold Palace - where disgraced consorts are banished.
|
|
9
|
+
*/
|
|
10
|
+
export class ColdPalace {
|
|
11
|
+
inmates;
|
|
12
|
+
registry;
|
|
13
|
+
events;
|
|
14
|
+
constructor(registry, events) {
|
|
15
|
+
this.inmates = new Map();
|
|
16
|
+
this.registry = registry;
|
|
17
|
+
this.events = events;
|
|
18
|
+
}
|
|
19
|
+
/** Banish an agent to the cold palace */
|
|
20
|
+
async banish(agentId, reason, durationMs) {
|
|
21
|
+
const citizen = this.registry.get(agentId);
|
|
22
|
+
if (!citizen)
|
|
23
|
+
return false;
|
|
24
|
+
if (citizen.status === 'eliminated')
|
|
25
|
+
return false;
|
|
26
|
+
if (this.inmates.has(agentId) && this.inmates.get(agentId).status === 'serving') {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
const now = new Date();
|
|
30
|
+
const inmate = {
|
|
31
|
+
agentId,
|
|
32
|
+
name: citizen.definition.name,
|
|
33
|
+
reason,
|
|
34
|
+
banishedAt: now.toISOString(),
|
|
35
|
+
duration: durationMs,
|
|
36
|
+
expiresAt: durationMs
|
|
37
|
+
? new Date(now.getTime() + durationMs).toISOString()
|
|
38
|
+
: undefined,
|
|
39
|
+
status: 'serving',
|
|
40
|
+
};
|
|
41
|
+
this.inmates.set(agentId, inmate);
|
|
42
|
+
this.registry.setStatus(agentId, 'suspended');
|
|
43
|
+
await this.events.emitSimple('agent.suspended', [agentId], `${citizen.definition.name}被打入冷宫:${reason}`, { reason, duration: durationMs });
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
/** Rehabilitate an agent from the cold palace */
|
|
47
|
+
async rehabilitate(agentId) {
|
|
48
|
+
const inmate = this.inmates.get(agentId);
|
|
49
|
+
if (!inmate || inmate.status !== 'serving')
|
|
50
|
+
return false;
|
|
51
|
+
inmate.status = 'rehabilitated';
|
|
52
|
+
this.registry.setStatus(agentId, 'idle');
|
|
53
|
+
await this.events.emitSimple('agent.reinstated', [agentId], `${inmate.name}重获恩宠,从冷宫复出`, { agentId });
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
/** Permanently eliminate an agent */
|
|
57
|
+
async eliminate(agentId) {
|
|
58
|
+
const inmate = this.inmates.get(agentId);
|
|
59
|
+
if (!inmate) {
|
|
60
|
+
// Agent might not be in cold palace yet; banish first
|
|
61
|
+
const citizen = this.registry.get(agentId);
|
|
62
|
+
if (!citizen)
|
|
63
|
+
return false;
|
|
64
|
+
this.inmates.set(agentId, {
|
|
65
|
+
agentId,
|
|
66
|
+
name: citizen.definition.name,
|
|
67
|
+
reason: '永久除名',
|
|
68
|
+
banishedAt: new Date().toISOString(),
|
|
69
|
+
status: 'eliminated',
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
inmate.status = 'eliminated';
|
|
74
|
+
}
|
|
75
|
+
this.registry.setStatus(agentId, 'eliminated');
|
|
76
|
+
const name = inmate?.name ?? agentId;
|
|
77
|
+
await this.events.emitSimple('agent.eliminated', [agentId], `${name}被永久除名,再无翻身之日`, { agentId });
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
/** Get all current inmates (those still serving) */
|
|
81
|
+
getInmates() {
|
|
82
|
+
return [...this.inmates.values()].filter(i => i.status === 'serving');
|
|
83
|
+
}
|
|
84
|
+
/** Get all records (including rehabilitated and eliminated) */
|
|
85
|
+
getAllRecords() {
|
|
86
|
+
return [...this.inmates.values()];
|
|
87
|
+
}
|
|
88
|
+
/** Check if any inmates have served their time and can be paroled */
|
|
89
|
+
checkParole() {
|
|
90
|
+
const now = new Date().toISOString();
|
|
91
|
+
const eligible = [];
|
|
92
|
+
for (const inmate of this.inmates.values()) {
|
|
93
|
+
if (inmate.status === 'serving' &&
|
|
94
|
+
inmate.expiresAt &&
|
|
95
|
+
inmate.expiresAt <= now) {
|
|
96
|
+
eligible.push(inmate);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return eligible;
|
|
100
|
+
}
|
|
101
|
+
/** Check if an agent is currently in the cold palace */
|
|
102
|
+
isInColdPalace(agentId) {
|
|
103
|
+
const inmate = this.inmates.get(agentId);
|
|
104
|
+
return inmate !== undefined && inmate.status === 'serving';
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Palace Dynamics - 后宫势力与关系
|
|
3
|
+
*
|
|
4
|
+
* Manages alliances, betrayals, factions, and influence calculations
|
|
5
|
+
* within the palace hierarchy.
|
|
6
|
+
*/
|
|
7
|
+
import type { RelationshipGraph } from '@agents-uni/core';
|
|
8
|
+
import type { AgentRegistry } from '@agents-uni/core';
|
|
9
|
+
import type { ResourcePool } from '@agents-uni/core';
|
|
10
|
+
export interface AllianceRecord {
|
|
11
|
+
agent1: string;
|
|
12
|
+
agent2: string;
|
|
13
|
+
reason: string;
|
|
14
|
+
formedAt: string;
|
|
15
|
+
}
|
|
16
|
+
export interface BetrayalRecord {
|
|
17
|
+
betrayer: string;
|
|
18
|
+
betrayed: string;
|
|
19
|
+
reason: string;
|
|
20
|
+
occurredAt: string;
|
|
21
|
+
}
|
|
22
|
+
export interface Faction {
|
|
23
|
+
id: string;
|
|
24
|
+
members: string[];
|
|
25
|
+
leader: string;
|
|
26
|
+
influence: number;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Manages the complex political dynamics of the palace.
|
|
30
|
+
*/
|
|
31
|
+
export declare class PalaceDynamics {
|
|
32
|
+
private graph;
|
|
33
|
+
private registry;
|
|
34
|
+
private resources;
|
|
35
|
+
private allianceHistory;
|
|
36
|
+
private betrayalHistory;
|
|
37
|
+
constructor(graph: RelationshipGraph, registry: AgentRegistry, resources: ResourcePool);
|
|
38
|
+
/** Form an alliance between two agents */
|
|
39
|
+
formAlliance(agent1: string, agent2: string, reason: string): boolean;
|
|
40
|
+
/** Betray an alliance, creating a rivalry */
|
|
41
|
+
betrayAlliance(betrayer: string, betrayed: string, reason: string): boolean;
|
|
42
|
+
/** Calculate an agent's influence based on rank, allies, and favor */
|
|
43
|
+
calculateInfluence(agentId: string): number;
|
|
44
|
+
/** Get all factions (groups of allied agents) */
|
|
45
|
+
getFactions(): Faction[];
|
|
46
|
+
/** Check if a challenger can challenge a target (adjacent ranks only) */
|
|
47
|
+
canChallenge(challengerId: string, targetId: string): boolean;
|
|
48
|
+
/** Get alliance history */
|
|
49
|
+
getAllianceHistory(): AllianceRecord[];
|
|
50
|
+
/** Get betrayal history */
|
|
51
|
+
getBetrayalHistory(): BetrayalRecord[];
|
|
52
|
+
}
|