BattleSessionReplacementResolver.kt

package io.github.lishangbu.avalon.game.battle.engine.core.session

/**
 * 负责濒死替补与胜负结算。
 *
 * 这是 `BattleSession` 里另一段很容易膨胀的逻辑:
 * - 检查 active 单位是否倒下
 * - 计算自动替补
 * - 生成待处理替补请求
 * - 更新最终胜者
 */
internal class BattleSessionReplacementResolver(
    private val session: BattleSession,
) {
    private val replacementPlanResolver: BattleSessionReplacementPlanResolver =
        BattleSessionReplacementPlanResolver(session.replacementStrategy)
    private val autoReplacementExecutor: BattleSessionAutoReplacementExecutor =
        BattleSessionAutoReplacementExecutor(session)
    private val winnerResolver: BattleSessionWinnerResolver = BattleSessionWinnerResolver(session)

    /**
     * 在给定快照上完成“濒死检查 + 自动替补 + 待替补请求 + 胜负更新”。
     *
     * @param snapshot 要处理的快照,默认使用会话当前快照
     * @return 处理后的快照
     */
    fun resolveFaintAndReplacement(snapshot: io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BattleRuntimeSnapshot = session.currentSnapshot): io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BattleRuntimeSnapshot {
        var nextSnapshot = session.processFaintHooks(snapshot)
        session.replacementRequests.clear()

        nextSnapshot.sides.forEach { (sideId, side) ->
            val currentUnits = nextSnapshot.units
            val plan = replacementPlanResolver.resolve(sideId, side, currentUnits)
            if (plan.requiresManualReplacement) {
                session.replacementRequests +=
                    BattleSessionReplacementRequest(
                        sideId = plan.sideId,
                        outgoingUnitIds = plan.requiredOutgoingUnitIds,
                        candidateUnitIds = plan.candidateUnitIds,
                    )
                return@forEach
            }
            nextSnapshot = autoReplacementExecutor.execute(nextSnapshot, plan)
        }

        return updateWinnerIfNeeded(nextSnapshot)
    }

    /**
     * 根据仍有可战斗单位的 side 计算胜者。
     *
     * @param snapshot 待判定的快照
     * @return 已更新胜者信息的快照
     */
    fun updateWinnerIfNeeded(snapshot: io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BattleRuntimeSnapshot): io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BattleRuntimeSnapshot = winnerResolver.updateWinnerIfNeeded(snapshot)
}