Example #1
0
 /** Record move as a failure. */
 public void addFail(Position pos, Move m, int depth)
 {
     int p = pos.getPiece(m.from);
     int cnt = depth;
     countFail[p][m.to] += cnt;
     score[p][m.to] = -1;
 }
Example #2
0
 /**
  * Return true if the side to move can take the opponents king.
  */
 public static bool canTakeKing(Position pos)
 {
     pos.setWhiteMove(!pos.whiteMove);
     bool ret = inCheck(pos);
     pos.setWhiteMove(!pos.whiteMove);
     return ret;
 }
Example #3
0
 /**
  * Prints board to console
  */
 public static void DispBoard(Position pos)
 {
     string ll = "    +----+----+----+----+----+----+----+----+";
     SystemHelper.println(ll);
     for (int y = 7; y >= 0; y--) {
     string ret = "    |";
     for (int x = 0; x < 8; x++) {
         ret+=' ';
         int p = pos.getPiece(Position.getSquare(x, y));
         if (p == Piece.EMPTY) {
             bool dark = Position.darkSquare(x, y);
             ret+=(dark ? ".. |" : "   |");
         } else {
             ret+=(Piece.isWhite(p) ? ' ' : '*');
             string pieceName = pieceToChar(p);
             if (pieceName.Length == 0)
                 pieceName = "P";
             ret+=pieceName;
             ret+=" |";
         }
     }
     SystemHelper.println(ret);
     SystemHelper.println(ll);
     }
 }
        public string getCommand(Position pos, bool drawOffer, List<Position> history)
        {
            // Create a search object
            ulong[] posHashList = new ulong[200 + history.Count];
            int posHashListSize = 0;
            for(int i=0;i<history.Count;i++)
            {
            Position p = history[i];
            posHashList[posHashListSize++] = p.zobristHash();
            }
            tt.nextGeneration();
            Search sc = new Search(pos, posHashList, posHashListSize, tt);

            // Determine all legal moves
            MoveGen.MoveList moves = new MoveGen().pseudoLegalMoves(pos);
            MoveGen.RemoveIllegal(pos, moves);
            sc.scoreMoveList(moves, 0);

            // Test for "game over"
            if (moves.size == 0) {
            // Switch sides so that the human can decide what to do next.
            return "swap";
            }

            if (bookEnabled) {
            Move bookMove = book.getBookMove(pos);
            if (bookMove != null) {
                SystemHelper.printf("Book moves: " + book.getAllBookMoves(pos));
                return TextIO.moveTostring(pos, bookMove, true);
            }
            }

            // Find best move using iterative deepening
            currentSearch = sc;
            sc.setListener(listener);
            Move bestM;
            if ((moves.size == 1) && (canClaimDraw(pos, posHashList, posHashListSize, moves.m[0]) == "")) {
            bestM = moves.m[0];
            bestM.score = 0;
            } else if (randomMode) {
            bestM = findSemiRandomMove(sc, moves);
            } else {
            sc.timeLimit(minTimeMillis, maxTimeMillis);
            bestM = sc.iterativeDeepening(moves, maxDepth, maxNodes, verbose);
            }
            currentSearch = null;
            //        tt.printStats();
            string strMove = TextIO.moveTostring(pos, bestM, true);
            bestmv = bestM;

            // Claim draw if appropriate
            if (bestM.score <= 0) {
            string drawClaim = canClaimDraw(pos, posHashList, posHashListSize, bestM);
            if (drawClaim != "")
                strMove = drawClaim;
            }
            return strMove;
        }
Example #5
0
 // To get all valid moves in one text-string
 public static string AllMovesTostring(Position pos, bool ulongForm)
 {
     string ret = "";
     MoveGen MG = new MoveGen();
     MoveGen.MoveList moves = MG.pseudoLegalMoves(pos);
     MoveGen.RemoveIllegal(pos, moves);
     for (int i = 0; i < moves.size; i++)
     {
     ret += moveTostring(pos, moves.m[i], ulongForm, moves) + ";";
     }
     return ret;
 }
Example #6
0
 /** Record move as a success. */
 public void addSuccess(Position pos, Move m, int depth)
 {
     int p = pos.getPiece(m.from);
     int cnt = depth;
     int val = countSuccess[p][m.to] + cnt;
     if (val > 1000) {
     val /= 2;
     countFail[p][m.to] /= 2;
     }
     countSuccess[p][m.to] = val;
     score[p][m.to] = -1;
 }
Example #7
0
 /** Return a string describing all book moves. */
 public string getAllBookMoves(Position pos)
 {
     string ret = "";
     List<BookEntry> bookMoves = bookMap[pos.zobristHash()];
     if (bookMoves != null) {
     BookEntry be;
     for (int i = 0; i < bookMoves.Count; i++) {
         be = bookMoves[i];
         string moveStr = TextIO.moveTostring(pos, be.move, false);
         ret = ret + (moveStr + "(" + be.count.ToString() + ") ");
     }
     }
     return ret;
 }
Example #8
0
 //@Override
 public string getCommand(Position pos, bool drawOffer, List<Position> history)
 {
     try {
     string moveStr = inp;
     if (moveStr == null)
         return "quit";
     if (moveStr.Length == 0) {
         return lastCmd;
     } else {
         lastCmd = moveStr;
     }
     return moveStr;
     } catch (IOException ex) {
     return "quit";
     }
 }
Example #9
0
 /** Get a score between 0 and 49, depending of the success/fail ratio of the move. */
 public int getHistScore(Position pos, Move m)
 {
     int p = pos.getPiece(m.from);
     int ret = score[p][m.to];
     if (ret >= 0)
     return ret;
     int succ = countSuccess[p][m.to];
     int fail = countFail[p][m.to];
     if (succ + fail > 0) {
     ret = succ * 49 / (succ + fail);
     } else {
     ret = 0;
     }
     score[p][m.to] = ret;
     return ret;
 }
 /** Extract the PV starting from pos, using hash entries, both exact scores and bounds. */
 public string extractPV(Position pos)
 {
     string ret = "";
     pos = new Position(pos);    // To avoid modifying the input parameter
     bool first = true;
     TTEntry ent = probe(pos.historyHash());
     UndoInfo ui = new UndoInfo();
     List<ulong> hashHistory = new List<ulong>();
     bool repetition = false;
     while (ent.type != TTEntry.T_EMPTY) {
     string type = "";
     if (ent.type == TTEntry.T_LE) {
         type = "<";
     } else if (ent.type == TTEntry.T_GE) {
         type = ">";
     }
     Move m = new Move(0,0,0);
     ent.getMove(m);
     MoveGen MG = new MoveGen();
     MoveGen.MoveList moves = MG.pseudoLegalMoves(pos);
     MoveGen.RemoveIllegal(pos, moves);
     bool contains = false;
     for (int mi = 0; mi < moves.size; mi++)
         if (moves.m[mi].equals(m)) {
             contains = true;
             break;
         }
     if  (!contains)
         break;
     string moveStr = TextIO.moveTostring(pos, m, false);
     if (repetition)
         break;
     if (!first) {
         ret += " ";
     }
     ret += type + moveStr;
     pos.makeMove(m, ui);
     if (hashHistory.Contains(pos.zobristHash())) {
         repetition = true;
     }
     hashHistory.Add(pos.zobristHash());
     ent = probe(pos.historyHash());
     first = false;
     }
     return ret;
 }
