Compare commits
5 Commits
08ba989170
...
26b9a5b58a
Author | SHA1 | Date | |
---|---|---|---|
26b9a5b58a | |||
65fe74c9c5 | |||
9b2f5ff751 | |||
edcc87be5a | |||
09afd98971 |
6
Makefile
6
Makefile
@@ -89,10 +89,10 @@ CFLAGS := -std=gnu11
|
|||||||
|
|
||||||
### dev OR release
|
### dev OR release
|
||||||
# dev
|
# dev
|
||||||
#CFLAGS += -O1
|
CFLAGS += -O1
|
||||||
#CFLAGS += -g
|
#CFLAGS += -g
|
||||||
# release
|
# release
|
||||||
CFLAGS += -Ofast
|
#CFLAGS += -Ofast
|
||||||
|
|
||||||
CFLAGS += -march=native
|
CFLAGS += -march=native
|
||||||
CFLAGS += -flto
|
CFLAGS += -flto
|
||||||
@@ -100,7 +100,7 @@ CFLAGS += -Wall
|
|||||||
CFLAGS += -Wextra
|
CFLAGS += -Wextra
|
||||||
CFLAGS += -Wmissing-declarations
|
CFLAGS += -Wmissing-declarations
|
||||||
# for gprof
|
# for gprof
|
||||||
#CFLAGS += -pg
|
CFLAGS += -pg
|
||||||
# Next one may be useful for valgrind (when invalid instructions)
|
# Next one may be useful for valgrind (when invalid instructions)
|
||||||
# CFLAGS += -mno-tbm
|
# CFLAGS += -mno-tbm
|
||||||
|
|
||||||
|
10
src/fen.c
10
src/fen.c
@@ -75,7 +75,7 @@ static const char *castle_str = "KQkq";
|
|||||||
static int fen_check(pos_t *pos)
|
static int fen_check(pos_t *pos)
|
||||||
{
|
{
|
||||||
char *colstr[2] = { "white", "black"};
|
char *colstr[2] = { "white", "black"};
|
||||||
int error = 0, warning = 0;
|
int warning = 0;
|
||||||
|
|
||||||
/* en passant, depends on who plays next */
|
/* en passant, depends on who plays next */
|
||||||
if (pos->en_passant != SQUARE_NONE) {
|
if (pos->en_passant != SQUARE_NONE) {
|
||||||
@@ -130,13 +130,7 @@ static int fen_check(pos_t *pos)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!(error = pos_check(pos, 0))) {
|
return pos_ok(pos, 0) ? warning: -1;
|
||||||
/* TODO: Should it really be here ? */
|
|
||||||
pos->checkers = pos_checkers(pos, pos->turn);
|
|
||||||
pos->pinners = pos_king_pinners(pos, pos->turn);
|
|
||||||
pos->blockers = pos_king_blockers(pos, pos->turn, pos->pinners);
|
|
||||||
}
|
|
||||||
return error ? -1: warning;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -42,12 +42,12 @@
|
|||||||
*
|
*
|
||||||
* @return: pos.
|
* @return: pos.
|
||||||
*/
|
*/
|
||||||
pos_t *move_do(pos_t *pos, const move_t move, state_t *state)
|
pos_t *move_do(pos_t *pos, const move_t move) //, state_t *state)
|
||||||
{
|
{
|
||||||
//# ifdef DEBUG_MOVE_DO
|
//# ifdef DEBUG_MOVE_DO
|
||||||
// move_print(move, M_PR_NL | M_PR_LONG);
|
// move_print(move, M_PR_NL | M_PR_LONG);
|
||||||
//# endif
|
//# endif
|
||||||
*state = pos->state; /* save irreversible changes */
|
//*state = pos->state; /* save irreversible changes */
|
||||||
|
|
||||||
color_t us = pos->turn, them = OPPONENT(us);
|
color_t us = pos->turn, them = OPPONENT(us);
|
||||||
square_t from = move_from(move), to = move_to(move);
|
square_t from = move_from(move), to = move_to(move);
|
||||||
@@ -146,7 +146,7 @@ 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)//, const state_t *state)
|
||||||
{
|
{
|
||||||
//# ifdef DEBUG_MOVE
|
//# ifdef DEBUG_MOVE
|
||||||
//log(1, "new move: ");
|
//log(1, "new move: ");
|
||||||
@@ -184,7 +184,7 @@ pos_t *move_undo(pos_t *pos, const move_t move, const state_t *state)
|
|||||||
pos_set_sq(pos, grabbed, MAKE_PIECE(PAWN, them));
|
pos_set_sq(pos, grabbed, MAKE_PIECE(PAWN, them));
|
||||||
}
|
}
|
||||||
|
|
||||||
pos->state = *state; /* restore irreversible changes */
|
//pos->state = *state; /* restore irreversible changes */
|
||||||
pos->turn = us;
|
pos->turn = us;
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
#include "position.h"
|
#include "position.h"
|
||||||
|
|
||||||
pos_t *move_do(pos_t *pos, const move_t move, state_t *state);
|
pos_t *move_do(pos_t *pos, const move_t move);//, state_t *state);
|
||||||
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);//, const state_t *state);
|
||||||
|
|
||||||
#endif /* MOVE_DO_H */
|
#endif /* MOVE_DO_H */
|
||||||
|
@@ -169,7 +169,7 @@ movelist_t *pos_all_legal(const pos_t *pos, movelist_t *movelist, movelist_t *de
|
|||||||
* - castling, if king passes an enemy-controlled square (not final square).
|
* - castling, if king passes an enemy-controlled square (not final square).
|
||||||
* When immediately known, a few move flags are also applied in these cases:
|
* When immediately known, a few move flags are also applied in these cases:
|
||||||
* - castling: M_CASTLE_{K,Q}
|
* - castling: M_CASTLE_{K,Q}
|
||||||
* - pawn capture (excl. en-passant): M_CAPTURE
|
* - capture (excl. en-passant): M_CAPTURE
|
||||||
* - en-passant: M_EN_PASSANT
|
* - en-passant: M_EN_PASSANT
|
||||||
* - pawn double push: M_DPUSH
|
* - pawn double push: M_DPUSH
|
||||||
* - promotion: M_PROMOTION
|
* - promotion: M_PROMOTION
|
||||||
@@ -192,7 +192,6 @@ int pos_gen_pseudomoves(pos_t *pos, movelist_t *movelist)
|
|||||||
|
|
||||||
bitboard_t movebits, from_pawns;
|
bitboard_t movebits, from_pawns;
|
||||||
bitboard_t tmp1, tmp2;
|
bitboard_t tmp1, tmp2;
|
||||||
|
|
||||||
move_t *moves = movelist->move;
|
move_t *moves = movelist->move;
|
||||||
int *nmoves = &movelist->nmoves;
|
int *nmoves = &movelist->nmoves;
|
||||||
int from, to;
|
int from, to;
|
||||||
@@ -223,7 +222,6 @@ int pos_gen_pseudomoves(pos_t *pos, movelist_t *movelist)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
bit_for_each64(from, tmp1, pos->bb[us][ROOK] | pos->bb[us][QUEEN]) {
|
bit_for_each64(from, tmp1, pos->bb[us][ROOK] | pos->bb[us][QUEEN]) {
|
||||||
// printf("rook=%d/%s\n", from, sq_to_string(from));
|
|
||||||
movebits = hyperbola_rook_moves(occ, from) & not_my_pieces;
|
movebits = hyperbola_rook_moves(occ, from) & not_my_pieces;
|
||||||
bit_for_each64(to, tmp2, movebits & empty) {
|
bit_for_each64(to, tmp2, movebits & empty) {
|
||||||
moves[(*nmoves)++] = move_make(from, to);
|
moves[(*nmoves)++] = move_make(from, to);
|
||||||
@@ -245,16 +243,23 @@ int pos_gen_pseudomoves(pos_t *pos, movelist_t *movelist)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* pawn: relative rank and files */
|
/* pawn: relative rank and files */
|
||||||
bitboard_t rel_rank7 = bb_rel_rank(RANK_7, us);
|
bitboard_t rel_rank8 = bb_rel_rank(RANK_8, us);
|
||||||
bitboard_t rel_rank3 = bb_rel_rank(RANK_3, us);
|
bitboard_t rel_rank3 = bb_rel_rank(RANK_3, us);
|
||||||
|
|
||||||
/* pawn: ranks 2-6 push 1 and 2 squares */
|
/* pawn: ranks 2-6 push 1 and 2 squares */
|
||||||
movebits = pawn_shift_up(pos->bb[us][PAWN] & ~rel_rank7, us) & empty;
|
movebits = pawn_shift_up(pos->bb[us][PAWN], us) & empty;
|
||||||
bit_for_each64(to, tmp1, movebits) {
|
bit_for_each64(to, tmp1, movebits & ~rel_rank8) {
|
||||||
from = pawn_push_up(to, them); /* reverse push */
|
from = pawn_push_up(to, them); /* reverse push */
|
||||||
//printf("push %d->%d %s->%s", from, to, sq_to_string(from), sq_to_string(to));
|
|
||||||
moves[(*nmoves)++] = move_make(from, to);
|
moves[(*nmoves)++] = move_make(from, to);
|
||||||
}
|
}
|
||||||
|
bit_for_each64(to, tmp1, movebits & rel_rank8) { /* promotions */
|
||||||
|
from = pawn_push_up(to, them); /* reverse push */
|
||||||
|
moves[(*nmoves)++] = move_make_promote(from, to, QUEEN);
|
||||||
|
moves[(*nmoves)++] = move_make_promote(from, to, ROOK);
|
||||||
|
moves[(*nmoves)++] = move_make_promote(from, to, BISHOP);
|
||||||
|
moves[(*nmoves)++] = move_make_promote(from, to, KNIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
/* possible second push */
|
/* possible second push */
|
||||||
movebits = pawn_shift_up(movebits & rel_rank3, us) & empty;
|
movebits = pawn_shift_up(movebits & rel_rank3, us) & empty;
|
||||||
bit_for_each64(to, tmp1, movebits) {
|
bit_for_each64(to, tmp1, movebits) {
|
||||||
@@ -262,20 +267,33 @@ int pos_gen_pseudomoves(pos_t *pos, movelist_t *movelist)
|
|||||||
moves[(*nmoves)++] = move_make_flags(from, to, M_DPUSH);
|
moves[(*nmoves)++] = move_make_flags(from, to, M_DPUSH);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pawn: ranks 2-6 captures left */
|
/* pawn: captures left */
|
||||||
from_pawns = pos->bb[us][PAWN] & ~rel_rank7; // & ~rel_filea;
|
movebits = pawn_shift_upleft(pos->bb[us][PAWN], us) & enemy_pieces;
|
||||||
movebits = pawn_shift_upleft(from_pawns, us) & enemy_pieces;
|
bit_for_each64(to, tmp1, movebits & ~rel_rank8) {
|
||||||
bit_for_each64(to, tmp1, movebits) {
|
|
||||||
from = pawn_push_upleft(to, them); /* reverse capture */
|
from = pawn_push_upleft(to, them); /* reverse capture */
|
||||||
moves[(*nmoves)++] = move_make_capture(from, to);
|
moves[(*nmoves)++] = move_make_capture(from, to);
|
||||||
}
|
}
|
||||||
/* pawn: ranks 2-6 captures right */
|
bit_for_each64(to, tmp1, movebits & rel_rank8) {
|
||||||
from_pawns = pos->bb[us][PAWN] & ~rel_rank7; // & ~rel_fileh;
|
from = pawn_push_upleft(to, them); /* reverse capture */
|
||||||
movebits = pawn_shift_upright(from_pawns, us) & enemy_pieces;
|
moves[(*nmoves)++] = move_make_promote_capture(from, to, QUEEN);
|
||||||
bit_for_each64(to, tmp1, movebits) {
|
moves[(*nmoves)++] = move_make_promote_capture(from, to, ROOK);
|
||||||
from = pawn_push_upright(to, them);
|
moves[(*nmoves)++] = move_make_promote_capture(from, to, BISHOP);
|
||||||
|
moves[(*nmoves)++] = move_make_promote_capture(from, to, KNIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pawn: captures right */
|
||||||
|
movebits = pawn_shift_upright(pos->bb[us][PAWN], us) & enemy_pieces;
|
||||||
|
bit_for_each64(to, tmp1, movebits & ~rel_rank8) {
|
||||||
|
from = pawn_push_upright(to, them); /* reverse capture */
|
||||||
moves[(*nmoves)++] = move_make_capture(from, to);
|
moves[(*nmoves)++] = move_make_capture(from, to);
|
||||||
}
|
}
|
||||||
|
bit_for_each64(to, tmp1, movebits & rel_rank8) {
|
||||||
|
from = pawn_push_upright(to, them); /* reverse capture */
|
||||||
|
moves[(*nmoves)++] = move_make_promote_capture(from, to, QUEEN);
|
||||||
|
moves[(*nmoves)++] = move_make_promote_capture(from, to, ROOK);
|
||||||
|
moves[(*nmoves)++] = move_make_promote_capture(from, to, BISHOP);
|
||||||
|
moves[(*nmoves)++] = move_make_promote_capture(from, to, KNIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
/* pawn: en-passant */
|
/* pawn: en-passant */
|
||||||
if ((to = pos->en_passant) != SQUARE_NONE) {
|
if ((to = pos->en_passant) != SQUARE_NONE) {
|
||||||
@@ -287,36 +305,6 @@ int pos_gen_pseudomoves(pos_t *pos, movelist_t *movelist)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pawn: rank 7 push */
|
|
||||||
movebits = pawn_shift_up(pos->bb[us][PAWN] & rel_rank7, us) & empty;
|
|
||||||
bit_for_each64(to, tmp1, movebits) {
|
|
||||||
from = pawn_push_up(to, them); /* reverse push */
|
|
||||||
moves[(*nmoves)++] = move_make_promote(from, to, QUEEN);
|
|
||||||
moves[(*nmoves)++] = move_make_promote(from, to, ROOK);
|
|
||||||
moves[(*nmoves)++] = move_make_promote(from, to, BISHOP);
|
|
||||||
moves[(*nmoves)++] = move_make_promote(from, to, KNIGHT);
|
|
||||||
}
|
|
||||||
/* pawn promotion: rank 7 captures left */
|
|
||||||
from_pawns = pos->bb[us][PAWN] & rel_rank7; // & ~rel_filea;
|
|
||||||
movebits = pawn_shift_upleft(from_pawns, us) & enemy_pieces;
|
|
||||||
bit_for_each64(to, tmp1, movebits) {
|
|
||||||
from = pawn_push_upleft(to, them); /* reverse capture */
|
|
||||||
moves[(*nmoves)++] = move_make_promote_capture(from, to, QUEEN);
|
|
||||||
moves[(*nmoves)++] = move_make_promote_capture(from, to, ROOK);
|
|
||||||
moves[(*nmoves)++] = move_make_promote_capture(from, to, BISHOP);
|
|
||||||
moves[(*nmoves)++] = move_make_promote_capture(from, to, KNIGHT);
|
|
||||||
}
|
|
||||||
/* pawn: rank 7 captures right */
|
|
||||||
from_pawns = pos->bb[us][PAWN] & rel_rank7; // & ~rel_fileh;
|
|
||||||
movebits = pawn_shift_upright(from_pawns, us) & enemy_pieces;
|
|
||||||
bit_for_each64(to, tmp1, movebits) {
|
|
||||||
from = pawn_push_upright(to, them); /* reverse capture */
|
|
||||||
moves[(*nmoves)++] = move_make_promote_capture(from, to, QUEEN);
|
|
||||||
moves[(*nmoves)++] = move_make_promote_capture(from, to, ROOK);
|
|
||||||
moves[(*nmoves)++] = move_make_promote_capture(from, to, BISHOP);
|
|
||||||
moves[(*nmoves)++] = move_make_promote_capture(from, to, KNIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* castle - Attention ! Castling flags are assumed correct
|
/* castle - Attention ! Castling flags are assumed correct
|
||||||
*/
|
*/
|
||||||
if (!pos->checkers) {
|
if (!pos->checkers) {
|
||||||
@@ -342,16 +330,7 @@ int pos_gen_pseudomoves(pos_t *pos, movelist_t *movelist)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* TODO
|
/* TODO: add function per piece, and type, for easier debug
|
||||||
* DONE. pawn ranks 2-6 advance (1 push, + 2 squares for rank 2)
|
|
||||||
* DONE. pawns rank 7 advance + promotions
|
|
||||||
* DONE. pawns ranks 2-6 captures, left and right
|
|
||||||
* DONE. pawns en-passant (with capture)
|
|
||||||
* DONE. pawns rank 7 capture + promotion
|
|
||||||
* DONE. castle
|
|
||||||
*
|
|
||||||
* add function per piece, and type, for easier debug
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
return *nmoves;
|
return *nmoves;
|
||||||
}
|
}
|
||||||
|
@@ -187,11 +187,30 @@ bitboard_t pos_checkers(const pos_t *pos, const color_t color)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pos_king_pinners_blockers() - set position "pinners" and "blockers".
|
* pos_set_checkers_pinners_blockers() - calculate checkers, pinners and blockers.
|
||||||
* @pos: &position
|
* @pos: &position
|
||||||
*
|
*
|
||||||
* set position "pinners" 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
|
||||||
|
* 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 *\/
|
||||||
|
*
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pos_set_pinners_blockers() - set position pinners and blockers.
|
||||||
|
* @pos: &position
|
||||||
|
*
|
||||||
|
* set position pinners and blockers on player-to-play king.
|
||||||
*/
|
*/
|
||||||
void pos_set_pinners_blockers(pos_t *pos)
|
void pos_set_pinners_blockers(pos_t *pos)
|
||||||
{
|
{
|
||||||
@@ -253,7 +272,7 @@ bitboard_t pos_king_blockers(const pos_t *pos, const color_t color, const bitboa
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pos_check() - extensive position consistency check.
|
* pos_ok() - extensive position consistency check.
|
||||||
* @pos: &position
|
* @pos: &position
|
||||||
* @strict: if true, call bug_on() on any error.
|
* @strict: if true, call bug_on() on any error.
|
||||||
*
|
*
|
||||||
@@ -278,9 +297,9 @@ bitboard_t pos_king_blockers(const pos_t *pos, const color_t color, const bitboa
|
|||||||
* TODO: add more checks:
|
* TODO: add more checks:
|
||||||
* - kings attacking each other
|
* - kings attacking each other
|
||||||
*
|
*
|
||||||
* @Return: Number of detected error (only if @strict is false).
|
* @return: (if @strict is false) return true if check is ok, false otherwise.
|
||||||
*/
|
*/
|
||||||
int pos_check(const pos_t *pos, 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;
|
||||||
bitboard_t tmp;
|
bitboard_t tmp;
|
||||||
@@ -324,7 +343,7 @@ int pos_check(const pos_t *pos, const bool strict)
|
|||||||
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);
|
bug_on(strict && error);
|
||||||
return error;
|
return error? false: true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -165,7 +165,7 @@ 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);
|
bitboard_t pos_king_pinners(const pos_t *pos, const color_t color);
|
||||||
bitboard_t pos_king_blockers(const pos_t *pos, const color_t color, const bitboard_t );
|
bitboard_t pos_king_blockers(const pos_t *pos, const color_t color, const bitboard_t );
|
||||||
|
|
||||||
int pos_check(const pos_t *pos, const bool strict);
|
bool pos_ok(const pos_t *pos, const bool strict);
|
||||||
|
|
||||||
void pos_print(const pos_t *pos);
|
void pos_print(const pos_t *pos);
|
||||||
void pos_print_mask(const pos_t *pos, const bitboard_t mask);
|
void pos_print_mask(const pos_t *pos, const bitboard_t mask);
|
||||||
|
39
src/search.c
39
src/search.c
@@ -37,33 +37,31 @@
|
|||||||
*/
|
*/
|
||||||
u64 perft(pos_t *pos, int depth, int ply)
|
u64 perft(pos_t *pos, int depth, int ply)
|
||||||
{
|
{
|
||||||
int subnodes, nmove = 0;
|
int subnodes, movetmp = 0;
|
||||||
u64 nodes = 0;
|
u64 nodes = 0;
|
||||||
movelist_t pseudo = { .nmoves = 0 }, legal = { .nmoves = 0 };
|
movelist_t pseudo = { .nmoves = 0 };
|
||||||
move_t move;
|
move_t move;
|
||||||
|
state_t state;
|
||||||
|
|
||||||
if (depth == 0)
|
if (depth == 0)
|
||||||
return 1;
|
return 1;
|
||||||
pos->checkers = pos_checkers(pos, pos->turn);
|
pos->checkers = pos_checkers(pos, pos->turn);
|
||||||
pos_set_pinners_blockers(pos);
|
pos_set_pinners_blockers(pos);
|
||||||
|
state = pos->state;
|
||||||
|
|
||||||
pos_gen_pseudomoves(pos, &pseudo);
|
pos_gen_pseudomoves(pos, &pseudo);
|
||||||
pos_all_legal(pos, &pseudo, &legal);
|
while ((move = pos_next_legal(pos, &pseudo, &movetmp)) != MOVE_NONE) {
|
||||||
|
move_do(pos, move);
|
||||||
for (nmove = 0; nmove < legal.nmoves; ++nmove ) {
|
|
||||||
//while ((move = pos_next_legal(pos, &pseudo, &movetmp)) != MOVE_NONE) {
|
|
||||||
//printf("depth=%d movetmp=%d\n", depth, movetmp);
|
|
||||||
state_t state;
|
|
||||||
move = legal.move[nmove];
|
|
||||||
move_do(pos, move, &state);
|
|
||||||
subnodes = perft(pos, depth - 1, ply + 1);
|
subnodes = perft(pos, depth - 1, ply + 1);
|
||||||
if (ply == 1) {
|
if (ply == 1) {
|
||||||
char movestr[8];
|
char movestr[8];
|
||||||
printf("%s: %d\n", move_str(movestr, move, 0), subnodes);
|
printf("%s: %d\n", move_str(movestr, move, 0), subnodes);
|
||||||
}
|
}
|
||||||
nodes += subnodes;
|
nodes += subnodes;
|
||||||
move_undo(pos, move, &state);
|
move_undo(pos, move);
|
||||||
|
pos->state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ply == 1)
|
if (ply == 1)
|
||||||
printf("\nTotal: %lu\n", nodes);
|
printf("\nTotal: %lu\n", nodes);
|
||||||
return nodes;
|
return nodes;
|
||||||
@@ -75,32 +73,31 @@ u64 perft2(pos_t *pos, int depth, int ply)
|
|||||||
u64 nodes = 0;
|
u64 nodes = 0;
|
||||||
movelist_t pseudo = { .nmoves = 0 };
|
movelist_t pseudo = { .nmoves = 0 };
|
||||||
move_t move;
|
move_t move;
|
||||||
|
state_t state;
|
||||||
|
|
||||||
if (is_in_check(pos, OPPONENT(pos->turn)))
|
if (is_in_check(pos, OPPONENT(pos->turn)))
|
||||||
return 0;
|
return 0;
|
||||||
if (depth == 0)
|
if (depth == 0)
|
||||||
return 1;
|
return 1;
|
||||||
pos->checkers = pos_checkers(pos, pos->turn);
|
pos->checkers = pos_checkers(pos, pos->turn);
|
||||||
pos->pinners = pos_king_pinners(pos, pos->turn);
|
pos_set_pinners_blockers(pos);
|
||||||
pos->blockers = pos_king_blockers(pos, pos->turn, pos->pinners);
|
state = pos->state;
|
||||||
|
|
||||||
pos_gen_pseudomoves(pos, &pseudo);
|
pos_gen_pseudomoves(pos, &pseudo);
|
||||||
//pos_all_legal(pos, &pseudo, &legal);
|
|
||||||
|
|
||||||
for (nmove = 0; nmove < pseudo.nmoves; ++nmove ) {
|
for (nmove = 0; nmove < pseudo.nmoves; ++nmove ) {
|
||||||
//while ((move = pos_next_legal(pos, &pseudo, &movetmp)) != MOVE_NONE) {
|
|
||||||
//printf("depth=%d movetmp=%d\n", depth, movetmp);
|
|
||||||
state_t state;
|
|
||||||
move = pseudo.move[nmove];
|
move = pseudo.move[nmove];
|
||||||
move_do(pos, move, &state);
|
move_do(pos, move);
|
||||||
|
//if (!is_in_check(pos, OPPONENT(pos->turn))) {
|
||||||
subnodes = perft2(pos, depth - 1, ply + 1);
|
subnodes = perft2(pos, depth - 1, ply + 1);
|
||||||
|
nodes += subnodes;
|
||||||
if (ply == 1) {
|
if (ply == 1) {
|
||||||
char movestr[8];
|
char movestr[8];
|
||||||
printf("%s: %d\n", move_str(movestr, move, 0), subnodes);
|
printf("%s: %d\n", move_str(movestr, move, 0), subnodes);
|
||||||
}
|
}
|
||||||
nodes += subnodes;
|
//}
|
||||||
move_undo(pos, move, &state);
|
move_undo(pos, move);
|
||||||
|
pos->state = state;
|
||||||
}
|
}
|
||||||
if (ply == 1)
|
if (ply == 1)
|
||||||
printf("\nTotal: %lu\n", nodes);
|
printf("\nTotal: %lu\n", nodes);
|
||||||
|
@@ -39,6 +39,15 @@ struct fentest {
|
|||||||
*/
|
*/
|
||||||
//"4k3/pppppppp/8/8/8/8/PPPPPPPP/2BRK3 w - - 0 1",
|
//"4k3/pppppppp/8/8/8/8/PPPPPPPP/2BRK3 w - - 0 1",
|
||||||
//"4k3/pppppppp/8/8/8/8/PPPPPPPP/1B1R1K2 w - - 0 1",
|
//"4k3/pppppppp/8/8/8/8/PPPPPPPP/1B1R1K2 w - - 0 1",
|
||||||
|
{ __LINE__, MOVEGEN | MOVEDO | PERFT,
|
||||||
|
"illegal white e.p.",
|
||||||
|
"3k4/8/5K2/3pP3/8/2b5/8/8 w - d6 0 1",
|
||||||
|
},
|
||||||
|
{ __LINE__, PERFT,
|
||||||
|
"only K, pawn push and ep moves",
|
||||||
|
"3k4/8/8/3pPK2/8/8/8/8 w - d6 0 1"
|
||||||
|
},
|
||||||
|
|
||||||
{ __LINE__, MOVEGEN | MOVEDO | PERFT,
|
{ __LINE__, MOVEGEN | MOVEDO | PERFT,
|
||||||
"illegal white e.p.",
|
"illegal white e.p.",
|
||||||
"3k4/8/8/2qpPK2/8/8/8/8 w - d6 0 1",
|
"3k4/8/8/2qpPK2/8/8/8/8 w - d6 0 1",
|
||||||
@@ -47,10 +56,6 @@ struct fentest {
|
|||||||
"illegal black e.p.",
|
"illegal black e.p.",
|
||||||
"8/8/8/8/2QPpk2/8/8/3K4 b - d3 0 1",
|
"8/8/8/8/2QPpk2/8/8/3K4 b - d3 0 1",
|
||||||
},
|
},
|
||||||
{ __LINE__, MOVEGEN | MOVEDO | PERFT,
|
|
||||||
"illegal white e.p.",
|
|
||||||
"3k4/8/5K2/3pP3/8/2b5/8/8 w - d6 0 1",
|
|
||||||
},
|
|
||||||
{ __LINE__, MOVEGEN | MOVEDO | PERFT,
|
{ __LINE__, MOVEGEN | MOVEDO | PERFT,
|
||||||
"illegal black e.p.",
|
"illegal black e.p.",
|
||||||
"8/8/2B5/8/3Pp3/5k2/8/3K4 b - d3 0 1",
|
"8/8/2B5/8/3Pp3/5k2/8/3K4 b - d3 0 1",
|
||||||
@@ -382,7 +387,18 @@ struct fentest {
|
|||||||
"Stalemate & Checkmate",
|
"Stalemate & Checkmate",
|
||||||
"8/8/2k5/5q2/5n2/8/5K2/8 b - - 0 1"
|
"8/8/2k5/5q2/5n2/8/5K2/8 b - - 0 1"
|
||||||
},
|
},
|
||||||
|
{ __LINE__, MOVEDO | PERFT,
|
||||||
|
"simple movedo/undo: only 2 W knights",
|
||||||
|
"8/1k6/8/8/8/8/6K1/1NN5 w - - 0 1"
|
||||||
|
},
|
||||||
|
{ __LINE__, MOVEDO | PERFT,
|
||||||
|
"simple movedo/undo: only 2 W knights",
|
||||||
|
"8/1k6/8/8/8/8/6K1/1NN5 w - - 0 1"
|
||||||
|
},
|
||||||
|
{ __LINE__, MOVEDO | PERFT,
|
||||||
|
"simple movedo/undo: only 2 W knights",
|
||||||
|
"5n2/1k6/8/8/5K2/8/P7/1N6 w - - 0 1"
|
||||||
|
},
|
||||||
{ __LINE__, FEN,
|
{ __LINE__, FEN,
|
||||||
"illegal EP and castle flags, fix-able by fen parser, SF crash",
|
"illegal EP and castle flags, fix-able by fen parser, SF crash",
|
||||||
"4k3/8/8/8/7B/8/8/4K3 w KQkq e6 0 1"
|
"4k3/8/8/8/7B/8/8/4K3 w KQkq e6 0 1"
|
||||||
@@ -399,18 +415,6 @@ struct fentest {
|
|||||||
"illegal, SF crash",
|
"illegal, SF crash",
|
||||||
"2r1k3/3P4/8/8/8/8/8/4K3 w - - 0 1"
|
"2r1k3/3P4/8/8/8/8/8/4K3 w - - 0 1"
|
||||||
},
|
},
|
||||||
{ __LINE__, MOVEDO | PERFT,
|
|
||||||
"simple movedo/undo: only 2 W knights",
|
|
||||||
"8/1k6/8/8/8/8/6K1/1NN5 w - - 0 1"
|
|
||||||
},
|
|
||||||
{ __LINE__, MOVEDO | PERFT,
|
|
||||||
"simple movedo/undo: only 2 W knights",
|
|
||||||
"8/1k6/8/8/8/8/6K1/1NN5 w - - 0 1"
|
|
||||||
},
|
|
||||||
{ __LINE__, MOVEDO | PERFT,
|
|
||||||
"simple movedo/undo: only 2 W knights",
|
|
||||||
"5n2/1k6/8/8/5K2/8/P7/1N6 w - - 0 1"
|
|
||||||
},
|
|
||||||
{ __LINE__, 0, NULL, NULL }
|
{ __LINE__, 0, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -43,28 +43,33 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pos->checkers = pos_checkers(pos, pos->turn);
|
||||||
|
pos_set_pinners_blockers(pos);
|
||||||
|
|
||||||
pos_gen_pseudomoves(pos, &pseudo);
|
pos_gen_pseudomoves(pos, &pseudo);
|
||||||
savepos = pos_dup(pos);
|
savepos = pos_dup(pos);
|
||||||
|
|
||||||
|
state_t state = pos->state;
|
||||||
int tmp = 0, j = 0;
|
int tmp = 0, j = 0;
|
||||||
while ((move = pos_next_legal(pos, &pseudo, &tmp)) != MOVE_NONE) {
|
while ((move = pos_next_legal(pos, &pseudo, &tmp)) != MOVE_NONE) {
|
||||||
state_t state;
|
|
||||||
move_str(movebuf, move, 0);
|
|
||||||
//pos_print(pos);
|
//pos_print(pos);
|
||||||
//printf("i=%d j=%d turn=%d move=[%s]\n", i, j, pos->turn,
|
//printf("i=%d j=%d turn=%d move=[%s]\n", i, j, pos->turn,
|
||||||
// move_str(movebuf, move, 0));
|
// move_str(movebuf, move, 0));
|
||||||
//move_p
|
//move_p
|
||||||
move_do(pos, move, &state);
|
move_do(pos, move);
|
||||||
//pos_print(pos);
|
//pos_print(pos);
|
||||||
//fflush(stdout);
|
//fflush(stdout);
|
||||||
if (pos_check(pos, false)) {
|
if (!pos_ok(pos, false)) {
|
||||||
printf("*** fen %d move %d [%s] invalid position after move_do\n",
|
printf("*** fen %d move %d [%s] invalid position after move_do\n",
|
||||||
test_line, j, movebuf);
|
test_line, j, movebuf);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//printf("%d/%d move_do check ok\n", i, j);
|
//printf("%d/%d move_do check ok\n", i, j);
|
||||||
move_undo(pos, move, &state);
|
move_undo(pos, move);
|
||||||
if (pos_check(pos, false)) {
|
pos->state = state;
|
||||||
|
if (!pos_ok(pos, false)) {
|
||||||
printf("*** fen %d move %d [%s] invalid position after move_undo\n",
|
printf("*** fen %d move %d [%s] invalid position after move_undo\n",
|
||||||
test_line, j, movebuf);
|
test_line, j, movebuf);
|
||||||
exit(0);
|
exit(0);
|
||||||
|
@@ -259,26 +259,41 @@ int main(int __unused ac, __unused char**av)
|
|||||||
#define NANOSEC 1000000000 /* nano sec in sec */
|
#define NANOSEC 1000000000 /* nano sec in sec */
|
||||||
#define MILLISEC 1000000 /* milli sec in sec */
|
#define MILLISEC 1000000 /* milli sec in sec */
|
||||||
|
|
||||||
struct timespec ts1, ts2;
|
|
||||||
clock_gettime(CLOCK_MONOTONIC_RAW, &ts1);
|
|
||||||
|
|
||||||
my_count = perft(pos, depth, 1);
|
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC_RAW, &ts2);
|
|
||||||
|
|
||||||
// 1 sec = 1000 millisec
|
// 1 sec = 1000 millisec
|
||||||
// 1 millisec = 1000 microsec
|
// 1 millisec = 1000 microsec
|
||||||
// 1 microsec = 1000 nanosec
|
// 1 microsec = 1000 nanosec
|
||||||
// milli = sec * 1000 + nanosec / 1000000
|
// milli = sec * 1000 + nanosec / 1000000
|
||||||
s64 microsecs = ((s64)ts2.tv_sec - (s64)ts1.tv_sec) * 1000000l
|
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 ;
|
+ ((s64)ts2.tv_nsec - (s64)ts1.tv_nsec) / 1000l ;
|
||||||
if (sf_count == my_count) {
|
if (sf_count == my_count) {
|
||||||
printf("OK : fen line=%03d \"%s\" perft=%lu in %'ldms (LPS: %'lu)\n",
|
printf("pt1 OK : line=%03d perft=%lu ms=%'ldms lps=%'lu \"%s\"\n",
|
||||||
test_line, fen, my_count, microsecs/1000l,
|
test_line, my_count, microsecs/1000l,
|
||||||
my_count*1000000l/microsecs);
|
my_count*1000000l/microsecs, fen);
|
||||||
} else {
|
} else {
|
||||||
printf("ERR: fen line=%03d [%s] sf=%lu me=%lu\n",
|
printf("pt1 ERR: line=%03d sf=%lu me=%lu \"%s\"\n",
|
||||||
test_line, fen, sf_count, my_count);
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
pos_del(savepos);
|
pos_del(savepos);
|
||||||
pos_del(pos);
|
pos_del(pos);
|
||||||
|
Reference in New Issue
Block a user