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