1 Commits

Author SHA1 Message Date
Lukas
b39e4923e1 Remove demo combatants and allow empty encounters
All checks were successful
CI / check (push) Successful in 45s
CI / build-image (push) Successful in 28s
Empty encounters are now valid (INV-1 updated). New sessions start
with zero combatants instead of pre-populated Aria/Brak/Cael.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 10:24:26 +01:00
3 changed files with 14 additions and 26 deletions

View File

@@ -22,7 +22,6 @@ import type {
} from "@initiative/domain";
import {
combatantId,
createEncounter,
isDomainError,
creatureId as makeCreatureId,
resolveCreatureName,
@@ -33,24 +32,16 @@ import {
saveEncounter,
} from "../persistence/encounter-storage.js";
function createDemoEncounter(): Encounter {
const result = createEncounter([
{ id: combatantId("1"), name: "Aria" },
{ id: combatantId("2"), name: "Brak" },
{ id: combatantId("3"), name: "Cael" },
]);
if (isDomainError(result)) {
throw new Error(`Failed to create demo encounter: ${result.message}`);
}
return result;
}
const EMPTY_ENCOUNTER: Encounter = {
combatants: [],
activeIndex: 0,
roundNumber: 1,
};
function initializeEncounter(): Encounter {
const stored = loadEncounter();
if (stored !== null) return stored;
return createDemoEncounter();
return EMPTY_ENCOUNTER;
}
function deriveNextId(encounter: Encounter): number {

View File

@@ -169,9 +169,9 @@ describe("advanceTurn", () => {
});
describe("invariants", () => {
it("INV-1: createEncounter rejects empty combatant list", () => {
it("INV-1: createEncounter accepts empty combatant list", () => {
const result = createEncounter([]);
expect(isDomainError(result)).toBe(true);
expect(isDomainError(result)).toBe(false);
});
it("INV-2: activeIndex always in bounds across all scenarios", () => {

View File

@@ -38,8 +38,8 @@ function domainError(code: string, message: string): DomainError {
/**
* Creates a valid Encounter, enforcing INV-1, INV-2, INV-3.
* - INV-1: At least one combatant required.
* - INV-2: activeIndex defaults to 0 (always in bounds).
* - INV-1: An encounter MAY have zero combatants.
* - INV-2: activeIndex defaults to 0 (always in bounds when combatants exist).
* - INV-3: roundNumber defaults to 1 (positive integer).
*/
export function createEncounter(
@@ -47,13 +47,10 @@ export function createEncounter(
activeIndex = 0,
roundNumber = 1,
): Encounter | DomainError {
if (combatants.length === 0) {
return domainError(
"invalid-encounter",
"An encounter must have at least one combatant",
);
}
if (activeIndex < 0 || activeIndex >= combatants.length) {
if (
combatants.length > 0 &&
(activeIndex < 0 || activeIndex >= combatants.length)
) {
return domainError(
"invalid-encounter",
`activeIndex ${activeIndex} out of bounds for ${combatants.length} combatants`,