Example #11
0
        /** Return a random book move for a position, or null if out of book. */
        public Move getBookMove(Position pos)
        {
            long t0 = SystemHelper.currentTimeMillis();
            Random rndGen = new Random((int)t0);
            ulong key = pos.zobristHash();
            bool iskey = bookMap.ContainsKey(key);
            List<BookEntry> bookMoves = (iskey ? bookMap[key] : null);
            if (bookMoves == null) {
            return null;
            }

            MoveGen.MoveList legalMoves = new MoveGen().pseudoLegalMoves(pos);
            MoveGen.RemoveIllegal(pos, legalMoves);
            int sum = 0;
            for (int i = 0; i < bookMoves.Count; i++) {
            BookEntry be = bookMoves[i];
            bool contains = false;
            for (int mi = 0; mi < legalMoves.size; mi++)
                if (legalMoves.m[mi].equals(be.move)) {
                    contains = true;
                    break;
                }
            if  (!contains) {
                // If an illegal move was found, it means there was a hash collision.
                return null;
            }
            sum += getWeight(bookMoves[i].count);
            }
            if (sum <= 0) {
            return null;
            }
            int rnd = rndGen.Next(sum);
            sum = 0;
            for (int i = 0; i < bookMoves.Count; i++) {
            sum += getWeight(bookMoves[i].count);
            if (rnd < sum) {
                return bookMoves[i].move;
            }
            }
            // Should never get here
            throw new RuntimeException();
        }
Example #12
0
 /** Remove pseudo-legal EP square if it is not legal, ie would leave king in check. */
 public static void fixupEPSquare(Position pos)
 {
     int epSquare = pos.getEpSquare();
     if (epSquare >= 0) {
     MoveGen MG = new MoveGen();
     MoveGen.MoveList moves = MG.pseudoLegalMoves(pos);
     MoveGen.RemoveIllegal(pos, moves);
     bool epValid = false;
     for (int mi = 0; mi < moves.size; mi++) {
         Move m = moves.m[mi];
         if (m.to == epSquare) {
             if (pos.getPiece(m.from) == (pos.whiteMove ? Piece.WPAWN : Piece.BPAWN)) {
                 epValid = true;
                 break;
             }
         }
     }
     if (!epValid) {
         pos.setEpSquare(-1);
     }
     }
 }
Example #13
0
        /** Compute king safety for both kings. */
        private int kingSafety(Position pos)
        {
            int minM = rV + bV;
            int m = (pos.wMtrl - pos.wMtrlPawns + pos.bMtrl - pos.bMtrlPawns) / 2;
            if (m <= minM)
            return 0;
            int maxM = qV + 2 * rV + 2 * bV + 2 * nV;
            int score = kingSafetyKPPart(pos);
            if (Position.getY(pos.wKingSq) == 0) {
            if (((pos.pieceTypeBB[Piece.WKING] & 0x60L) != 0) && // King on f1 or g1
                ((pos.pieceTypeBB[Piece.WROOK] & 0xC0L) != 0) && // Rook on g1 or h1
                ((pos.pieceTypeBB[Piece.WPAWN] & BitBoard.maskFile[6]) != 0) &&
                ((pos.pieceTypeBB[Piece.WPAWN] & BitBoard.maskFile[7]) != 0)) {
                score -= 6 * 15;
            } else
            if (((pos.pieceTypeBB[Piece.WKING] & 0x6L) != 0) && // King on b1 or c1
                ((pos.pieceTypeBB[Piece.WROOK] & 0x3L) != 0) && // Rook on a1 or b1
                ((pos.pieceTypeBB[Piece.WPAWN] & BitBoard.maskFile[0]) != 0) &&
                ((pos.pieceTypeBB[Piece.WPAWN] & BitBoard.maskFile[1]) != 0)) {
                score -= 6 * 15;
            }
            }
            if (Position.getY(pos.bKingSq) == 7) {
            if (((pos.pieceTypeBB[Piece.BKING] & 0x6000000000000000L) != 0) && // King on f8 or g8
                ((pos.pieceTypeBB[Piece.BROOK] & 0xC000000000000000L) != 0) && // Rook on g8 or h8
                ((pos.pieceTypeBB[Piece.BPAWN] & BitBoard.maskFile[6]) != 0) &&
                ((pos.pieceTypeBB[Piece.BPAWN] & BitBoard.maskFile[7]) != 0)) {
                score += 6 * 15;
            } else
            if (((pos.pieceTypeBB[Piece.BKING] & 0x600000000000000L) != 0) && // King on b8 or c8
                ((pos.pieceTypeBB[Piece.BROOK] & 0x300000000000000L) != 0) && // Rook on a8 or b8
                ((pos.pieceTypeBB[Piece.BPAWN] & BitBoard.maskFile[0]) != 0) &&
                ((pos.pieceTypeBB[Piece.BPAWN] & BitBoard.maskFile[1]) != 0)) {
                score += 6 * 15;
            }
            }
            score += (bKingAttacks - wKingAttacks) * 4;
            int kSafety = interpolate(m, minM, 0, maxM, score);
            return kSafety;

            // FIXME! g pawn is valuable (avoid g5, g4, gxf5)
        }
