📄 pawn.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 + -