public void testKingsideCastlingMoveIsExecutedCorrectly() { DoktorChessAIBoard ourBoard = new DoktorChessAIBoard(gameType.normal, boardSearchConfig.getDebugConfig()); square ourKing = ourBoard.addPiece(pieceType.king, pieceColour.white, 4, 0); square ourRook = ourBoard.addPiece(pieceType.rook, pieceColour.white, 7, 0); ourBoard.addPiece(pieceType.king, pieceColour.black, 0, 0); // Make our castling move.. move castlingMove = new move(ourKing, ourBoard[6, 0]); ourBoard.doMove(castlingMove); // Verify that the rook and king have both moved to their correct squares. Assert.IsTrue(ourBoard[6, 0] == ourKing); Assert.IsTrue(ourBoard[5, 0] == ourRook); }
public void testKingsideCastlingMoveIsNotAfterRookHasMoved() { DoktorChessAIBoard ourBoard = new DoktorChessAIBoard(gameType.normal, boardSearchConfig.getDebugConfig()); square ourKing = ourBoard.addPiece(pieceType.king, pieceColour.white, 4, 0); square ourRook = ourBoard.addPiece(pieceType.rook, pieceColour.white, 6, 0); ourBoard.addPiece(pieceType.king, pieceColour.black, 0, 0); // Move the rook to 7,0. ourBoard.doMove(new move(ourRook, ourBoard[7,0])); // Now make sure we cannot castle. sizableArray<move> possibleMoves = ourKing.getPossibleMoves(ourBoard); // None of these moves should end up at (6,0). if (Array.Find(possibleMoves.getArray(), a => a.dstPos.isSameSquareAs(new squarePos(6, 0))) != null) throw new AssertFailedException("Castling found after rook has moved"); }
public void testMoveDoingUndoingWithPawnPromotion() { DoktorChessAIBoard ourBoard = new DoktorChessAIBoard(gameType.normal, boardSearchConfig.getDebugConfig()); ourBoard.addPiece(pieceType.pawn, pieceColour.white, 1, 6); string origBoard = ourBoard.ToString(); sizableArray<move> potentialMoves = ourBoard.getMoves(pieceColour.white); if (potentialMoves.Length == 0) Assert.Inconclusive("No pawn moves found"); // Find promotion moves move[] promotionMoves = Array.FindAll(potentialMoves.getArray(), a => a.isPawnPromotion); if (promotionMoves.Length == 0) Assert.Inconclusive("No promotion moves found"); foreach (move thisMove in promotionMoves) { ourBoard.doMove(thisMove); if (ourBoard.ToString() == origBoard) throw new AssertFailedException("After a pawn promotion move, the board has not changed"); // Additionally, verify that the pawn has been promoted if (ourBoard[thisMove.dstPos].type != thisMove.typeToPromoteTo) throw new AssertFailedException("Pawn was not promoted"); if (ourBoard[thisMove.dstPos].GetType() == typeof(pawnSquare)) throw new AssertFailedException("Pawn was not promoted, but type has changed"); if (ourBoard[thisMove.dstPos].colour != pieceColour.white) throw new AssertFailedException("Pawn was promoted to wrong colour"); ourBoard.undoMove(thisMove); if (ourBoard.ToString() != origBoard) throw new AssertFailedException("After a pawn promotion move undo, the board has changed"); } }
public void testKingsideCastlingMoveIsUnExecutedCorrectly() { DoktorChessAIBoard ourBoard = new DoktorChessAIBoard(gameType.normal, boardSearchConfig.getDebugConfig()); square ourKing = ourBoard.addPiece(pieceType.king, pieceColour.white, 4, 0); square ourRook = ourBoard.addPiece(pieceType.rook, pieceColour.white, 7, 0); ourBoard.addPiece(pieceType.king, pieceColour.black, 0, 0); string origBoard = ourBoard.ToString(); // Make out castling move move castlingMove = new move(ourKing, ourBoard[6, 0]); ourBoard.doMove(castlingMove); Assert.AreNotEqual(origBoard, ourBoard.ToString(), "Castling did not affect the board"); // Now undo our castling and verify that we get back to the original position. ourBoard.undoMove(castlingMove); Assert.AreEqual(origBoard, ourBoard.ToString(), "Castling and then un-castling did not return the original board"); }
public void testThatEnPassantOccursWhenItShouldAsBlack() { DoktorChessAIBoard ourBoard = new DoktorChessAIBoard(gameType.normal, boardSearchConfig.getDebugConfig()); // En passant requires that the enemy pawn has just advanced two squares. Because of this, we make this move on a board and then check that en passant can occur. square ourPawn = ourBoard.addPiece(pieceType.pawn, pieceColour.black, 6, 3); square enemyPawn = ourBoard.addPiece(pieceType.pawn, pieceColour.white, 7, 1); // Advance the enemy pawn move advanceTwo = new move(enemyPawn, ourBoard[enemyPawn.position.up(2)]); ourBoard.doMove(advanceTwo); // Now verify that the enemy pawn is captured. sizableArray<move> possibleMoves = ourPawn.getPossibleMoves(ourBoard); move enPassantCapture = null; foreach (move thisMove in possibleMoves) { if (thisMove.isCapture) { if (enPassantCapture != null) throw new AssertFailedException("More than one capture was found"); // Note that our dest square is not the enemy square here. Assert.IsTrue(thisMove.srcPos.isSameSquareAs(ourPawn.position)); Assert.IsTrue(thisMove.dstPos.isSameSquareAs(ourPawn.position.rightOne().downOne() )); Assert.AreSame(thisMove.capturedSquare, enemyPawn); enPassantCapture = thisMove; } } if (enPassantCapture == null) throw new AssertFailedException("En passant capture did not occur"); // Make sure that the en passant capture ends up putting our pawn in the square above the enemy pawn Assert.IsTrue(enemyPawn.position.downOne().isSameSquareAs( enPassantCapture.dstPos) ); }
public void verifyFiftyMoveRule(DoktorChessAIBoard ourBoard, int moveOffset) { for (int n = 0; n < 100 - moveOffset; n++) { Assert.AreEqual(gameStatus.inProgress, ourBoard.getGameStatus(pieceColour.white), "Game declared drawn at move " + n.ToString()); switch (n % 4) { case 0: // Play Nc3 ourBoard.doMove(new move(ourBoard[1, 0], ourBoard[2, 2])); break; case 1: // Play Nc6 ourBoard.doMove(new move(ourBoard[1, 7], ourBoard[2, 5])); break; case 2: // And move knights back again. // Nb1 ourBoard.doMove(new move(ourBoard[2, 2], ourBoard[1, 0])); break; case 3: // nb8 ourBoard.doMove(new move(ourBoard[2, 5], ourBoard[1, 7])); break; default: throw new ArgumentException(); } } // 50 moves have elapsed! It's a draw! Assert.AreEqual(gameStatus.drawn, ourBoard.getGameStatus(pieceColour.white)); }
public void testThreatMapDeep_pawnCapture() { DoktorChessAIBoard ourBoard = new DoktorChessAIBoard(gameType.queenAndPawns, boardSearchConfig.getDebugConfig()); square ourPawn = ourBoard.addPiece(pieceType.pawn, pieceColour.white, 4, 1); square enemyPawn = ourBoard.addPiece(pieceType.pawn, pieceColour.black, 3, 2); if (ourBoard.getCoverLevel(new squarePos(3, 2), pieceColour.white) != 1 || ourBoard.getCoverLevel(new squarePos(5, 2), pieceColour.white) != 1) throw new AssertFailedException("Threatmap created wrongly"); if (ourBoard.getCoverLevel(new squarePos(2, 1), pieceColour.white) != -1 || ourBoard.getCoverLevel(new squarePos(4, 1), pieceColour.white) != -1) throw new AssertFailedException("Enemy pawn create with no threatened squares"); if (ourPawn.coveredSquares.Count != 2) throw new AssertFailedException("Pawn created not covering two squares"); if ((!ourPawn.coveredSquares[3, 2]) || (!ourPawn.coveredSquares[5, 2]) ) throw new AssertFailedException("Pawn created with incorrect .coveredSquares"); if (((threatMap)ourBoard.coverLevel).piecesWhichThreatenSquare[3, 2].Count != 1 || ((threatMap)ourBoard.coverLevel).piecesWhichThreatenSquare[3, 2].Count != 1) throw new AssertFailedException("Pawn created with incorrect .piecesWhichThreatenSquare count"); //if (((threatMap)ourBoard.coverLevel).piecesWhichThreatenSquare[3, 2][ourPawn.position.flatten()] != ourPawn || // ((threatMap)ourBoard.coverLevel).piecesWhichThreatenSquare[5, 2][ourPawn.position.flatten()] != ourPawn) // throw new AssertFailedException("Pawn created with incorrect .piecesWhichThreatenSquare contents"); move ourMove = new move(ourPawn, ourBoard[3, 2]); ourBoard.doMove(ourMove); if (ourBoard.getCoverLevel(new squarePos(2, 3), pieceColour.white) != 1 || ourBoard.getCoverLevel(new squarePos(4, 3), pieceColour.white) != 1) throw new AssertFailedException("Threatmap did not update cover levels correctly"); if (ourBoard.getCoverLevel(new squarePos(2, 1), pieceColour.white) != 0 || ourBoard.getCoverLevel(new squarePos(4, 1), pieceColour.white) != 0) throw new AssertFailedException("Captured pawn still has threatened squares"); if (ourPawn.coveredSquares.Count != 2) throw new AssertFailedException("Pawn updated not covering two squares"); if (!ourPawn.coveredSquares[2, 3] || !ourPawn.coveredSquares[4, 3] ) throw new AssertFailedException("Pawn updated with incorrect .coveredSquares"); if (((threatMap)ourBoard.coverLevel).piecesWhichThreatenSquare[3, 2].Count != 0 || ((threatMap)ourBoard.coverLevel).piecesWhichThreatenSquare[3, 2].Count != 0) throw new AssertFailedException("Pawn's pre-update .piecesWhichThreatenSquare was not changed"); if (((threatMap)ourBoard.coverLevel).piecesWhichThreatenSquare[2, 3].Count != 1 || ((threatMap)ourBoard.coverLevel).piecesWhichThreatenSquare[4, 3].Count != 1) throw new AssertFailedException("Pawn updated with incorrect .piecesWhichThreatenSquare count"); //if (((threatMap)ourBoard.coverLevel).piecesWhichThreatenSquare[2, 3][ourPawn.position.flatten()] != ourPawn || // ((threatMap)ourBoard.coverLevel).piecesWhichThreatenSquare[4, 3][ourPawn.position.flatten()] != ourPawn) // throw new AssertFailedException("Pawn updated with incorrect .piecesWhichThreatenSquare contents"); }
public void testThreatMapDeep_discoveredPromotion() { DoktorChessAIBoard ourBoard = new DoktorChessAIBoard(gameType.queenAndPawns, boardSearchConfig.getDebugConfig()); square ourPawn = ourBoard.addPiece(pieceType.pawn, pieceColour.white, 3, 6); square enemyPawn = ourBoard.addPiece(pieceType.pawn, pieceColour.black, 3, 7); square ourRook = ourBoard.addPiece(pieceType.rook, pieceColour.white, 0, 7); move ourMove = new move(ourPawn, ourBoard[3, 7], pieceType.queen); ourBoard.doMove(ourMove); // Observe the squares to the right of our pawn - they should not be accessible to the rook for (int x = 4; x < 7; x++) { if (ourBoard.getCoverLevel(new squarePos(x, 7), pieceColour.white) != 1) throw new AssertFailedException("Threatmap did not update cover levels correctly"); } // the pawn itself is protected once. if (ourBoard.getCoverLevel(new squarePos(3, 7), pieceColour.white) != 1) throw new AssertFailedException("Threatmap did not update cover levels of promoted piece correctly"); }
public void testThreatMapDeep_discoveredCapture() { DoktorChessAIBoard ourBoard = new DoktorChessAIBoard(gameType.queenAndPawns, boardSearchConfig.getDebugConfig()); square ourPawn = ourBoard.addPiece(pieceType.pawn, pieceColour.white, 0, 1); square enemyPawn = ourBoard.addPiece(pieceType.pawn, pieceColour.black, 1, 2); square ourRook = ourBoard.addPiece(pieceType.rook, pieceColour.white, 0, 0); square enemyRook = ourBoard.addPiece(pieceType.rook, pieceColour.black, 0, 7); move ourMove = new move(ourPawn, enemyPawn); ourBoard.doMove(ourMove); // Squares between rooks our pawn should be threatened by both rooks, so should have a threat // level of 0, apart from the one at y=3, which is threatened by a pawn. for (int x = 1; x < 7; x++) { if (x == 3) { if (ourBoard.getCoverLevel(new squarePos(0, x), pieceColour.black) != -1) throw new AssertFailedException("Threatmap did not update cover levels correctly for discovered spaces"); } else { if (ourBoard.getCoverLevel(new squarePos(0, x), pieceColour.black) != 0) throw new AssertFailedException("Threatmap did not update cover levels correctly for discovered spaces"); } } // Both rooks should be threatened once, by the other rook. if (ourBoard.getCoverLevel(new squarePos(0, 0), pieceColour.black) != 1 || ourBoard.getCoverLevel(new squarePos(0, 7), pieceColour.white) != 1 ) throw new AssertFailedException("Threatmap did not update cover levels correctly for rooks"); }
public void testThreatMapDeep_discovered() { DoktorChessAIBoard ourBoard = new DoktorChessAIBoard(gameType.queenAndPawns, boardSearchConfig.getDebugConfig() ); square ourPawn = ourBoard.addPiece(pieceType.pawn, pieceColour.white, 4, 1); square ourRook = ourBoard.addPiece(pieceType.rook, pieceColour.white, 0, 1); move ourMove = new move(ourPawn, ourBoard[4, 2]); ourBoard.doMove(ourMove); // Observe the squares to the right of our pawn - they should now be accessible to the rook for (int x = 1; x < 7; x++) { if (ourBoard.getCoverLevel(new squarePos(x, 1), pieceColour.white) != 1) throw new AssertFailedException("Threatmap did not update cover levels correctly"); } }
public void testMoveUndoingThreatmap_Castling() { DoktorChessAIBoard ourBoard = new DoktorChessAIBoard(gameType.normal, boardSearchConfig.getDebugConfig()); square ourKing = ourBoard.addPiece(pieceType.king, pieceColour.white, 4, 0); square ourRook = ourBoard.addPiece(pieceType.rook, pieceColour.white, 7, 0); square enemyPawn = ourBoard.addPiece(pieceType.pawn, pieceColour.black, 6, 6); string origThreatMap = ourBoard.coverLevel.ToString(); int[,] threatCounts = new int[DoktorChessAIBoard.sizeX,DoktorChessAIBoard.sizeY]; for (int x = 0; x < DoktorChessAIBoard.sizeX; x++) { for (int y = 0; y < DoktorChessAIBoard.sizeY; y++) { threatCounts[x, y] = ourBoard[x, y].coveredSquares.Count; } } move castling = new move(ourKing, ourBoard[6, 0]); ourBoard.doMove(castling); if (ourBoard.coverLevel.ToString() == origThreatMap) throw new AssertFailedException("After a move, the threat map has not changed"); ourBoard.undoMove(castling); if (ourBoard.coverLevel.ToString() != origThreatMap) { Debug.WriteLine("Expected:"); Debug.WriteLine(origThreatMap); Debug.WriteLine("Actual:"); Debug.WriteLine(ourBoard.coverLevel.ToString()); throw new AssertFailedException("After a move undo, the threat map has changed"); } for (int x = 0; x < DoktorChessAIBoard.sizeX; x++) { for (int y = 0; y < DoktorChessAIBoard.sizeY; y++) { if (threatCounts[x, y] != ourBoard[x, y].coveredSquares.Count) throw new AssertFailedException("Piece covered count incorrect"); } } }