BattleSettlementPlanner.kt

package io.github.lishangbu.avalon.game.battle.engine.application

import io.github.lishangbu.avalon.game.battle.engine.core.model.BattleType
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionQuery

/**
 * 引擎内部的结算计划生成器。
 *
 * 设计意图:
 * - 根据不同 battle type 规划出战后必须执行的标准任务;
 * - 保持“是否需要捕捉账本结算”这类 battle 规则判断留在引擎,而不是散落在 game 层。
 */
interface BattleSettlementPlanner {
    fun supports(battleKind: BattleType): Boolean

    fun buildPlan(
        sessionId: String,
        session: BattleSessionQuery,
    ): BattleSettlementPlan
}

/**
 * trainer / pvp / dungeon 共用的标准结算规划。
 */
class StandardBattleSettlementPlanner : BattleSettlementPlanner {
    override fun supports(battleKind: BattleType): Boolean = battleKind == BattleType.TRAINER || battleKind == BattleType.PVP || battleKind == BattleType.DUNGEON

    override fun buildPlan(
        sessionId: String,
        session: BattleSessionQuery,
    ): BattleSettlementPlan =
        BattleSettlementPlan(
            sessionId = sessionId,
            battleKind = session.snapshot.battle.battleKind,
            endedReason = session.snapshot.battle.endedReason,
            session = session,
            tasks =
                if (session.snapshot.battle.lifecycle
                        .isSettled()
                ) {
                    emptyList()
                } else {
                    listOf(BattleSettlementTask.MARK_SESSION_SETTLED)
                },
        )
}

/**
 * wild battle 的结算规划。
 *
 * 与普通 battle 相比,wild battle 需要先处理捕捉账本,再把 session 标记为已结算。
 */
class WildBattleSettlementPlanner : BattleSettlementPlanner {
    override fun supports(battleKind: BattleType): Boolean = battleKind == BattleType.WILD

    override fun buildPlan(
        sessionId: String,
        session: BattleSessionQuery,
    ): BattleSettlementPlan =
        BattleSettlementPlan(
            sessionId = sessionId,
            battleKind = session.snapshot.battle.battleKind,
            endedReason = session.snapshot.battle.endedReason,
            session = session,
            tasks =
                if (session.snapshot.battle.lifecycle
                        .isSettled()
                ) {
                    emptyList()
                } else {
                    listOf(
                        BattleSettlementTask.SETTLE_CAPTURE_LEDGER,
                        BattleSettlementTask.MARK_SESSION_SETTLED,
                    )
                },
        )
}