public bool contains(move toAdd, int depth)
        {
            List<List<bool>> thisDepth = _killerMovesAtDepth[depth];
            List<bool> fromThisSq = thisDepth[toAdd.dstPos.flatten()];

            return fromThisSq[toAdd.dstPos.flatten()];
        }
        public void testQueensideCastlingNotation()
        {
            DoktorChessAIBoard ourBoard = new DoktorChessAIBoard(gameType.normal, boardSearchConfig.getDebugConfig());
            square ourKing = ourBoard.addPiece(pieceType.king, pieceColour.white, 4, 0);
            ourBoard.addPiece(pieceType.rook, pieceColour.white, 0, 0);

            move theMove = new move(ourKing, new square(2, 0));

            Assert.AreEqual("O-O-O", theMove.ToString(moveStringStyle.chessNotation));
        }
        public void add(int depth, move toAdd)
        {
            if (contains(toAdd, depth))
                return;

            List<List<bool>> thisDepth = _killerMovesAtDepth[depth];
            List<bool> fromThisSq = thisDepth[toAdd.dstPos.flatten()];

            fromThisSq[toAdd.dstPos.flatten()] = true;
        }
        public void testPieceMoveNotation()
        {
            DoktorChessAIBoard ourBoard = new DoktorChessAIBoard(gameType.normal, boardSearchConfig.getDebugConfig());
            square bish = new bishopSquare(new squarePos(0, 0), pieceColour.black);
            square targetSpace = new square( new squarePos(0, 1) );

            move theMove = new move(bish, targetSpace);

            Assert.AreEqual("Ba2", theMove.ToString(moveStringStyle.chessNotation));
        }
        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);
        }
Example #6
0
        public void verifyMoveConstructorWithCapture()
        {
            // Make two occupied squares and construct a move from one to the other. Test
            // that the capture is correctly propagated to the move.
            square src = new pawnSquare(new squarePos(1, 1), pieceColour.black);
            square dst = new pawnSquare(new squarePos(2, 1), pieceColour.white);

            move captureMove = new move(src, dst);

            // First, check that the move has the correct squares associated with it..
            Assert.IsTrue(captureMove.srcPos.isSameSquareAs(src.position));
            Assert.IsTrue(captureMove.dstPos.isSameSquareAs(dst.position));

            Assert.IsTrue(captureMove.isCapture);
            Assert.IsTrue(captureMove.capturedSquare == dst);
        }
Example #7
0
        public void initFromMove(move initWith)
        {
            movedPieceSrc = initWith.srcPos;
            movedPieceDst = initWith.dstPos;

            // If this is an en passant capture, we need to express that the capture square is not the dest.
            if (initWith.capturedSquare == null ||
                initWith.capturedSquare.position.isSameSquareAs(initWith.dstPos))
            {
                hasExtraCaptureSquare = false;
            }
            else
            {
                hasExtraCaptureSquare = true;
                extraCaptureSquarePos = initWith.capturedSquare.position;
            }
        }
        public void testIterator()
        {
            sizableArray<move> foo = new sizableArray<move>(5);

            move move1 = new move(new square(0,0), new square(1,1));
            move move2 = new move(new square(1,1), new square(2,2));

            foo.Add(move1);
            foo.Add(move2);

            bool move1seen = false;
            bool move2seen = false;

            foreach (move iterated in foo)
            {
                Debug.WriteLine("Iterated object " + iterated);
                if (iterated == move1)
                {
                    if (move1seen)
                        throw new Exception("Move one iterated twice");
                    move1seen = true;
                }
                else if (iterated == move2)
                {
                    if (move2seen)
                        throw new Exception("Move two iterated twice");
                    move2seen = true;
                }
                else if (iterated == null)
                    throw new Exception("Iterator returned null");
                else
                    throw new Exception("Iterator returned something crazy");
            }

            if (!move1seen || !move2seen)
                throw new Exception("Iterator did not iterate over all elements");
        }
        /// <summary>
        /// Check a list of moves contains only one capture, which has the supplied src and dst/enemysquare.
        /// </summary>
        /// <param name="possibleMoves"></param>
        /// <param name="ourPiece"></param>
        /// <param name="enemyPiece"></param>
        /// <returns></returns>
        public move checkContainsSingleCapture(move[] possibleMoves, square ourPiece, square enemyPiece)
        {
            bool captureFound = false;
            move capture = null;

            foreach (move thisMove in possibleMoves)
            {
                if (thisMove.isCapture)
                {
                    Assert.IsTrue(thisMove.srcPos.isSameSquareAs(ourPiece.position));
                    Assert.IsTrue(thisMove.dstPos.isSameSquareAs(enemyPiece.position));
                    Assert.AreEqual(thisMove.dstPos, enemyPiece.position);
                    Assert.AreEqual(thisMove.capturedSquare, enemyPiece);

                    if (captureFound)
                        throw new AssertFailedException("Multiple captures found, one expected");
                    captureFound = true;
                    capture = thisMove;
                }
            }
            if (!captureFound)
                throw new AssertFailedException("No captures found, one expected");
            return capture;
        }
        public void testThatEnPassantDoesNotOccurAfterTwoPawnAdvances()
        {
            DoktorChessAIBoard ourBoard = DoktorChessAIBoard.makeFromFEN("8/8/8/8/6P1/8/7p/8 b - - 0 1", gameType.normal, boardSearchConfig.getDebugConfig());
            // Verify that we cannot en passant after our opponent has moved a pawn forward one, not two, squares.
            square ourPawn = ourBoard[6, 3];
            square enemyPawn = ourBoard[7, 1];

            square ourNewSquare = ourBoard[ourPawn.position.rightOne().upOne()];

            // Advance the enemy pawn twice
            move advanceOne = new move(enemyPawn, ourBoard[enemyPawn.position.upOne()]);
            ourBoard.doMove(advanceOne);
            ourBoard.colToMove = pieceColour.black;
            advanceOne = new move(enemyPawn, ourBoard[enemyPawn.position.upOne()]);
            ourBoard.doMove(advanceOne);

            sizableArray<move> possibleMoves = ourPawn.getPossibleMoves(ourBoard);
            if (Array.Find(possibleMoves.getArray(), a => a.isCapture == true) != null)
                throw new AssertFailedException("Found en passant capture when none is legal");
        }
