Beispiel #1
0
        public Boolean InCheck(int sideToMove)
        {
            int kingsq = King[sideToMove].BitScanForward();
            int xside = sideToMove ^ 1;
            if ((MoveGenerator.BishopAttacks(this, kingsq) & (Bishops[xside] | Queens[xside])) > 0)
                return true;
            else if ((MoveGenerator.RookAttacks(this, kingsq) & (Rooks[xside] | Queens[xside])) > 0)
                return true;
            else if ((MoveGenerator.PawnAttacks[sideToMove, kingsq] & Pawns[xside]) > 0)
                return true;
            else if ((MoveGenerator.KnightMoves[kingsq] & Knights[xside]) > 0)
                return true;
            else if ((MoveGenerator.KingMoves[kingsq] & King[xside]) > 0)
                return true;

            return false;
        }
Beispiel #2
0
        public string ToAlegbraicNotation(Board b)
        {
            //find Piece
            String   output = String.Empty;
            MoveBits bits   = 0;

            if ((b.Knights[b.SideToMove] & BitMask.Mask[From]) > 0)
            {
                bits = MoveBits.Knight;
            }
            else if ((b.Bishops[b.SideToMove] & BitMask.Mask[From]) > 0)
            {
                bits = MoveBits.Bishop;
            }
            else if ((b.Rooks[b.SideToMove] & BitMask.Mask[From]) > 0)
            {
                bits = MoveBits.Rook;
            }
            else if ((b.Queens[b.SideToMove] & BitMask.Mask[From]) > 0)
            {
                bits = MoveBits.Queen;
            }
            else if ((b.Pawns[b.SideToMove] & BitMask.Mask[From]) > 0)
            {
                bits = MoveBits.Pawn;
            }
            else if ((b.King[b.SideToMove] & BitMask.Mask[From]) > 0)
            {
                bits = MoveBits.King;
            }

            if (bits == MoveBits.Pawn)
            {
                if ((Bits & (byte)MoveBits.Capture) > 0)
                {
                    output += outputFiles[From.File()];
                }
            }
            else if (bits == MoveBits.Knight)
            {
                output += 'N';
                var sqs = MoveGenerator.KnightMoves[To] & b.Knights[b.SideToMove];
                if ((sqs).Count() > 1)
                {
                    output += FileOrRank(b, bits);
                }
            }
            else if (bits == MoveBits.Bishop)
            {
                output += 'B';
                var sqs = MoveGenerator.BishopAttacks(b, To) & b.Bishops[b.SideToMove];
                if (sqs.Count() > 1)
                {
                    output += FileOrRank(b, bits);
                }
            }
            else if (bits == MoveBits.Rook)
            {
                output += 'R';
                var sqs = MoveGenerator.RookAttacks(b, To) & b.Rooks[b.SideToMove];
                if (sqs.Count() > 1)
                {
                    output += FileOrRank(b, bits);
                }
            }
            else if (bits == MoveBits.Queen)
            {
                var sqs = MoveGenerator.QueenAttacks(b, To) & b.Queens[b.SideToMove];
                output += 'Q';
                if (sqs.Count() > 1)
                {
                    output += FileOrRank(b, bits);
                }
            }
            else if (bits == MoveBits.King)
            {
                //if we are castling
                if (Math.Abs(To.File() - From.File()) > 1)
                {
                    if (To == 6 || To == 62)
                    {
                        return("O-O");
                    }
                    else
                    {
                        return("O-O-O");
                    }
                }

                output += 'K';
            }
            else
            {
                output = Board.SquareNames[From];
            }

            if ((Bits & (byte)MoveBits.Capture) > 0)
            {
                output += 'x';
            }

            output += Board.SquareNames[To];

            if (Promotion > 0)
            {
                output += "=";
                switch ((Piece)Promotion)
                {
                case Piece.Knight:
                    output += "N";
                    break;

                case Piece.Bishop:
                    output += "B";
                    break;

                case Piece.Rook:
                    output += "R";
                    break;

                case Piece.Queen:
                    output += "Q";
                    break;
                }
            }

            b.MakeMove(this);
            if (b.InCheck(b.SideToMove))
            {
                output += "+";
            }
            b.UnMakeMove();

            return(output);
        }
