@ai-rpg-engine/starter-weird-west 2.0.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/README.md ADDED
@@ -0,0 +1,52 @@
1
+ # @ai-rpg-engine/starter-weird-west
2
+
3
+ **Dust Devil's Bargain** — A frontier town hides a cult summoning something from the red mesa.
4
+
5
+ Part of the [AI RPG Engine](https://github.com/mcp-tool-shop-org/ai-rpg-engine) starter pack catalog.
6
+
7
+ ## Theme
8
+
9
+ Western + supernatural. Gunslingers, dust spirits, and a mesa cult. The Dust resource accumulates over time — when it hits 100, the drifter is claimed by the desert.
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import { createGame } from '@ai-rpg-engine/starter-weird-west';
15
+
16
+ const engine = createGame();
17
+ engine.start();
18
+ ```
19
+
20
+ ## Content
21
+
22
+ - **5 zones:** Drifter's Crossroads, Saloon, Sheriff's Office, Red Mesa Trail, Spirit Hollow
23
+ - **2 NPCs:** Bartender Silas, Sheriff Hale
24
+ - **2 enemies:** Dust Revenant, Mesa Crawler
25
+ - **1 dialogue tree:** Bartender intel on the mesa cult
26
+ - **1 progression tree:** Gunslinger path (Quick Hand → Iron Will → Dead Eye)
27
+ - **1 item:** Sage Bundle (reduces Dust by 20)
28
+
29
+ ## Unique Mechanics
30
+
31
+ | Verb | Description |
32
+ |------|-------------|
33
+ | `draw` | Quick-draw duel — reflex contest |
34
+ | `commune` | Speak with spirits using lore |
35
+
36
+ ## Stats & Resources
37
+
38
+ | Stat | Role |
39
+ |------|------|
40
+ | grit | Toughness and willpower |
41
+ | draw-speed | Reflexes and reaction time |
42
+ | lore | Supernatural knowledge |
43
+
44
+ | Resource | Range | Notes |
45
+ |----------|-------|-------|
46
+ | HP | 0–30 | Standard health |
47
+ | Resolve | 0–20 | Mental fortitude, regens 1/tick |
48
+ | Dust | 0–100 | **Inverse pressure** — accumulates, 100 = death |
49
+
50
+ ## License
51
+
52
+ MIT
@@ -0,0 +1,20 @@
1
+ import type { EntityState, ZoneState, GameManifest, ActionIntent, WorldState, ResolvedEvent } from '@ai-rpg-engine/core';
2
+ import type { DialogueDefinition, ProgressionTreeDefinition } from '@ai-rpg-engine/content-schema';
3
+ import type { DistrictDefinition } from '@ai-rpg-engine/modules';
4
+ import type { PackMetadata } from '@ai-rpg-engine/pack-registry';
5
+ export declare const manifest: GameManifest;
6
+ export declare const player: EntityState;
7
+ export declare const bartender: EntityState;
8
+ export declare const sheriff: EntityState;
9
+ export declare const revenant: EntityState;
10
+ export declare const crawler: EntityState;
11
+ export declare const zones: ZoneState[];
12
+ export declare const bartenderDialogue: DialogueDefinition;
13
+ export declare const districts: DistrictDefinition[];
14
+ export declare const gunslingerTree: ProgressionTreeDefinition;
15
+ export declare const sageBundleEffect: {
16
+ itemId: string;
17
+ use: (action: ActionIntent, world: WorldState) => ResolvedEvent[];
18
+ };
19
+ export declare const packMeta: PackMetadata;
20
+ //# sourceMappingURL=content.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../src/content.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzH,OAAO,KAAK,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AACnG,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAIjE,eAAO,MAAM,QAAQ,EAAE,YActB,CAAC;AAIF,eAAO,MAAM,MAAM,EAAE,WAWpB,CAAC;AAIF,eAAO,MAAM,SAAS,EAAE,WAUvB,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,WAUrB,CAAC;AAIF,eAAO,MAAM,QAAQ,EAAE,WAiBtB,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,WAiBrB,CAAC;AAIF,eAAO,MAAM,KAAK,EAAE,SAAS,EAoD5B,CAAC;AAIF,eAAO,MAAM,iBAAiB,EAAE,kBA0D/B,CAAC;AAIF,eAAO,MAAM,SAAS,EAAE,kBAAkB,EAezC,CAAC;AAIF,eAAO,MAAM,cAAc,EAAE,yBAiC5B,CAAC;AAIF,eAAO,MAAM,gBAAgB;;kBAEb,YAAY,SAAS,UAAU,KAAG,aAAa,EAAE;CAqBhE,CAAC;AAIF,eAAO,MAAM,QAAQ,EAAE,YAYtB,CAAC"}
@@ -0,0 +1,296 @@
1
+ // Dust Devil's Bargain — content definitions
2
+ import { nextId } from '@ai-rpg-engine/core';
3
+ // --- Manifest ---
4
+ export const manifest = {
5
+ id: 'dust-devils-bargain',
6
+ title: "Dust Devil's Bargain",
7
+ version: '0.1.0',
8
+ engineVersion: '0.1.0',
9
+ ruleset: 'weird-west-minimal',
10
+ modules: [
11
+ 'traversal-core',
12
+ 'status-core',
13
+ 'combat-core',
14
+ 'inventory-core',
15
+ 'dialogue-core',
16
+ ],
17
+ contentPacks: ['dust-devils-bargain'],
18
+ };
19
+ // --- Player ---
20
+ export const player = {
21
+ id: 'drifter',
22
+ blueprintId: 'drifter',
23
+ type: 'player',
24
+ name: 'The Drifter',
25
+ tags: ['player', 'human', 'drifter', 'gunslinger'],
26
+ stats: { grit: 5, 'draw-speed': 6, lore: 4 },
27
+ resources: { hp: 18, resolve: 15, dust: 0 },
28
+ statuses: [],
29
+ inventory: [],
30
+ zoneId: 'crossroads',
31
+ };
32
+ // --- NPCs ---
33
+ export const bartender = {
34
+ id: 'bartender_silas',
35
+ blueprintId: 'bartender',
36
+ type: 'npc',
37
+ name: 'Silas',
38
+ tags: ['npc', 'townsfolk', 'informant', 'male'],
39
+ stats: { grit: 3, 'draw-speed': 2, lore: 5 },
40
+ resources: { hp: 10, resolve: 12, dust: 0 },
41
+ statuses: [],
42
+ zoneId: 'saloon',
43
+ };
44
+ export const sheriff = {
45
+ id: 'sheriff_hale',
46
+ blueprintId: 'sheriff',
47
+ type: 'npc',
48
+ name: 'Sheriff Hale',
49
+ tags: ['npc', 'law', 'secretive', 'male'],
50
+ stats: { grit: 6, 'draw-speed': 5, lore: 3 },
51
+ resources: { hp: 16, resolve: 14, dust: 0 },
52
+ statuses: [],
53
+ zoneId: 'sheriffs-office',
54
+ };
55
+ // --- Enemies ---
56
+ export const revenant = {
57
+ id: 'dust_revenant',
58
+ blueprintId: 'revenant',
59
+ type: 'enemy',
60
+ name: 'Dust Revenant',
61
+ tags: ['enemy', 'undead', 'cursed', 'gunslinger'],
62
+ stats: { grit: 6, 'draw-speed': 7, lore: 1 },
63
+ resources: { hp: 14, resolve: 20, dust: 0 },
64
+ statuses: [],
65
+ zoneId: 'red-mesa-trail',
66
+ ai: {
67
+ profileId: 'aggressive',
68
+ goals: ['guard-mesa', 'duel-intruders'],
69
+ fears: ['sacred-symbols'],
70
+ alertLevel: 0,
71
+ knowledge: {},
72
+ },
73
+ };
74
+ export const crawler = {
75
+ id: 'mesa_crawler',
76
+ blueprintId: 'crawler',
77
+ type: 'enemy',
78
+ name: 'Mesa Crawler',
79
+ tags: ['enemy', 'spirit', 'beast', 'supernatural'],
80
+ stats: { grit: 4, 'draw-speed': 3, lore: 8 },
81
+ resources: { hp: 10, resolve: 25, dust: 0 },
82
+ statuses: [],
83
+ zoneId: 'spirit-hollow',
84
+ ai: {
85
+ profileId: 'territorial',
86
+ goals: ['guard-hollow', 'consume-resolve'],
87
+ fears: [],
88
+ alertLevel: 0,
89
+ knowledge: {},
90
+ },
91
+ };
92
+ // --- Zones ---
93
+ export const zones = [
94
+ {
95
+ id: 'crossroads',
96
+ roomId: 'town',
97
+ name: "Drifter's Crossroads",
98
+ tags: ['outdoor', 'neutral', 'dusty'],
99
+ neighbors: ['saloon', 'sheriffs-office', 'red-mesa-trail'],
100
+ light: 5,
101
+ interactables: ['signpost', 'hitching-post', 'wanted-poster'],
102
+ },
103
+ {
104
+ id: 'saloon',
105
+ roomId: 'town',
106
+ name: 'The Dusty Spur Saloon',
107
+ tags: ['indoor', 'social', 'safe'],
108
+ neighbors: ['crossroads'],
109
+ light: 3,
110
+ interactables: ['bar', 'piano', 'notice-board'],
111
+ },
112
+ {
113
+ id: 'sheriffs-office',
114
+ roomId: 'town',
115
+ name: "Sheriff's Office",
116
+ tags: ['indoor', 'law', 'safe'],
117
+ neighbors: ['crossroads'],
118
+ light: 4,
119
+ interactables: ['desk', 'gun-rack', 'cell-door', 'lockbox'],
120
+ },
121
+ {
122
+ id: 'red-mesa-trail',
123
+ roomId: 'badlands',
124
+ name: 'Red Mesa Trail',
125
+ tags: ['outdoor', 'hostile', 'cursed'],
126
+ neighbors: ['crossroads', 'spirit-hollow'],
127
+ light: 6,
128
+ noise: 2,
129
+ stability: 3,
130
+ hazards: ['dust-storm', 'cursed-ground'],
131
+ interactables: ['petroglyphs', 'bone-cairn'],
132
+ },
133
+ {
134
+ id: 'spirit-hollow',
135
+ roomId: 'badlands',
136
+ name: 'Spirit Hollow',
137
+ tags: ['outdoor', 'supernatural', 'sacred'],
138
+ neighbors: ['red-mesa-trail'],
139
+ light: 1,
140
+ noise: 1,
141
+ stability: 2,
142
+ hazards: ['spirit-drain'],
143
+ interactables: ['ley-line-crack', 'ancient-altar', 'whispering-stones'],
144
+ },
145
+ ];
146
+ // --- Dialogue ---
147
+ export const bartenderDialogue = {
148
+ id: 'bartender-intel',
149
+ speakers: ['Silas'],
150
+ entryNodeId: 'greeting',
151
+ nodes: {
152
+ greeting: {
153
+ id: 'greeting',
154
+ speaker: 'Silas',
155
+ text: "Stranger. You've got the look of someone who doesn't plan on staying long. Smart. This town's got a sickness, and it ain't the kind a doctor fixes.",
156
+ choices: [
157
+ {
158
+ id: 'ask-mesa',
159
+ text: "What's out at Red Mesa?",
160
+ nextNodeId: 'mesa-info',
161
+ },
162
+ {
163
+ id: 'ask-sheriff',
164
+ text: 'What can you tell me about the sheriff?',
165
+ nextNodeId: 'sheriff-info',
166
+ },
167
+ ],
168
+ },
169
+ 'mesa-info': {
170
+ id: 'mesa-info',
171
+ speaker: 'Silas',
172
+ text: "Cult moved in three months back. Call themselves the Red Congregation. They do things out there at night — chanting, fires. Folks who go looking don't come back right. Some don't come back at all.",
173
+ choices: [
174
+ {
175
+ id: 'volunteer-mesa',
176
+ text: "I'll check it out. What should I watch for?",
177
+ nextNodeId: 'mesa-warning',
178
+ },
179
+ { id: 'leave-mesa', text: "Not my problem.", nextNodeId: 'end' },
180
+ ],
181
+ },
182
+ 'sheriff-info': {
183
+ id: 'sheriff-info',
184
+ speaker: 'Silas',
185
+ text: "Hale's been sheriff longer than anyone can remember. Good man, or was. Lately he locks himself in that office. Won't talk about the mesa. Won't talk about the disappearances. Something's eating at him.",
186
+ choices: [
187
+ { id: 'to-mesa', text: 'And the mesa?', nextNodeId: 'mesa-info' },
188
+ { id: 'leave-sheriff', text: "I'll keep that in mind.", nextNodeId: 'end' },
189
+ ],
190
+ },
191
+ 'mesa-warning': {
192
+ id: 'mesa-warning',
193
+ speaker: 'Silas',
194
+ text: "The dust out there — it gets inside you. Not your lungs. Your head. Sage helps. Burns it out, slows it down. Take this bundle. And if you see a dead man walking with a gun on his hip... shoot first.",
195
+ effects: [
196
+ { type: 'set-global', target: 'actor', params: { key: 'mesa-mission', value: true } },
197
+ ],
198
+ },
199
+ end: {
200
+ id: 'end',
201
+ speaker: 'Silas',
202
+ text: "Suit yourself, stranger. Whiskey's two bits if you're staying.",
203
+ },
204
+ },
205
+ };
206
+ // --- Districts ---
207
+ export const districts = [
208
+ {
209
+ id: 'town',
210
+ name: 'Perdition',
211
+ zoneIds: ['crossroads', 'saloon', 'sheriffs-office'],
212
+ tags: ['civilized', 'frontier'],
213
+ controllingFaction: 'townsfolk',
214
+ },
215
+ {
216
+ id: 'badlands',
217
+ name: 'The Badlands',
218
+ zoneIds: ['red-mesa-trail', 'spirit-hollow'],
219
+ tags: ['cursed', 'supernatural', 'hostile'],
220
+ controllingFaction: 'red-congregation',
221
+ },
222
+ ];
223
+ // --- Progression ---
224
+ export const gunslingerTree = {
225
+ id: 'gunslinger',
226
+ name: 'Gunslinger',
227
+ currency: 'xp',
228
+ nodes: [
229
+ {
230
+ id: 'quick-hand',
231
+ name: 'Quick Hand',
232
+ cost: 10,
233
+ effects: [
234
+ { type: 'stat-boost', params: { stat: 'draw-speed', amount: 1 } },
235
+ ],
236
+ },
237
+ {
238
+ id: 'iron-will',
239
+ name: 'Iron Will',
240
+ cost: 12,
241
+ effects: [
242
+ { type: 'stat-boost', params: { stat: 'grit', amount: 1 } },
243
+ { type: 'resource-boost', params: { resource: 'resolve', amount: 3 } },
244
+ ],
245
+ },
246
+ {
247
+ id: 'dead-eye',
248
+ name: 'Dead Eye',
249
+ cost: 25,
250
+ requires: ['quick-hand', 'iron-will'],
251
+ effects: [
252
+ { type: 'stat-boost', params: { stat: 'draw-speed', amount: 2 } },
253
+ { type: 'grant-tag', params: { tag: 'dead-eye' } },
254
+ ],
255
+ },
256
+ ],
257
+ };
258
+ // --- Item Effect ---
259
+ export const sageBundleEffect = {
260
+ itemId: 'sage-bundle',
261
+ use: (action, world) => {
262
+ const actor = world.entities[action.actorId];
263
+ if (!actor)
264
+ return [];
265
+ const previous = actor.resources.dust ?? 0;
266
+ actor.resources.dust = Math.max(0, previous - 20);
267
+ return [{
268
+ id: nextId('evt'),
269
+ tick: action.issuedAtTick,
270
+ type: 'resource.changed',
271
+ actorId: action.actorId,
272
+ payload: {
273
+ entityId: actor.id,
274
+ resource: 'dust',
275
+ previous,
276
+ current: actor.resources.dust,
277
+ delta: actor.resources.dust - previous,
278
+ },
279
+ }];
280
+ },
281
+ };
282
+ // --- Pack Metadata ---
283
+ export const packMeta = {
284
+ id: 'dust-devils-bargain',
285
+ name: "Dust Devil's Bargain",
286
+ tagline: 'A haunted frontier town where the dead still draw.',
287
+ genres: ['western'],
288
+ difficulty: 'intermediate',
289
+ tones: ['eerie', 'gritty'],
290
+ tags: ['supernatural', 'frontier', 'duel', 'spirits', 'cult'],
291
+ engineVersion: '2.0.0',
292
+ version: '2.0.0',
293
+ description: 'Drift into a cursed frontier town. Investigate a mesa cult, duel undead gunslingers, and commune with spirits before the dust takes you.',
294
+ narratorTone: 'weird western, laconic, sun-bleached, haunted',
295
+ };
296
+ //# sourceMappingURL=content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content.js","sourceRoot":"","sources":["../src/content.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { createGame } from './setup.js';
2
+ export { manifest, gunslingerTree, packMeta } from './content.js';
3
+ export { weirdWestMinimalRuleset } from './ruleset.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ // @ai-rpg-engine/starter-weird-west — Dust Devil's Bargain
2
+ export { createGame } from './setup.js';
3
+ export { manifest, gunslingerTree, packMeta } from './content.js';
4
+ export { weirdWestMinimalRuleset } from './ruleset.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAE3D,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { RulesetDefinition } from '@ai-rpg-engine/core';
2
+ export declare const weirdWestMinimalRuleset: RulesetDefinition;
3
+ //# sourceMappingURL=ruleset.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ruleset.d.ts","sourceRoot":"","sources":["../src/ruleset.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,eAAO,MAAM,uBAAuB,EAAE,iBAmErC,CAAC"}
@@ -0,0 +1,63 @@
1
+ // Dust Devil's Bargain — ruleset definition
2
+ export const weirdWestMinimalRuleset = {
3
+ id: 'weird-west-minimal',
4
+ name: 'Weird West Minimal',
5
+ version: '0.1.0',
6
+ stats: [
7
+ { id: 'grit', name: 'Grit', min: 1, max: 20, default: 5 },
8
+ { id: 'draw-speed', name: 'Draw Speed', min: 1, max: 20, default: 5 },
9
+ { id: 'lore', name: 'Lore', min: 1, max: 20, default: 4 },
10
+ ],
11
+ resources: [
12
+ { id: 'hp', name: 'HP', min: 0, max: 30, default: 18 },
13
+ { id: 'resolve', name: 'Resolve', min: 0, max: 20, default: 15, regenRate: 1 },
14
+ { id: 'dust', name: 'Dust', min: 0, max: 100, default: 0 },
15
+ ],
16
+ verbs: [
17
+ { id: 'move', name: 'Move', description: 'Move to an adjacent area' },
18
+ { id: 'inspect', name: 'Survey', description: 'Survey an area for clues or threats' },
19
+ { id: 'attack', name: 'Shoot', tags: ['combat'], description: 'Firearms or melee combat' },
20
+ { id: 'use', name: 'Use', description: 'Use an item from inventory' },
21
+ { id: 'speak', name: 'Speak', tags: ['dialogue'], description: 'Talk to another character' },
22
+ { id: 'choose', name: 'Choose', tags: ['dialogue'], description: 'Select a dialogue option' },
23
+ { id: 'draw', name: 'Draw', tags: ['combat', 'duel'], description: 'Quick-draw duel — reflexes determine who fires first' },
24
+ { id: 'commune', name: 'Commune', tags: ['supernatural'], description: 'Speak with spirits or read ley lines' },
25
+ ],
26
+ formulas: [
27
+ {
28
+ id: 'hit-chance',
29
+ name: 'Hit Chance',
30
+ description: 'Attacker draw-speed vs target draw-speed',
31
+ inputs: ['attacker.draw-speed', 'target.draw-speed'],
32
+ output: 'number (0-100)',
33
+ },
34
+ {
35
+ id: 'damage',
36
+ name: 'Damage',
37
+ description: 'Base: attacker grit, minimum 1',
38
+ inputs: ['attacker.grit'],
39
+ output: 'number',
40
+ },
41
+ {
42
+ id: 'commune-success',
43
+ name: 'Commune Success',
44
+ description: 'Lore vs spirit difficulty',
45
+ inputs: ['actor.lore', 'difficulty'],
46
+ output: 'number (0-100)',
47
+ },
48
+ ],
49
+ defaultModules: [
50
+ 'traversal-core',
51
+ 'status-core',
52
+ 'combat-core',
53
+ 'inventory-core',
54
+ 'dialogue-core',
55
+ ],
56
+ progressionModels: [],
57
+ contentConventions: {
58
+ entityTypes: ['player', 'npc', 'drifter', 'enemy', 'spirit'],
59
+ statusTags: ['buff', 'debuff', 'cursed', 'blessed', 'dust-sick'],
60
+ combatTags: ['firearm', 'melee', 'supernatural'],
61
+ },
62
+ };
63
+ //# sourceMappingURL=ruleset.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ruleset.js","sourceRoot":"","sources":["../src/ruleset.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ruleset.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ruleset.test.d.ts","sourceRoot":"","sources":["../src/ruleset.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,44 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { validateRulesetDefinition } from '@ai-rpg-engine/content-schema';
3
+ import { weirdWestMinimalRuleset } from './ruleset.js';
4
+ describe('weirdWestMinimalRuleset', () => {
5
+ it('validates against RulesetDefinition schema', () => {
6
+ const r = validateRulesetDefinition(weirdWestMinimalRuleset);
7
+ expect(r.ok).toBe(true);
8
+ expect(r.errors).toHaveLength(0);
9
+ });
10
+ it('declares expected stats', () => {
11
+ const statIds = weirdWestMinimalRuleset.stats.map((s) => s.id);
12
+ expect(statIds).toContain('grit');
13
+ expect(statIds).toContain('draw-speed');
14
+ expect(statIds).toContain('lore');
15
+ });
16
+ it('declares expected resources', () => {
17
+ const resIds = weirdWestMinimalRuleset.resources.map((r) => r.id);
18
+ expect(resIds).toContain('hp');
19
+ expect(resIds).toContain('resolve');
20
+ expect(resIds).toContain('dust');
21
+ });
22
+ it('declares all verbs used by starter modules', () => {
23
+ const verbIds = weirdWestMinimalRuleset.verbs.map((v) => v.id);
24
+ expect(verbIds).toContain('move');
25
+ expect(verbIds).toContain('attack');
26
+ expect(verbIds).toContain('inspect');
27
+ expect(verbIds).toContain('speak');
28
+ expect(verbIds).toContain('choose');
29
+ expect(verbIds).toContain('use');
30
+ expect(verbIds).toContain('draw');
31
+ expect(verbIds).toContain('commune');
32
+ });
33
+ it('lists all default modules', () => {
34
+ expect(weirdWestMinimalRuleset.defaultModules).toContain('traversal-core');
35
+ expect(weirdWestMinimalRuleset.defaultModules).toContain('combat-core');
36
+ });
37
+ it('declares combat and commune formulas', () => {
38
+ const formulaIds = weirdWestMinimalRuleset.formulas.map((f) => f.id);
39
+ expect(formulaIds).toContain('hit-chance');
40
+ expect(formulaIds).toContain('damage');
41
+ expect(formulaIds).toContain('commune-success');
42
+ });
43
+ });
44
+ //# sourceMappingURL=ruleset.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ruleset.test.js","sourceRoot":"","sources":["../src/ruleset.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Engine } from '@ai-rpg-engine/core';
2
+ export declare function createGame(seed?: number): Engine;
3
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAoD7C,wBAAgB,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAuHhD"}
package/dist/setup.js ADDED
@@ -0,0 +1,135 @@
1
+ // Game setup — wire content into engine
2
+ import { Engine } from '@ai-rpg-engine/core';
3
+ import { traversalCore, statusCore, combatCore, createInventoryCore, createDialogueCore, createCognitionCore, createPerceptionFilter, createProgressionCore, createEnvironmentCore, createFactionCognition, createRumorPropagation, createSimulationInspector, createDistrictCore, createBeliefProvenance, createObserverPresentation, giveItem, } from '@ai-rpg-engine/modules';
4
+ import { manifest, player, bartender, sheriff, revenant, crawler, zones, districts, bartenderDialogue, sageBundleEffect, gunslingerTree, } from './content.js';
5
+ import { weirdWestMinimalRuleset } from './ruleset.js';
6
+ // Spirits perceive the living as echoes of the future
7
+ const spiritPerception = {
8
+ id: 'spirit-future-echo',
9
+ eventPatterns: ['world.zone.entered'],
10
+ priority: 5,
11
+ condition: (_event, ctx) => ctx.observer.tags.includes('spirit'),
12
+ transform: (event, _ctx) => ({
13
+ ...event,
14
+ payload: {
15
+ ...event.payload,
16
+ _subjectiveDescription: 'an echo of the future stumbles through the veil',
17
+ _actorDescription: 'a flickering presence not yet dead',
18
+ _spiritPerception: true,
19
+ },
20
+ }),
21
+ };
22
+ export function createGame(seed) {
23
+ const engine = new Engine({
24
+ manifest,
25
+ seed: seed ?? 42,
26
+ ruleset: weirdWestMinimalRuleset,
27
+ modules: [
28
+ traversalCore,
29
+ statusCore,
30
+ combatCore,
31
+ createInventoryCore([sageBundleEffect]),
32
+ createDialogueCore([bartenderDialogue]),
33
+ createCognitionCore({ decay: { baseRate: 0.02, pruneThreshold: 0.05, instabilityFactor: 0.5 } }),
34
+ createPerceptionFilter(),
35
+ createProgressionCore({
36
+ trees: [gunslingerTree],
37
+ rewards: [{
38
+ eventPattern: 'combat.entity.defeated',
39
+ currencyId: 'xp',
40
+ amount: 12,
41
+ recipient: 'actor',
42
+ }],
43
+ }),
44
+ createEnvironmentCore({
45
+ hazards: [{
46
+ id: 'dust-storm',
47
+ triggerOn: 'world.zone.entered',
48
+ condition: (zone) => zone.hazards?.includes('dust-storm') ?? false,
49
+ effect: (zone, entity, _world, tick) => {
50
+ if (entity.tags.includes('human')) {
51
+ entity.resources.dust = Math.min(100, (entity.resources.dust ?? 0) + 8);
52
+ }
53
+ return [];
54
+ },
55
+ },
56
+ {
57
+ id: 'spirit-drain',
58
+ triggerOn: 'world.zone.entered',
59
+ condition: (zone) => zone.hazards?.includes('spirit-drain') ?? false,
60
+ effect: (zone, entity, _world, tick) => {
61
+ entity.resources.resolve = Math.max(0, (entity.resources.resolve ?? 0) - 3);
62
+ return [];
63
+ },
64
+ }],
65
+ }),
66
+ createFactionCognition({
67
+ factions: [
68
+ {
69
+ factionId: 'townsfolk',
70
+ entityIds: ['bartender_silas', 'sheriff_hale'],
71
+ cohesion: 0.4,
72
+ },
73
+ {
74
+ factionId: 'red-congregation',
75
+ entityIds: ['dust_revenant'],
76
+ cohesion: 0.9,
77
+ },
78
+ ],
79
+ }),
80
+ createRumorPropagation({ propagationDelay: 2 }),
81
+ createDistrictCore({ districts }),
82
+ createBeliefProvenance(),
83
+ createObserverPresentation({
84
+ rules: [spiritPerception],
85
+ }),
86
+ createSimulationInspector(),
87
+ ],
88
+ });
89
+ // Add zones
90
+ for (const zone of zones) {
91
+ engine.store.addZone(zone);
92
+ }
93
+ // Add entities
94
+ engine.store.addEntity({ ...player });
95
+ engine.store.addEntity({ ...bartender });
96
+ engine.store.addEntity({ ...sheriff });
97
+ engine.store.addEntity({ ...revenant });
98
+ engine.store.addEntity({ ...crawler });
99
+ // Set player
100
+ engine.store.state.playerId = 'drifter';
101
+ engine.store.state.locationId = 'crossroads';
102
+ // Give sage bundle after bartender warns about mesa
103
+ engine.store.events.on('dialogue.ended', (event) => {
104
+ if (event.payload.dialogueId === 'bartender-intel') {
105
+ const world = engine.store.state;
106
+ if (world.globals['mesa-mission']) {
107
+ const playerEntity = world.entities['drifter'];
108
+ if (playerEntity && !(playerEntity.inventory ?? []).includes('sage-bundle')) {
109
+ const giveEvent = giveItem(playerEntity, 'sage-bundle', engine.tick);
110
+ engine.store.recordEvent(giveEvent);
111
+ }
112
+ }
113
+ }
114
+ });
115
+ // Audio cue on entering spirit hollow
116
+ engine.store.events.on('world.zone.entered', (event) => {
117
+ if (event.payload.zoneId === 'spirit-hollow') {
118
+ engine.store.emitEvent('audio.cue.requested', {
119
+ cueId: 'scene.spirit-hollow-reveal',
120
+ channel: 'stinger',
121
+ priority: 'high',
122
+ });
123
+ }
124
+ });
125
+ // Audio cue on combat defeat
126
+ engine.store.events.on('combat.entity.defeated', () => {
127
+ engine.store.emitEvent('audio.cue.requested', {
128
+ cueId: 'combat.victory',
129
+ channel: 'stinger',
130
+ priority: 'high',
131
+ });
132
+ });
133
+ return engine;
134
+ }
135
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAAA,wCAAwC;AAExC,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EACL,aAAa,EACb,UAAU,EACV,UAAU,EACV,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,EACtB,sBAAsB,EACtB,yBAAyB,EACzB,kBAAkB,EAClB,sBAAsB,EACtB,0BAA0B,EAC1B,QAAQ,GACT,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,QAAQ,EACR,MAAM,EACN,SAAS,EACT,OAAO,EACP,QAAQ,EACR,OAAO,EACP,KAAK,EACL,SAAS,EACT,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAEvD,sDAAsD;AACtD,MAAM,gBAAgB,GAAqB;IACzC,EAAE,EAAE,oBAAoB;IACxB,aAAa,EAAE,CAAC,oBAAoB,CAAC;IACrC,QAAQ,EAAE,CAAC;IACX,SAAS,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;IAChE,SAAS,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;QAC3B,GAAG,KAAK;QACR,OAAO,EAAE;YACP,GAAG,KAAK,CAAC,OAAO;YAChB,sBAAsB,EAAE,iDAAiD;YACzE,iBAAiB,EAAE,oCAAoC;YACvD,iBAAiB,EAAE,IAAI;SACxB;KACF,CAAC;CACH,CAAC;AAEF,MAAM,UAAU,UAAU,CAAC,IAAa;IACtC,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC;QACxB,QAAQ;QACR,IAAI,EAAE,IAAI,IAAI,EAAE;QAChB,OAAO,EAAE,uBAAuB;QAChC,OAAO,EAAE;YACP,aAAa;YACb,UAAU;YACV,UAAU;YACV,mBAAmB,CAAC,CAAC,gBAAgB,CAAC,CAAC;YACvC,kBAAkB,CAAC,CAAC,iBAAiB,CAAC,CAAC;YACvC,mBAAmB,CAAC,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,iBAAiB,EAAE,GAAG,EAAE,EAAE,CAAC;YAChG,sBAAsB,EAAE;YACxB,qBAAqB,CAAC;gBACpB,KAAK,EAAE,CAAC,cAAc,CAAC;gBACvB,OAAO,EAAE,CAAC;wBACR,YAAY,EAAE,wBAAwB;wBACtC,UAAU,EAAE,IAAI;wBAChB,MAAM,EAAE,EAAE;wBACV,SAAS,EAAE,OAAO;qBACnB,CAAC;aACH,CAAC;YACF,qBAAqB,CAAC;gBACpB,OAAO,EAAE,CAAC;wBACR,EAAE,EAAE,YAAY;wBAChB,SAAS,EAAE,oBAAoB;wBAC/B,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,YAAY,CAAC,IAAI,KAAK;wBAClE,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;4BACrC,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gCAClC,MAAM,CAAC,SAAS,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;4BAC1E,CAAC;4BACD,OAAO,EAAE,CAAC;wBACZ,CAAC;qBACF;oBACD;wBACE,EAAE,EAAE,cAAc;wBAClB,SAAS,EAAE,oBAAoB;wBAC/B,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,cAAc,CAAC,IAAI,KAAK;wBACpE,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;4BACrC,MAAM,CAAC,SAAS,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;4BAC5E,OAAO,EAAE,CAAC;wBACZ,CAAC;qBACF,CAAC;aACH,CAAC;YACF,sBAAsB,CAAC;gBACrB,QAAQ,EAAE;oBACR;wBACE,SAAS,EAAE,WAAW;wBACtB,SAAS,EAAE,CAAC,iBAAiB,EAAE,cAAc,CAAC;wBAC9C,QAAQ,EAAE,GAAG;qBACd;oBACD;wBACE,SAAS,EAAE,kBAAkB;wBAC7B,SAAS,EAAE,CAAC,eAAe,CAAC;wBAC5B,QAAQ,EAAE,GAAG;qBACd;iBACF;aACF,CAAC;YACF,sBAAsB,CAAC,EAAE,gBAAgB,EAAE,CAAC,EAAE,CAAC;YAC/C,kBAAkB,CAAC,EAAE,SAAS,EAAE,CAAC;YACjC,sBAAsB,EAAE;YACxB,0BAA0B,CAAC;gBACzB,KAAK,EAAE,CAAC,gBAAgB,CAAC;aAC1B,CAAC;YACF,yBAAyB,EAAE;SAC5B;KACF,CAAC,CAAC;IAEH,YAAY;IACZ,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,eAAe;IACf,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;IACtC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,GAAG,SAAS,EAAE,CAAC,CAAC;IACzC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IACvC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,GAAG,QAAQ,EAAE,CAAC,CAAC;IACxC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IAEvC,aAAa;IACb,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,GAAG,SAAS,CAAC;IACxC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,GAAG,YAAY,CAAC;IAE7C,oDAAoD;IACpD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,gBAAgB,EAAE,CAAC,KAAK,EAAE,EAAE;QACjD,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,KAAK,iBAAiB,EAAE,CAAC;YACnD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;YACjC,IAAI,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;gBAClC,MAAM,YAAY,GAAG,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;gBAC/C,IAAI,YAAY,IAAI,CAAC,CAAC,YAAY,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;oBAC5E,MAAM,SAAS,GAAG,QAAQ,CAAC,YAAY,EAAE,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;oBACrE,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;gBACtC,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,sCAAsC;IACtC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,KAAK,EAAE,EAAE;QACrD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,eAAe,EAAE,CAAC;YAC7C,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,qBAAqB,EAAE;gBAC5C,KAAK,EAAE,4BAA4B;gBACnC,OAAO,EAAE,SAAS;gBAClB,QAAQ,EAAE,MAAM;aACjB,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,6BAA6B;IAC7B,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QACpD,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,qBAAqB,EAAE;YAC5C,KAAK,EAAE,gBAAgB;YACvB,OAAO,EAAE,SAAS;YAClB,QAAQ,EAAE,MAAM;SACjB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@ai-rpg-engine/starter-weird-west",
3
+ "version": "2.0.0",
4
+ "description": "AI RPG Engine weird west starter: Dust Devil's Bargain",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": ["dist"],
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "test": "vitest run"
18
+ },
19
+ "dependencies": {
20
+ "@ai-rpg-engine/core": "*",
21
+ "@ai-rpg-engine/content-schema": "*",
22
+ "@ai-rpg-engine/modules": "*",
23
+ "@ai-rpg-engine/pack-registry": "*"
24
+ },
25
+ "license": "MIT",
26
+ "author": "mcp-tool-shop",
27
+ "homepage": "https://mcp-tool-shop-org.github.io/ai-rpg-engine/",
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "https://github.com/mcp-tool-shop-org/ai-rpg-engine.git",
31
+ "directory": "packages/starter-weird-west"
32
+ },
33
+ "keywords": ["rpg", "western", "weird-west", "supernatural", "starter", "worldbuilding", "content-pack"],
34
+ "bugs": {
35
+ "url": "https://github.com/mcp-tool-shop-org/ai-rpg-engine/issues"
36
+ },
37
+ "engines": {
38
+ "node": ">=20"
39
+ }
40
+ }