From 90111f15f42d3d0530fe41c2e90f9705e8e531e5 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Tue, 17 Oct 2023 11:26:53 +0200 Subject: [PATCH] tests rewrite to munit WIP --- .../src/test/scala/AntichessVariantTest.scala | 464 ++++++++---------- .../src/test/scala/AtomicVariantTest.scala | 6 +- test-kit/src/test/scala/BoardTest.scala | 6 +- test-kit/src/test/scala/Chess960Test.scala | 2 +- test-kit/src/test/scala/ChessTest.scala | 8 +- test-kit/src/test/scala/HashTest.scala | 24 +- .../src/test/scala/HordeVariantTest.scala | 300 +++++------ .../test/scala/RacingKingsVariantTest.scala | 14 +- test-kit/src/test/scala/ReplayTest.scala | 6 +- test-kit/src/test/scala/SituationTest.scala | 10 +- .../src/test/scala/perft/FullPerftTest.scala | 88 ++-- 11 files changed, 410 insertions(+), 518 deletions(-) diff --git a/test-kit/src/test/scala/AntichessVariantTest.scala b/test-kit/src/test/scala/AntichessVariantTest.scala index 9abaa08f..713c86bb 100644 --- a/test-kit/src/test/scala/AntichessVariantTest.scala +++ b/test-kit/src/test/scala/AntichessVariantTest.scala @@ -7,7 +7,7 @@ import chess.format.{ EpdFen, Fen } import chess.format.pgn.Reader import chess.variant.Antichess -class AntichessVariantTest extends ChessSpecs: +class AntichessVariantTest extends ChessTest: // Random PGN taken from FICS val fullGame = @@ -50,271 +50,213 @@ Ne5 {[%emt 0.364]} 30. Rxc8 {[%emt 0.469]} Nc4 {[%emt 0.201]} 31. Rxc4 {[%emt 1. b5 {[%emt 0.223]} 32. Rxd4 {[%emt 0.359]} b4 {[%emt 0.202]} 33. Rxb4 {[%emt 0.500]} g4 {[%emt 0.200]} 34. Rxg4 {[%emt 0.172]} 0-1""" - "Antichess " should: - - "Allow an opening move for white taking into account a player may move without taking if possible" in: - val startingPosition = Game(Antichess) - val afterFirstMove = startingPosition.playMove(Square.E2, Square.E4, None) - - afterFirstMove must beRight.like { newGame => - val fen = Fen write newGame - fen mustEqual EpdFen("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b - - 0 1") - } - - "Not allow a player to make a non capturing move if a capturing move is available" in: - val game = Game(Antichess) - val gameAfterOpening = game.playMoves((Square.E2, Square.E4), (Square.F7, Square.F5)) - - val invalidGame = gameAfterOpening flatMap (_.playMove(Square.H2, Square.H4)) - - invalidGame must beLeft("Piece on h2 cannot move to h4") - - "A situation in antichess should only present the capturing moves if the player can capture" in: - val game = Game(Antichess) - val gameAfterOpening = game.playMoves((Square.E2, Square.E4), (Square.F7, Square.F5)) - - gameAfterOpening must beRight.like { case newGame => - newGame.situation.legalMoves.size must beEqualTo(1) - newGame.situation.legalMoves.exists(_.captures == false) must beEqualTo(false) - } - - "Allow a capturing move to be made" in: - val game = - Game(Antichess).playMoves((Square.E2, Square.E4), (Square.F7, Square.F5), (Square.E4, Square.F5)) - game must beRight - - "Not permit a player to castle" in: - // Castling is not allowed in antichess - val game = Game(Antichess).playMoves( - (Square.E2, Square.E4), - (Square.E7, Square.E5), - (Square.F1, Square.E2), - (Square.G8, Square.H6), - (Square.G1, Square.H3) - ) - - val possibleDestinations = - game flatMap (_.board.destsFrom(Square.E1).toRight("king has no destinations")) - - possibleDestinations must beRight.like { case dests => - // G1 (to castle) should not be a valid destination - dests must beEqualTo(List(Square.F1)) - } - - "Not allow a king to be put into check" in: - val game = Game(Antichess).playMoves( + test("Allow an opening move for white taking into account a player may move without taking if possible"): + val startingPosition = Game(Antichess) + val newGame = startingPosition.playMove(Square.E2, Square.E4, None).get + val fen = Fen write newGame + assertEquals(fen, EpdFen("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b - - 0 1")) + + test("Not allow a player to make a non capturing move if a capturing move is available"): + val game = Game(Antichess) + val gameAfterOpening = game.playMoves((Square.E2, Square.E4), (Square.F7, Square.F5)) + val invalidGame = gameAfterOpening.flatMap(_.playMove(Square.H2, Square.H4)) + assertEquals(invalidGame, Left(ErrorStr("Piece on h2 cannot move to h4"))) + + test("A situation in antichess should only present the capturing moves if the player can capture"): + val game = Game(Antichess).playMoves((Square.E2, Square.E4), (Square.F7, Square.F5)).get + assertEquals(game.situation.legalMoves.size, 1) + assertNot(game.situation.legalMoves.exists(_.captures == false)) + + test("Allow a capturing move to be made"): + val game = + Game(Antichess).playMoves((Square.E2, Square.E4), (Square.F7, Square.F5), (Square.E4, Square.F5)) + assert(game.isRight) + + test("Not permit a player to castle"): + // Castling is not allowed in antichess + val game = Game(Antichess).playMoves( + (Square.E2, Square.E4), + (Square.E7, Square.E5), + (Square.F1, Square.E2), + (Square.G8, Square.H6), + (Square.G1, Square.H3) + ) + val possibleDestinations = + game.flatMap(_.board.destsFrom(Square.E1).toRight("king has no destinations")) + assertEquals(possibleDestinations.get, List(Square.F1)) + + test("Not allow a king to be put into check"): + val game = Game(Antichess) + .playMoves( Square.E2 -> Square.E4, Square.E7 -> Square.E5, Square.D1 -> Square.H5 ) + .get + assertEquals(game.situation.check, Check.No) - game must beRight.like { newGame => - newGame.situation.check === Check.No - } - - "Allow kings to be captured" in: - val game = Game(Antichess).playMoves( + test("Allow kings to be captured"): + val game = Game(Antichess) + .playMoves( Square.E2 -> Square.E4, Square.E7 -> Square.E5, Square.D1 -> Square.H5, Square.F7 -> Square.F6, Square.H5 -> Square.E8 ) + .get + assert(game.board.kingOf(Color.black).isEmpty) - game must beRight.like { case newGame => - newGame.board.kingOf(Color.black).isEmpty - } - - "Not allow a king to be check mated" in: - val game = Game(Antichess).playMoves( + test("Not allow a king to be check mated"): + val game = Game(Antichess) + .playMoves( Square.F2 -> Square.F3, Square.E7 -> Square.E6, Square.G2 -> Square.G4, Square.D8 -> Square.H4 ) + .get + assertNot(game.situation.checkMate) + + test("Allow a pawn to be promoted to a king"): + val position = EpdFen("8/5P2/8/2b5/8/8/4B3/8 w - -") + val game = fenToGame(position, Antichess) + val newGame = game(Square.F7, Square.F8, Option(King)).get._1 + assertEquals(newGame.board(Square.F8), Option(White - King)) + + test("deal with 2 white kings"): + val position = EpdFen("K3k1nr/p2q2pp/p2p1p2/8/2PP4/8/PP4PP/RNBQK1NR w - - 0 11") + val game = fenToGame(position, Antichess) + assertEquals(game.situation.destinations, Map(Square.A8 -> Square.A7.bb)) + + test("Be drawn when there are only opposite colour bishops remaining"): + val position = EpdFen("8/2b5/8/8/8/6Q1/4B3/8 b - -") + val game = fenToGame(position, Antichess)(Square.C7, Square.G3, None).get._1 + assert(game.situation.end) + assert(game.situation.autoDraw) + assertEquals(game.situation.winner, None) + assertEquals(game.situation.status, Some(Status.Draw)) + + test("Be drawn on multiple bishops on the opposite color"): + val position = EpdFen("8/6P1/8/8/1b6/8/8/5B2 w - -") + val game = fenToGame(position, Antichess)(Square.G7, Square.G8, Bishop.some).get._1 + assert(game.situation.end) + assert(game.situation.autoDraw) + assertEquals(game.situation.winner, None) + assertEquals(game.situation.status, Some(Status.Draw)) + + test("Not be drawn when the black and white bishops are on the same coloured squares "): + val position = EpdFen("7b/8/1p6/8/8/8/5B2/8 w - -") + val game = fenToGame(position, Antichess)(Square.F2, Square.B6, None).get._1 + assertNot(game.situation.end) + assertNot(game.situation.autoDraw) + assertEquals(game.situation.winner, None) + + test( + "Be drawn when there are only opposite colour bishops and pawns which could not attack those bishops remaining" + ): + val position = EpdFen("8/6p1/4B1P1/4p3/4P3/8/2p5/8 b - - 1 28") + val game = fenToGame(position, Antichess)(Square.C2, Square.C1, Option(Bishop)).get._1 + assert(game.situation.end) + assert(game.situation.autoDraw) + assertEquals(game.situation.status, Some(Status.Draw)) + + test("Not be drawn on opposite color bishops but with pawns that could be forced to attack a bishop"): + val position = EpdFen("8/6p1/1B4P1/4p3/4P3/8/3p4/8 b - -") + val game = fenToGame(position, Antichess)(Square.D2, Square.D1, Option(Bishop)).get._1 + assertNot(game.situation.end) + assertNot(game.situation.autoDraw) + assertEquals(game.situation.winner, None) + + test("Not be drawn where a white bishop can attack a black pawn in an almost closed position"): + val position = EpdFen("5b2/1P4p1/4B1P1/4p3/4P3/8/8/8 w - -") + val game = fenToGame(position, Antichess)(Square.B7, Square.B8, Bishop.some).get._1 + assertNot(game.situation.end) + assertNot(game.situation.autoDraw) + assertEquals(game.situation.winner, None) + + test("Not be drawn where a pawn is unattackable, but is blocked by a bishop, not a pawn"): + val position = EpdFen("8/8/4BbP1/4p3/4P3/8/8/8 b - -") + val game = fenToGame(position, Antichess).playMoves(Square.F6 -> Square.G7).get + assertNot(game.situation.end) + assertNot(game.situation.autoDraw) + assertEquals(game.situation.status, None) + + test("Opponent has insufficient material when there are only two remaining knights on same color squares"): + val position = EpdFen("8/8/3n2N1/8/8/8/8/8 w - -") + val game = fenToGame(position, Antichess).playMoves(Square.G6 -> Square.F4).get + assert(game.situation.opponentHasInsufficientMaterial) + + test( + "Opponent has sufficient material when there are only two remaining knights on opposite color squares" + ): + val position = EpdFen("7n/8/8/8/8/8/8/N7 w - -") + val game = fenToGame(position, Antichess) + + val newGame = game flatMap (_.playMoves(Square.A1 -> Square.B3)) + + newGame must beRight.like: + _.situation.opponentHasInsufficientMaterial must beFalse + + test("Not be drawn on insufficient mating material"): + val position = EpdFen("4K3/8/1b6/8/8/8/5B2/3k4 b - -") + val maybeGame = fenToGame(position, Antichess) + + maybeGame must beRight.like { case game => + game.situation.end must beFalse + } + + test("Be drawn on a three move repetition"): + val game = Game(Antichess) + + val moves = + List((Square.G1, Square.F3), (Square.G8, Square.F6), (Square.F3, Square.G1), (Square.F6, Square.G8)) + val repeatedMoves: List[(Square, Square)] = List.fill(3)(moves).flatten + + val drawnGame = game.playMoveList(repeatedMoves) + + drawnGame must beRight.like { case g => + g.situation.threefoldRepetition must beTrue + } + + test("Successfully play through a full game until one player loses all their pieces"): + val game = Reader.full(fullGame) + + game must beRight.like { case Reader.Result.Complete(replay) => + val game = replay.state + + game.situation.end must beTrue + + // In antichess, the player who has just lost all their pieces is the winner + game.situation.winner must beSome(Black) + } + + test("Win on a traditional stalemate where the player has no valid moves"): + val position = EpdFen("8/p7/8/P7/8/8/8/8 w - -") + val maybeGame = fenToGame(position, Antichess) + + val drawnGame = maybeGame flatMap (_.playMoves((Square.A5, Square.A6))) + + drawnGame must beRight.like { case game => + game.situation.end must beTrue + game.situation.winner must beSome(Black) + } + + test("Stalemate is a win - second test"): + val fen = EpdFen("2Q5/8/p7/8/8/8/6PR/8 w - -") + val maybeGame = fenToGame(fen, Antichess) + + val drawnGame = maybeGame flatMap (_.playMoves((Square.C8, Square.A6))) + + drawnGame must beRight.like { case game => + game.situation.end must beTrue + game.situation.status must beSome(Status.VariantEnd) + game.situation.winner must beSome(Black) + } + + test("two kings on replay"): - game must beRight.like { case newGame => - newGame.situation.checkMate must beFalse - } - - "Allow a pawn to be promoted to a king" in: - val position = EpdFen("8/5P2/8/2b5/8/8/4B3/8 w - -") - val originalGame = fenToGame(position, Antichess) - - val newGame = originalGame flatMap (_.apply(Square.F7, Square.F8, Option(King))) map (_._1) - - newGame must beRight: - (_: Game).board(Square.F8).mustEqual(Option(White - King)) - - "deal with 2 white kings" in: - val position = EpdFen("K3k1nr/p2q2pp/p2p1p2/8/2PP4/8/PP4PP/RNBQK1NR w - - 0 11") - val originalGame = fenToGame(position, Antichess).toOption.get - - originalGame.situation.destinations === Map(Square.A8 -> Square.A7.bb) - - "Be drawn when there are only opposite colour bishops remaining" in: - val position = EpdFen("8/2b5/8/8/8/6Q1/4B3/8 b - -") - val originalGame = fenToGame(position, Antichess) - - val newGame = originalGame flatMap (_.apply(Square.C7, Square.G3, None)) map (_._1) - - newGame must beRight.like { case (drawnGame: Game) => - drawnGame.situation.end must beTrue - drawnGame.situation.autoDraw must beTrue - drawnGame.situation.winner must beNone - drawnGame.situation.status must beSome(Status.Draw) - } - - "Be drawn on multiple bishops on the opposite color" in: - val position = EpdFen("8/6P1/8/8/1b6/8/8/5B2 w - -") - val originalGame = fenToGame(position, Antichess) - - val newGame = originalGame flatMap (_.apply(Square.G7, Square.G8, Bishop.some)) map (_._1) - - newGame must beRight.like { case (drawnGame: Game) => - drawnGame.situation.end must beTrue - drawnGame.situation.autoDraw must beTrue - drawnGame.situation.winner must beNone - drawnGame.situation.status must beSome(Status.Draw) - } - - "Not be drawn when the black and white bishops are on the same coloured squares " in: - val position = EpdFen("7b/8/1p6/8/8/8/5B2/8 w - -") - val originalGame = fenToGame(position, Antichess) - - val newGame = originalGame flatMap (_.apply(Square.F2, Square.B6, None)) map (_._1) - - newGame must beRight.like { case nonDrawnGame => - nonDrawnGame.situation.end must beFalse - nonDrawnGame.situation.autoDraw must beFalse - nonDrawnGame.situation.winner must beNone - } - - "Be drawn when there are only opposite colour bishops and pawns which could not attack those bishops remaining" in: - val position = EpdFen("8/6p1/4B1P1/4p3/4P3/8/2p5/8 b - - 1 28") - val originalGame = fenToGame(position, Antichess) - - val newGame = originalGame flatMap (_.apply(Square.C2, Square.C1, Option(Bishop))) map (_._1) - - newGame must beRight.like { case (drawnGame: Game) => - drawnGame.situation.end must beTrue - drawnGame.situation.autoDraw must beTrue - drawnGame.situation.status must beSome(Status.Draw) - } - - "Not be drawn on opposite color bishops but with pawns that could be forced to attack a bishop" in: - val position = EpdFen("8/6p1/1B4P1/4p3/4P3/8/3p4/8 b - -") - val originalGame = fenToGame(position, Antichess) - - val newGame = originalGame flatMap (_.apply(Square.D2, Square.D1, Option(Bishop))) map (_._1) - - newGame must beRight.like { case nonDrawnGame => - nonDrawnGame.situation.end must beFalse - nonDrawnGame.situation.autoDraw must beFalse - nonDrawnGame.situation.status must beNone - } - - "Not be drawn where a white bishop can attack a black pawn in an almost closed position" in: - val position = EpdFen("5b2/1P4p1/4B1P1/4p3/4P3/8/8/8 w - -") - val originalGame = fenToGame(position, Antichess) - - val newGame = originalGame flatMap (_.apply(Square.B7, Square.B8, Bishop.some)) map (_._1) - - newGame must beRight.like { case nonDrawnGame => - nonDrawnGame.situation.end must beFalse - nonDrawnGame.situation.autoDraw must beFalse - nonDrawnGame.situation.status must beNone - } - - "Not be drawn where a pawn is unattackable, but is blocked by a bishop, not a pawn" in: - val position = EpdFen("8/8/4BbP1/4p3/4P3/8/8/8 b - -") - val originalGame = fenToGame(position, Antichess) - - val newGame = originalGame flatMap (_.playMoves(Square.F6 -> Square.G7)) - - newGame must beRight.like { case nonDrawnGame => - nonDrawnGame.situation.end must beFalse - nonDrawnGame.situation.autoDraw must beFalse - nonDrawnGame.situation.status must beNone - } - - "Opponent has insufficient material when there are only two remaining knights on same color squares" in: - val position = EpdFen("8/8/3n2N1/8/8/8/8/8 w - -") - val originalGame = fenToGame(position, Antichess) - - val newGame = originalGame flatMap (_.playMoves(Square.G6 -> Square.F4)) - - newGame must beRight.like: - _.situation.opponentHasInsufficientMaterial must beTrue - - "Opponent has sufficient material when there are only two remaining knights on opposite color squares" in: - val position = EpdFen("7n/8/8/8/8/8/8/N7 w - -") - val originalGame = fenToGame(position, Antichess) - - val newGame = originalGame flatMap (_.playMoves(Square.A1 -> Square.B3)) - - newGame must beRight.like: - _.situation.opponentHasInsufficientMaterial must beFalse - - "Not be drawn on insufficient mating material" in: - val position = EpdFen("4K3/8/1b6/8/8/8/5B2/3k4 b - -") - val maybeGame = fenToGame(position, Antichess) - - maybeGame must beRight.like { case game => - game.situation.end must beFalse - } - - "Be drawn on a three move repetition" in: - val game = Game(Antichess) - - val moves = - List((Square.G1, Square.F3), (Square.G8, Square.F6), (Square.F3, Square.G1), (Square.F6, Square.G8)) - val repeatedMoves: List[(Square, Square)] = List.fill(3)(moves).flatten - - val drawnGame = game.playMoveList(repeatedMoves) - - drawnGame must beRight.like { case g => - g.situation.threefoldRepetition must beTrue - } - - "Successfully play through a full game until one player loses all their pieces" in: - val game = Reader.full(fullGame) - - game must beRight.like { case Reader.Result.Complete(replay) => - val game = replay.state - - game.situation.end must beTrue - - // In antichess, the player who has just lost all their pieces is the winner - game.situation.winner must beSome(Black) - } - - "Win on a traditional stalemate where the player has no valid moves" in: - val position = EpdFen("8/p7/8/P7/8/8/8/8 w - -") - val maybeGame = fenToGame(position, Antichess) - - val drawnGame = maybeGame flatMap (_.playMoves((Square.A5, Square.A6))) - - drawnGame must beRight.like { case game => - game.situation.end must beTrue - game.situation.winner must beSome(Black) - } - - "Stalemate is a win - second test" in: - val fen = EpdFen("2Q5/8/p7/8/8/8/6PR/8 w - -") - val maybeGame = fenToGame(fen, Antichess) - - val drawnGame = maybeGame flatMap (_.playMoves((Square.C8, Square.A6))) - - drawnGame must beRight.like { case game => - game.situation.end must beTrue - game.situation.status must beSome(Status.VariantEnd) - game.situation.winner must beSome(Black) - } - - "two kings on replay" in: - - val pgn = """ + val pgn = """ [Event "Rated Antichess game"] [Site "https://lichess.org/60a0EiZh"] [Date "2023.01.16"] @@ -335,20 +277,20 @@ g4 {[%emt 0.200]} 34. Rxg4 {[%emt 0.172]} 0-1""" [Annotator "lichess.org"] 1. e3 b5 2. Bxb5 Bb7 3. Bxd7 Bxg2 4. Bxe8 Bxh1 5. Bxf7 Qxd2 6. Bxg8 Qxc2 7. Bxh7 Rxh7 8. Qxc2 Rxh2 9. Qxc7 Rxf2 10. Qxe7 Bxe7 11. Kxf2 Ba3 12. bxa3 Bf3 13. Nxf3 Nc6 14. Ne5 Nxe5 15. Kf3 Nxf3 16. Bd2 Nxd2 17. Nxd2 Rh8 18. Rh1 Rxh1 19. Nf1 Rxf1 20. a4 g6 21. e4 Rb1 22. a5 a6 23. a4 Rb6 24. axb6 g5 25. b7 g4 26. b8=R g3 27. a5 g2 28. Rb5 axb5 29. e5 g1=R 30. e6 b4 31. e7 Rg3 32. e8=K b3 33. a6 b2 34. a7 b1=R 35. a8=K Rb8 36. Kxb8 Rg6 37. Kc8 Ra6 38. Kf8 Rh6 39. Ke8 Rg6 40. Kcd8 Rb6 41. Kf8 Rh6 42. Kfe8 Rb6 43. Kf8 Rh6 44. Kfe8 Rb6 { The game is a draw. } 1/2-1/2 - """ - val game = Reader.full(pgn) + """ + val game = Reader.full(pgn) - game must beRight.like { case Reader.Result.Complete(replay) => - val game = replay.state + game must beRight.like { case Reader.Result.Complete(replay) => + val game = replay.state - game.situation.end must beFalse - game.situation.winner must beNone - } + game.situation.end must beFalse + game.situation.winner must beNone + } - "fen with castles" in: - val game = fenToGame(EpdFen("rnbqk2r/ppppppbp/5np1/8/8/5NP1/PPPPPPBP/RNBQK2R w KQkq - 4 4"), Antichess) + test("fen with castles"): + val game = fenToGame(EpdFen("rnbqk2r/ppppppbp/5np1/8/8/5NP1/PPPPPPBP/RNBQK2R w KQkq - 4 4"), Antichess) - game must beRight.like { case game => - game.situation.board.history.castles must_== Castles.none - game.situation.board.history.unmovedRooks must_== UnmovedRooks.none - } + game must beRight.like { case game => + assertEquals(game.situation.board.history.castles, Castles.none) + assertEquals(game.situation.board.history.unmovedRooks, UnmovedRooks.none) + } diff --git a/test-kit/src/test/scala/AtomicVariantTest.scala b/test-kit/src/test/scala/AtomicVariantTest.scala index c0a47ce8..04661464 100644 --- a/test-kit/src/test/scala/AtomicVariantTest.scala +++ b/test-kit/src/test/scala/AtomicVariantTest.scala @@ -241,7 +241,7 @@ class AtomicVariantTest extends ChessSpecs: val successGame = game flatMap (_.playMoves((Square.F6, Square.F5), (Square.G4, Square.H3))) successGame must beRight.like { game => - game.situation.check === Check.Yes + game.situation.check must_== Check.Yes } "Can move into discovered check in order to explode the opponent's king" in: @@ -262,7 +262,7 @@ class AtomicVariantTest extends ChessSpecs: val successGame = game flatMap (_.playMoves((Square.B5, Square.D7))) successGame must beRight.like { game => - game.situation.check === Check.No + game.situation.check must_== Check.No } "It should not be possible to explode a piece, exploding a piece next to it which would result in a check" in: @@ -546,7 +546,7 @@ class AtomicVariantTest extends ChessSpecs: .toVector val (game, steps, error) = chess.Replay.gameMoveWhileValid(sans, Atomic.initialFen, Atomic) error must beNone - steps.size === sans.size + steps.size must_== sans.size "castlings" should: diff --git a/test-kit/src/test/scala/BoardTest.scala b/test-kit/src/test/scala/BoardTest.scala index ac9f7be1..b75dcca7 100644 --- a/test-kit/src/test/scala/BoardTest.scala +++ b/test-kit/src/test/scala/BoardTest.scala @@ -53,7 +53,7 @@ class BoardTest extends ChessSpecs: "allow a piece to be placed" in: board.place(White - Rook, E3) must beSome: - (_: Board)(E3) mustEqual Option(White - Rook) + (_: Board)(E3) must_== Option(White - Rook) "allow a piece to be taken" in: board take A1 must beSome: @@ -61,7 +61,7 @@ class BoardTest extends ChessSpecs: "allow a piece to move" in: board.move(E2, E4) must beSome: - (_: Board)(E4) mustEqual Option(White - Pawn) + (_: Board)(E4) must_== Option(White - Pawn) "not allow an empty position to move" in: board.move(E5, E6) must beNone @@ -75,7 +75,7 @@ class BoardTest extends ChessSpecs: _.place(White - Pawn, A3), _.move(A2, A4) ) must beSome: - (_: Board)(A4) mustEqual Option(White - Pawn) + (_: Board)(A4) must_== Option(White - Pawn) "fail on bad actions chain" in: makeEmptyBoard.seq( diff --git a/test-kit/src/test/scala/Chess960Test.scala b/test-kit/src/test/scala/Chess960Test.scala index 314c7c6a..ee76eb63 100644 --- a/test-kit/src/test/scala/Chess960Test.scala +++ b/test-kit/src/test/scala/Chess960Test.scala @@ -39,7 +39,7 @@ class Chess960Test extends ChessSpecs: """ Reader.full(pgn) must beRight.like { case Reader.Result.Complete(replay) => - replay.state.situation.legalMoves.find(_.castles).map(_.toUci) === Some( + replay.state.situation.legalMoves.find(_.castles).map(_.toUci) must_== Some( format.Uci.Move(Square.E1, Square.B1) ) } diff --git a/test-kit/src/test/scala/ChessTest.scala b/test-kit/src/test/scala/ChessTest.scala index 9e33005c..65e17cf3 100644 --- a/test-kit/src/test/scala/ChessTest.scala +++ b/test-kit/src/test/scala/ChessTest.scala @@ -55,7 +55,7 @@ trait ChessTestCommon: def movesAt(s: Square): List[Move] = sit.moves.getOrElse(s, Nil) - def fenToGame(positionString: EpdFen, variant: Variant) = + def fenToGameEither(positionString: EpdFen, variant: Variant): Either[String, Game] = Fen .read(variant, positionString) .map: sit => @@ -117,6 +117,9 @@ trait ChessTest extends munit.FunSuite with ChessTestCommon: def assertCloseTo[T](a: T, b: T, delta: Double)(using n: Numeric[T])(using Location) = assert(isCloseTo(a, b, delta), s"$a is not close to $b by $delta") + def fenToGame(positionString: EpdFen, variant: Variant)(using Location): Game = + fenToGameEither(positionString, variant).get + private def isCloseTo[T](a: T, b: T, delta: Double)(using n: Numeric[T])(using Location) = (n.toDouble(a) - n.toDouble(b)).abs <= delta @@ -143,6 +146,9 @@ end ChessTest trait ChessSpecs extends Specification with EitherMatchers with ChessTestCommon: + def fenToGame(positionString: EpdFen, variant: Variant): Either[String, Game] = + fenToGameEither(positionString, variant) + def bePoss(poss: Square*) = // : Matcher[Option[Iterable[square]]] = beSome: (p: Iterable[Square]) => sortPoss(p.toList).map(_.key) must_== sortPoss(poss.toList).map(_.key) diff --git a/test-kit/src/test/scala/HashTest.scala b/test-kit/src/test/scala/HashTest.scala index 60b56c08..a7ccd701 100644 --- a/test-kit/src/test/scala/HashTest.scala +++ b/test-kit/src/test/scala/HashTest.scala @@ -20,51 +20,51 @@ class HashTest extends ChessSpecs: "match on the starting position" in: val fen = EpdFen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1") val game = fenToGame(fen, Standard).toOption.get - hash(game.situation) mustEqual hexToBytes("463b96181691fc9c") + hash(game.situation) must_== hexToBytes("463b96181691fc9c") "match after 1. e4" in: val fen = EpdFen("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1") val game = fenToGame(fen, Standard).toOption.get - hash(game.situation) mustEqual hexToBytes("823c9b50fd114196") + hash(game.situation) must_== hexToBytes("823c9b50fd114196") "match after 1. e4 d5" in: val fen = EpdFen("rnbqkbnr/ppp1pppp/8/3p4/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 2") val game = fenToGame(fen, Standard).toOption.get - hash(game.situation) mustEqual hexToBytes("0756b94461c50fb0") + hash(game.situation) must_== hexToBytes("0756b94461c50fb0") "match after 1. e4 d5 2. e5" in: val fen = EpdFen("rnbqkbnr/ppp1pppp/8/3pP3/8/8/PPPP1PPP/RNBQKBNR b KQkq - 0 2") val game = fenToGame(fen, Standard).toOption.get - hash(game.situation) mustEqual hexToBytes("662fafb965db29d4") + hash(game.situation) must_== hexToBytes("662fafb965db29d4") "match after 1. e4 d5 2. e5 f5" in: // note that en-passant matters val fen = EpdFen("rnbqkbnr/ppp1p1pp/8/3pPp2/8/8/PPPP1PPP/RNBQKBNR w KQkq f6 0 3") val game = fenToGame(fen, Standard).toOption.get - hash(game.situation) mustEqual hexToBytes("22a48b5a8e47ff78") + hash(game.situation) must_== hexToBytes("22a48b5a8e47ff78") "match after 1. e4 d5 2. e5 f5 3. Ke2" in: // 3. Ke2 forfeits castling rights val fen = EpdFen("rnbqkbnr/ppp1p1pp/8/3pPp2/8/8/PPPPKPPP/RNBQ1BNR b kq - 1 3") val game = fenToGame(fen, Standard).toOption.get - hash(game.situation) mustEqual hexToBytes("652a607ca3f242c1") + hash(game.situation) must_== hexToBytes("652a607ca3f242c1") "match after 1. e4 d5 2. e5 f5 3. Ke2 Kf7" in: val fen = EpdFen("rnbq1bnr/ppp1pkpp/8/3pPp2/8/8/PPPPKPPP/RNBQ1BNR w - - 2 4") val game = fenToGame(fen, Standard).toOption.get - hash(game.situation) mustEqual hexToBytes("00fdd303c946bdd9") + hash(game.situation) must_== hexToBytes("00fdd303c946bdd9") "match after 1. a4 b5 2. h4 b4 3. c4" in: // again, note en-passant matters val fen = EpdFen("rnbqkbnr/p1pppppp/8/8/PpP4P/8/1P1PPPP1/RNBQKBNR b KQkq c3 0 3") val game = fenToGame(fen, Standard).toOption.get - hash(game.situation) mustEqual hexToBytes("3c8123ea7b067637") + hash(game.situation) must_== hexToBytes("3c8123ea7b067637") "match after 1. a4 b5 2. h4 b4 3. c4 bxc3 4. Ra3" in: // 4. Ra3 partially forfeits castling rights val fen = EpdFen("rnbqkbnr/p1pppppp/8/8/P6P/R1p5/1P1PPPP1/1NBQKBNR b Kkq - 1 4") val game = fenToGame(fen, Standard).toOption.get - hash(game.situation) mustEqual hexToBytes("5c3f9b829b279560") + hash(game.situation) must_== hexToBytes("5c3f9b829b279560") "Hasher" should: @@ -140,7 +140,7 @@ class HashTest extends ChessSpecs: val situationAfter = Fen.read(Crazyhouse, fenAfter).get val hashAfter = hash(situationAfter) - hashAfterMove mustEqual hashAfter + hashAfterMove must_== hashAfter "be consistent when king is captured in antichess" in: val fen = EpdFen("rnbqkb1r/ppp1pppp/3p1n2/1B6/8/4P3/PPPP1PPP/RNBQK1NR w KQkq - 2 3") @@ -153,7 +153,7 @@ class HashTest extends ChessSpecs: val situationAfter = Fen.read(Antichess, fenAfter).get val hashAfter = hash(situationAfter) - hashAfterMove mustEqual hashAfter + hashAfterMove must_== hashAfter "be consistent when rook is exploded in atomic" in: val fen = EpdFen("rnbqkb1r/ppppp1pp/5p1n/6N1/8/8/PPPPPPPP/RNBQKB1R w KQkq - 2 3") @@ -166,7 +166,7 @@ class HashTest extends ChessSpecs: val situationAfter = Fen.read(Atomic, fenAfter).get val hashAfter = hash(situationAfter) - hashAfterMove mustEqual hashAfter + hashAfterMove must_== hashAfter "prod 5 Three-Check games accumulate hash" in: val gameMoves = format.pgn.Fixtures.prod5threecheck.map { g => diff --git a/test-kit/src/test/scala/HordeVariantTest.scala b/test-kit/src/test/scala/HordeVariantTest.scala index 4b3a5eb4..1df2a4db 100644 --- a/test-kit/src/test/scala/HordeVariantTest.scala +++ b/test-kit/src/test/scala/HordeVariantTest.scala @@ -4,181 +4,125 @@ import variant.Horde import chess.format.EpdFen import chess.format.pgn.SanStr -class HordeVariantTest extends ChessSpecs: - - "Horde chess" should: - - "Must not be insufficient winning material for horde with only 1 pawn left" in: - val position = EpdFen("k7/ppP5/brp5/8/8/8/8/8 b - -") - val game = fenToGame(position, Horde) - - game must beRight.like { case game => - game.situation.opponentHasInsufficientMaterial must beFalse - } - - "Must recognise insufficient winning material for horde with only 1 pawn left" in: - val position = EpdFen("8/2k5/3q4/8/8/8/1P6/8 b - -") - val game = fenToGame(position, Horde) - - game must beRight.like { case game => - game.situation.opponentHasInsufficientMaterial must beTrue - } - - "Must not be insufficient winning material for king with only 1 pawn left" in: - val position = EpdFen("8/2k5/3q4/8/8/8/1P6/8 w - -") - val game = fenToGame(position, Horde) - - game must beRight.like { case game => - game.situation.opponentHasInsufficientMaterial must beFalse - } - - "Must recognise insufficient winning material for horde with only 1 bishop left" in: - val position = EpdFen("r7/2Bb4/q3k3/8/8/3q4/8/5qqr b - -") - val game = fenToGame(position, Horde) - - game must beRight.like { case game => - game.situation.autoDraw must beFalse - game.situation.end must beFalse - game.situation.opponentHasInsufficientMaterial must beTrue - } - - "Must recognise insufficient winning material for horde with only 1 queen left" in: - val position = EpdFen("8/2k5/3q4/8/8/1Q6/8/8 b - -") - val game = fenToGame(position, Horde) - - game must beRight.like { case game => - game.situation.opponentHasInsufficientMaterial must beTrue - } - - "Must not be insufficient winning material for king with only 1 queen left" in: - val position = EpdFen("8/2k5/3q4/8/8/1Q6/8/8 w - -") - val game = fenToGame(position, Horde) - - game must beRight.like { case game => - game.situation.opponentHasInsufficientMaterial must beFalse - } - - "Must recognise insufficient winning material for horde with only 2 minor pieces left" in: - val position = EpdFen("8/2k5/3q4/8/8/1B2N3/8/8 b - -") - val game = fenToGame(position, Horde) - - game must beRight.like { case game => - game.situation.opponentHasInsufficientMaterial must beTrue - } - - "Must not be insufficient winning material for king with only 2 minor pieces left" in: - val position = EpdFen("8/2k5/3q4/8/8/1B2N3/8/8 w - -") - val game = fenToGame(position, Horde) - - game must beRight.like { case game => - game.situation.opponentHasInsufficientMaterial must beFalse - } - - "Must not be insufficient winning material for horde with 3 minor pieces left" in: - val position = EpdFen("8/2k5/3q4/8/8/3B4/4NB2/8 b - -") - val game = fenToGame(position, Horde) - - game must beRight.like { case game => - game.situation.opponentHasInsufficientMaterial must beFalse - } - - "Must not be insufficient winning material for king with queen and rook left" in: - val position = EpdFen("8/5k2/7q/7P/6rP/6P1/6P1/8 b - - 0 52") - val game = fenToGame(position, Horde) - - game must beRight.like { case game => - game.situation.opponentHasInsufficientMaterial must beFalse - game.situation.autoDraw must beFalse - } - - "Must auto-draw in simple pawn fortress" in: - val position = EpdFen("8/p7/pk6/P7/P7/8/8/8 b - -") - val game = fenToGame(position, Horde) - - game must beRight.like { case game => - game.situation.autoDraw must beTrue - game.situation.opponentHasInsufficientMaterial must beTrue - } - - "Must auto-draw if horde is stalemated and only king can move" in: - val position = EpdFen("QNBRRBNQ/PPpPPpPP/P1P2PkP/8/8/8/8/8 b - -") - val game = fenToGame(position, Horde) - - game must beRight.like { case game => - game.situation.autoDraw must beTrue - game.situation.opponentHasInsufficientMaterial must beTrue - } - - "Must auto-draw if horde is stalemated and only king can move" in: - val position = EpdFen("b7/pk6/P7/P7/8/8/8/8 b - - 0 1") - val game = fenToGame(position, Horde) - - game must beRight.like { case game => - game.situation.autoDraw must beTrue - game.situation.opponentHasInsufficientMaterial must beTrue - } - - "Must not auto-draw if horde is not stalemated after the only king move" in: - val position = EpdFen("8/1b5r/1P6/1Pk3q1/1PP5/r1P5/P1P5/2P5 b - - 0 52") - val game = fenToGame(position, Horde) - - game must beRight.like { case game => - game.situation.autoDraw must beFalse - game.situation.opponentHasInsufficientMaterial must beFalse - } - - "Must not auto-draw if not all black King moves leads to stalemate" in: - val position = EpdFen("8/8/8/7k/7P/7P/8/8 b - - 0 58") - val game = fenToGame(position, Horde) - - game must beRight.like { case game => - game.situation.autoDraw must beFalse - game.situation.end must beFalse - game.situation.status must beNone - Horde.isInsufficientMaterial(game.situation.board) must beFalse - game.situation.opponentHasInsufficientMaterial must beFalse - } - - "Must not auto-draw in B vs K endgame, king can win" in: - val position = EpdFen("7B/6k1/8/8/8/8/8/8 b - -") - val game = fenToGame(position, Horde) - - game must beRight.like { case game => - game.situation.autoDraw must beFalse - game.situation.opponentHasInsufficientMaterial must beTrue - } - - "Pawn on first rank should able to move two squares" in: - val position = EpdFen("8/pp1k2q1/3P2p1/8/P3PP2/PPP2r2/PPP5/PPPP4 w - - 1 2") - val game = fenToGame(position, Horde) - game must beRight.like { case game => - game.situation.legalMoves.exists(m => m.orig == Square.D1 && m.dest == Square.D3) must beTrue - } - - "Cannot en passant a pawn from the first rank" in: - val position = EpdFen("k7/5p2/4p2P/3p2P1/2p2P2/1p2P2P/p2P2P1/2P2P2 w - - 0 1") - val game = fenToGame(position, Horde).toOption.get - val newGame = game(Square.C1, Square.C3) - newGame must beRight.like: game => - game._1.situation.legalMoves.exists(m => m.orig == Square.B3 && m.dest == Square.C2) must beFalse - - "Castle with one rook moved" in: - val sans = SanStr from "a5 h5 a4 Nc6 a3 b6 a2 Bb7 d5 d6 d4 Rh6 cxd6 Qxd6 f6" - .split(' ') - .toVector - val (game, steps, error) = chess.Replay.gameMoveWhileValid(sans, Horde.initialFen, Horde) - error must beNone - steps.last._1.situation.legalMoves.exists(_.castles) must_== true - - "UnmovedRooks & castles at the starting position" in: - val board = Board.init(Horde) - board.history.unmovedRooks must_== UnmovedRooks(Set(Square.A8, Square.H8)) - board.history.castles must_== Castles("kq") - - "the h8 rooks move" in: - val position = EpdFen("r3kbnr/p1pqppp1/1pnp3P/PPPP1P1P/PPP1PPP1/1PPP1PPP/PPPPPPPP/PPPPPPPP b kq - 0 7") - val game = fenToGame(position, Horde).toOption.get - val newGame = game(Square.H8, Square.H6) - newGame must beRight.like: game => - game._1.situation.board.history.unmovedRooks must_== UnmovedRooks(Set(Square.A8)) - game._1.situation.board.history.castles must_== Castles("q") +class HordeVariantTest extends ChessTest: + + test("Must not be insufficient winning material for horde with only 1 pawn left"): + val position = EpdFen("k7/ppP5/brp5/8/8/8/8/8 b - -") + val game = fenToGame(position, Horde) + assertNot(game.get.situation.opponentHasInsufficientMaterial) + + test("Must recognise insufficient winning material for horde with only 1 pawn left"): + val position = EpdFen("8/2k5/3q4/8/8/8/1P6/8 b - -") + val game = fenToGame(position, Horde) + assert(game.get.situation.opponentHasInsufficientMaterial) + + test("Must not be insufficient winning material for king with only 1 pawn left"): + val position = EpdFen("8/2k5/3q4/8/8/8/1P6/8 w - -") + val game = fenToGame(position, Horde) + assertNot(game.get.situation.opponentHasInsufficientMaterial) + + test("Must recognise insufficient winning material for horde with only 1 bishop left"): + val position = EpdFen("r7/2Bb4/q3k3/8/8/3q4/8/5qqr b - -") + val game = fenToGame(position, Horde) + assertNot(game.get.situation.autoDraw) + assertNot(game.get.situation.end) + assert(game.get.situation.opponentHasInsufficientMaterial) + + test("Must recognise insufficient winning material for horde with only 1 queen left"): + val position = EpdFen("8/2k5/3q4/8/8/1Q6/8/8 b - -") + val game = fenToGame(position, Horde) + assert(game.get.situation.opponentHasInsufficientMaterial) + + test("Must not be insufficient winning material for king with only 1 queen left"): + val position = EpdFen("8/2k5/3q4/8/8/1Q6/8/8 w - -") + val game = fenToGame(position, Horde) + assertNot(game.get.situation.opponentHasInsufficientMaterial) + + test("Must recognise insufficient winning material for horde with only 2 minor pieces left"): + val position = EpdFen("8/2k5/3q4/8/8/1B2N3/8/8 b - -") + val game = fenToGame(position, Horde) + assert(game.get.situation.opponentHasInsufficientMaterial) + + test("Must not be insufficient winning material for king with only 2 minor pieces left"): + val position = EpdFen("8/2k5/3q4/8/8/1B2N3/8/8 w - -") + val game = fenToGame(position, Horde) + assertNot(game.get.situation.opponentHasInsufficientMaterial) + + test("Must not be insufficient winning material for horde with 3 minor pieces left"): + val position = EpdFen("8/2k5/3q4/8/8/3B4/4NB2/8 b - -") + val game = fenToGame(position, Horde) + assertNot(game.get.situation.opponentHasInsufficientMaterial) + + test("Must not be insufficient winning material for king with queen and rook left"): + val position = EpdFen("8/5k2/7q/7P/6rP/6P1/6P1/8 b - - 0 52") + val game = fenToGame(position, Horde) + assertNot(game.get.situation.opponentHasInsufficientMaterial) + assertNot(game.get.situation.autoDraw) + + test("Must auto-draw in simple pawn fortress"): + val position = EpdFen("8/p7/pk6/P7/P7/8/8/8 b - -") + val game = fenToGame(position, Horde) + assert(game.get.situation.autoDraw) + assert(game.get.situation.opponentHasInsufficientMaterial) + + test("Must auto-draw if horde is stalemated and only king can move"): + val position = EpdFen("QNBRRBNQ/PPpPPpPP/P1P2PkP/8/8/8/8/8 b - -") + val game = fenToGame(position, Horde) + assert(game.get.situation.autoDraw) + assert(game.get.situation.opponentHasInsufficientMaterial) + + test("Must auto-draw if horde is stalemated and only king can move"): + val position = EpdFen("b7/pk6/P7/P7/8/8/8/8 b - - 0 1") + val game = fenToGame(position, Horde) + assert(game.get.situation.autoDraw) + assert(game.get.situation.opponentHasInsufficientMaterial) + + test("Must not auto-draw if horde is not stalemated after the only king move"): + val position = EpdFen("8/1b5r/1P6/1Pk3q1/1PP5/r1P5/P1P5/2P5 b - - 0 52") + val game = fenToGame(position, Horde) + assertNot(game.get.situation.autoDraw) + assertNot(game.get.situation.opponentHasInsufficientMaterial) + + test("Must not auto-draw if not all black King moves leads to stalemate"): + val position = EpdFen("8/8/8/7k/7P/7P/8/8 b - - 0 58") + val game = fenToGame(position, Horde) + assertNot(game.get.situation.autoDraw) + assertNot(game.get.situation.end) + assertEquals(game.get.situation.status, None) + assertNot(Horde.isInsufficientMaterial(game.get.situation.board)) + assertNot(game.get.situation.opponentHasInsufficientMaterial) + + test("Must not auto-draw in B vs K endgame, king can win"): + val position = EpdFen("7B/6k1/8/8/8/8/8/8 b - -") + val game = fenToGame(position, Horde) + assertNot(game.get.situation.autoDraw) + assert(game.get.situation.opponentHasInsufficientMaterial) + + test("Pawn on first rank should able to move two squares"): + val position = EpdFen("8/pp1k2q1/3P2p1/8/P3PP2/PPP2r2/PPP5/PPPP4 w - - 1 2") + val game = fenToGame(position, Horde) + assert(game.get.situation.legalMoves.exists(m => m.orig == Square.D1 && m.dest == Square.D3)) + + test("Cannot en passant a pawn from the first rank"): + val position = EpdFen("k7/5p2/4p2P/3p2P1/2p2P2/1p2P2P/p2P2P1/2P2P2 w - - 0 1") + val game = fenToGame(position, Horde).get.apply(Square.C1, Square.C3) + assertNot(game.get._1.situation.legalMoves.exists(m => m.orig == Square.B3 && m.dest == Square.C2)) + + test("Castle with one rook moved"): + val sans = SanStr from "a5 h5 a4 Nc6 a3 b6 a2 Bb7 d5 d6 d4 Rh6 cxd6 Qxd6 f6" + .split(' ') + .toVector + val (game, steps, error) = chess.Replay.gameMoveWhileValid(sans, Horde.initialFen, Horde) + assertEquals(error, None) + assertEquals(steps.last._1.situation.legalMoves.exists(_.castles), true) + + test("UnmovedRooks & castles at the starting position"): + val board = Board.init(Horde) + assertEquals(board.history.unmovedRooks, UnmovedRooks(Set(Square.A8, Square.H8))) + assertEquals(board.history.castles, Castles("kq")) + + test("the h8 rooks move"): + val position = EpdFen("r3kbnr/p1pqppp1/1pnp3P/PPPP1P1P/PPP1PPP1/1PPP1PPP/PPPPPPPP/PPPPPPPP b kq - 0 7") + val game = fenToGame(position, Horde).get.apply(Square.H8, Square.H6) + assertEquals(game.get._1.situation.board.history.unmovedRooks, UnmovedRooks(Set(Square.A8))) + assertEquals(game.get._1.situation.board.history.castles, Castles("q")) diff --git a/test-kit/src/test/scala/RacingKingsVariantTest.scala b/test-kit/src/test/scala/RacingKingsVariantTest.scala index 036cee62..5599c10e 100644 --- a/test-kit/src/test/scala/RacingKingsVariantTest.scala +++ b/test-kit/src/test/scala/RacingKingsVariantTest.scala @@ -17,43 +17,43 @@ class RacingKingsVariantTest extends ChessSpecs: val fenPosition = EpdFen("4krn1/K2b4/8/8/8/8/8/8 w - - 4 3") val game = fenToGame(fenPosition, RacingKings).toOption.get game.situation.end must beTrue - game.situation.winner mustEqual Option(Black) + game.situation.winner must_== Option(Black) "game end to black 2" in: val fenPosition = EpdFen("4brk1/8/5n2/K7/8/8/8/8 w - - 6 4") val game = fenToGame(fenPosition, RacingKings).toOption.get game.situation.end must beTrue - game.situation.winner mustEqual Option(Black) + game.situation.winner must_== Option(Black) "game end to black 3" in: val fenPosition = EpdFen("3kbrn1/8/8/K7/8/8/8/8 w - - 4 3") val game = fenToGame(fenPosition, RacingKings).toOption.get game.situation.end must beTrue - game.situation.winner mustEqual Option(Black) + game.situation.winner must_== Option(Black) "game end to black 4" in: val fenPosition = EpdFen("4brk1/4n3/8/K7/8/8/8/8 w - - 4 3") val game = fenToGame(fenPosition, RacingKings).toOption.get game.situation.end must beTrue - game.situation.winner mustEqual Option(Black) + game.situation.winner must_== Option(Black) "game end to white" in: val fenPosition = EpdFen("K3br2/5k2/8/8/6n1/8/8/8 w - - 4 3") val game = fenToGame(fenPosition, RacingKings).toOption.get game.situation.end must beTrue - game.situation.winner mustEqual Option(White) + game.situation.winner must_== Option(White) "game end to white 2" in: val fenPosition = EpdFen("K3b2r/5k2/5n2/8/8/8/8/8 w - - 4 3") val game = fenToGame(fenPosition, RacingKings).toOption.get game.situation.end must beTrue - game.situation.winner mustEqual Option(White) + game.situation.winner must_== Option(White) "game is draw if both kings are in 8th rank" in: val fenPosition = EpdFen("K3brk1/8/5n2/8/8/8/8/8 w - - 4 3") val game = fenToGame(fenPosition, RacingKings).toOption.get game.situation.end must beTrue - game.situation.winner mustEqual None + game.situation.winner must_== None "game is not end when Black's King can go to the 8th rank" in: val fenPosition = EpdFen("1K2br2/5k2/5n2/8/8/8/8/8 b - - 3 2") diff --git a/test-kit/src/test/scala/ReplayTest.scala b/test-kit/src/test/scala/ReplayTest.scala index a2068393..76b710f9 100644 --- a/test-kit/src/test/scala/ReplayTest.scala +++ b/test-kit/src/test/scala/ReplayTest.scala @@ -15,7 +15,7 @@ class ReplayTest extends ChessSpecs: val moves = SanStr from """d4 d5 Nf4 Nf5 g4 g5 gxf5 exf5""".split(' ').toList Replay.gameMoveWhileValid(moves, fen, variant.FromPosition) must beLike { case (_, games, None) => games.size must_== 8 - games(1)._2._2 === "d5" + games(1)._2._2 must_== "d5" } "replay errors should keep order" in: @@ -23,7 +23,7 @@ class ReplayTest extends ChessSpecs: val moves = SanStr from """d4 d5 Nf3""".split(' ').toList Replay.gameMoveWhileValid(moves, fen, variant.FromPosition) must beLike { case (_, games, Some(_)) => games.size must_== 2 - games(1)._2._2 === "d5" + games(1)._2._2 must_== "d5" } "castle rights" in: @@ -60,7 +60,7 @@ class ReplayTest extends ChessSpecs: Chess960 ) error must beNone - steps.size === sans.size + steps.size must_== sans.size "castling always 960 notation" in: val sans: Vector[SanStr] = diff --git a/test-kit/src/test/scala/SituationTest.scala b/test-kit/src/test/scala/SituationTest.scala index 2e1e081d..bf2368e4 100644 --- a/test-kit/src/test/scala/SituationTest.scala +++ b/test-kit/src/test/scala/SituationTest.scala @@ -7,29 +7,29 @@ class SituationTest extends ChessSpecs: "by rook" in: (""" K r -""" as White).check === Check.Yes +""" as White).check must_== Check.Yes "by knight" in: (""" n K -""" as White).check === Check.Yes +""" as White).check must_== Check.Yes "by bishop" in: (""" b K -""" as White).check === Check.Yes +""" as White).check must_== Check.Yes "by pawn" in: (""" p K -""" as White).check === Check.Yes +""" as White).check must_== Check.Yes "not" in: (""" n K -""" as White).check === Check.No +""" as White).check must_== Check.No "detect check mate" in: "by rook" in: (""" diff --git a/test-kit/src/test/scala/perft/FullPerftTest.scala b/test-kit/src/test/scala/perft/FullPerftTest.scala index ca700edc..ffb60661 100644 --- a/test-kit/src/test/scala/perft/FullPerftTest.scala +++ b/test-kit/src/test/scala/perft/FullPerftTest.scala @@ -16,47 +16,47 @@ object FullPerftTest extends SimpleIOSuite: val nodeLimits = 1_000L - test("random.perft"): - perfts(Perft.randomPerfts, Chess960, 10_000L) - .map(assert(_)) - - test("threeCheck.perft"): - perfts(Perft.threeCheckPerfts, ThreeCheck, nodeLimits) - .map(assert(_)) - - test("antichess.perft"): - perfts(Perft.antichessPerfts, Antichess, nodeLimits) - .map(assert(_)) - - test("atomic.perft"): - perfts(Perft.atomicPerfts, Atomic, nodeLimits) - .map(assert(_)) - - test("crazyhouse.perft"): - perfts(Perft.crazyhousePerfts, Crazyhouse, nodeLimits) - .map(assert(_)) - - test("horde.perft"): - perfts(Perft.hordePerfts, Horde, nodeLimits) - .map(assert(_)) - - test("racingkings.perft"): - perfts(Perft.racingkingsPerfts, RacingKings, nodeLimits) - .map(assert(_)) - - test("tricky.perft"): - perfts(Perft.trickyPerfts, Chess960, nodeLimits) - .map(assert(_)) - - test("chess960.perft"): - perfts(Perft.chess960, Chess960, nodeLimits) - .map(assert(_)) - - private def perfts(perfts: List[Perft], variant: Variant, nodeLimit: Long): IO[Boolean] = - perfts.parFoldMapA(perft => IO(perftTest(perft, variant, nodeLimit))) - - private def perftTest(perft: Perft, variant: Variant, nodeLimit: Long): Boolean = - perft - .withLimit(nodeLimit) - .calculate(variant) - .forall(r => r.result === r.expected) + // test("random.perft"): + // perfts(Perft.randomPerfts, Chess960, 10_000L) + // .map(assert(_)) + // + // test("threeCheck.perft"): + // perfts(Perft.threeCheckPerfts, ThreeCheck, nodeLimits) + // .map(assert(_)) + // + // test("antichess.perft"): + // perfts(Perft.antichessPerfts, Antichess, nodeLimits) + // .map(assert(_)) + // + // test("atomic.perft"): + // perfts(Perft.atomicPerfts, Atomic, nodeLimits) + // .map(assert(_)) + // + // test("crazyhouse.perft"): + // perfts(Perft.crazyhousePerfts, Crazyhouse, nodeLimits) + // .map(assert(_)) + // + // test("horde.perft"): + // perfts(Perft.hordePerfts, Horde, nodeLimits) + // .map(assert(_)) + // + // test("racingkings.perft"): + // perfts(Perft.racingkingsPerfts, RacingKings, nodeLimits) + // .map(assert(_)) + // + // test("tricky.perft"): + // perfts(Perft.trickyPerfts, Chess960, nodeLimits) + // .map(assert(_)) + // + // test("chess960.perft"): + // perfts(Perft.chess960, Chess960, nodeLimits) + // .map(assert(_)) + // + // private def perfts(perfts: List[Perft], variant: Variant, nodeLimit: Long): IO[Boolean] = + // perfts.parFoldMapA(perft => IO(perftTest(perft, variant, nodeLimit))) + // + // private def perftTest(perft: Perft, variant: Variant, nodeLimit: Long): Boolean = + // perft + // .withLimit(nodeLimit) + // .calculate(variant) + // .forall(r => r.result === r.expected)