Example #14
0
        /** Implements special knowledge for some endgame situations. */
        private int endGameEval(Position pos, int oldScore)
        {
            int score = oldScore;
            if (pos.wMtrl + pos.bMtrl > 6 * rV)
            return score;
            int wMtrlPawns = pos.wMtrlPawns;
            int bMtrlPawns = pos.bMtrlPawns;
            int wMtrlNoPawns = pos.wMtrl - wMtrlPawns;
            int bMtrlNoPawns = pos.bMtrl - bMtrlPawns;

            bool handled = false;
            if ((wMtrlPawns + bMtrlPawns == 0) && (wMtrlNoPawns < rV) && (bMtrlNoPawns < rV)) {
            // King + minor piece vs king + minor piece is a draw
            return 0;
            }
            if (!handled && (pos.wMtrl == qV) && (pos.bMtrl == pV) &&
            (BITS.bitCount(pos.pieceTypeBB[Piece.WQUEEN]) == 1)) {
            int wk = BitBoard.numberOfTrailingZeros(pos.pieceTypeBB[Piece.WKING]);
            int wq = BitBoard.numberOfTrailingZeros(pos.pieceTypeBB[Piece.WQUEEN]);
            int bk = BitBoard.numberOfTrailingZeros(pos.pieceTypeBB[Piece.BKING]);
            int bp = BitBoard.numberOfTrailingZeros(pos.pieceTypeBB[Piece.BPAWN]);
            score = evalKQKP(wk, wq, bk, bp);
            handled = true;
            }
            if (!handled && (pos.bMtrl == qV) && (pos.wMtrl == pV) &&
            (BITS.bitCount(pos.pieceTypeBB[Piece.BQUEEN]) == 1)) {
            int bk = BitBoard.numberOfTrailingZeros(pos.pieceTypeBB[Piece.BKING]);
            int bq = BitBoard.numberOfTrailingZeros(pos.pieceTypeBB[Piece.BQUEEN]);
            int wk = BitBoard.numberOfTrailingZeros(pos.pieceTypeBB[Piece.WKING]);
            int wp = BitBoard.numberOfTrailingZeros(pos.pieceTypeBB[Piece.WPAWN]);
            score = -evalKQKP(63-bk, 63-bq, 63-wk, 63-wp);
            handled = true;
            }
            if (!handled && (score > 0)) {
            if ((wMtrlPawns == 0) && (wMtrlNoPawns <= bMtrlNoPawns + bV)) {
                if (wMtrlNoPawns < rV) {
                    return -pos.bMtrl / 50;
                } else {
                    score /= 8;         // Too little excess material, probably draw
                    handled = true;
                }
            } else if ((pos.pieceTypeBB[Piece.WROOK] | pos.pieceTypeBB[Piece.WKNIGHT] |
                        pos.pieceTypeBB[Piece.WQUEEN]) == 0) {
                // Check for rook pawn + wrong color bishop
                if (((pos.pieceTypeBB[Piece.WPAWN] & BitBoard.maskBToHFiles) == 0) &&
                    ((pos.pieceTypeBB[Piece.WBISHOP] & BitBoard.maskLightSq) == 0) &&
                    ((pos.pieceTypeBB[Piece.BKING] & 0x0303000000000000L) != 0)) {
                    return 0;
                } else
                if (((pos.pieceTypeBB[Piece.WPAWN] & BitBoard.maskAToGFiles) == 0) &&
                    ((pos.pieceTypeBB[Piece.WBISHOP] & BitBoard.maskDarkSq) == 0) &&
                    ((pos.pieceTypeBB[Piece.BKING] & 0xC0C0000000000000L) != 0)) {
                    return 0;
                }
            }
            }
            if (!handled) {
            if (bMtrlPawns == 0) {
                if (wMtrlNoPawns - bMtrlNoPawns > bV) {
                    int wKnights = BITS.bitCount(pos.pieceTypeBB[Piece.WKNIGHT]);
                    int wBishops = BITS.bitCount(pos.pieceTypeBB[Piece.WBISHOP]);
                    if ((wKnights == 2) && (wMtrlNoPawns == 2 * nV) && (bMtrlNoPawns == 0)) {
                        score /= 50;    // KNNK is a draw
                    } else if ((wKnights == 1) && (wBishops == 1) && (wMtrlNoPawns == nV + bV) && (bMtrlNoPawns == 0)) {
                        score /= 10;
                        score += nV + bV + 300;
                        int kSq = pos.getKingSq(false);
                        int x = Position.getX(kSq);
                        int y = Position.getY(kSq);
                        if ((pos.pieceTypeBB[Piece.WBISHOP] & BitBoard.maskDarkSq) != 0) {
                            score += (7 - distToH1A8[7-y][7-x]) * 10;
                        } else {
                            score += (7 - distToH1A8[7-y][x]) * 10;
                        }
                    } else {
                        score += 300;       // Enough excess material, should win
                    }
                    handled = true;
                } else if ((wMtrlNoPawns + bMtrlNoPawns == 0) && (wMtrlPawns == pV)) { // KPK
                    int wp = BitBoard.numberOfTrailingZeros(pos.pieceTypeBB[Piece.WPAWN]);
                    score = kpkEval(pos.getKingSq(true), pos.getKingSq(false),
                                    wp, pos.whiteMove);
                    handled = true;
                }
            }
            }
            if (!handled && (score < 0)) {
            if ((bMtrlPawns == 0) && (bMtrlNoPawns <= wMtrlNoPawns + bV)) {
                if (bMtrlNoPawns < rV) {
                    return pos.wMtrl / 50;
                } else {
                    score /= 8;         // Too little excess material, probably draw
                    handled = true;
                }
            } else if ((pos.pieceTypeBB[Piece.BROOK] | pos.pieceTypeBB[Piece.BKNIGHT] |
                        pos.pieceTypeBB[Piece.BQUEEN]) == 0) {
                // Check for rook pawn + wrong color bishop
                if (((pos.pieceTypeBB[Piece.BPAWN] & BitBoard.maskBToHFiles) == 0) &&
                    ((pos.pieceTypeBB[Piece.BBISHOP] & BitBoard.maskDarkSq) == 0) &&
                    ((pos.pieceTypeBB[Piece.WKING] & 0x0303L) != 0)) {
                    return 0;
                } else
                if (((pos.pieceTypeBB[Piece.BPAWN] & BitBoard.maskAToGFiles) == 0) &&
                    ((pos.pieceTypeBB[Piece.BBISHOP] & BitBoard.maskLightSq) == 0) &&
                    ((pos.pieceTypeBB[Piece.WKING] & 0xC0C0L) != 0)) {
                    return 0;
                }
            }
            }
            if (!handled) {
            if (wMtrlPawns == 0) {
                if (bMtrlNoPawns - wMtrlNoPawns > bV) {
                    int bKnights = BITS.bitCount(pos.pieceTypeBB[Piece.BKNIGHT]);
                    int bBishops = BITS.bitCount(pos.pieceTypeBB[Piece.BBISHOP]);
                    if ((bKnights == 2) && (bMtrlNoPawns == 2 * nV) && (wMtrlNoPawns == 0)) {
                        score /= 50;    // KNNK is a draw
                    } else if ((bKnights == 1) && (bBishops == 1) && (bMtrlNoPawns == nV + bV) && (wMtrlNoPawns == 0)) {
                        score /= 10;
                        score -= nV + bV + 300;
                        int kSq = pos.getKingSq(true);
                        int x = Position.getX(kSq);
                        int y = Position.getY(kSq);
                        if ((pos.pieceTypeBB[Piece.BBISHOP] & BitBoard.maskDarkSq) != 0) {
                            score -= (7 - distToH1A8[7-y][7-x]) * 10;
                        } else {
                            score -= (7 - distToH1A8[7-y][x]) * 10;
                        }
                    } else {
                        score -= 300;       // Enough excess material, should win
                    }
                    handled = true;
                } else if ((wMtrlNoPawns + bMtrlNoPawns == 0) && (bMtrlPawns == pV)) { // KPK
                    int bp = BitBoard.numberOfTrailingZeros(pos.pieceTypeBB[Piece.BPAWN]);
                    score = -kpkEval(63-pos.getKingSq(false), 63-pos.getKingSq(true),
                                     63-bp, !pos.whiteMove);
                    handled = true;
                }
            }
            }
            return score;

            // FIXME! Add evaluation of KRKP
            // FIXME! Add evaluation of KRPKR   : eg 8/8/8/5pk1/1r6/R7/8/4K3 w - - 0 74
            // FIXME! KRBKR is very hard to draw
        }
