import { type Creature, type CreatureId, calculateInitiative, type DomainError, type DomainEvent, isDomainError, rollInitiative, setInitiative, } from "@initiative/domain"; import type { EncounterStore } from "./ports.js"; export interface RollAllResult { events: DomainEvent[]; skippedNoSource: number; } export function rollAllInitiativeUseCase( store: EncounterStore, rollDice: () => number, getCreature: (id: CreatureId) => Creature | undefined, ): RollAllResult | DomainError { let encounter = store.get(); const allEvents: DomainEvent[] = []; let skippedNoSource = 0; for (const combatant of encounter.combatants) { if (!combatant.creatureId) continue; if (combatant.initiative !== undefined) continue; const creature = getCreature(combatant.creatureId); if (!creature) { skippedNoSource++; continue; } const { modifier } = calculateInitiative({ dexScore: creature.abilities.dex, cr: creature.cr, initiativeProficiency: creature.initiativeProficiency, }); const value = rollInitiative(rollDice(), modifier); if (isDomainError(value)) { return value; } const result = setInitiative(encounter, combatant.id, value); if (isDomainError(result)) { return result; } encounter = result.encounter; allEvents.push(...result.events); } store.save(encounter); return { events: allEvents, skippedNoSource }; }