Example #1
0
        public void remove(square toRemove)
        {
            int posDirection = toRemove.colour == pieceColour.white ? 1 : -1;

            // Remove the actual piece, and what it threatens.
            foreach (int threatenedSquareFlat in toRemove.coveredSquares )
            {
                squarePos threatenedSquare = squarePos.unflatten(threatenedSquareFlat);

                this[threatenedSquare] -= posDirection;

                // The removed piece no longer threatens this square.
                piecesWhichThreatenSquare[threatenedSquare.x, threatenedSquare.y][toRemove.position] = false;
            }
            toRemove.coveredSquares.Clear();

            // and now force a re-evaluation of things that threatened this square.
            sizableArray<int> piecesToRecalc = new sizableArray<int>(piecesWhichThreatenSquare[toRemove.position.x, toRemove.position.y].Count);
            piecesToRecalc.AddRange(piecesWhichThreatenSquare[toRemove.position.x, toRemove.position.y]);

            foreach (int toRecalcFlat in piecesToRecalc)
            {
                square toRecalc = _parentBoard[squarePos.unflatten(toRecalcFlat)];

                // Knights can never be blocked from accessing squares.
                if (toRecalc.type == pieceType.knight)
                    continue;

                //Pawns can always access their two attack squares.
                if (toRecalc.type == pieceType.pawn)
                    continue;

                int toRecalcAddition = toRecalc.colour == pieceColour.white ? 1 : -1;

                // Remove covered squares which are on the other 'side' of us - for example, if a rook
                // is to our left, remove squares to our right from it.
                int offX = toRecalc.position.x - toRemove.position.x;
                int offY = toRecalc.position.y - toRemove.position.y;

                int sx;
                if (offX < 0)
                    sx = +1;
                else if (offX > 0)
                    sx = -1;
                else
                    sx = 0;

                int sy;
                if (offY < 0)
                    sy = +1;
                else if (offY > 0)
                    sy = -1;
                else
                    sy = 0;

                // Look right up to the edge for all pieces apart from the king, which can look only
                // one square in each direction.
                int limitx = DoktorChessAIBoard.sizeX;
                int limity = DoktorChessAIBoard.sizeY;
                if (toRecalc.type == pieceType.king)
                {
                    limitx = toRecalc.position.x + (2 * sx);
                    limity = toRecalc.position.x + (2 * sx);

                    if (limitx > DoktorChessAIBoard.sizeX)
                        limitx = DoktorChessAIBoard.sizeX;
                    if (limity > DoktorChessAIBoard.sizeY)
                        limity = DoktorChessAIBoard.sizeY;
                }

                //Debug.WriteLine(toRecalc.type + " @ " + toRecalc.position + ":");
                int removex = toRemove.position.x + sx;
                int removey = toRemove.position.y + sy;
                while(removex >= 0 && removex < limitx &&
                      removey >= 0 && removey < limity   )
                {
                    squarePos pos = new squarePos(removex, removey);

                    this[pos] += toRecalcAddition;
                    piecesWhichThreatenSquare[removex, removey][toRecalc.position] = true;
                    toRecalc.coveredSquares[pos.flatten()] = true;

                    //Debug.WriteLine("Added discovered " + pos);

                    // we can threaten one piece, but no farther.
                    if (_parentBoard[removex, removey].type != pieceType.none)
                        break;

                    removex += sx;
                    removey += sy;

                }
            }
            sanityCheck();
        }