Example #15
0
        /** Compute pawn hash data for pos. */
        private void computePawnHashData(Position pos, PawnHashData ph)
        {
            int score = 0;

            // Evaluate double pawns and pawn islands
            ulong wPawns = pos.pieceTypeBB[Piece.WPAWN];
            ulong wPawnFiles = BitBoard.southFill(wPawns) & 0xff;
            int wDouble = BITS.bitCount(wPawns) - BITS.bitCount(wPawnFiles);
            int wIslands = BITS.bitCount(((~wPawnFiles) >> 1) & wPawnFiles);
            int wIsolated = BITS.bitCount(~(wPawnFiles<<1) & wPawnFiles & ~(wPawnFiles>>1));

            ulong bPawns = pos.pieceTypeBB[Piece.BPAWN];
            ulong bPawnFiles = BitBoard.southFill(bPawns) & 0xff;
            int bDouble = BITS.bitCount(bPawns) - BITS.bitCount(bPawnFiles);
            int bIslands = BITS.bitCount(((~bPawnFiles) >> 1) & bPawnFiles);
            int bIsolated = BITS.bitCount(~(bPawnFiles<<1) & bPawnFiles & ~(bPawnFiles>>1));

            score -= (wDouble - bDouble) * 25;
            score -= (wIslands - bIslands) * 15;
            score -= (wIsolated - bIsolated) * 15;

            // Evaluate backward pawns, defined as a pawn that guards a friendly pawn,
            // can't be guarded by friendly pawns, can advance, but can't advance without
            // being captured by an enemy pawn.
            ulong wPawnAttacks = (((wPawns & BitBoard.maskBToHFiles) << 7) |
                             ((wPawns & BitBoard.maskAToGFiles) << 9));
            ulong bPawnAttacks = (((bPawns & BitBoard.maskBToHFiles) >> 9) |
                             ((bPawns & BitBoard.maskAToGFiles) >> 7));
            ulong wBackward = wPawns & ~((wPawns | bPawns) >> 8) & (bPawnAttacks >> 8) &
                         ~BitBoard.northFill(wPawnAttacks);
            wBackward &= (((wPawns & BitBoard.maskBToHFiles) >> 9) |
                      ((wPawns & BitBoard.maskAToGFiles) >> 7));
            wBackward &= ~BitBoard.northFill(bPawnFiles);
            ulong bBackward = bPawns & ~((wPawns | bPawns) << 8) & (wPawnAttacks << 8) &
                         ~BitBoard.southFill(bPawnAttacks);
            bBackward &= (((bPawns & BitBoard.maskBToHFiles) << 7) |
                      ((bPawns & BitBoard.maskAToGFiles) << 9));
            bBackward &= ~BitBoard.northFill(wPawnFiles);
            score -= (BITS.bitCount(wBackward) - BITS.bitCount(bBackward)) * 15;

            // Evaluate passed pawn bonus, white
            ulong passedPawnsW = wPawns & ~BitBoard.southFill(bPawns | bPawnAttacks | (wPawns >> 8));
            int[] ppBonus = {-1,24,26,30,36,47,64,-1};
            int passedBonusW = 0;
            if (passedPawnsW != 0) {
            ulong guardedPassedW = passedPawnsW & (((wPawns & BitBoard.maskBToHFiles) << 7) |
                                                  ((wPawns & BitBoard.maskAToGFiles) << 9));
            passedBonusW += 15 * BITS.bitCount(guardedPassedW);
            ulong m = passedPawnsW;
            while (m != 0) {
                int sq = /*long.numberOfTrailingZeros(m) */  BitBoard.numberOfTrailingZeros(m);
                int y = Position.getY(sq);
                passedBonusW += ppBonus[y];
                m &= m-1;
            }
            }

            // Evaluate passed pawn bonus, black
            ulong passedPawnsB = bPawns & ~BitBoard.northFill(wPawns | wPawnAttacks | (bPawns << 8));
            int passedBonusB = 0;
            if (passedPawnsB != 0) {
            ulong guardedPassedB = passedPawnsB & (((bPawns & BitBoard.maskBToHFiles) >> 9) |
                                                  ((bPawns & BitBoard.maskAToGFiles) >> 7));
            passedBonusB += 15 * BITS.bitCount(guardedPassedB);
            ulong m = passedPawnsB;
            while (m != 0) {
                int sq = /*long.numberOfTrailingZeros(m) */  BitBoard.numberOfTrailingZeros(m);
                int y = Position.getY(sq);
                passedBonusB += ppBonus[7-y];
                m &= m-1;
            }
            }

            // Connected passed pawn bonus. Seems logical but doesn't help in tests
            //        if (passedPawnsW != 0)
            //            passedBonusW += 15 * BITS.bitCount(passedPawnsW & ((passedPawnsW & BitBoard.maskBToHFiles) >> 1));
            //        if (passedPawnsB != 0)
            //            passedBonusB += 15 * BITS.bitCount(passedPawnsB & ((passedPawnsB & BitBoard.maskBToHFiles) >> 1));

            ph.key = pos.pawnZobristHash();
            ph.score = score;
            ph.passedBonusW = (short)passedBonusW;
            ph.passedBonusB = (short)passedBonusB;
            ph.passedPawnsW = passedPawnsW;
            ph.passedPawnsB = passedPawnsB;
        }
Example #16
0
        /** Score castling ability. */
        private int castleBonus(Position pos)
        {
            if (pos.getCastleMask() == 0) return 0;

            int k1 = kt1b[7*8+6] - kt1b[7*8+4];
            int k2 = kt2b[7*8+6] - kt2b[7*8+4];
            int t1 = qV + 2 * rV + 2 * bV;
            int t2 = rV;
            int t = pos.bMtrl - pos.bMtrlPawns;
            int ks = interpolate(t, t2, k2, t1, k1);

            int castleValue = ks + rt1b[7*8+5] - rt1b[7*8+7];
            if (castleValue <= 0)
            return 0;

            ulong occupied = pos.whiteBB | pos.blackBB;
            int tmp = (int) (occupied & 0x6E);
            if (pos.a1Castle()) tmp |= 1;
            if (pos.h1Castle()) tmp |= (1 << 7);
            int wBonus = (castleValue * castleFactor[tmp]) >> 10;

            tmp = (int) ((occupied >> 56) & 0x6E);
            if (pos.a8Castle()) tmp |= 1;
            if (pos.h8Castle()) tmp |= (1 << 7);
            int bBonus = (castleValue * castleFactor[tmp]) >> 10;

            return wBonus - bBonus;
        }
Example #17
0
 private static bool isCapture(Position pos, Move move)
 {
     if (pos.getPiece(move.to) == Piece.EMPTY) {
     int p = pos.getPiece(move.from);
     if ((p == (pos.whiteMove ? Piece.WPAWN : Piece.BPAWN)) && (move.to == pos.getEpSquare())) {
         return true;
     } else {
         return false;
     }
     } else {
     return true;
     }
 }
