From 3ac41d7f78598ae33407eaab8dcbb542fc3f5d87 Mon Sep 17 00:00:00 2001 From: Bruno Raoult Date: Sun, 31 Oct 2021 19:57:14 +0100 Subject: [PATCH] Add pawn pseudo-moves --- src/fen.c | 1 + src/move.c | 183 ++++++++++++++++++++++++++++++++++++++++++----------- src/move.h | 19 ++++-- 3 files changed, 162 insertions(+), 41 deletions(-) diff --git a/src/fen.c b/src/fen.c index 6949659..14a38c6 100644 --- a/src/fen.c +++ b/src/fen.c @@ -131,6 +131,7 @@ pos_t *fen2pos(pos_t *pos, char *fen) } } } + p++; /* 4) en passant */ diff --git a/src/move.c b/src/move.c index 02c14b9..8fe6e63 100644 --- a/src/move.c +++ b/src/move.c @@ -51,6 +51,10 @@ void move_print(move_t *move) printf("%c%c", FILE2C(GET_F(move->to)), RANK2C(GET_R(move->to))); + if (move->flags & M_EN_PASSANT) + printf("e.p."); + if (move->promotion) + printf("=%s", P_SYM(move->promotion)); printf(" "); } @@ -70,9 +74,131 @@ void moves_print(pos_t *pos) printf("\n\tTotal moves = %d\n", i); } -/* generate moves for non pawn pieces +inline static move_t *move_add(pos_t *pos, piece_t piece, square_t from, + square_t to) +{ + board_t *board = pos->board; + move_t *move; + + if (!(move = pool_get(moves_pool))) + return NULL; + move->piece = piece; + move->from = from; + move->to = to; + move->taken = board[to].piece; + move->flags = M_NORMAL; + if (move->taken) + move->flags |= M_CAPTURE; + list_add(&move->list, &pos->moves); + return move; +} + +/* TODO: return nmoves */ +inline static move_t *move_pawn_add(pos_t *pos, piece_t piece, square_t from, + square_t to, unsigned char rank7) +{ + //board_t *board = pos->board; + move_t *move; + piece_t promote; + unsigned char color = COLOR(piece); + + if (RANK88(from) == rank7) { /* promotion */ + for (promote = QUEEN; promote > PAWN; promote >>= 1) { + if ((move = move_add(pos, piece, from, to))) { + move->flags |= M_PROMOTION; + move->promotion = promote | color; + } + } + } else { + move = move_add(pos, piece, from, to); + } + return move; +} + +/* pawn moves. We do not test for valid destination square here, + * assuming position is valid. Is that correct ? */ -int pseudo_moves_get(pos_t *pos, piece_list_t *ppiece) +int pseudo_moves_pawn(pos_t *pos, piece_list_t *ppiece) +{ + piece_t piece = PIECE(ppiece->piece); + square_t square = ppiece->square, new; + unsigned char color = COLOR(piece); + board_t *board = pos->board; + unsigned char rank2, rank7, rank5; + move_t *move = NULL; + char dir; + int count = 0; + + /* setup direction */ + if (color == WHITE) { + dir = 1; + rank2 = 1; + rank7 = 6; + rank5 = 4; + } else { + dir = -1; + rank2 = 6; + rank7 = 1; + rank5 = 3; + } + + /* normal push. We do not test for valid destination square here, + * assuming position is valid. Is that correct ? + */ + //moves_print(pos); + new = square + dir * 16; + if (!board[new].piece) { + //printf("pushing pawn %#04x\n", square); + if ((move = move_pawn_add(pos, piece, square, new, rank7))) + count++; + //moves_print(pos); + + /* push 2 squares */ + if (move && RANK88(square) == rank2) { + new += dir * 16; + if (SQ88_OK(new) && !board[new].piece) { + //printf("pushing pawn %#04x 2 squares\n", square); + if ((move = move_pawn_add(pos, piece, square, new, rank7))) + count++; + } + } + } + + /* en passant */ + if (pos->en_passant && RANK88(square) == rank5) { + unsigned char ep_file = FILE88(pos->en_passant); + unsigned char sq_file = FILE88(square); + + //printf("possible en passant on rank %#x (current = %#0x)\n", ep_file, + // sq_file); + + if (sq_file == ep_file - 1 || sq_file == ep_file + 1) { + square_t taken = board[SQUARE(ep_file, rank5)].piece; + move = move_pawn_add(pos, piece, square, pos->en_passant, rank7); + count++; + move->flags |= M_EN_PASSANT; + move->taken = taken; + count++; + } + + } + + /* capture */ + for (new = square + dir * 15; new <= square + 17; new += 2) { + if (SQ88_NOK(new)) + continue; + if (board[new].piece && COLOR(board[new].piece) != color) { + //printf("pawn capture %#04x\n", square); + if ((move = move_pawn_add(pos, piece, square, new, rank7))) + count++; + } + } + return count; +} + +/* general rule moves for non pawn pieces + */ +int pseudo_moves_gen(pos_t *pos, piece_list_t *ppiece) { piece_t piece = PIECE(ppiece->piece); struct vector *vector = vectors+piece; @@ -80,16 +206,16 @@ int pseudo_moves_get(pos_t *pos, piece_list_t *ppiece) unsigned char ndirs = vector->ndirs; char slide = vector->slide; board_t *board = pos->board; - char color = COLOR(piece); + unsigned char color = COLOR(piece); move_t *move; int count = 0; /*printf("%s: pos:%p piece:%d [%s] at %#04x[%c%c]\n", __func__, pos, piece, - piece2string(piece), - square, - FILE2C(GET_F(square)), - RANK2C(GET_R(square))); - printf("\tvector=%ld ndirs=%d slide=%d\n", vector-vectors, ndirs, slide); + piece2string(piece), + square, + FILE2C(GET_F(square)), + RANK2C(GET_R(square))); + printf("\tvector=%ld ndirs=%d slide=%d\n", vector-vectors, ndirs, slide); */ for (int curdir = 0; curdir < ndirs; ++curdir) { char dir = vector->dir[curdir]; @@ -107,17 +233,8 @@ int pseudo_moves_get(pos_t *pos, piece_list_t *ppiece) } /* we are sure the move is valid : we create move */ - if (!(move = pool_get(moves_pool))) { - //printf("\t\tmem error\n"); - return count; - } - move->piece = piece; - move->from = square; - move->to = new; - move->taken = board[new].piece; - //move_print(move); - list_add(&move->list, &pos->moves); - count++; + if ((move = move_add(pos, piece, square, new))) + count++; if (move->taken) break; if (!slide) @@ -138,30 +255,24 @@ int moves_get(pos_t *pos) list_for_each_safe(p_cur, tmp, piece_list) { piece = list_entry(p_cur, piece_list_t, list); if (PIECE(piece->piece) != PAWN) - pseudo_moves_get(pos, piece); + pseudo_moves_gen(pos, piece); + else + pseudo_moves_pawn(pos, piece); count++; } return count; } -move_t *pseudo_moves_pawn(pos_t *pos) -{ - static short directions[] = {16}; - if (!pos && *directions) - printf("for flycheck"); - return NULL; -} - /* unused -move_t *(*moves_fct[])(pos_t *) = { - [PAWN] = pseudo_moves_pawn, - [KNIGHT] = pseudo_moves_knight, - [BISHOP] = pseudo_moves_bishop, - [ROOK] = pseudo_moves_rook, - [QUEEN] = pseudo_moves_queen, - [KING] = pseudo_moves_king -}; + move_t *(*moves_fct[])(pos_t *) = { + [PAWN] = pseudo_moves_pawn, + [KNIGHT] = pseudo_moves_knight, + [BISHOP] = pseudo_moves_bishop, + [ROOK] = pseudo_moves_rook, + [QUEEN] = pseudo_moves_queen, + [KING] = pseudo_moves_king + }; */ #ifdef MOVEBIN diff --git a/src/move.h b/src/move.h index e12526c..36da1a8 100644 --- a/src/move.h +++ b/src/move.h @@ -19,21 +19,30 @@ #include "pool.h" #include "piece.h" +/* move flags + */ +typedef unsigned char move_flags_t; +#define M_NORMAL 0x00 +#define M_CHECK 0x01 /* unsure if we know */ +#define M_CAPTURE 0x02 +#define M_EN_PASSANT 0x04 +#define M_PROMOTION 0x08 +#define M_CASTLE 0x10 + typedef struct move_s { piece_t piece; square_t from, to; piece_t taken; /* removed piece */ - + piece_t promotion; /* promoted piece */ + move_flags_t flags; struct list_head list; } move_t; pool_t *moves_pool_init(); void move_print(move_t *move); void moves_print(pos_t *move); -int pseudo_moves_get(pos_t *pos, piece_list_t *piece); +int pseudo_moves_gen(pos_t *pos, piece_list_t *piece); +int pseudo_moves_pawn(pos_t *pos, piece_list_t *piece); int moves_get(pos_t *pos); -/* not used */ -move_t *pseudo_moves_pawn(pos_t *pos); - #endif