3 Commits

11 changed files with 160 additions and 33 deletions

View File

@@ -68,6 +68,9 @@ CPPFLAGS += -DWARN_ON # brlib bug.h
# fen.c
#CPPFLAGS += -DDEBUG_FEN # FEN decoding
# hash.c
#CPPFLAGS += -HASH_VERIFY # chk zobrist consistency
# attack.c
#CPPFLAGS += -DDEBUG_ATTACK_ATTACKERS # sq_attackers
#CPPFLAGS += -DDEBUG_ATTACK_PINNERS # sq_pinners details
@@ -342,12 +345,12 @@ TEST += movedo-test perft-test
PIECE_OBJS := piece.o
FEN_OBJS := $(PIECE_OBJS) fen.o position.o bitboard.o board.o \
hyperbola-quintessence.o attack.o
hyperbola-quintessence.o attack.o hash.o init.o
BB_OBJS := $(FEN_OBJS)
MOVEGEN_OBJS := $(BB_OBJS) move.o move-gen.o
ATTACK_OBJS := $(MOVEGEN_OBJS)
MOVEDO_OBJS := $(ATTACK_OBJS) move-do.o hash.o
PERFT_OBJS := $(MOVEDO_OBJS) search.o misc.o
MOVEDO_OBJS := $(ATTACK_OBJS) move-do.o misc.o
PERFT_OBJS := $(MOVEDO_OBJS) search.o
TEST := $(addprefix $(BINDIR)/,$(TEST))

View File

@@ -178,4 +178,6 @@ double clock_elapsed_sec(mclock_t *clock);
void rand_init(u64 seed);
u64 rand64(void);
void init_all(void);
#endif /* _CHESSDEFS_H */

View File

@@ -184,6 +184,8 @@ pos_t *fen2pos(pos_t *pos, const char *fen)
piece, PIECE(piece), COLOR(piece));
# endif
pos_set_sq(&tmppos, sq_make(file, rank), piece);
if (PIECE(piece) == KING)
tmppos.king[COLOR(piece)] = sq_make(file, rank);
file++;
} else { /* error */
err_line = __LINE__, err_char = *cur, err_pos = cur - fen;
@@ -250,8 +252,10 @@ end:
}
if (fen_check(&tmppos) < 0)
return NULL;
tmppos.key = zobrist_calc(&tmppos);
if (!pos)
pos = pos_dup(&tmppos);
pos = pos_new();
pos_copy(&tmppos, pos);
//puts("prout 1");
//pos_print_raw(&tmppos, 1);
//puts("prout 2");

View File

@@ -51,6 +51,7 @@ void zobrist_init(void)
/**
* zobrist_calc() - calculate a position zobrist hash.
* @pos: &position
*
* Normally, Zobrist keys are incrementally calculated when doing or
* undoing a move.
@@ -58,6 +59,7 @@ void zobrist_init(void)
* - When starting a new position
* - To verify incremental Zobrist calculation is correct
*
* @return: @pos Zobrist key
*/
key_t zobrist_calc(pos_t *pos)
{
@@ -76,12 +78,64 @@ key_t zobrist_calc(pos_t *pos)
}
}
}
key ^= pos->castle;
key ^= EP_ZOBRIST_IDX(pos->en_passant);
key ^= zobrist_castling[pos->castle];
key ^= zobrist_ep[EP_ZOBRIST_IDX(pos->en_passant)];
return key;
}
/**
* zobrist_verify() - verify current position Zobrist key.
* @pos: &position
*
* Verify that position Zobrist key matches a full Zobrist calculation.
* This function cannot be called if DEBUG_HASH is not set.
*
* @return: True if Zobrist key is OK.
*/
#ifdef ZOBRIST_VERIFY
bool zobrist_verify(pos_t *pos)
{
key_t diff, key = zobrist_calc(pos);
if (pos->key == key)
return true;
printf("key verify: cur=%#lx != %#lx\n", pos->key, key);
/* try to find-out the key in different zobrist tables */
diff = pos->key ^ key;
for (color_t c = WHITE; c <= BLACK; ++c) {
for (piece_type_t p = PAWN; p <= KING; ++p)
for (square_t sq = A1; sq <= H8; ++sq)
if (diff == zobrist_pieces[MAKE_PIECE(p, c)][sq]) {
warn(true, "zobrist difference is piece:[%s][%s]\n",
piece_to_fen(MAKE_PIECE(p, c)), sq_to_string(sq));
goto end;
}
}
for (castle_rights_t c = CASTLE_NONE; c <= CASTLE_ALL; ++c)
if (diff == zobrist_castling[c]) {
warn(true, "zobrist difference is castling:[%d]\n", c);
goto end;
}
for (file_t f = FILE_A; f <= FILE_H; ++f)
if (diff == zobrist_ep[f]) {
warn(true, "zobrist difference is ep:[%d]\n", f);
goto end;
}
if (diff == zobrist_turn) {
warn(true, "zobrist difference is turn\n");
goto end;
}
warn(true, "zobrist diff %lx is unknown\n", diff);
end:
return false;
}
#endif
/**
* hash_create() - hashtable creation.
* @sizemb: s32 size of hash table in Mb

View File

@@ -91,6 +91,12 @@ extern hasht_t hash_tt; /* main transposition table */
void zobrist_init(void);
key_t zobrist_calc(pos_t *pos);
#ifdef ZOBRIST_VERIFY
bool zobrist_verify(pos_t *pos);
#else
#define zobrist_verify(p) true
#endif
int hash_create(int Mb);
void hash_clear(void);
void hash_delete(void);