Beispiel #3
0
        //evaluates exchanges on a square initiated by stm
        public static int Eval(Board b, Move m, int stm)
        {
            ulong[] attackers = new ulong[2];
            int     score     = 0;
            var     sq        = m.To;
            var     pieceVal  = Evaluator.PieceValueOnSquare(b, sq);
            var     attacks   = MoveGenerator.Attacks(b, sq);
            var     mystm     = stm ^ 1;

            attackers[mystm] = attacks & b.Pieces[mystm];
            attackers[stm]   = attacks & b.Pieces[stm];

            //change the pieceVal to be the new piece

            //if there is a promotion, then stm is already up material
            if (m.Promotion > 0)
            {
                pieceVal = Evaluator.PieceValues[m.Promotion];
                score    = pieceVal - 100; //lose the initial pawn
            }
            else
            {
                pieceVal = Evaluator.PieceValues[(int)Move.GetPiece((MoveBits)m.Bits)];
            }

            //add in any material taken on the first capture
            if ((m.Bits & (byte)MoveBits.Capture) > 0)
            {
                score += Evaluator.PieceValueOnSquare(b, m.To);
            }

            //remove the first Move, unless this was a straight pawn push
            if (!((m.Bits & (byte)MoveBits.Pawn) > 0 && Math.Abs(m.From - m.To) == 8))
            {
                attackers[stm] ^= BitMask.Mask[m.From];
            }

            while (attackers[mystm] > 0)
            {
                var  tempAttackers = attackers[mystm];
                var  leastValuable = int.MaxValue;
                int  leastValSq = -1;
                bool promote, promoting = false;

                //make a pass over the attackers to find the lowest valued piece
                while (tempAttackers > 0)
                {
                    promote = false;
                    var attack_sq = tempAttackers.BitScanForward();
                    tempAttackers ^= BitMask.Mask[attack_sq];
                    var attackerVal = Evaluator.PieceValueOnSquare(b, attack_sq);

                    //if we found a pawn capturing onto the 8th rank, we need to consider promotion
                    if (attackerVal == 100 && (sq.Rank() == 0 || sq.Rank() == 7))
                    {
                        //we will treat this attacker as if it were a queen
                        attackerVal = Evaluator.PieceValues[(int)Piece.Queen];
                        promote     = true;
                    }

                    if (attackerVal < leastValuable)
                    {
                        promoting     = promote;
                        leastValSq    = attack_sq;
                        leastValuable = attackerVal;
                    }
                }

                //now we have the least valuable attacker
                //remove whatever value is on the square
                if (mystm == stm)
                {
                    score += pieceVal;
                    if (promoting)
                    {
                        score += leastValuable - 100;//lose the promoting pawn, add in queen
                    }
                }
                else
                {
                    score -= pieceVal;
                    if (promoting)
                    {
                        score -= leastValuable + 100;//lose the promoting pawn, add in queen
                    }
                }

                //update the attacked piece
                pieceVal = leastValuable;

                //remove the attacker
                attackers[mystm] ^= BitMask.Mask[leastValSq];

                //now we check for x-ray attacks
                //the idea here is that if any rooks, queens, or bishops attack the temporary
                //square from the same direction that the temporary square is attacking the target
                //then we have an xray attacker
                var   direction   = MoveGenerator.Directions[leastValSq, sq];
                ulong xrayAttacks = 0;
                switch (Math.Abs(direction))
                {
                case 1:
                case 8:
                    if (((b.Rooks[mystm] | b.Queens[mystm]) & Board.FileMask[sq.File()]) > 0)
                    {
                        xrayAttacks = MoveGenerator.RookAttacks(b, leastValSq) & (b.Rooks[mystm] | b.Queens[mystm]) & attackers[mystm];
                    }
                    break;

                case 7:
                case 9:
                    xrayAttacks = MoveGenerator.BishopAttacks(b, leastValSq) & (b.Bishops[mystm] | b.Queens[mystm]) & attackers[mystm];
                    break;
                }

                while (xrayAttacks > 0)
                {
                    var xraySq = xrayAttacks.BitScanForward();
                    xrayAttacks ^= BitMask.Mask[xraySq];
                    if (MoveGenerator.Directions[xraySq, sq] == direction)
                    {
                        //put this piece in main attackers bitboard
                        attackers[mystm] |= BitMask.Mask[xraySq];
                    }
                }
                //switch stm
                mystm ^= 1;
            }

            return(score);
        }
