BOOL test_bittwiddles() { BOOL ok = true; ok &= SQUARECOLOR(A1) == BLACK; ok &= SQUARECOLOR(H1) == WHITE; ok &= SQUARECOLOR(A2) == WHITE; ok &= SQUARECOLOR(E4) == WHITE; return ok; }
bool Evaluation::isDraw(ChessBoard& cb) { int wp, bp; // No insufficient material if there are rooks, queens or pawns on the board if (queenlist[WHITE].size || queenlist[BLACK].size || rooklist[WHITE].size || rooklist[BLACK].size || pawnlist[WHITE].size || pawnlist[BLACK].size) return false; wp = knightlist[WHITE].size + bishoplist[WHITE].size; bp = knightlist[BLACK].size + bishoplist[BLACK].size; // King alone or only one piece is draw if ((wp + bp) < 2) return true; // All bishops of same color if (!knightlist[WHITE].size && !knightlist[BLACK].size) { typeColor w = 0, b = 0; typeSquare sq = 0; for (typeColor c = 0; c < 2; c++) { while (sq < bishoplist[WHITE].size) { if (SQUARECOLOR(bishoplist[WHITE].square[sq]) == WHITE) ++w; else ++b; ++sq; } } if (!w || !b) return true; } // Only knights are draws. if (!bishoplist[WHITE].size && !bishoplist[BLACK].size) return true; // One bishop or knight on each side draws if (((knightlist[WHITE].size + bishoplist[WHITE].size)<2) && ((knightlist[BLACK].size + bishoplist[BLACK].size)<2)) return true; // Two knight against bishop or knight can not win if ((wp == 2) && (bp == 1)) if (knightlist[WHITE].size == 2) return true; if ((wp == 1) && (bp == 2)) if (knightlist[BLACK].size == 2) return true; return false; }
inline void calc_piece_value(struct t_board *board, struct t_chess_eval *eval) { t_chess_color color, opponent; t_chess_square square; t_chess_piece piece; t_chess_piece piece_type; t_bitboard b; t_bitboard attack_squares; t_bitboard moves; int move_count; struct t_pawn_hash_record *pawn_record = eval->pawn_evaluation; for (color = WHITE; color <= BLACK; color++) { t_chess_value middlegame = 0; t_chess_value endgame = 0; opponent = OPPONENT(color); //========================================================= //-- Rooks first //========================================================= piece = PIECEINDEX(color, ROOK); eval->attacklist[piece] = 0; b = board->piecelist[piece]; //-- Remove Rook and Queens (so we can easily evaluate rams) t_bitboard _all_pieces = board->all_pieces ^ board->pieces[color][QUEEN] ^ b; t_bitboard _not_occupied = ~(board->occupied[color] & _all_pieces); //-- Rooks on the 7th if ((b & rank_mask[color][6]) && (board->pieces[opponent][KING] & rank_mask[color][7])) { middlegame += MG_ROOK_ON_7TH; endgame += MG_ROOK_ON_7TH; } //-- Rooks on Open file if (b & pawn_record->open_file) { middlegame += popcount(b & pawn_record->open_file) * pawn_record->pawn_count[color] * MG_ROOK_ON_OPEN_FILE; } //-- Rooks on Semi-Open file if (b & pawn_record->semi_open_file[color]) { middlegame += popcount(b & pawn_record->semi_open_file[color]) * pawn_record->pawn_count[color] * MG_ROOK_ON_SEMI_OPEN_FILE; } //-- Loop around for all pieces while (b) { //-- Find the square it resides square = bitscan_reset(&b); //-- Generate moves moves = rook_magic_moves[square][((rook_magic[square].mask & _all_pieces) * rook_magic[square].magic) >> 52]; eval->attacks[color][ROOK] |= moves; moves &= _not_occupied; //-- Mobility (along ranks) move_count = popcount(moves & square_rank_mask[square]); middlegame += horizontal_rook_mobility[MIDDLEGAME][move_count]; endgame += horizontal_rook_mobility[ENDGAME][move_count]; //-- Mobility (along files) move_count = popcount(moves & square_column_mask[square]); middlegame += vertical_rook_mobility[MIDDLEGAME][move_count]; endgame += vertical_rook_mobility[ENDGAME][move_count]; //-- King safety if (attack_squares = (moves & eval->king_zone[opponent])) { eval->king_attack_count[opponent]++; eval->king_attack_pressure[opponent] += popcount(attack_squares) * 40; } assert(eval->king_zone[opponent] != 0); // piece-square tables middlegame += piece_square_table[piece][MIDDLEGAME][square]; endgame += piece_square_table[piece][ENDGAME][square]; } //========================================================= //-- Queens //========================================================= piece = PIECEINDEX(color, QUEEN); eval->attacklist[piece] = 0; b = board->piecelist[piece]; _all_pieces ^= board->pieces[color][BISHOP]; _not_occupied = ~(board->occupied[color] & _all_pieces); while (b) { //-- Find the square it resides square = bitscan_reset(&b); //-- Rook-like Moves t_bitboard rook_moves = rook_magic_moves[square][((rook_magic[square].mask & _all_pieces) * rook_magic[square].magic) >> 52]; eval->attacklist[piece] |= rook_moves; rook_moves &= _not_occupied; //-- Bishop-like moves t_bitboard bishop_moves = bishop_magic_moves[square][((bishop_magic[square].mask & _all_pieces) * bishop_magic[square].magic) >> 55]; eval->attacklist[piece] |= bishop_moves; bishop_moves &= _not_occupied; //-- Mobility move_count = popcount((rook_moves & square_column_mask[square]) | bishop_moves); middlegame += move_count; //-- King safety if (attack_squares = ((rook_moves | bishop_moves) & eval->king_zone[opponent])) { eval->king_attack_count[opponent]++; eval->king_attack_pressure[opponent] += 80 * popcount(attack_squares); } //-- piece-square tables middlegame += piece_square_table[piece][MIDDLEGAME][square]; endgame += piece_square_table[piece][ENDGAME][square]; } //-- Interaction of double pawns & major pieces if (pawn_record->double_pawns[color]) { int double_pawn_count = popcount(pawn_record->double_pawns[color]); int major_piece_count = popcount(board->pieces[color][ROOK] | board->pieces[color][QUEEN]); switch (major_piece_count) { case 0: break; case 1: middlegame += (double_pawn_count * 12) - pawn_record->semi_open_double_pawns[color] * 30; endgame += (double_pawn_count * 12) - pawn_record->semi_open_double_pawns[color] * 25; break; case 2: middlegame += (double_pawn_count * 24) - pawn_record->semi_open_double_pawns[color] * 35; endgame += (double_pawn_count * 24) - pawn_record->semi_open_double_pawns[color] * 30; break; case 3: middlegame += (double_pawn_count * 30) - pawn_record->semi_open_double_pawns[color] * 40; endgame += (double_pawn_count * 30) - pawn_record->semi_open_double_pawns[color] * 35; break; case 4: middlegame += (double_pawn_count * 30) - pawn_record->semi_open_double_pawns[color] * 40; endgame += (double_pawn_count * 30) - pawn_record->semi_open_double_pawns[color] * 35; break; case 5: middlegame += (double_pawn_count * 30) - pawn_record->semi_open_double_pawns[color] * 40; endgame += (double_pawn_count * 30) - pawn_record->semi_open_double_pawns[color] * 35; break; } } //========================================================= //-- Bishops //========================================================= piece = PIECEINDEX(color, BISHOP); eval->attacklist[piece] = 0; b = board->piecelist[piece]; //-- Bishop pair bonus if (b & (b - 1)) { middlegame += MG_BISHOP_PAIR; endgame += EG_BISHOP_PAIR; } //-- Remove Own Pieces (leave pawns) _all_pieces = board->all_pieces ^ board->pieces[color][KNIGHT] ^ board->pieces[color][QUEEN]; _not_occupied = ~(board->occupied[color] & _all_pieces); while (b) { //-- Find the square it resides square = bitscan_reset(&b); //-- Generate moves moves = bishop_magic_moves[square][((bishop_magic[square].mask & _all_pieces) * bishop_magic[square].magic) >> 55]; eval->attacklist[piece] |= moves; moves &= _not_occupied; //-- Mobility move_count = popcount(moves); middlegame += bishop_mobility[MIDDLEGAME][move_count]; endgame += bishop_mobility[ENDGAME][move_count]; //-- Trapped //middlegame -= trapped_bishop[MIDDLEGAME][move_count]; //endgame -= trapped_bishop[ENDGAME][move_count]; //-- King safety if (attack_squares = (moves & eval->king_zone[opponent])) { eval->king_attack_count[opponent]++; eval->king_attack_pressure[opponent] += 20 * popcount(attack_squares); } // piece-square tables middlegame += piece_square_table[piece][MIDDLEGAME][square]; endgame += piece_square_table[piece][ENDGAME][square]; } //========================================================= //-- Knights //========================================================= piece = PIECEINDEX(color, KNIGHT); eval->attacklist[piece] = 0; b = board->piecelist[piece]; _not_occupied = ~board->occupied[color] & ~eval->attacks[opponent][PAWN]; //-- Outposts t_bitboard knight_outpost = b & pawn_record->potential_outpost[color]; while (knight_outpost) { square = bitscan_reset(&knight_outpost); t_chess_color square_color = SQUARECOLOR(square); //-- Can it be taken by a minor piece? if ((board->pieces[opponent][KNIGHT] == 0) && ((board->pieces[opponent][BISHOP] & color_square_mask[square_color]) == 0)) { middlegame += 25 - square_distance(square, board->king_square[opponent]); endgame += 10; } else { middlegame += 15 - square_distance(square, board->king_square[opponent]); endgame += 8; } } while (b) { //-- Find the square it resides square = bitscan_reset(&b); //-- Opponents King Tropism middlegame -= square_distance(square, board->king_square[opponent]) * 2; //-- Generate moves moves = knight_mask[square]; eval->attacklist[piece] |= moves; //-- Connected to another knight if (moves & board->piecelist[piece]) { middlegame += MG_CONNECTED_KNIGHTS; endgame += EG_CONNECTED_KNIGHTS; } //-- King safety if (attack_squares = (moves & eval->king_zone[opponent])) { eval->king_attack_count[opponent]++; eval->king_attack_pressure[opponent] += 20 * popcount(attack_squares); } //-- Mobility (not including any squares attacked by enemy pawns) moves &= _not_occupied; move_count = popcount(moves); middlegame += knight_mobility[MIDDLEGAME][move_count]; endgame += knight_mobility[ENDGAME][move_count]; // piece-square tables middlegame += piece_square_table[piece][MIDDLEGAME][square]; endgame += piece_square_table[piece][ENDGAME][square]; } //========================================================= //-- King Attacks //========================================================= piece = PIECEINDEX(color, KING); eval->attacklist[piece] = king_mask[board->king_square[color]]; //========================================================= //-- Blocked Central Pawns //========================================================= if (b = (central_kq_pawns[color] & board->pieces[color][PAWN])){ b = ((b << 8) >> (color * 16)) & board->all_pieces; middlegame += -10 * popcount(b); } //-- Add to board scores eval->middlegame += middlegame * (1 - color * 2); eval->endgame += endgame * (1 - color * 2); //-- Create combined attacks eval->attacks[color][BLANK] = eval->attacks[color][PAWN] | eval->attacks[color][ROOK] | eval->attacks[color][BISHOP] | eval->attacks[color][KNIGHT] | eval->attacks[color][QUEEN] | eval->attacks[color][KING]; }