60 lines
1.4 KiB
TypeScript
60 lines
1.4 KiB
TypeScript
import type { DomainEvent } from "./events.js";
|
|
import type { DomainError, Encounter } from "./types.js";
|
|
|
|
interface RetreatTurnSuccess {
|
|
readonly encounter: Encounter;
|
|
readonly events: DomainEvent[];
|
|
}
|
|
|
|
export function retreatTurn(
|
|
encounter: Encounter,
|
|
): RetreatTurnSuccess | DomainError {
|
|
if (encounter.combatants.length === 0) {
|
|
return {
|
|
kind: "domain-error",
|
|
code: "invalid-encounter",
|
|
message: "Cannot retreat turn on an encounter with no combatants",
|
|
};
|
|
}
|
|
|
|
if (encounter.roundNumber === 1 && encounter.activeIndex === 0) {
|
|
return {
|
|
kind: "domain-error",
|
|
code: "no-previous-turn",
|
|
message: "Cannot retreat before the start of the encounter",
|
|
};
|
|
}
|
|
|
|
const previousIndex = encounter.activeIndex;
|
|
const wraps = previousIndex === 0;
|
|
const newIndex = wraps ? encounter.combatants.length - 1 : previousIndex - 1;
|
|
const newRoundNumber = wraps
|
|
? encounter.roundNumber - 1
|
|
: encounter.roundNumber;
|
|
|
|
const events: DomainEvent[] = [
|
|
{
|
|
type: "TurnRetreated",
|
|
previousCombatantId: encounter.combatants[previousIndex].id,
|
|
newCombatantId: encounter.combatants[newIndex].id,
|
|
roundNumber: newRoundNumber,
|
|
},
|
|
];
|
|
|
|
if (wraps) {
|
|
events.push({
|
|
type: "RoundRetreated",
|
|
newRoundNumber,
|
|
});
|
|
}
|
|
|
|
return {
|
|
encounter: {
|
|
combatants: encounter.combatants,
|
|
activeIndex: newIndex,
|
|
roundNumber: newRoundNumber,
|
|
},
|
|
events,
|
|
};
|
|
}
|