package pl.edu.pw.mini.sg.bosansky

import pl.edu.pw.mini.sg.game.deterministic.{AdvanceablePlayerVisibleState, DeterministicGame, PlayerVisibleState}

/**
  * Helper methods for the bosansky method
  * @tparam DM  type of the defender move
  * @tparam AM  type of the attacker move
  * @tparam DS  type of the defender state
  * @tparam AS  type of the attacker state
  * @tparam G   type of the game which the method solves
  */
trait GameUtilsProvider[DM, AM, DS <: PlayerVisibleState[DM], AS <: AdvanceablePlayerVisibleState[AM, AS], G <: DeterministicGame[DM, AM, DS, AS, G]] {
  /**
    * Returns all possible game sequences from a given state. This includes not finished games.
    * @param initialState state from which the game tree is generated
    * @return List of tuples with the game state and attacker and defender sequences (extended to ensure unique moves for different information sets) to reach that state
    */
  def getAllSequences(initialState: G): Stream[(G, List[ExtendedMove[DM, DS]], List[ExtendedMove[AM, AS]])]

  def getNodeFromSequences(initialState: G, defenderSequence: List[ExtendedMove[DM, DS]], attackerSequence: List[ExtendedMove[AM, AS]]): Option[G]

  /**
    * Groups the game sequences into attacker information sets
    * @param sequences  generated game sequences
    * @return Map with one element for each attacker information set (for a given inf. set id it returns a list with all states in the inf. set.
    *         For each state the list contains one tuple with the game state and attacker and defender sequences to reach it.
    */
  def getAttackerInformationSets(sequences: => Stream[(G, List[ExtendedMove[DM, DS]], List[ExtendedMove[AM, AS]])]): Set[InformationSetId[AM, AS]]

  /**
    * Groups the game sequences into defender information sets
    *
    * @param sequences generated game sequences
    * @return Map with one element for each defender information set (for a given inf. set id it returns a list with all states in the inf. set.
    *         For each state the list contains one tuple with the game state and attacker and defender sequences to reach it.
    */
  def getDefenderInformationSets(sequences: => Stream[(G, List[ExtendedMove[DM, DS]], List[ExtendedMove[AM, AS]])]): Set[InformationSetId[DM, DS]]
}
