diff --git a/src/position.c-move-to-temp-migration-bitboard__position.c b/src/position.c-move-to-temp-migration-bitboard__position.c new file mode 100644 index 0000000..051d174 --- /dev/null +++ b/src/position.c-move-to-temp-migration-bitboard__position.c @@ -0,0 +1,323 @@ +/* position.c - position management. + * + * Copyright (C) 2021 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 . + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include +#include +#include +#include +#include + +#include "chessdefs.h" +#include "position.h" +#include "move.h" +#include "fen.h" +#include "piece.h" +#include "eval.h" + +static pool_t *pos_pool; + +#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') + +inline void bitboard_print(bitboard_t bb) +{ + int i; + printf("%#018lx\n", bb); + for (i=56; i>=0; i-=8) + printf("\t"BYTE_PRINT"\n", + BYTE2BIN(bb>>i)); +} + +inline void bitboard_print2(bitboard_t bb1, bitboard_t bb2) +{ + int i; + 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_pieces_print() - Print position pieces + * @pos: &position + */ +void pos_pieces_print(pos_t *pos) +{ + 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]); +} + +/** + * 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_print() - Print position on stdout. + * @pos: &position + */ +void pos_print(pos_t *pos) +{ + int rank, file; + piece_t piece; + board_t *board = pos->board; + 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); + + + printf(" +---+---+---+---+---+---+---+---+\n"); + for (rank = 7; rank >= 0; --rank) { + printf("%c |", rank + '1'); + for (file = 0; file < 8; ++file) { + piece = board[SQ88(file, rank)].piece; + printf(" %s |", P_CSYM(piece)); + } + printf("\n +---+---+---+---+---+---+---+---+\n"); + } + printf(" A B C D E F G H\n\n"); + 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("Possible en-passant: [%#x] ", pos->en_passant); + if (pos->en_passant == 0) + printf("None.\n"); + else + printf("%d %d = %c%c\n", + F88(pos->en_passant), + R88(pos->en_passant), + FILE2C(F88(pos->en_passant)), + RANK2C(R88(pos->en_passant))); + + printf("castle [%#x] : ", pos->castle); + + if (pos->castle & CASTLE_WK) + printf("K"); + if (pos->castle & CASTLE_WQ) + printf("Q"); + if (pos->castle & CASTLE_BK) + printf("k"); + if (pos->castle & CASTLE_BQ) + printf("q"); + + printf("\n50 half-moves-rule = %d\n", 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_check() - extensive position consistenci check. + * @pos: &position + */ +void pos_check(pos_t *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"); + } + } +} + +pos_t *pos_clear(pos_t *pos) +{ + int file, rank; + board_t *board = pos->board; + + for (file = 0; file < 8; ++file) { + for (rank = 0; rank < 8; ++rank) { + /*printf("file = %d rank = %d SQ88 = %#2x = %d addr=%p\n", file, rank, + SQ88(file, rank), SQ88(file, rank), + &board[SQ88(file, rank)].piece); + */ + board[SQ88(file, rank)].piece = EMPTY; + } + } + + SET_WHITE(pos->turn); + pos->node_count = 0; + pos->castle = 0; + pos->clock_50 = 0; + pos->curmove = 0; + pos->eval = 0; + pos->en_passant = 0; + pos->occupied[WHITE] = 0; + pos->occupied[BLACK] = 0; + for (int color=0; color<2; ++color) + for (int piece = BB_ALL; piece < BB_END; ++piece) + pos->bb[color][piece] = 0; + pos->controlled[WHITE] = 0; + pos->controlled[BLACK] = 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); + + return pos; +} + +/** + * pos_del() - delete a position. + * @pos: &position. + */ +void pos_del(pos_t *pos) +{ + pieces_del(pos, WHITE); + pieces_del(pos, BLACK); + moves_del(pos); + pool_add(pos_pool, pos); +} + +pos_t *pos_startpos(pos_t *pos) +{ + static char *startfen="rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"; + + return fen2pos(pos, startfen); +} + +pos_t *pos_get() +{ + pos_t *pos = pool_get(pos_pool); + if (pos) { + INIT_LIST_HEAD(&pos->pieces[WHITE]); + INIT_LIST_HEAD(&pos->pieces[BLACK]); + + INIT_LIST_HEAD(&pos->moves[WHITE]); + INIT_LIST_HEAD(&pos->moves[BLACK]); + pos_clear(pos); + } else { + fprintf(stderr, "zobaaa\n"); + } + return pos; +} + +/** + * pos_dup() - duplicate a position. + * @pos: &position to duplicate. + * + * New position is the same as source one (with duplicated pieces list), + * except: + * - moves list is empty + * - bestmove is NULL + * - nodecount is set to zero + * - eval is set to EVAL_INVALID + * - moves_generated ans moves_counted are unset + * - check is set to zero + * + * @return: The new position. + * + * TODO: merge with pos_get - NULL for init, non null for duplicate + */ +pos_t *pos_dup(pos_t *pos) +{ + struct list_head *p_cur, *piece_list; + piece_list_t *oldpiece; + board_t *board; + pos_t *new = pool_get(pos_pool); + + if (new) { + board = new->board; + *new = *pos; + for (int color = 0; color < 2; ++color) { + INIT_LIST_HEAD(&new->pieces[color]); + INIT_LIST_HEAD(&new->moves[color]); + /* duplicate piece list */ + piece_list = &pos->pieces[color]; /* white/black piece list */ + + list_for_each(p_cur, piece_list) { + oldpiece = list_entry(p_cur, piece_list_t, list); + board[oldpiece->square].s_piece = + piece_add(new, oldpiece->piece, oldpiece->square); + } + } + new->bestmove = NULL; + new->node_count = 0; + new->eval = EVAL_INVALID; + new->moves_generated = false; + new->moves_counted = false; + new->check[WHITE] = new->check[BLACK] = 0; + } + return new; +} + +pool_t *pos_pool_init() +{ + if (!pos_pool) + pos_pool = pool_create("positions", 128, sizeof(pos_t)); + return pos_pool; +} + +void pos_pool_stats() +{ + if (pos_pool) + pool_stats(pos_pool); +}