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

📄 material.cpp

📁 超强国际象棋引擎
💻 CPP
字号:
// material.cpp

// includes

#include <cstring>
#include <cstdlib>

#include "config.h"
#include "hash.h"
#include "evaluate.h"
#include "interface.h"
#include "material.h"
#include "search.h"

// constants and variables

#define ABS(x) ((x)<0?-(x):(x))

// types

typedef material_info_t entry_t;

struct material_t
    {
    entry_t *table;
    uint32 size;
    uint32 mask;
    uint32 used;
    sint64 read_nb;
    sint64 read_hit;
    sint64 write_nb;
    sint64 write_collision;
    };

// variables

static material_t Material[16][1];

// prototypes

static void material_comp_info(material_info_t *info, const board_t *board);

// functions

// material_init()

void material_init()
    {

    int thread_id;

    // material table

    for ( thread_id = 0; thread_id < number_threads; thread_id++ )
        {
        Material[thread_id]->size = 0;
        Material[thread_id]->mask = 0;
        Material[thread_id]->table = NULL;
        }
    }

// material_alloc()

void material_alloc()
    {

    int thread_id;

    for ( thread_id = 0; thread_id < number_threads; thread_id++ )
        {
        Material[thread_id]->size = 256;
        Material[thread_id]->mask = 256 - 1;
        Material[thread_id]->table = (entry_t *)malloc(Material[thread_id]->size * sizeof(entry_t));

        material_clear(thread_id);
        }
    }

// material_free()

void material_free()
	{

	int thread_id;
    for ( thread_id = 0; thread_id < number_threads; thread_id++ )
		{
		if (Material[thread_id]->table)
			free(Material[thread_id]->table);
		Material[thread_id]->table = 0;
		}
	}

// material_clear()

void material_clear(int thread_id)
    {

    if(Material[thread_id]->table != NULL)
        {
        memset(Material[thread_id]->table, 0, Material[thread_id]->size * sizeof(entry_t));
        }

    Material[thread_id]->used = 0;
    Material[thread_id]->read_nb = 0;
    Material[thread_id]->read_hit = 0;
    Material[thread_id]->write_nb = 0;
    Material[thread_id]->write_collision = 0;
    }

// material_get_info()

void material_get_info(material_info_t *info, const board_t *board, int thread_id)
    {

    uint64 key;
    entry_t *entry;

    // probe

    Material[thread_id]->read_nb++;

    key = board->material_key;
    entry = &Material[thread_id]->table[KEY_INDEX(key) & Material[thread_id]->mask];

    if(entry->lock == KEY_LOCK(key))
        {

        // found

        Material[thread_id]->read_hit++;

        *info = *entry;

        return;
        }

    // calculation

    material_comp_info(info, board);

    // store

    Material[thread_id]->write_nb++;

    if(entry->lock == 0)
        {
        Material[thread_id]->used++;
        }
    else
        {
        Material[thread_id]->write_collision++;
        }

    *entry = *info;
    entry->lock = KEY_LOCK(key);
    }

// material_comp_info()

