BattleSessionTargetingSupport.kt
package io.github.lishangbu.avalon.game.battle.engine.core.session.target
import io.github.lishangbu.avalon.game.battle.engine.core.model.SideState
/**
* BattleSession 目标模型辅助组件。
*
* 设计意图:
* - 把 `data.target` 到内部目标模式的映射集中管理。
* - 提供当前会话快照下的可选目标计算逻辑。
*/
object BattleSessionTargetingSupport {
fun resolveMode(rawTarget: String?): BattleSessionTargetMode =
when (rawTarget) {
null -> BattleSessionTargetMode.UNKNOWN
"self", "user" -> BattleSessionTargetMode.SELF
"ally" -> BattleSessionTargetMode.ALLY
"selected-pokemon", "random-opponent" -> BattleSessionTargetMode.FOE
"all-opponents" -> BattleSessionTargetMode.ALL_FOES
"all-allies", "user-and-allies", "user-or-ally" -> BattleSessionTargetMode.ALL_ALLIES
"all-other-pokemon" -> BattleSessionTargetMode.ALL_OTHER_POKEMON
"all-pokemon", "entire-field" -> BattleSessionTargetMode.ALL_POKEMON
"users-field" -> BattleSessionTargetMode.SIDE
"opponents-field" -> BattleSessionTargetMode.FOE_SIDE
else -> BattleSessionTargetMode.UNKNOWN
}
fun availableTargetUnitIds(
mode: BattleSessionTargetMode,
actorUnitId: String,
sides: Collection<SideState>,
): List<String> {
val actorSide =
requireNotNull(sides.firstOrNull { side -> actorUnitId in side.activeUnitIds }) {
"Actor unit '$actorUnitId' is not currently active."
}
val foeSides = sides.filterNot { side -> side.id == actorSide.id }
val foeActive = foeSides.flatMap(SideState::activeUnitIds)
val allActive = sides.flatMap(SideState::activeUnitIds)
return when (mode) {
BattleSessionTargetMode.SELF -> listOf(actorUnitId)
BattleSessionTargetMode.ALLY -> actorSide.activeUnitIds.filterNot { unitId -> unitId == actorUnitId }
BattleSessionTargetMode.FOE -> foeActive
BattleSessionTargetMode.ALL_ALLIES -> actorSide.activeUnitIds
BattleSessionTargetMode.ALL_FOES -> foeActive
BattleSessionTargetMode.ALL_OTHER_POKEMON -> allActive.filterNot { unitId -> unitId == actorUnitId }
BattleSessionTargetMode.ALL_POKEMON -> allActive
BattleSessionTargetMode.SIDE -> actorSide.activeUnitIds
BattleSessionTargetMode.FOE_SIDE -> foeActive
BattleSessionTargetMode.FIELD -> emptyList()
BattleSessionTargetMode.UNKNOWN -> allActive
}
}
fun requiresExplicitTarget(mode: BattleSessionTargetMode): Boolean =
when (mode) {
BattleSessionTargetMode.SELF,
BattleSessionTargetMode.ALL_ALLIES,
BattleSessionTargetMode.ALL_FOES,
BattleSessionTargetMode.ALL_OTHER_POKEMON,
BattleSessionTargetMode.ALL_POKEMON,
BattleSessionTargetMode.SIDE,
BattleSessionTargetMode.FOE_SIDE,
BattleSessionTargetMode.FIELD,
-> false
BattleSessionTargetMode.ALLY,
BattleSessionTargetMode.FOE,
BattleSessionTargetMode.UNKNOWN,
-> true
}
}