@datamoc/mw_games 0.5.0 → 0.5.1
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/dist/actors/EntityTemplate.d.ts +86 -0
- package/dist/actors/EntityTemplate.d.ts.map +1 -0
- package/dist/actors/EntityTemplate.js +65 -0
- package/dist/actors/EntityTemplate.js.map +1 -0
- package/dist/actors/index.d.ts +2 -0
- package/dist/actors/index.d.ts.map +1 -1
- package/dist/actors/index.js +1 -0
- package/dist/actors/index.js.map +1 -1
- package/dist/board/HexSkirmish.d.ts +213 -0
- package/dist/board/HexSkirmish.d.ts.map +1 -0
- package/dist/board/HexSkirmish.js +271 -0
- package/dist/board/HexSkirmish.js.map +1 -0
- package/dist/board/index.d.ts +2 -0
- package/dist/board/index.d.ts.map +1 -1
- package/dist/board/index.js +1 -0
- package/dist/board/index.js.map +1 -1
- package/dist/core/Csv.d.ts +64 -0
- package/dist/core/Csv.d.ts.map +1 -0
- package/dist/core/Csv.js +164 -0
- package/dist/core/Csv.js.map +1 -0
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -0
- package/dist/core/index.js.map +1 -1
- package/dist/mw_games.global.js +91 -90
- package/dist/two-d/render/Shape2D.d.ts +23 -1
- package/dist/two-d/render/Shape2D.d.ts.map +1 -1
- package/dist/two-d/render/Shape2D.js +23 -1
- package/dist/two-d/render/Shape2D.js.map +1 -1
- package/dist/two-d/render/index.d.ts +1 -1
- package/dist/two-d/render/index.d.ts.map +1 -1
- package/dist/two-d/render/index.js +1 -1
- package/dist/two-d/render/index.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { StatBlock } from './StatBlock.ts';
|
|
2
|
+
import { Progression, type GrowthCurve } from './Progression.ts';
|
|
3
|
+
import { type AffixDef } from './Affix.ts';
|
|
4
|
+
import type { InventoryItem } from './Inventory.ts';
|
|
5
|
+
import { ReactionTable } from '../core/Reactions.ts';
|
|
6
|
+
/**
|
|
7
|
+
* One row of a hero or monster "file" - a `core.parseCSV` result, typically - turned into a
|
|
8
|
+
* fully wired entity: a `StatBlock` of base stats, an optional `Progression` against a named
|
|
9
|
+
* growth curve, an optional starting item carrying a named starting affix, and a
|
|
10
|
+
* `ReactionTable` already holding a low-HP rule if the row names one. The single call a game
|
|
11
|
+
* makes once per row, in place of the per-field glue code every one of those systems would
|
|
12
|
+
* otherwise need written out by hand.
|
|
13
|
+
*
|
|
14
|
+
* A handful of column names are reserved (`id`, `growth`, `level`, `startingAffix`,
|
|
15
|
+
* `startingItem`, `lowHpReaction`); every other column in the row becomes a base stat, so a
|
|
16
|
+
* game's own stat names (`attack`, `speed`, `armor`, whatever it calls them) need no
|
|
17
|
+
* declaring here. What each named growth curve, affix, and item actually *is* stays the
|
|
18
|
+
* game's own `EntityTemplateCatalog` - `mwg` resolves the reference, never invents the
|
|
19
|
+
* content behind it, the same boundary `AffixDef.id` already draws.
|
|
20
|
+
*
|
|
21
|
+
* Deliberately narrow: one low-HP threshold per row, not an arbitrary list of reactions -
|
|
22
|
+
* add a second column and a second `ReactionRule` in a game's own code the moment a second
|
|
23
|
+
* one is actually needed, rather than a general reaction-list column format speculatively
|
|
24
|
+
* built ahead of that need.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* import { parseCSV } from '@datamoc/mw_games/core';
|
|
29
|
+
* import { buildEntities, type EntityTemplateRow } from '@datamoc/mw_games/actors';
|
|
30
|
+
*
|
|
31
|
+
* const csv = `id,attack,speed,growth,startingAffix,startingItem,lowHpReaction
|
|
32
|
+
* fireling,10,8,steep,blazing,ember_charm,0.25`;
|
|
33
|
+
*
|
|
34
|
+
* const rows = parseCSV<EntityTemplateRow>(csv, {
|
|
35
|
+
* columns: { attack: 'number', speed: 'number', lowHpReaction: 'number' },
|
|
36
|
+
* });
|
|
37
|
+
*
|
|
38
|
+
* const monsters = buildEntities(rows, {
|
|
39
|
+
* growthCurves: { steep: { maxLevel: 20, experienceFor: (level) => level * level * 10 } },
|
|
40
|
+
* affixes: { blazing: { id: 'blazing', trigger: 'strike', weight: 1 } },
|
|
41
|
+
* items: { ember_charm: () => ({ id: 'ember_charm', quantity: 1 }) },
|
|
42
|
+
* }, (entity) => console.log(`${entity.id} panics at low hp`));
|
|
43
|
+
*
|
|
44
|
+
* monsters[0].reactions.check({ hp: 2, maxHp: 10 }); // fires the callback above
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export interface EntityTemplateRow {
|
|
48
|
+
id: string;
|
|
49
|
+
growth?: string;
|
|
50
|
+
level?: number;
|
|
51
|
+
startingAffix?: string;
|
|
52
|
+
startingItem?: string;
|
|
53
|
+
lowHpReaction?: number;
|
|
54
|
+
/** any other column is a base stat by that name; must be a number */
|
|
55
|
+
[stat: string]: unknown;
|
|
56
|
+
}
|
|
57
|
+
/** what each row's named references actually mean - entirely the game's own content */
|
|
58
|
+
export interface EntityTemplateCatalog {
|
|
59
|
+
growthCurves?: Record<string, GrowthCurve>;
|
|
60
|
+
affixes?: Record<string, AffixDef>;
|
|
61
|
+
/** a factory, not a shared instance, so every built entity gets its own item object */
|
|
62
|
+
items?: Record<string, () => InventoryItem>;
|
|
63
|
+
}
|
|
64
|
+
export interface BuiltEntity {
|
|
65
|
+
id: string;
|
|
66
|
+
stats: StatBlock;
|
|
67
|
+
progression?: Progression;
|
|
68
|
+
item?: InventoryItem;
|
|
69
|
+
reactions: ReactionTable<{
|
|
70
|
+
hp: number;
|
|
71
|
+
maxHp: number;
|
|
72
|
+
}>;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* @example
|
|
76
|
+
* ```ts
|
|
77
|
+
* import { buildEntity } from '@datamoc/mw_games/actors';
|
|
78
|
+
*
|
|
79
|
+
* const goblin = buildEntity({ id: 'goblin', attack: 4, speed: 3 }, {});
|
|
80
|
+
* console.log(goblin.stats.get('attack')); // 4
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export declare function buildEntity(row: EntityTemplateRow, catalog?: EntityTemplateCatalog, onLowHp?: (entity: BuiltEntity) => void): BuiltEntity;
|
|
84
|
+
/** `buildEntity` over every row - the usual shape once a whole file's worth loads at once */
|
|
85
|
+
export declare function buildEntities(rows: readonly EntityTemplateRow[], catalog?: EntityTemplateCatalog, onLowHp?: (entity: BuiltEntity) => void): BuiltEntity[];
|
|
86
|
+
//# sourceMappingURL=EntityTemplate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EntityTemplate.d.ts","sourceRoot":"","sources":["../../src/actors/EntityTemplate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAc,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,MAAM,WAAW,iBAAiB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,qEAAqE;IACrE,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,uFAAuF;AACvF,MAAM,WAAW,qBAAqB;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAEnC,uFAAuF;IACvF,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,aAAa,CAAC,CAAC;CAC5C;AAED,MAAM,WAAW,WAAW;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,SAAS,EAAE,aAAa,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACxD;AAID;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,iBAAiB,EAAE,OAAO,GAAE,qBAA0B,EAAE,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,GAAG,WAAW,CAkC7I;AAED,6FAA6F;AAC7F,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,iBAAiB,EAAE,EAAE,OAAO,GAAE,qBAA0B,EAAE,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,GAAG,WAAW,EAAE,CAE7J"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { StatBlock } from './StatBlock.js';
|
|
2
|
+
import { Progression } from './Progression.js';
|
|
3
|
+
import { applyAffix } from './Affix.js';
|
|
4
|
+
import { ReactionTable } from '../core/Reactions.js';
|
|
5
|
+
const RESERVED_KEYS = new Set(['id', 'growth', 'level', 'startingAffix', 'startingItem', 'lowHpReaction']);
|
|
6
|
+
/**
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { buildEntity } from '@datamoc/mw_games/actors';
|
|
10
|
+
*
|
|
11
|
+
* const goblin = buildEntity({ id: 'goblin', attack: 4, speed: 3 }, {});
|
|
12
|
+
* console.log(goblin.stats.get('attack')); // 4
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export function buildEntity(row, catalog = {}, onLowHp) {
|
|
16
|
+
const stats = new StatBlock({ base: statsFrom(row) });
|
|
17
|
+
let progression;
|
|
18
|
+
if (row.growth !== undefined) {
|
|
19
|
+
const curve = catalog.growthCurves?.[row.growth];
|
|
20
|
+
if (!curve)
|
|
21
|
+
throw new Error(`entity template "${row.id}": unknown growth curve "${row.growth}"`);
|
|
22
|
+
progression = new Progression(curve, { level: row.level ?? 1 });
|
|
23
|
+
}
|
|
24
|
+
let item;
|
|
25
|
+
if (row.startingItem !== undefined) {
|
|
26
|
+
const factory = catalog.items?.[row.startingItem];
|
|
27
|
+
if (!factory)
|
|
28
|
+
throw new Error(`entity template "${row.id}": unknown starting item "${row.startingItem}"`);
|
|
29
|
+
item = factory();
|
|
30
|
+
if (row.startingAffix !== undefined) {
|
|
31
|
+
const affix = catalog.affixes?.[row.startingAffix];
|
|
32
|
+
if (!affix)
|
|
33
|
+
throw new Error(`entity template "${row.id}": unknown affix "${row.startingAffix}"`);
|
|
34
|
+
applyAffix(item, affix);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else if (row.startingAffix !== undefined) {
|
|
38
|
+
throw new Error(`entity template "${row.id}": a starting affix needs a starting item to carry it`);
|
|
39
|
+
}
|
|
40
|
+
const reactions = new ReactionTable();
|
|
41
|
+
const entity = { id: row.id, stats, progression, item, reactions };
|
|
42
|
+
if (row.lowHpReaction !== undefined) {
|
|
43
|
+
if (!onLowHp)
|
|
44
|
+
throw new Error(`entity template "${row.id}": names a lowHpReaction threshold but no onLowHp callback was given`);
|
|
45
|
+
const threshold = row.lowHpReaction;
|
|
46
|
+
reactions.add({ id: 'low-hp', when: (s) => s.hp / s.maxHp <= threshold, action: () => onLowHp(entity) });
|
|
47
|
+
}
|
|
48
|
+
return entity;
|
|
49
|
+
}
|
|
50
|
+
/** `buildEntity` over every row - the usual shape once a whole file's worth loads at once */
|
|
51
|
+
export function buildEntities(rows, catalog = {}, onLowHp) {
|
|
52
|
+
return rows.map((row) => buildEntity(row, catalog, onLowHp));
|
|
53
|
+
}
|
|
54
|
+
function statsFrom(row) {
|
|
55
|
+
const stats = {};
|
|
56
|
+
for (const [key, value] of Object.entries(row)) {
|
|
57
|
+
if (RESERVED_KEYS.has(key))
|
|
58
|
+
continue;
|
|
59
|
+
if (typeof value !== 'number')
|
|
60
|
+
throw new Error(`entity template "${row.id}": stat "${key}" must be a number, got ${typeof value}`);
|
|
61
|
+
stats[key] = value;
|
|
62
|
+
}
|
|
63
|
+
return stats;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=EntityTemplate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EntityTemplate.js","sourceRoot":"","sources":["../../src/actors/EntityTemplate.ts"],"names":[],"mappings":"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"}
|
package/dist/actors/index.d.ts
CHANGED
|
@@ -41,4 +41,6 @@ export { AuraField } from './Aura.ts';
|
|
|
41
41
|
export type { AuraDef, AuraParticipant } from './Aura.ts';
|
|
42
42
|
export { SupportLedger } from './Support.ts';
|
|
43
43
|
export type { SupportLevel, SupportChange, SupportSave } from './Support.ts';
|
|
44
|
+
export { buildEntity, buildEntities } from './EntityTemplate.ts';
|
|
45
|
+
export type { EntityTemplateRow, EntityTemplateCatalog, BuiltEntity } from './EntityTemplate.ts';
|
|
44
46
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/actors/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/actors/index.ts"],"names":[],"mappings":"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"}
|
package/dist/actors/index.js
CHANGED
|
@@ -20,4 +20,5 @@ export { Barrier } from './Barrier.js';
|
|
|
20
20
|
export { assignTraits } from './Traits.js';
|
|
21
21
|
export { AuraField } from './Aura.js';
|
|
22
22
|
export { SupportLedger } from './Support.js';
|
|
23
|
+
export { buildEntity, buildEntities } from './EntityTemplate.js';
|
|
23
24
|
//# sourceMappingURL=index.js.map
|
package/dist/actors/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/actors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE3D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEpG,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAElE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE3E,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/actors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE3D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEpG,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAElE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE3E,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A Wesnoth-style hex army-game rules layer: terrain that costs different movement points and
|
|
3
|
+
* grants a defence bonus per terrain kind, adjacent attacks that always let a surviving
|
|
4
|
+
* defender strike back, capturable villages that grant income and heal whoever stands on one,
|
|
5
|
+
* and per-side turn income built on both. Distinct from `board.Tactics` (an X-COM-style
|
|
6
|
+
* action-point/cover/overwatch layer, ranged attacks, no retaliation) - this is the other
|
|
7
|
+
* shape a hex army game needs, adjacency-only combat with a hit chance and no zone of control.
|
|
8
|
+
*
|
|
9
|
+
* `mwg` supplies the mechanism only: `SkirmishTerrain`'s move cost and defence numbers, unit
|
|
10
|
+
* attack/hit-chance/hp values, and income rates are entirely the game's own data, the same
|
|
11
|
+
* policy `board.Army`'s `armyIncome` already follows.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* import { startingSkirmish, setSkirmishTerrain, addSkirmishUnit, skirmishMoves, moveSkirmishUnit, skirmishAttack, endSkirmishTurn, skirmishIncome } from '@datamoc/mw_games/board';
|
|
16
|
+
*
|
|
17
|
+
* const terrain = { plain: { moveCost: 1, defense: 0 }, forest: { moveCost: 2, defense: 0.3 } };
|
|
18
|
+
* const state = startingSkirmish(6, 6, terrain);
|
|
19
|
+
* setSkirmishTerrain(state, 2, 2, 'forest');
|
|
20
|
+
* setSkirmishTerrain(state, 0, 0, 'plain', true); // a village at the corner
|
|
21
|
+
*
|
|
22
|
+
* addSkirmishUnit(state, { id: 'axeman', owner: 'blue', x: 0, y: 0, hp: 10, maxHp: 10, moves: 4, attack: 4, hitChance: 0.7 });
|
|
23
|
+
* addSkirmishUnit(state, { id: 'raider', owner: 'red', x: 1, y: 0, hp: 10, maxHp: 10, moves: 4, attack: 3, hitChance: 0.6 });
|
|
24
|
+
*
|
|
25
|
+
* const moves = skirmishMoves(state, 'axeman'); // reachable cells, weighted by terrain cost
|
|
26
|
+
* const exchange = skirmishAttack(state, 'axeman', 'raider'); // both strike if raider survives
|
|
27
|
+
*
|
|
28
|
+
* endSkirmishTurn(state); // hands the turn to red, refills moves, heals units on owned villages
|
|
29
|
+
* const income = skirmishIncome(state, 'blue', 2, 1); // base 2, +1 per village blue owns
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export interface SkirmishTerrain {
|
|
33
|
+
/** movement points spent entering this terrain kind; `Infinity` makes it impassable */
|
|
34
|
+
moveCost: number;
|
|
35
|
+
/** 0-1 defence bonus for whoever is standing here while defending - what it multiplies is `skirmishAttack`'s own formula, not this terrain's own business */
|
|
36
|
+
defense: number;
|
|
37
|
+
}
|
|
38
|
+
export interface SkirmishCell {
|
|
39
|
+
terrain: string;
|
|
40
|
+
/** a capturable village - `moveSkirmishUnit` sets `owner` to whoever last stood here */
|
|
41
|
+
village?: boolean;
|
|
42
|
+
owner?: string;
|
|
43
|
+
}
|
|
44
|
+
export interface SkirmishUnit {
|
|
45
|
+
id: string;
|
|
46
|
+
owner: string;
|
|
47
|
+
x: number;
|
|
48
|
+
y: number;
|
|
49
|
+
hp: number;
|
|
50
|
+
maxHp: number;
|
|
51
|
+
/** movement points available this turn; refilled to `moves` by `endSkirmishTurn` */
|
|
52
|
+
moves: number;
|
|
53
|
+
remainingMoves?: number;
|
|
54
|
+
attack: number;
|
|
55
|
+
/** 0-1 base chance to land a hit, before the defender's terrain defence reduces it */
|
|
56
|
+
hitChance: number;
|
|
57
|
+
}
|
|
58
|
+
export interface SkirmishState {
|
|
59
|
+
width: number;
|
|
60
|
+
height: number;
|
|
61
|
+
terrainTable: Record<string, SkirmishTerrain>;
|
|
62
|
+
cells: SkirmishCell[];
|
|
63
|
+
units: SkirmishUnit[];
|
|
64
|
+
turn: string;
|
|
65
|
+
round: number;
|
|
66
|
+
}
|
|
67
|
+
export interface SkirmishMove {
|
|
68
|
+
unit: string;
|
|
69
|
+
x: number;
|
|
70
|
+
y: number;
|
|
71
|
+
cost: number;
|
|
72
|
+
}
|
|
73
|
+
export interface SkirmishStrike {
|
|
74
|
+
attacker: string;
|
|
75
|
+
defender: string;
|
|
76
|
+
hit: boolean;
|
|
77
|
+
damage: number;
|
|
78
|
+
killed: boolean;
|
|
79
|
+
}
|
|
80
|
+
export interface SkirmishExchange {
|
|
81
|
+
strikes: SkirmishStrike[];
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* @example
|
|
85
|
+
* ```ts
|
|
86
|
+
* import { startingSkirmish } from '@datamoc/mw_games/board';
|
|
87
|
+
*
|
|
88
|
+
* const state = startingSkirmish(6, 6, { plain: { moveCost: 1, defense: 0 } });
|
|
89
|
+
* console.log(state.width, state.round); // 6 1
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
export declare function startingSkirmish(width: number, height: number, terrainTable: Record<string, SkirmishTerrain>, defaultTerrain?: string): SkirmishState;
|
|
93
|
+
/**
|
|
94
|
+
* @example
|
|
95
|
+
* ```ts
|
|
96
|
+
* import { startingSkirmish, setSkirmishTerrain } from '@datamoc/mw_games/board';
|
|
97
|
+
*
|
|
98
|
+
* const state = startingSkirmish(6, 6, { plain: { moveCost: 1, defense: 0 }, forest: { moveCost: 2, defense: 0.3 } });
|
|
99
|
+
* setSkirmishTerrain(state, 2, 2, 'forest', true);
|
|
100
|
+
* console.log(state.cells[2 * 6 + 2]); // { terrain: 'forest', village: true }
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
export declare function setSkirmishTerrain(state: SkirmishState, x: number, y: number, terrain: string, village?: boolean): void;
|
|
104
|
+
/**
|
|
105
|
+
* whether a unit could be placed at (x, y) right now - on the map, passable, and unoccupied
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```ts
|
|
109
|
+
* import { startingSkirmish, addSkirmishUnit, canPlaceSkirmishUnit } from '@datamoc/mw_games/board';
|
|
110
|
+
*
|
|
111
|
+
* const state = startingSkirmish(6, 6, { plain: { moveCost: 1, defense: 0 } });
|
|
112
|
+
* addSkirmishUnit(state, { id: 'axeman', owner: 'blue', x: 0, y: 0, hp: 10, maxHp: 10, moves: 4, attack: 4, hitChance: 0.7 });
|
|
113
|
+
*
|
|
114
|
+
* console.log(canPlaceSkirmishUnit(state, 1, 0)); // true
|
|
115
|
+
* console.log(canPlaceSkirmishUnit(state, 0, 0)); // false - axeman is already there
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
export declare function canPlaceSkirmishUnit(state: SkirmishState, x: number, y: number): boolean;
|
|
119
|
+
/**
|
|
120
|
+
* Places a unit at full remaining movement; the first unit added decides whose turn it is.
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```ts
|
|
124
|
+
* import { startingSkirmish, addSkirmishUnit } from '@datamoc/mw_games/board';
|
|
125
|
+
*
|
|
126
|
+
* const state = startingSkirmish(6, 6, { plain: { moveCost: 1, defense: 0 } });
|
|
127
|
+
* addSkirmishUnit(state, { id: 'axeman', owner: 'blue', x: 0, y: 0, hp: 10, maxHp: 10, moves: 4, attack: 4, hitChance: 0.7 });
|
|
128
|
+
* console.log(state.turn); // 'blue'
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
export declare function addSkirmishUnit(state: SkirmishState, unit: SkirmishUnit): void;
|
|
132
|
+
/**
|
|
133
|
+
* Every cell a unit can reach with its remaining movement points this turn, weighted by each
|
|
134
|
+
* terrain kind's own `moveCost` - no zone of control, unlike `board.Tactics`.
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```ts
|
|
138
|
+
* import { startingSkirmish, addSkirmishUnit, skirmishMoves } from '@datamoc/mw_games/board';
|
|
139
|
+
*
|
|
140
|
+
* const state = startingSkirmish(6, 6, { plain: { moveCost: 1, defense: 0 } });
|
|
141
|
+
* addSkirmishUnit(state, { id: 'axeman', owner: 'blue', x: 0, y: 0, hp: 10, maxHp: 10, moves: 2, attack: 4, hitChance: 0.7 });
|
|
142
|
+
*
|
|
143
|
+
* console.log(skirmishMoves(state, 'axeman').length); // 6 - every hex within 2 plain steps
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
export declare function skirmishMoves(state: SkirmishState, unitId: string): SkirmishMove[];
|
|
147
|
+
/**
|
|
148
|
+
* @example
|
|
149
|
+
* ```ts
|
|
150
|
+
* import { startingSkirmish, addSkirmishUnit, skirmishMoves, moveSkirmishUnit } from '@datamoc/mw_games/board';
|
|
151
|
+
*
|
|
152
|
+
* const state = startingSkirmish(6, 6, { plain: { moveCost: 1, defense: 0 } });
|
|
153
|
+
* addSkirmishUnit(state, { id: 'axeman', owner: 'blue', x: 0, y: 0, hp: 10, maxHp: 10, moves: 2, attack: 4, hitChance: 0.7 });
|
|
154
|
+
*
|
|
155
|
+
* moveSkirmishUnit(state, skirmishMoves(state, 'axeman')[0]);
|
|
156
|
+
* console.log(state.units[0].remainingMoves); // 1 - one plain hex spent
|
|
157
|
+
* ```
|
|
158
|
+
*/
|
|
159
|
+
export declare function moveSkirmishUnit(state: SkirmishState, move: SkirmishMove): void;
|
|
160
|
+
/**
|
|
161
|
+
* An attacker's strike against an adjacent enemy, followed by the defender's own retaliation
|
|
162
|
+
* if it survives - both use the same formula: `hitChance` reduced by the defender's terrain
|
|
163
|
+
* defence, `Random.chance` deciding whether it lands, `attack` as the flat damage on a hit.
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```ts
|
|
167
|
+
* import { startingSkirmish, addSkirmishUnit, skirmishAttack } from '@datamoc/mw_games/board';
|
|
168
|
+
* import { Random } from '@datamoc/mw_games/core';
|
|
169
|
+
*
|
|
170
|
+
* const state = startingSkirmish(6, 6, { plain: { moveCost: 1, defense: 0 } });
|
|
171
|
+
* addSkirmishUnit(state, { id: 'axeman', owner: 'blue', x: 0, y: 0, hp: 10, maxHp: 10, moves: 4, attack: 4, hitChance: 1 });
|
|
172
|
+
* addSkirmishUnit(state, { id: 'raider', owner: 'red', x: 1, y: 0, hp: 10, maxHp: 10, moves: 4, attack: 3, hitChance: 1 });
|
|
173
|
+
*
|
|
174
|
+
* const exchange = Random.withSeed(1, () => skirmishAttack(state, 'axeman', 'raider'));
|
|
175
|
+
* console.log(exchange.strikes.map((strike: { attacker: string }) => strike.attacker)); // ['axeman', 'raider'] - raider survived to retaliate
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
export declare function skirmishAttack(state: SkirmishState, attackerId: string, defenderId: string): SkirmishExchange;
|
|
179
|
+
/**
|
|
180
|
+
* Net income for one side, from a flat base plus every village it currently owns - purely a
|
|
181
|
+
* function of the map's own village ownership, no formula beyond that belongs here, the same
|
|
182
|
+
* policy `board.Army`'s `armyIncome` already follows.
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* ```ts
|
|
186
|
+
* import { startingSkirmish, setSkirmishTerrain, skirmishIncome } from '@datamoc/mw_games/board';
|
|
187
|
+
*
|
|
188
|
+
* const state = startingSkirmish(4, 1, { plain: { moveCost: 1, defense: 0 } });
|
|
189
|
+
* setSkirmishTerrain(state, 0, 0, 'plain', true);
|
|
190
|
+
* state.cells[0].owner = 'blue';
|
|
191
|
+
*
|
|
192
|
+
* console.log(skirmishIncome(state, 'blue', 2, 1)); // 3 - base 2, plus 1 for the one village
|
|
193
|
+
* ```
|
|
194
|
+
*/
|
|
195
|
+
export declare function skirmishIncome(state: SkirmishState, owner: string, baseIncome: number, perVillage: number): number;
|
|
196
|
+
/**
|
|
197
|
+
* Hands the turn to the next owner with units on the board, refilling their movement and
|
|
198
|
+
* healing every one of their units standing on a village they own.
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* ```ts
|
|
202
|
+
* import { startingSkirmish, addSkirmishUnit, endSkirmishTurn } from '@datamoc/mw_games/board';
|
|
203
|
+
*
|
|
204
|
+
* const state = startingSkirmish(6, 6, { plain: { moveCost: 1, defense: 0 } });
|
|
205
|
+
* addSkirmishUnit(state, { id: 'axeman', owner: 'blue', x: 0, y: 0, hp: 10, maxHp: 10, moves: 4, attack: 4, hitChance: 0.7 });
|
|
206
|
+
* addSkirmishUnit(state, { id: 'raider', owner: 'red', x: 3, y: 0, hp: 10, maxHp: 10, moves: 4, attack: 3, hitChance: 0.6 });
|
|
207
|
+
*
|
|
208
|
+
* endSkirmishTurn(state, 2);
|
|
209
|
+
* console.log(state.turn, state.round); // 'red' 1
|
|
210
|
+
* ```
|
|
211
|
+
*/
|
|
212
|
+
export declare function endSkirmishTurn(state: SkirmishState, healPerVillage?: number): void;
|
|
213
|
+
//# sourceMappingURL=HexSkirmish.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HexSkirmish.d.ts","sourceRoot":"","sources":["../../src/board/HexSkirmish.ts"],"names":[],"mappings":"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"}
|