Example #18
0
        /** Compute score based on piece square tables. Positive values are good for white. */
        private int pieceSquareEval(Position pos)
        {
            int score = 0;
            int wMtrl = pos.wMtrl;
            int bMtrl = pos.bMtrl;
            int wMtrlPawns = pos.wMtrlPawns;
            int bMtrlPawns = pos.bMtrlPawns;

            // Kings
            {
            int t1 = qV + 2 * rV + 2 * bV;
            int t2 = rV;
            {
                int k1 = pos.psScore1[Piece.WKING];
                int k2 = pos.psScore2[Piece.WKING];
                int t = bMtrl - bMtrlPawns;
                score += interpolate(t, t2, k2, t1, k1);
            }
            {
                int k1 = pos.psScore1[Piece.BKING];
                int k2 = pos.psScore2[Piece.BKING];
                int t = wMtrl - wMtrlPawns;
                score -= interpolate(t, t2, k2, t1, k1);
            }
            }

            // Pawns
            {
            int t1 = qV + 2 * rV + 2 * bV;
            int t2 = rV;
            int wp1 = pos.psScore1[Piece.WPAWN];
            int wp2 = pos.psScore2[Piece.WPAWN];
            if ((wp1 != 0) || (wp2 != 0)) {
                int tw = bMtrl - bMtrlPawns;
                score += interpolate(tw, t2, wp2, t1, wp1);
            }
            int bp1 = pos.psScore1[Piece.BPAWN];
            int bp2 = pos.psScore2[Piece.BPAWN];
            if ((bp1 != 0) || (bp2 != 0)) {
                int tb = wMtrl - wMtrlPawns;
                score -= interpolate(tb, t2, bp2, t1, bp1);
            }
            }

            // Knights
            {
            int t1 = qV + 2 * rV + 1 * bV + 1 * nV + 6 * pV;
            int t2 = nV + 8 * pV;
            int n1 = pos.psScore1[Piece.WKNIGHT];
            int n2 = pos.psScore2[Piece.WKNIGHT];
            if ((n1 != 0) || (n2 != 0)) {
                score += interpolate(bMtrl, t2, n2, t1, n1);
            }
            n1 = pos.psScore1[Piece.BKNIGHT];
            n2 = pos.psScore2[Piece.BKNIGHT];
            if ((n1 != 0) || (n2 != 0)) {
                score -= interpolate(wMtrl, t2, n2, t1, n1);
            }
            }

            // Bishops
            {
            score += pos.psScore1[Piece.WBISHOP];
            score -= pos.psScore1[Piece.BBISHOP];
            }

            // Queens
            {
            ulong occupied = pos.whiteBB | pos.blackBB;
            score += pos.psScore1[Piece.WQUEEN];
            ulong m = pos.pieceTypeBB[Piece.WQUEEN];
            while (m != 0) {
                int sq = BitBoard.numberOfTrailingZeros(m);
                ulong atk = BitBoard.rookAttacks(sq, occupied) | BitBoard.bishopAttacks(sq, occupied);
                wAttacksBB |= atk;
                score += queenMobScore[BITS.bitCount(atk & ~pos.whiteBB)];
                bKingAttacks += BITS.bitCount(atk & bKingZone) * 2;
                m &= m-1;
            }
            score -= pos.psScore1[Piece.BQUEEN];
            m = pos.pieceTypeBB[Piece.BQUEEN];
            while (m != 0) {
                int sq = BitBoard.numberOfTrailingZeros(m);
                ulong atk = BitBoard.rookAttacks(sq, occupied) | BitBoard.bishopAttacks(sq, occupied);
                bAttacksBB |= atk;
                score -= queenMobScore[BITS.bitCount(atk & ~pos.blackBB)];
                wKingAttacks += BITS.bitCount(atk & wKingZone) * 2;
                m &= m-1;
            }
            }

            // Rooks
            {
            int r1 = pos.psScore1[Piece.WROOK];
            if (r1 != 0) {
                int nP = bMtrlPawns / pV;
                int s = r1 * Math.Min(nP, 6) / 6;
                score += s;
            }
            r1 = pos.psScore1[Piece.BROOK];
            if (r1 != 0) {
                int nP = wMtrlPawns / pV;
                int s = r1 * Math.Min(nP, 6) / 6;
                score -= s;
            }
            }

            return score;
        }
Example #19
0
        /** Implement the "when ahead trade pieces, when behind trade pawns" rule. */
        private int tradeBonus(Position pos)
        {
            int wM = pos.wMtrl;
            int bM = pos.bMtrl;
            int wPawn = pos.wMtrlPawns;
            int bPawn = pos.bMtrlPawns;
            int deltaScore = wM - bM;

            int pBonus = 0;
            pBonus += interpolate((deltaScore > 0) ? wPawn : bPawn, 0, -30 * deltaScore / 100, 6 * pV, 0);
            pBonus += interpolate((deltaScore > 0) ? bM : wM, 0, 30 * deltaScore / 100, qV + 2 * rV + 2 * bV + 2 * nV, 0);

            return pBonus;
        }
Example #20
0
 /** Compute rook bonus. Rook on open/half-open file. */
 private int rookBonus(Position pos)
 {
     int score = 0;
     ulong wPawns = pos.pieceTypeBB[Piece.WPAWN];
     ulong bPawns = pos.pieceTypeBB[Piece.BPAWN];
     ulong occupied = pos.whiteBB | pos.blackBB;
     ulong m = pos.pieceTypeBB[Piece.WROOK];
     while (m != 0) {
     int sq = BitBoard.numberOfTrailingZeros(m);
     int x = Position.getX(sq);
     if ((wPawns & BitBoard.maskFile[x]) == 0) { // At least half-open file
         score += (bPawns & BitBoard.maskFile[x]) == 0 ? 25 : 12;
     }
     ulong atk = BitBoard.rookAttacks(sq, occupied);
     wAttacksBB |= atk;
     score += rookMobScore[BITS.bitCount(atk & ~pos.whiteBB)];
     if ((atk & bKingZone) != 0)
         bKingAttacks += BITS.bitCount(atk & bKingZone);
     m &= m-1;
     }
     ulong r7 = pos.pieceTypeBB[Piece.WROOK] & 0x00ff000000000000L;
     if (((r7 & (r7 - 1)) != 0) &&
     ((pos.pieceTypeBB[Piece.BKING] & 0xff00000000000000L) != 0))
     score += 20; // Two rooks on 7:th row
     m = pos.pieceTypeBB[Piece.BROOK];
     while (m != 0) {
     int sq = BitBoard.numberOfTrailingZeros(m);
     int x = Position.getX(sq);
     if ((bPawns & BitBoard.maskFile[x]) == 0) {
         score -= (wPawns & BitBoard.maskFile[x]) == 0 ? 25 : 12;
     }
     ulong atk = BitBoard.rookAttacks(sq, occupied);
     bAttacksBB |= atk;
     score -= rookMobScore[BITS.bitCount(atk & ~pos.blackBB)];
     if ((atk & wKingZone) != 0)
         wKingAttacks += BITS.bitCount(atk & wKingZone);
     m &= m-1;
     }
     r7 = pos.pieceTypeBB[Piece.BROOK] & 0xff00L;
     if (((r7 & (r7 - 1)) != 0) &&
     ((pos.pieceTypeBB[Piece.WKING] & 0xffL) != 0))
       score -= 20; // Two rooks on 2:nd row
     return score;
 }
Example #21
0
 /*throws ChessParseError */
 private static void safeSetPiece(Position pos, int col, int row, int p)
 {
     if (row < 0) throw new ChessParseError(/* "Too many rows" */);
     if (col > 7) throw new ChessParseError(/* "Too many columns" */);
     if ((p == Piece.WPAWN) || (p == Piece.BPAWN)) {
     if ((row == 0) || (row == 7))
         throw new ChessParseError(/* "Pawn on first/last rank" */);
     }
     pos.setPiece(Position.getSquare(col, row), p);
 }
