Implement the 002-add-combatant feature that adds the possibility to add new combatants to an encounter

This commit is contained in:
Lukas
2026-03-03 23:11:07 +01:00
parent 187f98fc52
commit 0de68100c8
15 changed files with 914 additions and 16 deletions

View File

@@ -0,0 +1,50 @@
import type { DomainEvent } from "./events.js";
import type { CombatantId, DomainError, Encounter } from "./types.js";
export interface AddCombatantSuccess {
readonly encounter: Encounter;
readonly events: DomainEvent[];
}
/**
* Pure function that adds a combatant to the end of an encounter's list.
*
* FR-001: Accepts an Encounter, CombatantId, and name; returns next state + events.
* FR-002: Appends new combatant to end of combatants list.
* FR-004: Rejects empty/whitespace-only names with DomainError.
* FR-005: Does not alter activeIndex or roundNumber.
* FR-006: Events returned as values, not dispatched via side effects.
*/
export function addCombatant(
encounter: Encounter,
id: CombatantId,
name: string,
): AddCombatantSuccess | DomainError {
const trimmed = name.trim();
if (trimmed === "") {
return {
kind: "domain-error",
code: "invalid-name",
message: "Combatant name must not be empty",
};
}
const position = encounter.combatants.length;
return {
encounter: {
combatants: [...encounter.combatants, { id, name: trimmed }],
activeIndex: encounter.activeIndex,
roundNumber: encounter.roundNumber,
},
events: [
{
type: "CombatantAdded",
combatantId: id,
name: trimmed,
position,
},
],
};
}