Compare commits
3 Commits
022daf0a89
...
2069d6073d
| Author | SHA1 | Date | |
|---|---|---|---|
| 2069d6073d | |||
| 5db45a760a | |||
| 86f8184c56 |
9
Makefile
9
Makefile
@@ -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))
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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");
|
||||
|
||||
58
src/hash.c
58
src/hash.c
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user