diff --git a/src/main/kotlin/Main.kt b/src/main/kotlin/Main.kt index 35a1f45..9117584 100644 --- a/src/main/kotlin/Main.kt +++ b/src/main/kotlin/Main.kt @@ -1,14 +1,15 @@ import fr.tvbarthel.mtg.engine.* import fr.tvbarthel.mtg.engine.agent.ConsoleAgent import fr.tvbarthel.mtg.engine.agent.RandomAgent +import fr.tvbarthel.mtg.engine.card.white.Plains import kotlin.random.Random fun main() { val engine = GameEngine() val seed = Random.nextLong() - val player1 = Player(1).apply { repeat(60) { library.add(Card()) } } - val player2 = Player(2).apply { repeat(60) { library.add(Card()) } } + val player1 = Player(1).apply { repeat(60) { library.add(Plains()) } } + val player2 = Player(2).apply { repeat(60) { library.add(Plains()) } } val state = GameState(seed, listOf(player1, player2)) val config = GameConfig(state, mapOf(1 to RandomAgent(), 2 to ConsoleAgent())) diff --git a/src/main/kotlin/fr/tvbarthel/mtg/engine/GameState.kt b/src/main/kotlin/fr/tvbarthel/mtg/engine/GameState.kt index cbba386..6e92f2f 100644 --- a/src/main/kotlin/fr/tvbarthel/mtg/engine/GameState.kt +++ b/src/main/kotlin/fr/tvbarthel/mtg/engine/GameState.kt @@ -3,5 +3,23 @@ package fr.tvbarthel.mtg.engine data class GameState( val seed: Long, val players: List = mutableListOf(), - val turn: Int = 0 -) \ No newline at end of file + var turn: Int = 0, + var startingPlayer: Int = 0, /* index of the starting player */ + var activePlayer: Int = 0 /* index of the current active player */ +) { + + /** + * Used to know if the game has ended or not. + */ + fun isGameOver(): Boolean = players.find { it.health == 0 } != null + + /** + * Retrieve the current active player. + */ + fun activePlayer(): Player = players[activePlayer] + + /** + * Retrieve current non actives players. + */ + fun nonActivePlayers(): List = players.filterIndexed { index, player -> index != activePlayer } +} \ No newline at end of file diff --git a/src/main/kotlin/fr/tvbarthel/mtg/engine/playing/PlayingStage.kt b/src/main/kotlin/fr/tvbarthel/mtg/engine/playing/PlayingStage.kt index 9758197..ffa9264 100644 --- a/src/main/kotlin/fr/tvbarthel/mtg/engine/playing/PlayingStage.kt +++ b/src/main/kotlin/fr/tvbarthel/mtg/engine/playing/PlayingStage.kt @@ -3,12 +3,30 @@ package fr.tvbarthel.mtg.engine.playing import fr.tvbarthel.mtg.engine.Agent import fr.tvbarthel.mtg.engine.GameState import fr.tvbarthel.mtg.engine.Stage +import fr.tvbarthel.mtg.engine.playing.phase.BeginningPhase +import fr.tvbarthel.mtg.engine.playing.phase.CombatPhase +import fr.tvbarthel.mtg.engine.playing.phase.EndingPhase +import fr.tvbarthel.mtg.engine.playing.phase.MainPhase /** * [Stage] which must ensure the opening stage. */ -class PlayingStage : Stage { +class PlayingStage( + val beginningPhase: BeginningPhase = BeginningPhase(), + val mainPhase: MainPhase = MainPhase(), + val combatPhase: CombatPhase = CombatPhase(), + val endingPhase: EndingPhase = EndingPhase() +) : Stage { override fun proceed(agents: Map, state: GameState): GameState { - return state + var tempState: GameState = state + + while (!state.isGameOver()) { + val newTurn = Turn(beginningPhase, mainPhase, combatPhase, endingPhase) + tempState = newTurn.play(agents, tempState) + tempState.activePlayer = (tempState.activePlayer + 1) % tempState.players.size + tempState.turn++ + } + + return tempState } } \ No newline at end of file diff --git a/src/main/kotlin/fr/tvbarthel/mtg/engine/playing/step/DamageStep.kt b/src/main/kotlin/fr/tvbarthel/mtg/engine/playing/step/DamageStep.kt index edd0e4d..42722e3 100644 --- a/src/main/kotlin/fr/tvbarthel/mtg/engine/playing/step/DamageStep.kt +++ b/src/main/kotlin/fr/tvbarthel/mtg/engine/playing/step/DamageStep.kt @@ -11,6 +11,7 @@ import fr.tvbarthel.mtg.engine.Step */ class DamageStep : Step { override fun proceed(agents: Map, state: GameState): GameState { + state.nonActivePlayers().forEach { it.health = 0 } return state } } \ No newline at end of file diff --git a/src/test/kotlin/fr/tvbarthel/mtg/engine/opening/FromHandToBottomLibraryTest.kt b/src/test/kotlin/fr/tvbarthel/mtg/engine/opening/FromHandToBottomLibraryTest.kt index 17d0f20..5826d22 100644 --- a/src/test/kotlin/fr/tvbarthel/mtg/engine/opening/FromHandToBottomLibraryTest.kt +++ b/src/test/kotlin/fr/tvbarthel/mtg/engine/opening/FromHandToBottomLibraryTest.kt @@ -3,6 +3,7 @@ package fr.tvbarthel.mtg.engine.opening import fr.tvbarthel.mtg.engine.Card import fr.tvbarthel.mtg.engine.GameState import fr.tvbarthel.mtg.engine.Player +import fr.tvbarthel.mtg.engine.card.white.Plains import io.kotlintest.shouldThrow import io.kotlintest.specs.StringSpec import io.mockk.MockKAnnotations @@ -29,7 +30,7 @@ class FromHandToBottomLibraryTest : StringSpec() { "given card inside hand when apply then card at bottom of library" { // given player.hand.add(card) - repeat(10) { player.library.add(Card()) } + repeat(10) { player.library.add(Plains()) } val state = GameState(12354890L, listOf(player)) // when @@ -42,7 +43,7 @@ class FromHandToBottomLibraryTest : StringSpec() { "given card not inside hand when apply then exception" { // given - repeat(10) { player.library.add(Card()) } + repeat(10) { player.library.add(Plains()) } val state = GameState(12354890L, listOf(player)) // when diff --git a/src/test/kotlin/fr/tvbarthel/mtg/engine/opening/OpeningStageTest.kt b/src/test/kotlin/fr/tvbarthel/mtg/engine/opening/OpeningStageTest.kt index d825135..68fd2bd 100644 --- a/src/test/kotlin/fr/tvbarthel/mtg/engine/opening/OpeningStageTest.kt +++ b/src/test/kotlin/fr/tvbarthel/mtg/engine/opening/OpeningStageTest.kt @@ -1,6 +1,7 @@ package fr.tvbarthel.mtg.engine.opening import fr.tvbarthel.mtg.engine.* +import fr.tvbarthel.mtg.engine.card.white.Plains import io.kotlintest.TestCase import io.kotlintest.specs.StringSpec import io.mockk.MockKAnnotations @@ -36,10 +37,10 @@ class OpeningStageTest : StringSpec() { MockKAnnotations.init(this) player1 = Player(1) - repeat(60) { player1.library.add(Card()) } + repeat(60) { player1.library.add(Plains()) } player2 = Player(2) - repeat(60) { player2.library.add(Card()) } + repeat(60) { player2.library.add(Plains()) } agents = mapOf(player1.id to agent1, player2.id to agent2) players = mutableListOf(player1, player2) diff --git a/src/test/kotlin/fr/tvbarthel/mtg/engine/playing/PlayingStageTest.kt b/src/test/kotlin/fr/tvbarthel/mtg/engine/playing/PlayingStageTest.kt new file mode 100644 index 0000000..05c59b2 --- /dev/null +++ b/src/test/kotlin/fr/tvbarthel/mtg/engine/playing/PlayingStageTest.kt @@ -0,0 +1,81 @@ +package fr.tvbarthel.mtg.engine.playing + +import fr.tvbarthel.mtg.engine.Agent +import fr.tvbarthel.mtg.engine.GameState +import fr.tvbarthel.mtg.engine.Player +import fr.tvbarthel.mtg.engine.playing.phase.BeginningPhase +import fr.tvbarthel.mtg.engine.playing.phase.CombatPhase +import fr.tvbarthel.mtg.engine.playing.phase.EndingPhase +import fr.tvbarthel.mtg.engine.playing.phase.MainPhase +import io.kotlintest.TestCase +import io.kotlintest.specs.StringSpec +import io.mockk.MockKAnnotations +import io.mockk.every +import io.mockk.impl.annotations.RelaxedMockK +import kotlin.test.assertEquals + +class PlayingStageTest : StringSpec() { + + @RelaxedMockK + lateinit var beginningPhase: BeginningPhase + @RelaxedMockK + lateinit var mainPhase: MainPhase + @RelaxedMockK + lateinit var combatPhase: CombatPhase + + @RelaxedMockK + lateinit var endingPhase: EndingPhase + + @RelaxedMockK + lateinit var agents: Map + + private lateinit var state: GameState + private lateinit var player1: Player + private lateinit var player2: Player + + override fun beforeTest(testCase: TestCase) { + super.beforeTest(testCase) + + player1 = Player(1).apply { health = 20 } + player2 = Player(2).apply { health = 20 } + state = GameState(12354890L, players = listOf(player1, player2)) + + every { beginningPhase.proceed(any(), any()) } returns state + every { mainPhase.proceed(any(), any()) } returns state + every { endingPhase.proceed(any(), any()) } returns state + } + + init { + MockKAnnotations.init(this) + + "given empty state when proceed one turn then active player became second player" { + // given + val gameOverTurn = 0 + every { combatPhase.proceed(any(), any()) } answers { + if (state.turn == gameOverTurn) player1.health = 0 + state + } + + // when + PlayingStage(beginningPhase, mainPhase, combatPhase, endingPhase).proceed(agents, state) + + // then + assertEquals(1, state.activePlayer) + } + + "given empty state when proceed 2 turn then active player became first player" { + // given + val gameOverTurn = 1 + every { combatPhase.proceed(any(), any()) } answers { + if (state.turn == gameOverTurn) player1.health = 0 + state + } + + // when + PlayingStage(beginningPhase, mainPhase, combatPhase, endingPhase).proceed(agents, state) + + // then + assertEquals(0, state.activePlayer) + } + } +} \ No newline at end of file