int[] getChangedIndices(bool isWhite, int[] lastMove)
 {
     int colorIndex = isWhite ? 0 : 1;
     int oppositeColorIndex = isWhite ? 1 : 0;
     HashSet<int> retVal = new HashSet<int>();
     BitboardLayer nums = new BitboardLayer(c.getDict(true)[pieceIndex.ALL_LOCATIONS].getLayerData() | c.getDict(true)[pieceIndex.ALL_LOCATIONS].getLayerData() | (pieceLocations[colorIndex].getLayerData() ^ c.getDict(isWhite)[pieceIndex.ALL_LOCATIONS].getLayerData()));
     foreach(int i in nums.getTrueIndicies())
     {
         retVal.Add(i);
     }
     int[] arrayForm = new int[retVal.Count];
     retVal.CopyTo(arrayForm);
     return arrayForm;
 }
Beispiel #2
0
 public BitboardLayer(BitboardLayer b)
 {
     layerData = b.getLayerData();
     trueIndicies = new HashSet<int>();
     foreach (int i in b.getTrueIndicies()) { trueIndicies.Add(i); }
 }
        //returns the indicies we need to change findAttackMove / getAttackedSquares for
        /*
        int[] getChangedIndices(bool isWhite, int[] lastMove)
        {
            int colorIndex = isWhite ? 0 : 1;
            int oppositeColorIndex = isWhite ? 1 : 0;
            HashSet<int> retVal = new HashSet<int>();

            BitboardLayer oldAttackedSquares = new BitboardLayer(currAttackedSquares[colorIndex][lastMove[0]].getLayerData() | currValidMoves[colorIndex][lastMove[0]].getLayerData());
            BitboardLayer changedIndicies = new BitboardLayer(pieceLocations[colorIndex].getLayerData() ^ c.getDict(isWhite)[pieceIndex.ALL_LOCATIONS].getLayerData());
            int[] sidesInOrder;
            if (currCheckers[oppositeColorIndex].Count != 0) sidesInOrder = new int[] { oppositeColorIndex, colorIndex };
            else sidesInOrder = new int[] { colorIndex, oppositeColorIndex };

            int currColorIndex = sidesInOrder[0];
            //int consideredIndex = 1 - currColorIndex; //consideredIndex is the index of the opposite side

            foreach (int index in c.getDict(currColorIndex == 0)[pieceIndex.ALL_LOCATIONS].getTrueIndicies())
            {
                BitboardLayer valAttack = new BitboardLayer(currAttackedSquares[currColorIndex][index].getLayerData() | currValidMoves[currColorIndex][index].getLayerData());
                //BitboardLayer valAttack = new BitboardLayer(currAttackedSquares[consideredIndex][index].getLayerData() | currValidMoves[consideredIndex][index].getLayerData());
                foreach (int changedIndex in changedIndicies.getTrueIndicies())
                {
                    if (valAttack.trueAtIndex(changedIndex)) retVal.Add(index); //was attacking (opposite color)
                }
            }

            currColorIndex = 1 - currColorIndex;
            if (currCheckers[1 - currColorIndex].Count != 0) //if the first side was checking the second side
            {
                foreach (int index in c.getDict(currColorIndex == 0)[pieceIndex.ALL_LOCATIONS].getTrueIndicies())
                {
                    retVal.Add(index);
                }
            } else {
                foreach (int index in c.getDict(currColorIndex == 0)[pieceIndex.ALL_LOCATIONS].getTrueIndicies())
                {
                    BitboardLayer valAttack = new BitboardLayer(currAttackedSquares[currColorIndex][index].getLayerData() | currValidMoves[currColorIndex][index].getLayerData());
                    //BitboardLayer valAttack = new BitboardLayer(currAttackedSquares[consideredIndex][index].getLayerData() | currValidMoves[consideredIndex][index].getLayerData());
                    foreach (int changedIndex in changedIndicies.getTrueIndicies())
                    {
                        if (valAttack.trueAtIndex(changedIndex)) retVal.Add(index); //was attacking (opposite color)
                    }
                    //if (valAttack.trueAtIndex(c.getDict(isWhite)[pieceIndex.KING].getTrueIndicies()[0])) retVal.Add(index); //is checking (opposite color)
                }
            }
            foreach (List<int[]> pinList in currPinnedPcs)
            {
                foreach (int[] pin in pinList)
                {
                    retVal.Add(pin[0]);
                    retVal.Add(pin[1]);
                }
            }
            retVal.Add(lastMove[1]);
            foreach (int i in changedIndicies.getTrueIndicies())
            {
                retVal.Add(i);
            }
            int[] arrayForm = new int[retVal.Count];
            retVal.CopyTo(arrayForm);
            return arrayForm;
        }
        */
        //updates both black and white's attacked squares
        public void updatePosition(bool isWhite, int[] move)
        {
            int colorIndex = isWhite ? 0 : 1;
            int oppositeColorIndex = isWhite ? 1 : 0;

            //get changed indices before we update all locations
            int[] changedIndicies = getChangedIndices(isWhite, move);
            pieceLocations[colorIndex] = c.getDict(isWhite)[pieceIndex.ALL_LOCATIONS];

            /*
            int oldLocation = move[0];
            currAttackedSquares[colorIndex][oldLocation] = new BitboardLayer();
            */
            for (int i = 0; i < 2; i++) {
                kingAttackedSquares[i] = new BitboardLayer();
                currCheckers[i] = new List<int[]>();
                currPinnedPcs[i] = new List<int[]>();
            }
            //if move was a capture, nullify all valid moves and attacked squares
            //pins and checks are cleared and re-revaluated every move, so no need to directly nullify them
            if (pieceLocations[oppositeColorIndex].trueAtIndex(move[1])) {
                currValidMoves[oppositeColorIndex][move[1]] = new BitboardLayer();
                currAttackedSquares[oppositeColorIndex][move[1]] = new BitboardLayer();
            }

            BitboardLayer allOccupiedSquares = new BitboardLayer(c.getDict(true)[pieceIndex.ALL_LOCATIONS].getLayerData() | c.getDict(false)[pieceIndex.ALL_LOCATIONS].getLayerData());
            bool ftupdate = false;
            foreach (int location in changedIndicies)
            {
                numIterations++;
                /*
                if (numIterations == 244438)
                {
                    Debug.Print("Found bug!");
                }
                */
                if (allOccupiedSquares.trueAtIndex(location))
                {
                    findAttackMove(pieceLocations[0].trueAtIndex(location), location);
                    if (location == 57 && currValidMoves[0][57].getLayerData() == 10489856)
                    {
                        Debug.Print("Knight updated! New value: " + currAttackedSquares[0][52].getLayerData() + " numIterations: " + numIterations);
                    }
                }
                else
                {
                    for (int i = 0; i < 2; i++)
                    {
                        currAttackedSquares[i][location] = new BitboardLayer();
                        currValidMoves[i][location] = new BitboardLayer();
                    }
                }
                //update valid moves and attacked squares for piece at location
            }
            foreach (int[] pin in currPinnedPcs[colorIndex])
            {
                //format: pinner, pinned piece, interval
                ulong vMoveLayer = 0uL;
                for (int i = pin[0]; checkCollision(oppositeColorIndex == 1, i) != 3; i += pin[2])
                {
                    vMoveLayer |= 1uL << (63 - i);
                }
                currValidMoves[oppositeColorIndex][pin[1]].setLayerData(currValidMoves[oppositeColorIndex][pin[1]].getLayerData() & vMoveLayer);
            }
            foreach (int[] pin in currPinnedPcs[oppositeColorIndex])
            {
                ulong vMoveLayer = 0uL;
                for (int i = pin[0]; checkCollision(colorIndex == 1, i) != 3; i += pin[2])
                {
                    vMoveLayer |= 1uL << (63 - i);
                }
                currValidMoves[colorIndex][pin[1]].setLayerData(currValidMoves[oppositeColorIndex][pin[1]].getLayerData() & vMoveLayer);
            }
            //get all attacked squares so we can get king's valid moves
            for (int i = 0; i < 2; i++)
            {
                ulong fullAttackedSq = 0;
                foreach(BitboardLayer pieceAttackedSq in currAttackedSquares[i])
                {
                    fullAttackedSq |= pieceAttackedSq.getLayerData();
                }
                allAttackedSq[i] = new BitboardLayer(fullAttackedSq);
            }

            //to make sure only valid moves are considered, bitwise-AND each non-king's valid moves with position of each piece attacking the king and their attack vector
            //if double-checked, this makes sure no positions will show up
            //otherwise will automatically limit to capture or block
            for (int i = 0; i < 2; i++)
            {
                int kingPos = c.getDict(i == 1)[pieceIndex.KING].getTrueIndicies()[0];
                //if opponent is checking, limit valid moves
                foreach (int[] checker in currCheckers[1 - i])
                {
                    ulong vMoveMask = 0;
                    for (int j = checker[0]; checkCollision(i == 1, j) != 3; j += checker[1])
                    {
                        vMoveMask |= 1uL << (63 - j);
                    }
                    for(int j = 0; j < 64; j++)
                    {
                        currValidMoves[i][j].setLayerData(currValidMoves[i][j].getLayerData() & vMoveMask);
                    }
                }

                //limit king's valid moves
                BitboardLayer kingVMoves = new BitboardLayer(currAttackedSquares[i][kingPos].getLayerData());
                foreach (int possibleMove in kingVMoves.getTrueIndicies())
                {
                    if (checkCollision(i == 0, i) == 2) kingVMoves.setAtIndex(possibleMove, false);
                    if (allAttackedSq[1 - i].trueAtIndex(possibleMove)) kingVMoves.setAtIndex(possibleMove, false);
                    if (kingAttackedSquares[1 - i].trueAtIndex(possibleMove)) kingVMoves.setAtIndex(possibleMove, false);
                }

                //castling
                if (canCastle[i][1] && !allAttackedSq[1 - i].trueAtIndex(kingPos + 1) && !allAttackedSq[1 - i].trueAtIndex(kingPos + 2)) //can castle right
                {
                    kingVMoves.setAtIndex(kingPos + 2, true);
                }
                if (canCastle[i][0] && !allAttackedSq[1 - i].trueAtIndex(kingPos - 1) && !allAttackedSq[1 - i].trueAtIndex(kingPos - 2))
                {
                    kingVMoves.setAtIndex(kingPos - 2, true);
                }
                currValidMoves[i][kingPos] = new BitboardLayer(kingVMoves);
            }
            for (int i = 0; i < 2; i++)
            {
                ulong fullValidMoves = 0;
                foreach (BitboardLayer pieceValidMoves in currValidMoves[i])
                {
                    fullValidMoves |= pieceValidMoves.getLayerData();
                    pieceValidMoves.setAtIndex(c.getDict(i == 1)[pieceIndex.KING].getTrueIndicies()[0], false);
                }
                allValidMoves[i] = new BitboardLayer(fullValidMoves);
            }
        }