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

📄 pawn.cpp

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

// includes

#include <cstring>
#include <cstdlib>

#include "config.h"
#include "hash.h"
#include "interface.h"
#include "pawn.h"
#include "search.h"

// types

typedef pawn_info_t entry_t;

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

// this was moved to eval.cpp

static int bonus[16];

// variables

int bit_eq[16];
int bit_lt[16];
int bit_le[16];
int bit_gt[16];
int bit_ge[16];

int bit_first[0x100];
int bit_last[0x100];
int bit_count[0x100];
int bit_rev[0x100];

static pawn_t pawn[16][1];

static int bit_rank_1[16];
static int bit_rank_2[16];
static int bit_rank_3[16];

// prototypes

static void pawn_comp_info(pawn_info_t *info, const board_t *board);

// functions

// pawn_init_bit()

void pawn_init_bit()
    {

    int rank;
    int first, last, count;
    int b, rev;

    // rank-indexed Bit*[]

    for ( rank = 0; rank < 16; rank++ )
        {

        bit_eq[rank] = 0;
        bit_lt[rank] = 0;
        bit_le[rank] = 0;
        bit_gt[rank] = 0;
        bit_ge[rank] = 0;

        bit_rank_1[rank] = 0;
        bit_rank_2[rank] = 0;
        bit_rank_3[rank] = 0;
        }

    for ( rank = (0x4); rank <= (0xB); rank++ )
        {
        bit_eq[rank] = 1 << (rank - (0x4));
        bit_lt[rank] = bit_eq[rank] - 1;
        bit_le[rank] = bit_lt[rank] | bit_eq[rank];
        bit_gt[rank] = bit_le[rank] ^ 0xFF;
        bit_ge[rank] = bit_gt[rank] | bit_eq[rank];
        }

    for ( rank = (0x4); rank <= (0xB); rank++ )
        {
        bit_rank_1[rank] = bit_eq[rank + 1];
        bit_rank_2[rank] = bit_eq[rank + 1] | bit_eq[rank + 2];
        bit_rank_3[rank] = bit_eq[rank + 1] | bit_eq[rank + 2] | bit_eq[rank + 3];
        }

    // bit-indexed Bit*[]

    for ( b = 0; b < 0x100; b++ )
        {

        first = (0xB);
        last = (0x4);
        count = 0;
        rev = 0;

        for ( rank = (0x4); rank <= (0xB); rank++ )
            {
            if((b &bit_eq[rank]) != 0)
                {
                if(rank < first)
                    first = rank;

                if(rank > last)
                    last = rank;
                count++;
                rev |= bit_eq[RANK_OPP(rank)];
                }
            }

        bit_first[b] = first;
        bit_last[b] = last;
        bit_count[b] = count;
        bit_rev[b] = rev;
        }
    }

// pawn_init()

void pawn_init()
    {

    int rank, thread_id;

    // bonus

    for ( rank = 0; rank < 16; rank++ )
        bonus[rank] = 0;

    bonus[(0x7)] = 26;
    bonus[(0x8)] = 77;
    bonus[(0x9)] = 154;
    bonus[(0xA)] = 256;

    // pawn hash-table

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

// pawn_alloc()

void pawn_alloc()
    {

    int thread_id;

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

        pawn_clear(thread_id);
        }
    }

// pawn_free()

