diff --git a/.gitignore b/.gitignore index 373ac47..b09654a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ GTAGS fen pool piece +move diff --git a/Makefile b/Makefile index 62bc157..3aaaaaf 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ SRCDIR=./src SRC=$(wildcard $(SRCDIR)/*.c) INC=$(wildcard $(SRCDIR)/*.h) -BIN=fen pool piece +BIN=fen pool piece move CFLAGS += -std=gnu99 CFLAGS += -g @@ -37,3 +37,8 @@ piece: CFLAGS+=-DPIECEBIN piece: $(SRC) echo SRC=$(SRC) $(CC) $(CFLAGS) $? -o $@ + +move: CFLAGS+=-DMOVEBIN +move: $(SRC) + echo SRC=$(SRC) + $(CC) $(CFLAGS) $? -o $@ diff --git a/dir-locals.el b/dir-locals.el new file mode 100644 index 0000000..f45a2ac --- /dev/null +++ b/dir-locals.el @@ -0,0 +1 @@ +((c-mode . ((compile-command . "make -C ../build -j2 whatever")))) diff --git a/src/board.h b/src/board.h index fc6f641..d0cdff4 100644 --- a/src/board.h +++ b/src/board.h @@ -27,7 +27,10 @@ typedef struct { */ #define SQ88(f, r) (16 * (r) + (f)) /* from rank,file to sq88 */ #define FILE88(s) ((s) & 7) /* from sq88 to file */ -#define RANK88(s) ((s) >> 8) /* from sq88 to rank */ +#define RANK88(s) ((s) >> 4) /* from sq88 to rank */ + +#define SQ88_NOK(s) ((s) & 0x88) /* invalid square */ +#define SQ88_OK(s) (!SQ88_NOK(s)) /* piece human notation */ diff --git a/src/move.c b/src/move.c new file mode 100644 index 0000000..2079385 --- /dev/null +++ b/src/move.c @@ -0,0 +1,222 @@ +/* move.c - move 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 "chessdefs.h" +#include "piece.h" +#include "move.h" +#include "list.h" + +static pool_t *moves_pool; + +static struct vector { + unsigned char ndirs; + char slide; + char dir[8]; +} vectors[] = { + [KNIGHT] = { 8, 0, { -33, -31, -18, -14, 14, 18, 31, 33}}, + [BISHOP] = { 4, 1, { -15, -17, 15, 17}}, + [ROOK] = { 4, 1, { -1, -16, 1, 16}}, + [QUEEN] = { 8, 1, { -1, -16, 1, 16, -15, -17, 15, 17}}, + [KING] = { 8, 0, { -1, -16, 1, 16, -15, -17, 15, 17}}, +}; + +inline static char piece2char(piece_t p) +{ + piece_t piece = PIECE(p); + char res; + + //printf("%#x p=%#x\n", p, PIECE(p)); + switch (piece) { + case PAWN: + res = CHAR_PAWN; + break; + case KNIGHT: + res = CHAR_KNIGHT; + break; + case BISHOP: + res = CHAR_BISHOP; + break; + case ROOK: + res = CHAR_ROOK; + break; + case QUEEN: + res = CHAR_QUEEN; + break; + case KING: + res = CHAR_KING; + break; + default: + res = CHAR_EMPTY; + } + return res; + +} + +pool_t *moves_pool_init() +{ + if (!moves_pool) + moves_pool = pool_init("moves", 128, sizeof(piece_list_t)); + return moves_pool; +} + + + +void move_print(move_t *move) +{ + printf("%c%c%c", piece2char(move->piece), + FILE2C(GET_F(move->from)), + RANK2C(GET_R(move->from))); + if (move->taken) + printf("x%c", piece2char(move->taken)); + else + printf("-"); + printf("%c%c", + FILE2C(GET_F(move->to)), + RANK2C(GET_R(move->to))); + printf(" "); +} + +void moves_print(pos_t *pos) +{ + struct list_head *p_cur, *tmp; + move_t *move; + int i = 0; + + printf("%s pseudo-moves: ", pos->turn == WHITE? "White": "Black"); + list_for_each_safe(p_cur, tmp, &pos->moves) { + move = list_entry(p_cur, move_t, list); + + move_print(move); + i++; + } + printf("Total moves = %d\n", i); +} + +/* generate moves for non pawn pieces + */ +int pseudo_moves_get(pos_t *pos, piece_list_t *ppiece) +{ + piece_t piece = PIECE(ppiece->piece); + struct vector *vector = vectors+piece; + square_t square = ppiece->square; + unsigned char ndirs = vector->ndirs; + char slide = vector->slide; + board_t *board = pos->board; + 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); + */ + for (int curdir = 0; curdir < ndirs; ++curdir) { + char dir = vector->dir[curdir]; + for (square_t new = square + dir; ; new = new + dir) { + /* outside board */ + if (SQ88_NOK(new)) { + //printf("\t\tskipping %04x (invalid square)\n", new); + break; + } + //printf("\ttrying %c%c", FILE2C(GET_F(new)), RANK2C(GET_R(new))); + /* own color on dest square */ + if (board[new].piece && COLOR(board[new].piece) == color) { + //printf("\t\tskipping %04x (same color piece)\n", new); + break; + } + + /* 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->taken) + break; + if (!slide) + break; + } + } + return count; +} + +int moves_get(pos_t *pos) +{ + struct list_head *p_cur, *tmp, *piece_list; + piece_list_t *piece; + int count = 0; + + piece_list = pos->turn == WHITE? &pos->pieces_white: &pos->pieces_black; + + 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); + + 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 +}; +*/ + +#ifdef MOVEBIN +#include "fen.h" +int main(int ac, char**av) +{ + pos_t *pos; + + pos = pos_create(); + piece_pool_init(); + moves_pool_init(); + + + if (ac == 1) { + pos_startpos(pos); + } else { + fen2pos(pos, av[1]); + } + pos_print(pos); + pieces_print_pos_pieces(pos); + moves_get(pos); + moves_print(pos); +} +#endif diff --git a/src/move.h b/src/move.h index 32a7c4e..e12526c 100644 --- a/src/move.h +++ b/src/move.h @@ -16,12 +16,24 @@ #include "chessdefs.h" #include "position.h" +#include "pool.h" +#include "piece.h" -typedef struct { - piece_t t; +typedef struct move_s { + piece_t piece; square_t from, to; -} MOVE; + piece_t taken; /* removed piece */ -extern MOVE *moves_rook(POS *pos); + 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 moves_get(pos_t *pos); + +/* not used */ +move_t *pseudo_moves_pawn(pos_t *pos); #endif diff --git a/src/piece.c b/src/piece.c index ae17fe2..b08122c 100644 --- a/src/piece.c +++ b/src/piece.c @@ -14,9 +14,42 @@ #include #include "chessdefs.h" #include "piece.h" +#include "ctype.h" static pool_t *pieces_pool; +inline static char piece2char(piece_t p) +{ + piece_t piece = PIECE(p); + char res; + + //printf("%#x p=%#x\n", p, PIECE(p)); + switch (piece) { + case PAWN: + res = CHAR_PAWN; + break; + case KNIGHT: + res = CHAR_KNIGHT; + break; + case BISHOP: + res = CHAR_BISHOP; + break; + case ROOK: + res = CHAR_ROOK; + break; + case QUEEN: + res = CHAR_QUEEN; + break; + case KING: + res = CHAR_KING; + break; + default: + res = CHAR_EMPTY; + } + return res; + +} + void piece_list_print(struct list_head *list) { struct list_head *p_cur, *tmp; @@ -26,7 +59,7 @@ void piece_list_print(struct list_head *list) list_for_each_safe(p_cur, tmp, list) { piece = list_entry(p_cur, piece_list_t, list); - printf("%c%c%c ", *piece2string(piece->piece), + printf("%c%c%c ", piece2char(piece->piece), FILE2C(GET_F(piece->square)), RANK2C(GET_R(piece->square))); /*printf("\t%d: %s on %c%c\n", i, diff --git a/src/position.c b/src/position.c index 3f4a506..921ed8f 100644 --- a/src/position.c +++ b/src/position.c @@ -145,6 +145,7 @@ pos_t *pos_init(pos_t *pos) pos->en_passant = 0; INIT_LIST_HEAD(&pos->pieces_white); INIT_LIST_HEAD(&pos->pieces_black); + INIT_LIST_HEAD(&pos->moves); return pos; } diff --git a/src/position.h b/src/position.h index 11baf7c..dc85bfa 100644 --- a/src/position.h +++ b/src/position.h @@ -28,6 +28,7 @@ typedef struct position { eval_t eval; struct list_head pieces_white; struct list_head pieces_black; + struct list_head moves; board_t *board; } pos_t;