#include "evaluation.h" #include "movegen.h" #include "repetition.h" // Material values const int piece_value[12] = {100, 320, 330, 500, 900, 20000, -100, -320, -330, -500, -900, -20000}; // Piece-square tables for evaluation const int pst_pawn[64] = { 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 10, 10, 20, 30, 30, 20, 10, 10, 5, 5, 10, 25, 25, 10, 5, 5, 0, 0, 0, 20, 20, 0, 0, 0, 5, -5,-10, 0, 0,-10, -5, 5, 5, 10, 10,-20,-20, 10, 10, 5, 0, 0, 0, 0, 0, 0, 0, 0 }; const int pst_knight[64] = { -50,-40,-30,-30,-30,-30,-40,-50, -40,-20, 0, 0, 0, 0,-20,-40, -30, 0, 10, 15, 15, 10, 0,-30, -30, 5, 15, 20, 20, 15, 5,-30, -30, 0, 15, 20, 20, 15, 0,-30, -30, 5, 10, 15, 15, 10, 5,-30, -40,-20, 0, 5, 5, 0,-20,-40, -50,-40,-30,-30,-30,-30,-40,-50 }; const int pst_bishop[64] = { -20,-10,-10,-10,-10,-10,-10,-20, -10, 0, 0, 0, 0, 0, 0,-10, -10, 0, 10, 10, 10, 10, 0,-10, -10, 5, 5, 10, 10, 5, 5,-10, -10, 0, 5, 10, 10, 5, 0,-10, -10, 5, 5, 5, 5, 5, 5,-10, -10, 0, 5, 0, 0, 5, 0,-10, -20,-10,-10,-10,-10,-10,-10,-20 }; const int pst_rook[64] = { 0, 0, 0, 0, 0, 0, 0, 0, 5, 10, 10, 10, 10, 10, 10, 5, -5, 0, 0, 0, 0, 0, 0, -5, -5, 0, 0, 0, 0, 0, 0, -5, -5, 0, 0, 0, 0, 0, 0, -5, -5, 0, 0, 0, 0, 0, 0, -5, -5, 0, 0, 0, 0, 0, 0, -5, 0, 0, 0, 5, 5, 0, 0, 0 }; const int pst_queen[64] = { -20,-10,-10, -5, -5,-10,-10,-20, -10, 0, 0, 0, 0, 0, 0,-10, -10, 0, 5, 5, 5, 5, 0,-10, -5, 0, 5, 5, 5, 5, 0, -5, 0, 0, 5, 5, 5, 5, 0, -5, -10, 5, 5, 5, 5, 5, 0,-10, -10, 0, 5, 0, 0, 0, 0,-10, -20,-10,-10, -5, -5,-10,-10,-20 }; const int pst_king_mid[64] = { -30,-40,-40,-50,-50,-40,-40,-30, -30,-40,-40,-50,-50,-40,-40,-30, -30,-40,-40,-50,-50,-40,-40,-30, -30,-40,-40,-50,-50,-40,-40,-30, -20,-30,-30,-40,-40,-30,-30,-20, -10,-20,-20,-20,-20,-20,-20,-10, 20, 20, 0, 0, 0, 0, 20, 20, 20, 30, 10, 0, 0, 10, 30, 20 }; const int pst_king_end[64] = { -50,-40,-30,-20,-20,-30,-40,-50, -30,-20,-10, 0, 0,-10,-20,-30, -30,-10, 20, 30, 30, 20,-10,-30, -30,-10, 30, 40, 40, 30,-10,-30, -30,-10, 30, 40, 40, 30,-10,-30, -30,-10, 20, 30, 30, 20,-10,-30, -30,-30, 0, 0, 0, 0,-30,-30, -50,-30,-30,-30,-30,-30,-30,-50 }; // Evaluate material balance int evaluate_material(const GameState *state) { int score = 0; // Material balance for (int pc = P; pc <= K; pc++) { score += piece_value[pc] * __builtin_popcountll(state->bitboards[pc]); } for (int pc = p; pc <= k; pc++) { score += piece_value[pc] * __builtin_popcountll(state->bitboards[pc]); } return score; } // Evaluate positional factors int evaluate_position(const GameState *state) { int score = 0; int sq; // Piece-square tables for positional evaluation // White pawns U64 wp = state->bitboards[P]; while (wp) { sq = __builtin_ctzll(wp); score += pst_pawn[sq]; CLEAR_BIT(wp, sq); } // Black pawns U64 bp = state->bitboards[p]; while (bp) { sq = __builtin_ctzll(bp); score -= pst_pawn[63 - sq]; // Flip for black CLEAR_BIT(bp, sq); } // White knights U64 wn = state->bitboards[N]; while (wn) { sq = __builtin_ctzll(wn); score += pst_knight[sq]; CLEAR_BIT(wn, sq); } // Black knights U64 bn = state->bitboards[n]; while (bn) { sq = __builtin_ctzll(bn); score -= pst_knight[63 - sq]; CLEAR_BIT(bn, sq); } // White bishops U64 wb = state->bitboards[B]; while (wb) { sq = __builtin_ctzll(wb); score += pst_bishop[sq]; CLEAR_BIT(wb, sq); } // Black bishops U64 bb = state->bitboards[b]; while (bb) { sq = __builtin_ctzll(bb); score -= pst_bishop[63 - sq]; CLEAR_BIT(bb, sq); } // White rooks U64 wr = state->bitboards[R]; while (wr) { sq = __builtin_ctzll(wr); score += pst_rook[sq]; CLEAR_BIT(wr, sq); } // Black rooks U64 br = state->bitboards[r]; while (br) { sq = __builtin_ctzll(br); score -= pst_rook[63 - sq]; CLEAR_BIT(br, sq); } // White queens U64 wq = state->bitboards[Q]; while (wq) { sq = __builtin_ctzll(wq); score += pst_queen[sq]; CLEAR_BIT(wq, sq); } // Black queens U64 bq = state->bitboards[q]; while (bq) { sq = __builtin_ctzll(bq); score -= pst_queen[63 - sq]; CLEAR_BIT(bq, sq); } // Kings if (state->bitboards[K]) { sq = __builtin_ctzll(state->bitboards[K]); score += pst_king_mid[sq]; } if (state->bitboards[k]) { sq = __builtin_ctzll(state->bitboards[k]); score -= pst_king_mid[63 - sq]; } // Add randomness to break symmetry in equal positions score += (int)(hash_position(state) % 10) - 5; // Slight bonus for having pieces in the center U64 center = 0x0000001818000000ULL; // e4, e5, d4, d5 U64 extended_center = 0x00003C3C3C3C0000ULL; // c3-f3 to c6-f6 score += __builtin_popcountll(state->occ_white & center) * 5; score -= __builtin_popcountll(state->occ_black & center) * 5; score += __builtin_popcountll(state->occ_white & extended_center) * 2; score -= __builtin_popcountll(state->occ_black & extended_center) * 2; return score; } // Complete evaluation function int evaluate(const GameState *state) { int score = evaluate_material(state) + evaluate_position(state); // Mobility bonus GameState temp_state = *state; Move moves[256]; // Add repetition penalty to avoid draw by repetition everytime U64 current_hash = hash_position(state); for (int i = 0; i < state->history.position_count; i++) { if (state->history.positions[i].hash == current_hash) { if (state->history.positions[i].count >= 2) { score -= 50; // Penalty for positions appearing twice } break; } } temp_state.side_to_move = 0; // White int white_mobility = generate_moves(&temp_state, moves); temp_state.side_to_move = 1; // Black int black_mobility = generate_moves(&temp_state, moves); score += (white_mobility - black_mobility) * 5; // 5 points per move advantage // Adjust for side to move return state->side_to_move == 0 ? score : -score; }