static void material_comp_info(material_info_t *info, const board_t *board)
    {

    int wp, wn, wb, wr, wq;
    int bp, bn, bb, br, bq;
    int wt, bt;
    int wm, bm;
    int color;
    int recog;
    int flags;
    int cflags[2];
    int mul[2];
    int phase;
    int opening, endgame;
    int owf, obf, ewf, ebf;

    // init

    wp = board->number[0];
    wn = board->number[2];
    wb = board->number[4];
    wr = board->number[6];
    wq = board->number[8];

    bp = board->number[1];
    bn = board->number[3];
    bb = board->number[5];
    br = board->number[7];
    bq = board->number[9];

    wt = wq + wr + wb + wn + wp; // no king
    bt = bq + br + bb + bn + bp; // no king

    wm = wb + wn;
    bm = bb + bn;

    // recogniser

    recog = MAT_NONE;

    if(false) { }
    else if(wt == 0 && bt == 0)
        {

        recog = MAT_KK;
        }
    else if(wt == 1 && bt == 0)
        {
        if(wb == 1)
            recog = MAT_KBK;

        if(wn == 1)
            recog = MAT_KNK;

        if(wp == 1)
            recog = MAT_KPK;
        }
    else if(wt == 0 && bt == 1)
        {
        if(bb == 1)
            recog = MAT_KKB;

        if(bn == 1)
            recog = MAT_KKN;

        if(bp == 1)
            recog = MAT_KKP;
        }
    else if(wt == 1 && bt == 1)
        {
        if(wq == 1 && bq == 1)
            recog = MAT_KQKQ;

        if(wq == 1 && bp == 1)
            recog = MAT_KQKP;

        if(wp == 1 && bq == 1)
            recog = MAT_KPKQ;

        if(wr == 1 && br == 1)
            recog = MAT_KRKR;

        if(wr == 1 && bp == 1)
            recog = MAT_KRKP;

        if(wp == 1 && br == 1)
            recog = MAT_KPKR;

        if(wb == 1 && bb == 1)
            recog = MAT_KBKB;

        if(wb == 1 && bp == 1)
            recog = MAT_KBKP;

        if(wp == 1 && bb == 1)
            recog = MAT_KPKB;

        if(wn == 1 && bn == 1)
            recog = MAT_KNKN;

        if(wn == 1 && bp == 1)
            recog = MAT_KNKP;

        if(wp == 1 && bn == 1)
            recog = MAT_KPKN;
        }
    else if(wt == 2 && bt == 0)
        {
        if(wb == 1 && wp == 1)
            recog = MAT_KBPK;

        if(wn == 1 && wp == 1)
            recog = MAT_KNPK;
        }
    else if(wt == 0 && bt == 2)
        {
        if(bb == 1 && bp == 1)
            recog = MAT_KKBP;

        if(bn == 1 && bp == 1)
            recog = MAT_KKNP;
        }
    else if(wt == 2 && bt == 1)
        {
        if(wr == 1 && wp == 1 && br == 1)
            recog = MAT_KRPKR;

        if(wb == 1 && wp == 1 && bb == 1)
            recog = MAT_KBPKB;
        }
    else if(wt == 1 && bt == 2)
        {
        if(wr == 1 && br == 1 && bp == 1)
            recog = MAT_KRKRP;

        if(wb == 1 && bb == 1 && bp == 1)
            recog = MAT_KBKBP;
        }

    // draw node (exact-draw recogniser)

    flags = 0; // TODO: MOVE ME

    for ( color = 0; color < 2; color++ )
        cflags[color] = 0;

    if(wq + wr + wp == 0 && bq + br + bp == 0)
        {               // no major piece or pawn
        if(wm + bm <= 1 // at most one minor => KK, KBK or KNK
        || recog == MAT_KBKB)
            {
            flags |= (1 << 0);
            }
        }
    else if(recog == MAT_KPK || recog == MAT_KKP || recog == MAT_KBPK || recog == MAT_KKBP)
        {
        flags |= (1 << 0);
        }

    // bishop endgame

    if(wq + wr + wn == 0 && bq + br + bn == 0)
        { // only bishops
        if(wb == 1 && bb == 1)
            {
            if(wp - bp >= -2 && wp - bp <= +2)
                { // pawn diff <= 2
                flags |= (1 << 1);
                }
            }
        }

    // multipliers

    for ( color = 0; color < 2; color++ )
        mul[color] = 16; // 1

    // white multiplier

    if(wp == 0)
        { // white has no pawns

        int w_maj = wq * 2 + wr;
        int w_min = wb + wn;
        int w_tot = w_maj * 2 + w_min;

        int b_maj = bq * 2 + br;
        int b_min = bb + bn;
        int b_tot = b_maj * 2 + b_min;

        if(false) { }
        else if(w_tot == 1)
            {

            // KBK* or KNK*, always insufficient

            mul[0] = 0;
            }
        else if(w_tot == 2 && wn == 2)
            {

            // KNNK*, usually insufficient

            if(b_tot != 0 || bp == 0)
                {
                mul[0] = 0;
                }
            else
                {           // KNNKP+, might not be draw
                mul[0] = 1; // 1/16
                }
            }
        else if(w_tot == 2 && wb == 2 && b_tot == 1 && bn == 1)
            {

            // KBBKN*, barely drawish (not at all?)

            mul[0] = 8; // 1/2
            }
        else if(w_tot - b_tot <= 1 && w_maj <= 2)
            {

            // no more than 1 minor up, drawish

            mul[0] = 2; // 1/8
            }
        }
    else if(wp == 1)
        { // white has one pawn

        int w_maj = wq * 2 + wr;
        int w_min = wb + wn;
        int w_tot = w_maj * 2 + w_min;

        int b_maj = bq * 2 + br;
        int b_min = bb + bn;
        int b_tot = b_maj * 2 + b_min;

        if(false) { }
        else if(b_min != 0)
            {

            // assume black sacrifices a minor against the lone pawn

            b_min--;
            b_tot--;

            if(false) { }
            else if(w_tot == 1)
                {

                // KBK* or KNK*, always insufficient

                mul[0] = 4; // 1/4
                }
            else if(w_tot == 2 && wn == 2)
                {

                // KNNK*, usually insufficient

                mul[0] = 4; // 1/4
                }
            else if(w_tot - b_tot <= 1 && w_maj <= 2)
                {

                // no more than 1 minor up, drawish

                mul[0] = 8; // 1/2
                }
            }
        else if(br != 0)
            {

            // assume black sacrifices a rook against the lone pawn

            b_maj--;
            b_tot -= 2;

            if(false) { }
            else if(w_tot == 1)
                {

                // KBK* or KNK*, always insufficient

                mul[0] = 4; // 1/4
                }
            else if(w_tot == 2 && wn == 2)
                {

                // KNNK*, usually insufficient

                mul[0] = 4; // 1/4
                }
            else if(w_tot - b_tot <= 1 && w_maj <= 2)
                {

                // no more than 1 minor up, drawish

                mul[0] = 8; // 1/2
                }
            }
        }

    // black multiplier

    if(bp == 0)
        { // black has no pawns

        int w_maj = wq * 2 + wr;
        int w_min = wb + wn;
        int w_tot = w_maj * 2 + w_min;

        int b_maj = bq * 2 + br;
        int b_min = bb + bn;
        int b_tot = b_maj * 2 + b_min;

        if(false) { }
        else if(b_tot == 1)
            {

            // KBK* or KNK*, always insufficient

            mul[1] = 0;
            }
        else if(b_tot == 2 && bn == 2)
            {

            // KNNK*, usually insufficient

            if(w_tot != 0 || wp == 0)
                {
                mul[1] = 0;
                }
            else
                {           // KNNKP+, might not be draw
                mul[1] = 1; // 1/16
                }
            }
        else if(b_tot == 2 && bb == 2 && w_tot == 1 && wn == 1)
            {

            // KBBKN*, barely drawish (not at all?)

            mul[1] = 8; // 1/2
            }
        else if(b_tot - w_tot <= 1 && b_maj <= 2)
            {

            // no more than 1 minor up, drawish

            mul[1] = 2; // 1/8
            }
        }
    else if(bp == 1)
        { // black has one pawn

        int w_maj = wq * 2 + wr;
        int w_min = wb + wn;
        int w_tot = w_maj * 2 + w_min;

        int b_maj = bq * 2 + br;
        int b_min = bb + bn;
        int b_tot = b_maj * 2 + b_min;

        if(false) { }
        else if(w_min != 0)
            {

            // assume white sacrifices a minor against the lone pawn

            w_min--;
            w_tot--;

            if(false) { }
            else if(b_tot == 1)
                {

                // KBK* or KNK*, always insufficient

                mul[1] = 4; // 1/4
                }
            else if(b_tot == 2 && bn == 2)
                {

                // KNNK*, usually insufficient

                mul[1] = 4; // 1/4
                }
            else if(b_tot - w_tot <= 1 && b_maj <= 2)
                {

                // no more than 1 minor up, drawish

                mul[1] = 8; // 1/2
                }
            }
        else if(wr != 0)
            {

            // assume white sacrifices a rook against the lone pawn

            w_maj--;
            w_tot -= 2;

            if(false) { }
            else if(b_tot == 1)
                {

                // KBK* or KNK*, always insufficient

                mul[1] = 4; // 1/4
                }
            else if(b_tot == 2 && bn == 2)
                {

                // KNNK*, usually insufficient

                mul[1] = 4; // 1/4
                }
            else if(b_tot - w_tot <= 1 && b_maj <= 2)
                {

                // no more than 1 minor up, drawish

                mul[1] = 8; // 1/2
                }
            }
        }

    // potential draw for white

    if(wt == wb + wp && wp >= 1)
        cflags[0] |= (1 << 0);

    if(wt == wb + wp && wb <= 1 && wp >= 1 && bt > bp)
        cflags[0] |= (1 << 1);

    if(wt == 2 && wn == 1 && wp == 1 && bt > bp)
        cflags[0] |= (1 << 2);

    // potential draw for black

    if(bt == bb + bp && bp >= 1)
        cflags[1] |= (1 << 0);

    if(bt == bb + bp && bb <= 1 && bp >= 1 && wt > wp)
        cflags[1] |= (1 << 1);

    if(bt == 2 && bn == 1 && bp == 1 && wt > wp)
        cflags[1] |= (1 << 2);

    // draw leaf (likely draw)

    if(recog == MAT_KQKQ || recog == MAT_KRKR)
        {
        mul[0] = 0;
        mul[1] = 0;
        }

    // king safety

    if(bq >= 1 && bq + br + bb + bn >= 2)
        cflags[0] |= (1 << 3);

    if(wq >= 1 && wq + wr + wb + wn >= 2)
        cflags[1] |= (1 << 3);

    // phase (0: opening -> 256: endgame)

    phase = 24;

    phase -= wp * 0;
    phase -= wn * 1;
    phase -= wb * 1;
    phase -= wr * 2;
    phase -= wq * 4;

    phase -= bp * 0;
    phase -= bn * 1;
    phase -= bb * 1;
    phase -= br * 2;
    phase -= bq * 4;

    if(phase < 0)
        phase = 0;

    phase = (phase * 256 + (24 / 2)) / 24;

    // material

    opening = 0;
    endgame = 0;

    owf = wn * 325 + wb * 325 + wr * 500 + wq * 975;
    opening += owf;
    opening += wp * 70;

    obf = bn * 325 + bb * 325 + br * 500 + bq * 975;
    opening -= obf;
    opening -= bp * 70;

    ewf = wn * 315 + wb * 315 + wr * 500 + wq * 975;
    endgame += wp * 90;
    endgame += ewf;

    ebf = bn * 315 + bb * 315 + br * 500 + bq * 975;
    endgame -= bp * 90;
    endgame -= ebf;

    // Trade bonus

    if(owf > obf && bp > wp)
        {
        opening += 20;
        endgame += 20;
        }
    else if(obf > owf && wp > bp)
        {
        opening -= 20;
        endgame -= 20;
        }

    // bishop pair

    if(wb >= 2)
        {
        opening += 50;
        endgame += 70;
        }

    if(bb >= 2)
        {
        opening -= 50;
        endgame -= 70;
        }

    // store info

    info->recog = recog;
    info->flags = flags;

    for ( color = 0; color < 2; color++ )
        info->cflags[color] = cflags[color];

    for ( color = 0; color < 2; color++ )
        info->mul[color] = mul[color];
    info->phase = phase;
    info->opening = (opening * 256) / 256;
    info->endgame = (endgame * 256) / 256;
    }

// end of material.cpp

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -