miaoda-game-roster-core
v0.3.0
Published
Engine-agnostic roster and squad state: uniquely identified unit instances across named capacity/eligibility zones, atomic add/move/swap/remove operations, deterministic cascading merge recipes with payload inheritance, trait-threshold derivation, structu
Maintainers
Readme
miaoda-game-roster-core
Use this engine-independent package for auto-battler boards and benches, squad lineups, reserves, injured lists, garages, or any game where uniquely identified unit instances move between named zones. It enforces ownership, capacity, eligibility, deterministic merges, and validated snapshots; it does not place units on spatial cells.
Install
pnpm add miaoda-game-roster-coreMinimal auto-battler roster
import { Roster } from 'miaoda-game-roster-core';
const roster = new Roster({
definitions: [
{ id: 'guard', tags: ['warrior', 'human'] },
{ id: 'wolf', tags: ['beast'] },
],
zones: [
{ id: 'board', capacity: 6 },
{ id: 'bench', capacity: 8 },
],
recipes: [{
id: 'guard-star',
input: { definitionId: 'guard', rank: 1, count: 3 },
output: { rank: 2 },
}],
mergePayload: ({ anchor }) => ({ ...anchor.payload }),
});
const result = roster.add({
definitionId: 'guard', rank: 1, payload: { hp: 100 }, zoneId: 'bench',
}, { resolveMerges: true });
roster.move(result.ok && result.instance ? result.instance.id : 'u1', 'board');Every instance has a stable id, definitionId, positive integer rank, and game-owned payload. A unit belongs to exactly one zone. add, move, swap, and remove return explicit failure reasons instead of partially applying an operation.
Merges and traits
Recipes run in declaration order and repeat until no recipe matches. Candidates are selected in configured zone and position order; the first candidate is the anchor, so it keeps its instance ID and position while other inputs are consumed. mergePayload decides how the consumed payloads become the output payload.
const traits = roster.traitTiers([
{ id: 'warriors', tag: 'warrior', thresholds: [
{ count: 2, tier: 1 }, { count: 4, tier: 2 },
] },
], { zones: ['board'] });Trait results are derived data only. By default duplicate definitions count once; set countBy: 'instances' when every copy should count. Apply the resulting tier to stats or status in your game.
Save and restore
const snapshot = roster.snapshot();
// Persist snapshot with your save system.
roster.loadSnapshot(snapshot);Snapshots contain zones, instance IDs, ranks, payloads, and generated-ID state. A configuration signature rejects snapshots created with incompatible definitions, zone rules, capacities, or merge recipes. The signature is a compatibility check, not an authenticity or anti-cheat mechanism; use a trusted server or cryptographic save layer when needed.
Public API
Roster is the runtime entry point. Public types include RosterDefinition, RosterZoneDefinition, RosterInstance, MergeRecipe, TraitRule, RosterEvent, RosterResult, and RosterSnapshot.
Compose board instances with miaoda-game-grid-core or miaoda-game-grid-piece-core when you also need movement or collision on a grid. This package does not own combat, balance, or rendering.
