Compare commits
8 Commits
6e38de58cb
...
f4280dfa13
Author | SHA1 | Date | |
---|---|---|---|
f4280dfa13 | |||
d1cc7a8066 | |||
cfa8b42077 | |||
0c2d30c938 | |||
3a6c1d11c0 | |||
a7311a546f | |||
84b6c41107 | |||
19d10fdfa8 |
32
Makefile
32
Makefile
@@ -19,7 +19,7 @@ ifeq ($(CC),cc)
|
||||
CC = gcc
|
||||
endif
|
||||
ifeq ($(BUILD),)
|
||||
BUILD = release
|
||||
BUILD = perf
|
||||
endif
|
||||
|
||||
BEAR := bear
|
||||
@@ -49,7 +49,7 @@ OBJ := $(addprefix $(OBJDIR)/,$(SRC_FN:.c=.o))
|
||||
TSTSRC := $(wildcard $(TSTDIR)/*.c)
|
||||
|
||||
LIB := br_$(shell uname -m) # library name
|
||||
LIBS := $(strip -l$(LIB) -lreadline -lncurses -ltinfo)
|
||||
LIBS := $(strip -l$(LIB))
|
||||
|
||||
DEP_FN := $(SRC_FN)
|
||||
DEP := $(addprefix $(DEPDIR)/,$(DEP_FN:.c=.d))
|
||||
@@ -92,7 +92,7 @@ CPPFLAGS := -I$(BRINCDIR) -I$(INCDIR) -DVERSION=\"$(VERSION)\"
|
||||
|
||||
ifeq ($(BUILD),release)
|
||||
CPPFLAGS += -DNDEBUG # assert (unused)
|
||||
else ifeq ($(BUILD),dev)
|
||||
else # ifeq ($(BUILD),dev)
|
||||
CPPFLAGS += -DWARN_ON # brlib bug.h
|
||||
CPPFLAGS += -DBUG_ON # brlib bug.h
|
||||
|
||||
@@ -127,18 +127,27 @@ CFLAGS += -Wall
|
||||
CFLAGS += -Wextra
|
||||
CFLAGS += -Wshadow
|
||||
CFLAGS += -Wmissing-declarations
|
||||
CFLAGS += -march=native
|
||||
|
||||
### dev OR release
|
||||
ifeq ($(BUILD),release)
|
||||
CFLAGS += -O3
|
||||
|
||||
CFLAGS += -march=native
|
||||
CFLAGS += -flto
|
||||
CFLAGS += -g
|
||||
CFLAGS += -ginline-points # inlined funcs debug info
|
||||
CFLAGS += -funroll-loops
|
||||
CFLAGS += -flto
|
||||
else ifeq ($(BUILD),dev)
|
||||
CFLAGS += -Og
|
||||
CFLAGS += -g # symbols (gdb, perf, etc.)
|
||||
CFLAGS += -ginline-points # inlined funcs debug info
|
||||
#CFLAGS += -pg # gprof
|
||||
# Next one may be useful for valgrind (when invalid instructions)
|
||||
#CFLAGS += -mno-tbm
|
||||
else ifeq ($(BUILD),perf)
|
||||
CFLAGS += -O3
|
||||
CFLAGS += -g # symbols (gdb, perf, etc.)
|
||||
CFLAGS += -ginline-points # inlined funcs debug info
|
||||
CFLAGS += -funroll-loops
|
||||
# for gprof
|
||||
#CFLAGS += -pg
|
||||
# Next one may be useful for valgrind (when invalid instructions)
|
||||
@@ -198,7 +207,7 @@ $(sort all $(MAKECMDGOALS)):
|
||||
else
|
||||
|
||||
##################################### General targets
|
||||
.PHONY: all release dev compile clean cleanall
|
||||
.PHONY: all release dev perf compile clean cleanall
|
||||
|
||||
all: testing $(TARGET)
|
||||
|
||||
@@ -208,6 +217,9 @@ release:
|
||||
dev:
|
||||
$(MAKE) BUILD=dev clean all
|
||||
|
||||
perf:
|
||||
$(MAKE) BUILD=perf clean all
|
||||
|
||||
compile: brlib objs
|
||||
|
||||
libs: brlib
|
||||
@@ -337,7 +349,7 @@ cleanasmcpp:
|
||||
|
||||
%.s: %.c
|
||||
@echo "generating $@ (asm)."
|
||||
@$(CC) -S -fverbose-asm $(CPPFLAGS) $(CFLAGS) $< -o $@
|
||||
$(CC) -S -fverbose-asm $(CPPFLAGS) $(CFLAGS) $< -o $@
|
||||
|
||||
##################################### LSP (ccls)
|
||||
.PHONY: ccls
|
||||
@@ -380,11 +392,11 @@ TEST += movedo-test perft-test tt-test
|
||||
|
||||
PIECE_OBJS := piece.o
|
||||
FEN_OBJS := $(PIECE_OBJS) fen.o position.o bitboard.o board.o \
|
||||
hyperbola-quintessence.o attack.o hash.o init.o
|
||||
hyperbola-quintessence.o attack.o hash.o init.o misc.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 misc.o
|
||||
MOVEDO_OBJS := $(ATTACK_OBJS) move-do.o
|
||||
PERFT_OBJS := $(MOVEDO_OBJS) search.o
|
||||
TT_OBJS := $(MOVEDO_OBJS)
|
||||
|
||||
|
2
brlib
2
brlib
Submodule brlib updated: 8ff163dcf5...553dc6bd07
@@ -61,7 +61,7 @@ struct command commands[] = {
|
||||
|
||||
{ "position", do_position, "position startpos|fen [moves ...]" },
|
||||
|
||||
{ "perft", do_perft, "(not UCI) perft [divide] depth" },
|
||||
{ "perft", do_perft, "(not UCI) perft [divide] [alt] depth" },
|
||||
{ "moves", do_moves, "(not UCI) moves ..." },
|
||||
{ "diagram", do_diagram, "(not UCI) print current position diagram" },
|
||||
|
||||
@@ -318,17 +318,25 @@ int do_diagram(pos_t *pos, __unused char *arg)
|
||||
int do_perft(__unused pos_t *pos, __unused char *arg)
|
||||
{
|
||||
char *saveptr, *token;
|
||||
int divide = 0, depth = 6;
|
||||
int divide = 0, depth = 6, alt = 0;
|
||||
|
||||
token = strtok_r(arg, " ", &saveptr);
|
||||
if (!strcmp(token, "divide")) {
|
||||
divide = 1;
|
||||
token = strtok_r(NULL, " ", &saveptr);
|
||||
}
|
||||
if (!strcmp(token, "alt")) {
|
||||
alt = 1;
|
||||
token = strtok_r(NULL, " ", &saveptr);
|
||||
}
|
||||
depth = atoi(token);
|
||||
printf("perft: divide=%d depth=%d\n", divide, depth);
|
||||
if (depth > 0)
|
||||
printf("perft: divide=%d alt=%d depth=%d\n", divide, alt, depth);
|
||||
if (depth > 0) {
|
||||
if (!alt)
|
||||
perft(pos, depth, 1, divide);
|
||||
else
|
||||
perft_alt(pos, depth, 1, divide);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@@ -21,9 +21,7 @@
|
||||
#include <bug.h>
|
||||
|
||||
#include "chessdefs.h"
|
||||
#include "util.h"
|
||||
//#include "piece.h"
|
||||
//#include "bitboard.h"
|
||||
#include "misc.h"
|
||||
#include "position.h"
|
||||
#include "fen.h"
|
||||
|
||||
|
@@ -18,7 +18,7 @@
|
||||
#include <bitops.h>
|
||||
|
||||
#include "chessdefs.h"
|
||||
#include "util.h"
|
||||
#include "misc.h"
|
||||
#include "position.h"
|
||||
#include "piece.h"
|
||||
#include "hash.h"
|
||||
|
@@ -14,7 +14,7 @@
|
||||
#ifndef HASH_H
|
||||
#define HASH_H
|
||||
|
||||
//#include <bug.h>
|
||||
#include <bug.h>
|
||||
|
||||
#include "chessdefs.h"
|
||||
|
||||
@@ -121,7 +121,7 @@ bool zobrist_verify(pos_t *pos);
|
||||
*/
|
||||
static inline void tt_prefetch(hkey_t key)
|
||||
{
|
||||
// bug_on(!hash_tt.keys);
|
||||
bug_on(!hash_tt.keys);
|
||||
__builtin_prefetch(hash_tt.keys + (key & hash_tt.mask));
|
||||
}
|
||||
|
||||
|
@@ -26,7 +26,6 @@
|
||||
#include "attack.h"
|
||||
#include "move-gen.h"
|
||||
|
||||
|
||||
/**
|
||||
* pseudo_is_legal() - check if a move is legal.
|
||||
* @pos: position
|
||||
@@ -36,74 +35,71 @@
|
||||
*/
|
||||
bool pseudo_is_legal(const pos_t *pos, const move_t move)
|
||||
{
|
||||
color_t us = pos->turn, them = OPPONENT(us);
|
||||
square_t from = move_from(move), to = move_to(move);
|
||||
square_t king = pos->king[us];
|
||||
color_t us = pos->turn;
|
||||
color_t them = OPPONENT(us);
|
||||
square_t from = move_from(move);
|
||||
square_t to = move_to(move);
|
||||
square_t kingsq = pos->king[us];
|
||||
square_t ep = pos->en_passant;
|
||||
bitboard_t kingbb = pos->bb[us][KING];
|
||||
bitboard_t occ = pos_occ(pos);
|
||||
u64 pinned = BIT(from) & pos->blockers;
|
||||
u64 checkers = pos->checkers;
|
||||
|
||||
bug_on(pos->board[from] == NO_PIECE || COLOR(pos->board[from]) != us);
|
||||
|
||||
/* (1) - Castling & King
|
||||
* For castling, we need to check intermediate squares attacks only.
|
||||
* Attention: To test if K is in check after moving, we need to exclude
|
||||
* king from occupation bitboard (to catch king moving away from checker
|
||||
* on same line) !
|
||||
*/
|
||||
if (unlikely(from == king)) {
|
||||
if (unlikely(is_castle(move))) {
|
||||
square_t dir = to > from? 1: -1;
|
||||
if (is_castle(move)) {
|
||||
int dir = to > from? 1: -1;
|
||||
if (sq_is_attacked(pos, occ, from + dir, them))
|
||||
return false;
|
||||
}
|
||||
if (from == kingsq) {
|
||||
return !sq_is_attacked(pos, occ ^ kingbb, to, them);
|
||||
}
|
||||
|
||||
/* (2) - King is in check
|
||||
* Double-check is already handled in (1), as only K moves were generated
|
||||
* by pseudo legal move generator.
|
||||
* Here, allowed dest squares are only on King-checker line, or on checker
|
||||
* square.
|
||||
* attacker.
|
||||
* Special cases:
|
||||
* e.p., legal if the grabbed pawn is giving check
|
||||
* pinned piece: always illegal
|
||||
* Special cases (illegal):
|
||||
* - e.p., if the grabbed pawn is *not* giving check
|
||||
* - piece is pinned
|
||||
*/
|
||||
if (checkers) {
|
||||
if (pinned)
|
||||
return false;
|
||||
if (bb_multiple(checkers))
|
||||
return false;
|
||||
square_t checker = ctz64(checkers);
|
||||
if (is_enpassant(move)) {
|
||||
return pos->en_passant + sq_up(them) == checker;
|
||||
return ep + sq_up(them) == ctz64(checkers);
|
||||
}
|
||||
return true;
|
||||
//bitboard_t between = bb_between[king][checker] | pos->checkers;
|
||||
//return mask(to) & between;
|
||||
}
|
||||
|
||||
/* (3) - pinned pieces
|
||||
* We verify here that pinned piece P stays on line King-P.
|
||||
* We verify here that pinned piece P stays on line between K & dest square.
|
||||
*/
|
||||
if (BIT(from) & pos->blockers) {
|
||||
return bb_line[from][king] & BIT(to); /* is to on pinner line ? */
|
||||
if (pinned) {
|
||||
return bb_line[from][kingsq] & BIT(to); /* is to on pinner line ? */
|
||||
}
|
||||
|
||||
/* (4) - En-passant
|
||||
* pinned pieces are handled in pinned section.
|
||||
* pinned piece is already handled in (3).
|
||||
* One case not handled anywhere else: when the two "disappearing" pawns
|
||||
* would discover a R/Q horizontal check.
|
||||
* Note: grabbed pawn *cannot* discover a check (impossible position).
|
||||
*/
|
||||
if (unlikely(is_enpassant(move))) {
|
||||
if (is_enpassant(move)) {
|
||||
bitboard_t rank5 = bb_rel_rank(RANK_5, us);
|
||||
|
||||
if (unlikely((pos->bb[us][KING] & rank5))) {
|
||||
bitboard_t exclude = BIT(pos->en_passant - sq_up(us)) | BIT(from);
|
||||
if (kingbb & rank5) {
|
||||
bitboard_t exclude = BIT(ep + sq_up(them)) | BIT(from);
|
||||
bitboard_t rooks = (pos->bb[them][ROOK] | pos->bb[them][QUEEN]) & rank5;
|
||||
|
||||
if (hyperbola_rank_moves(occ ^ exclude, king) & rooks)
|
||||
return false;
|
||||
return !(hyperbola_rank_moves(occ ^ exclude, kingsq) & rooks);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -349,12 +345,12 @@ movelist_t *pos_gen_pseudo(pos_t *pos, movelist_t *movelist)
|
||||
bitboard_t dest_squares = ~my_pieces;
|
||||
bitboard_t occ = my_pieces | enemy_pieces;
|
||||
bitboard_t empty = ~occ;
|
||||
move_t *moves = movelist->move;
|
||||
square_t king = pos->king[us];
|
||||
|
||||
bitboard_t from_bb, to_bb;
|
||||
bitboard_t tmp_bb;
|
||||
move_t *moves = movelist->move;
|
||||
square_t from, to;
|
||||
square_t king = pos->king[us];
|
||||
|
||||
/* king - MUST BE FIRST */
|
||||
to_bb = bb_king_moves(dest_squares, king);
|
||||
@@ -379,6 +375,8 @@ movelist_t *pos_gen_pseudo(pos_t *pos, movelist_t *movelist)
|
||||
* To square attack check will be done in gen_is_legal.
|
||||
*/
|
||||
if (can_oo(pos->castle, us)) {
|
||||
|
||||
/* CHANGE HERE, either with bitmask >> or direct sq check */
|
||||
bitboard_t occmask = rel_rank1 & (FILE_Fbb | FILE_Gbb);
|
||||
if (!(occ & occmask)) {
|
||||
*moves++ = move_make_flags(king, king + 2, M_CASTLE_K);
|
||||
|
@@ -27,7 +27,7 @@
|
||||
#include "hyperbola-quintessence.h"
|
||||
#include "fen.h"
|
||||
#include "piece.h"
|
||||
#include "util.h"
|
||||
#include "misc.h"
|
||||
#include "board.h"
|
||||
#include "attack.h"
|
||||
|
||||
|
@@ -19,7 +19,7 @@
|
||||
#include <brlib.h>
|
||||
#include <bitops.h>
|
||||
#include <struct-group.h>
|
||||
// #include <bug.h>
|
||||
#include <bug.h>
|
||||
|
||||
#include "chessdefs.h"
|
||||
#include "hash.h"
|
||||
|
18
src/util.c
18
src/util.c
@@ -1,18 +0,0 @@
|
||||
/* util.c - various util 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "bitboard.h"
|
@@ -279,9 +279,10 @@ int main(int ac, char**av)
|
||||
s64 ms, lps;
|
||||
int opt, depth = 6, run = 3, tt, newtt = HASH_SIZE_DEFAULT;
|
||||
struct {
|
||||
s64 count, ms;
|
||||
s64 count, countskipped, ms;
|
||||
s64 minlps, maxlps;
|
||||
int skipped;
|
||||
int err;
|
||||
} res[3] = {
|
||||
{ .minlps = LONG_MAX },
|
||||
{ .minlps = LONG_MAX },
|
||||
@@ -362,6 +363,7 @@ int main(int ac, char**av)
|
||||
ms = clock_elapsed_ms(&clock);
|
||||
if (!ms) {
|
||||
res[2].skipped++;
|
||||
res[2].countskipped += sf_count;
|
||||
lps = 0;
|
||||
} else {
|
||||
lps = sf_count * 1000l / ms;
|
||||
@@ -382,6 +384,7 @@ int main(int ac, char**av)
|
||||
ms = clock_elapsed_ms(&clock);
|
||||
if (!ms) {
|
||||
res[0].skipped++;
|
||||
res[0].countskipped += my_count;
|
||||
lps = 0;
|
||||
} else {
|
||||
lps = my_count * 1000l / ms;
|
||||
@@ -399,6 +402,7 @@ int main(int ac, char**av)
|
||||
tt_stats();
|
||||
} else {
|
||||
printf("perft : perft:%'lu ***ERROR***\n", my_count);
|
||||
res[0].err++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,6 +412,7 @@ int main(int ac, char**av)
|
||||
ms = clock_elapsed_ms(&clock);
|
||||
if (!ms) {
|
||||
res[1].skipped++;
|
||||
res[1].countskipped += my_count;
|
||||
lps = 0;
|
||||
} else {
|
||||
lps = my_count * 1000l / ms;
|
||||
@@ -424,6 +429,7 @@ int main(int ac, char**av)
|
||||
my_count, ms, lps);
|
||||
} else {
|
||||
printf("perft_alt : perft:%'lu ***ERROR***\n", my_count);
|
||||
res[1].err++;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
@@ -434,30 +440,30 @@ int main(int ac, char**av)
|
||||
res[2].ms = 1;
|
||||
printf("total Stockfish : perft:%'lu ms:%'lu lps:%'lu min:%'lu max:%'lu "
|
||||
"(skipped %d/%d)\n",
|
||||
res[2].count, res[2].ms,
|
||||
res[2].count + res[2].countskipped, res[2].ms,
|
||||
res[2].count * 1000l / res[2].ms,
|
||||
res[2].minlps, res[2].maxlps,
|
||||
res[0].skipped, curtest);
|
||||
res[2].skipped, curtest);
|
||||
}
|
||||
if (run & 1) {
|
||||
if (!res[0].ms)
|
||||
res[0].ms = 1;
|
||||
printf("total perft : perft:%'lu ms:%'lu lps:%'lu min:%'lu max:%'lu "
|
||||
"(skipped %d/%d)\n",
|
||||
res[0].count, res[0].ms,
|
||||
"(pos:%d skipped:%d err:%d)\n",
|
||||
res[0].count + res[0].countskipped, res[0].ms,
|
||||
res[0].count * 1000l / res[0].ms,
|
||||
res[0].minlps, res[0].maxlps,
|
||||
res[0].skipped, curtest);
|
||||
curtest, res[0].skipped, res[0].err);
|
||||
}
|
||||
if (run & 2) {
|
||||
if (!res[1].ms)
|
||||
res[1].ms = 1;
|
||||
printf("total perft_alt : perft:%'lu ms:%'lu lps:%'lu min:%'lu max:%'lu "
|
||||
"(skipped %d/%d)\n",
|
||||
res[1].count, res[1].ms,
|
||||
"(pos:%d skipped:%d err:%d)\n",
|
||||
res[1].count + res[1].countskipped, res[1].ms,
|
||||
res[1].count * 1000l / res[1].ms,
|
||||
res[1].minlps, res[1].maxlps,
|
||||
res[0].skipped, curtest);
|
||||
curtest, res[1].skipped, res[1].err);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user