📄 evaluate.cpp
字号:
// eval.cpp
// includes
#include <cstdlib> // for abs()
#include "attack.h"
#include "material.h"
#include "move.h"
#include "config.h"
#include "pawn.h"
#include "piece.h"
#include "interface.h"
#include "see.h"
#include "search.h"
#include "search_root.h"
#include "values.h"
// macros
#define THROUGH(piece) ((piece)==0)
#define ABS(x) ((x)<0?-(x):(x))
// constants and variables
const int knight_outpost[2][64] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 5, 10, 10, 5, 2, 0, 0, 2, 5, 10, 10,
5, 2, 0, 0, 0, 4, 5, 5, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 5, 4, 0, 0, 0, 2, 5, 10, 10, 5, 2, 0, 0, 2, 5, 10, 10, 5, 2, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
static bool king_is_safe[2];
// "constants"
static const int king_attack_weight[16] =
{
0, 0, 128, 192, 224, 240, 248, 252, 254, 255, 256, 256, 256, 256, 256, 256,
};
static const int s_space_weight[16] =
{
0, 2, 5, 8, 12, 15, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
};
// variables
static int mob_unit[2][256];
static int king_attack_unit[256];
// prototypes
static void eval_draw(const board_t *board, const material_info_t *mat_info, const pawn_info_t *pawn_info, int mul[2]);
static void eval_piece(const board_t *board, const material_info_t *mat_info, const pawn_info_t *pawn_info,
int *opening, int *endgame);
static void eval_king(const board_t *board, const material_info_t *mat_info, int *opening, int *endgame);
static void eval_passer(const board_t *board, const pawn_info_t *pawn_info, int *opening, int *endgame);
static void eval_pattern(const board_t *board, int *opening, int *endgame);
static bool unstoppable_passer(const board_t *board, int pawn, int color);
static bool king_passer(const board_t *board, int pawn, int color);
static bool free_passer(const board_t *board, int pawn, int color);
static int pawn_att_dist(int pawn, int king, int color);
static int pawn_def_dist(int pawn, int king, int color);
static void draw_init_list(int list [], const board_t *board, int pawn_colour);
static bool draw_kpkq(const int list [], int turn);
static bool draw_kpkr(const int list [], int turn);
static bool draw_kpkb(const int list [], int turn);
static bool draw_kpkn(const int list [], int turn);
static bool draw_knpk(const int list [], int turn);
static bool draw_krpkr(const int list [], int turn);
static bool draw_kbpkb(const int list [], int turn);
static int shelter_square(const board_t *board, int square, int color);
static int shelter_file(const board_t *board, int file, int rank, int color);
static int storm_file(const board_t *board, int file, int color);
static bool bishop_can_attack(const board_t *board, int to, int color);
// functions
// eval_init()
void eval_init()
{
int color;
int piece;
// mobility table
for ( color = 0; color < 2; color++ )
{
for ( piece = 0; piece < 256; piece++ )
{
mob_unit[color][piece] = 0;
}
}
mob_unit[0][0] = 1;
mob_unit[0][((1 << 3) | (1 << 1))] = 1;
mob_unit[0][((1 << 4) | (1 << 1))] = 1;
mob_unit[0][((1 << 5) | (1 << 1))] = 1;
mob_unit[0][((1 << 6) | (1 << 1))] = 1;
mob_unit[0][(((1 << 5) | (1 << 6)) | (1 << 1))] = 1;
mob_unit[0][((1 << 7) | (1 << 1))] = 1;
mob_unit[0][((1 << 2) | (1 << 0))] = 0;
mob_unit[0][((1 << 4) | (1 << 0))] = 0;
mob_unit[0][((1 << 5) | (1 << 0))] = 0;
mob_unit[0][((1 << 6) | (1 << 0))] = 0;
mob_unit[0][(((1 << 5) | (1 << 6)) | (1 << 0))] = 0;
mob_unit[0][((1 << 7) | (1 << 0))] = 0;
mob_unit[1][0] = 1;
mob_unit[1][((1 << 2) | (1 << 0))] = 1;
mob_unit[1][((1 << 4) | (1 << 0))] = 1;
mob_unit[1][((1 << 5) | (1 << 0))] = 1;
mob_unit[1][((1 << 6) | (1 << 0))] = 1;
mob_unit[1][(((1 << 5) | (1 << 6)) | (1 << 0))] = 1;
mob_unit[1][((1 << 7) | (1 << 0))] = 1;
mob_unit[1][((1 << 3) | (1 << 1))] = 0;
mob_unit[1][((1 << 4) | (1 << 1))] = 0;
mob_unit[1][((1 << 5) | (1 << 1))] = 0;
mob_unit[1][((1 << 6) | (1 << 1))] = 0;
mob_unit[1][(((1 << 5) | (1 << 6)) | (1 << 1))] = 0;
mob_unit[1][((1 << 7) | (1 << 1))] = 0;
// king_attack_unit[]
for ( piece = 0; piece < 256; piece++ )
{
king_attack_unit[piece] = 0;
}
king_attack_unit[((1 << 4) | (1 << 0))] = 1;
king_attack_unit[((1 << 5) | (1 << 0))] = 1;
king_attack_unit[((1 << 6) | (1 << 0))] = 2;
king_attack_unit[(((1 << 5) | (1 << 6)) | (1 << 0))] = 4;
king_attack_unit[((1 << 4) | (1 << 1))] = 1;
king_attack_unit[((1 << 5) | (1 << 1))] = 1;
king_attack_unit[((1 << 6) | (1 << 1))] = 2;
king_attack_unit[(((1 << 5) | (1 << 6)) | (1 << 1))] = 4;
}
// eval()
int eval(board_t *board, int alpha, int beta, int thread_id)
{
int opening, endgame;
material_info_t mat_info[1];
pawn_info_t pawn_info[1];
int mul[2];
int phase;
int eval;
int wb, bb;
int lazy_eval;
// init
opening = 0;
endgame = 0;
// material
material_get_info(mat_info, board, thread_id);
opening += mat_info->opening;
endgame += mat_info->endgame;
mul[0] = mat_info->mul[0];
mul[1] = mat_info->mul[1];
// PST
opening += board->opening;
endgame += board->endgame;
// pawns
pawn_get_info(pawn_info, board, thread_id);
opening += pawn_info->opening;
endgame += pawn_info->endgame;
// draw
eval_draw(board, mat_info, pawn_info, mul);
if(mat_info->mul[0] < mul[0])
mul[0] = mat_info->mul[0];
if(mat_info->mul[1] < mul[1])
mul[1] = mat_info->mul[1];
if(mul[0] == 0 && mul[1] == 0)
return 0;
// eval
// Tempo
if(COLOUR_IS_WHITE(board->turn))
{
opening += 20;
endgame += 10;
}
else
{
opening -= 20;
endgame -= 10;
}
eval_pattern(board, &opening, &endgame);
if(board->piece_size[0] > 3 && board->piece_size[1] > 3)
{
phase = mat_info->phase;
lazy_eval = ((opening * (256 - mat_info->phase)) + (endgame * mat_info->phase)) / 256;
if(COLOUR_IS_BLACK(board->turn))
lazy_eval = -lazy_eval;
if(lazy_eval - 200 >= beta)
return (lazy_eval);
if(lazy_eval + 200 <= alpha)
return (lazy_eval);
}
// eval
eval_piece(board, mat_info, pawn_info, &opening, &endgame);
eval_king(board, mat_info, &opening, &endgame);
eval_passer(board, pawn_info, &opening, &endgame);
// phase mix
phase = mat_info->phase;
eval = ((opening * (256 - phase)) + (endgame * phase)) / 256;
// drawish bishop endgames
if((mat_info->flags &(1 << 1)) != 0)
{
wb = board->piece[0][1];
bb = board->piece[1][1];
if(SQUARE_COLOUR(wb) != SQUARE_COLOUR(bb))
{
if(mul[0] == 16)
mul[0] = 8; // 1/2
if(mul[1] == 16)
mul[1] = 8; // 1/2
}
}
// draw bound
if(eval > 0)
{
eval = (eval * mul[0]) / 16;
}
else if(eval < 0)
{
eval = (eval * mul[1]) / 16;
}
// value range
if(eval < -(30000 - 256))
eval = -(30000 - 256);
if(eval > +(30000 - 256))
eval = +(30000 - 256);
// turn
if(COLOUR_IS_BLACK(board->turn))
eval = -eval;
return eval;
}
// eval_draw()
static void eval_draw(const board_t *board, const material_info_t *mat_info, const pawn_info_t *pawn_info, int mul[2])
{
int color;
int me, opp;
int pawn, king;
int pawn_file;
int prom;
int list[7 + 1];
// draw patterns
for ( color = 0; color < 2; color++ )
{
me = color;
opp = COLOUR_OPP(me);
// KB*P+K* draw
if((mat_info->cflags[me]&(1 << 0)) != 0)
{
pawn = pawn_info->single_file[me];
if(pawn != 0)
{ // all pawns on one file
pawn_file = SQUARE_FILE(pawn);
if(pawn_file == (0x4) || pawn_file == (0xB))
{
king = KING_POS(board, opp);
prom = PAWN_PROMOTE(pawn, me);
if(DISTANCE(king, prom) <= 1 && !bishop_can_attack(board, prom, me))
{
mul[me] = 0;
}
}
}
}
// K(B)P+K+ draw
if((mat_info->cflags[me]&(1 << 1)) != 0)
{
pawn = pawn_info->single_file[me];
if(pawn != 0)
{ // all pawns on one file
king = KING_POS(board, opp);
if(SQUARE_FILE(king) == SQUARE_FILE(pawn) && PAWN_RANK(king, me) > PAWN_RANK(pawn, me)
&& !bishop_can_attack(board, king, me))
{
mul[me] = 1; // 1/16
}
}
}
// KNPK* draw
if((mat_info->cflags[me]&(1 << 2)) != 0)
{
pawn = board->pawn[me][0];
king = KING_POS(board, opp);
if(SQUARE_FILE(king) == SQUARE_FILE(pawn) && PAWN_RANK(king, me) > PAWN_RANK(pawn, me)
&& PAWN_RANK(pawn, me) <= (0x9))
{
mul[me] = 1; // 1/16
}
}
}
// recognisers, only heuristic draws here!
if(false) { }
else if(mat_info->recog == MAT_KPKQ)
{
// KPKQ (white)
draw_init_list(list, board, 0);
if(draw_kpkq(list, board->turn))
{
mul[0] = 1; // 1/16;
mul[1] = 1; // 1/16;
}
}
else if(mat_info->recog == MAT_KQKP)
{
// KPKQ (black)
draw_init_list(list, board, 1);
if(draw_kpkq(list, COLOUR_OPP(board->turn)))
{
mul[0] = 1; // 1/16;
mul[1] = 1; // 1/16;
}
}
else if(mat_info->recog == MAT_KPKR)
{
// KPKR (white)
draw_init_list(list, board, 0);
if(draw_kpkr(list, board->turn))
{
mul[0] = 1; // 1/16;
mul[1] = 1; // 1/16;
}
}
else if(mat_info->recog == MAT_KRKP)
{
// KPKR (black)
draw_init_list(list, board, 1);
if(draw_kpkr(list, COLOUR_OPP(board->turn)))
{
mul[0] = 1; // 1/16;
mul[1] = 1; // 1/16;
}
}
else if(mat_info->recog == MAT_KPKB)
{
// KPKB (white)
draw_init_list(list, board, 0);
if(draw_kpkb(list, board->turn))
{
mul[0] = 1; // 1/16;
mul[1] = 1; // 1/16;
}
}
else if(mat_info->recog == MAT_KBKP)
{
// KPKB (black)
draw_init_list(list, board, 1);
if(draw_kpkb(list, COLOUR_OPP(board->turn)))
{
mul[0] = 1; // 1/16;
mul[1] = 1; // 1/16;
}
}
else if(mat_info->recog == MAT_KPKN)
{
// KPKN (white)
draw_init_list(list, board, 0);
if(draw_kpkn(list, board->turn))
{
mul[0] = 1; // 1/16;
mul[1] = 1; // 1/16;
}
}
else if(mat_info->recog == MAT_KNKP)
{
// KPKN (black)
draw_init_list(list, board, 1);
if(draw_kpkn(list, COLOUR_OPP(board->turn)))
{
mul[0] = 1; // 1/16;
mul[1] = 1; // 1/16;
}
}
else if(mat_info->recog == MAT_KNPK)
{
// KNPK (white)
draw_init_list(list, board, 0);
if(draw_knpk(list, board->turn))
{
mul[0] = 1; // 1/16;
mul[1] = 1; // 1/16;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -