SideMutationStateApplier.kt
package io.github.lishangbu.avalon.game.battle.engine.core.runtime.apply
import io.github.lishangbu.avalon.game.battle.engine.core.model.AttachedEffectState
import io.github.lishangbu.avalon.game.battle.engine.core.model.SideState
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.ApplySideConditionMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.RemoveSideConditionMutation
import io.github.lishangbu.avalon.game.battle.engine.core.type.StandardTargetSelectorIds
/**
* side 级 mutation 写回助手。
*/
internal object SideMutationStateApplier {
fun applyAddSideCondition(
mutation: ApplySideConditionMutation,
context: MutationApplicationContext,
sides: Map<String, SideState>,
): Map<String, SideState> =
updateSideTargets(mutation.target, context, sides) { side ->
val existingState = side.conditionStates[mutation.conditionEffectId]
val nextOrder =
existingState?.effectOrder
?: ((side.conditionStates.values.maxOfOrNull(AttachedEffectState::effectOrder) ?: 0) + 1)
val nextState =
AttachedEffectState(
effectId = mutation.conditionEffectId,
sourceId = mutation.sourceId,
duration = mutation.duration,
effectOrder = nextOrder,
)
side.copy(
conditionStates = side.conditionStates + (mutation.conditionEffectId to nextState),
)
}
fun applyRemoveSideCondition(
mutation: RemoveSideConditionMutation,
context: MutationApplicationContext,
sides: Map<String, SideState>,
): Map<String, SideState> =
updateSideTargets(mutation.target, context, sides) { side ->
side.copy(conditionStates = side.conditionStates - mutation.conditionEffectId)
}
private fun updateSideTargets(
selector: io.github.lishangbu.avalon.game.battle.engine.core.type.TargetSelectorId,
context: MutationApplicationContext,
sides: Map<String, SideState>,
transform: (SideState) -> SideState,
): Map<String, SideState> {
val targetSideIds =
when (selector) {
StandardTargetSelectorIds.SIDE -> listOfNotNull(context.side?.id)
StandardTargetSelectorIds.FOE_SIDE -> listOfNotNull(context.foeSide?.id)
else -> error("Unsupported side condition target selector '${selector.value}'.")
}
if (targetSideIds.isEmpty()) {
return sides
}
val nextSides = sides.toMutableMap()
targetSideIds.forEach { sideId ->
val side = requireNotNull(nextSides[sideId]) { "Target side '$sideId' was not found." }
nextSides[sideId] = transform(side)
}
return nextSides
}
}