Compare commits
11 Commits
movegen-re
...
2505217c70
Author | SHA1 | Date | |
---|---|---|---|
2505217c70 | |||
8b3202fac0 | |||
473cc8683e | |||
f0acdb6a66 | |||
a49c712471 | |||
2b72fac45e | |||
0330696f87 | |||
a6eedebc19 | |||
ab31274d17 | |||
03da11cc9c | |||
bfed0f417d |
@@ -1,3 +1,3 @@
|
|||||||
((nil . ((compile-command . (concat "make -C "
|
((nil . ((compile-command . (concat "make -C "
|
||||||
(vc-root-dir)
|
(vc-root-dir)
|
||||||
" -k -j2 testing")))))
|
" -k -j4 testing")))))
|
||||||
|
46
Makefile
46
Makefile
@@ -70,15 +70,14 @@ CPPFLAGS += -DWARN_ON # brlib bug.h
|
|||||||
#CPPFLAGS += -DDEBUG_FEN # FEN decoding
|
#CPPFLAGS += -DDEBUG_FEN # FEN decoding
|
||||||
|
|
||||||
# attack.c
|
# attack.c
|
||||||
#CPPFLAGS += -DDEBUG_ATTACK_ATTACKERS1 # sq_attackers details
|
#CPPFLAGS += -DDEBUG_ATTACK_ATTACKERS # sq_attackers
|
||||||
CPPFLAGS += -DDEBUG_ATTACK_ATTACKERS # sq_attackers
|
#CPPFLAGS += -DDEBUG_ATTACK_PINNERS # sq_pinners details
|
||||||
CPPFLAGS += -DDEBUG_ATTACK_PINNERS # sq_pinners details
|
|
||||||
|
|
||||||
#CPPFLAGS += -DDEBUG_EVAL # eval functions
|
#CPPFLAGS += -DDEBUG_EVAL # eval functions
|
||||||
#CPPFLAGS += -DDEBUG_PIECE # piece list management
|
#CPPFLAGS += -DDEBUG_PIECE # piece list management
|
||||||
#CPPFLAGS += -DDEBUG_SEARCH # move search
|
#CPPFLAGS += -DDEBUG_SEARCH # move search
|
||||||
|
|
||||||
CPPFLAGS += -DDIAGRAM_SYM # diagram with symbols
|
CPPFLAGS += -DDIAGRAM_SYM # UTF8 symbols in diagrams
|
||||||
|
|
||||||
# remove extraneous spaces (due to spaces before comments)
|
# remove extraneous spaces (due to spaces before comments)
|
||||||
CPPFLAGS := $(strip $(CPPFLAGS))
|
CPPFLAGS := $(strip $(CPPFLAGS))
|
||||||
@@ -98,12 +97,14 @@ CFLAGS += -ginline-points # inlined funcs debu
|
|||||||
#CFLAGS += -mno-tbm
|
#CFLAGS += -mno-tbm
|
||||||
|
|
||||||
# release
|
# release
|
||||||
CFLAGS += -Ofast
|
CFLAGS += -O3
|
||||||
|
|
||||||
CFLAGS += -march=native
|
CFLAGS += -march=native
|
||||||
CFLAGS += -flto
|
CFLAGS += -flto
|
||||||
|
CFLAGS += -funroll-loops
|
||||||
CFLAGS += -Wall
|
CFLAGS += -Wall
|
||||||
CFLAGS += -Wextra
|
CFLAGS += -Wextra
|
||||||
|
CFLAGS += -Wshadow
|
||||||
CFLAGS += -Wmissing-declarations
|
CFLAGS += -Wmissing-declarations
|
||||||
|
|
||||||
CFLAGS := $(strip $(CFLAGS))
|
CFLAGS := $(strip $(CFLAGS))
|
||||||
@@ -130,6 +131,38 @@ DEPFLAGS = -MMD -MP -MF $(DEPDIR)/$*.d
|
|||||||
ALL_CFLAGS = $(DEPFLAGS) $(CPPFLAGS) $(CFLAGS)
|
ALL_CFLAGS = $(DEPFLAGS) $(CPPFLAGS) $(CFLAGS)
|
||||||
ALL_LDFLAGS = $(LDFLAGS) $(LIBS)
|
ALL_LDFLAGS = $(LDFLAGS) $(LIBS)
|
||||||
|
|
||||||
|
##################################### Multi-targets
|
||||||
|
# We can have an issue with Make's "-j" option, in some situations,
|
||||||
|
# for example "make -j2 clean testing".
|
||||||
|
# See https://stackoverflow.com/a/8496333/3079831
|
||||||
|
|
||||||
|
# Check if job server supported:
|
||||||
|
ifeq ($(filter jobserver, $(.FEATURES)),)
|
||||||
|
# Job server not supported: sub-makes will only start one job unless
|
||||||
|
# you specify a higher number here. Here we use a MS Windows environment
|
||||||
|
# variable specifying number of processors.
|
||||||
|
JOBSARG := -j $(NUMBER_OF_PROCESSORS)
|
||||||
|
else
|
||||||
|
# Job server is supported; let GNU Make work as normal.
|
||||||
|
JOBSARG :=
|
||||||
|
endif
|
||||||
|
|
||||||
|
# .FEATURES only works in GNU Make 3.81+.
|
||||||
|
# If GNU make is older, assume job server support.
|
||||||
|
ifneq ($(firstword $(sort 3.81 $(MAKE_VERSION))),3.81)
|
||||||
|
# If you are using GNU Make < 3.81 that does not support job servers, you
|
||||||
|
# might want to specify -jN parameter here instead.
|
||||||
|
JOBSARG :=
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(words $(MAKECMDGOALS)),1)
|
||||||
|
.NOTPARALLEL:
|
||||||
|
# The "all" target is required in the list,
|
||||||
|
# in case user invokes make with no targets.
|
||||||
|
$(sort all $(MAKECMDGOALS)):
|
||||||
|
@$(MAKE) $(JOBSARG) -f $(firstword $(MAKEFILE_LIST)) $@
|
||||||
|
else
|
||||||
|
|
||||||
##################################### General targets
|
##################################### General targets
|
||||||
.PHONY: all compile clean cleanall
|
.PHONY: all compile clean cleanall
|
||||||
|
|
||||||
@@ -380,3 +413,6 @@ wtf:
|
|||||||
|
|
||||||
zob:
|
zob:
|
||||||
$(CC) $(LDFLAGS) $(CPPFLAGS) $(CFLAGS) $< $(LIBS) src/util.c -o util
|
$(CC) $(LDFLAGS) $(CPPFLAGS) $(CFLAGS) $< $(LIBS) src/util.c -o util
|
||||||
|
|
||||||
|
##################################### End of multi-targets
|
||||||
|
endif
|
||||||
|
13
src/attack.c
13
src/attack.c
@@ -101,7 +101,6 @@ bitboard_t sq_attackers(const pos_t *pos, const bitboard_t occ, const square_t s
|
|||||||
{
|
{
|
||||||
bitboard_t attackers = 0, tmp;
|
bitboard_t attackers = 0, tmp;
|
||||||
bitboard_t sqbb = mask(sq);
|
bitboard_t sqbb = mask(sq);
|
||||||
//bitboard_t occ = pos_occ(pos);
|
|
||||||
bitboard_t to;
|
bitboard_t to;
|
||||||
color_t opp = OPPONENT(c);
|
color_t opp = OPPONENT(c);
|
||||||
|
|
||||||
@@ -109,12 +108,12 @@ bitboard_t sq_attackers(const pos_t *pos, const bitboard_t occ, const square_t s
|
|||||||
to = pos->bb[c][PAWN];
|
to = pos->bb[c][PAWN];
|
||||||
tmp = pawn_shift_upleft(sqbb, opp) & to;
|
tmp = pawn_shift_upleft(sqbb, opp) & to;
|
||||||
attackers |= tmp;
|
attackers |= tmp;
|
||||||
# ifdef DEBUG_ATTACK_ATTACKERS1
|
# ifdef DEBUG_ATTACK_ATTACKERS
|
||||||
bb_print("att pawn upleft", tmp);
|
bb_print("att pawn upleft", tmp);
|
||||||
# endif
|
# endif
|
||||||
tmp = pawn_shift_upright(sqbb, opp) & to;
|
tmp = pawn_shift_upright(sqbb, opp) & to;
|
||||||
attackers |= tmp;
|
attackers |= tmp;
|
||||||
# ifdef DEBUG_ATTACK_ATTACKERS1
|
# ifdef DEBUG_ATTACK_ATTACKERS
|
||||||
bb_print("att pawn upright", tmp);
|
bb_print("att pawn upright", tmp);
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
@@ -122,13 +121,13 @@ bitboard_t sq_attackers(const pos_t *pos, const bitboard_t occ, const square_t s
|
|||||||
to = pos->bb[c][KNIGHT];
|
to = pos->bb[c][KNIGHT];
|
||||||
tmp = bb_knight_moves(to, sq);
|
tmp = bb_knight_moves(to, sq);
|
||||||
attackers |= tmp;
|
attackers |= tmp;
|
||||||
# ifdef DEBUG_ATTACK_ATTACKERS1
|
# ifdef DEBUG_ATTACK_ATTACKERS
|
||||||
bb_print("att knight", tmp);
|
bb_print("att knight", tmp);
|
||||||
# endif
|
# endif
|
||||||
to = pos->bb[c][KING];
|
to = pos->bb[c][KING];
|
||||||
tmp = bb_king_moves(to, sq);
|
tmp = bb_king_moves(to, sq);
|
||||||
attackers |= tmp;
|
attackers |= tmp;
|
||||||
# ifdef DEBUG_ATTACK_ATTACKERS1
|
# ifdef DEBUG_ATTACK_ATTACKERS
|
||||||
bb_print("att king", tmp);
|
bb_print("att king", tmp);
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
@@ -136,7 +135,7 @@ bitboard_t sq_attackers(const pos_t *pos, const bitboard_t occ, const square_t s
|
|||||||
to = pos->bb[c][BISHOP] | pos->bb[c][QUEEN];
|
to = pos->bb[c][BISHOP] | pos->bb[c][QUEEN];
|
||||||
tmp = hyperbola_bishop_moves(occ, sq) & to;
|
tmp = hyperbola_bishop_moves(occ, sq) & to;
|
||||||
attackers |= tmp;
|
attackers |= tmp;
|
||||||
# ifdef DEBUG_ATTACK_ATTACKERS1
|
# ifdef DEBUG_ATTACK_ATTACKERS
|
||||||
bb_print("att bishop/queen", tmp);
|
bb_print("att bishop/queen", tmp);
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
@@ -144,7 +143,7 @@ bitboard_t sq_attackers(const pos_t *pos, const bitboard_t occ, const square_t s
|
|||||||
to = pos->bb[c][ROOK] | pos->bb[c][QUEEN];
|
to = pos->bb[c][ROOK] | pos->bb[c][QUEEN];
|
||||||
tmp = hyperbola_rook_moves(occ, sq) & to;
|
tmp = hyperbola_rook_moves(occ, sq) & to;
|
||||||
attackers |= tmp;
|
attackers |= tmp;
|
||||||
# ifdef DEBUG_ATTACK_ATTACKERS1
|
# ifdef DEBUG_ATTACK_ATTACKERS
|
||||||
bb_print("att rook/queen", tmp);
|
bb_print("att rook/queen", tmp);
|
||||||
bb_print("ATTACKERS", attackers);
|
bb_print("ATTACKERS", attackers);
|
||||||
printf("attackers=%lx\n", attackers);
|
printf("attackers=%lx\n", attackers);
|
||||||
|
@@ -54,7 +54,6 @@ pos_t *move_do(pos_t *pos, const move_t move) //, state_t *state)
|
|||||||
piece_t piece = pos->board[from];
|
piece_t piece = pos->board[from];
|
||||||
piece_t captured = pos->board[to];
|
piece_t captured = pos->board[to];
|
||||||
piece_type_t ptype = PIECE(piece);
|
piece_type_t ptype = PIECE(piece);
|
||||||
color_t pcolor = COLOR(piece);
|
|
||||||
piece_t new_piece = piece;
|
piece_t new_piece = piece;
|
||||||
int up = sq_up(us);
|
int up = sq_up(us);
|
||||||
|
|
||||||
@@ -64,7 +63,7 @@ pos_t *move_do(pos_t *pos, const move_t move) //, state_t *state)
|
|||||||
pos->turn = them;
|
pos->turn = them;
|
||||||
pos->captured = captured;
|
pos->captured = captured;
|
||||||
|
|
||||||
bug_on(pcolor != us);
|
bug_on(COLOR(piece) != us);
|
||||||
|
|
||||||
if (is_promotion(move)) {
|
if (is_promotion(move)) {
|
||||||
bug_on(sq_rank(to) != sq_rel_rank(RANK_8, us));
|
bug_on(sq_rank(to) != sq_rel_rank(RANK_8, us));
|
||||||
@@ -149,12 +148,8 @@ pos_t *move_do(pos_t *pos, const move_t move) //, state_t *state)
|
|||||||
*
|
*
|
||||||
* @return: pos.
|
* @return: pos.
|
||||||
*/
|
*/
|
||||||
pos_t *move_undo(pos_t *pos, const move_t move)//, const state_t *state)
|
pos_t *move_undo(pos_t *pos, const move_t move)
|
||||||
{
|
{
|
||||||
//# ifdef DEBUG_MOVE
|
|
||||||
//log(1, "new move: ");
|
|
||||||
//move_print(0, move, M_PR_NL | M_PR_LONG);
|
|
||||||
//# endif
|
|
||||||
color_t them = pos->turn, us = OPPONENT(them);
|
color_t them = pos->turn, us = OPPONENT(them);
|
||||||
square_t from = move_from(move), to = move_to(move);
|
square_t from = move_from(move), to = move_to(move);
|
||||||
piece_t piece = pos->board[to];
|
piece_t piece = pos->board[to];
|
||||||
|
175
src/move-gen.c
175
src/move-gen.c
@@ -53,10 +53,10 @@ bool pseudo_is_legal(const pos_t *pos, const move_t move)
|
|||||||
if (unlikely(from == king)) {
|
if (unlikely(from == king)) {
|
||||||
if (unlikely(is_castle(move))) {
|
if (unlikely(is_castle(move))) {
|
||||||
square_t dir = to > from? 1: -1;
|
square_t dir = to > from? 1: -1;
|
||||||
if (sq_attackers(pos, occ, from + dir, them))
|
if (sq_is_attacked(pos, occ, from + dir, them))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return !sq_attackers(pos, occ ^ kingbb, to, them);
|
return !sq_is_attacked(pos, occ ^ kingbb, to, them);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (2) - King is in check
|
/* (2) - King is in check
|
||||||
@@ -138,24 +138,52 @@ move_t pos_next_legal(const pos_t *pos, movelist_t *movelist, int *start)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pos_all_legal() - get the list of legal moves from pseudo-legal.
|
* pos_legal_dup() - get legal moves from pseudo-legal ones in new list.
|
||||||
* @pos: position
|
* @pos: position
|
||||||
* @movelist: &pseudo-legal movelist_t
|
* @pseudo: &movelist_t pseudo-legal moves list
|
||||||
* @dest: &destination movelist_t
|
* @legal: &movelist_t legal moves
|
||||||
*
|
*
|
||||||
* The pseudo-legal moves must be already calculated before calling this function.
|
* The pseudo-legal moves must be already calculated before calling this function.
|
||||||
* No check is done on @dest limits.
|
* No check is done on @legal limits.
|
||||||
|
* This function is similar to pos_legal(), but creates a new list for legal moves.
|
||||||
|
* It should only be used for debug purpose, when we want to keep a copy of
|
||||||
|
* pseudo-legal moves.
|
||||||
*
|
*
|
||||||
* @Return: @dest
|
* @return: @legal
|
||||||
*/
|
*/
|
||||||
movelist_t *pos_all_legal(const pos_t *pos, movelist_t *movelist, movelist_t *dest)
|
movelist_t *pos_legal_dup(const pos_t *pos, movelist_t *pseudo, movelist_t *legal)
|
||||||
{
|
{
|
||||||
int tmp = dest->nmoves = 0;
|
int tmp = legal->nmoves = 0;
|
||||||
move_t move;
|
move_t move;
|
||||||
|
|
||||||
while ((move = pos_next_legal(pos, movelist, &tmp)) != MOVE_NONE)
|
while ((move = pos_next_legal(pos, pseudo, &tmp)) != MOVE_NONE)
|
||||||
dest->move[dest->nmoves++] = move;
|
legal->move[legal->nmoves++] = move;
|
||||||
return dest;
|
return legal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pos_legal() - get legal moves from pseudo-legal ones in new list.
|
||||||
|
* @pos: position
|
||||||
|
* @list: &movelist_t pseudo-legal moves list
|
||||||
|
*
|
||||||
|
* The pseudo-legal moves must be already calculated before calling this function.
|
||||||
|
* @list is replaced by legal moves.
|
||||||
|
*
|
||||||
|
* @return: @list
|
||||||
|
*/
|
||||||
|
movelist_t *pos_legal(const pos_t *pos, movelist_t *list)
|
||||||
|
{
|
||||||
|
move_t *cur = list->move, *last = list->move + list->nmoves;
|
||||||
|
|
||||||
|
while (cur < last) {
|
||||||
|
if (pseudo_is_legal(pos, *cur))
|
||||||
|
cur++;
|
||||||
|
else {
|
||||||
|
*cur = *--last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list->nmoves = last - list->move;
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -230,16 +258,40 @@ static inline __unused move_t *gen_pseudo_king(move_t *moves, square_t from,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* move_make_promotions() - generate all promotions for given pawn and dest.
|
* moves_gen_flags() - generate all moves from square to bitboard (with flags).
|
||||||
|
* @moves: &move_t array where to store moves
|
||||||
|
* @from: square_t piece position
|
||||||
|
* @to_bb: destination bitboard
|
||||||
|
* @flags: flags to apply
|
||||||
|
*
|
||||||
|
* Generate (at address @moves) moves from square @from to each square in @to_bb,
|
||||||
|
* with flags @flags.
|
||||||
|
*
|
||||||
|
* @Return: New @moves.
|
||||||
|
*/
|
||||||
|
static inline __unused move_t *moves_gen_flags(move_t *moves, square_t from, bitboard_t to_bb,
|
||||||
|
__unused move_flags_t flags)
|
||||||
|
{
|
||||||
|
square_t to;
|
||||||
|
while(to_bb) {
|
||||||
|
to = bb_next(&to_bb);
|
||||||
|
*moves++ = move_make_flags(from, to, flags);
|
||||||
|
}
|
||||||
|
return moves;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* move_gen_promotions() - generate all promotions for given pawn and dest.
|
||||||
* @moves: &move_t array where to store moves
|
* @moves: &move_t array where to store moves
|
||||||
* @from: pawn position
|
* @from: pawn position
|
||||||
* @to: promotion square
|
* @to: promotion square
|
||||||
*
|
*
|
||||||
* Generate all (Q/R/B/N) promotion moves on @to for pawn @from.
|
* Generate (at address @moves) all promotion (Q/R/B/N) moves on @to for
|
||||||
|
* pawn @from.
|
||||||
*
|
*
|
||||||
* @Return: New @moves (incremented by 4).
|
* @Return: New @moves.
|
||||||
*/
|
*/
|
||||||
static inline move_t *move_make_promotions(move_t *moves, square_t from, square_t to)
|
static inline move_t *move_gen_promotions(move_t *moves, square_t from, square_t to)
|
||||||
{
|
{
|
||||||
for (piece_type_t pt = QUEEN; pt >= KNIGHT; --pt)
|
for (piece_type_t pt = QUEEN; pt >= KNIGHT; --pt)
|
||||||
*moves++ = move_make_promote(from, to, pt);
|
*moves++ = move_make_promote(from, to, pt);
|
||||||
@@ -247,7 +299,28 @@ static inline move_t *move_make_promotions(move_t *moves, square_t from, square_
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pos_gen_pseudomoves() - generate position pseudo-legal moves
|
* moves_gen() - generate all moves from square to bitboard.
|
||||||
|
* @moves: &move_t array where to store moves
|
||||||
|
* @from: square_t piece position
|
||||||
|
* @to_bb: destination bitboard
|
||||||
|
*
|
||||||
|
* Generate (at address @moves) moves from square @from to each square in @to_bb.
|
||||||
|
*
|
||||||
|
* @Return: New @moves.
|
||||||
|
*/
|
||||||
|
static inline move_t *moves_gen(move_t *moves, square_t from, bitboard_t to_bb)
|
||||||
|
{
|
||||||
|
square_t to;
|
||||||
|
// bb_print(sq_to_string(from), to_bb);
|
||||||
|
while(to_bb) {
|
||||||
|
to = bb_next(&to_bb);
|
||||||
|
*moves++ = move_make(from, to);
|
||||||
|
}
|
||||||
|
return moves;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pos_gen_pseudo() - generate position pseudo-legal moves
|
||||||
* @pos: position
|
* @pos: position
|
||||||
* @movelist: &movelist_t array to store pseudo-moves
|
* @movelist: &movelist_t array to store pseudo-moves
|
||||||
*
|
*
|
||||||
@@ -267,9 +340,9 @@ static inline move_t *move_make_promotions(move_t *moves, square_t from, square_
|
|||||||
*
|
*
|
||||||
* TODO: move code to specific functions (especially castling, pawn push/capture)
|
* TODO: move code to specific functions (especially castling, pawn push/capture)
|
||||||
*
|
*
|
||||||
* @Return: The total number of moves.
|
* @Return: movelist
|
||||||
*/
|
*/
|
||||||
int pos_gen_pseudomoves(pos_t *pos, movelist_t *movelist)
|
movelist_t *pos_gen_pseudo(pos_t *pos, movelist_t *movelist)
|
||||||
{
|
{
|
||||||
color_t us = pos->turn;
|
color_t us = pos->turn;
|
||||||
color_t them = OPPONENT(us);
|
color_t them = OPPONENT(us);
|
||||||
@@ -289,12 +362,13 @@ int pos_gen_pseudomoves(pos_t *pos, movelist_t *movelist)
|
|||||||
|
|
||||||
//*nmoves = 0;
|
//*nmoves = 0;
|
||||||
|
|
||||||
/* king - MUST BE FIRST (we stop if doubler check) */
|
/* king - MUST BE FIRST */
|
||||||
to_bb = bb_king_moves(dest_squares, king);
|
to_bb = bb_king_moves(dest_squares, king);
|
||||||
while(to_bb) {
|
moves = moves_gen(moves, king, to_bb);
|
||||||
to = bb_next(&to_bb);
|
//while(to_bb) {
|
||||||
*moves++ = move_make(king, to);
|
// to = bb_next(&to_bb);
|
||||||
}
|
// *moves++ = move_make(king, to);
|
||||||
|
//}
|
||||||
|
|
||||||
if (bb_multiple(pos->checkers)) /* double check, we stop here */
|
if (bb_multiple(pos->checkers)) /* double check, we stop here */
|
||||||
goto finish;
|
goto finish;
|
||||||
@@ -334,19 +408,21 @@ int pos_gen_pseudomoves(pos_t *pos, movelist_t *movelist)
|
|||||||
while (from_bb) {
|
while (from_bb) {
|
||||||
from = bb_next(&from_bb);
|
from = bb_next(&from_bb);
|
||||||
to_bb = hyperbola_bishop_moves(occ, from) & dest_squares;
|
to_bb = hyperbola_bishop_moves(occ, from) & dest_squares;
|
||||||
while(to_bb) {
|
moves = moves_gen(moves, from, to_bb);
|
||||||
to = bb_next(&to_bb);
|
//while(to_bb) {
|
||||||
*moves++ = move_make(from, to);
|
// to = bb_next(&to_bb);
|
||||||
}
|
// *moves++ = move_make(from, to);
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
from_bb = pos->bb[us][ROOK] | pos->bb[us][QUEEN];
|
from_bb = pos->bb[us][ROOK] | pos->bb[us][QUEEN];
|
||||||
while (from_bb) {
|
while (from_bb) {
|
||||||
from = bb_next(&from_bb);
|
from = bb_next(&from_bb);
|
||||||
to_bb = hyperbola_rook_moves(occ, from) & dest_squares;
|
to_bb = hyperbola_rook_moves(occ, from) & dest_squares;
|
||||||
while(to_bb) {
|
moves = moves_gen(moves, from, to_bb);
|
||||||
to = bb_next(&to_bb);
|
//while(to_bb) {
|
||||||
*moves++ = move_make(from, to);
|
// to = bb_next(&to_bb);
|
||||||
}
|
// *moves++ = move_make(from, to);
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* knight */
|
/* knight */
|
||||||
@@ -354,10 +430,11 @@ int pos_gen_pseudomoves(pos_t *pos, movelist_t *movelist)
|
|||||||
while (from_bb) {
|
while (from_bb) {
|
||||||
from = bb_next(&from_bb);
|
from = bb_next(&from_bb);
|
||||||
to_bb = bb_knight_moves(dest_squares, from);
|
to_bb = bb_knight_moves(dest_squares, from);
|
||||||
while(to_bb) {
|
moves = moves_gen(moves, from, to_bb);
|
||||||
to = bb_next(&to_bb);
|
//while(to_bb) {
|
||||||
*moves++ = move_make(from, to);
|
// to = bb_next(&to_bb);
|
||||||
}
|
// *moves++ = move_make(from, to);
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pawn: relative rank and files */
|
/* pawn: relative rank and files */
|
||||||
@@ -374,11 +451,11 @@ int pos_gen_pseudomoves(pos_t *pos, movelist_t *movelist)
|
|||||||
from = to - shift;
|
from = to - shift;
|
||||||
*moves++ = move_make(from, to);
|
*moves++ = move_make(from, to);
|
||||||
}
|
}
|
||||||
to_bb = tmp_bb & rel_rank8 & dest_squares; /* promotions */
|
to_bb = tmp_bb & rel_rank8 & dest_squares; /* promotions */
|
||||||
while(to_bb) {
|
while(to_bb) {
|
||||||
to = bb_next(&to_bb);
|
to = bb_next(&to_bb);
|
||||||
from = to - shift;
|
from = to - shift;
|
||||||
moves = move_make_promotions(moves, from, to);
|
moves = move_gen_promotions(moves, from, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* possible second push */
|
/* possible second push */
|
||||||
@@ -428,7 +505,7 @@ int pos_gen_pseudomoves(pos_t *pos, movelist_t *movelist)
|
|||||||
while (to_bb) {
|
while (to_bb) {
|
||||||
to = bb_next(&to_bb);
|
to = bb_next(&to_bb);
|
||||||
from = to - shift;
|
from = to - shift;
|
||||||
moves = move_make_promotions(moves, from, to);
|
moves = move_gen_promotions(moves, from, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pawn: captures right */
|
/* pawn: captures right */
|
||||||
@@ -445,7 +522,7 @@ int pos_gen_pseudomoves(pos_t *pos, movelist_t *movelist)
|
|||||||
while (to_bb) {
|
while (to_bb) {
|
||||||
to = bb_next(&to_bb);
|
to = bb_next(&to_bb);
|
||||||
from = to - shift;
|
from = to - shift;
|
||||||
moves = move_make_promotions(moves, from, to);
|
moves = move_gen_promotions(moves, from, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pawn: en-passant
|
/* pawn: en-passant
|
||||||
@@ -458,23 +535,11 @@ int pos_gen_pseudomoves(pos_t *pos, movelist_t *movelist)
|
|||||||
*moves++ = move_make_enpassant(from, to);
|
*moves++ = move_make_enpassant(from, to);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* to_bb = mask(to);
|
|
||||||
* /\* if e.p not on file H, we may add an e.p move to "up-left" *\/
|
|
||||||
* filter = ~bb_rel_file(FILE_A, us);
|
|
||||||
* shift = sq_upleft(us);
|
|
||||||
* if (bb_shift(pos->bb[us][PAWN] & filter, shift) & to_bb)
|
|
||||||
* *moves++ = move_make_enpassant(to - shift, to);
|
|
||||||
*
|
|
||||||
* filter = ~bb_rel_file(FILE_H, us);
|
|
||||||
* shift = sq_upright(us);
|
|
||||||
* if (bb_shift(pos->bb[us][PAWN] & filter, shift) & to_bb)
|
|
||||||
* *moves++ = move_make_enpassant(to - shift, to);
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* TODO: add function per piece, and type, for easier debug
|
/* TODO: add function per piece, and type, for easier debug
|
||||||
*/
|
*/
|
||||||
finish:
|
finish:
|
||||||
return movelist->nmoves = moves - movelist->move;
|
movelist->nmoves = moves - movelist->move;
|
||||||
|
return movelist;
|
||||||
|
//return movelist->nmoves = moves - movelist->move;
|
||||||
}
|
}
|
||||||
|
@@ -23,7 +23,9 @@
|
|||||||
|
|
||||||
bool pseudo_is_legal(const pos_t *pos, const move_t move);
|
bool pseudo_is_legal(const pos_t *pos, const move_t move);
|
||||||
move_t pos_next_legal(const pos_t *pos, movelist_t *movelist, int *start);
|
move_t pos_next_legal(const pos_t *pos, movelist_t *movelist, int *start);
|
||||||
movelist_t *pos_all_legal(const pos_t *pos, movelist_t *movelist, movelist_t *dest);
|
movelist_t *pos_legal_dup(const pos_t *pos, movelist_t *pseudo, movelist_t *legal);
|
||||||
int pos_gen_pseudomoves(pos_t *pos, movelist_t *movelist);
|
movelist_t *pos_legal(const pos_t *pos, movelist_t *list);
|
||||||
|
|
||||||
|
movelist_t *pos_gen_pseudo(pos_t *pos, movelist_t *movelist);
|
||||||
|
|
||||||
#endif /* MOVEGEN_H */
|
#endif /* MOVEGEN_H */
|
||||||
|
@@ -101,7 +101,8 @@ static inline move_t move_make(square_t from, square_t to)
|
|||||||
|
|
||||||
static inline move_t move_make_flags(square_t from, square_t to, move_flags_t flags)
|
static inline move_t move_make_flags(square_t from, square_t to, move_flags_t flags)
|
||||||
{
|
{
|
||||||
return move_set_flags(move_make(from, to), flags);
|
return (to << M_OFF_TO) | from | flags;
|
||||||
|
//move_set_flags(move_make(from, to), flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline move_t move_make_capture(square_t from, square_t to)
|
static inline move_t move_make_capture(square_t from, square_t to)
|
||||||
|
@@ -18,8 +18,8 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "brlib.h"
|
#include <brlib.h>
|
||||||
#include "bitops.h"
|
#include <bitops.h>
|
||||||
|
|
||||||
#include "chessdefs.h"
|
#include "chessdefs.h"
|
||||||
#include "position.h"
|
#include "position.h"
|
||||||
@@ -65,6 +65,7 @@ pos_t *pos_dup(const pos_t *pos)
|
|||||||
/**
|
/**
|
||||||
* pos_del() - delete a position.
|
* pos_del() - delete a position.
|
||||||
* @pos: &position.
|
* @pos: &position.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
void pos_del(pos_t *pos)
|
void pos_del(pos_t *pos)
|
||||||
{
|
{
|
||||||
@@ -120,50 +121,29 @@ bool pos_cmp(__unused const pos_t *pos1, __unused const pos_t *pos2)
|
|||||||
{
|
{
|
||||||
#define _cmpf(a) (pos1->a != pos2->a)
|
#define _cmpf(a) (pos1->a != pos2->a)
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
if (warn_on(_cmpf(node_count)))
|
|
||||||
goto end;
|
if (_cmpf(node_count) || _cmpf(turn))
|
||||||
if (warn_on(_cmpf(turn)))
|
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
/* move_do/undo position state */
|
/* move_do/undo position state */
|
||||||
if (warn_on(_cmpf(en_passant)))
|
if (_cmpf(en_passant) || _cmpf(castle) ||
|
||||||
|
_cmpf(clock_50) || _cmpf(plycount))
|
||||||
goto end;
|
goto end;
|
||||||
if (warn_on(_cmpf(castle)))
|
|
||||||
goto end;
|
|
||||||
if (warn_on(_cmpf(clock_50)))
|
|
||||||
goto end;
|
|
||||||
if (warn_on(_cmpf(plycount)))
|
|
||||||
goto end;
|
|
||||||
//if (warn_on(_cmpf(captured)))
|
|
||||||
// goto end;
|
|
||||||
|
|
||||||
for (square_t sq = A1; sq <= H8; ++sq)
|
for (square_t sq = A1; sq <= H8; ++sq)
|
||||||
if (warn_on(_cmpf(board[sq])))
|
if (_cmpf(board[sq]))
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
for (color_t color = WHITE; color <= BLACK; ++color) {
|
for (color_t color = WHITE; color <= BLACK; ++color) {
|
||||||
for (piece_type_t piece = 0; piece <= KING; ++piece)
|
for (piece_type_t piece = 0; piece <= KING; ++piece)
|
||||||
if (warn_on(_cmpf(bb[color][piece])))
|
if (_cmpf(bb[color][piece]))
|
||||||
goto end;
|
goto end;
|
||||||
//pos->controlled[color] = 0;
|
if (_cmpf(king[color]))
|
||||||
if (warn_on(_cmpf(king[color])))
|
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (warn_on(_cmpf(checkers)))
|
if (_cmpf(checkers) ||_cmpf(pinners) || _cmpf(blockers))
|
||||||
goto end;
|
goto end;
|
||||||
if (warn_on(_cmpf(pinners)))
|
|
||||||
goto end;
|
|
||||||
if (warn_on(_cmpf(blockers)))
|
|
||||||
goto end;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* if (warn_on(_cmpf(moves.nmoves)))
|
|
||||||
* goto end;
|
|
||||||
* for (int i = 0; i < pos1->moves.nmoves; ++i)
|
|
||||||
* if (warn_on(_cmpf(moves.move[i])))
|
|
||||||
* goto end;
|
|
||||||
*/
|
|
||||||
|
|
||||||
ret = true;
|
ret = true;
|
||||||
end:
|
end:
|
||||||
@@ -179,7 +159,7 @@ end:
|
|||||||
* Get a bitboard of all checkers on @color king.
|
* Get a bitboard of all checkers on @color king.
|
||||||
* Just a wrapper over @sq_attackers().
|
* Just a wrapper over @sq_attackers().
|
||||||
*
|
*
|
||||||
* @return: a bitboard of attackers.
|
* @return: a bitboard of checkers.
|
||||||
*/
|
*/
|
||||||
bitboard_t pos_checkers(const pos_t *pos, const color_t color)
|
bitboard_t pos_checkers(const pos_t *pos, const color_t color)
|
||||||
{
|
{
|
||||||
@@ -192,7 +172,7 @@ bitboard_t pos_checkers(const pos_t *pos, const color_t color)
|
|||||||
* @pos: &position
|
* @pos: &position
|
||||||
*
|
*
|
||||||
* Set position checkers, pinners and blockers on player-to-play king.
|
* Set position checkers, pinners and blockers on player-to-play king.
|
||||||
* It should be faster than @pos_checkers + @pos_set_pinners_blockers, as
|
* It should be slightly faster than @pos_checkers + @pos_set_pinners_blockers, as
|
||||||
* some calculation will be done once.
|
* some calculation will be done once.
|
||||||
*/
|
*/
|
||||||
void pos_set_checkers_pinners_blockers(pos_t *pos)
|
void pos_set_checkers_pinners_blockers(pos_t *pos)
|
||||||
@@ -336,11 +316,11 @@ bitboard_t pos_king_blockers(const pos_t *pos, const color_t color, const bitboa
|
|||||||
* - total number of pieces > 16 or zero (per color)
|
* - total number of pieces > 16 or zero (per color)
|
||||||
* - number of kings != 1 (per color)
|
* - number of kings != 1 (per color)
|
||||||
* - discrepancy between board and king (per color)
|
* - discrepancy between board and king (per color)
|
||||||
* - discrepancy between piece bitboards and ALL_PIECES bitboards (per color)
|
|
||||||
* - discrepancy between bitboards and board (per color)
|
* - discrepancy between bitboards and board (per color)
|
||||||
* - side-to-move already checking opponent king
|
* - side-to-move already checking opponent king
|
||||||
* - side-to-move in check more than twice
|
* - side-to-move in check more than twice
|
||||||
* - kings distance is 1
|
* - kings distance is 1
|
||||||
|
* - TODO: discrepancy between piece bitboards and ALL_PIECES bitboards (per color)
|
||||||
*
|
*
|
||||||
* In case of errors, and @strict is true, @bug_on() is called, and program will
|
* In case of errors, and @strict is true, @bug_on() is called, and program will
|
||||||
* be terminated.
|
* be terminated.
|
||||||
@@ -348,19 +328,23 @@ bitboard_t pos_king_blockers(const pos_t *pos, const color_t color, const bitboa
|
|||||||
* (eg after fen parsing), and with @strict == true otherwise (as we have some data
|
* (eg after fen parsing), and with @strict == true otherwise (as we have some data
|
||||||
* corruption).
|
* corruption).
|
||||||
*
|
*
|
||||||
* TODO: add more checks:
|
|
||||||
* - kings attacking each other
|
|
||||||
*
|
|
||||||
* @return: (if @strict is false) return true if check is ok, false otherwise.
|
* @return: (if @strict is false) return true if check is ok, false otherwise.
|
||||||
*/
|
*/
|
||||||
bool pos_ok(__unused const pos_t *pos, __unused const bool strict)
|
bool pos_ok(const pos_t *pos, const bool strict)
|
||||||
{
|
{
|
||||||
int n, count = 0, bbcount = 0, error = 0;
|
int n, count = 0, bbcount = 0, error = 0;
|
||||||
__unused bitboard_t tmp;
|
|
||||||
|
/* force BUG_ON and WARN_ON */
|
||||||
|
# pragma push_macro("BUG_ON")
|
||||||
|
# pragma push_macro("WARN_ON")
|
||||||
|
# undef BUG_ON
|
||||||
|
# define BUG_ON
|
||||||
|
# undef WARN_ON
|
||||||
|
# define WARN_ON
|
||||||
|
|
||||||
/* pawns on 1st ot 8th rank */
|
/* pawns on 1st ot 8th rank */
|
||||||
tmp = (pos->bb[WHITE][PAWN] | pos->bb[BLACK][PAWN]) & (RANK_1bb | RANK_8bb);
|
error += warn_on((pos->bb[WHITE][PAWN] | pos->bb[BLACK][PAWN]) &
|
||||||
error += warn_on(tmp);
|
(RANK_1bb | RANK_8bb));
|
||||||
|
|
||||||
for (color_t color = WHITE; color <= BLACK; ++color) {
|
for (color_t color = WHITE; color <= BLACK; ++color) {
|
||||||
/* pawn count */
|
/* pawn count */
|
||||||
@@ -378,7 +362,7 @@ bool pos_ok(__unused const pos_t *pos, __unused const bool strict)
|
|||||||
}
|
}
|
||||||
for (square_t sq = 0; sq < 64; ++sq) {
|
for (square_t sq = 0; sq < 64; ++sq) {
|
||||||
piece_t piece = pos->board[sq];
|
piece_t piece = pos->board[sq];
|
||||||
__unused bitboard_t match;
|
bitboard_t match;
|
||||||
if (piece == EMPTY)
|
if (piece == EMPTY)
|
||||||
continue;
|
continue;
|
||||||
color_t c = COLOR(piece);
|
color_t c = COLOR(piece);
|
||||||
@@ -387,17 +371,22 @@ bool pos_ok(__unused const pos_t *pos, __unused const bool strict)
|
|||||||
error += warn_on(!match);
|
error += warn_on(!match);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
/* occupied occupation is different from bitboards */
|
/* occupied board is different from bitboards */
|
||||||
error += warn_on(count != bbcount);
|
error += warn_on(count != bbcount);
|
||||||
/* is opponent already in check ? */
|
/* is opponent already in check ? */
|
||||||
error += warn_on(pos_checkers(pos, OPPONENT(pos->turn)));
|
error += warn_on(pos_checkers(pos, OPPONENT(pos->turn)));
|
||||||
/* is color to play in check more than twice ? */
|
/* is color to play in check more than twice ? */
|
||||||
error += warn_on(popcount64(pos_checkers(pos, OPPONENT(pos->turn))) > 2);
|
error += warn_on(popcount64(pos_checkers(pos, pos->turn)) > 2);
|
||||||
/* kings distance is less than 2 */
|
/* kings distance is less than 2 */
|
||||||
error += warn_on(sq_dist(pos->king[WHITE], pos->king[BLACK]) < 2);
|
error += warn_on(sq_dist(pos->king[WHITE], pos->king[BLACK]) < 2);
|
||||||
|
|
||||||
bug_on(strict && error);
|
if (strict) {
|
||||||
|
bug_on(error);
|
||||||
|
/* not reached */
|
||||||
|
}
|
||||||
return error? false: true;
|
return error? false: true;
|
||||||
|
# pragma pop_macro("WARN_ON")
|
||||||
|
# pragma pop_macro("BUG_ON")
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -32,7 +32,7 @@ typedef struct __pos_s {
|
|||||||
|
|
||||||
/* data which cannot be recovered by move_undo (like castle_rights, ...),
|
/* data which cannot be recovered by move_undo (like castle_rights, ...),
|
||||||
* or would be expensive to recover (checkers, ...)
|
* or would be expensive to recover (checkers, ...)
|
||||||
* following data can be accessed either directly, either via "movesave"
|
* following data can be accessed either directly, either via "state"
|
||||||
* structure name.
|
* structure name.
|
||||||
* For example, pos->en_passant and pos->state.en_passant are the same.
|
* For example, pos->en_passant and pos->state.en_passant are the same.
|
||||||
* This allows a memcpy on this data (to save/restore position state).
|
* This allows a memcpy on this data (to save/restore position state).
|
||||||
@@ -40,8 +40,8 @@ typedef struct __pos_s {
|
|||||||
struct_group_tagged(state_s, state,
|
struct_group_tagged(state_s, state,
|
||||||
square_t en_passant;
|
square_t en_passant;
|
||||||
castle_rights_t castle;
|
castle_rights_t castle;
|
||||||
u16 clock_50;
|
int clock_50;
|
||||||
u16 plycount; /* plies so far, start from 1 */
|
int plycount; /* plies so far, start from 1 */
|
||||||
piece_t captured; /* only for move_undo */
|
piece_t captured; /* only for move_undo */
|
||||||
bitboard_t checkers; /* opponent checkers */
|
bitboard_t checkers; /* opponent checkers */
|
||||||
bitboard_t pinners; /* opponent pinners */
|
bitboard_t pinners; /* opponent pinners */
|
||||||
|
113
src/search.c
113
src/search.c
@@ -33,8 +33,8 @@
|
|||||||
* This version uses the algorithm:
|
* This version uses the algorithm:
|
||||||
* if last depth
|
* if last depth
|
||||||
* return 1;
|
* return 1;
|
||||||
* gen pseudo-legal moves
|
* gen legal moves
|
||||||
* loop for each legal move
|
* loop for legal move
|
||||||
* do-move
|
* do-move
|
||||||
* perft (depth -1)
|
* perft (depth -1)
|
||||||
* undo-move
|
* undo-move
|
||||||
@@ -43,30 +43,32 @@
|
|||||||
*/
|
*/
|
||||||
u64 perft(pos_t *pos, int depth, int ply)
|
u64 perft(pos_t *pos, int depth, int ply)
|
||||||
{
|
{
|
||||||
int subnodes, movetmp = 0;
|
int subnodes;
|
||||||
u64 nodes = 0;
|
u64 nodes = 0;
|
||||||
movelist_t pseudo;
|
movelist_t movelist;
|
||||||
move_t move;
|
move_t *move, *last;
|
||||||
state_t state;
|
state_t state;
|
||||||
|
|
||||||
if (depth == 0)
|
movelist.nmoves = 0;
|
||||||
return 1;
|
pos_set_checkers_pinners_blockers(pos);
|
||||||
pseudo.nmoves = 0;
|
|
||||||
pos->checkers = pos_checkers(pos, pos->turn);
|
|
||||||
pos_set_pinners_blockers(pos);
|
|
||||||
state = pos->state;
|
state = pos->state;
|
||||||
|
|
||||||
pos_gen_pseudomoves(pos, &pseudo);
|
pos_legal(pos, pos_gen_pseudo(pos, &movelist));
|
||||||
while ((move = pos_next_legal(pos, &pseudo, &movetmp)) != MOVE_NONE) {
|
last = movelist.move + movelist.nmoves;
|
||||||
move_do(pos, move);
|
for (move = movelist.move; move < last; ++move) {
|
||||||
subnodes = perft(pos, depth - 1, ply + 1);
|
if (depth == 1) {
|
||||||
if (ply == 1) {
|
nodes++;
|
||||||
char movestr[8];
|
} else {
|
||||||
printf("%s: %d\n", move_str(movestr, move, 0), subnodes);
|
move_do(pos, *move);
|
||||||
|
subnodes = perft(pos, depth - 1, ply + 1);
|
||||||
|
if (ply == 1) {
|
||||||
|
char movestr[8];
|
||||||
|
printf("%s: %d\n", move_str(movestr, *move, 0), subnodes);
|
||||||
|
}
|
||||||
|
nodes += subnodes;
|
||||||
|
move_undo(pos, *move);
|
||||||
|
pos->state = state;
|
||||||
}
|
}
|
||||||
nodes += subnodes;
|
|
||||||
move_undo(pos, move);
|
|
||||||
pos->state = state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ply == 1)
|
if (ply == 1)
|
||||||
@@ -83,6 +85,15 @@ u64 perft(pos_t *pos, int depth, int ply)
|
|||||||
* Run perft on a position. This function displays the available moves at @depth
|
* Run perft on a position. This function displays the available moves at @depth
|
||||||
* level for each possible first move, and the total of moves.
|
* level for each possible first move, and the total of moves.
|
||||||
*
|
*
|
||||||
|
* This version uses the algorithm:
|
||||||
|
* if last depth
|
||||||
|
* return 1;
|
||||||
|
* gen pseudo-legal moves
|
||||||
|
* loop for each legal move in pseudo-legal list
|
||||||
|
* do-move
|
||||||
|
* perft (depth -1)
|
||||||
|
* undo-move
|
||||||
|
*
|
||||||
* @return: total moves found at @depth level.
|
* @return: total moves found at @depth level.
|
||||||
*/
|
*/
|
||||||
u64 perft_new_pinners(pos_t *pos, int depth, int ply)
|
u64 perft_new_pinners(pos_t *pos, int depth, int ply)
|
||||||
@@ -93,23 +104,25 @@ u64 perft_new_pinners(pos_t *pos, int depth, int ply)
|
|||||||
move_t move;
|
move_t move;
|
||||||
state_t state;
|
state_t state;
|
||||||
|
|
||||||
if (depth == 0)
|
|
||||||
return 1;
|
|
||||||
pseudo.nmoves = 0;
|
pseudo.nmoves = 0;
|
||||||
pos_set_checkers_pinners_blockers(pos);
|
pos_set_checkers_pinners_blockers(pos);
|
||||||
state = pos->state;
|
state = pos->state;
|
||||||
|
|
||||||
pos_gen_pseudomoves(pos, &pseudo);
|
pos_gen_pseudo(pos, &pseudo);
|
||||||
while ((move = pos_next_legal(pos, &pseudo, &movetmp)) != MOVE_NONE) {
|
while ((move = pos_next_legal(pos, &pseudo, &movetmp)) != MOVE_NONE) {
|
||||||
move_do(pos, move);
|
if (depth == 1) {
|
||||||
subnodes = perft_new_pinners(pos, depth - 1, ply + 1);
|
nodes++;
|
||||||
if (ply == 1) {
|
} else {
|
||||||
char movestr[8];
|
move_do(pos, move);
|
||||||
printf("%s: %d\n", move_str(movestr, move, 0), subnodes);
|
subnodes = perft_new_pinners(pos, depth - 1, ply + 1);
|
||||||
|
if (ply == 1) {
|
||||||
|
char movestr[8];
|
||||||
|
printf("%s: %d\n", move_str(movestr, move, 0), subnodes);
|
||||||
|
}
|
||||||
|
nodes += subnodes;
|
||||||
|
move_undo(pos, move);
|
||||||
|
pos->state = state;
|
||||||
}
|
}
|
||||||
nodes += subnodes;
|
|
||||||
move_undo(pos, move);
|
|
||||||
pos->state = state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ply == 1)
|
if (ply == 1)
|
||||||
@@ -315,24 +328,24 @@ u64 perft_new_pinners(pos_t *pos, int depth, int ply)
|
|||||||
* @return: The @pos negamax evaluation.
|
* @return: The @pos negamax evaluation.
|
||||||
*/
|
*/
|
||||||
/*int ab_negamax(pos_t *pos, int alpha, int beta, int depth)
|
/*int ab_negamax(pos_t *pos, int alpha, int beta, int depth)
|
||||||
{
|
{
|
||||||
move_t *move;
|
move_t *move;
|
||||||
pos_t *newpos;
|
pos_t *newpos;
|
||||||
eval_t best = EVAL_MIN, score;
|
eval_t best = EVAL_MIN, score;
|
||||||
|
|
||||||
if(depth == 0) {
|
if(depth == 0) {
|
||||||
//return quiesce( alpha, beta );
|
//return quiesce( alpha, beta );
|
||||||
moves_gen_all_nomoves(pos);
|
moves_gen_all_nomoves(pos);
|
||||||
score = eval(pos) * color;
|
score = eval(pos) * color;
|
||||||
return score;
|
return score;
|
||||||
}
|
}
|
||||||
for ( all moves) {
|
for ( all moves) {
|
||||||
score = -alphaBeta( -beta, -alpha, depthleft - 1 );
|
score = -alphaBeta( -beta, -alpha, depthleft - 1 );
|
||||||
if( score >= beta )
|
if( score >= beta )
|
||||||
return beta; // fail hard beta-cutoff
|
return beta; // fail hard beta-cutoff
|
||||||
if( score > alpha )
|
if( score > alpha )
|
||||||
alpha = score; // alpha acts like max in MiniMax
|
alpha = score; // alpha acts like max in MiniMax
|
||||||
}
|
}
|
||||||
return alpha;
|
return alpha;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
@@ -29,12 +29,11 @@ struct fentest {
|
|||||||
char *fen;
|
char *fen;
|
||||||
} fentest[] = {
|
} fentest[] = {
|
||||||
/*
|
/*
|
||||||
{ __LINE__.
|
{ __LINE__, 1,
|
||||||
ATTACK,
|
"",
|
||||||
"checkers: ",
|
|
||||||
""
|
""
|
||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* ***************** TEMP TESTS ABOVE ************************** */
|
/* ***************** TEMP TESTS ABOVE ************************** */
|
||||||
|
|
||||||
@@ -413,22 +412,22 @@ struct fentest {
|
|||||||
{ __LINE__, 0, NULL, NULL }
|
{ __LINE__, 0, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static int cur = -1;
|
static int fentest_cur = -1;
|
||||||
|
|
||||||
static char *next_fen(uint module)
|
static char *next_fen(uint module)
|
||||||
{
|
{
|
||||||
cur++;
|
fentest_cur++;
|
||||||
while (fentest[cur].fen && !(fentest[cur].modules & module))
|
while (fentest[fentest_cur].fen && !(fentest[fentest_cur].modules & module))
|
||||||
cur++;
|
fentest_cur++;
|
||||||
return fentest[cur].fen;
|
return fentest[fentest_cur].fen;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __unused char* cur_comment()
|
static __unused char* cur_comment()
|
||||||
{
|
{
|
||||||
return fentest[cur].comment;
|
return fentest[fentest_cur].comment;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __unused int cur_line()
|
static __unused int cur_line()
|
||||||
{
|
{
|
||||||
return fentest[cur].line;
|
return fentest[fentest_cur].line;
|
||||||
}
|
}
|
||||||
|
@@ -47,7 +47,7 @@ int main(int __unused ac, __unused char**av)
|
|||||||
pos->checkers = pos_checkers(pos, pos->turn);
|
pos->checkers = pos_checkers(pos, pos->turn);
|
||||||
pos_set_pinners_blockers(pos);
|
pos_set_pinners_blockers(pos);
|
||||||
|
|
||||||
pos_gen_pseudomoves(pos, &pseudo);
|
pos_gen_pseudo(pos, &pseudo);
|
||||||
savepos = pos_dup(pos);
|
savepos = pos_dup(pos);
|
||||||
|
|
||||||
state_t state = pos->state;
|
state_t state = pos->state;
|
||||||
|
@@ -216,7 +216,7 @@ int main(int __unused ac, __unused char**av)
|
|||||||
FILE *outfd;
|
FILE *outfd;
|
||||||
char *fen;
|
char *fen;
|
||||||
pos_t *pos, *fishpos = pos_new();
|
pos_t *pos, *fishpos = pos_new();
|
||||||
movelist_t pseudo, legal, fishmoves;
|
movelist_t pseudo, fishmoves;
|
||||||
//bitboard_t wrong = 0x5088000040, tmp, loop;
|
//bitboard_t wrong = 0x5088000040, tmp, loop;
|
||||||
//bit_for_each64(loop, tmp, )
|
//bit_for_each64(loop, tmp, )
|
||||||
//printf("fishpos 1=%p\n", fishpos);
|
//printf("fishpos 1=%p\n", fishpos);
|
||||||
@@ -239,9 +239,9 @@ int main(int __unused ac, __unused char**av)
|
|||||||
send_stockfish_fen(outfd, fishpos, &fishmoves, fen);
|
send_stockfish_fen(outfd, fishpos, &fishmoves, fen);
|
||||||
|
|
||||||
pos_set_checkers_pinners_blockers(pos);
|
pos_set_checkers_pinners_blockers(pos);
|
||||||
pos_gen_pseudomoves(pos, &pseudo);
|
pos_gen_pseudo(pos, &pseudo);
|
||||||
//moves_print(&pseudo, 0);
|
//moves_print(&pseudo, 0);
|
||||||
pos_all_legal(pos, &pseudo, &legal);
|
pos_legal(pos, &pseudo);
|
||||||
|
|
||||||
//moves_print(&legal, 0);
|
//moves_print(&legal, 0);
|
||||||
//printf("Fu ");
|
//printf("Fu ");
|
||||||
@@ -253,7 +253,7 @@ int main(int __unused ac, __unused char**av)
|
|||||||
|
|
||||||
/* sort and print movelists */
|
/* sort and print movelists */
|
||||||
move_sort_by_sq(&fishmoves);
|
move_sort_by_sq(&fishmoves);
|
||||||
move_sort_by_sq(&legal);
|
move_sort_by_sq(&pseudo);
|
||||||
// printf("\nFs ");
|
// printf("\nFs ");
|
||||||
// moves_print(fishpos, 0);
|
// moves_print(fishpos, 0);
|
||||||
// fflush(stdout);
|
// fflush(stdout);
|
||||||
@@ -262,14 +262,14 @@ int main(int __unused ac, __unused char**av)
|
|||||||
// fflush(stdout);
|
// fflush(stdout);
|
||||||
|
|
||||||
/* compare movelists */
|
/* compare movelists */
|
||||||
if (!movelists_equal(&fishmoves, &legal)) {
|
if (!movelists_equal(&fishmoves, &pseudo)) {
|
||||||
pos_print(pos);
|
pos_print(pos);
|
||||||
printf("F: ");
|
printf("F: ");
|
||||||
moves_print(&fishmoves, 0);
|
moves_print(&fishmoves, 0);
|
||||||
printf("M: ");
|
printf("M: ");
|
||||||
moves_print(&legal, 0);
|
moves_print(&pseudo, 0);
|
||||||
} else {
|
} else {
|
||||||
printf("[%s]: OK (%d Moves)\n", fen, legal.nmoves);
|
printf("[%s]: OK (%d Moves)\n", fen, pseudo.nmoves);
|
||||||
//moves_print(&fishpos->moves, 0);
|
//moves_print(&fishpos->moves, 0);
|
||||||
}
|
}
|
||||||
//compare_moves(&fishpos->moves, &legal);
|
//compare_moves(&fishpos->moves, &legal);
|
||||||
|
@@ -222,32 +222,55 @@ static __unused void compare_moves(movelist_t *fish, movelist_t *me)
|
|||||||
printf("F(%2d): %s\nM(%2d): %s\n", n1, str1, n2, str2);
|
printf("F(%2d): %s\nM(%2d): %s\n", n1, str1, n2, str2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int usage(char *prg)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: %s [-d depth] [-p pertf-modules] -n\n", prg);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int __unused ac, __unused char**av)
|
int main(int __unused ac, __unused char**av)
|
||||||
{
|
{
|
||||||
int i = 0, test_line;
|
int i = 0, test_line;
|
||||||
u64 sf_count, my_count;
|
u64 sf_count = 0, my_count;
|
||||||
char *fen;
|
char *fen;
|
||||||
pos_t *pos, *savepos, *fishpos = pos_new();
|
pos_t *pos, *savepos, *fishpos = pos_new();
|
||||||
movelist_t fishmoves;
|
movelist_t fishmoves;
|
||||||
//move_t move;
|
//move_t move;
|
||||||
FILE *outfd;
|
FILE *outfd = NULL;
|
||||||
s64 ms1 = 0, ms1_total = 0;
|
s64 ms1 = 0, ms1_total = 0;
|
||||||
s64 ms2 = 0, ms2_total = 0;
|
s64 ms2 = 0, ms2_total = 0;
|
||||||
|
|
||||||
int depth = 6, run = 3;
|
int opt, depth = 6, run = 3;
|
||||||
|
bool sf_run = true;
|
||||||
|
|
||||||
if (ac > 1)
|
while ((opt = getopt(ac, av, "nd:p:")) != -1) {
|
||||||
depth = atoi(av[1]);
|
switch (opt) {
|
||||||
if (ac > 2)
|
case 'd':
|
||||||
run = atoi(av[2]) & 3;
|
depth = atoi(optarg);
|
||||||
printf("depth = %d run=%d\n", depth, run);
|
break;
|
||||||
|
case 'p': /* 1 or 2 */
|
||||||
|
run = atoi(optarg);
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
sf_run = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return usage(*av);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//if (ac > 1)
|
||||||
|
// depth = atoi(av[1]);
|
||||||
|
//if (ac > 2)
|
||||||
|
// run = atoi(av[2]) & 3;
|
||||||
|
printf("depth = %d run = %x sf = %s\n", depth, run, sf_run? "true": "false");
|
||||||
|
|
||||||
if (!run)
|
if (!run)
|
||||||
exit(0);
|
exit(0);
|
||||||
setlocale(LC_NUMERIC, "");
|
setlocale(LC_NUMERIC, "");
|
||||||
setlinebuf(stdout); /* line-buffered stdout */
|
setlinebuf(stdout); /* line-buffered stdout */
|
||||||
outfd = open_stockfish();
|
|
||||||
|
if (sf_run)
|
||||||
|
outfd = open_stockfish();
|
||||||
|
|
||||||
bitboard_init();
|
bitboard_init();
|
||||||
hyperbola_init();
|
hyperbola_init();
|
||||||
@@ -259,7 +282,9 @@ int main(int __unused ac, __unused char**av)
|
|||||||
printf("wrong fen %d: [%s]\n", i, fen);
|
printf("wrong fen %d: [%s]\n", i, fen);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sf_count = send_stockfish_fen(outfd, fishpos, &fishmoves, fen, depth);
|
if (sf_run)
|
||||||
|
sf_count = send_stockfish_fen(outfd, fishpos, &fishmoves, fen, depth);
|
||||||
|
|
||||||
savepos = pos_dup(pos);
|
savepos = pos_dup(pos);
|
||||||
|
|
||||||
if (run & 1) {
|
if (run & 1) {
|
||||||
@@ -268,7 +293,7 @@ int main(int __unused ac, __unused char**av)
|
|||||||
ms1 = clock_elapsed_ms(&clock);
|
ms1 = clock_elapsed_ms(&clock);
|
||||||
ms1_total += ms1;
|
ms1_total += ms1;
|
||||||
|
|
||||||
if (sf_count == my_count) {
|
if (!sf_run || sf_count == my_count) {
|
||||||
printf("pt1 OK : line=%3d perft=%'lu %'ldms lps=%'lu \"%s\"\n",
|
printf("pt1 OK : line=%3d perft=%'lu %'ldms lps=%'lu \"%s\"\n",
|
||||||
test_line, my_count, ms1,
|
test_line, my_count, ms1,
|
||||||
ms1? my_count*1000l/ms1: 0,
|
ms1? my_count*1000l/ms1: 0,
|
||||||
@@ -285,7 +310,7 @@ int main(int __unused ac, __unused char**av)
|
|||||||
ms2 = clock_elapsed_ms(&clock);
|
ms2 = clock_elapsed_ms(&clock);
|
||||||
ms2_total += ms2;
|
ms2_total += ms2;
|
||||||
|
|
||||||
if (sf_count == my_count) {
|
if (!sf_run || sf_count == my_count) {
|
||||||
printf("pt2 OK : line=%3d perft=%'lu %'ldms lps=%'lu \"%s\"\n",
|
printf("pt2 OK : line=%3d perft=%'lu %'ldms lps=%'lu \"%s\"\n",
|
||||||
test_line, my_count, ms2,
|
test_line, my_count, ms2,
|
||||||
ms2? my_count*1000l/ms2: 0,
|
ms2? my_count*1000l/ms2: 0,
|
||||||
|
Reference in New Issue
Block a user