From 264459dc0f843a0839dc7869592f1ff156b00a89 Mon Sep 17 00:00:00 2001 From: Bruno Raoult Date: Wed, 27 Oct 2021 16:09:56 +0200 Subject: [PATCH] initial files --- .gitignore | 4 + .projectile | 0 Makefile | 27 ++ src/board.h | 37 ++ src/chessdefs.h | 56 +++ src/fen.c | 151 ++++++++ src/fen.h | 8 + src/list.h | 995 ++++++++++++++++++++++++++++++++++++++++++++++++ src/move.h | 16 + src/piece.h | 15 + src/position.c | 128 +++++++ src/position.h | 22 ++ src/rook.c | 9 + 13 files changed, 1468 insertions(+) create mode 100644 .gitignore create mode 100644 .projectile create mode 100644 Makefile create mode 100644 src/board.h create mode 100644 src/chessdefs.h create mode 100644 src/fen.c create mode 100644 src/fen.h create mode 100644 src/list.h create mode 100644 src/move.h create mode 100644 src/piece.h create mode 100644 src/position.c create mode 100644 src/position.h create mode 100644 src/rook.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ae88d00 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +core +GPATH +GRTAGS +GTAGS diff --git a/.projectile b/.projectile new file mode 100644 index 0000000..e69de29 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e9a63cd --- /dev/null +++ b/Makefile @@ -0,0 +1,27 @@ +# + +BINDIR=./bin +SRCDIR=./src + +SRC=$(wildcard $(SRCDIR)/*.c) +INC=$(wildcard $(SRCDIR)/*.h) +BIN=fen + +CFLAGS += -std=c99 +CFLAGS += -g +CFLAGS += -Wall +CFLAGS += -Wextra +CFLAGS += -pedantic +#CFLAGS += -Werror +CFLAGS += -Wmissing-declarations + +all: clean $(BIN) + +.PHONY: clean +clean: + rm -rf *.o core $(BIN) + +fen: CFLAGS+=-DFENBIN +fen: $(SRC) + echo SRC=$(SRC) + $(CC) $(CFLAGS) $? -o $@ diff --git a/src/board.h b/src/board.h new file mode 100644 index 0000000..96b4789 --- /dev/null +++ b/src/board.h @@ -0,0 +1,37 @@ +#ifndef BOARD_H +#define BOARD_H + +#include + +/* ffff rrrr */ +typedef unsigned char SQUARE; +#define SQUARE_F(s) ((s) >> 4) +#define SQUARE_R(s) ((s) & 0x0f) +#define SET_F(s, f) ((s) &= 0x0f, (s) |= (f)<<4) +#define SET_R(s, r) ((s) &= 0xf0, (s) |= (r)) + +typedef struct { + unsigned char piece; + //struct piece *s_piece; +} BOARD[8*8*2]; /* 0x88 board */ + +/* definitions for 0x88 representation */ +#define SQ88(f, r) (16 * (r) + (f)) +#define FILE88(s) ((s) & 7) +#define RANK88(s) ((s) >> 8) + +/* piece notation */ +#define CHAR_EMPTY ' ' +#define CHAR_PAWN 'P' +#define CHAR_KNIGHT 'N' +#define CHAR_BISHOP 'B' +#define CHAR_ROOK 'R' +#define CHAR_QUEEN 'Q' +#define CHAR_KING 'K' + +#define C2FILE(c) (tolower(c)-'a') +#define C2RANK(c) (tolower(c)-'1') +#define FILE2C(c) ((c)+'a') +#define RANK2C(c) ((c)+'1') + +#endif diff --git a/src/chessdefs.h b/src/chessdefs.h new file mode 100644 index 0000000..e208d27 --- /dev/null +++ b/src/chessdefs.h @@ -0,0 +1,56 @@ +#ifndef CHESSDEFS_H +#define CHESSDEFS_H + +/* We use the following notation + * Bit Binary Piece/color + * + * 0 0000 0001 White + * 1 0000 0010 Black + * + * 2 0000 0100 Pawn + * 3 0000 1000 Knight + * 4 0001 0000 Bishop + * 5 0010 0000 Rook + * 6 0100 0000 Queen + * 7 1000 0000 King + */ + +//#define INVALID -1 /* unused in 0x88 */ +#define EMPTY 0 + +#define WHITE (0) /* 0000000 0 */ +#define BLACK (1) /* 0000000 1 */ + +#define PAWN (1 << 1) /* 0000001 0 */ +#define KNIGHT (1 << 2) /* 0000010 0 */ +#define BISHOP (1 << 3) /* 0000100 0 */ +#define ROOK (1 << 4) /* 0001000 0 */ +#define QUEEN (1 << 5) /* 0010000 0 */ +#define KING (1 << 6) /* 0100000 0 */ + +#define MASK_COLOR 0x01 /* 0000000 1 */ +#define MASK_PIECE 0x7E /* 0111111 0 */ + +#define COLOR(p) ((p) & MASK_COLOR) +#define PIECE(p) ((p) & MASK_PIECE) + +#define IS_WHITE(p) (!COLOR(p)) +#define IS_BLACK(p) (COLOR(p)) + +#define SET_WHITE(p) ((p) &= ~MASK_COLOR) +#define SET_BLACK(p) ((p) |= MASK_COLOR) +#define SET_COLOR(p, c) (!(c)? SET_WHITE(p): SET_BLACK(p)) + +#define TURN_WHITE 0 +#define TURN_BLACK 1 + +typedef unsigned char piece_t, color_t; + +#define CASTLE_WK 0x01 +#define CASTLE_WQ 0x02 +#define CASTLE_BK 0x04 +#define CASTLE_BQ 0x08 +#define CASTLE_W 0x03 /* white castle mask */ +#define CASTLE_B 0x0C /* black castle mask */ + +#endif diff --git a/src/fen.c b/src/fen.c new file mode 100644 index 0000000..a02d407 --- /dev/null +++ b/src/fen.c @@ -0,0 +1,151 @@ +/* Starting Position : + * rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 + * After 1.e4 : + * rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1 + * After 1... c5 : + * rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR w KQkq c6 0 2 + * After 2. Nf3: + * rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R b KQkq - 1 2 + * + * 1 : White uppercase + * 2 : next move (w or b) + * 3 : Castling capabilities: "-" if none, KQ/kq if white/black can castle + * on K or Q side + * 4 : en-passant: if pawn just moved 2 squares, indicate target square (e.g. + * for e2-e4 this field is e3) + * 5 : half moves since last capture or pawn advance (for 50 moves rule) + * 6 : full moves, starts at 1, increments after black move + * + */ + +#include +#include +#include +#include +#include + +#include "chessdefs.h" +#include "position.h" +#include "board.h" +#include "fen.h" + +// warning, we expect a valid fen input +POS *fen2pos(POS *pos, char *fen) +{ + char *p = fen; + int rank, file, skip; + BOARD *board = pos->board; +# define SKIP_BLANK(p) for(;*(p) == ' '; (p)++) + + //pos_init(pos); + + // 1) get piece placement information + for (rank = 7, file = 0; *p && *p != ' '; ++p) { + char cp = toupper(*p); + switch (cp) { + case CHAR_PAWN: + board[SQ88(file, rank)]->piece = PAWN; + goto color; + case CHAR_KNIGHT: + board[SQ88(file, rank)]->piece = KNIGHT; + goto color; + case CHAR_BISHOP: + board[SQ88(file, rank)]->piece = BISHOP; + goto color; + case CHAR_ROOK: + board[SQ88(file, rank)]->piece = ROOK; + goto color; + case CHAR_QUEEN: + board[SQ88(file, rank)]->piece = QUEEN; + goto color; + case CHAR_KING: + board[SQ88(file, rank)]->piece = KING; + goto color; + //printf("f=%d r=%d *p=%c piece=%c\n", file, rank, *p, cp); + color: + SET_COLOR(board[SQ88(file, rank)]->piece, islower(*p)); + //board[SQ88(file, rank)]->piece |= isupper(*p)? WHITE: BLACK; + file++; + break; + case '/': + rank--; + file = 0; + break; + default: + skip = cp - '0'; + file += skip; + while (skip--) { + board[SQ88(file, rank)]->piece = EMPTY; + } + } + } + for (rank = 7; rank >= 0; --rank) { + for (file = 0; file < 8; ++file) { + printf("%2x ", board[SQ88(file, rank)]->piece); + } + putchar('\n'); + } + + + // 2) next move color + SKIP_BLANK(p); + pos->turn = *p == 'w' ? TURN_WHITE : TURN_BLACK; + p++; + + // 3) castle status + SKIP_BLANK(p); + pos->castle = 0; + if (*p != '-') { + for (; *p && *p != ' '; ++p) { + switch (*p) { + case 'K': + pos->castle |= CASTLE_WK; + break; + case 'k': + pos->castle |= CASTLE_BK; + break; + case 'Q': + pos->castle |= CASTLE_WQ; + break; + case 'q': + pos->castle |= CASTLE_BQ; + break; + } + } + } + + // 4) en passant + SKIP_BLANK(p); + //printf("pos=%d\n", (int)(p-fen)); + pos->en_passant = 0; + if (*p != '-') { + //printf("passant=%c\n", *p); + SET_F(pos->en_passant, C2FILE(*p++)); + SET_R(pos->en_passant, C2RANK(*p++)); + //printf("passant=%c\n", *p); + } else { + p++; + } + + // 5) half moves since last capture or pawn move and + // 6) current move number + SKIP_BLANK(p); + //printf("pos=%d\n", (int)(p-fen)); + sscanf(p, "%hd %hd", &pos->clock_50, &pos->curmove); + return pos; +} + +#ifdef FENBIN +int main(int ac, char**av) +{ + POS *pos; + + pos = pos_create(); + if (ac == 1) { + pos_startpos(pos); + } else { + fen2pos(pos, av[1]); + } + pos_print(pos); +} +#endif diff --git a/src/fen.h b/src/fen.h new file mode 100644 index 0000000..c566973 --- /dev/null +++ b/src/fen.h @@ -0,0 +1,8 @@ +#ifndef FEN_H +#define FEN_H + +#include "position.h" + +POS *fen2pos(POS *pos, char *fen); + +#endif diff --git a/src/list.h b/src/list.h new file mode 100644 index 0000000..d005caf --- /dev/null +++ b/src/list.h @@ -0,0 +1,995 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* adaptation of kernel's + * Main change is that I don't use READ_ONCE and WRITE_ONCE + * See https://www.kernel.org/doc/Documentation/memory-barriers.txt + */ +#ifndef __BR_LIST_H +#define __BR_LIST_H + +#include +#include + +/************ originally in */ +struct list_head { + struct list_head *next, *prev; +}; +struct hlist_head { + struct hlist_node *first; +}; + +struct hlist_node { + struct hlist_node *next, **pprev; +}; + +/************ originally in */ +# define POISON_POINTER_DELTA 0 +/* These are non-NULL pointers that will result in page faults + * under normal circumstances, used to verify that nobody uses + * non-initialized list entries. + */ +#define LIST_POISON1 ((void *) 0x100 + POISON_POINTER_DELTA) +#define LIST_POISON2 ((void *) 0x200 + POISON_POINTER_DELTA) + +/************ originally in */ +#define container_of(ptr, type, member) ({ \ + void *__mptr = (void *)(ptr); \ + ((type *)(__mptr - offsetof(type, member))); }) + +/* + * Circular doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +/** + * INIT_LIST_HEAD - Initialize a list_head structure + * @list: list_head structure to be initialized. + * + * Initializes the list_head to point to itself. If it is a list header, + * the result is an empty list. + */ +static inline void INIT_LIST_HEAD(struct list_head *list) +{ + list->next = list; + list->prev = list; +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head * prev, struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/* + * Delete a list entry and clear the 'prev' pointer. + * + * This is a special-purpose list clearing method used in the networking code + * for lists allocated as per-cpu, where we don't want to incur the extra + * WRITE_ONCE() overhead of a regular list_del_init(). The code that uses this + * needs to check the node 'prev' pointer instead of calling list_empty(). + */ +static inline void __list_del_clearprev(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->prev = NULL; +} + +static inline void __list_del_entry(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty() on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del_entry(entry); + entry->next = LIST_POISON1; + entry->prev = LIST_POISON2; +} + +/** + * list_replace - replace old entry by new one + * @old : the element to be replaced + * @new : the new element to insert + * + * If @old was empty, it will be overwritten. + */ +static inline void list_replace(struct list_head *old, + struct list_head *new) +{ + new->next = old->next; + new->next->prev = new; + new->prev = old->prev; + new->prev->next = new; +} + +/** + * list_replace_init - replace old entry by new one and initialize the old one + * @old : the element to be replaced + * @new : the new element to insert + * + * If @old was empty, it will be overwritten. + */ +static inline void list_replace_init(struct list_head *old, + struct list_head *new) +{ + list_replace(old, new); + INIT_LIST_HEAD(old); +} + +/** + * list_swap - replace entry1 with entry2 and re-add entry1 at entry2's position + * @entry1: the location to place entry2 + * @entry2: the location to place entry1 + */ +static inline void list_swap(struct list_head *entry1, + struct list_head *entry2) +{ + struct list_head *pos = entry2->prev; + + list_del(entry2); + list_replace(entry1, entry2); + if (pos == entry1) + pos = entry2; + list_add(entry1, pos); +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del_entry(entry); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del_entry(list); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del_entry(list); + list_add_tail(list, head); +} + +/** + * list_bulk_move_tail - move a subsection of a list to its tail + * @head: the head that will follow our entry + * @first: first entry to move + * @last: last entry to move, can be the same as first + * + * Move all entries between @first and including @last before @head. + * All three entries must belong to the same linked list. + */ +static inline void list_bulk_move_tail(struct list_head *head, + struct list_head *first, + struct list_head *last) +{ + first->prev->next = last->next; + last->next->prev = first->prev; + + head->prev->next = first; + first->prev = head->prev; + + last->next = head; + head->prev = last; +} + +/** + * list_is_first -- tests whether @list is the first entry in list @head + * @list: the entry to test + * @head: the head of the list + */ +static inline int list_is_first(const struct list_head *list, + const struct list_head *head) +{ + return list->prev == head; +} + +/** + * list_is_last - tests whether @list is the last entry in list @head + * @list: the entry to test + * @head: the head of the list + */ +static inline int list_is_last(const struct list_head *list, + const struct list_head *head) +{ + return list->next == head; +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +/** + * list_rotate_left - rotate the list to the left + * @head: the head of the list + */ +static inline void list_rotate_left(struct list_head *head) +{ + struct list_head *first; + + if (!list_empty(head)) { + first = head->next; + list_move_tail(first, head); + } +} + +/** + * list_rotate_to_front() - Rotate list to specific item. + * @list: The desired new front of the list. + * @head: The head of the list. + * + * Rotates list so that @list becomes the new front of the list. + */ +static inline void list_rotate_to_front(struct list_head *list, + struct list_head *head) +{ + /* + * Deletes the list head from the list denoted by @head and + * places it as the tail of @list, this effectively rotates the + * list so that @list is at the front. + */ + list_move_tail(head, list); +} + +/** + * list_is_singular - tests whether a list has just one entry. + * @head: the list to test. + */ +static inline int list_is_singular(const struct list_head *head) +{ + return !list_empty(head) && (head->next == head->prev); +} + +static inline void __list_cut_position(struct list_head *list, + struct list_head *head, struct list_head *entry) +{ + struct list_head *new_first = entry->next; + list->next = head->next; + list->next->prev = list; + list->prev = entry; + entry->next = list; + head->next = new_first; + new_first->prev = head; +} + +/** + * list_cut_position - cut a list into two + * @list: a new list to add all removed entries + * @head: a list with entries + * @entry: an entry within head, could be the head itself + * and if so we won't cut the list + * + * This helper moves the initial part of @head, up to and + * including @entry, from @head to @list. You should + * pass on @entry an element you know is on @head. @list + * should be an empty list or a list you do not care about + * losing its data. + * + */ +static inline void list_cut_position(struct list_head *list, + struct list_head *head, struct list_head *entry) +{ + if (list_empty(head)) + return; + if (list_is_singular(head) && + (head->next != entry && head != entry)) + return; + if (entry == head) + INIT_LIST_HEAD(list); + else + __list_cut_position(list, head, entry); +} + +/** + * list_cut_before - cut a list into two, before given entry + * @list: a new list to add all removed entries + * @head: a list with entries + * @entry: an entry within head, could be the head itself + * + * This helper moves the initial part of @head, up to but + * excluding @entry, from @head to @list. You should pass + * in @entry an element you know is on @head. @list should + * be an empty list or a list you do not care about losing + * its data. + * If @entry == @head, all entries on @head are moved to + * @list. + */ +static inline void list_cut_before(struct list_head *list, + struct list_head *head, + struct list_head *entry) +{ + if (head->next == entry) { + INIT_LIST_HEAD(list); + return; + } + list->next = head->next; + list->next->prev = list; + list->prev = entry->prev; + list->prev->next = list; + head->next = entry; + entry->prev = head; +} + +static inline void __list_splice(const struct list_head *list, + struct list_head *prev, + struct list_head *next) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + + first->prev = prev; + prev->next = first; + + last->next = next; + next->prev = last; +} + +/** + * list_splice - join two lists, this is designed for stacks + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(const struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head, head->next); +} + +/** + * list_splice_tail - join two lists, each list being a queue + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice_tail(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head->prev, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head, head->next); + INIT_LIST_HEAD(list); + } +} + +/** + * list_splice_tail_init - join two lists and reinitialise the emptied list + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * Each of the lists is a queue. + * The list at @list is reinitialised + */ +static inline void list_splice_tail_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head->prev, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_head within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * list_first_entry - get the first element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_head within the struct. + * + * Note, that list is expected to be not empty. + */ +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + +/** + * list_last_entry - get the last element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_head within the struct. + * + * Note, that list is expected to be not empty. + */ +#define list_last_entry(ptr, type, member) \ + list_entry((ptr)->prev, type, member) + +/** + * list_first_entry_or_null - get the first element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_head within the struct. + * + * Note that if the list is empty, it returns NULL. + */ +#define list_first_entry_or_null(ptr, type, member) ({ \ + struct list_head *head__ = (ptr); \ + struct list_head *pos__ = head__->next; \ + pos__ != head__ ? list_entry(pos__, type, member) : NULL; \ + }) + +/** + * list_next_entry - get the next element in list + * @pos: the type * to cursor + * @member: the name of the list_head within the struct. + */ +#define list_next_entry(pos, member) \ + list_entry((pos)->member.next, __typeof__(*(pos)), member) + +/** + * list_prev_entry - get the prev element in list + * @pos: the type * to cursor + * @member: the name of the list_head within the struct. + */ +#define list_prev_entry(pos, member) \ + list_entry((pos)->member.prev, __typeof__(*(pos)), member) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * list_for_each_continue - continue iteration over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + * + * Continue to iterate over a list, continuing after the current position. + */ +#define list_for_each_continue(pos, head) \ + for (pos = pos->next; pos != (head); pos = pos->next) + +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); pos = pos->prev) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_prev_safe(pos, n, head) \ + for (pos = (head)->prev, n = pos->prev; \ + pos != (head); \ + pos = n, n = pos->prev) + +/** + * list_entry_is_head - test if the entry points to the head of the list + * @pos: the type * to cursor + * @head: the head for your list. + * @member: the name of the list_head within the struct. + */ +#define list_entry_is_head(pos, head, member) \ + (&pos->member == (head)) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_first_entry(head, __typeof__(*pos), member); \ + !list_entry_is_head(pos, head, member); \ + pos = list_next_entry(pos, member)) + +/** + * list_for_each_entry_reverse - iterate backwards over list of given type. + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the struct. + */ +#define list_for_each_entry_reverse(pos, head, member) \ + for (pos = list_last_entry(head, __typeof__(*pos), member); \ + !list_entry_is_head(pos, head, member); \ + pos = list_prev_entry(pos, member)) + +/** + * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue() + * @pos: the type * to use as a start point + * @head: the head of the list + * @member: the name of the list_head within the struct. + * + * Prepares a pos entry for use as a start point in list_for_each_entry_continue(). + */ +#define list_prepare_entry(pos, head, member) \ + ((pos) ? : list_entry(head, __typeof__(*pos), member)) + +/** + * list_for_each_entry_continue - continue iteration over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the struct. + * + * Continue to iterate over list of given type, continuing after + * the current position. + */ +#define list_for_each_entry_continue(pos, head, member) \ + for (pos = list_next_entry(pos, member); \ + !list_entry_is_head(pos, head, member); \ + pos = list_next_entry(pos, member)) + +/** + * list_for_each_entry_continue_reverse - iterate backwards from the given point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the struct. + * + * Start to iterate over list of given type backwards, continuing after + * the current position. + */ +#define list_for_each_entry_continue_reverse(pos, head, member) \ + for (pos = list_prev_entry(pos, member); \ + !list_entry_is_head(pos, head, member); \ + pos = list_prev_entry(pos, member)) + +/** + * list_for_each_entry_from - iterate over list of given type from the current point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the struct. + * + * Iterate over list of given type, continuing from current position. + */ +#define list_for_each_entry_from(pos, head, member) \ + for (; !list_entry_is_head(pos, head, member); \ + pos = list_next_entry(pos, member)) + +/** + * list_for_each_entry_from_reverse - iterate backwards over list of given type + * from the current point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the struct. + * + * Iterate backwards over list of given type, continuing from current position. + */ +#define list_for_each_entry_from_reverse(pos, head, member) \ + for (; !list_entry_is_head(pos, head, member); \ + pos = list_prev_entry(pos, member)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_head within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_first_entry(head, __typeof__(*pos), member), \ + n = list_next_entry(pos, member); \ + !list_entry_is_head(pos, head, member); \ + pos = n, n = list_next_entry(n, member)) + +/** + * list_for_each_entry_safe_continue - continue list iteration safe against removal + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_head within the struct. + * + * Iterate over list of given type, continuing after current point, + * safe against removal of list entry. + */ +#define list_for_each_entry_safe_continue(pos, n, head, member) \ + for (pos = list_next_entry(pos, member), \ + n = list_next_entry(pos, member); \ + !list_entry_is_head(pos, head, member); \ + pos = n, n = list_next_entry(n, member)) + +/** + * list_for_each_entry_safe_from - iterate over list from current point safe against removal + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_head within the struct. + * + * Iterate over list of given type from current point, safe against + * removal of list entry. + */ +#define list_for_each_entry_safe_from(pos, n, head, member) \ + for (n = list_next_entry(pos, member); \ + !list_entry_is_head(pos, head, member); \ + pos = n, n = list_next_entry(n, member)) + +/** + * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_head within the struct. + * + * Iterate backwards over list of given type, safe against removal + * of list entry. + */ +#define list_for_each_entry_safe_reverse(pos, n, head, member) \ + for (pos = list_last_entry(head, __typeof__(*pos), member), \ + n = list_prev_entry(pos, member); \ + !list_entry_is_head(pos, head, member); \ + pos = n, n = list_prev_entry(n, member)) + +/** + * list_safe_reset_next - reset a stale list_for_each_entry_safe loop + * @pos: the loop cursor used in the list_for_each_entry_safe loop + * @n: temporary storage used in list_for_each_entry_safe + * @member: the name of the list_head within the struct. + * + * list_safe_reset_next is not safe to use in general if the list may be + * modified concurrently (eg. the lock is dropped in the loop body). An + * exception to this is if the cursor element (pos) is pinned in the list, + * and list_safe_reset_next is called after re-taking the lock and before + * completing the current iteration of the loop body. + */ +#define list_safe_reset_next(pos, n, member) \ + n = list_next_entry(pos, member) + +/* + * Double linked lists with a single pointer list head. + * Mostly useful for hash tables where the two pointer list head is + * too wasteful. + * You lose the ability to access the tail in O(1). + */ + +#define HLIST_HEAD_INIT { .first = NULL } +#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } +#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) +static inline void INIT_HLIST_NODE(struct hlist_node *h) +{ + h->next = NULL; + h->pprev = NULL; +} + +/** + * hlist_unhashed - Has node been removed from list and reinitialized? + * @h: Node to be checked + * + * Not that not all removal functions will leave a node in unhashed + * state. For example, hlist_nulls_del_init_rcu() does leave the + * node in unhashed state, but hlist_nulls_del() does not. + */ +static inline int hlist_unhashed(const struct hlist_node *h) +{ + return !h->pprev; +} + +/** + * hlist_unhashed_lockless - Version of hlist_unhashed for lockless use + * @h: Node to be checked + * + * This variant of hlist_unhashed() must be used in lockless contexts + * to avoid potential load-tearing. The READ_ONCE() is paired with the + * various WRITE_ONCE() in hlist helpers that are defined below. + */ +static inline int hlist_unhashed_lockless(const struct hlist_node *h) +{ + return !h->pprev; +} + +/** + * hlist_empty - Is the specified hlist_head structure an empty hlist? + * @h: Structure to check. + */ +static inline int hlist_empty(const struct hlist_head *h) +{ + return !h->first; +} + +static inline void __hlist_del(struct hlist_node *n) +{ + struct hlist_node *next = n->next; + struct hlist_node **pprev = n->pprev; + + *pprev = next; + if (next) + next->pprev = pprev; +} + +/** + * hlist_del - Delete the specified hlist_node from its list + * @n: Node to delete. + * + * Note that this function leaves the node in hashed state. Use + * hlist_del_init() or similar instead to unhash @n. + */ +static inline void hlist_del(struct hlist_node *n) +{ + __hlist_del(n); + n->next = LIST_POISON1; + n->pprev = LIST_POISON2; +} + +/** + * hlist_del_init - Delete the specified hlist_node from its list and initialize + * @n: Node to delete. + * + * Note that this function leaves the node in unhashed state. + */ +static inline void hlist_del_init(struct hlist_node *n) +{ + if (!hlist_unhashed(n)) { + __hlist_del(n); + INIT_HLIST_NODE(n); + } +} + +/** + * hlist_add_head - add a new entry at the beginning of the hlist + * @n: new entry to be added + * @h: hlist head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) +{ + struct hlist_node *first = h->first; + n->next = first; + if (first) + first->pprev = &n->next; + h->first = n; + n->pprev = &h->first; +} + +/** + * hlist_add_before - add a new entry before the one specified + * @n: new entry to be added + * @next: hlist node to add it before, which must be non-NULL + */ +static inline void hlist_add_before(struct hlist_node *n, + struct hlist_node *next) +{ + n->pprev = next->pprev; + n->next = next; + next->pprev = &n->next; + *(n->pprev) = n; +} + +/** + * hlist_add_behind - add a new entry after the one specified + * @n: new entry to be added + * @prev: hlist node to add it after, which must be non-NULL + */ +static inline void hlist_add_behind(struct hlist_node *n, + struct hlist_node *prev) +{ + n->next = prev->next; + prev->next = n; + n->pprev = &prev->next; + + if (n->next) + n->next->pprev = &n->next; +} + +/** + * hlist_add_fake - create a fake hlist consisting of a single headless node + * @n: Node to make a fake list out of + * + * This makes @n appear to be its own predecessor on a headless hlist. + * The point of this is to allow things like hlist_del() to work correctly + * in cases where there is no list. + */ +static inline void hlist_add_fake(struct hlist_node *n) +{ + n->pprev = &n->next; +} + +/** + * hlist_fake: Is this node a fake hlist? + * @h: Node to check for being a self-referential fake hlist. + */ +static inline bool hlist_fake(struct hlist_node *h) +{ + return h->pprev == &h->next; +} + +/** + * hlist_is_singular_node - is node the only element of the specified hlist? + * @n: Node to check for singularity. + * @h: Header for potentially singular list. + * + * Check whether the node is the only node of the head without + * accessing head, thus avoiding unnecessary cache misses. + */ +static inline bool +hlist_is_singular_node(struct hlist_node *n, struct hlist_head *h) +{ + return !n->next && n->pprev == &h->first; +} + +/** + * hlist_move_list - Move an hlist + * @old: hlist_head for old list. + * @new: hlist_head for new list. + * + * Move a list from one list head to another. Fixup the pprev + * reference of the first entry if it exists. + */ +static inline void hlist_move_list(struct hlist_head *old, + struct hlist_head *new) +{ + new->first = old->first; + if (new->first) + new->first->pprev = &new->first; + old->first = NULL; +} + +#define hlist_entry(ptr, type, member) container_of(ptr,type,member) + +#define hlist_for_each(pos, head) \ + for (pos = (head)->first; pos ; pos = pos->next) + +#define hlist_for_each_safe(pos, n, head) \ + for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ + pos = n) + +#define hlist_entry_safe(ptr, type, member) \ + ({ __typeof__(ptr) ____ptr = (ptr); \ + ____ptr ? hlist_entry(____ptr, type, member) : NULL; \ + }) + +/** + * hlist_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry(pos, head, member) \ + for (pos = hlist_entry_safe((head)->first, __typeof__(*(pos)), member); \ + pos; \ + pos = hlist_entry_safe((pos)->member.next, __typeof__(*(pos)), member)) + +/** + * hlist_for_each_entry_continue - iterate over a hlist continuing after current point + * @pos: the type * to use as a loop cursor. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_continue(pos, member) \ + for (pos = hlist_entry_safe((pos)->member.next, __typeof__(*(pos)), member); \ + pos; \ + pos = hlist_entry_safe((pos)->member.next, __typeof__(*(pos)), member)) + +/** + * hlist_for_each_entry_from - iterate over a hlist continuing from current point + * @pos: the type * to use as a loop cursor. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_from(pos, member) \ + for (; pos; \ + pos = hlist_entry_safe((pos)->member.next, __typeof__(*(pos)), member)) + +/** + * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: a &struct hlist_node to use as temporary storage + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_safe(pos, n, head, member) \ + for (pos = hlist_entry_safe((head)->first, __typeof__(*pos), member); \ + pos && ({ n = pos->member.next; 1; }); \ + pos = hlist_entry_safe(n, __typeof__(*pos), member)) + +#endif diff --git a/src/move.h b/src/move.h new file mode 100644 index 0000000..d3770f7 --- /dev/null +++ b/src/move.h @@ -0,0 +1,16 @@ +#ifndef ROOK_H +#define ROOK_H + +#include "chessdefs.h" +#include "position.h" + +typedef struct { + PIECE piece; + SQUARE from; + SQUARE to; + +} MOVE; + +extern MOVE *moves_rook(POS *pos); + +#endif diff --git a/src/piece.h b/src/piece.h new file mode 100644 index 0000000..38e5c5f --- /dev/null +++ b/src/piece.h @@ -0,0 +1,15 @@ +#ifndef PIECE_H +#define PIECE_H + +#include "chessdefs.h" +#include "board.h" + +typedef struct piece { + short piece; + short color; + SQUARE square; + short castle; + float value; +} PIECE, PLAYER_PIECES[16]; + +#endif diff --git a/src/position.c b/src/position.c new file mode 100644 index 0000000..5c45822 --- /dev/null +++ b/src/position.c @@ -0,0 +1,128 @@ +#include +#include +#include +#include +#include + +#include "chessdefs.h" +#include "position.h" +#include "fen.h" + +inline static char piece2char(unsigned char 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; + } + if (IS_BLACK(p)) + res = tolower(res); + return res; + +} + +void pos_print(POS *pos) +{ + int rank, file; + piece_t piece; + BOARD *board = pos->board; + + 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(" %c |", piece2char(piece)); + } + printf("\n +---+---+---+---+---+---+---+---+\n"); + } + printf(" A B C D E F G H\n\n"); + printf("Next move: %s.\n", IS_WHITE(pos->turn) ? "white" : "black"); + printf("Possible en-passant: [%#x] ", pos->en_passant); + if (pos->en_passant == 0) + printf("None.\n"); + else + printf("%d %d = %c%c\n", SQUARE_F(pos->en_passant), + SQUARE_R(pos->en_passant), + FILE2C(SQUARE_F(pos->en_passant)), + RANK2C(SQUARE_R(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); +} + +POS *pos_init(POS *pos) +{ + int file, rank; + BOARD *board = pos->board; + + for (rank = 0; rank < 8; ++rank) { + for (file = 0; file < 8; ++file) { + printf("file = %d rank = %d SQ88 = %#x\n", file, rank, SQ88(file, rank)); + board[SQ88(file, rank)]->piece = EMPTY; + } + } + + pos->turn = TURN_WHITE; + pos->castle = 0; + pos->clock_50 = 0; + pos->curmove = 0; + pos->en_passant = 0; + pos->en_passant = 0; + + return pos; +} + +POS *pos_startpos(POS *pos) +{ + static char *startfen="rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"; + + return fen2pos(pos, startfen); +} + +POS *pos_create() +{ + POS *pos = malloc(sizeof(POS)); + if (pos) { + pos->board = malloc(sizeof (BOARD)); + if (pos->board) + pos_init(pos); + else { + free(pos); + pos = NULL; + } + } + return pos; +} diff --git a/src/position.h b/src/position.h new file mode 100644 index 0000000..dcdd481 --- /dev/null +++ b/src/position.h @@ -0,0 +1,22 @@ +#ifndef POSITION_H +#define POSITION_H + +#include + +#include "board.h" + +typedef struct position { + short turn; + short castle; + short clock_50; + short curmove; + SQUARE en_passant; + BOARD *board; +} POS; + +void pos_print(POS *pos); +POS *pos_init(POS *pos); +POS *pos_startpos(POS *pos); +POS *pos_create(); + +#endif diff --git a/src/rook.c b/src/rook.c new file mode 100644 index 0000000..b32e29b --- /dev/null +++ b/src/rook.c @@ -0,0 +1,9 @@ +#include "chessdefs.h" +#include "position.h" +#include "fen.h" + +/* +rook_move_list(POS *position) +{ +} +*/