BattleSessionWinnerResolver.kt
package io.github.lishangbu.avalon.game.battle.engine.core.session
import io.github.lishangbu.avalon.game.battle.engine.core.model.BattleLifecycle
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BattleRuntimeSnapshot
/**
* 胜负判定器。
*
* 设计意图:
* - 收敛“当前还有哪些 side 仍有可战斗单位”与“是否应当结束 battle”
* 这组判定逻辑;
* - 让 replacement resolver 不再同时承担替补与胜负决策两类职责;
* - 便于后续扩展不同 battle 模式下的结束规则。
*/
internal class BattleSessionWinnerResolver(
private val session: BattleSession,
) {
/**
* 根据当前快照更新胜者信息。
*/
fun updateWinnerIfNeeded(snapshot: BattleRuntimeSnapshot): BattleRuntimeSnapshot {
val survivingSideIds =
snapshot.sides.values
.filter { side ->
side.unitIds.any { unitId -> (snapshot.units[unitId]?.currentHp ?: 0) > 0 }
}.map { side -> side.id }
return when {
survivingSideIds.size == 1 -> {
val winnerId = survivingSideIds.single()
session.recordLog("Battle ended. Winner: $winnerId.")
session.recordEvent(BattleSessionBattleEndedPayload(winner = winnerId))
// 这里只负责宣布 battle 已结束,不直接掺入战后资源、副作用结算。
snapshot.copy(
battle =
snapshot.battle.copy(
lifecycle = BattleLifecycle.ENDED_UNSETTLED,
winner = winnerId,
),
)
}
survivingSideIds.isEmpty() -> {
session.recordLog("Battle ended with no surviving sides.")
session.recordEvent(BattleSessionBattleEndedPayload(winner = null))
// 平局同样先进入“已结束待结算”,由上层决定是否还有额外副作用要处理。
snapshot.copy(
battle =
snapshot.battle.copy(
lifecycle = BattleLifecycle.ENDED_UNSETTLED,
winner = null,
),
)
}
else -> {
snapshot
}
}
}
}