DefaultReplacementStrategy.kt

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

import io.github.lishangbu.avalon.game.battle.engine.core.model.SideState
import io.github.lishangbu.avalon.game.battle.engine.core.model.UnitState

/**
 * 默认替补策略。
 *
 * 设计意图:
 * - 维持当前最小 session 的行为不变。
 * - 当 active 单位倒下,或被 `forceSwitchMutation` 标记为必须换下后,
 *   按 `side.unitIds` 顺序选择第一个仍存活的 bench 顶上。
 */
class DefaultReplacementStrategy : ReplacementStrategy {
    override fun selectActiveUnitIds(
        side: SideState,
        units: Map<String, UnitState>,
    ): List<String> {
        val activeIds = side.activeUnitIds
        val replaceRequiredIds =
            activeIds.filter { unitId ->
                val unit = units[unitId]
                (unit?.currentHp ?: 0) <= 0 || unit?.forceSwitchRequested == true
            }
        if (replaceRequiredIds.isEmpty()) {
            return activeIds
        }

        val remainingBench =
            side.unitIds
                .filterNot { unitId -> unitId in activeIds }
                .filter { unitId -> (units[unitId]?.currentHp ?: 0) > 0 }
                .toMutableList()

        val rebuiltActive = activeIds.toMutableList()
        replaceRequiredIds.forEach { outgoingUnitId ->
            val index = rebuiltActive.indexOf(outgoingUnitId)
            if (index >= 0) {
                rebuiltActive.removeAt(index)
                if (remainingBench.isNotEmpty()) {
                    rebuiltActive.add(index, remainingBench.removeAt(0))
                }
            }
        }
        return rebuiltActive
    }
}