sq_attackers() + others (see dedails). Ready for move do/undo ?
- add many "const" in func parameters - attack.c: sq_attackers() - move print_board_raw from position.c to to board.c - move some fen_check() tests to pos_check() - add REL_RANK() macro. TODO: add one more for bitboards - fen.c: more tests for FEN validity - position.c: add pos_checkers() and pos_check() - tests: add common-test.h (for shared FEN positions access)
This commit is contained in:
56
src/attack.c
56
src/attack.c
@@ -18,9 +18,10 @@
|
||||
#include "bitboard.h"
|
||||
#include "position.h"
|
||||
#include "hyperbola-quintessence.h"
|
||||
#include "attack.h"
|
||||
|
||||
/**
|
||||
* square_attackers() - find attackers on a square
|
||||
* sq_attackers() - find attackers on a square
|
||||
* @pos: position
|
||||
* @sq: square to test
|
||||
* @c: attacker color
|
||||
@@ -36,32 +37,69 @@
|
||||
* @Return: a bitboard of attackers.
|
||||
*
|
||||
*/
|
||||
bitboard_t sq_attackers(pos_t *pos, square_t sq, color_t c)
|
||||
bitboard_t sq_attackers(const pos_t *pos, const square_t sq, const color_t c)
|
||||
{
|
||||
bitboard_t attackers = 0;
|
||||
bitboard_t from = mask(sq);
|
||||
bitboard_t sqbb = mask(sq);
|
||||
bitboard_t c_pieces = pos->bb[c][ALL_PIECES];
|
||||
bitboard_t occ = c_pieces | pos->bb[OPPONENT(c)][ALL_PIECES];
|
||||
bitboard_t to;
|
||||
color_t opp = OPPONENT(c);
|
||||
|
||||
/* pawn */
|
||||
to = pos->bb[c][PAWN];
|
||||
attackers |= pawn_push_upleft(from, c) & to;
|
||||
attackers |= pawn_push_upright(from, c) & to;
|
||||
attackers |= pawn_shift_upleft(sqbb, opp) & to;
|
||||
# ifdef DEBUG_ATTACK
|
||||
bitboard_print("sq_attackers after pawn upleft", attackers);
|
||||
# endif
|
||||
attackers |= pawn_shift_upright(sqbb, opp) & to;
|
||||
# ifdef DEBUG_ATTACK
|
||||
bitboard_print("sq_attackers pawn upright", attackers);
|
||||
# endif
|
||||
|
||||
/* knight & king */
|
||||
to = pos->bb[c][KNIGHT];
|
||||
attackers |= bb_knight_moves(c_pieces, from);
|
||||
attackers |= bb_knight_moves(to, sq);
|
||||
# ifdef DEBUG_ATTACK
|
||||
bitboard_print("sq_attackers after knight", attackers);
|
||||
# endif
|
||||
to = pos->bb[c][KING];
|
||||
attackers |= bb_king_moves(c_pieces, from);
|
||||
attackers |= bb_king_moves(to, sq);
|
||||
# ifdef DEBUG_ATTACK
|
||||
bitboard_print("sq_attackers after king", attackers);
|
||||
# endif
|
||||
|
||||
/* bishop / queen */
|
||||
to = pos->bb[c][BISHOP] | pos->bb[c][QUEEN];
|
||||
attackers |= hyperbola_bishop_moves(occ, from) & to;
|
||||
attackers |= hyperbola_bishop_moves(occ, sq) & to;
|
||||
# ifdef DEBUG_ATTACK
|
||||
bitboard_print("sq_attackers after bishop/queen", attackers);
|
||||
# endif
|
||||
|
||||
/* rook / queen */
|
||||
to = pos->bb[c][ROOK] | pos->bb[c][QUEEN];
|
||||
attackers |= hyperbola_rook_moves(occ, from) & to;
|
||||
# ifdef DEBUG_ATTACK
|
||||
bitboard_print("sq_attackers after queen", attackers);
|
||||
# endif
|
||||
attackers |= hyperbola_rook_moves(occ, sq) & to;
|
||||
# ifdef DEBUG_ATTACK
|
||||
bitboard_print("sq_attackers after rook/queen", attackers);
|
||||
# endif
|
||||
|
||||
return attackers;
|
||||
}
|
||||
|
||||
/**
|
||||
* sq_attackers() - find all attackers on a square
|
||||
* @pos: position
|
||||
* @sq: square to test
|
||||
*
|
||||
* Find all attacks on @sq. En-passant is not considered.
|
||||
* Just a wrapper over @sq_attackers().
|
||||
*
|
||||
* @Return: a bitboard of attackers.
|
||||
*/
|
||||
bitboard_t sq_attackers_all(const pos_t *pos, const square_t sq)
|
||||
{
|
||||
return sq_attackers(pos, sq, WHITE) | sq_attackers(pos, sq, BLACK);
|
||||
}
|
||||
|
@@ -17,6 +17,7 @@
|
||||
#include "chessdefs.h"
|
||||
#include "bitboard.h"
|
||||
|
||||
extern bitboard_t sq_attackers(pos_t *pos, square_t sq, color_t c);
|
||||
extern bitboard_t sq_attackers(const pos_t *pos, const square_t sq, const color_t c);
|
||||
extern bitboard_t sq_attackers_all(const pos_t *pos, const square_t sq);
|
||||
|
||||
#endif
|
||||
|
@@ -118,7 +118,9 @@ static __always_inline bitboard_t shift_nw(const bitboard_t bb)
|
||||
#define pawn_shift_up(bb, c) ((c) == WHITE ? shift_n(bb): shift_s(bb))
|
||||
#define pawn_shift_upleft(bb, c) ((c) == WHITE ? shift_nw(bb): shift_se(bb))
|
||||
#define pawn_shift_upright(bb, c) ((c) == WHITE ? shift_ne(bb): shift_sw(bb))
|
||||
/* pawn move (for single pawn) */
|
||||
/* pawn move (for single pawn) - NO SQUARE CONTROL HERE !
|
||||
* Need to make functions with control instead.
|
||||
*/
|
||||
#define pawn_push_up(sq, c) ((sq) + ((c) == WHITE ? NORTH: SOUTH))
|
||||
#define pawn_push_upleft(sq, c) ((sq) + ((c) == WHITE ? NORTH_WEST: SOUTH_EAST))
|
||||
#define pawn_push_upright(sq, c) ((sq) + ((c) == WHITE ? NORTH_EAST: SOUTH_WEST))
|
||||
|
26
src/board.c
26
src/board.c
@@ -1,4 +1,4 @@
|
||||
/* board.c - 8x8 board.
|
||||
/* board.c - 8x8 functions.
|
||||
*
|
||||
* Copyright (C) 2024 Bruno Raoult ("br")
|
||||
* Licensed under the GNU General Public License v3.0 or later.
|
||||
@@ -57,7 +57,7 @@ square_t sq_from_string(const char *sqstr)
|
||||
* board_print() - Print a board
|
||||
* @board: &board_t to print
|
||||
*/
|
||||
void board_print(piece_t *board)
|
||||
void board_print(const piece_t *board)
|
||||
{
|
||||
printf(" +---+---+---+---+---+---+---+---+\n");
|
||||
for (int rank = 7; rank >= 0; --rank) {
|
||||
@@ -82,7 +82,7 @@ void board_print(piece_t *board)
|
||||
*
|
||||
* Squares corresponding to @mask will be displayed in reverse colors.
|
||||
*/
|
||||
void board_print_mask(piece_t *board, bitboard_t mask)
|
||||
void board_print_mask(const piece_t *board, const bitboard_t mask)
|
||||
{
|
||||
// 6: blink
|
||||
# define REVERSE "\e[7m▌"
|
||||
@@ -106,3 +106,23 @@ void board_print_mask(piece_t *board, bitboard_t mask)
|
||||
}
|
||||
printf(" A B C D E F G H\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* board_print_raw - print raw (octal or FEN symbol) board
|
||||
* @bb: the bitboard
|
||||
* @type: int, 0 for octal, 1 for fen symbol
|
||||
*/
|
||||
void board_print_raw(const piece_t *board, const int type)
|
||||
{
|
||||
for (rank_t r = RANK_8; r >= RANK_1; --r) {
|
||||
for (file_t f = FILE_A; f <= FILE_H; ++f) {
|
||||
piece_t p = board[sq_make(f, r)];
|
||||
if (type) {
|
||||
printf("%s ", p == EMPTY? ".": piece_to_char_color(p));
|
||||
} else {
|
||||
printf("%02o ", p);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
@@ -65,7 +65,8 @@ static __always_inline rank_t sq_rank(square_t square)
|
||||
extern const char *sq_to_string(const square_t sq);
|
||||
extern square_t sq_from_string(const char *sq_string);
|
||||
|
||||
extern void board_print(piece_t *board);
|
||||
extern void board_print_mask(piece_t *board, bitboard_t mask);
|
||||
extern void board_print(const piece_t *board);
|
||||
extern void board_print_mask(const piece_t *board, const bitboard_t mask);
|
||||
extern void board_print_raw(const piece_t *board, const int type);
|
||||
|
||||
#endif /* _BOARD_H */
|
||||
|
@@ -16,19 +16,21 @@
|
||||
|
||||
#include "brlib.h" /* brlib types */
|
||||
|
||||
#define ONE 1ull
|
||||
#define C64(const_u64) const_u64##ULL
|
||||
#define mask(i) ( (unsigned long long) (ONE << (i)) )
|
||||
#define ONE 1ull
|
||||
#define C64(const_u64) const_u64##ULL
|
||||
#define mask(i) ( (unsigned long long) (ONE << (i)) )
|
||||
//typedef ushort board;
|
||||
|
||||
#define BOARDSIZE (8*8)
|
||||
/* from human to machine */
|
||||
#define C2FILE(c) (tolower(c) - 'a')
|
||||
#define C2RANK(c) (tolower(c) - '1')
|
||||
/* from machine to human */
|
||||
#define FILE2C(f) ((f) + 'a')
|
||||
#define RANK2C(r) ((r) + '1')
|
||||
#define BOARDSIZE (8*8)
|
||||
/* from human to machin e */
|
||||
#define C2FILE(c) (tolower(c) - 'a')
|
||||
#define C2RANK(c) (tolower(c) - '1')
|
||||
/* from machine to huma n */
|
||||
#define FILE2C(f) ((f) + 'a')
|
||||
#define RANK2C(r) ((r) + '1')
|
||||
|
||||
/* relative rank */
|
||||
#define REL_RANK(r, c) ((7 * (c)) ^ r)
|
||||
/* castle_t bits structure
|
||||
*/
|
||||
typedef enum {
|
||||
|
60
src/fen.c
60
src/fen.c
@@ -1,4 +1,4 @@
|
||||
/* fen.c - fen notation.
|
||||
/* fen.c - fen parsing/generation/test.
|
||||
*
|
||||
* Copyright (C) 2021-2024 Bruno Raoult ("br")
|
||||
* Licensed under the GNU General Public License v3.0 or later.
|
||||
@@ -22,8 +22,8 @@
|
||||
|
||||
#include "chessdefs.h"
|
||||
#include "util.h"
|
||||
#include "piece.h"
|
||||
#include "bitboard.h"
|
||||
//#include "piece.h"
|
||||
//#include "bitboard.h"
|
||||
#include "position.h"
|
||||
#include "fen.h"
|
||||
|
||||
@@ -61,19 +61,18 @@ static const char *castle_str = "KQkq";
|
||||
#define SKIP_BLANK(p) for(;isspace(*(p)); (p)++)
|
||||
|
||||
/**
|
||||
* fen_test(pos_t *pos) - test (and try to fix) fen-generated position.
|
||||
* fen_check(pos_t *pos) - test (and try to fix) fen-generated position.
|
||||
* @pos: position
|
||||
*
|
||||
* fen_test() tests the following:
|
||||
* - fatal: number of pawns > 8
|
||||
* - fatal: number of pieces > 16
|
||||
* - fatal: number of kings != 1
|
||||
* - fixable: inconsistent castle flags (if K & R are not in correct position)
|
||||
* - fixable: inconsistent en-passant square (turn, bad pawn position)
|
||||
* Test and fix the following:
|
||||
* - inconsistent castle flags (if K & R are not in correct position)
|
||||
* - inconsistent en-passant square (turn, bad pawn position)
|
||||
*
|
||||
* pos_check() is also called, leading to fatal errors if something is wrong.
|
||||
*
|
||||
* @return: 0 if OK, 1 if OK after fix, -1 if fatal issue.
|
||||
*/
|
||||
static int fen_test(pos_t *pos)
|
||||
static int fen_check(pos_t *pos)
|
||||
{
|
||||
char *colstr[2] = { "white", "black"};
|
||||
int error = 0, warning = 0;
|
||||
@@ -82,24 +81,25 @@ static int fen_test(pos_t *pos)
|
||||
if (pos->en_passant != SQUARE_NONE) {
|
||||
rank_t eprank = sq_rank(pos->en_passant);
|
||||
file_t epfile = sq_file(pos->en_passant);
|
||||
rank_t rank5 = pos->turn == WHITE? RANK_5: RANK_4;
|
||||
rank_t rank6 = pos->turn == WHITE? RANK_6: RANK_3;
|
||||
rank_t rank7 = pos->turn == WHITE? RANK_7: RANK_2;
|
||||
rank_t rank5 = REL_RANK(RANK_5, pos->turn);
|
||||
rank_t rank6 = REL_RANK(RANK_6, pos->turn);
|
||||
rank_t rank7 = REL_RANK(RANK_7, pos->turn);
|
||||
piece_t pawn = pos->turn == WHITE? B_PAWN: W_PAWN;
|
||||
if (warn(eprank != rank6 ||
|
||||
pos->board[sq_make(epfile, rank5)] != pawn ||
|
||||
pos->board[sq_make(epfile, rank6)] != EMPTY ||
|
||||
pos->board[sq_make(epfile, rank7)] != EMPTY,
|
||||
"fen warn: wrong en-passant settings. (fixed)\n")) {
|
||||
# ifdef DEBUG_FEN
|
||||
printf("ep5=%o ep6=%o ep7=%o\n", sq_make(epfile, rank5),
|
||||
sq_make(epfile, rank6), sq_make(epfile, rank6));
|
||||
sq_make(epfile, rank6), sq_make(epfile, rank7));
|
||||
# endif
|
||||
warning++;
|
||||
pos->en_passant = SQUARE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
for (int color = WHITE; color <= BLACK; ++color) {
|
||||
int n;
|
||||
rank_t rank1 = color == WHITE? RANK_1: RANK_8;
|
||||
|
||||
/* castling */
|
||||
@@ -130,18 +130,12 @@ static int fen_test(pos_t *pos)
|
||||
}
|
||||
}
|
||||
|
||||
/* piece, pawn, anf king count */
|
||||
n = popcount64(pos->bb[color][PAWN]);
|
||||
error += warn(n > 8,
|
||||
"fen err: %s has %d pawns\n", colstr[color], n);
|
||||
n = popcount64(pos->bb[color][KING]);
|
||||
error += warn(n != 1,
|
||||
"fen err: %s has %d kings\n", colstr[color], n);
|
||||
n = popcount64(pos->bb[color][ALL_PIECES]);
|
||||
error += warn(n > 16,
|
||||
"fen err: %s has %d pieces\n", colstr[color], n);
|
||||
}
|
||||
return error ? -1: warning ? 1: 0;
|
||||
if (!(error = pos_check(pos, 0))) {
|
||||
/* TODO: Should it really be here ? */
|
||||
pos->checkers = pos_checkers(pos, pos->turn);
|
||||
}
|
||||
return error ? -1: warning;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -259,13 +253,13 @@ end:
|
||||
err_line, err_pos, err_char, err_char)) {
|
||||
return NULL;
|
||||
}
|
||||
if (fen_test(&tmppos) >= 0) {
|
||||
if (!pos)
|
||||
pos = pos_new();
|
||||
*pos = tmppos;
|
||||
}
|
||||
if (fen_check(&tmppos) < 0)
|
||||
return NULL;
|
||||
if (!pos)
|
||||
pos = pos_new();
|
||||
*pos = tmppos;
|
||||
# ifdef DEBUG_FEN
|
||||
pos_print_board_raw(&tmppos, 1);
|
||||
pos_print_raw(&tmppos, 1);
|
||||
# endif
|
||||
|
||||
return pos;
|
||||
|
@@ -14,7 +14,7 @@
|
||||
#ifndef FEN_H
|
||||
#define FEN_H
|
||||
|
||||
#include "position.h"
|
||||
#include "chessdefs.h"
|
||||
|
||||
#define FENSTRLEN 92 /* secure FEN string size */
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* movegen.c - move generation
|
||||
/* move-gen.c - move generation
|
||||
*
|
||||
* Copyright (C) 2024 Bruno Raoult ("br")
|
||||
* Licensed under the GNU General Public License v3.0 or later.
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "position.h"
|
||||
#include "move.h"
|
||||
#include "hyperbola-quintessence.h"
|
||||
#include "movegen.h"
|
||||
#include "move-gen.h"
|
||||
|
||||
|
||||
/**
|
||||
@@ -111,8 +111,8 @@ int gen_all_pseudomoves(pos_t *pos)
|
||||
}
|
||||
|
||||
/* pawn: relative rank and files */
|
||||
bitboard_t rel_rank7 = (me == WHITE ? RANK_7bb : RANK_2bb);
|
||||
bitboard_t rel_rank3 = (me == WHITE ? RANK_3bb : RANK_6bb);
|
||||
bitboard_t rel_rank7 = me == WHITE ? RANK_7bb : RANK_2bb;
|
||||
bitboard_t rel_rank3 = me == WHITE ? RANK_3bb : RANK_6bb;
|
||||
//bitboard_t rel_filea = (me == WHITE ? FILE_Abb : FILE_Hbb);
|
||||
//bitboard_t rel_fileh = (me == WHITE ? FILE_Hbb : FILE_Abb);
|
||||
int en_passant = pos->en_passant == SQUARE_NONE? 0: pos->en_passant;
|
@@ -1,4 +1,4 @@
|
||||
/* movegen.h - move generation
|
||||
/* move-gen.h - move generation
|
||||
*
|
||||
* Copyright (C) 2024 Bruno Raoult ("br")
|
||||
* Licensed under the GNU General Public License v3.0 or later.
|
@@ -115,7 +115,7 @@ void moves_print(pos_t *pos, __unused int flags)
|
||||
}
|
||||
|
||||
|
||||
static int _moves_comp_square(const void *p1, const void *p2)
|
||||
static int _moves_cmp_bysquare(const void *p1, const void *p2)
|
||||
{
|
||||
move_t m1 = *(move_t *)p1;
|
||||
move_t m2 = *(move_t *)p2;
|
||||
@@ -129,7 +129,7 @@ static int _moves_comp_square(const void *p1, const void *p2)
|
||||
/* f1 == f2 */
|
||||
if (t1 < t2) return -1;
|
||||
if (t1 > t2) return 1;
|
||||
return 0; /* DUP BUG ! */
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* move_sort_by_sq() - sort moves by from/to squares ascending
|
||||
@@ -139,7 +139,7 @@ static int _moves_comp_square(const void *p1, const void *p2)
|
||||
*/
|
||||
void move_sort_by_sq(pos_t *pos)
|
||||
{
|
||||
qsort(pos->moves.move, pos->moves.nmoves, sizeof(move_t), _moves_comp_square);
|
||||
qsort(pos->moves.move, pos->moves.nmoves, sizeof(move_t), _moves_cmp_bysquare);
|
||||
}
|
||||
|
||||
/*
|
||||
|
352
src/position.c
352
src/position.c
@@ -28,18 +28,7 @@
|
||||
#include "piece.h"
|
||||
#include "util.h"
|
||||
#include "board.h"
|
||||
|
||||
/****************************************************
|
||||
* #define BYTE_PRINT "%c%c%c%c%c%c%c%c" *
|
||||
* #define BYTE2BIN(b) ((b) & 0x01 ? '1' : '0'), \ *
|
||||
* ((b) & 0x02 ? '1' : '0'), \ *
|
||||
* ((b) & 0x04 ? '1' : '0'), \ *
|
||||
* ((b) & 0x08 ? '1' : '0'), \ *
|
||||
* ((b) & 0x10 ? '1' : '0'), \ *
|
||||
* ((b) & 0x20 ? '1' : '0'), \ *
|
||||
* ((b) & 0x40 ? '1' : '0'), \ *
|
||||
* ((b) & 0x80 ? '1' : '0') *
|
||||
****************************************************/
|
||||
#include "attack.h"
|
||||
|
||||
/**
|
||||
* pos_new() - allocate a new position
|
||||
@@ -71,7 +60,7 @@ pos_t *pos_new(void)
|
||||
*
|
||||
* TODO: merge with pos_new - NULL for init, non null for duplicate
|
||||
*/
|
||||
pos_t *pos_dup(pos_t *pos)
|
||||
pos_t *pos_dup(const pos_t *pos)
|
||||
{
|
||||
pos_t *newpos = safe_malloc(sizeof(pos_t));
|
||||
|
||||
@@ -104,82 +93,143 @@ pos_t *pos_clear(pos_t *pos)
|
||||
# ifdef DEBUG_POS
|
||||
printf("size(pos_board=%lu elt=%lu\n", sizeof(pos->board), sizeof(int));
|
||||
# endif
|
||||
//for (square square = A1; square <= H8; ++square)
|
||||
// pos->board[square] = EMPTY;
|
||||
|
||||
SET_WHITE(pos->turn);
|
||||
pos->node_count = 0;
|
||||
pos->turn = 0;
|
||||
pos->turn = WHITE;
|
||||
pos->clock_50 = 0;
|
||||
pos->plycount = 0;
|
||||
pos->en_passant = SQUARE_NONE;
|
||||
pos->castle = 0;
|
||||
memset(pos->board, EMPTY, sizeof(pos->board));
|
||||
//pos->curmove = 0;
|
||||
//pos->eval = 0;
|
||||
//pos->occupied[WHITE] = 0;
|
||||
//pos->occupied[BLACK] = 0;
|
||||
|
||||
for (color_t color = WHITE; color <= BLACK; ++color) {
|
||||
for (piece_type_t piece = 0; piece <= KING; ++piece)
|
||||
pos->bb[color][piece] = 0;
|
||||
pos->controlled[WHITE] = 0;
|
||||
pos->controlled[BLACK] = 0;
|
||||
pos->controlled[color] = 0;
|
||||
pos->king[color] = SQUARE_NONE;
|
||||
}
|
||||
pos->moves.curmove = pos->moves.nmoves = 0;
|
||||
//pos->mobility[WHITE] = 0;
|
||||
//pos->mobility[BLACK] = 0;
|
||||
//pos->moves_generated = false;
|
||||
//pos->moves_counted = false;
|
||||
/* remove pieces / moves */
|
||||
//pieces_del(pos, WHITE);
|
||||
//pieces_del(pos, BLACK);
|
||||
//moves_del(pos);
|
||||
|
||||
for (square_t sq = A1; sq <= H8; ++sq)
|
||||
pos->board[sq] = EMPTY;
|
||||
pos->moves.curmove = 0;
|
||||
pos->moves.nmoves = 0;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* pos_checkers() - find all checkers on a king.
|
||||
* @pos: &position
|
||||
* @color: king color
|
||||
*
|
||||
* Get a bitboard of all checkers on @color king.
|
||||
* Just a wrapper over @sq_attackers().
|
||||
*
|
||||
* @return: a bitboard of attackers.
|
||||
*/
|
||||
bitboard_t pos_checkers(const pos_t *pos, const color_t color)
|
||||
{
|
||||
return sq_attackers(pos, pos->king[color], OPPONENT(color));
|
||||
}
|
||||
|
||||
/**
|
||||
* pos_checkers2str() - convert checkers to string.
|
||||
* @pos: &position
|
||||
* @str: destination string (should be at least 2*3 + 1 = 7 length)
|
||||
*
|
||||
* @return: The string.
|
||||
*/
|
||||
char *pos_checkers2str(const pos_t *pos, char *str)
|
||||
{
|
||||
int sq, tmp;
|
||||
char *p = str;
|
||||
bit_for_each64(sq, tmp, pos->checkers) {
|
||||
const char *sqstr = sq_to_string(sq);
|
||||
*p++ = sqstr[0];
|
||||
*p++ = sqstr[1];
|
||||
*p++ = ' ';
|
||||
}
|
||||
*p = 0;
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* pos_check() - extensive position consistenci check.
|
||||
* @pos: &position
|
||||
* @strict: if not zero, call bug_on() on any error.
|
||||
*
|
||||
* Check (hopefully) if position is valid:
|
||||
* - pawns on first or 8th rank
|
||||
* - number of pawns per color > 8
|
||||
* - total number of pieces per color > 16 or zero
|
||||
* - number of kings per color != 1
|
||||
* - discrepancy between bitboards per piece and ALL_PIECES per color
|
||||
* - discrepancy between bitboards and board
|
||||
* - side-to-move already checking opponent king.
|
||||
*
|
||||
* In case of errors, and @abort is true, @bug_on() is called, and program will
|
||||
* be terminated.
|
||||
* This function should be called with @abort == 0 during initialization phase
|
||||
* (eg after fen parsing), and with @abort != 0 otherwise (as we have some data
|
||||
* corruption).
|
||||
*
|
||||
* TODO: add more checks
|
||||
* - en-prise king for side to move.
|
||||
*
|
||||
* @Return: 0 if no error detected
|
||||
* the number of detected error if @abort == 0.
|
||||
* this function does not return if @abort != 0 and errors are found.
|
||||
*/
|
||||
int pos_check(const pos_t *pos, const int fatal)
|
||||
{
|
||||
int n, count = 0, bbcount = 0, error = 0;
|
||||
|
||||
/* pawns on 1st ot 8th rank */
|
||||
n = popcount64((pos->bb[WHITE][PAWN] | pos->bb[BLACK][PAWN]) &
|
||||
(RANK_1bb | RANK_8bb));
|
||||
error += warn_on(n != 0);
|
||||
|
||||
for (color_t color = WHITE; color <= BLACK; ++color) {
|
||||
/* pawn count */
|
||||
n = popcount64(pos->bb[color][PAWN]);
|
||||
error += warn_on(n > 8);
|
||||
/* king count */
|
||||
n = popcount64(pos->bb[color][KING]);
|
||||
error += warn_on(n != 1);
|
||||
/* pieces count */
|
||||
n = popcount64(pos->bb[color][ALL_PIECES]);
|
||||
error += warn_on(n == 0 || n > 16);
|
||||
bbcount += n;
|
||||
}
|
||||
for (square_t sq = 0; sq < 64; ++sq) {
|
||||
piece_t piece = pos->board[sq];
|
||||
bitboard_t match;
|
||||
if (piece == EMPTY)
|
||||
continue;
|
||||
color_t c = COLOR(piece);
|
||||
piece_type_t p = PIECE(piece);
|
||||
match = pos->bb[c][p] & mask(sq);
|
||||
error += warn_on(!match);
|
||||
count++;
|
||||
}
|
||||
/* occupied occupation is different from bitboards */
|
||||
error += warn_on(count != bbcount);
|
||||
/* is color to play in check ? */
|
||||
error += warn_on(pos_checkers(pos, OPPONENT(pos->turn)));
|
||||
|
||||
bug_on(fatal && error);
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* pos_print() - Print position and fen on stdout.
|
||||
* @pos: &position
|
||||
*/
|
||||
void pos_print(pos_t *pos)
|
||||
void pos_print(const pos_t *pos)
|
||||
{
|
||||
//int rank, file;
|
||||
//piece_t *board = pos->board;
|
||||
char fen[92];
|
||||
char str[92];
|
||||
|
||||
//piece_list_t *wk = list_first_entry(&pos->pieces[WHITE], piece_list_t, list),
|
||||
// *bk = list_first_entry(&pos->pieces[BLACK], piece_list_t, list);
|
||||
board_print(pos->board);
|
||||
|
||||
/*
|
||||
* printf(" +---+---+---+---+---+---+---+---+\n");
|
||||
* for (rank = 7; rank >= 0; --rank) {
|
||||
* printf("%c |", rank + '1');
|
||||
* for (file = 0; file < 8; ++file) {
|
||||
* pc = board[sq_make(file, rank)];
|
||||
* printf(" %s |", pc? piece_to_sym_color(pc): " ");
|
||||
* }
|
||||
* printf("\n +---+---+---+---+---+---+---+---+\n");
|
||||
* }
|
||||
* printf(" A B C D E F G H\n");
|
||||
*/
|
||||
printf("fen %s\n", pos2fen(pos, fen));
|
||||
//printf("Turn: %s.\n", IS_WHITE(pos->turn) ? "white" : "black");
|
||||
/*
|
||||
* printf("Kings: W:%c%c B:%c%c\n",
|
||||
* FILE2C(F88(wk->square)),
|
||||
* RANK2C(R88(wk->square)),
|
||||
* FILE2C(F88(bk->square)),
|
||||
* RANK2C(R88(bk->square)));
|
||||
*/
|
||||
//printf("plies=%d clock50=%d\n", pos->plycount, pos->clock_50);
|
||||
//printf("Current move = %d\n", pos->curmove);
|
||||
//printf("Squares controlled: W:%d B:%d\n", popcount64(pos->controlled[WHITE]),
|
||||
// popcount64(pos->controlled[BLACK]));
|
||||
//printf("Mobility: W:%u B:%u\n", pos->mobility[WHITE],
|
||||
// pos->mobility[BLACK]);
|
||||
printf("fen %s\n", pos2fen(pos, str));
|
||||
printf("checkers %s\n", pos_checkers2str(pos, str));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -187,50 +237,30 @@ void pos_print(pos_t *pos)
|
||||
* @pos: &position
|
||||
* @mask: mask of highlighted squares.
|
||||
*/
|
||||
void pos_print_mask(pos_t *pos, bitboard_t mask)
|
||||
void pos_print_mask(const pos_t *pos, const bitboard_t mask)
|
||||
{
|
||||
//int rank, file;
|
||||
//piece_t pc, *board = pos->board;
|
||||
char fen[92];
|
||||
|
||||
//piece_list_t *wk = list_first_entry(&pos->pieces[WHITE], piece_list_t, list),
|
||||
// *bk = list_first_entry(&pos->pieces[BLACK], piece_list_t, list);
|
||||
board_print_mask(pos->board, mask);
|
||||
|
||||
/*
|
||||
* printf(" +---+---+---+---+---+---+---+---+\n");
|
||||
* for (rank = 7; rank >= 0; --rank) {
|
||||
* printf("%c |", rank + '1');
|
||||
* for (file = 0; file < 8; ++file) {
|
||||
* pc = board[sq_make(file, rank)];
|
||||
* printf(" %s |", pc? piece_to_sym_color(pc): " ");
|
||||
* }
|
||||
* printf("\n +---+---+---+---+---+---+---+---+\n");
|
||||
* }
|
||||
* printf(" A B C D E F G H\n");
|
||||
*/
|
||||
printf("fen %s\n", pos2fen(pos, fen));
|
||||
//printf("Turn: %s.\n", IS_WHITE(pos->turn) ? "white" : "black");
|
||||
/*
|
||||
* printf("Kings: W:%c%c B:%c%c\n",
|
||||
* FILE2C(F88(wk->square)),
|
||||
* RANK2C(R88(wk->square)),
|
||||
* FILE2C(F88(bk->square)),
|
||||
* RANK2C(R88(bk->square)));
|
||||
*/
|
||||
//printf("plies=%d clock50=%d\n", pos->plycount, pos->clock_50);
|
||||
//printf("Current move = %d\n", pos->curmove);
|
||||
//printf("Squares controlled: W:%d B:%d\n", popcount64(pos->controlled[WHITE]),
|
||||
// popcount64(pos->controlled[BLACK]));
|
||||
//printf("Mobility: W:%u B:%u\n", pos->mobility[WHITE],
|
||||
// pos->mobility[BLACK]);
|
||||
}
|
||||
|
||||
/**
|
||||
* pos_pieces_print() - Print position pieces
|
||||
* pos_print_board_raw - print simple position board (octal/FEN symbol values)
|
||||
* @bb: the bitboard
|
||||
* @type: int, 0 for octal, 1 for fen symbol
|
||||
*/
|
||||
void pos_print_raw(const pos_t *pos, const int type)
|
||||
{
|
||||
board_print_raw(pos->board, type);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* pos_print_pieces() - Print position pieces
|
||||
* @pos: &position
|
||||
*/
|
||||
void pos_pieces_print(pos_t *pos)
|
||||
void pos_print_pieces(const pos_t *pos)
|
||||
{
|
||||
int bit, count, cur;
|
||||
char *pname;
|
||||
@@ -254,123 +284,5 @@ void pos_pieces_print(pos_t *pos)
|
||||
printf(" ");
|
||||
}
|
||||
printf("\n");
|
||||
//printf("White pieces (%d): \t", popcount64(pos->occupied[WHITE]));
|
||||
//piece_list_print(&pos->pieces[WHITE]);
|
||||
//printf("Black pieces (%d): \t", popcount64(pos->occupied[BLACK]));
|
||||
//piece_list_print(&pos->pieces[BLACK]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
inline void bitboard_print2_raw(bitboard_t bb1, bitboard_t bb2, char *title)
|
||||
{
|
||||
int i;
|
||||
printf("%s%s", title? title: "", title? ":\n": "");
|
||||
|
||||
printf("\tW: %#018lx\tB: %#018lx\n", bb1, bb2);
|
||||
for (i=56; i>=0; i-=8)
|
||||
printf("\t"BYTE_PRINT"\t\t"BYTE_PRINT"\n",
|
||||
BYTE2BIN(bb1>>i),
|
||||
BYTE2BIN(bb2>>i));
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* pos_print_board_raw - print simple position board (octal/FEN symbol values)
|
||||
* @bb: the bitboard
|
||||
* @type: int, 0 for octal, 1 for fen symbol
|
||||
*/
|
||||
void pos_print_board_raw(const pos_t *pos, int type)
|
||||
{
|
||||
if (type == 0) {
|
||||
for (rank_t r = RANK_8; r >= RANK_1; --r) {
|
||||
for (file_t f = FILE_A; f <= FILE_H; ++f)
|
||||
printf("%02o ", pos->board[sq_make(f, r)]);
|
||||
printf(" \n");
|
||||
}
|
||||
} else {
|
||||
for (rank_t r = RANK_8; r >= RANK_1; --r) {
|
||||
for (file_t f = FILE_A; f <= FILE_H; ++f) {
|
||||
square_t sq = sq_make(f, r);
|
||||
if (pos->board[sq] == EMPTY)
|
||||
printf(". ");
|
||||
else
|
||||
printf("%s ", piece_to_char_color(pos->board[sq]));
|
||||
}
|
||||
printf(" \n");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* pos_bitboards_print() - Print position bitboards
|
||||
* @pos: &position
|
||||
*/
|
||||
//void pos_bitboards_print(pos_t *pos)
|
||||
//{
|
||||
// printf("Bitboards occupied :\n");
|
||||
// bitboard_print2(pos->occupied[WHITE], pos->occupied[BLACK]);
|
||||
// printf("Bitboards controlled :\n");
|
||||
// bitboard_print2(pos->controlled[WHITE], pos->controlled[BLACK]);
|
||||
//
|
||||
//}
|
||||
|
||||
/**
|
||||
* pos_check() - extensive position consistenci check.
|
||||
* @pos: &position
|
||||
*/
|
||||
/*
|
||||
* void pos_check(position *pos)
|
||||
* {
|
||||
* int rank, file;
|
||||
* piece_t piece;
|
||||
* board_t *board = pos->board;
|
||||
*
|
||||
* /\* check that board and bitboard reflect same information *\/
|
||||
* for (rank = 7; rank >= 0; --rank) {
|
||||
* for (file = 0; file < 8; ++file) {
|
||||
* piece_list_t *ppiece;
|
||||
* printf("checking %c%c ", file+'a', rank+'1');
|
||||
*
|
||||
* piece = board[SQ88(file, rank)].piece;
|
||||
* ppiece= board[SQ88(file, rank)].s_piece;
|
||||
* printf("piece=%s ", P_CSYM(piece));
|
||||
* if (ppiece)
|
||||
* printf("ppiece=%s/sq=%#x ", P_CSYM(ppiece->piece), ppiece->square);
|
||||
* switch(PIECE(piece)) {
|
||||
* case PAWN:
|
||||
* printf("pawn" );
|
||||
* break;
|
||||
* case KNIGHT:
|
||||
* printf("knight ");
|
||||
* break;
|
||||
* case BISHOP:
|
||||
* printf("bishop ");
|
||||
* break;
|
||||
* case ROOK:
|
||||
* printf("rook ");
|
||||
* break;
|
||||
* case QUEEN:
|
||||
* printf("queen ");
|
||||
* break;
|
||||
* case KING:
|
||||
* printf("king ");
|
||||
* break;
|
||||
* }
|
||||
* printf("\n");
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
|
||||
/*
|
||||
* void pos_del(pos_t *pos)
|
||||
* {
|
||||
* pieces_del(pos, WHITE);
|
||||
* pieces_del(pos, BLACK);
|
||||
* moves_del(pos);
|
||||
* pool_add(pos_pool, pos);
|
||||
* }
|
||||
*/
|
||||
|
@@ -35,22 +35,11 @@ typedef struct __pos_s {
|
||||
square_t en_passant;
|
||||
castle_rights_t castle;
|
||||
|
||||
//eval_t eval;
|
||||
//int check[2];
|
||||
//int eval_simple_phase;
|
||||
//eval_t eval_simple;
|
||||
//move_t *bestmove;
|
||||
//bool moves_generated;
|
||||
//bool moves_counted;
|
||||
|
||||
bitboard_t bb[2][PIECE_TYPE_MAX]; /* bb[0][PAWN], bb[1][ALL_PIECES] */
|
||||
bitboard_t controlled[2];
|
||||
//u16 mobility[2];
|
||||
//struct list_head pieces[2]; /* pieces list, King is first */
|
||||
//struct list_head moves[2];
|
||||
bitboard_t controlled[2]; /* unsure */
|
||||
bitboard_t checkers; /* opponent checkers */
|
||||
piece_t board[BOARDSIZE];
|
||||
movelist_t moves;
|
||||
//int nmoves;
|
||||
} pos_t;
|
||||
|
||||
/**
|
||||
@@ -93,18 +82,20 @@ static inline void pos_clr_sq(pos_t *pos, square_t square)
|
||||
//void bitboard_print2(bitboard_t bb1, bitboard_t bb2, char *title);
|
||||
|
||||
extern pos_t *pos_new();
|
||||
extern pos_t *pos_dup(pos_t *pos);
|
||||
extern pos_t *pos_dup(const pos_t *pos);
|
||||
extern void pos_del(pos_t *pos);
|
||||
extern pos_t *pos_clear(pos_t *pos);
|
||||
|
||||
extern void pos_print(pos_t *pos);
|
||||
extern void pos_print_mask(pos_t *pos, bitboard_t mask);
|
||||
extern void pos_pieces_print(pos_t *pos);
|
||||
extern bitboard_t pos_checkers(const pos_t *pos, const color_t color);
|
||||
extern char *pos_checkers2str(const pos_t *pos, char *str);
|
||||
|
||||
extern void pos_print_board_raw(const pos_t *pos, int type);
|
||||
extern int pos_check(const pos_t *pos, const int strict);
|
||||
|
||||
//extern pos_t *pos_startpos(pos_t *pos);
|
||||
extern void pos_print(const pos_t *pos);
|
||||
extern void pos_print_mask(const pos_t *pos, const bitboard_t mask);
|
||||
extern void pos_print_raw(const pos_t *pos, const int type);
|
||||
|
||||
extern void pos_print_pieces(const pos_t *pos);
|
||||
|
||||
//void pos_check(position *pos);
|
||||
|
||||
#endif /* POSITION_H */
|
||||
|
Reference in New Issue
Block a user