package pl.edu.pw.mini.sg.game.graph.discounting

import pl.edu.pw.mini.sg.game.graph.sud.DeterministicSingleUnitMoveGraphGame
import pl.edu.pw.mini.sg.game.deterministic.DeterministicGame
import scala.inline



final class DiscountingGraphGame (
  override val defenderState: DiscountingGraphGameDefenderState,
  override val attackerState: DiscountingGraphGameAttackerState,
  override val defenderPayoff : Double,
  override val attackerPayoff : Double
) extends DeterministicGame[
  Int, Int, DiscountingGraphGameDefenderState,
  DiscountingGraphGameAttackerState, DiscountingGraphGame
]{
  override def equals(other: Any) : Boolean = other match {
    case game: DiscountingGraphGame => game.defenderState == defenderState && game.attackerState == attackerState && defenderPayoff == game.defenderPayoff && attackerPayoff == game.attackerPayoff
    case _ => false
  }
  import DeterministicSingleUnitMoveGraphGame.NEUTRAL_PAYOFF

  override def hashCode: Int = (defenderState, attackerState, defenderPayoff, attackerPayoff).hashCode()

  override def makeMove(defenderMove: Int, attackerMove: Int): DiscountingGraphGame = {
    @inline def defenderPenalty = defenderState.gameConfig.defenderRoundLoss*(defenderState.timeStep)
    @inline def attackerPenalty = defenderState.gameConfig.attackerRoundLoss*(defenderState.timeStep)

    val nextDS = defenderState.continuation(defenderMove)
    val nextAS = attackerState.continuation(attackerMove)
    if(nextDS.defenderUnit == 0) {
      if(nextDS.positions.contains(nextAS.vertex)) {
        val dp = nextDS.gameConfig.graphConfig.vertexDefenderRewards(nextAS.vertex)-defenderPenalty
        val ap = nextDS.gameConfig.graphConfig.vertexAttackerPenalties(nextAS.vertex)-attackerPenalty
        new DiscountingGraphGame(nextDS.makeFinal, nextAS.makeFinal, dp, ap)
      } else if (nextDS.gameConfig.graphConfig.targets.contains(nextAS.vertex)) {
        val target = nextDS.gameConfig.graphConfig.targets.indexOf(nextAS.vertex)
        val dp = nextDS.gameConfig.graphConfig.targetDefenderPenalties(target)-defenderPenalty
        val ap = nextDS.gameConfig.graphConfig.targetAttackerRewards(target)-attackerPenalty
        new DiscountingGraphGame(nextDS.makeFinal, nextAS.makeFinal, dp, ap)
      } else if (nextDS.gameConfig.graphConfig.rounds <= nextDS.timeStep) {
        new DiscountingGraphGame(nextDS, nextAS, NEUTRAL_PAYOFF-defenderPenalty, NEUTRAL_PAYOFF-attackerPenalty)
      } else {
        new DiscountingGraphGame(nextDS, nextAS, 0, 0)
      }
    } else {
      new DiscountingGraphGame(nextDS, nextAS, 0, 0)
    }
  }
}