Example #11
0
        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");
            }
        }
Example #12
0
        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 testThatEnPassantDoesNotOccurAfterExtraMove()
        {
            DoktorChessAIBoard ourBoard = DoktorChessAIBoard.makeFromFEN("8/8/8/8/6P1/8/1P5p/8 b - - 0 1", gameType.normal, boardSearchConfig.getDebugConfig());
            // Verify that we cannot en passant after we move a piece
            square ourPawn = ourBoard[6, 3];
            square ourKing = ourBoard[1, 1];
            square enemyPawn = ourBoard[7, 1];

            // Advance the enemy pawn two squares, and then move our king. This should cause en passant to be impossible.
            move advanceTwo = new move(enemyPawn, ourBoard[enemyPawn.position.up(2)]);
            ourBoard.doMove(advanceTwo);

            // Then, move our king
            move kingMove = new move(ourKing, ourBoard[ourKing.position.upOne()]);
            ourBoard.doMove(kingMove);

            // Now. Can we en passant?
            sizableArray<move> possibleMoves = ourPawn.getPossibleMoves(ourBoard);
            if (Array.Find(possibleMoves.getArray(), a => a.isCapture == true) != null)
                throw new AssertFailedException("Found en passant capture when none is legal");
        }
Example #14
0
        /// <summary>
        /// Would the specified move put the player of the specified colour in to check?
        /// </summary>
        /// <param name="playerCol">Colour which may move in ot check</param>
        /// <param name="playersMove">Move to examine</param>
        /// <returns></returns>
        public bool wouldMovePutPlayerInCheck(pieceColour playerCol, move playersMove)
        {
            doMove(playersMove);
            bool toRet = isPlayerInCheck(playerCol);
            undoMove(playersMove);

            return toRet;
        }
Example #15
0
        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 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");
        }
Example #17
0
        public void testMoveUndoingThreatmapWithCapture()
        {
            DoktorChessAIBoard ourBoard = DoktorChessAIBoard.makeFromFEN("8/8/8/8/4p3/5P2/8/8 b - - 0 1", gameType.normal, boardSearchConfig.getDebugConfig());
            square ourPawn = ourBoard[4, 3];
            square enemyPawn = ourBoard[5, 2];

            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 ourMove = new move(ourPawn, enemyPawn);
            ourBoard.doMove(ourMove);

            if (ourBoard.coverLevel.ToString() == origThreatMap)
                throw new AssertFailedException("After a move, the threat map has not changed");

            ourBoard.undoMove(ourMove);

            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");
                }

            }
        }