Example #22
0
        private static string moveTostring(Position pos, Move move, bool ulongForm, MoveGen.MoveList moves)
        {
            string ret = "";
            int wKingOrigPos = Position.getSquare(4, 0);
            int bKingOrigPos = Position.getSquare(4, 7);
            if (move.from == wKingOrigPos && pos.getPiece(wKingOrigPos) == Piece.WKING) {
            // Check white castle
            if (move.to == Position.getSquare(6, 0)) {
                    ret += ("O-O");
            } else if (move.to == Position.getSquare(2, 0)) {
                ret += ("O-O-O");
            }
            } else if (move.from == bKingOrigPos && pos.getPiece(bKingOrigPos) == Piece.BKING) {
            // Check white castle
            if (move.to == Position.getSquare(6, 7)) {
                ret += ("O-O");
            } else if (move.to == Position.getSquare(2, 7)) {
                ret += ("O-O-O");
            }
            }
            if (ret.Length == 0) {
            int p = pos.getPiece(move.from);
            ret += pieceToChar(p);
            int x1 = Position.getX(move.from);
            int y1 = Position.getY(move.from);
            int x2 = Position.getX(move.to);
            int y2 = Position.getY(move.to);
            if (ulongForm) {
                ret += ((char)(x1 + 'a'));
                ret += ((char)(y1 + '1'));
                ret += (isCapture(pos, move) ? 'x' : '-');
            } else {
                if (p == (pos.whiteMove ? Piece.WPAWN : Piece.BPAWN)) {
                    if (isCapture(pos, move)) {
                        ret += ((char)(x1 + 'a'));
                    }
                } else {
                    int numSameTarget = 0;
                    int numSameFile = 0;
                    int numSameRow = 0;
                    for (int mi = 0; mi < moves.size; mi++) {
                        Move m = moves.m[mi];
                        if (m == null)
                            break;
                        if ((pos.getPiece(m.from) == p) && (m.to == move.to)) {
                            numSameTarget++;
                            if (Position.getX(m.from) == x1)
                                numSameFile++;
                            if (Position.getY(m.from) == y1)
                                numSameRow++;
                        }
                    }
                    if (numSameTarget < 2) {
                        // No file/row info needed
                    } else if (numSameFile < 2) {
                        ret += ((char)(x1 + 'a'));   // Only file info needed
                    } else if (numSameRow < 2) {
                        ret += ((char)(y1 + '1'));   // Only row info needed
                    } else {
                        ret += ((char)(x1 + 'a'));   // File and row info needed
                        ret += ((char)(y1 + '1'));
                    }
                }
                if (isCapture(pos, move)) {
                    ret += ('x');
                }
            }
            ret += ((char)(x2 + 'a'));
            ret += ((char)(y2 + '1'));
            if (move.promoteTo != Piece.EMPTY) {
                ret += (pieceToChar(move.promoteTo));
            }
            }
            UndoInfo ui = new UndoInfo();
            if (MoveGen.givesCheck(pos, move)) {
            pos.makeMove(move, ui);
            MoveGen MG = new MoveGen();
            MoveGen.MoveList nextMoves = MG.pseudoLegalMoves(pos);
            MoveGen.RemoveIllegal(pos, nextMoves);
            if (nextMoves.size == 0) {
                ret += ('#');
            } else {
                ret += ('+');
            }
            pos.unMakeMove(move, ui);
            }

            return ret;
        }
Example #23
0
        private int kingSafetyKPPart(Position pos)
        {
            ulong key = pos.pawnZobristHash() ^ pos.kingZobristHash();
            KingSafetyHashData ksh = kingSafetyHash[(int)key & (kingSafetyHash.Length - 1)];
            if (ksh.key != key) {
            int score = 0;
            ulong wPawns = pos.pieceTypeBB[Piece.WPAWN];
            ulong bPawns = pos.pieceTypeBB[Piece.BPAWN];
            {
                int safety = 0;
                int halfOpenFiles = 0;
                if (Position.getY(pos.wKingSq) < 2) {
                    ulong shelter = 1UL << Position.getX(pos.wKingSq);
                    shelter |= ((shelter & BitBoard.maskBToHFiles) >> 1) |
                               ((shelter & BitBoard.maskAToGFiles) << 1);
                    shelter <<= 8;
                    safety += 3 * BITS.bitCount(wPawns & shelter);
                    safety -= 2 * BITS.bitCount(bPawns & (shelter | (shelter << 8)));
                    shelter <<= 8;
                    safety += 2 * BITS.bitCount(wPawns & shelter);
                    shelter <<= 8;
                    safety -= BITS.bitCount(bPawns & shelter);

                    ulong wOpen = BitBoard.southFill(shelter) & (~BitBoard.southFill(wPawns)) & 0xff;
                    if (wOpen != 0) {
                        halfOpenFiles += 25 * BITS.bitCount(wOpen & 0xe7);
                        halfOpenFiles += 10 * BITS.bitCount(wOpen & 0x18);
                    }
                    ulong bOpen = BitBoard.southFill(shelter) & (~BitBoard.southFill(bPawns)) & 0xff;
                    if (bOpen != 0) {
                        halfOpenFiles += 25 * BITS.bitCount(bOpen & 0xe7);
                        halfOpenFiles += 10 * BITS.bitCount(bOpen & 0x18);
                    }
                    safety = Math.Min(safety, 8);
                }
                int kSafety = (safety - 9) * 15 - halfOpenFiles;
                score += kSafety;
            }
            {
                int safety = 0;
                int halfOpenFiles = 0;
                if (Position.getY(pos.bKingSq) >= 6) {
                    ulong shelter = 1UL << (56 + Position.getX(pos.bKingSq));
                    shelter |= ((shelter & BitBoard.maskBToHFiles) >> 1) |
                               ((shelter & BitBoard.maskAToGFiles) << 1);
                    shelter >>= 8;
                    safety += 3 * BITS.bitCount(bPawns & shelter);
                    safety -= 2 * BITS.bitCount(wPawns & (shelter | (shelter >> 8)));
                    shelter >>= 8;
                    safety += 2 * BITS.bitCount(bPawns & shelter);
                    shelter >>= 8;
                    safety -= BITS.bitCount(wPawns & shelter);

                    ulong wOpen = BitBoard.southFill(shelter) & (~BitBoard.southFill(wPawns)) & 0xff;
                    if (wOpen != 0) {
                        halfOpenFiles += 25 * BITS.bitCount(wOpen & 0xe7);
                        halfOpenFiles += 10 * BITS.bitCount(wOpen & 0x18);
                    }
                    ulong bOpen = BitBoard.southFill(shelter) & (~BitBoard.southFill(bPawns)) & 0xff;
                    if (bOpen != 0) {
                        halfOpenFiles += 25 * BITS.bitCount(bOpen & 0xe7);
                        halfOpenFiles += 10 * BITS.bitCount(bOpen & 0x18);
                    }
                    safety = Math.Min(safety, 8);
                }
                int kSafety = (safety - 9) * 15 - halfOpenFiles;
                score -= kSafety;
            }
            ksh.key = key;
            ksh.score = score;
            }
            return ksh.score;
        }
Example #24
0
        /**
         * Static evaluation of a position.
         * @param pos The position to evaluate.
         * @return The evaluation score, measured in centipawns.
         *         Positive values are good for the side to make the next move.
         */
        public int evalPos(Position pos)
        {
            int score = pos.wMtrl - pos.bMtrl;

            wKingAttacks = bKingAttacks = 0;
            wKingZone = BitBoard.kingAttacks[pos.getKingSq(true)]; wKingZone |= wKingZone << 8;
            bKingZone = BitBoard.kingAttacks[pos.getKingSq(false)]; bKingZone |= bKingZone >> 8;
            wAttacksBB = bAttacksBB = 0L;

            score += pieceSquareEval(pos);
            score += pawnBonus(pos);
            score += tradeBonus(pos);
            score += castleBonus(pos);

            score += rookBonus(pos);
            score += bishopEval(pos, score);
            score += threatBonus(pos);
            score += kingSafety(pos);
            score = endGameEval(pos, score);

            if (!pos.whiteMove)
            score = -score;
            return score;

            // FIXME! Test penalty if side to move has >1 hanging piece

            // FIXME! Test "tempo value"
        }
