void caps_ordering(move_t ms[], int count) { int i; for (i = 0; i < count; i++) { if(ms[i].type & PROM) { ms[i].score = 500000 + pval[ms[i].promoted]; if(ms[i].type & CAP) ms[i].score += pval[PieceType(ms[i].to)]; } else if(ms[i].type & CAP) { if(ms[i].type & EP) ms[i].score = 30000 - P_VALUE; else { int p_from = pval[PieceType(ms[i].from)]; int p_to = pval[PieceType(ms[i].to)]; //bishop/knight correction if(abs(p_to - p_from) == B_N_DIFF) ms[i].score = 30000 - p_from; else if(p_to > p_from)//good caps ms[i].score = 40000 + (p_to - p_from); else if(p_to == p_from) //equal caps ms[i].score = 30000 - p_from; else if(p_to < p_from) //presumably bad caps { ms[i].score = see(ms[i]); if(ms[i].score == 0) ms[i].score = 30000 - p_from;//it's equal. else if(ms[i].score > 0) ms[i].score += 40000; //appears to be a good sequence. } } } } }
void do_perft(position_t *pos, scored_move_t *ms, int ply, int depth) { scored_move_t *msbase = ms; uint8 stm = Stm(ply); scored_move_t *mv; if (Checked(stm^1)) return; if (Checked(stm)) { ms = generate_evasions(pos, ms, ply); for (mv = msbase; mv < ms; mv++) if (PieceType(Capture(mv->move)) == KING) return; } else { ms = generate_captures(pos, ms, ply); for (mv = msbase; mv < ms; mv++) if (PieceType(Capture(mv->move)) == KING) return; ms = generate_noncaptures(pos, ms, ply); } for (mv = msbase; mv < ms; mv++) { make_move(pos, mv->move, ply); if (depth - 1) do_perft(pos, ms, ply + 1, depth - 1); else if (!Checked(stm)) total_moves++; unmake_move(pos, mv->move, ply); } }
static int eval_black_bishop(int sq) { int score = 0; //trapped bishop on 7th if(((sq == A2) && (PieceType(B3) == WHITE_PAWN)) || ((sq == B1) && (PieceType(C2) == WHITE_PAWN))) score -= TRAPPED_BISHOP_PENALTY; if(((sq == H2) && (PieceType(G3) == WHITE_PAWN)) || ((sq == G1) && (PieceType(F2) == WHITE_PAWN))) score -= TRAPPED_BISHOP_PENALTY; //trapped on 6th: if((sq == A3) && (PieceType(B4) == WHITE_PAWN)) score -= (TRAPPED_BISHOP_PENALTY / 2); if((sq == H3) && (PieceType(G4) == WHITE_PAWN)) score -= (TRAPPED_BISHOP_PENALTY / 2); //bishop, blocked by it's own pawns: if(sq == C8 && PieceType(D7) == BLACK_PAWN && !IsEmpty(D6)) score -= BLOCKED_BISHOP_PENALTY; if(sq == F8 && PieceType(E7) == BLACK_PAWN && !IsEmpty(E6)) score -= BLOCKED_BISHOP_PENALTY; return score; }
static int eval_white_bishop(int sq) { int score = 0; //trapped bishop on 7th rank if(((sq == A7) && (PieceType(B6) == BLACK_PAWN)) || ((sq == B8) && (PieceType(C7) == BLACK_PAWN))) score -= TRAPPED_BISHOP_PENALTY; if(((sq == H7) && (PieceType(G6) == BLACK_PAWN)) || ((sq == G8) && (PieceType(F7) == BLACK_PAWN))) score -= TRAPPED_BISHOP_PENALTY; //trapped on 6th: if((sq == A6) && (PieceType(B5) == BLACK_PAWN)) score -= (TRAPPED_BISHOP_PENALTY / 2); if((sq == H6) && (PieceType(G5) == BLACK_PAWN)) score -= (TRAPPED_BISHOP_PENALTY / 2); //bishop, blocked by it's own pawns: if(sq == C1 && PieceType(D2) == WHITE_PAWN && !IsEmpty(D3)) score -= BLOCKED_BISHOP_PENALTY; if(sq == F1 && PieceType(E2) == WHITE_PAWN && !IsEmpty(E3)) score -= BLOCKED_BISHOP_PENALTY; return score; }
static int eval_black_rook(int sq) { int score = 0; int file = calc_file(sq); int rank = calc_rank(sq); int k_sq = King_Square(B); bool wf,bf; wf = (bool)(true && (file_mask[file] & board->bb_pawns[W])); bf = (bool)(true && (file_mask[file] & board->bb_pawns[B])); if(rank == RANK_2) score += ROOK_ON_7TH_REWARD; if(!bf && !wf) { score += ROOK_ON_OPEN_FILE_REWARD; if(rank < RANK_8) { if(PieceType(sq + 16) == BLACK_ROOK) score+= ROOKS_DOUBLED; } } if(!bf && wf) score += ROOK_ON_SEMI_OPEN_FILE_REWARD; //black trapped rook: if(sq == H8 || sq == G8) { if(k_sq > E8 && k_sq < H8) score -= TRAPPED_ROOK_PENALTY; } if(sq >= A8 && sq <= C8) { if(k_sq <= D8) score -= TRAPPED_ROOK_PENALTY; } if(file == FILE_E) score += ROOK_ON_E_FILE_REWARD; if(file == FILE_D) score += ROOK_ON_D_FILE_REWARD; return score; }
static int eval_black_opening() { int score = 0; bool queen_developed = false; bool all_pieces_developed = true; if(PieceType(D8) != BLACK_QUEEN) queen_developed = true; if(PieceType(E7) == BLACK_PAWN) score -= UNDEVELOPED_KING_PAWN_PENALTY; if(PieceType(D7) == BLACK_PAWN) score -= UNDEVELOPED_QUEEN_PAWN_PENALTY; if(PieceType(B8) == BLACK_KNIGHT) { score -= UNDEVELOPED_QKNIGHT_PENALTY; all_pieces_developed = false; } if(PieceType(G8) == BLACK_KNIGHT) { score -= UNDEVELOPED_KKNIGHT_PENALTY; all_pieces_developed = false; } if(PieceType(C8) == BLACK_BISHOP) { score -= UNDEVELOPED_QBISHOP_PENALTY; all_pieces_developed = false; } if(PieceType(F8) == BLACK_BISHOP) { score -= UNDEVELOPED_KBISHOP_PENALTY; all_pieces_developed = false; } if(!all_pieces_developed && queen_developed) score -= QUEEN_EARLY_DEVELOPMENT_PENALTY; if(all_pieces_developed && !queen_developed) score += DEVELOPMENT_REWARD; return score; }
static int eval_white_opening() { int score = 0; bool queen_developed = false; bool all_pieces_developed = true; if(PieceType(D1) != WHITE_QUEEN) queen_developed = true; if(PieceType(E2) == WHITE_PAWN) score -= UNDEVELOPED_KING_PAWN_PENALTY; if(PieceType(D2) == WHITE_PAWN) score -= UNDEVELOPED_QUEEN_PAWN_PENALTY; if(PieceType(B1) == WHITE_KNIGHT) { score -= UNDEVELOPED_QKNIGHT_PENALTY; all_pieces_developed = false; } if(PieceType(G1) == WHITE_KNIGHT) { score -= UNDEVELOPED_KKNIGHT_PENALTY; all_pieces_developed = false; } if(PieceType(C1) == WHITE_BISHOP) { score -= UNDEVELOPED_QBISHOP_PENALTY; all_pieces_developed = false; } if(PieceType(F1) == WHITE_BISHOP) { score -= UNDEVELOPED_KBISHOP_PENALTY; all_pieces_developed = false; } if(!all_pieces_developed && queen_developed) score -= QUEEN_EARLY_DEVELOPMENT_PENALTY; if(all_pieces_developed && !queen_developed) score += DEVELOPMENT_REWARD; return score; }
static int eval_black_king(int sq) { register int pawn_first; int score = 0; safety[B] = &empty[0]; if(!(board->castle & (BLACK_OO|BLACK_OOO))) { if(sq > F8 && sq <= H8) { pawn_first = calc_rank64(bitscanr(board->bb_pawns[B] & file_mask[FILE_F])); score += (king_shield[B][pawn_first]) * 3; pawn_first = calc_rank64(bitscanr(board->bb_pawns[B] & file_mask[FILE_G])); score += (king_shield[B][pawn_first]) * 2; pawn_first = calc_rank64(bitscanr(board->bb_pawns[B] & file_mask[FILE_H])); score += (king_shield[B][pawn_first]); score -= popcnt(board->bb_pawns[W] & king_storm_mask[B]) * 4; safety[B] = &safety_kingside[B][0]; } else if(sq < D8 && sq >= A8) { pawn_first = calc_rank64(bitscanr(board->bb_pawns[B] & file_mask[FILE_C])); score += (king_shield[B][pawn_first]) * 3; pawn_first = calc_rank64(bitscanr(board->bb_pawns[B] & file_mask[FILE_B])); score += (king_shield[B][pawn_first]) * 2; pawn_first = calc_rank64(bitscanr(board->bb_pawns[B] & file_mask[FILE_A])); score += (king_shield[B][pawn_first]); score -= popcnt(board->bb_pawns[W] & queen_storm_mask[B]) * 4; safety[B] = &safety_queenside[B][0]; } else score -= KING_UNCASTLED_STILL; } else { score -= KING_UNCASTLED_YET; if(PieceType(sq - 16) != BP &&(PieceType(sq - 15) != BP || PieceType(sq - 17) != BP)) score -= KING_EXPOSED; } return score; }
static int eval_white_king(int sq) { register int pawn_first; int score = 0; safety[W] = &empty[0]; if(!(board->castle & (WHITE_OO|WHITE_OOO))) { if(sq > F1 && sq <= H1) { pawn_first = calc_rank64(bitscanf(board->bb_pawns[W] & file_mask[FILE_F])); score += (king_shield[W][pawn_first]) * 3; pawn_first = calc_rank64(bitscanf(board->bb_pawns[W] & file_mask[FILE_G])); score += (king_shield[W][pawn_first]) * 2; pawn_first = calc_rank64(bitscanf(board->bb_pawns[W] & file_mask[FILE_H])); score += (king_shield[W][pawn_first]); score -= popcnt(board->bb_pawns[B] & king_storm_mask[W]) * 4; safety[W] = &safety_kingside[W][0]; } else if(sq < D1 && sq >= A1) { pawn_first = calc_rank64(bitscanf(board->bb_pawns[W] & file_mask[FILE_C])); score += (king_shield[W][pawn_first]) * 3; pawn_first = calc_rank64(bitscanf(board->bb_pawns[W] & file_mask[FILE_B])); score += (king_shield[W][pawn_first]) * 2; pawn_first = calc_rank64(bitscanf(board->bb_pawns[W] & file_mask[FILE_A])); score += (king_shield[W][pawn_first]); score -= popcnt(board->bb_pawns[B] & queen_storm_mask[W]) * 4; safety[W] = &safety_queenside[W][0]; } else score -= KING_UNCASTLED_STILL; } else { score -= KING_UNCASTLED_YET; if(PieceType(sq + 16) != WP &&(PieceType(sq + 15) != WP || PieceType(sq + 17) != WP)) score -= KING_EXPOSED; } return score; }
void ordering(move_t ms[], int count, uint32 bestmove) { int i,ply = board->ply; for (i = 0; i < count; i++) { if(ms[i].p == bestmove) ms[i].score = 1000000; else if(ms[i].type & PROM) { ms[i].score = 500000 + pval[ms[i].promoted]; if(ms[i].type & CAP) ms[i].score += pval[PieceType(ms[i].to)]; } else if(ms[i].type & CAP) { if(ms[i].type & EP) ms[i].score = 30000 - P_VALUE; else { int p_from = pval[PieceType(ms[i].from)]; int p_to = pval[PieceType(ms[i].to)]; //bishop/knight correction if(abs(p_to - p_from) == B_N_DIFF) ms[i].score = 30000 - p_from; else if(p_to > p_from)//good caps ms[i].score = 40000 + (p_to - p_from); else if(p_to == p_from) //equal caps ms[i].score = 30000 - p_from; else if(p_to < p_from) //presumably bad caps { ms[i].score = see(ms[i]); if(ms[i].score == 0) ms[i].score = 30000 - p_from;//it's equal. else if(ms[i].score > 0) ms[i].score += 40000; //appears to be a good sequence. } } } else if(ms[i].p == si->killer[0][ply]) ms[i].score = 20000; else if(ms[i].p == si->killer[1][ply]) ms[i].score = 10000; else if(ms[i].type & CASTLE) ms[i].score = 5000 - (ms[i].type ^ CASTLE); else ms[i].score += si->history[ms[i].from][ms[i].to]; } }
static int eval_white_rook(int sq) { int score = 0; int file = calc_file(sq); int rank = calc_rank(sq); int k_sq = King_Square(W); bool wf,bf; wf = (bool)(true && (file_mask[file] & board->bb_pawns[W])); bf = (bool)(true && (file_mask[file] & board->bb_pawns[B])); if(rank == RANK_7) score += ROOK_ON_7TH_REWARD; if(!wf && !bf) { score += ROOK_ON_OPEN_FILE_REWARD; //opened file with doubled rooks //(backward rook examined if exists): if(rank > RANK_1) { if(PieceType(sq-16) == WHITE_ROOK) score+= ROOKS_DOUBLED; } } if(!wf && bf) score += ROOK_ON_SEMI_OPEN_FILE_REWARD; //white trapped rook: if(sq == H1 || sq == G1) { if(k_sq > E1 && k_sq < H1) score -= TRAPPED_ROOK_PENALTY; } if(sq >= A1 && sq <= C1) { if(k_sq <= D1) score -= TRAPPED_ROOK_PENALTY; } if(file == FILE_E) score += ROOK_ON_E_FILE_REWARD; if(file == FILE_D) score += ROOK_ON_D_FILE_REWARD; return score; }
PieceType piece_type_from_char(char c) { const char *ch = strchr(PieceChars, tolower(c)); return ch? PieceType(ch - PieceChars) : NO_PIECE_TYPE; }
void PlacePieces() { for(int i = 0; i < 8; i++) for(int j = 0; j < 8; j++) if(PieceAt(i, j)) DrawFourTilesAt((i * 2) + BOARD_OFFSET_X, (j * 2) + BOARD_OFFSET_Y, 29, _pieces[PieceColor(i, j)][PieceType(i, j)]); }
void AvailableMoves(int x, int y, int* moves, int* takingMoves) { // Maximum number of moves available at one time is 28 (Queen at C3) int kPTC[8][2] = {{-2,-1},{-2,1},{-1,-2},{1,-2},{2,-1},{2,1},{1,2},{-1,2}}; int kingPTC[8][2] = {{-1,0},{1,0},{0,-1},{0,1},{-1,-1},{-1,1},{1,-1},{1,1}}; for(int i = 0; i < 28; i++) moves[i] = -1; for(int i = 0; i < 16; i++) takingMoves[i] = -1; if(PieceAt(x, y)) { int colour = PieceColor(x, y); int type = PieceType(x, y); int nextMoveSlot = 0; int nextTMoveSlot = 0; switch(type) { case KING: for(int i = 0; i < 8; i++) { int nx = x + kingPTC[i][0], ny = y + kingPTC[i][1]; if(nx >= 0 && ny >= 0 && nx < 8 && ny < 8) { if(!PieceAt(nx, ny)) moves[nextMoveSlot++] = ny * 8 + nx; else if(PieceColor(nx, ny) != colour) takingMoves[nextTMoveSlot++] = ny * 8 + nx; } } break; case QUEEN: HorizontalMovesFrom(x, y, moves, nextMoveSlot, takingMoves, nextTMoveSlot); DiagonalMovesFrom(x, y, moves, nextMoveSlot, takingMoves, nextTMoveSlot); break; case BISHOP: DiagonalMovesFrom(x, y, moves, nextMoveSlot, takingMoves, nextTMoveSlot); break; case ROOK: HorizontalMovesFrom(x, y, moves, nextMoveSlot, takingMoves, nextTMoveSlot); break; case KNIGHT: for(int i = 0; i < 8; i++) { int nx = x + kPTC[i][0], ny = y + kPTC[i][1]; if(nx >= 0 && nx < 8 && ny >= 0 && ny < 8) { if(!PieceAt(nx, ny)) moves[nextMoveSlot++] = ny * 8 + nx; else if(PieceColor(nx, ny) != colour) takingMoves[nextTMoveSlot++] = ny * 8 + nx; } } break; case PAWN: if(colour == WHITE) { for(int i = 0; i < (y == 6 ? 2 : 1); i++) if(!PieceAt(x, y - 1 - i)) moves[nextMoveSlot++] = (y - 1 - i) * 8 + x; else break; if(x > 0) if(PieceAt(x - 1, y - 1) && PieceColor(x - 1, y - 1) != colour) takingMoves[nextTMoveSlot++] = (y - 1) * 8 + x - 1; if(x < 7) if(PieceAt(x + 1, y - 1) && PieceColor(x + 1, y - 1) != colour) takingMoves[nextTMoveSlot++] = (y - 1) * 8 + x + 1; } else { for(int i = 0; i < (y == 1 ? 2 : 1); i++) if(!PieceAt(x, y + 1 + i)) moves[nextMoveSlot++] = (y + 1 + i) * 8 + x; else break; if(x > 0) if(PieceAt(x - 1, y + 1) && PieceColor(x - 1, y + 1) != colour) takingMoves[nextTMoveSlot++] = (y + 1) * 8 + x - 1; if(x < 7) if(PieceAt(x + 1, y + 1) && PieceColor(x + 1, y + 1) != colour) takingMoves[nextTMoveSlot++] = (y + 1) * 8 + x + 1; } break; } } }
void MovePiece(int cx, int cy, int nx, int ny) { DrawFourTilesAt(nx * 2 + BOARD_OFFSET_X, ny * 2 + BOARD_OFFSET_Y, 29, _pieces[PieceColor(cx, cy)][PieceType(cx, cy)]); EraseFourTilesAt(cx * 2 + BOARD_OFFSET_X, cy * 2 + BOARD_OFFSET_Y, 29); _pieceLayout[ny][nx] = _pieceLayout[cy][cx]; _pieceLayout[cy][cx] = -1; }