Compare commits
9 Commits
perft
...
afecbeb955
Author | SHA1 | Date | |
---|---|---|---|
afecbeb955 | |||
05748e19ab | |||
4816b4a53a | |||
96744cea20 | |||
24207583d1 | |||
92d6909546 | |||
85ae4a2230 | |||
ad8a9609ce | |||
ad704c216b |
15
Makefile
15
Makefile
@@ -89,10 +89,10 @@ CFLAGS := -std=gnu11
|
||||
|
||||
### dev OR release
|
||||
# dev
|
||||
CFLAGS += -O1
|
||||
#CFLAGS += -O1
|
||||
#CFLAGS += -g
|
||||
# release
|
||||
#CFLAGS += -Ofast
|
||||
CFLAGS += -Ofast
|
||||
|
||||
CFLAGS += -march=native
|
||||
CFLAGS += -flto
|
||||
@@ -100,7 +100,7 @@ CFLAGS += -Wall
|
||||
CFLAGS += -Wextra
|
||||
CFLAGS += -Wmissing-declarations
|
||||
# for gprof
|
||||
CFLAGS += -pg
|
||||
#CFLAGS += -pg
|
||||
# Next one may be useful for valgrind (when invalid instructions)
|
||||
# CFLAGS += -mno-tbm
|
||||
|
||||
@@ -114,7 +114,8 @@ CFLAGS := $(strip $(CFLAGS))
|
||||
#REL_CFLAGS := -Ofast
|
||||
|
||||
##################################### linker flags
|
||||
LDFLAGS := -L$(BRLIBDIR)
|
||||
LDFLAGS := --static
|
||||
LDFLAGS += -L$(BRLIBDIR)
|
||||
LDFLAGS += -flto
|
||||
|
||||
LDFLAGS := $(strip $(LDFLAGS))
|
||||
@@ -256,11 +257,11 @@ cleanasmcpp:
|
||||
@$(call rmfiles,$(ASMFILES) $(CPPFILES),asm and pre-processed)
|
||||
|
||||
%.i: %.c
|
||||
@echo generating $@ (cpp processed).
|
||||
@echo "generating $@ (cpp processed)."
|
||||
@$(CC) -E $(CPPFLAGS) $(CFLAGS) $< -o $@
|
||||
|
||||
%.s: %.c
|
||||
@echo generating $@ (asm).
|
||||
@echo "generating $@ (asm)."
|
||||
@$(CC) -S -fverbose-asm $(CPPFLAGS) $(CFLAGS) $< -o $@
|
||||
|
||||
##################################### LSP (ccls)
|
||||
@@ -309,7 +310,7 @@ BB_OBJS := $(FEN_OBJS)
|
||||
MOVEGEN_OBJS := $(BB_OBJS) move.o move-gen.o
|
||||
ATTACK_OBJS := $(MOVEGEN_OBJS)
|
||||
MOVEDO_OBJS := $(ATTACK_OBJS) move-do.o
|
||||
PERFT_OBJS := $(MOVEDO_OBJS) search.o
|
||||
PERFT_OBJS := $(MOVEDO_OBJS) search.o misc.o
|
||||
|
||||
TEST := $(addprefix $(BINDIR)/,$(TEST))
|
||||
|
||||
|
@@ -134,5 +134,35 @@ typedef enum {
|
||||
NORTH_WEST = (NORTH + WEST),
|
||||
} dir_t;
|
||||
|
||||
#include <time.h>
|
||||
|
||||
typedef struct mclock {
|
||||
clockid_t clocktype;
|
||||
ulong elapsed_l;
|
||||
double elapsed_f;
|
||||
struct timespec start;
|
||||
} mclock_t;
|
||||
|
||||
#define CLOCK_WALL CLOCK_REALTIME
|
||||
#define CLOCK_SYSTEM CLOCK_MONOTONIC_RAW
|
||||
#define CLOCK_PROCESS CLOCK_PROCESS_CPUTIME_ID
|
||||
#define CLOCK_THREAD CLOCK_THREAD_CPUTIME_ID
|
||||
|
||||
/**
|
||||
* CLOCK_DEFINE - define a clock type.
|
||||
* @name: clock name
|
||||
* @type: clock type
|
||||
*
|
||||
* This macro is equivalent to:
|
||||
* mclock_t name;
|
||||
* clock_init(&name, type);
|
||||
*/
|
||||
#define CLOCK_DEFINE(name, type) struct mclock name = { .clocktype = type }
|
||||
|
||||
void clock_init(mclock_t *clock, clockid_t type);
|
||||
void clock_start(mclock_t *clock);
|
||||
s64 clock_elapsed_μs(mclock_t *clock);
|
||||
s64 clock_elapsed_ms(mclock_t *clock);
|
||||
double clock_elapsed_sec(mclock_t *clock);
|
||||
|
||||
#endif /* _CHESSDEFS_H */
|
||||
|
112
src/misc.c
Normal file
112
src/misc.c
Normal file
@@ -0,0 +1,112 @@
|
||||
/* misc.c - generic/catchall functions.
|
||||
*
|
||||
* Copyright (C) 2024 Bruno Raoult ("br")
|
||||
* Licensed under the GNU General Public License v3.0 or later.
|
||||
* Some rights reserved. See COPYING.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this
|
||||
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "chessdefs.h"
|
||||
|
||||
/*
|
||||
* 1 sec = 1000 millisec
|
||||
* 1 millisec = 1000 microsec
|
||||
* 1 microsec = 1000 nanosec
|
||||
* milli = sec * 1000 + nanosec / 1000000
|
||||
*
|
||||
*/
|
||||
|
||||
/* We use microsec for all intermediate calcluation */
|
||||
#define NANO_IN_MICRO 1000ll /* nanosecond in millisecond */
|
||||
#define MICRO_IN_SEC 1000000ll /* millisecond in second */
|
||||
|
||||
#define MILLI_IN_SEC 1000ll /* millisecond in second */
|
||||
|
||||
#define MICRO_IN_MILLI 1000ll
|
||||
|
||||
//#define NANO_IN_MILLI 1000000ll /* nanosecond in millisecond */
|
||||
//#define NANO_IN_SEC (NANOS_IN_MS * MS_IN_SEC)
|
||||
|
||||
|
||||
/**
|
||||
* clock_start - start or restart a clock.
|
||||
* @clock: &mclock_t clock
|
||||
*
|
||||
* Save current time according to @clock type.
|
||||
*/
|
||||
void clock_start(mclock_t *clock)
|
||||
{
|
||||
clock_gettime(clock->clocktype, &clock->start);
|
||||
}
|
||||
|
||||
/**
|
||||
* clock_init - initializes a clock type.
|
||||
* @clock: &mclock_t clock
|
||||
* @type: clock type
|
||||
*
|
||||
* See the clock_gettime(2) for details.
|
||||
* CLOCK_WALL (a.k.a CLOCK_REALTIME): Wall clock.
|
||||
* CLOCK_SYSTEM (a.k.a CLOCK_MONOTONIC_RAW): System clock.
|
||||
* CLOCK_PROCESS (a.k.a CLOCK_PROCESS_CPUTIME_ID): Process CPU clock (incl. threads).
|
||||
* CLOCK_THREAD (a.k.a CLOCK_THREAD_CPUTIME_ID): Thread CPU clock.
|
||||
*/
|
||||
void clock_init(mclock_t *clock, clockid_t type)
|
||||
{
|
||||
clock->clocktype = type;
|
||||
clock_start(clock);
|
||||
}
|
||||
|
||||
/**
|
||||
* clock_elapsed_μs - return a mclock_t elapsed time in microseconds.
|
||||
* @clock: &mclock_t clock
|
||||
*
|
||||
* The elapsed time is calculated between current time and last clock_start(@clock)
|
||||
* call time.
|
||||
*
|
||||
* @return: microseconds elapsed since last clock_start().
|
||||
*/
|
||||
s64 clock_elapsed_μs(mclock_t *clock)
|
||||
{
|
||||
struct timespec current;
|
||||
s64 μs;
|
||||
|
||||
clock_gettime(clock->clocktype, ¤t);
|
||||
μs = ((s64)current.tv_sec - (s64)clock->start.tv_sec) * MICRO_IN_SEC +
|
||||
((s64)current.tv_nsec - (s64)clock->start.tv_nsec) / NANO_IN_MICRO ;
|
||||
return μs;
|
||||
}
|
||||
|
||||
/**
|
||||
* clock_elapsed_ms - return a mclock_t elapsed time in milliseconds.
|
||||
* @clock: &mclock_t clock
|
||||
*
|
||||
* The elapsed time is calculated between current time and last clock_start(@clock)
|
||||
* call time.
|
||||
*
|
||||
* @return: milliseconds elapsed since last clock_start().
|
||||
*/
|
||||
s64 clock_elapsed_ms(mclock_t *clock)
|
||||
{
|
||||
return clock_elapsed_μs(clock) / MICRO_IN_MILLI;
|
||||
}
|
||||
|
||||
/**
|
||||
* clock_elapsed_sec - return a mclock_t elapsed time in seconds.
|
||||
* @clock: &mclock_t clock
|
||||
*
|
||||
* The elapsed time is calculated between current time and last clock_start(@clock)
|
||||
* call time.
|
||||
*
|
||||
* @return: seconds elapsed since last clock_start().
|
||||
*/
|
||||
double clock_elapsed_sec(mclock_t *clock)
|
||||
{
|
||||
return (double) clock_elapsed_μs(clock) / (double) MICRO_IN_SEC;
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
/* move-do.h - move do/undo.
|
||||
*
|
||||
* Copyright (C) 2021 Bruno Raoult ("br")
|
||||
* Copyright (C) 2021-2024 Bruno Raoult ("br")
|
||||
* Licensed under the GNU General Public License v3.0 or later.
|
||||
* Some rights reserved. See COPYING.
|
||||
*
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* move.c - move management.
|
||||
*
|
||||
* Copyright (C) 2021 Bruno Raoult ("br")
|
||||
* Copyright (C) 2021-2024 Bruno Raoult ("br")
|
||||
* Licensed under the GNU General Public License v3.0 or later.
|
||||
* Some rights reserved. See COPYING.
|
||||
*
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* move.h - move management.
|
||||
*
|
||||
* Copyright (C) 2021 Bruno Raoult ("br")
|
||||
* Copyright (C) 2021-2024 Bruno Raoult ("br")
|
||||
* Licensed under the GNU General Public License v3.0 or later.
|
||||
* Some rights reserved. See COPYING.
|
||||
*
|
||||
|
@@ -24,6 +24,7 @@
|
||||
#include "chessdefs.h"
|
||||
#include "position.h"
|
||||
#include "bitboard.h"
|
||||
#include "hyperbola-quintessence.h"
|
||||
#include "fen.h"
|
||||
#include "piece.h"
|
||||
#include "util.h"
|
||||
@@ -194,17 +195,83 @@ bitboard_t pos_checkers(const pos_t *pos, const color_t color)
|
||||
* It should be faster than @pos_checkers + @pos_set_pinners_blockers, as
|
||||
* some calculation will be done once.
|
||||
*/
|
||||
/*
|
||||
* void pos_set_checkers_pinners_blockers(pos_t *pos)
|
||||
* {
|
||||
* bitboard_t b_bb = pos->bb[WHITE][BISHOP] | pos->bb[BLACK][BISHOP];
|
||||
* bitboard_t r_bb = pos->bb[WHITE][ROOK] | pos->bb[BLACK][ROOK];
|
||||
* bitboard_t q_bb = pos->bb[WHITE][QUEEN] | pos->bb[BLACK][QUEEN];
|
||||
*
|
||||
* /\* find out first piece on every diagonal *\/
|
||||
*
|
||||
* }
|
||||
*/
|
||||
void pos_set_checkers_pinners_blockers(pos_t *pos)
|
||||
{
|
||||
int us = pos->turn, them = OPPONENT(us);
|
||||
bitboard_t occ = pos_occ(pos);
|
||||
bitboard_t attackers;
|
||||
bitboard_t checkers = 0, blockers = 0, pinners = 0;
|
||||
bitboard_t targets, tmpcheckers, tmpblockers, tmppinners, tmpbb;
|
||||
square_t king = pos->king[us];
|
||||
bitboard_t king_bb = mask(king);
|
||||
int pinner;
|
||||
|
||||
/* bishop type - we attack with a bishop from king position */
|
||||
attackers = pos->bb[them][BISHOP] | pos->bb[them][QUEEN];
|
||||
|
||||
/* targets is all "target" pieces if K was a bishop */
|
||||
targets = hyperbola_bishop_moves(occ, king) & occ;
|
||||
|
||||
/* checkers = only opponent B/Q */
|
||||
tmpcheckers = targets & attackers;
|
||||
checkers |= tmpcheckers;
|
||||
|
||||
/* maybe blockers = not checkers */
|
||||
tmpblockers = targets & ~tmpcheckers;
|
||||
|
||||
/* we find second targets, by removing only first ones (excl. checkers) */
|
||||
targets = hyperbola_bishop_moves(occ ^ tmpblockers, king) ^ tmpcheckers;
|
||||
|
||||
/* pinners = only B/Q */
|
||||
tmppinners = targets & attackers;
|
||||
pinners |= tmppinners;
|
||||
//tmpblockers = 0;
|
||||
|
||||
/* blockers = we find occupied squares between pinner and king */
|
||||
bit_for_each64(pinner, tmpbb, tmppinners)
|
||||
blockers |= bb_between[pinner][king] & tmpblockers;
|
||||
//blockers |= tmpblockers;
|
||||
|
||||
/* same for rook type */
|
||||
attackers = pos->bb[them][ROOK] | pos->bb[them][QUEEN];
|
||||
|
||||
/* targets is all "target" pieces if K was a bishop */
|
||||
targets = hyperbola_rook_moves(occ, king) & occ;
|
||||
|
||||
/* checkers = only opponent B/Q */
|
||||
tmpcheckers = targets & attackers;
|
||||
checkers |= tmpcheckers;
|
||||
|
||||
/* maybe blockers = not checkers */
|
||||
tmpblockers = targets & ~tmpcheckers;
|
||||
|
||||
/* we find second targets, by removing only first ones (excl. checkers) */
|
||||
targets = hyperbola_rook_moves(occ ^ tmpblockers, king) ^ tmpcheckers;
|
||||
|
||||
/* pinners = only B/Q */
|
||||
tmppinners = targets & attackers;
|
||||
pinners |= tmppinners;
|
||||
//tmpblockers = 0;
|
||||
|
||||
/* blockers = we find occupied squares between pinner and king */
|
||||
bit_for_each64(pinner, tmpbb, tmppinners)
|
||||
blockers |= bb_between[pinner][king] & tmpblockers;
|
||||
//blockers |= tmpblockers;
|
||||
|
||||
/* pawns */
|
||||
attackers = pos->bb[them][PAWN];
|
||||
targets = pawn_shift_upleft(king_bb, us) | pawn_shift_upright(king_bb, us);
|
||||
checkers |= targets & attackers;
|
||||
|
||||
/* knight */
|
||||
attackers = pos->bb[them][KNIGHT];
|
||||
targets = bb_knight_moves(attackers, king);
|
||||
checkers |= targets;
|
||||
|
||||
pos->checkers = checkers;
|
||||
pos->pinners = pinners;
|
||||
pos->blockers = blockers;
|
||||
}
|
||||
|
||||
/**
|
||||
* pos_set_pinners_blockers() - set position pinners and blockers.
|
||||
|
@@ -159,7 +159,7 @@ void pos_del(pos_t *pos);
|
||||
pos_t *pos_clear(pos_t *pos);
|
||||
bool pos_cmp(const pos_t *pos1, const pos_t *pos2);
|
||||
|
||||
//bitboard_t set_king_pinners_blockers(pos_t *pos);
|
||||
void pos_set_checkers_pinners_blockers(pos_t *pos);
|
||||
void pos_set_pinners_blockers(pos_t *pos);
|
||||
bitboard_t pos_checkers(const pos_t *pos, const color_t color);
|
||||
bitboard_t pos_king_pinners(const pos_t *pos, const color_t color);
|
||||
|
90
src/search.c
90
src/search.c
@@ -21,19 +21,25 @@
|
||||
#include "search.h"
|
||||
#include "attack.h"
|
||||
|
||||
//#include "move.h"
|
||||
//#include "eval.h"
|
||||
|
||||
/**
|
||||
* perft() - Perform perft on position
|
||||
* @pos: &position to search
|
||||
* @depth: Wanted depth.
|
||||
* @ply: Depth level where perft is consolidated.
|
||||
* @ply: perft depth level.
|
||||
*
|
||||
* Print perftCalculate the negamax value of @pos. This is an extensive search, with
|
||||
* absolutely no cutoff.
|
||||
* Run perft on a position. This function displays the available moves at @depth
|
||||
* level for each possible first move, and the total of moves.
|
||||
*
|
||||
* @return: The @pos negamax evaluation.
|
||||
* This version uses the algorithm:
|
||||
* if last depth
|
||||
* return 1;
|
||||
* gen pseudo-legal moves
|
||||
* loop for each legal move
|
||||
* do-move
|
||||
* perft (depth -1)
|
||||
* undo-move
|
||||
*
|
||||
* @return: total moves found at @depth level.
|
||||
*/
|
||||
u64 perft(pos_t *pos, int depth, int ply)
|
||||
{
|
||||
@@ -63,10 +69,29 @@ u64 perft(pos_t *pos, int depth, int ply)
|
||||
}
|
||||
|
||||
if (ply == 1)
|
||||
printf("\nTotal: %lu\n", nodes);
|
||||
printf("Total: %lu\n", nodes);
|
||||
return nodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* perft2() - Perform perft on position
|
||||
* @pos: &position to search
|
||||
* @depth: Wanted depth.
|
||||
* @ply: perft depth level.
|
||||
*
|
||||
* Run perft on a position. This function displays the available moves at @depth
|
||||
* level for each possible first move, and the total of moves.
|
||||
*
|
||||
* This version uses the algorithm:
|
||||
* if (king in check)
|
||||
* finish;
|
||||
* if last depth
|
||||
* return 1;
|
||||
* gen pseudo-legal moves
|
||||
* foreach pseudo-legal move...
|
||||
*
|
||||
* @return: total moves found at @depth level.
|
||||
*/
|
||||
u64 perft2(pos_t *pos, int depth, int ply)
|
||||
{
|
||||
int subnodes, nmove = 0;
|
||||
@@ -75,8 +100,6 @@ u64 perft2(pos_t *pos, int depth, int ply)
|
||||
move_t move;
|
||||
state_t state;
|
||||
|
||||
if (is_in_check(pos, OPPONENT(pos->turn)))
|
||||
return 0;
|
||||
if (depth == 0)
|
||||
return 1;
|
||||
pos->checkers = pos_checkers(pos, pos->turn);
|
||||
@@ -88,19 +111,50 @@ u64 perft2(pos_t *pos, int depth, int ply)
|
||||
for (nmove = 0; nmove < pseudo.nmoves; ++nmove ) {
|
||||
move = pseudo.move[nmove];
|
||||
move_do(pos, move);
|
||||
//if (!is_in_check(pos, OPPONENT(pos->turn))) {
|
||||
subnodes = perft2(pos, depth - 1, ply + 1);
|
||||
nodes += subnodes;
|
||||
if (ply == 1) {
|
||||
char movestr[8];
|
||||
printf("%s: %d\n", move_str(movestr, move, 0), subnodes);
|
||||
if (!is_in_check(pos, OPPONENT(pos->turn))) {
|
||||
subnodes = perft2(pos, depth - 1, ply + 1);
|
||||
nodes += subnodes;
|
||||
if (ply == 1) {
|
||||
char movestr[8];
|
||||
printf("%s: %d\n", move_str(movestr, move, 0), subnodes);
|
||||
}
|
||||
}
|
||||
//}
|
||||
move_undo(pos, move);
|
||||
pos->state = state;
|
||||
}
|
||||
if (ply == 1)
|
||||
printf("\nTotal: %lu\n", nodes);
|
||||
printf("Total: %lu\n", nodes);
|
||||
return nodes;
|
||||
}
|
||||
|
||||
u64 perft_new_pinners(pos_t *pos, int depth, int ply)
|
||||
{
|
||||
int subnodes, movetmp = 0;
|
||||
u64 nodes = 0;
|
||||
movelist_t pseudo = { .nmoves = 0 };
|
||||
move_t move;
|
||||
state_t state;
|
||||
|
||||
if (depth == 0)
|
||||
return 1;
|
||||
pos_set_checkers_pinners_blockers(pos);
|
||||
state = pos->state;
|
||||
|
||||
pos_gen_pseudomoves(pos, &pseudo);
|
||||
while ((move = pos_next_legal(pos, &pseudo, &movetmp)) != MOVE_NONE) {
|
||||
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;
|
||||
}
|
||||
|
||||
if (ply == 1)
|
||||
printf("Total: %lu\n", nodes);
|
||||
return nodes;
|
||||
}
|
||||
|
||||
|
@@ -21,5 +21,6 @@
|
||||
|
||||
u64 perft(pos_t *pos, int depth, int ply);
|
||||
u64 perft2(pos_t *pos, int depth, int ply);
|
||||
u64 perft_new_pinners(pos_t *pos, int depth, int ply);
|
||||
|
||||
#endif /* SEARCH_H */
|
||||
|
@@ -28,6 +28,7 @@ int main(int __unused ac, __unused char**av)
|
||||
int i = 0;
|
||||
char *fen;
|
||||
pos_t *pos;//, *fishpos = pos_new();
|
||||
bitboard_t checkers, pinners, blockers;
|
||||
|
||||
setlinebuf(stdout); /* line-buffered stdout */
|
||||
|
||||
@@ -41,8 +42,22 @@ int main(int __unused ac, __unused char**av)
|
||||
printf("wrong fen %d: [%s]\n", i, fen);
|
||||
continue;
|
||||
}
|
||||
pos->checkers = pos_checkers(pos, pos->turn);
|
||||
pos_set_pinners_blockers(pos);
|
||||
|
||||
pos_print(pos);
|
||||
|
||||
checkers = pos->checkers;
|
||||
pinners = pos->pinners;
|
||||
blockers = pos->blockers;
|
||||
|
||||
pos_set_checkers_pinners_blockers(pos);
|
||||
|
||||
printf("******* %s\n", cur_comment());
|
||||
bb_print_multi("checkers", 2, checkers, pos->checkers);
|
||||
bb_print_multi("pinners", 2, pinners, pos->pinners);
|
||||
bb_print_multi("blockers", 2, blockers, pos->blockers);
|
||||
|
||||
pos_del(pos);
|
||||
i++;
|
||||
}
|
||||
|
@@ -237,6 +237,8 @@ int main(int __unused ac, __unused char**av)
|
||||
}
|
||||
/* print movelists */
|
||||
send_stockfish_fen(outfd, fishpos, &fishmoves, fen);
|
||||
|
||||
pos_set_checkers_pinners_blockers(pos);
|
||||
pos_gen_pseudomoves(pos, &pseudo);
|
||||
//moves_print(&pseudo, 0);
|
||||
pos_all_legal(pos, &pseudo, &legal);
|
||||
|
@@ -233,11 +233,19 @@ int main(int __unused ac, __unused char**av)
|
||||
//move_t move;
|
||||
FILE *outfd;
|
||||
int depth = 6;
|
||||
s64 ms1 = 0, ms1_total = 0;
|
||||
s64 ms2 = 0, ms2_total = 0;
|
||||
s64 ms3 = 0, ms3_total = 0;
|
||||
int run = 3;
|
||||
|
||||
if (ac > 1)
|
||||
depth = atoi(av[1]);
|
||||
printf("depth = %d\n", depth);
|
||||
if (ac > 2)
|
||||
run = atoi(av[2]);
|
||||
printf("depth = %d run=%d\n", depth, run);
|
||||
|
||||
if (!run)
|
||||
exit(0);
|
||||
setlocale(LC_NUMERIC, "");
|
||||
setlinebuf(stdout); /* line-buffered stdout */
|
||||
outfd = open_stockfish();
|
||||
@@ -245,6 +253,8 @@ int main(int __unused ac, __unused char**av)
|
||||
bitboard_init();
|
||||
hyperbola_init();
|
||||
|
||||
|
||||
CLOCK_DEFINE(clock, CLOCK_PROCESS);
|
||||
while ((fen = next_fen(PERFT | MOVEDO))) {
|
||||
test_line = cur_line();
|
||||
if (!(pos = fen2pos(NULL, fen))) {
|
||||
@@ -256,48 +266,66 @@ int main(int __unused ac, __unused char**av)
|
||||
savepos = pos_dup(pos);
|
||||
//int j = 0;
|
||||
|
||||
#define NANOSEC 1000000000 /* nano sec in sec */
|
||||
#define MILLISEC 1000000 /* milli sec in sec */
|
||||
if (run & 1) {
|
||||
clock_start(&clock);
|
||||
my_count = perft(pos, depth, 1);
|
||||
ms1 = clock_elapsed_ms(&clock);
|
||||
ms1_total += ms1;
|
||||
|
||||
// 1 sec = 1000 millisec
|
||||
// 1 millisec = 1000 microsec
|
||||
// 1 microsec = 1000 nanosec
|
||||
// milli = sec * 1000 + nanosec / 1000000
|
||||
struct timespec ts1, ts2;
|
||||
s64 microsecs;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &ts1);
|
||||
my_count = perft(pos, depth, 1);
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &ts2);
|
||||
|
||||
microsecs = ((s64)ts2.tv_sec - (s64)ts1.tv_sec) * 1000000l
|
||||
+ ((s64)ts2.tv_nsec - (s64)ts1.tv_nsec) / 1000l ;
|
||||
if (sf_count == my_count) {
|
||||
printf("pt1 OK : line=%03d perft=%lu ms=%'ldms lps=%'lu \"%s\"\n",
|
||||
test_line, my_count, microsecs/1000l,
|
||||
my_count*1000000l/microsecs, fen);
|
||||
} else {
|
||||
printf("pt1 ERR: line=%03d sf=%lu me=%lu \"%s\"\n",
|
||||
test_line, sf_count, my_count, fen);
|
||||
if (sf_count == my_count) {
|
||||
printf("pt1 OK : line=%03d perft=%lu %'ldms lps=%'lu \"%s\"\n",
|
||||
test_line, my_count, ms1,
|
||||
ms1? my_count*1000l/ms1: 0,
|
||||
fen);
|
||||
} else {
|
||||
printf("pt1 ERR: line=%03d sf=%lu me=%lu \"%s\"\n",
|
||||
test_line, sf_count, my_count, fen);
|
||||
}
|
||||
}
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &ts1);
|
||||
my_count = perft2(pos, depth, 1);
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &ts2);
|
||||
if (run & 2) {
|
||||
clock_start(&clock);
|
||||
my_count = perft2(pos, depth, 1);
|
||||
ms2 = clock_elapsed_ms(&clock);
|
||||
ms2_total += ms2;
|
||||
|
||||
microsecs = ((s64)ts2.tv_sec - (s64)ts1.tv_sec) * 1000000l
|
||||
+ ((s64)ts2.tv_nsec - (s64)ts1.tv_nsec) / 1000l ;
|
||||
if (sf_count == my_count) {
|
||||
printf("pt2 OK : line=%03d perft=%lu ms=%'ldms lps=%'lu \"%s\"\n\n",
|
||||
test_line, my_count, microsecs/1000l,
|
||||
my_count*1000000l/microsecs, fen);
|
||||
} else {
|
||||
printf("pt2 ERR: line=%03d sf=%lu me=%lu \"%s\"\n\n",
|
||||
test_line, sf_count, my_count, fen);
|
||||
if (sf_count == my_count) {
|
||||
printf("pt2 OK : line=%03d perft=%lu %'ldms lps=%'lu \"%s\"\n",
|
||||
test_line, my_count, ms2,
|
||||
ms2? my_count*1000l/ms2: 0,
|
||||
fen);
|
||||
} else {
|
||||
printf("pt2 ERR: line=%03d sf=%lu me=%lu \"%s\"\n",
|
||||
test_line, sf_count, my_count, fen);
|
||||
}
|
||||
}
|
||||
|
||||
if (run & 4) {
|
||||
clock_start(&clock);
|
||||
my_count = perft_new_pinners(pos, depth, 1);
|
||||
ms3 = clock_elapsed_ms(&clock);
|
||||
ms3_total += ms3;
|
||||
|
||||
if (sf_count == my_count) {
|
||||
printf("pt3 OK : line=%3d perft=%lu %'ldms lps=%'lu \"%s\"\n",
|
||||
test_line, my_count, ms3,
|
||||
ms3? my_count*1000l/ms3: 0,
|
||||
fen);
|
||||
} else {
|
||||
printf("pt3 ERR: line=%3d sf=%lu me=%lu \"%s\"\n",
|
||||
test_line, sf_count, my_count, fen);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
pos_del(savepos);
|
||||
pos_del(pos);
|
||||
i++;
|
||||
}
|
||||
if (run & 1)
|
||||
printf("total perft %'ldms\n", ms1_total);
|
||||
if (run & 2)
|
||||
printf("total perft2 %'ldms\n", ms2_total);
|
||||
if (run & 4)
|
||||
printf("total perft3 %'ldms\n", ms3_total);
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user