Example #25
0
        private int pawnBonus(Position pos)
        {
            ulong key = pos.pawnZobristHash();
            PawnHashData phd = pawnHash[(int)key & (pawnHash.Length - 1)];
            if (phd.key != key)
            computePawnHashData(pos, phd);
            int score = phd.score;

            int hiMtrl = qV + rV;
            score += interpolate(pos.bMtrl - pos.bMtrlPawns, 0, 2 * phd.passedBonusW, hiMtrl, phd.passedBonusW);
            score -= interpolate(pos.wMtrl - pos.wMtrlPawns, 0, 2 * phd.passedBonusB, hiMtrl, phd.passedBonusB);

            // Passed pawns are more dangerous if enemy king is far away
            int mtrlNoPawns;
            int highMtrl = qV + rV;
            ulong m = phd.passedPawnsW;
            if (m != 0) {
            mtrlNoPawns = pos.bMtrl - pos.bMtrlPawns;
            if (mtrlNoPawns < highMtrl) {
                int kingPos = pos.getKingSq(false);
                int kingX = Position.getX(kingPos);
                int kingY = Position.getY(kingPos);
                while (m != 0) {
                    int sq = BitBoard.numberOfTrailingZeros(m);
                    int x = Position.getX(sq);
                    int y = Position.getY(sq);
                    int pawnDist = Math.Min(5, 7 - y);
                    int kingDistX = Math.Abs(kingX - x);
                    int kingDistY = Math.Abs(kingY - 7);
                    int kingDist = Math.Max(kingDistX, kingDistY);
                    int kScore = kingDist * 4;
                    if (kingDist > pawnDist) kScore += (kingDist - pawnDist) * (kingDist - pawnDist);
                    score += interpolate(mtrlNoPawns, 0, kScore, highMtrl, 0);
                    if (!pos.whiteMove)
                        kingDist--;
                    if ((pawnDist < kingDist) && (mtrlNoPawns == 0))
                        score += 500; // King can't stop pawn
                    m &= m-1;
                }
            }
            }
            m = phd.passedPawnsB;
            if (m != 0) {
            mtrlNoPawns = pos.wMtrl - pos.wMtrlPawns;
            if (mtrlNoPawns < highMtrl) {
                int kingPos = pos.getKingSq(true);
                int kingX = Position.getX(kingPos);
                int kingY = Position.getY(kingPos);
                while (m != 0) {
                    int sq = BitBoard.numberOfTrailingZeros(m);
                    int x = Position.getX(sq);
                    int y = Position.getY(sq);
                    int pawnDist = Math.Min(5, y);
                    int kingDistX = Math.Abs(kingX - x);
                    int kingDistY = Math.Abs(kingY - 0);
                    int kingDist = Math.Max(kingDistX, kingDistY);
                    int kScore = kingDist * 4;
                    if (kingDist > pawnDist) kScore += (kingDist - pawnDist) * (kingDist - pawnDist);
                    score -= interpolate(mtrlNoPawns, 0, kScore, highMtrl, 0);
                    if (pos.whiteMove)
                        kingDist--;
                    if ((pawnDist < kingDist) && (mtrlNoPawns == 0))
                        score -= 500; // King can't stop pawn
                    m &= m-1;
                }
            }
            }

            return score;
        }
Example #26
0
 /** Compute white_material - black_material. */
 static int material(Position pos)
 {
     return pos.wMtrl - pos.bMtrl;
 }
Example #27
0
        /**
         * Convert a chess move string to a Move object.
         * Any prefix of the string representation of a valid move counts as a legal move string,
         * as ulong as the string only matches one valid move.
         */
        public static Move stringToMove(Position pos, string strMove)
        {
            strMove = strMove.Replace("=", "");
            Move move = null;
            if (strMove.Length == 0)
            return move;
            MoveGen MG = new MoveGen();
            MoveGen.MoveList moves = MG.pseudoLegalMoves(pos);
            MoveGen.RemoveIllegal(pos, moves);
            {
            char lastChar = strMove[strMove.Length - 1];
            if ((lastChar == '#') || (lastChar == '+')) {
                MoveGen.MoveList subMoves = new MoveGen.MoveList();
                int len = 0;
                for (int mi = 0; mi < moves.size; mi++) {
                    Move m = moves.m[mi];
                    string str1 = TextIO.moveTostring(pos, m, true, moves);
                    if (str1[str1.Length - 1] == lastChar) {
                        subMoves.m[len++] = m;
                    }
                }
                subMoves.size = len;
                moves = subMoves;
                strMove = normalizeMovestring(strMove);
            }
            }

            for (int i = 0; i < 2; i++) {
            // Search for full match
            for (int mi = 0; mi < moves.size; mi++) {
                Move m = moves.m[mi];
                string str1 = normalizeMovestring(TextIO.moveTostring(pos, m, true, moves));
                string str2 = normalizeMovestring(TextIO.moveTostring(pos, m, false, moves));
                if (i == 0) {
                    if ((str1 == strMove) || (str2 == strMove))
                    {
                        return m;
                    }
                } else {
                    if ((strMove.ToLower() == str1.ToLower()) ||
                            (strMove.ToLower() == str2.ToLower()))
                    {
                        return m;
                    }
                }
            }
            }

            for (int i = 0; i < 2; i++) {
            // Search for unique substring match
            for (int mi = 0; mi < moves.size; mi++) {
                Move m = moves.m[mi];
                string str1 = normalizeMovestring(TextIO.moveTostring(pos, m, true));
                string str2 = normalizeMovestring(TextIO.moveTostring(pos, m, false));
                bool match;
                if (i == 0) {
                    match = (str1.StartsWith(strMove) || str2.StartsWith(strMove));
                } else {
                    match = (str1.ToLower().StartsWith(strMove.ToLower()) ||
                            str2.ToLower().StartsWith(strMove.ToLower()));
                }
                if (match) {
                    if (move != null) {
                        return null; // More than one match, not ok
                    } else {
                        move = m;
                    }
                }
            }
            if (move != null)
                return move;
            }
            return move;
        }
