private static void EvalTrappedKnights(Evaluation e, int[] eval, int side, int sq) { //look for trapped knights if (side == 0) { if (sq == 7) // white knight on h8 { if ((e.Board.Pawns[1] & (BitMask.Mask[13] | BitMask.Mask[15])) > 0) { eval[0] -= PieceValues[(int)Piece.Knight] / 2; //this trap costs us half a knight } } else if (sq == 0) { //white knight on a8 if ((e.Board.Pawns[1] & (BitMask.Mask[8] | BitMask.Mask[10])) > 0) { eval[0] -= PieceValues[(int)Piece.Knight] / 2; //this trap costs us half a knight } } else if (sq == 15) //white knight on h7 { if ((e.Board.Pawns[1] & BitMask.Mask[14]) > 0 && (e.Board.Pawns[1] & (BitMask.Mask[23] | BitMask.Mask[21])) > 0) { eval[0] -= PieceValues[(int)Piece.Knight] / 2; //this trap costs us half a knight } } else if (sq == 08) //white knight on a7 { if ((e.Board.Pawns[1] & BitMask.Mask[9]) > 0 && (e.Board.Pawns[1] & (BitMask.Mask[16] | BitMask.Mask[18])) > 0) { eval[0] -= PieceValues[(int)Piece.Knight] / 2; //this trap costs us half a knight } } } else { if (sq == 63) // black knight on h1 { if ((e.Board.Pawns[0] & (BitMask.Mask[53] | BitMask.Mask[55])) > 0) { eval[1] -= PieceValues[(int)Piece.Knight] / 2; //this trap costs us half a knight } } else if (sq == 56) { //black knight on a1 if ((e.Board.Pawns[0] & (BitMask.Mask[48] | BitMask.Mask[50])) > 0) { eval[1] -= PieceValues[(int)Piece.Knight] / 2; //this trap costs us half a knight } } else if (sq == 55) //black knight on h2 { if ((e.Board.Pawns[0] & BitMask.Mask[54]) > 0 && (e.Board.Pawns[0] & (BitMask.Mask[45] | BitMask.Mask[47])) > 0) { eval[1] -= PieceValues[(int)Piece.Knight] / 2; //this trap costs us half a knight } } else if (sq == 48)//black knight on a2 { if ((e.Board.Pawns[0] & BitMask.Mask[49]) > 0 && (e.Board.Pawns[0] & (BitMask.Mask[40] | BitMask.Mask[42])) > 0) { eval[1] -= PieceValues[(int)Piece.Knight] / 2; //this trap costs us half a knight } } } }
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]); }