@datamoc/mw_games 0.5.0 → 0.5.2
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 +127 -0
- package/dist/actors/EntityTemplate.d.ts.map +1 -0
- package/dist/actors/EntityTemplate.js +117 -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/Registry.d.ts +31 -0
- package/dist/core/Registry.d.ts.map +1 -0
- package/dist/core/Registry.js +46 -0
- package/dist/core/Registry.js.map +1 -0
- package/dist/core/SceneComponents.d.ts +67 -0
- package/dist/core/SceneComponents.d.ts.map +1 -0
- package/dist/core/SceneComponents.js +76 -0
- package/dist/core/SceneComponents.js.map +1 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +3 -0
- package/dist/core/index.js.map +1 -1
- package/dist/mw_games.global.js +91 -90
- package/dist/rpg/Quest.d.ts +45 -0
- package/dist/rpg/Quest.d.ts.map +1 -1
- package/dist/rpg/Quest.js +76 -0
- package/dist/rpg/Quest.js.map +1 -1
- package/dist/rpg/index.d.ts +2 -2
- package/dist/rpg/index.d.ts.map +1 -1
- package/dist/rpg/index.js +1 -1
- package/dist/rpg/index.js.map +1 -1
- 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,271 @@
|
|
|
1
|
+
import { hexNeighbors, hexDistance } from '../core/Hex.js';
|
|
2
|
+
import * as Random from '../core/Random.js';
|
|
3
|
+
/**
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { startingSkirmish } from '@datamoc/mw_games/board';
|
|
7
|
+
*
|
|
8
|
+
* const state = startingSkirmish(6, 6, { plain: { moveCost: 1, defense: 0 } });
|
|
9
|
+
* console.log(state.width, state.round); // 6 1
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export function startingSkirmish(width, height, terrainTable, defaultTerrain) {
|
|
13
|
+
if (width < 1 || height < 1)
|
|
14
|
+
throw new Error('a skirmish map needs positive dimensions');
|
|
15
|
+
const terrain = defaultTerrain ?? Object.keys(terrainTable)[0];
|
|
16
|
+
if (!terrain || !terrainTable[terrain])
|
|
17
|
+
throw new Error('a skirmish map needs at least one terrain kind');
|
|
18
|
+
return {
|
|
19
|
+
width,
|
|
20
|
+
height,
|
|
21
|
+
terrainTable,
|
|
22
|
+
cells: Array.from({ length: width * height }, () => ({ terrain })),
|
|
23
|
+
units: [],
|
|
24
|
+
turn: '',
|
|
25
|
+
round: 1,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* import { startingSkirmish, setSkirmishTerrain } from '@datamoc/mw_games/board';
|
|
32
|
+
*
|
|
33
|
+
* const state = startingSkirmish(6, 6, { plain: { moveCost: 1, defense: 0 }, forest: { moveCost: 2, defense: 0.3 } });
|
|
34
|
+
* setSkirmishTerrain(state, 2, 2, 'forest', true);
|
|
35
|
+
* console.log(state.cells[2 * 6 + 2]); // { terrain: 'forest', village: true }
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export function setSkirmishTerrain(state, x, y, terrain, village = false) {
|
|
39
|
+
if (!inside(state, x, y))
|
|
40
|
+
throw new Error('cell is outside the skirmish map');
|
|
41
|
+
if (!state.terrainTable[terrain])
|
|
42
|
+
throw new Error(`unknown skirmish terrain "${terrain}"`);
|
|
43
|
+
state.cells[y * state.width + x] = village ? { terrain, village: true } : { terrain };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* whether a unit could be placed at (x, y) right now - on the map, passable, and unoccupied
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* import { startingSkirmish, addSkirmishUnit, canPlaceSkirmishUnit } from '@datamoc/mw_games/board';
|
|
51
|
+
*
|
|
52
|
+
* const state = startingSkirmish(6, 6, { plain: { moveCost: 1, defense: 0 } });
|
|
53
|
+
* addSkirmishUnit(state, { id: 'axeman', owner: 'blue', x: 0, y: 0, hp: 10, maxHp: 10, moves: 4, attack: 4, hitChance: 0.7 });
|
|
54
|
+
*
|
|
55
|
+
* console.log(canPlaceSkirmishUnit(state, 1, 0)); // true
|
|
56
|
+
* console.log(canPlaceSkirmishUnit(state, 0, 0)); // false - axeman is already there
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export function canPlaceSkirmishUnit(state, x, y) {
|
|
60
|
+
return inside(state, x, y) && moveCostOf(state, x, y) < Infinity && !occupied(state, x, y);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Places a unit at full remaining movement; the first unit added decides whose turn it is.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```ts
|
|
67
|
+
* import { startingSkirmish, addSkirmishUnit } from '@datamoc/mw_games/board';
|
|
68
|
+
*
|
|
69
|
+
* const state = startingSkirmish(6, 6, { plain: { moveCost: 1, defense: 0 } });
|
|
70
|
+
* addSkirmishUnit(state, { id: 'axeman', owner: 'blue', x: 0, y: 0, hp: 10, maxHp: 10, moves: 4, attack: 4, hitChance: 0.7 });
|
|
71
|
+
* console.log(state.turn); // 'blue'
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export function addSkirmishUnit(state, unit) {
|
|
75
|
+
if (!canPlaceSkirmishUnit(state, unit.x, unit.y))
|
|
76
|
+
throw new Error('skirmish unit cannot be placed there');
|
|
77
|
+
state.units.push({ ...unit, remainingMoves: unit.moves });
|
|
78
|
+
if (!state.turn)
|
|
79
|
+
state.turn = unit.owner;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Every cell a unit can reach with its remaining movement points this turn, weighted by each
|
|
83
|
+
* terrain kind's own `moveCost` - no zone of control, unlike `board.Tactics`.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```ts
|
|
87
|
+
* import { startingSkirmish, addSkirmishUnit, skirmishMoves } from '@datamoc/mw_games/board';
|
|
88
|
+
*
|
|
89
|
+
* const state = startingSkirmish(6, 6, { plain: { moveCost: 1, defense: 0 } });
|
|
90
|
+
* addSkirmishUnit(state, { id: 'axeman', owner: 'blue', x: 0, y: 0, hp: 10, maxHp: 10, moves: 2, attack: 4, hitChance: 0.7 });
|
|
91
|
+
*
|
|
92
|
+
* console.log(skirmishMoves(state, 'axeman').length); // 6 - every hex within 2 plain steps
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export function skirmishMoves(state, unitId) {
|
|
96
|
+
const unit = getUnit(state, unitId);
|
|
97
|
+
const budget = unit.remainingMoves ?? unit.moves;
|
|
98
|
+
if (unit.owner !== state.turn || budget <= 0)
|
|
99
|
+
return [];
|
|
100
|
+
const out = [];
|
|
101
|
+
for (let y = 0; y < state.height; y++)
|
|
102
|
+
for (let x = 0; x < state.width; x++) {
|
|
103
|
+
if ((x === unit.x && y === unit.y) || moveCostOf(state, x, y) === Infinity || occupied(state, x, y))
|
|
104
|
+
continue;
|
|
105
|
+
const cost = pathCost(state, unit, x, y, budget);
|
|
106
|
+
if (cost !== null)
|
|
107
|
+
out.push({ unit: unitId, x, y, cost });
|
|
108
|
+
}
|
|
109
|
+
return out;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* @example
|
|
113
|
+
* ```ts
|
|
114
|
+
* import { startingSkirmish, addSkirmishUnit, skirmishMoves, moveSkirmishUnit } from '@datamoc/mw_games/board';
|
|
115
|
+
*
|
|
116
|
+
* const state = startingSkirmish(6, 6, { plain: { moveCost: 1, defense: 0 } });
|
|
117
|
+
* addSkirmishUnit(state, { id: 'axeman', owner: 'blue', x: 0, y: 0, hp: 10, maxHp: 10, moves: 2, attack: 4, hitChance: 0.7 });
|
|
118
|
+
*
|
|
119
|
+
* moveSkirmishUnit(state, skirmishMoves(state, 'axeman')[0]);
|
|
120
|
+
* console.log(state.units[0].remainingMoves); // 1 - one plain hex spent
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
export function moveSkirmishUnit(state, move) {
|
|
124
|
+
const legal = skirmishMoves(state, move.unit).find((candidate) => candidate.x === move.x && candidate.y === move.y);
|
|
125
|
+
if (!legal)
|
|
126
|
+
throw new Error('illegal skirmish move');
|
|
127
|
+
const unit = getUnit(state, move.unit);
|
|
128
|
+
unit.x = move.x;
|
|
129
|
+
unit.y = move.y;
|
|
130
|
+
unit.remainingMoves = (unit.remainingMoves ?? unit.moves) - legal.cost;
|
|
131
|
+
const cell = state.cells[move.y * state.width + move.x];
|
|
132
|
+
if (cell.village)
|
|
133
|
+
cell.owner = unit.owner;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* An attacker's strike against an adjacent enemy, followed by the defender's own retaliation
|
|
137
|
+
* if it survives - both use the same formula: `hitChance` reduced by the defender's terrain
|
|
138
|
+
* defence, `Random.chance` deciding whether it lands, `attack` as the flat damage on a hit.
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```ts
|
|
142
|
+
* import { startingSkirmish, addSkirmishUnit, skirmishAttack } from '@datamoc/mw_games/board';
|
|
143
|
+
* import { Random } from '@datamoc/mw_games/core';
|
|
144
|
+
*
|
|
145
|
+
* const state = startingSkirmish(6, 6, { plain: { moveCost: 1, defense: 0 } });
|
|
146
|
+
* addSkirmishUnit(state, { id: 'axeman', owner: 'blue', x: 0, y: 0, hp: 10, maxHp: 10, moves: 4, attack: 4, hitChance: 1 });
|
|
147
|
+
* addSkirmishUnit(state, { id: 'raider', owner: 'red', x: 1, y: 0, hp: 10, maxHp: 10, moves: 4, attack: 3, hitChance: 1 });
|
|
148
|
+
*
|
|
149
|
+
* const exchange = Random.withSeed(1, () => skirmishAttack(state, 'axeman', 'raider'));
|
|
150
|
+
* console.log(exchange.strikes.map((strike: { attacker: string }) => strike.attacker)); // ['axeman', 'raider'] - raider survived to retaliate
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
153
|
+
export function skirmishAttack(state, attackerId, defenderId) {
|
|
154
|
+
const attacker = getUnit(state, attackerId);
|
|
155
|
+
const defender = getUnit(state, defenderId);
|
|
156
|
+
if (attacker.owner !== state.turn || attacker.owner === defender.owner)
|
|
157
|
+
throw new Error('invalid skirmish attack');
|
|
158
|
+
if (hexDistance(attacker, defender) !== 1)
|
|
159
|
+
throw new Error('skirmish combat is adjacency-only');
|
|
160
|
+
const strikes = [strike(state, attacker, defender)];
|
|
161
|
+
if (defender.hp > 0)
|
|
162
|
+
strikes.push(strike(state, defender, attacker));
|
|
163
|
+
state.units = state.units.filter((unit) => unit.hp > 0);
|
|
164
|
+
return { strikes };
|
|
165
|
+
}
|
|
166
|
+
function strike(state, attacker, defender) {
|
|
167
|
+
const defense = terrainOf(state, defender.x, defender.y).defense;
|
|
168
|
+
const hit = Random.chance(Math.max(0, Math.min(1, attacker.hitChance * (1 - defense))));
|
|
169
|
+
const damage = hit ? Math.min(attacker.attack, defender.hp) : 0;
|
|
170
|
+
defender.hp -= damage;
|
|
171
|
+
return { attacker: attacker.id, defender: defender.id, hit, damage, killed: defender.hp <= 0 };
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Net income for one side, from a flat base plus every village it currently owns - purely a
|
|
175
|
+
* function of the map's own village ownership, no formula beyond that belongs here, the same
|
|
176
|
+
* policy `board.Army`'s `armyIncome` already follows.
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```ts
|
|
180
|
+
* import { startingSkirmish, setSkirmishTerrain, skirmishIncome } from '@datamoc/mw_games/board';
|
|
181
|
+
*
|
|
182
|
+
* const state = startingSkirmish(4, 1, { plain: { moveCost: 1, defense: 0 } });
|
|
183
|
+
* setSkirmishTerrain(state, 0, 0, 'plain', true);
|
|
184
|
+
* state.cells[0].owner = 'blue';
|
|
185
|
+
*
|
|
186
|
+
* console.log(skirmishIncome(state, 'blue', 2, 1)); // 3 - base 2, plus 1 for the one village
|
|
187
|
+
* ```
|
|
188
|
+
*/
|
|
189
|
+
export function skirmishIncome(state, owner, baseIncome, perVillage) {
|
|
190
|
+
const villages = state.cells.filter((cell) => cell.village && cell.owner === owner).length;
|
|
191
|
+
return baseIncome + villages * perVillage;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Hands the turn to the next owner with units on the board, refilling their movement and
|
|
195
|
+
* healing every one of their units standing on a village they own.
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* ```ts
|
|
199
|
+
* import { startingSkirmish, addSkirmishUnit, endSkirmishTurn } from '@datamoc/mw_games/board';
|
|
200
|
+
*
|
|
201
|
+
* const state = startingSkirmish(6, 6, { plain: { moveCost: 1, defense: 0 } });
|
|
202
|
+
* addSkirmishUnit(state, { id: 'axeman', owner: 'blue', x: 0, y: 0, hp: 10, maxHp: 10, moves: 4, attack: 4, hitChance: 0.7 });
|
|
203
|
+
* addSkirmishUnit(state, { id: 'raider', owner: 'red', x: 3, y: 0, hp: 10, maxHp: 10, moves: 4, attack: 3, hitChance: 0.6 });
|
|
204
|
+
*
|
|
205
|
+
* endSkirmishTurn(state, 2);
|
|
206
|
+
* console.log(state.turn, state.round); // 'red' 1
|
|
207
|
+
* ```
|
|
208
|
+
*/
|
|
209
|
+
export function endSkirmishTurn(state, healPerVillage = 0) {
|
|
210
|
+
const owners = [...new Set(state.units.map((unit) => unit.owner))];
|
|
211
|
+
if (owners.length === 0)
|
|
212
|
+
return;
|
|
213
|
+
const next = owners.indexOf(state.turn) + 1;
|
|
214
|
+
if (next >= owners.length)
|
|
215
|
+
state.round++;
|
|
216
|
+
state.turn = owners[next % owners.length];
|
|
217
|
+
for (const unit of state.units) {
|
|
218
|
+
if (unit.owner !== state.turn)
|
|
219
|
+
continue;
|
|
220
|
+
unit.remainingMoves = unit.moves;
|
|
221
|
+
const cell = state.cells[unit.y * state.width + unit.x];
|
|
222
|
+
if (cell.village && cell.owner === unit.owner && healPerVillage > 0) {
|
|
223
|
+
unit.hp = Math.min(unit.maxHp, unit.hp + healPerVillage);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
function getUnit(state, id) {
|
|
228
|
+
const unit = state.units.find((candidate) => candidate.id === id);
|
|
229
|
+
if (!unit)
|
|
230
|
+
throw new Error(`unknown skirmish unit "${id}"`);
|
|
231
|
+
return unit;
|
|
232
|
+
}
|
|
233
|
+
function inside(state, x, y) { return x >= 0 && y >= 0 && x < state.width && y < state.height; }
|
|
234
|
+
function occupied(state, x, y) { return state.units.some((unit) => unit.x === x && unit.y === y); }
|
|
235
|
+
function terrainOf(state, x, y) { return state.terrainTable[state.cells[y * state.width + x].terrain]; }
|
|
236
|
+
function moveCostOf(state, x, y) { return terrainOf(state, x, y).moveCost; }
|
|
237
|
+
//the real weighted walking cost to (targetX, targetY), never exceeding `budget`, or null if it
|
|
238
|
+
//cannot be reached within that budget - Dijkstra over a small grid rather than BFS, since
|
|
239
|
+
//terrain move cost varies per cell unlike board.Tactics' uniform one-step cost
|
|
240
|
+
function pathCost(state, unit, targetX, targetY, budget) {
|
|
241
|
+
const best = new Map([[`${unit.x},${unit.y}`, 0]]);
|
|
242
|
+
const todo = [{ x: unit.x, y: unit.y, cost: 0 }];
|
|
243
|
+
while (todo.length > 0) {
|
|
244
|
+
todo.sort((a, b) => a.cost - b.cost);
|
|
245
|
+
const current = todo.shift();
|
|
246
|
+
const key = `${current.x},${current.y}`;
|
|
247
|
+
if (current.cost > (best.get(key) ?? Infinity))
|
|
248
|
+
continue;
|
|
249
|
+
if (current.x === targetX && current.y === targetY)
|
|
250
|
+
return current.cost;
|
|
251
|
+
for (const next of hexNeighbors(current.x, current.y)) {
|
|
252
|
+
if (!inside(state, next.x, next.y))
|
|
253
|
+
continue;
|
|
254
|
+
const stepCost = moveCostOf(state, next.x, next.y);
|
|
255
|
+
if (stepCost === Infinity)
|
|
256
|
+
continue;
|
|
257
|
+
if (occupied(state, next.x, next.y) && !(next.x === targetX && next.y === targetY))
|
|
258
|
+
continue;
|
|
259
|
+
const total = current.cost + stepCost;
|
|
260
|
+
if (total > budget)
|
|
261
|
+
continue;
|
|
262
|
+
const nextKey = `${next.x},${next.y}`;
|
|
263
|
+
if (total < (best.get(nextKey) ?? Infinity)) {
|
|
264
|
+
best.set(nextKey, total);
|
|
265
|
+
todo.push({ x: next.x, y: next.y, cost: total });
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
//# sourceMappingURL=HexSkirmish.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HexSkirmish.js","sourceRoot":"","sources":["../../src/board/HexSkirmish.ts"],"names":[],"mappings":"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"}
|
package/dist/board/index.d.ts
CHANGED
|
@@ -10,4 +10,6 @@ export { FactionFog } from './FogOfWar.ts';
|
|
|
10
10
|
export type { VisionCell } from './FogOfWar.ts';
|
|
11
11
|
export { startingArmy, recruit, recall, bankUnit, armyIncome, applyUpkeep } from './Army.ts';
|
|
12
12
|
export type { UnitTemplate, ArmyState, UpkeepRates } from './Army.ts';
|
|
13
|
+
export { startingSkirmish, setSkirmishTerrain, canPlaceSkirmishUnit, addSkirmishUnit, skirmishMoves, moveSkirmishUnit, skirmishAttack, skirmishIncome, endSkirmishTurn, } from './HexSkirmish.ts';
|
|
14
|
+
export type { SkirmishTerrain, SkirmishCell, SkirmishUnit, SkirmishState, SkirmishMove, SkirmishStrike, SkirmishExchange, } from './HexSkirmish.ts';
|
|
13
15
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/board/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,aAAa,EACb,QAAQ,EACR,UAAU,EACV,UAAU,EACV,SAAS,EACT,OAAO,EACP,UAAU,EACV,EAAE,EACF,UAAU,GACV,MAAM,YAAY,CAAC;AACpB,YAAY,EACX,SAAS,EACT,SAAS,EACT,UAAU,EACV,WAAW,EACX,aAAa,EACb,SAAS,EACT,aAAa,EACb,UAAU,EACV,WAAW,GACX,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACjD,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EACN,SAAS,EACT,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,MAAM,EACN,MAAM,EACN,QAAQ,EACR,OAAO,EACP,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,mBAAmB,EACnB,UAAU,EACV,WAAW,EACX,IAAI,EACJ,WAAW,EACX,aAAa,EACb,aAAa,EACb,oBAAoB,EACpB,yBAAyB,EACzB,YAAY,EACZ,QAAQ,EACR,cAAc,EACd,OAAO,EACP,SAAS,GACT,MAAM,eAAe,CAAC;AACvB,YAAY,EACX,UAAU,EACV,UAAU,EACV,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,aAAa,EACb,OAAO,EACP,OAAO,EACP,YAAY,EACZ,SAAS,EACT,eAAe,EACf,cAAc,EACd,QAAQ,EACR,QAAQ,EACR,IAAI,EACJ,cAAc,GACd,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,oBAAoB,EAAE,aAAa,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACxM,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC3H,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7F,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/board/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,aAAa,EACb,QAAQ,EACR,UAAU,EACV,UAAU,EACV,SAAS,EACT,OAAO,EACP,UAAU,EACV,EAAE,EACF,UAAU,GACV,MAAM,YAAY,CAAC;AACpB,YAAY,EACX,SAAS,EACT,SAAS,EACT,UAAU,EACV,WAAW,EACX,aAAa,EACb,SAAS,EACT,aAAa,EACb,UAAU,EACV,WAAW,GACX,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACjD,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EACN,SAAS,EACT,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,MAAM,EACN,MAAM,EACN,QAAQ,EACR,OAAO,EACP,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,mBAAmB,EACnB,UAAU,EACV,WAAW,EACX,IAAI,EACJ,WAAW,EACX,aAAa,EACb,aAAa,EACb,oBAAoB,EACpB,yBAAyB,EACzB,YAAY,EACZ,QAAQ,EACR,cAAc,EACd,OAAO,EACP,SAAS,GACT,MAAM,eAAe,CAAC;AACvB,YAAY,EACX,UAAU,EACV,UAAU,EACV,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,aAAa,EACb,OAAO,EACP,OAAO,EACP,YAAY,EACZ,SAAS,EACT,eAAe,EACf,cAAc,EACd,QAAQ,EACR,QAAQ,EACR,IAAI,EACJ,cAAc,GACd,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,oBAAoB,EAAE,aAAa,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACxM,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC3H,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7F,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,EACN,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,EACpB,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,eAAe,GACf,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACX,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,cAAc,EACd,gBAAgB,GAChB,MAAM,kBAAkB,CAAC"}
|
package/dist/board/index.js
CHANGED
|
@@ -4,4 +4,5 @@ export { BoardGrid, startingCheckers, checkersMoves, applyCheckersMove, starting
|
|
|
4
4
|
export { startingTactics, addTacticalUnit, canPlaceTacticalUnit, tacticalMoves, moveTacticalUnit, setTacticalOverwatch, triggerTacticalOverwatch, tacticalAttack, endTacticalTurn } from './Tactics.js';
|
|
5
5
|
export { FactionFog } from './FogOfWar.js';
|
|
6
6
|
export { startingArmy, recruit, recall, bankUnit, armyIncome, applyUpkeep } from './Army.js';
|
|
7
|
+
export { startingSkirmish, setSkirmishTerrain, canPlaceSkirmishUnit, addSkirmishUnit, skirmishMoves, moveSkirmishUnit, skirmishAttack, skirmishIncome, endSkirmishTurn, } from './HexSkirmish.js';
|
|
7
8
|
//# sourceMappingURL=index.js.map
|
package/dist/board/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/board/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,aAAa,EACb,QAAQ,EACR,UAAU,EACV,UAAU,EACV,SAAS,EACT,OAAO,EACP,UAAU,EACV,EAAE,EACF,UAAU,GACV,MAAM,YAAY,CAAC;AAYpB,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EACN,SAAS,EACT,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,MAAM,EACN,MAAM,EACN,QAAQ,EACR,OAAO,EACP,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,mBAAmB,EACnB,UAAU,EACV,WAAW,EACX,IAAI,EACJ,WAAW,EACX,aAAa,EACb,aAAa,EACb,oBAAoB,EACpB,yBAAyB,EACzB,YAAY,EACZ,QAAQ,EACR,cAAc,EACd,OAAO,EACP,SAAS,GACT,MAAM,eAAe,CAAC;AAmBvB,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,oBAAoB,EAAE,aAAa,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAExM,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/board/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,aAAa,EACb,QAAQ,EACR,UAAU,EACV,UAAU,EACV,SAAS,EACT,OAAO,EACP,UAAU,EACV,EAAE,EACF,UAAU,GACV,MAAM,YAAY,CAAC;AAYpB,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EACN,SAAS,EACT,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,MAAM,EACN,MAAM,EACN,QAAQ,EACR,OAAO,EACP,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,mBAAmB,EACnB,UAAU,EACV,WAAW,EACX,IAAI,EACJ,WAAW,EACX,aAAa,EACb,aAAa,EACb,oBAAoB,EACpB,yBAAyB,EACzB,YAAY,EACZ,QAAQ,EACR,cAAc,EACd,OAAO,EACP,SAAS,GACT,MAAM,eAAe,CAAC;AAmBvB,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,oBAAoB,EAAE,aAAa,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAExM,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7F,OAAO,EACN,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,EACpB,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,eAAe,GACf,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A header-row CSV into an array of typed row objects - so a content designer edits a
|
|
3
|
+
* spreadsheet instead of a `.ts` object literal for a table shaped like `actors.AffixTable`,
|
|
4
|
+
* `actors.LootTable`, or any other array-of-records a game defines. The same precedent
|
|
5
|
+
* `i18n`'s `parseFTL` already set: this takes a raw string and has no opinion on how that
|
|
6
|
+
* string reached the game (a small table can sit in a `.ts` template literal; a larger one
|
|
7
|
+
* loads through a bundler's raw-text import - Vite resolves a `?raw`-suffixed path to its
|
|
8
|
+
* file's contents as a plain string - or through a game's own asset pipeline) - `mwg`
|
|
9
|
+
* supplies the parsing, not the loading.
|
|
10
|
+
*
|
|
11
|
+
* Every cell is a string until a column says otherwise: `columns` names which fields are
|
|
12
|
+
* `'number'`/`'boolean'`/`'list'` (semicolon-separated by default, for a field shaped like
|
|
13
|
+
* `AffixDef.kinds`) /`'map'` (semicolon-separated `key=value` pairs, for a per-row property
|
|
14
|
+
* bag such as `{ str: '2', dex: '-1' }` a game reads its own way) - and an undeclared column
|
|
15
|
+
* stays a plain string. An **empty cell omits that field from the row entirely**, the same as
|
|
16
|
+
* never setting an optional property - so a blank `curse` column reads exactly like the
|
|
17
|
+
* `curse?: boolean` it fills never being set.
|
|
18
|
+
*
|
|
19
|
+
* Follows RFC 4180 far enough for real game-data text: a quoted field may contain the
|
|
20
|
+
* delimiter, a newline, or an escaped `""` for a literal quote, which a naive `split(',')`
|
|
21
|
+
* cannot survive the moment a description contains a comma.
|
|
22
|
+
*
|
|
23
|
+
* What this cannot hold: a `core.ReactionTable` rule's `when`/`action` are executable code,
|
|
24
|
+
* not data, so no cell format expresses them - the same boundary `AffixDef.id` already draws
|
|
25
|
+
* (a string the game interprets, `mwg` never does). A CSV row can drive *which* reactions a
|
|
26
|
+
* game builds at startup (an id, a comparison string like `'hp<=0.25'`, a threshold number a
|
|
27
|
+
* `'number'` column already coerces) with the game's own code turning each row into a real
|
|
28
|
+
* `ReactionRule`; it cannot hold the rule's logic itself.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* import { parseCSV } from '@datamoc/mw_games/core';
|
|
33
|
+
* import type { AffixDef, AffixTable } from '@datamoc/mw_games/actors';
|
|
34
|
+
*
|
|
35
|
+
* const csv = `id,trigger,weight,curse,description
|
|
36
|
+
* blazing,strike,3,,Ignites the victim
|
|
37
|
+
* wayward,strike,1,true,"Cursed: -3 accuracy"`;
|
|
38
|
+
*
|
|
39
|
+
* const table: AffixTable = {
|
|
40
|
+
* entries: parseCSV<AffixDef>(csv, { columns: { weight: 'number', curse: 'boolean' } }),
|
|
41
|
+
* };
|
|
42
|
+
* console.log(table.entries[1]); // { id: 'wayward', trigger: 'strike', weight: 1, curse: true, description: 'Cursed: -3 accuracy' }
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export type CsvColumnType = 'string' | 'number' | 'boolean' | 'list' | 'map';
|
|
46
|
+
export interface CsvOptions {
|
|
47
|
+
/** how to interpret each named column beyond a plain string; an undeclared column stays one */
|
|
48
|
+
columns?: Record<string, CsvColumnType>;
|
|
49
|
+
/** splits a `'list'`/`'map'` column's cell into individual entries; default `;` */
|
|
50
|
+
listDelimiter?: string;
|
|
51
|
+
/** splits a `'map'` entry into its key and value; default `=` */
|
|
52
|
+
mapDelimiter?: string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* @example
|
|
56
|
+
* ```ts
|
|
57
|
+
* import { parseCSV } from '@datamoc/mw_games/core';
|
|
58
|
+
*
|
|
59
|
+
* const rows = parseCSV('id,weight\nblazing,3\nchilling,3', { columns: { weight: 'number' } });
|
|
60
|
+
* console.log(rows); // [{ id: 'blazing', weight: 3 }, { id: 'chilling', weight: 3 }]
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export declare function parseCSV<T = Record<string, string>>(source: string, options?: CsvOptions): T[];
|
|
64
|
+
//# sourceMappingURL=Csv.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Csv.d.ts","sourceRoot":"","sources":["../../src/core/Csv.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,KAAK,CAAC;AAE7E,MAAM,WAAW,UAAU;IAC1B,+FAA+F;IAC/F,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAExC,mFAAmF;IACnF,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,GAAG,CAAC,EAAE,CAiBlG"}
|
package/dist/core/Csv.js
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A header-row CSV into an array of typed row objects - so a content designer edits a
|
|
3
|
+
* spreadsheet instead of a `.ts` object literal for a table shaped like `actors.AffixTable`,
|
|
4
|
+
* `actors.LootTable`, or any other array-of-records a game defines. The same precedent
|
|
5
|
+
* `i18n`'s `parseFTL` already set: this takes a raw string and has no opinion on how that
|
|
6
|
+
* string reached the game (a small table can sit in a `.ts` template literal; a larger one
|
|
7
|
+
* loads through a bundler's raw-text import - Vite resolves a `?raw`-suffixed path to its
|
|
8
|
+
* file's contents as a plain string - or through a game's own asset pipeline) - `mwg`
|
|
9
|
+
* supplies the parsing, not the loading.
|
|
10
|
+
*
|
|
11
|
+
* Every cell is a string until a column says otherwise: `columns` names which fields are
|
|
12
|
+
* `'number'`/`'boolean'`/`'list'` (semicolon-separated by default, for a field shaped like
|
|
13
|
+
* `AffixDef.kinds`) /`'map'` (semicolon-separated `key=value` pairs, for a per-row property
|
|
14
|
+
* bag such as `{ str: '2', dex: '-1' }` a game reads its own way) - and an undeclared column
|
|
15
|
+
* stays a plain string. An **empty cell omits that field from the row entirely**, the same as
|
|
16
|
+
* never setting an optional property - so a blank `curse` column reads exactly like the
|
|
17
|
+
* `curse?: boolean` it fills never being set.
|
|
18
|
+
*
|
|
19
|
+
* Follows RFC 4180 far enough for real game-data text: a quoted field may contain the
|
|
20
|
+
* delimiter, a newline, or an escaped `""` for a literal quote, which a naive `split(',')`
|
|
21
|
+
* cannot survive the moment a description contains a comma.
|
|
22
|
+
*
|
|
23
|
+
* What this cannot hold: a `core.ReactionTable` rule's `when`/`action` are executable code,
|
|
24
|
+
* not data, so no cell format expresses them - the same boundary `AffixDef.id` already draws
|
|
25
|
+
* (a string the game interprets, `mwg` never does). A CSV row can drive *which* reactions a
|
|
26
|
+
* game builds at startup (an id, a comparison string like `'hp<=0.25'`, a threshold number a
|
|
27
|
+
* `'number'` column already coerces) with the game's own code turning each row into a real
|
|
28
|
+
* `ReactionRule`; it cannot hold the rule's logic itself.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* import { parseCSV } from '@datamoc/mw_games/core';
|
|
33
|
+
* import type { AffixDef, AffixTable } from '@datamoc/mw_games/actors';
|
|
34
|
+
*
|
|
35
|
+
* const csv = `id,trigger,weight,curse,description
|
|
36
|
+
* blazing,strike,3,,Ignites the victim
|
|
37
|
+
* wayward,strike,1,true,"Cursed: -3 accuracy"`;
|
|
38
|
+
*
|
|
39
|
+
* const table: AffixTable = {
|
|
40
|
+
* entries: parseCSV<AffixDef>(csv, { columns: { weight: 'number', curse: 'boolean' } }),
|
|
41
|
+
* };
|
|
42
|
+
* console.log(table.entries[1]); // { id: 'wayward', trigger: 'strike', weight: 1, curse: true, description: 'Cursed: -3 accuracy' }
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
/**
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* import { parseCSV } from '@datamoc/mw_games/core';
|
|
49
|
+
*
|
|
50
|
+
* const rows = parseCSV('id,weight\nblazing,3\nchilling,3', { columns: { weight: 'number' } });
|
|
51
|
+
* console.log(rows); // [{ id: 'blazing', weight: 3 }, { id: 'chilling', weight: 3 }]
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export function parseCSV(source, options = {}) {
|
|
55
|
+
const rows = tokenizeCsv(source);
|
|
56
|
+
if (rows.length === 0)
|
|
57
|
+
return [];
|
|
58
|
+
const [header, ...body] = rows;
|
|
59
|
+
const listDelimiter = options.listDelimiter ?? ';';
|
|
60
|
+
const mapDelimiter = options.mapDelimiter ?? '=';
|
|
61
|
+
return body.map((cells, rowIndex) => {
|
|
62
|
+
const row = {};
|
|
63
|
+
header.forEach((name, columnIndex) => {
|
|
64
|
+
const raw = cells[columnIndex] ?? '';
|
|
65
|
+
if (raw === '')
|
|
66
|
+
return; //an empty cell omits the field, the same as an optional property never set
|
|
67
|
+
row[name] = coerceCsvCell(raw, options.columns?.[name] ?? 'string', name, rowIndex, listDelimiter, mapDelimiter);
|
|
68
|
+
});
|
|
69
|
+
return row;
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
function coerceCsvCell(raw, type, column, rowIndex, listDelimiter, mapDelimiter) {
|
|
73
|
+
switch (type) {
|
|
74
|
+
case 'string':
|
|
75
|
+
return raw;
|
|
76
|
+
case 'number': {
|
|
77
|
+
const value = Number(raw);
|
|
78
|
+
if (!Number.isFinite(value))
|
|
79
|
+
throw new Error(`CSV row ${rowIndex + 1}, column "${column}": "${raw}" is not a number`);
|
|
80
|
+
return value;
|
|
81
|
+
}
|
|
82
|
+
case 'boolean': {
|
|
83
|
+
const lower = raw.toLowerCase();
|
|
84
|
+
if (lower === 'true')
|
|
85
|
+
return true;
|
|
86
|
+
if (lower === 'false')
|
|
87
|
+
return false;
|
|
88
|
+
throw new Error(`CSV row ${rowIndex + 1}, column "${column}": "${raw}" is not "true" or "false"`);
|
|
89
|
+
}
|
|
90
|
+
case 'list':
|
|
91
|
+
return raw.split(listDelimiter).map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
92
|
+
case 'map': {
|
|
93
|
+
const map = {};
|
|
94
|
+
for (const entry of raw.split(listDelimiter).map((piece) => piece.trim()).filter((piece) => piece.length > 0)) {
|
|
95
|
+
const at = entry.indexOf(mapDelimiter);
|
|
96
|
+
if (at === -1)
|
|
97
|
+
throw new Error(`CSV row ${rowIndex + 1}, column "${column}": "${entry}" has no "${mapDelimiter}" to split a key from its value`);
|
|
98
|
+
map[entry.slice(0, at).trim()] = entry.slice(at + mapDelimiter.length).trim();
|
|
99
|
+
}
|
|
100
|
+
return map;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
//RFC 4180-shaped tokenizer, char by char rather than split(',')/split('\n'): a quoted field may
|
|
105
|
+
//itself contain the delimiter, a bare newline, or an escaped `""` for a literal quote, none of
|
|
106
|
+
//which a naive split survives the moment a description column contains a comma
|
|
107
|
+
function tokenizeCsv(source) {
|
|
108
|
+
const rows = [];
|
|
109
|
+
let row = [];
|
|
110
|
+
let field = '';
|
|
111
|
+
let inQuotes = false;
|
|
112
|
+
let i = 0;
|
|
113
|
+
while (i < source.length) {
|
|
114
|
+
const char = source[i];
|
|
115
|
+
if (inQuotes) {
|
|
116
|
+
if (char === '"') {
|
|
117
|
+
if (source[i + 1] === '"') {
|
|
118
|
+
field += '"';
|
|
119
|
+
i += 2;
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
inQuotes = false;
|
|
123
|
+
i++;
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
field += char;
|
|
127
|
+
i++;
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
if (char === '"') {
|
|
131
|
+
inQuotes = true;
|
|
132
|
+
i++;
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (char === ',') {
|
|
136
|
+
row.push(field);
|
|
137
|
+
field = '';
|
|
138
|
+
i++;
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
if (char === '\r') {
|
|
142
|
+
i++;
|
|
143
|
+
continue;
|
|
144
|
+
} //normalize CRLF, and swallow a bare CR too
|
|
145
|
+
if (char === '\n') {
|
|
146
|
+
row.push(field);
|
|
147
|
+
rows.push(row);
|
|
148
|
+
row = [];
|
|
149
|
+
field = '';
|
|
150
|
+
i++;
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
field += char;
|
|
154
|
+
i++;
|
|
155
|
+
}
|
|
156
|
+
if (field.length > 0 || row.length > 0) {
|
|
157
|
+
row.push(field);
|
|
158
|
+
rows.push(row);
|
|
159
|
+
}
|
|
160
|
+
//a trailing newline (the common case for a hand-edited file) would otherwise flush one
|
|
161
|
+
//more, entirely blank row after the real data
|
|
162
|
+
return rows.filter((cells) => !(cells.length === 1 && cells[0] === ''));
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=Csv.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Csv.js","sourceRoot":"","sources":["../../src/core/Csv.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A named lookup of values, registered once and read back by name - the shape underneath a
|
|
3
|
+
* catalog of factories, handlers, or scene sections, so a game can grow that catalog by
|
|
4
|
+
* registering another entry instead of adding another branch to a hand-written `if`/`switch`.
|
|
5
|
+
*
|
|
6
|
+
* Deliberately does not discover or import anything on its own: a game still writes the
|
|
7
|
+
* import and the `register` call for each entry itself, the same explicit-import style
|
|
8
|
+
* `core`/`two-d` already use throughout - this only replaces the dispatch step after that,
|
|
9
|
+
* not the wiring step before it.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* import { Registry } from '@datamoc/mw_games/core';
|
|
14
|
+
*
|
|
15
|
+
* const commands = new Registry<(args: string[]) => void>();
|
|
16
|
+
* commands.register('heal', (args) => console.log('healing', args[0]));
|
|
17
|
+
*
|
|
18
|
+
* commands.get('heal')(['fireling']); // "healing fireling"
|
|
19
|
+
* commands.get('missing'); // throws: no registration named "missing"
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare class Registry<T> {
|
|
23
|
+
private items;
|
|
24
|
+
/** throws if `name` is already registered - a duplicate is always an authoring error */
|
|
25
|
+
register(name: string, value: T): void;
|
|
26
|
+
get(name: string): T;
|
|
27
|
+
has(name: string): boolean;
|
|
28
|
+
/** every registered name, in registration order */
|
|
29
|
+
list(): string[];
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=Registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Registry.d.ts","sourceRoot":"","sources":["../../src/core/Registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,QAAQ,CAAC,CAAC;IACtB,OAAO,CAAC,KAAK,CAAwB;IAErC,wFAAwF;IACxF,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAGrC;IAED,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,CAInB;IAED,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzB;IAED,mDAAmD;IACnD,IAAI,IAAI,MAAM,EAAE,CAEf;CACD"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A named lookup of values, registered once and read back by name - the shape underneath a
|
|
3
|
+
* catalog of factories, handlers, or scene sections, so a game can grow that catalog by
|
|
4
|
+
* registering another entry instead of adding another branch to a hand-written `if`/`switch`.
|
|
5
|
+
*
|
|
6
|
+
* Deliberately does not discover or import anything on its own: a game still writes the
|
|
7
|
+
* import and the `register` call for each entry itself, the same explicit-import style
|
|
8
|
+
* `core`/`two-d` already use throughout - this only replaces the dispatch step after that,
|
|
9
|
+
* not the wiring step before it.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* import { Registry } from '@datamoc/mw_games/core';
|
|
14
|
+
*
|
|
15
|
+
* const commands = new Registry<(args: string[]) => void>();
|
|
16
|
+
* commands.register('heal', (args) => console.log('healing', args[0]));
|
|
17
|
+
*
|
|
18
|
+
* commands.get('heal')(['fireling']); // "healing fireling"
|
|
19
|
+
* commands.get('missing'); // throws: no registration named "missing"
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export class Registry {
|
|
23
|
+
constructor() {
|
|
24
|
+
this.items = new Map();
|
|
25
|
+
}
|
|
26
|
+
/** throws if `name` is already registered - a duplicate is always an authoring error */
|
|
27
|
+
register(name, value) {
|
|
28
|
+
if (this.items.has(name))
|
|
29
|
+
throw new Error(`"${name}" is already registered`);
|
|
30
|
+
this.items.set(name, value);
|
|
31
|
+
}
|
|
32
|
+
get(name) {
|
|
33
|
+
const value = this.items.get(name);
|
|
34
|
+
if (value === undefined)
|
|
35
|
+
throw new Error(`no registration named "${name}"`);
|
|
36
|
+
return value;
|
|
37
|
+
}
|
|
38
|
+
has(name) {
|
|
39
|
+
return this.items.has(name);
|
|
40
|
+
}
|
|
41
|
+
/** every registered name, in registration order */
|
|
42
|
+
list() {
|
|
43
|
+
return [...this.items.keys()];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=Registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Registry.js","sourceRoot":"","sources":["../../src/core/Registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,OAAO,QAAQ;IAArB;QACS,UAAK,GAAG,IAAI,GAAG,EAAa,CAAC;IAsBtC,CAAC;IApBA,wFAAwF;IACxF,QAAQ,CAAC,IAAY,EAAE,KAAQ;QAC9B,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,IAAI,IAAI,yBAAyB,CAAC,CAAC;QAC7E,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC7B,CAAC;IAED,GAAG,CAAC,IAAY;QACf,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,KAAK,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,GAAG,CAAC,CAAC;QAC5E,OAAO,KAAK,CAAC;IACd,CAAC;IAED,GAAG,CAAC,IAAY;QACf,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,mDAAmD;IACnD,IAAI;QACH,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/B,CAAC;CACD"}
|