diff --git a/src/samples/slay-the-spire-like/system/progress/encounter.ts b/src/samples/slay-the-spire-like/system/progress/encounter.ts index 57ea484..f3ff8eb 100644 --- a/src/samples/slay-the-spire-like/system/progress/encounter.ts +++ b/src/samples/slay-the-spire-like/system/progress/encounter.ts @@ -1,11 +1,9 @@ -import type { PointCrawlMap, MapNode } from '../map/types'; +import type { PointCrawlMap } from '../map/types'; import type { CombatState, EnemyEntity, PlayerEntity, EffectTable } from '../combat/types'; import type { EncounterData, EnemyData, EffectData, IntentData } from '../types'; -import type { RunState, GameItemMeta } from './types'; -import type { GridInventory } from '../grid-inventory/types'; +import type { RunState } from './types'; import { generateDeckFromInventory } from '../deck/factory'; import { ReadonlyRNG } from '@/utils/rng'; -import { createRegion } from '@/core/region'; // -- Encounter assignment to nodes -- @@ -77,10 +75,8 @@ export function assignAllEncounters( export function buildCombatState( encounter: EncounterData, runState: RunState, - intentPool: IntentData[] = [] ): CombatState { - const intentIndex = buildIntentIndex(intentPool); - const enemies = createEnemyEntities(encounter, intentIndex); + const enemies = createEnemyEntities(encounter); const deck = generateDeckFromInventory(runState.inventory); const player = createPlayerEntity(runState, deck); @@ -95,47 +91,33 @@ export function buildCombatState( }; } -/** - * Builds an index of intents by their ID for fast lookup. - */ -function buildIntentIndex(intentPool: IntentData[]): Map { - const index = new Map(); - for (const intent of intentPool) { - index.set(intent.id, intent); - } - return index; -} - /** * Creates EnemyEntity instances from encounter enemy definitions. - * Each enemy gets: initial HP from enemy data, initial buffs from encounter, intents from enemy definition. + * Each enemy gets: HP from encounter tuple, initial buffs from encounter, intents from enemy definition. */ export function createEnemyEntities( encounter: EncounterData, - intentIndex: Map ): EnemyEntity[] { const enemies: EnemyEntity[] = []; let instanceCounter = 0; - for (const [enemyData, count, encounterBuffs] of encounter.enemies) { - for (let i = 0; i < count; i++) { - const instanceId = `${enemyData.id}-${instanceCounter++}`; - const intents = buildIntentMap(enemyData, intentIndex); - const initialIntentId = findInitialIntent(enemyData, intentIndex); - const effects = buildEffectTable(encounterBuffs); + for (const [enemyData, hp, encounterBuffs] of encounter.enemies) { + const instanceId = `${enemyData.id}-${instanceCounter++}`; + const intents = buildIntentMap(enemyData); + const initialIntent = findInitialIntent(enemyData); + const effects = buildEffectTable(encounterBuffs); - const entity: EnemyEntity = { - id: instanceId, - enemy: enemyData, - hp: enemyData.hp, - maxHp: enemyData.hp, - isAlive: true, - effects, - intents, - currentIntentId: initialIntentId, - }; - enemies.push(entity); - } + const entity: EnemyEntity = { + id: instanceId, + enemy: enemyData, + hp, + maxHp: hp, + isAlive: true, + effects, + intents, + currentIntent: initialIntent, + }; + enemies.push(entity); } return enemies; @@ -146,14 +128,10 @@ export function createEnemyEntities( */ function buildIntentMap( enemy: EnemyData, - intentIndex: Map ): Record { const intents: Record = {}; - for (const intentId of enemy.intentIds) { - const intent = intentIndex.get(intentId); - if (intent) { - intents[intentId] = intent; - } + for (const intent of enemy.intents) { + intents[intent.id] = intent; } return intents; } @@ -161,18 +139,16 @@ function buildIntentMap( /** * Finds the initial intent ID for an enemy. */ -function findInitialIntent( - enemy: EnemyData, - intentIndex: Map -): string { - for (const intentId of enemy.intentIds) { - const intent = intentIndex.get(intentId); - if (intent?.initialIntent) { - return intentId; +function findInitialIntent(enemy: EnemyData): IntentData { + for (const intent of enemy.intents) { + if (intent.initialIntent) { + return intent; } } - // Fallback: first intent - return enemy.intentIds[0] ?? ''; + if (enemy.intents.length === 0) { + throw new Error(`Enemy "${enemy.id}" has no intents`); + } + return enemy.intents[0]; } /** @@ -191,6 +167,7 @@ function buildEffectTable(buffs: readonly [EffectData, number][]): EffectTable { */ function createPlayerEntity(runState: RunState, deck: ReturnType): PlayerEntity { return { + id: "player", hp: runState.player.currentHp, maxHp: runState.player.maxHp, isAlive: runState.player.currentHp > 0, @@ -224,13 +201,13 @@ export function isCombatEncounter(runState: RunState): boolean { * Starts the encounter at the current node. * Returns the constructed CombatState, or null if no combat encounter. */ -export function startEncounter(runState: RunState, intentPool: IntentData[] = []): CombatState | null { +export function startEncounter(runState: RunState): CombatState | null { const encounter = getCurrentEncounterData(runState); if (!encounter || encounter.enemies.length === 0) { return null; } - return buildCombatState(encounter, runState, intentPool); + return buildCombatState(encounter, runState); } /**