Example #28
0
        /** Compute bishop evaluation. */
        private int bishopEval(Position pos, int oldScore)
        {
            int score = 0;
            ulong occupied = pos.whiteBB | pos.blackBB;
            ulong wBishops = pos.pieceTypeBB[Piece.WBISHOP];
            ulong bBishops = pos.pieceTypeBB[Piece.BBISHOP];
            if ((wBishops | bBishops) == 0)
            return 0;
            ulong m = wBishops;
            while (m != 0) {
            int sq = BitBoard.numberOfTrailingZeros(m);
            ulong atk = BitBoard.bishopAttacks(sq, occupied);
            wAttacksBB |= atk;
            score += bishMobScore[BITS.bitCount(atk & ~pos.whiteBB)];
            if ((atk & bKingZone) != 0)
                bKingAttacks += BITS.bitCount(atk & bKingZone);
            m &= m-1;
            }
            m = bBishops;
            while (m != 0) {
            int sq = BitBoard.numberOfTrailingZeros(m);
            ulong atk = BitBoard.bishopAttacks(sq, occupied);
            bAttacksBB |= atk;
            score -= bishMobScore[BITS.bitCount(atk & ~pos.blackBB)];
            if ((atk & wKingZone) != 0)
                wKingAttacks += BITS.bitCount(atk & wKingZone);
            m &= m-1;
            }

            bool whiteDark  = (pos.pieceTypeBB[Piece.WBISHOP] & BitBoard.maskDarkSq ) != 0;
            bool whiteLight = (pos.pieceTypeBB[Piece.WBISHOP] & BitBoard.maskLightSq) != 0;
            bool blackDark  = (pos.pieceTypeBB[Piece.BBISHOP] & BitBoard.maskDarkSq ) != 0;
            bool blackLight = (pos.pieceTypeBB[Piece.BBISHOP] & BitBoard.maskLightSq) != 0;
            int numWhite = (whiteDark ? 1 : 0) + (whiteLight ? 1 : 0);
            int numBlack = (blackDark ? 1 : 0) + (blackLight ? 1 : 0);

            // Bishop pair bonus
            if (numWhite == 2) {
            int numPawns = pos.wMtrlPawns / pV;
            score += 20 + (8 - numPawns) * 3;
            }
            if (numBlack == 2) {
            int numPawns = pos.bMtrlPawns / pV;
            score -= 20 + (8 - numPawns) * 3;
            }

            // FIXME!!! Bad bishop

            if ((numWhite == 1) && (numBlack == 1) && (whiteDark != blackDark) &&
            (pos.wMtrl - pos.wMtrlPawns == pos.bMtrl - pos.bMtrlPawns)) {
            int penalty = (oldScore + score) / 2;
            int loMtrl = 2 * bV;
            int hiMtrl = 2 * (qV + rV + bV);
            int mtrl = pos.wMtrl + pos.bMtrl - pos.wMtrlPawns - pos.bMtrlPawns;
            score -= interpolate(mtrl, loMtrl, penalty, hiMtrl, 0);
            }

            // Penalty for bishop trapped behind pawn at a2/h2/a7/h7
            if (((wBishops | bBishops) & 0x0081000000008100L) != 0) {
            if ((pos.squares[48] == Piece.WBISHOP) && // a7
                (pos.squares[41] == Piece.BPAWN) &&
                (pos.squares[50] == Piece.BPAWN))
                score -= pV * 3 / 2;
            if ((pos.squares[55] == Piece.WBISHOP) && // h7
                (pos.squares[46] == Piece.BPAWN) &&
                (pos.squares[53] == Piece.BPAWN))
                score -= (pos.pieceTypeBB[Piece.WQUEEN] != 0) ? pV : pV * 3 / 2;
            if ((pos.squares[8] == Piece.BBISHOP) &&  // a2
                (pos.squares[17] == Piece.WPAWN) &&
                (pos.squares[10] == Piece.WPAWN))
                score += pV * 3 / 2;
            if ((pos.squares[15] == Piece.BBISHOP) && // h2
                (pos.squares[22] == Piece.WPAWN) &&
                (pos.squares[13] == Piece.WPAWN))
                score += (pos.pieceTypeBB[Piece.BQUEEN] != 0) ? pV : pV * 3 / 2;
            }

            return score;
        }
Example #29
0
        private int threatBonus(Position pos)
        {
            int score = 0;

            // Sum values for all black pieces under attack
            ulong m = pos.pieceTypeBB[Piece.WKNIGHT];
            while (m != 0) {
            int sq = BitBoard.numberOfTrailingZeros(m);
            wAttacksBB |= BitBoard.knightAttacks[sq];
            m &= m-1;
            }
            wAttacksBB &= (pos.pieceTypeBB[Piece.BKNIGHT] |
                       pos.pieceTypeBB[Piece.BBISHOP] |
                       pos.pieceTypeBB[Piece.BROOK] |
                       pos.pieceTypeBB[Piece.BQUEEN]);
            ulong pawns = pos.pieceTypeBB[Piece.WPAWN];
            wAttacksBB |= (pawns & BitBoard.maskBToHFiles) << 7;
            wAttacksBB |= (pawns & BitBoard.maskAToGFiles) << 9;
            m = wAttacksBB & pos.blackBB & ~pos.pieceTypeBB[Piece.BKING];
            int tmp = 0;
            while (m != 0) {
            int sq = BitBoard.numberOfTrailingZeros(m);
            tmp += pieceValue[pos.squares[sq]];
            m &= m-1;
            }
            score += tmp + tmp * tmp / qV;

            // Sum values for all white pieces under attack
            m = pos.pieceTypeBB[Piece.BKNIGHT];
            while (m != 0) {
            int sq = BitBoard.numberOfTrailingZeros(m);
            bAttacksBB |= BitBoard.knightAttacks[sq];
            m &= m-1;
            }
            bAttacksBB &= (pos.pieceTypeBB[Piece.WKNIGHT] |
                       pos.pieceTypeBB[Piece.WBISHOP] |
                       pos.pieceTypeBB[Piece.WROOK] |
                       pos.pieceTypeBB[Piece.WQUEEN]);
            pawns = pos.pieceTypeBB[Piece.BPAWN];
            bAttacksBB |= (pawns & BitBoard.maskBToHFiles) >> 9;
            bAttacksBB |= (pawns & BitBoard.maskAToGFiles) >> 7;
            m = bAttacksBB & pos.whiteBB & ~pos.pieceTypeBB[Piece.WKING];
            tmp = 0;
            while (m != 0) {
            int sq = BitBoard.numberOfTrailingZeros(m);
            tmp += pieceValue[pos.squares[sq]];
            m &= m-1;
            }
            score -= tmp + tmp * tmp / qV;
            return score / 64;
        }
Example #30
0
        /** Return a FEN string corresponding to a chess Position object. */
        public static string toFEN(Position pos)
        {
            string ret = "";
            // Piece placement
            for (int r = 7; r >=0; r--) {
            int numEmpty = 0;
            for (int c = 0; c < 8; c++) {
                int p = pos.getPiece(Position.getSquare(c, r));
                if (p == Piece.EMPTY) {
                    numEmpty++;
                } else {
                    if (numEmpty > 0) {
                        ret+=numEmpty.ToString();
                        numEmpty = 0;
                    }
                    switch (p) {
                        case Piece.WKING:   ret+=('K'); break;
                        case Piece.WQUEEN:  ret+=('Q'); break;
                        case Piece.WROOK:   ret+=('R'); break;
                        case Piece.WBISHOP: ret+=('B'); break;
                        case Piece.WKNIGHT: ret+=('N'); break;
                        case Piece.WPAWN:   ret+=('P'); break;
                        case Piece.BKING:   ret+=('k'); break;
                        case Piece.BQUEEN:  ret+=('q'); break;
                        case Piece.BROOK:   ret+=('r'); break;
                        case Piece.BBISHOP: ret+=('b'); break;
                        case Piece.BKNIGHT: ret+=('n'); break;
                        case Piece.BPAWN:   ret+=('p'); break;
                        default: throw new RuntimeException();
                    }
                }
            }
            if (numEmpty > 0) {
                ret += numEmpty.ToString();
            }
            if (r > 0) {
                ret += ('/');
            }
            }
            ret += (pos.whiteMove ? " w " : " b ");

            // Castling rights
            bool anyCastle = false;
            if (pos.h1Castle()) {
            ret += ('K');
            anyCastle = true;
            }
            if (pos.a1Castle()) {
            ret += ('Q');
            anyCastle = true;
            }
            if (pos.h8Castle()) {
            ret += ('k');
            anyCastle = true;
            }
            if (pos.a8Castle()) {
            ret += ('q');
            anyCastle = true;
            }
            if (!anyCastle) {
            ret += ('-');
            }

            // En passant target square
            {
            ret += (' ');
            if (pos.getEpSquare() >= 0) {
                int x = Position.getX(pos.getEpSquare());
                int y = Position.getY(pos.getEpSquare());
                ret += ((char)(x + 'a'));
                ret += ((char)(y + '1'));
            } else {
                ret += ('-');
            }
            }

            // Move counters
            ret += " " + pos.halfMoveClock;
            ret += " " + pos.fullMoveCounter;

            return ret;
        }