void pawn_free()
    {

    int thread_id;

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

// pawn_clear()

void pawn_clear(int thread_id)
    {

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

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

// pawn_get_info()

void pawn_get_info(pawn_info_t *info, const board_t *board, int thread_id)
    {

    uint64 key;
    entry_t *entry;

    // probe

    pawn[thread_id]->read_nb++;

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

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

        // found

        pawn[thread_id]->read_hit++;

        *info = *entry;

        return;
        }

    // calculation

    pawn_comp_info(info, board);

    // store

    pawn[thread_id]->write_nb++;

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

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

// pawn_comp_info()

static void pawn_comp_info(pawn_info_t *info, const board_t *board)
    {

    int color;
    int file, rank;
    int me, opp;
    const sq_t *ptr;
    int sq;
    bool backward, candidate, doubled, isolated, open, passed;
    int t1, t2;
    int n;
    int bits;
    int opening[2], endgame[2];
    int flags[2];
    int file_bits[2];
    int passed_bits[2];
    int single_file[2];

    // pawn_file[]

    // init

    for ( color = 0; color < 2; color++ )
        {

        opening[color] = 0;
        endgame[color] = 0;

        flags[color] = 0;
        file_bits[color] = 0;
        passed_bits[color] = 0;
        single_file[color] = 0;
        }

    // features and scoring

    for ( color = 0; color < 2; color++ )
        {

        me = color;
        opp = COLOUR_OPP(me);

        for ( ptr = &board->pawn[me][0]; (sq = *ptr) != 0; ptr++ )
            {

            // init

            file = SQUARE_FILE(sq);
            rank = PAWN_RANK(sq, me);

            // flags

            file_bits[me] |= BIT(file);

            if(rank == (0x5))
                flags[me] |= (1 << 0);

            // features

            backward = false;
            candidate = false;
            doubled = false;
            isolated = false;
            open = false;
            passed = false;

            t1 = board->pawn_file[me][file - 1] | board->pawn_file[me][file + 1];
            t2 = board->pawn_file[me][file] | bit_rev[board->pawn_file[opp][file]];

            // doubled

            if((board->pawn_file[me][file]&bit_lt[rank]) != 0)
                {
                doubled = true;
                }

            // isolated and backward

            if(t1 == 0)
                {

                isolated = true;
                }
            else if((t1 &bit_le[rank]) == 0)
                {

                backward = true;

                // really backward?

                if((t1 &bit_rank_1[rank]) != 0)
                    {
                    if(((t2 &bit_rank_1[rank])
                        | ((bit_rev[board->pawn_file[opp][file - 1]]
                            | bit_rev[board->pawn_file[opp][file + 1]]) & bit_rank_2[rank]))
                        == 0)
                        {
                        backward = false;
                        }
                    }
                else if(rank == (0x5) && ((t1 &bit_eq[rank + 2]) != 0))
                    {
                    if(((t2 &bit_rank_2[rank])
                        | ((bit_rev[board->pawn_file[opp][file - 1]]
                            | bit_rev[board->pawn_file[opp][file + 1]]) & bit_rank_3[rank]))
                        == 0)
                        {
                        backward = false;
                        }
                    }
                }

            // open, candidate and passed

            if((t2 &bit_gt[rank]) == 0)
                {

                open = true;

                if(((bit_rev[board->pawn_file[opp][file - 1]]
                    | bit_rev[board->pawn_file[opp][file + 1]]) & bit_gt[rank])
                    == 0)
                    {
                    passed = true;
                    passed_bits[me] |= BIT(file);
                    }
                else
                    {

                    // candidate?

                    n = 0;

                    n += BIT_COUNT(board->pawn_file[me][file - 1] & bit_le[rank]);
                    n += BIT_COUNT(board->pawn_file[me][file + 1] & bit_le[rank]);

                    n -= BIT_COUNT(bit_rev[board->pawn_file[opp][file - 1]] & bit_gt[rank]);
                    n -= BIT_COUNT(bit_rev[board->pawn_file[opp][file + 1]] & bit_gt[rank]);

                    if(n >= 0)
                        {

                        // safe?

                        n = 0;

                        n += BIT_COUNT(board->pawn_file[me][file - 1] & bit_eq[rank - 1]);
                        n += BIT_COUNT(board->pawn_file[me][file + 1] & bit_eq[rank - 1]);

                        n -= BIT_COUNT(bit_rev[board->pawn_file[opp][file - 1]] & bit_eq[rank + 1]);
                        n -= BIT_COUNT(bit_rev[board->pawn_file[opp][file + 1]] & bit_eq[rank + 1]);

                        if(n >= 0)
                            candidate = true;
                        }
                    }
                }

            // score

            if(doubled)
                {
                opening[me] -= 10;
                endgame[me] -= 20;
                }

            if(isolated)
                {
                if(open)
                    {
                    opening[me] -= 20;
                    endgame[me] -= 20;
                    }
                else
                    {
                    opening[me] -= 10;
                    endgame[me] -= 20;
                    }
                }

            if(backward)
                {
                if(open)
                    {
                    opening[me] -= 16;
                    endgame[me] -= 10;
                    }
                else
                    {
                    opening[me] -= 8;
                    endgame[me] -= 10;
                    }
                }

            if(candidate)
                {
                opening[me] += quad(5, 55, rank);
                endgame[me] += quad(10, 110, rank);
                }
            }
        }

    // store info

    info->opening = ((opening[0] - opening[1]) * 256) / 256;
    info->endgame = ((endgame[0] - endgame[1]) * 256) / 256;

    for ( color = 0; color < 2; color++ )
        {

        me = color;
        opp = COLOUR_OPP(me);

        // draw flags

        bits = file_bits[me];

        if(bits != 0 && (bits &(bits - 1)) == 0)
            { // one set bit

            file = BIT_FIRST(bits);
            rank = BIT_FIRST(board->pawn_file[me][file]);

            if(((bit_rev[board->pawn_file[opp][file - 1]] | bit_rev[board->pawn_file[opp][file + 1]]) & bit_gt[rank])
                == 0)
                {
                rank = BIT_LAST(board->pawn_file[me][file]);
                single_file[me] = SQUARE_MAKE(file, rank);
                }
            }

        info->flags[color] = flags[color];
        info->passed_bits[color] = passed_bits[color];
        info->single_file[color] = single_file[color];
        }
    }

// quad()

int quad(int y_min, int y_max, int x)
    {

    int y;

    y = y_min + ((y_max - y_min) * bonus[x] + 128) / 256;

    return y;
    }

// end of pawn.cpp

⌨️ 快捷键说明

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