View File

@@ -21,7 +21,7 @@
#include "hash.h"
void init_all()
void init_all(void)
{
/* for printf() numeric thousands separator */
setlocale(LC_NUMERIC, "");
@@ -37,6 +37,6 @@ void init_all()
/* zobrist tables & default tt hashtable */
zobrist_init();
hash_create(HASH_DEFAULT);
hash_create(HASH_SIZE_DEFAULT);
}

View File

@@ -61,9 +61,12 @@ pos_t *move_do(pos_t *pos, const move_t move) //, state_t *state)
piece_type_t ptype = PIECE(piece);
piece_t new_piece = piece;
int up = sq_up(us);
key_t key = pos->key;
/* update turn, reset castling and ep */
pos->key ^= zobrist_turn;
/* update key: switch turn, reset castling and ep */
key ^= zobrist_turn;
key ^= zobrist_castling[pos->castle];
key ^= zobrist_ep[EP_ZOBRIST_IDX(pos->en_passant)];
++pos->clock_50;
++pos->plycount;
@@ -82,6 +85,7 @@ pos_t *move_do(pos_t *pos, const move_t move) //, state_t *state)
pos->clock_50 = 0;
//pos->captured = pos->board[to]; /* save capture info */
bug_on(pos->board[to] == EMPTY || COLOR(pos->captured) != them);
key ^= zobrist_pieces[captured][to];
pos_clr_sq(pos, to); /* clear square */
} else if (is_castle(move)) { /* handle rook move */
square_t rookfrom, rookto;
@@ -92,20 +96,26 @@ pos_t *move_do(pos_t *pos, const move_t move) //, state_t *state)
rookfrom = sq_rel(A1, us);
rookto = sq_rel(D1, us);
}
key ^= zobrist_pieces[pos->board[rookfrom]][rookto] ^
zobrist_pieces[pos->board[rookfrom]][rookfrom];
pos_set_sq(pos, rookto, pos->board[rookfrom]);
pos_clr_sq(pos, rookfrom);
pos->castle = clr_castle(pos->castle, us);
//pos->castle = clr_castle(pos->castle, us);
} else if (ptype == PAWN) { /* pawn non capture or e.p. */
pos->clock_50 = 0;
if (is_dpush(move)) /* if pawn double push, set e.p. */
if (is_dpush(move)) { /* if pawn double push, set e.p. */
pos->en_passant = from + up;
else if (is_enpassant(move)) { /* clear grabbed pawn */
/* update ep key */
key ^= zobrist_ep[EP_ZOBRIST_IDX(pos->en_passant)];
} else if (is_enpassant(move)) { /* clear grabbed pawn */
square_t grabbed = to - up;
key ^= zobrist_pieces[pos->board[grabbed]][grabbed];
pos_clr_sq(pos, grabbed);
}
}
pos_clr_sq(pos, from); /* always clear "from" and set "to" */
key ^= zobrist_pieces[piece][from] ^ zobrist_pieces[new_piece][to];
pos_clr_sq(pos, from); /* clear "from" and set "to" */
pos_set_sq(pos, to, new_piece);
if (ptype == KING)
@@ -127,7 +137,6 @@ pos_t *move_do(pos_t *pos, const move_t move) //, state_t *state)
else if (from == rel_h1)
pos->castle = clr_oo(pos->castle, us);
}
if (can_castle(pos->castle, them)) {
square_t rel_a8 = sq_rel(A8, us);
square_t rel_h8 = sq_rel(H8, us);
@@ -137,6 +146,12 @@ pos_t *move_do(pos_t *pos, const move_t move) //, state_t *state)
pos->castle = clr_oo(pos->castle, them);
}
/* update castle key */
key ^= zobrist_castling[pos->castle];
pos->key = key;
bug_on(zobrist_verify(pos) == false);
return pos;
}
@@ -153,9 +168,15 @@ pos_t *move_do2(pos_t *pos, const move_t move, state_t *state)
piece_type_t ptype = PIECE(piece);
piece_t new_piece = piece;
int up = sq_up(us);
key_t key = pos->key;
*state = pos->state; /* save irreversible changes */
/* update key: switch turn, reset castling and ep */
key ^= zobrist_turn;
key ^= zobrist_castling[pos->castle];
key ^= zobrist_ep[EP_ZOBRIST_IDX(pos->en_passant)];
++pos->clock_50;
++pos->plycount;
pos->en_passant = SQUARE_NONE;
@@ -173,6 +194,7 @@ pos_t *move_do2(pos_t *pos, const move_t move, state_t *state)
pos->clock_50 = 0;
//pos->captured = pos->board[to]; /* save capture info */
bug_on(pos->board[to] == EMPTY || COLOR(pos->captured) != them);
key ^= zobrist_pieces[captured][to];
pos_clr_sq(pos, to); /* clear square */
} else if (is_castle(move)) { /* handle rook move */
square_t rookfrom, rookto;
@@ -183,20 +205,27 @@ pos_t *move_do2(pos_t *pos, const move_t move, state_t *state)
rookfrom = sq_rel(A1, us);
rookto = sq_rel(D1, us);
}
key ^= zobrist_pieces[pos->board[rookfrom]][rookto];
key ^= zobrist_pieces[pos->board[rookfrom]][rookfrom];
pos_set_sq(pos, rookto, pos->board[rookfrom]);
pos_clr_sq(pos, rookfrom);
pos->castle = clr_castle(pos->castle, us);
} else if (ptype == PAWN) { /* pawn non capture or e.p. */
pos->clock_50 = 0;
if (is_dpush(move)) /* if pawn double push, set e.p. */
if (is_dpush(move)) { /* if pawn double push, set e.p. */
pos->en_passant = from + up;
else if (is_enpassant(move)) { /* clear grabbed pawn */
/* update key */
key ^= zobrist_ep[EP_ZOBRIST_IDX(pos->en_passant)];
} else if (is_enpassant(move)) { /* clear grabbed pawn */
square_t grabbed = to - up;
key ^= zobrist_pieces[pos->board[grabbed]][grabbed];
pos_clr_sq(pos, grabbed);
}
}
pos_clr_sq(pos, from); /* always clear "from" and set "to" */
key ^= zobrist_pieces[piece][from];
key ^= zobrist_pieces[new_piece][to];
pos_clr_sq(pos, from); /* clear "from" and set "to" */
pos_set_sq(pos, to, new_piece);
if (ptype == KING)
@@ -218,7 +247,7 @@ pos_t *move_do2(pos_t *pos, const move_t move, state_t *state)
else if (from == rel_h1)
pos->castle = clr_oo(pos->castle, us);
}
if (can_castle(pos->castle, them)) { /* do we save time with this test ? */
if (can_castle(pos->castle, them)) {
square_t rel_a8 = sq_rel(A8, us);
square_t rel_h8 = sq_rel(H8, us);
if (to == rel_a8)
@@ -227,6 +256,13 @@ pos_t *move_do2(pos_t *pos, const move_t move, state_t *state)
pos->castle = clr_oo(pos->castle, them);
}
/* update castle key */
key ^= zobrist_castling[pos->castle];
pos->key = key;
bug_on(zobrist_verify(pos) == false);
return pos;
}