Example #2
0
        public void add(int x, int y)
        {
            // This is slightly complicated by the fact that any new piece could block other pieces
            // from threatening squares. Because of this, we keep per-piece 'threat lists' containing
            // the a list of squares threatened by the given piece, and if a piece is placed in to a
            // square threatened by another piece, we then re-evaluate the threatening pieces.

            // Find squares which threaten the square we are placing in to, and stash them in another
            // list
            sizableArray<int> piecesToRecalc = new sizableArray<int>(piecesWhichThreatenSquare[x, y].Count);
            piecesToRecalc.AddRange( piecesWhichThreatenSquare[x, y] );

            // Now, add the new pieces threatened squares
            sizableArray<square> potentialDestSquares = _parentBoard[x, y].getCoveredSquares(_parentBoard);

            // Since our threat map is always stored from white's viewpoint, we should add or subtract
            // depending if threatened pieces are white or black.
            int mapAddition = _parentBoard[x, y].colour == pieceColour.white ? 1 : -1;

            // Now cycle through each move and apply them to our map, and to the piece.
            //_parentBoard[x, y].coveredSquares.Clear();
            foreach (square potentialDstSq in potentialDestSquares)
            {
                // Add the threatened squares to our threat map
                this[potentialDstSq.position] += mapAddition;

                speedySquareList piecesWhichThreatenThisSq = piecesWhichThreatenSquare[potentialDstSq.position.x, potentialDstSq.position.y];
                // update our list of pieces threatening each square
                piecesWhichThreatenThisSq[squarePos.flatten(x, y)] = true;

                // and our list of squares covered by piece
                _parentBoard[x, y].coveredSquares[potentialDstSq.position.flatten()] = true;
            }

            // and then recalculate pieces that need it. To save time, we don't re-evaluate everything-
            // we just remove extra squares based on the piece.
            foreach (int toRecalcPos in piecesToRecalc)
            {
                square toRecalc = _parentBoard[toRecalcPos];

                int toRecalcAddition = toRecalc.colour == pieceColour.white ? 1 : -1;

                // Knights can never be blocked from accessing squares.
                if (toRecalc.type == pieceType.knight)
                    continue;

                 //Pawns can always access their two attack squares.
                if (toRecalc.type == pieceType.pawn)
                    continue;

                // Remove covered squares which are on the other 'side' of us - for example, if a rook
                // is to our left, remove squares to our right from it.

                int offX = toRecalc.position.x - x;
                int offY = toRecalc.position.y - y;

                int sx;
                if (offX < 0)
                    sx = +1;
                else if (offX > 0)
                    sx = -1;
                else
                    sx = 0;

                int sy;
                if (offY < 0)
                    sy = +1;
                else if (offY > 0)
                    sy = -1;
                else
                    sy = 0;

                // Look right up to the edge for all pieces apart from the king, which can look only
                // one square in each direction.
                int limitx = DoktorChessAIBoard.sizeX;
                int limity = DoktorChessAIBoard.sizeY;
                if (toRecalc.type == pieceType.king)
                {
                    limitx = toRecalc.position.x + (sx * 2);
                    limity = toRecalc.position.x + (sy * 2);

                    if (limitx > DoktorChessAIBoard.sizeX)
                        limitx = DoktorChessAIBoard.sizeX;
                    if (limity > DoktorChessAIBoard.sizeY)
                        limity = DoktorChessAIBoard.sizeY;
                }

                //Debug.WriteLine( toRecalc.type + toRecalc.position + ":");
                int removex = x + sx;
                int removey = y + sy;
                while(removex >= 0 && removex < limitx &&
                    removey >= 0 && removey < limity )
                {
                    squarePos toRemoveSqPos = new squarePos(removex, removey);

                    this[toRemoveSqPos] -= toRecalcAddition;

                    speedySquareList piecesWhichThreatenThisSq = piecesWhichThreatenSquare[removex, removey];

                    piecesWhichThreatenThisSq[toRecalc.position] = false;
                    toRecalc.coveredSquares[ toRemoveSqPos ] = false;

                    //Debug.WriteLine("Removed now-blocked " + pos);

                    // we can threaten one piece, but no farther.
                    if (_parentBoard[removex, removey].type != pieceType.none)
                        break;

                    removex += sx;
                    removey += sy;

                }
            }
            sanityCheck();
        }
Example #3
0
        /// <summary>
        /// Return a collecetion of all moves one player may be able to make.
        /// Note that moves in to check will also be returned.
        /// </summary>
        /// <param name="toMoveColour">Side to examine</param>
        /// <returns></returns>
        public sizableArray<move> getMoves(pieceColour toMoveColour)
        {
            List<square> occupiedSquares = getPiecesForColour(toMoveColour);

            // Generously guess the size of this array
            sizableArray<move> possibleMoves = new sizableArray<move>(occupiedSquares.Count * 50);

            // Add all moves from all pieces
            foreach (square occupiedSquare in occupiedSquares)
                possibleMoves.AddRange(occupiedSquare.getPossibleMoves(this));

            return possibleMoves;
        }