⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 evaluate.cpp

📁 超强国际象棋引擎
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// 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 + -