Example #18
0
 public lineAndScore(move[] newLine, int newFinalScore, baseBoardScorer scorer)
 {
     line = newLine;
     finalScore = newFinalScore;
     _scorer = scorer;
 }
        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 override void undoMove(move move)
        {
            if (move.isACastling)
            {
                if (this[move.dstPos].colour == pieceColour.white)
                    whiteHasCastled = false;
                else if (this[move.dstPos].colour == pieceColour.black)
                    blackHasCastled = false;
                else
                    throw new Exception("Cannot identify colour");

            }

            base.undoMove(move);
        }
        public override void doMove(move move)
        {
            // If this move is a castling, update the rooks movedCount
            if (move.isACastling)
            {
                if (this[move.srcPos].colour == pieceColour.white)
                    whiteHasCastled = true;
                else if (this[move.srcPos].colour == pieceColour.black)
                    blackHasCastled = true;
                else
                    throw new Exception("Cannot identify colour");
            }

            base.doMove(move);
        }
Example #22
0
 public void verifyMoveOfEmptySpaceIsIllegal()
 {
     DoktorChessAIBoard ourBoard = DoktorChessAIBoard.makeQueenAndPawnsStartPosition(boardSearchConfig.getDebugConfig());
     move illegalMove = new move(ourBoard[3, 3], ourBoard[4, 4]);
     Assert.IsFalse(illegalMove.isLegal(ourBoard));
 }
Example #23
0
        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");
        }
Example #24
0
 public void verifyLegalMoveIsLegal()
 {
     DoktorChessAIBoard ourBoard = DoktorChessAIBoard.makeQueenAndPawnsStartPosition(boardSearchConfig.getDebugConfig());
     move legalMove = new move(ourBoard[1, 1], ourBoard[1, 3]);
     Assert.IsTrue(legalMove.isLegal(ourBoard));
 }
        public void testThatEnPassantOccursWhenItShouldAsWhite()
        {
            DoktorChessAIBoard ourBoard = DoktorChessAIBoard.makeFromFEN("8/6p1/8/7P/8/8/8/8 b - - 0 1", gameType.normal, boardSearchConfig.getDebugConfig());

            square enemyPawn = ourBoard[6, 6];
            square ourPawn = ourBoard[7, 4];

            // Advance the enemy pawn
            move advanceTwo = new move(enemyPawn, ourBoard[enemyPawn.position.down(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.leftOne().upOne()));
                    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.upOne().isSameSquareAs(enPassantCapture.dstPos));
        }
Example #26
0
        /// <summary>
        /// Perform the specified move
        /// </summary>
        /// <param name="move">The move to play</param>
        public virtual void doMove(move move)
        {
            sanityCheck();

            #if DEBUG
            if (this[move.srcPos].type == pieceType.none)
                throw new ArgumentException("Moving empty space");
            if (this[move.srcPos].colour != colToMove)
                throw new ArgumentException("Moving peice of wrong colour");
            #endif
            // If this is a pawn move or a capture, reset the fifty-move rule counter.
            if (this[move.srcPos].type == pieceType.pawn || move.isCapture)
            {
                fiftyMoveCounter.Push(0);
            }
            else
            {
                if (moveCount > 0)
                    fiftyMoveCounter.Push(fiftyMoveCounter.Peek() + 1);
                else
                    fiftyMoveCounter.Push(1);
            }

            // Update movedness count for the moving piece
            this[move.srcPos].moveNumbers.Push(moveCount);
            this[move.srcPos].movedCount++;

            square movingSquare = this[move.srcPos];

            // If this move is a castling, update the rooks movedCount
            if (move.isACastling)
            {
                this[move.castlingRookSrcPos].movedCount++;
                this[move.castlingRookSrcPos].moveNumbers.Push(moveCount);
            }

            // Update the number of moves on this board
            moveCount++;

            // Move our piece from the source to the destination, removing any piece that might be there
            if (this[move.dstPos].type != pieceType.none)
            {
                removePiece(this[move.dstPos]);
                if (!move.isCapture)
                    throw new Exception("Non-capture in to occupied square");
            }
            movePiece(movingSquare, move.dstPos);

            // If we're castling, move the rook appropriately
            if (move.isACastling)
            {
                square rook = move.findCastlingRook(this);
                movePiece(rook, move.findNewPosForCastlingRook());
            }

            square captured;
            if (move.isCapture)
            {
                captured = move.capturedSquare;

                if (!captured.position.isSameSquareAs(move.dstPos))
                {
                    // The capture was not in to our piece's destination square. Set the captured
                    // square to be empty.
                    removePiece(captured);
                }
            }

            if (move.isPawnPromotion)
            {
                removePiece(movingSquare);
                this[move.dstPos] = addPiece(move.typeToPromoteTo, movingSquare.colour, move.dstPos);
                this[move.dstPos].pastLife = movingSquare;
            }

            colToMove = getOtherSide(colToMove);

            // Store this new position on our stack
            if (positionsSoFar != null)
                positionsSoFar.Push(this.ToString());

            sanityCheck();
        }
