testsAndMisc/C/lichess_random_engine/search.c

113 lines
2.2 KiB
C

#include "search.h"
#include "movegen.h"
#include <limits.h>
#include <stddef.h>
static int piece_value(Piece p)
{
if (p == WK || p == BK)
{
return 0; // king is invaluable; PST handled later if needed
}
switch (p)
{
case WP:
case BP:
return 100;
case WN:
case BN:
return 320;
case WB:
case BB:
return 330;
case WR:
case BR:
return 500;
case WQ:
case BQ:
return 900;
default:
return 0;
}
}
int evaluate(const Position *pos)
{
int score = 0;
for (int sq = 0; sq < BOARD_SIZE; ++sq)
{
if ((sq & 0x88))
{
sq = (sq | 7);
continue;
}
Piece p = pos->board[sq];
if (p == EMPTY)
{
continue;
}
int v = piece_value(p);
if (p >= WP && p <= WK)
{
score += v;
}
else if (p >= BP && p <= BK)
{
score -= v;
}
}
// Score from side-to-move perspective
return (pos->side == WHITE) ? score : -score;
}
int alphabeta(Position pos, int depth, int alpha, int beta, PrincipalVariation *pv)
{
if (depth <= 0)
{
return evaluate(&pos);
}
Move moves[256];
int n = gen_moves(&pos, moves, 256, 0);
if (n == 0)
{
// Checkmate or stalemate
if (in_check(&pos, pos.side))
{
return -30000 + (10 - depth); // checkmated
}
return 0; // stalemate
}
int best_score = INT_MIN / 2;
int best_from = -1;
int best_to = -1;
for (int i = 0; i < n; i++)
{
Position child = pos;
Piece cap = EMPTY;
make_move(&child, &moves[i], &cap);
int score = -alphabeta(child, depth - 1, -beta, -alpha, NULL);
if (score > best_score)
{
best_score = score;
best_from = moves[i].from;
best_to = moves[i].to;
}
if (best_score > alpha)
{
alpha = best_score;
}
if (alpha >= beta)
{
break; // beta cutoff
}
}
if (pv != NULL)
{
pv->from = best_from;
pv->to = best_to;
}
return best_score;
}