6 Commits

7 changed files with 108 additions and 100 deletions

View File

@@ -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))

View File

@@ -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);

View File

@@ -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];

View File

@@ -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
@@ -230,22 +230,67 @@ 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);
return moves; return 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_pseudomoves() - generate position pseudo-legal moves * pos_gen_pseudomoves() - generate position pseudo-legal moves
* @pos: position * @pos: position
@@ -289,12 +334,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 +380,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 +402,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 +423,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 +477,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 +494,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,20 +507,6 @@ 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
*/ */

View File

@@ -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)

View File

@@ -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)
@@ -353,14 +333,13 @@ bitboard_t pos_king_blockers(const pos_t *pos, const color_t color, const bitboa
* *
* @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;
/* 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 */
@@ -396,7 +375,8 @@ bool pos_ok(__unused const pos_t *pos, __unused const bool strict)
/* 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);
return error? false: true; return error? false: true;
} }

View File

@@ -52,8 +52,7 @@ u64 perft(pos_t *pos, int depth, int ply)
if (depth == 0) if (depth == 0)
return 1; return 1;
pseudo.nmoves = 0; pseudo.nmoves = 0;
pos->checkers = pos_checkers(pos, pos->turn); pos_set_checkers_pinners_blockers(pos);
pos_set_pinners_blockers(pos);
state = pos->state; state = pos->state;
pos_gen_pseudomoves(pos, &pseudo); pos_gen_pseudomoves(pos, &pseudo);