BattleSessionReplacementPlan.kt

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

/**
 * 单个 side 的替补解析结果。
 *
 * 设计意图:
 * - 显式表达当前 side 是否需要玩家手动替补、是否存在自动替补结果、
 *   以及本轮替补过程中真正发生变化的槽位迁移;
 * - 避免 `BattleSessionReplacementResolver` 在一次循环里同时持有
 *   扫描、选择、执行、记录多种中间变量;
 * - 让后续替补策略或多槽位规则调整时有稳定的数据载体。
 */
internal data class BattleSessionReplacementPlan(
    val sideId: String,
    val beforeActiveUnitIds: List<String>,
    val nextActiveUnitIds: List<String>,
    val requiredOutgoingUnitIds: List<String>,
    val candidateUnitIds: List<String>,
    val slotTransitions: List<BattleSessionSlotTransition>,
) {
    /**
     * 当前 side 是否仍需要人工提交 replacement choice。
     */
    val requiresManualReplacement: Boolean
        get() = requiredOutgoingUnitIds.isNotEmpty() && nextActiveUnitIds == beforeActiveUnitIds && candidateUnitIds.isNotEmpty()

    /**
     * 当前 side 是否已经存在自动替补结果。
     */
    val hasAutomaticReplacement: Boolean
        get() = slotTransitions.isNotEmpty()
}

/**
 * 表示一个 active 槽位上的替换前后单位。
 */
internal data class BattleSessionSlotTransition(
    val outgoingUnitId: String?,
    val incomingUnitId: String?,
)