Example #27
0
        public virtual void undoMove(move move)
        {
            //sanityCheck();

            #if DEBUG
            if (this[move.dstPos].colour == colToMove)
                throw new ArgumentException("Unmoving peice of wrong colour");
            #endif
            // undo our fifty-move counter
            fiftyMoveCounter.Pop();

            // remove this position from our list of played positions
            if (positionsSoFar != null)
            {
                string oldPos = positionsSoFar.Pop();
            #if DEBUG
                if(oldPos != this.ToString())
                    throw new Exception("positionsSoFar contains incorrect pos");
            #endif
            }

            // Revert any promotion
            if (move.isPawnPromotion)
            {
                square promoted = this[move.dstPos];
                removePiece(promoted);
                this[move.dstPos] = promoted.pastLife;
                addPiece(promoted.pastLife, move.dstPos);
            }

            // dec the move counters
            moveCount--;
            this[move.dstPos].movedCount--;
            if (this[move.dstPos].moveNumbers.Count == 0)
                this[move.dstPos].moveNumbers = this[move.dstPos].moveNumbers;

            int popped = this[move.dstPos].moveNumbers.Pop();
            #if DEBUG
            if (popped != moveCount)
                throw new Exception("moveNumbers contains wrong move count");
            #endif

            // Dec the rook's move counter if this is a castling
            square castlingRook = null;
            if (move.isACastling)
            {
                castlingRook = this[move.castlingRookDstPos];
                castlingRook.movedCount--;
                int poppedRook = castlingRook.moveNumbers.Pop();
            #if DEBUG
                if (moveCount != poppedRook)
                    throw new Exception("moveNumbers contains wrong move count after popping uncastling rook");
            #endif
            }

            unmovePiece(move.srcPos, move.dstPos);

            // If a castling, move the rook back too.
            if (move.isACastling)
            {
                removePiece(castlingRook);

                // ReSharper disable PossibleNullReferenceException
                // castlingRook cannot be null at this point, as we set it if there is a castling.
                this[castlingRook.position] = new square(castlingRook.position);
                // ReSharper restore PossibleNullReferenceException
                if (castlingRook.position.x == 3)
                {
                    addPiece(castlingRook, new squarePos(0, castlingRook.position.y));
                }
                else if (castlingRook.position.x == 5)
                {
                    addPiece(castlingRook, new squarePos(7, castlingRook.position.y));
                }
                else
                {
                    throw new Exception("While uncastling, could not find castled rook");
                }
            }

            // Restore any captured piece
            if (move.isCapture)
                addPiece(move.capturedSquare, move.capturedSquarePos);

            colToMove = getOtherSide(colToMove);

            sanityCheck();
        }
Example #28
0
        public void testMoveUndoingEnPassant()
        {
            DoktorChessAIBoard ourBoard = DoktorChessAIBoard.makeFromFEN("8/6p1/8/7P/8/8/8/8 b - - 0 1", gameType.normal, boardSearchConfig.getDebugConfig());

            square enemyPawn = ourBoard[6, 6];

            // Advance the enemy pawn, so we can capture it via en passant
            move advanceTwo = new move(enemyPawn, ourBoard[enemyPawn.position.down(2)]);
            ourBoard.doMove(advanceTwo);

            string origBoard = ourBoard.ToString();

            sizableArray<move> moves = ourBoard.getMoves(pieceColour.white);

            // Play our only capturing move
            move enPassant = Array.Find(moves.getArray(), a => a.isCapture == true);
            if (enPassant == null)
                Assert.Inconclusive("No en passant move found");
            ourBoard.doMove(enPassant);

            if (ourBoard.ToString() == origBoard)
                throw new AssertFailedException("After a move, the board has not changed");

            ourBoard.undoMove(enPassant);

            if (ourBoard.ToString() != origBoard)
                throw new AssertFailedException("After a move undo, the board has changed");
        }
Example #29
0
        public static move fromJSON(string JSON, baseBoard parentBoard)
        {
            minimalMove json = new JavaScriptSerializer().Deserialize<minimalMove>(JSON);

            // Don't forget that the board is inverted, as we show it to the user
            json.srcSquarePos = new squarePos(json.srcSquarePos.x, 7 - json.srcSquarePos.y);
            json.dstSquarePos = new squarePos(json.dstSquarePos.x, 7 - json.dstSquarePos.y);

            move toRet = new move( parentBoard[json.srcSquarePos], parentBoard[json.dstSquarePos]);

            return toRet;
        }
Example #30
0
        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");
                }
            }
        }