View File

@@ -62,6 +62,21 @@ pos_t *pos_dup(const pos_t *pos)
return newpos;
}
/**
* pos_copy() - copy a position into another one.
* @from: &position to duplicate.
* @to: &destination position.
*
* Return a copy of @from into @to.
*
* @Return: @to.
*/
pos_t *pos_copy(const pos_t *from, pos_t *to)
{
*to = *from;
return to;
}
/**
* pos_del() - delete a position.
* @pos: &position.
@@ -87,6 +102,7 @@ pos_t *pos_clear(pos_t *pos)
pos->turn = WHITE;
/* move_do/undo position state */
pos->key = 0;
pos->en_passant = SQUARE_NONE;
pos->castle = 0;
pos->clock_50 = 0;
@@ -336,9 +352,9 @@ bool pos_ok(const pos_t *pos, const bool strict)
/* force BUG_ON and WARN_ON */
# pragma push_macro("BUG_ON")
# pragma push_macro("WARN_ON")
# undef BUG_ON
# define BUG_ON
# pragma push_macro("WARN_ON")
# undef WARN_ON
# define WARN_ON

View File

@@ -19,6 +19,7 @@
#include <brlib.h>
#include <bitops.h>
#include <struct-group.h>
#include <bug.h>
#include "chessdefs.h"
#include "hash.h"
@@ -74,11 +75,16 @@ static __always_inline void pos_set_sq(pos_t *pos, square_t square, piece_t piec
{
color_t color = COLOR(piece);
piece_type_t type = PIECE(piece);
bug_on(pos->board[square] != EMPTY);
pos->board[square] = piece;
pos->bb[color][type] |= BIT(square);
pos->bb[color][ALL_PIECES] |= BIT(square);
if (type == KING)
pos->king[color] = square;
//if (type == KING)
// pos->king[color] = square;
//pos->key ^= zobrist_pieces[piece][square];
}
/**
@@ -93,11 +99,16 @@ static __always_inline void pos_clr_sq(pos_t *pos, square_t square)
piece_t piece = pos->board[square];
piece_type_t type = PIECE(piece);
color_t color = COLOR(piece);
bug_on(pos->board[square] == EMPTY);
//pos->key ^= zobrist_pieces[piece][square];
pos->board[square] = EMPTY;
pos->bb[color][type] &= ~BIT(square);
pos->bb[color][ALL_PIECES] &= ~BIT(square);
if (type == KING)
pos->king[color] = SQUARE_NONE;
//if (type == KING)
// pos->king[color] = SQUARE_NONE;
}
/**
@@ -158,6 +169,7 @@ static __always_inline int pos_between_count(const pos_t *pos,
pos_t *pos_new();
pos_t *pos_dup(const pos_t *pos);
pos_t *pos_copy(const pos_t *from, pos_t *to);
void pos_del(pos_t *pos);
pos_t *pos_clear(pos_t *pos);
bool pos_cmp(const pos_t *pos1, const pos_t *pos2);

View File

@@ -32,10 +32,7 @@ int main(int __unused ac, __unused char**av)
movelist_t pseudo;
move_t move;
setlinebuf(stdout); /* line-buffered stdout */
bitboard_init();
hyperbola_init();
init_all();
while ((fen = next_fen(MOVEDO))) {
test_line = cur_line();

View File

@@ -277,17 +277,14 @@ int main(int __unused ac, __unused char**av)
// run = atoi(av[2]) & 3;
printf("depth = %d run = %x sf = %s\n", depth, run, sf_run? "true": "false");
init_all();
if (!run)
exit(0);
setlocale(LC_NUMERIC, "");
setlinebuf(stdout); /* line-buffered stdout */
if (sf_run)
outfd = open_stockfish();
bitboard_init();
hyperbola_init();
CLOCK_DEFINE(clock, CLOCK_PROCESS);
while ((fen = next_fen(PERFT | MOVEDO))) {
test_line = cur_line();