import type { SquadComposition, SquadRole } from "../../combat/squadTactics.js"; import type { Vec3 } from "../../world/geometry.js"; /** * The five duties a fighter can be given in a fight. A duty is *who does what*; the squad role a * game dials (range, angles, fire discipline) is *how that duty fights* and stays content. */ export type FightIntent = "retreat" | "hold" | "flank" | "cover" | "assault"; /** One fighter the director can order, with the state the decision reads. */ export interface FighterState { id: string; /** Position on the ground plane; only `x` and `z` are read. */ position: Vec3; /** Health fraction `0..1`. */ health: number; /** True while the fighter is taking fire this tick. */ underFire?: boolean; } /** The squad as it stands and the enemy it is facing, or no enemy at all. */ export interface FightSituation { fighters: readonly FighterState[]; /** Where the squad last knew the enemy to be, or null when it has no contact. */ threat: Vec3 | null; /** Health fraction at or below which a fighter falls back. Default `0.25`. */ retreatBelow?: number; } /** What the director decided, per fighter, and why. */ export interface FightOrders { /** Duty per fighter id. Every fighter in the situation appears exactly once. */ intents: Map; /** How many fighters took each duty, for a HUD or a test. */ counts: Record; /** One line naming the terms that drove the split. */ reason: string; } /** * Assign each fighter a duty from the squad's own state — who is hurt, who is under fire, and who * already stands on the outside of the formation — never from an authored order or a spawn index. * * Rules, applied in this order: * 1. A fighter at or below `retreatBelow` health falls back (`retreat`). * 2. With no known enemy the rest advance (`assault`); there is nothing to hold, flank or hide from. * 3. Against a known enemy one fighter holds the line: the healthiest fighter closest to the * squad's centre, ties broken by id, so the anchor is the one already standing there. * 4. A third of what is left flanks, taken from the outside of the formation, alternating sides so * a squad never stacks its flankers on one shoulder. Under fire disqualifies a flanker. * 5. Everyone else fights from cover, which is where `createSquadCombat` puts them anyway. * * Deterministic: same situation, same orders, and input order does not change a duty. * * @capability fight-intents assign hold, flank, cover, assault and retreat duties from live squad state */ export declare function assignFightIntents(situation: FightSituation): FightOrders; /** * Turn duties into a squad composition `createSquadCombat` accepts: one slot per fighter, in the * order the game gives its members, each mapped to the role that game dials for the duty. Build it * through `composition` so squad combat executes the director's assignment instead of its own * static list. * * @capability fight-intent-composition map assigned duties onto a squad combat composition in member order */ export declare function compositionForIntents(order: readonly string[], intents: ReadonlyMap, roleFor: (intent: FightIntent) => SquadRole): SquadComposition;