Beispiel #4
0
        static int EvaluatePieces(Evaluation e)
        {
            //evaluate things like material imbalance,
            //bishop pair, knights supported by pawns, etc.

            int[] eval = new int[2];
            for (int side = 0; side < 2; side++)
            {
                int xside = side ^ 1;

                //evaluate material imbalances
                // a rook+pawn for two pieces is not good

                //if side has only one rook and opponent has two
                if (e.Board.Rooks[side] > 0 &&
                    e.Board.Rooks[xside] > 0 &&
                    e.Board.Rooks[side].Count() == 1 &&
                    e.Board.Rooks[xside].Count() == 2)
                {
                    //if opposite side has two less minors then we get a bonus
                    if (e.Board.Minors(side).Count() - e.Board.Minors(xside).Count() == 2)
                    {
                        eval[side] += MinorMaterialInbalanceBonus;
                    }
                }

                //bishop pair bonus
                eval[side] += (e.Board.Bishops[side].Count() == 2) ? BishopPairBonus : 0;

                //increase the value of rooks as pawns come off the board
                int totalPawns = e.Board.Pawns[0].Count() + e.Board.Pawns[1].Count();
                eval[side] += RookBonusPawnCount[totalPawns];

                //rooks
                var rooks = e.Board.Rooks[side];
                while (rooks > 0)
                {
                    int sq = rooks.BitScanForward();
                    rooks ^= BitMask.Mask[sq];

                    //open file bonus
                    if (e.PawnScore.Files[side, sq.File()] == 0)
                    {
                        eval[side] += RookOnOpenFileBonus / 2;
                        if (e.PawnScore.Files[xside, sq.File()] == 0)
                        {
                            eval[side] = RookOnOpenFileBonus;
                        }
                    }

                    //rooks on the seventh (or eigth)
                    if (side == 0 && sq.Rank() <= 1)
                    {
                        eval[0] += RookOnSeventhBonus;
                    }
                    else if (side == 1 && sq.Rank() >= 6)
                    {
                        eval[1] += RookOnSeventhBonus;
                    }
                }

                //knights
                var knights = e.Board.Knights[side];
                while (knights > 0)
                {
                    int sq = knights.BitScanForward();
                    knights ^= BitMask.Mask[sq];

                    //only looking for forward knights
                    if (side == 0 && sq.Rank() > 3)
                    {
                        continue;
                    }
                    else if (side == 1 && sq.Rank() < 3)
                    {
                        continue;
                    }

                    //look for knights on outposts
                    if ((MoveGenerator.PawnAttacks[xside, sq] & e.Board.Pawns[side]) > 0)
                    {
                        //knight is defended by a pawn
                        //use the passed pawn lookup - minus the file to see if
                        //we have an ouput
                        if ((PassedPawnMask[side, sq] & ~Board.FileMask[sq.File()] & e.Board.Pawns[xside]) == 0)
                        {
                            eval[side] += KnightOnOutpostBonus;
                        }
                    }

                    EvalTrappedKnights(e, eval, side, sq);
                }

                var bishops = e.Board.Bishops[side];
                while (bishops > 0)
                {
                    int sq = bishops.BitScanForward();
                    bishops ^= BitMask.Mask[sq];

                    //evaluate trapped bishops
                    if (side == 0)
                    {
                        if (sq == 23 && //white bishop on h6
                            (e.Board.Pawns[1] & BitMask.Mask[30]) > 0 &&
                            (e.Board.Pawns[1] & BitMask.Mask[21]) > 0)
                        {
                            eval[side] -= PieceValues[(int)Piece.Bishop] / 3;
                        }

                        else if (sq == 16 && //white bishop on a6
                                 (e.Board.Pawns[1] & BitMask.Mask[25]) > 0 &&
                                 (e.Board.Pawns[1] & BitMask.Mask[18]) > 0)
                        {
                            eval[side] -= PieceValues[(int)Piece.Bishop] / 3;
                        }
                    }
                    else
                    {
                        if (sq == 47 && //blackbishop on h3
                            (e.Board.Pawns[0] & BitMask.Mask[38]) > 0 &&
                            (e.Board.Pawns[0] & BitMask.Mask[47]) > 0)
                        {
                            eval[side] -= PieceValues[(int)Piece.Bishop] / 3;
                        }
                        else if (sq == 40 && //black bishop on a3
                                 (e.Board.Pawns[0] & BitMask.Mask[33]) > 0 &&
                                 (e.Board.Pawns[0] & BitMask.Mask[42]) > 0)
                        {
                            eval[side] -= PieceValues[(int)Piece.Bishop] / 3;
                        }
                    }

                    //mobility score
                    var mobilitySquares = MoveGenerator.BishopAttacks(e.Board, sq);
                    eval[side] += mobilitySquares.Count();
                }
            }

            return(eval[e.Board.SideToMove] - eval[e.Board.SideToMove ^ 1]);
        }