return alpha;
}
int negamax(Stats *stats, int alpha, int beta, int depth) {
int negamax(Stats *stats, int alpha, int beta, int depth, bool null) {
int pv_node = (beta - alpha) > 1;
HasheFlag flag = flagAlpha;
Move bestMove = {0};
int futility = 0;
Board copy;
stats->pv_length[stats->ply] = stats->ply;
int score = ttable_read(stats, alpha, beta, depth);
int score = ttable_read(stats, &bestMove, alpha, beta, depth);
if (stats->ply && score != TTABLE_UNKNOWN && !pv_node) return score;
// && fifty >= 100
if (stats->ply && is_repetition()) return 0;
if (depth == 0) {
stats->nodes++;
int score = quiescence(stats, alpha, beta);
ttable_write(stats, score, depth, flagExact);
// ttable_write(stats, bestMove, score, depth, flagExact);
return score;
}
if (alpha < -MATE_VALUE) alpha = -MATE_VALUE;
if (beta > MATE_VALUE - 1) beta = MATE_VALUE - 1;
if (alpha >= beta) return alpha;
if (stats->ply > MAX_PLY - 1) return evaluate(stats->board);
// if (stats->ply > MAX_PLY - 1) return evaluate(stats->board);
stats->nodes++;
int isCheck = board_isCheck(stats->board);
if (isCheck) depth++;
if (depth >= 3 && !isCheck && stats->ply) {
stats_move_make_pruning(stats, ©);
score = -negamax(stats, -beta, -beta + 1, depth - 1 - REDUCTION_MOVE);
stats_move_unmake(stats, ©);
if (score >= beta) return beta;
if (!pv_node && !isCheck) {
int staticEval = evaluate(stats->board);
// evaluation pruning
if (depth < 3 && abs(beta - 1) > -MATE_VALUE + 100) {
int marginEval = Score_value(PAWN) * depth;
if (staticEval - marginEval >= beta) return staticEval - marginEval;
}
if (null) {
// null move pruning
if (stats->ply && depth > 2 && staticEval >= beta) {
stats_move_make_pruning(stats, ©);
score = -negamax(stats, -beta, -beta + 1,
depth - 1 - REDUCTION_MOVE, false);
stats_move_unmake(stats, ©);
if (score >= beta) return beta;
}
// razoring
score = staticEval + Score_value(PAWN);
int scoreNew = quiescence(stats, alpha, beta);
if (score < beta && depth == 1) {
return (scoreNew > score) ? scoreNew : score;
}
score += Score_value(PAWN);
if (score < beta && depth < 4) {
if (scoreNew < beta)
return (scoreNew > score) ? scoreNew : score;
}
}
// futility pruning condition
static const int margin[] = {0, 100, 300, 500};
if (depth < 4 && abs(alpha) < MATE_SCORE &&
staticEval + margin[depth] <= alpha)
futility = 1;
}
MoveList list;