From 3c540db464f4034d0a393b076c79a26851f68f47 Mon Sep 17 00:00:00 2001 From: Aargh Rai Date: Mon, 6 Jul 2026 23:39:55 +0530 Subject: removed unnescessary stuff + ipc with shared memory + somehow the build is faster? --- src/bitboard.c | 58 +++++++++++++++ src/bitboard.h | 87 ++++++++++++++++++++++ src/engine.c | 112 +++++++++++++++------------- src/engine/bitboard.c | 58 --------------- src/engine/bitboard.h | 87 ---------------------- src/engine/fen.c | 197 ------------------------------------------------- src/engine/fen.h | 12 --- src/engine/ints.h | 20 ----- src/engine/moves.c | 2 +- src/engine/moves.h | 4 +- src/fen.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/fen.h | 12 +++ src/ints.h | 20 +++++ src/ipc.c | 133 +++++---------------------------- src/ipc.h | 45 ++++++++++++ src/uci.c | 8 +- src/uci.h | 8 ++ src/uci/response.c | 6 +- src/uci/state.h | 2 +- 19 files changed, 521 insertions(+), 548 deletions(-) create mode 100644 src/bitboard.c create mode 100644 src/bitboard.h delete mode 100644 src/engine/bitboard.c delete mode 100644 src/engine/bitboard.h delete mode 100644 src/engine/fen.c delete mode 100644 src/engine/fen.h delete mode 100644 src/engine/ints.h create mode 100644 src/fen.c create mode 100644 src/fen.h create mode 100644 src/ints.h create mode 100644 src/ipc.h create mode 100644 src/uci.h (limited to 'src') diff --git a/src/bitboard.c b/src/bitboard.c new file mode 100644 index 0000000..565f425 --- /dev/null +++ b/src/bitboard.c @@ -0,0 +1,58 @@ +#include "bitboard.h" +#include +#include +#include + +position_t position_starting() { + return (position_t) { + .bitboards = { + 16ULL, + 8ULL, + 129ULL, + 36ULL, + 66ULL, + 65280ULL, + 1152921504606846976ULL, + 576460752303423488ULL, + 9295429630892703744ULL, + 2594073385365405696ULL, + 4755801206503243776ULL, + 71776119061217280ULL, + }, + .castling = + WHITE_SHORT_CASTLE | WHITE_LONG_CASTLE | + BLACK_SHORT_CASTLE | BLACK_LONG_CASTLE, + .turn = WHITE_TURN, + .passantable_file = 0, + .halfmove_clock = 0, + .fullmove_clock = 1 + }; +} + +void assert_valid_position(position_t position) { + assert(check_valid_position(position) == true); +} + +bool check_valid_position(position_t position) { + if (position.castling > + ( + WHITE_SHORT_CASTLE | WHITE_LONG_CASTLE | + BLACK_SHORT_CASTLE | BLACK_LONG_CASTLE + ) + ) return false; + if (position.turn != WHITE_TURN && position.turn != BLACK_TURN) return false; + if (position.passantable_file > 8) return false; // 0 means no passant + if (position.bitboards[WHITE_KING] == 0) return false; + if (position.bitboards[BLACK_KING] == 0) return false; + return true; +} + +void print_bitboard(bitboard_t bitboard) { + printf("Bitboard(%" PRIu64 ")\n", bitboard); + for (int i = 7; i >= 0; i--) { + for (int j = 0; j < 8; j++) { + printf("%" PRIu64 "", (bitboard >> (8 * i + j)) & 1); + } + printf("\n"); + } +} diff --git a/src/bitboard.h b/src/bitboard.h new file mode 100644 index 0000000..ecd8c35 --- /dev/null +++ b/src/bitboard.h @@ -0,0 +1,87 @@ +#ifndef BITBOARD_H +#define BITBOARD_H + +#include "ints.h" +#include + +typedef u64 bitboard_t; + +enum { + WHITE_KING, + WHITE_QUEEN, + WHITE_ROOK, + WHITE_BISHOP, + WHITE_KNIGHT, + WHITE_PAWN, + BLACK_KING, + BLACK_QUEEN, + BLACK_ROOK, + BLACK_BISHOP, + BLACK_KNIGHT, + BLACK_PAWN, + PIECE_TYPE_COUNT, +}; + +enum { + WHITE_SHORT_CASTLE = 1 << 0, + WHITE_LONG_CASTLE = 1 << 1, + BLACK_SHORT_CASTLE = 1 << 2, + BLACK_LONG_CASTLE = 1 << 3, +}; + +enum { + WHITE_TURN, + BLACK_TURN, +}; + +#define BITMASK_RANK_1 255ULL +#define BITMASK_RANK_2 65280ULL +#define BITMASK_RANK_3 16711680ULL +#define BITMASK_RANK_4 4278190080ULL +#define BITMASK_RANK_5 1095216660480ULL +#define BITMASK_RANK_6 280375465082880ULL +#define BITMASK_RANK_7 71776119061217280ULL +#define BITMASK_RANK_8 18374686479671623680ULL +#define BITMASK_FILE_A 72340172838076673ULL +#define BITMASK_FILE_B 144680345676153346ULL +#define BITMASK_FILE_C 289360691352306692ULL +#define BITMASK_FILE_D 578721382704613384ULL +#define BITMASK_FILE_E 1157442765409226768ULL +#define BITMASK_FILE_F 2314885530818453536ULL +#define BITMASK_FILE_G 4629771061636907072ULL +#define BITMASK_FILE_H 9259542123273814144ULL + +#define occupied_by(bitboard, index) (bitboard & ((bitboard_t)1 << index)) + +typedef struct { + bitboard_t bitboards[PIECE_TYPE_COUNT]; + u8 castling; + u8 turn; + u8 passantable_file; + u16 halfmove_clock; + u16 fullmove_clock; +} position_t; + +position_t position_starting(); +void assert_valid_position(position_t position); +bool check_valid_position(position_t position); +#define whites(position) \ + position.bitboards[WHITE_KING] | \ + position.bitboards[WHITE_QUEEN] | \ + position.bitboards[WHITE_ROOK] | \ + position.bitboards[WHITE_BISHOP] | \ + position.bitboards[WHITE_KNIGHT] | \ + position.bitboards[WHITE_PAWN] + +#define blacks(position) \ + position.bitboards[BLACK_KING] | \ + position.bitboards[BLACK_QUEEN] | \ + position.bitboards[BLACK_ROOK] | \ + position.bitboards[BLACK_BISHOP] | \ + position.bitboards[BLACK_KNIGHT] | \ + position.bitboards[BLACK_PAWN] + + +void print_bitboard(bitboard_t bitboard); + +#endif // BITBOARD_H diff --git a/src/engine.c b/src/engine.c index 3c64cce..c5843a4 100644 --- a/src/engine.c +++ b/src/engine.c @@ -1,63 +1,71 @@ -#include +#include #include -#include "engine/bitboard.h" +#include + +#include "bitboard.h" #include "engine/moves.h" -#include "engine/fen.h" +#include "fen.h" #include "fcntl.h" -#include "ipc.c" - -struct sqrstr { - char data[2]; -}; -struct sqrstr sqr_to_str(int i) { - assert(i < 64); - return (struct sqrstr) { .data = {(i / 10) + '0', (i % 10) + '0' } }; -} - -int main(void) { - while (1) { - char* x = read_queue(rx); - log_infof("Received: %s", x); - - moves_t moves = moves_init(); - struct fen_load result = load_fen(x); - free(x); - - if (result.failed) { - log_warnf("Invalid fen"); - send_queue(tx, "Failed", 7); - return 0; - } - log_infof("Valid fen"); +#include "uci.h" +#include "ipc.h" - position_t position = result.position; +// struct sqrstr { +// char data[2]; +// }; +// struct sqrstr sqr_to_str(int i) { +// assert(i < 64); +// return (struct sqrstr) { .data = {(i / 10) + '0', (i % 10) + '0' } }; +// } - get_moves(&moves, position); - send_queue(tx, "Sending", 8); - char buf[65]; - int k = 0; - for (int i = 0; i < moves.length; i++) { - struct sqrstr from_str = sqr_to_str(moves.moves[i].from); - struct sqrstr to_str = sqr_to_str(moves.moves[i].to); - buf[k++] = from_str.data[0]; - buf[k++] = from_str.data[1]; - buf[k++] = to_str.data[0]; - buf[k++] = to_str.data[1]; - if (k != 64) continue; - buf[k] = 0; - send_queue(tx, buf, sizeof(buf)); - k = 0; - } - if (k != 0) send_queue(tx, buf, sizeof(buf)); - char end_transmission[] = "END-TRANSMISSION"; - int n = strlen(end_transmission); - log_infof("%s", end_transmission); - send_queue(tx, end_transmission, n + 1); +int main(int argc, char** argv) { + comms *state = create_shared_memory(sizeof(comms)); + printf("ENGINE: %p\n", state); + state->uci_message_ready = 69; + if (fork() == 0) { + return uci(state); } + while (1) {} + // while (1) { + // char* x = read_queue(rx); + // log_infof("Received: %s", x); + // + // moves_t moves = moves_init(); + // struct fen_load result = load_fen(x); + // free(x); + // + // if (result.failed) { + // log_warnf("Invalid fen"); + // send_queue(tx, "Failed", 7); + // return 0; + // } + // log_infof("Valid fen"); + // + // position_t position = result.position; + // + // get_moves(&moves, position); + // send_queue(tx, "Sending", 8); + // char buf[65]; + // int k = 0; + // for (int i = 0; i < moves.length; i++) { + // struct sqrstr from_str = sqr_to_str(moves.moves[i].from); + // struct sqrstr to_str = sqr_to_str(moves.moves[i].to); + // buf[k++] = from_str.data[0]; + // buf[k++] = from_str.data[1]; + // buf[k++] = to_str.data[0]; + // buf[k++] = to_str.data[1]; + // if (k != 64) continue; + // buf[k] = 0; + // send_queue(tx, buf, sizeof(buf)); + // k = 0; + // } + // if (k != 0) send_queue(tx, buf, sizeof(buf)); + // char end_transmission[] = "END-TRANSMISSION"; + // int n = strlen(end_transmission); + // log_infof("%s", end_transmission); + // send_queue(tx, end_transmission, n + 1); + // } return 0; } -#include "engine/bitboard.c" #include "engine/moves.c" -#include "engine/fen.c" diff --git a/src/engine/bitboard.c b/src/engine/bitboard.c deleted file mode 100644 index 565f425..0000000 --- a/src/engine/bitboard.c +++ /dev/null @@ -1,58 +0,0 @@ -#include "bitboard.h" -#include -#include -#include - -position_t position_starting() { - return (position_t) { - .bitboards = { - 16ULL, - 8ULL, - 129ULL, - 36ULL, - 66ULL, - 65280ULL, - 1152921504606846976ULL, - 576460752303423488ULL, - 9295429630892703744ULL, - 2594073385365405696ULL, - 4755801206503243776ULL, - 71776119061217280ULL, - }, - .castling = - WHITE_SHORT_CASTLE | WHITE_LONG_CASTLE | - BLACK_SHORT_CASTLE | BLACK_LONG_CASTLE, - .turn = WHITE_TURN, - .passantable_file = 0, - .halfmove_clock = 0, - .fullmove_clock = 1 - }; -} - -void assert_valid_position(position_t position) { - assert(check_valid_position(position) == true); -} - -bool check_valid_position(position_t position) { - if (position.castling > - ( - WHITE_SHORT_CASTLE | WHITE_LONG_CASTLE | - BLACK_SHORT_CASTLE | BLACK_LONG_CASTLE - ) - ) return false; - if (position.turn != WHITE_TURN && position.turn != BLACK_TURN) return false; - if (position.passantable_file > 8) return false; // 0 means no passant - if (position.bitboards[WHITE_KING] == 0) return false; - if (position.bitboards[BLACK_KING] == 0) return false; - return true; -} - -void print_bitboard(bitboard_t bitboard) { - printf("Bitboard(%" PRIu64 ")\n", bitboard); - for (int i = 7; i >= 0; i--) { - for (int j = 0; j < 8; j++) { - printf("%" PRIu64 "", (bitboard >> (8 * i + j)) & 1); - } - printf("\n"); - } -} diff --git a/src/engine/bitboard.h b/src/engine/bitboard.h deleted file mode 100644 index ecd8c35..0000000 --- a/src/engine/bitboard.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef BITBOARD_H -#define BITBOARD_H - -#include "ints.h" -#include - -typedef u64 bitboard_t; - -enum { - WHITE_KING, - WHITE_QUEEN, - WHITE_ROOK, - WHITE_BISHOP, - WHITE_KNIGHT, - WHITE_PAWN, - BLACK_KING, - BLACK_QUEEN, - BLACK_ROOK, - BLACK_BISHOP, - BLACK_KNIGHT, - BLACK_PAWN, - PIECE_TYPE_COUNT, -}; - -enum { - WHITE_SHORT_CASTLE = 1 << 0, - WHITE_LONG_CASTLE = 1 << 1, - BLACK_SHORT_CASTLE = 1 << 2, - BLACK_LONG_CASTLE = 1 << 3, -}; - -enum { - WHITE_TURN, - BLACK_TURN, -}; - -#define BITMASK_RANK_1 255ULL -#define BITMASK_RANK_2 65280ULL -#define BITMASK_RANK_3 16711680ULL -#define BITMASK_RANK_4 4278190080ULL -#define BITMASK_RANK_5 1095216660480ULL -#define BITMASK_RANK_6 280375465082880ULL -#define BITMASK_RANK_7 71776119061217280ULL -#define BITMASK_RANK_8 18374686479671623680ULL -#define BITMASK_FILE_A 72340172838076673ULL -#define BITMASK_FILE_B 144680345676153346ULL -#define BITMASK_FILE_C 289360691352306692ULL -#define BITMASK_FILE_D 578721382704613384ULL -#define BITMASK_FILE_E 1157442765409226768ULL -#define BITMASK_FILE_F 2314885530818453536ULL -#define BITMASK_FILE_G 4629771061636907072ULL -#define BITMASK_FILE_H 9259542123273814144ULL - -#define occupied_by(bitboard, index) (bitboard & ((bitboard_t)1 << index)) - -typedef struct { - bitboard_t bitboards[PIECE_TYPE_COUNT]; - u8 castling; - u8 turn; - u8 passantable_file; - u16 halfmove_clock; - u16 fullmove_clock; -} position_t; - -position_t position_starting(); -void assert_valid_position(position_t position); -bool check_valid_position(position_t position); -#define whites(position) \ - position.bitboards[WHITE_KING] | \ - position.bitboards[WHITE_QUEEN] | \ - position.bitboards[WHITE_ROOK] | \ - position.bitboards[WHITE_BISHOP] | \ - position.bitboards[WHITE_KNIGHT] | \ - position.bitboards[WHITE_PAWN] - -#define blacks(position) \ - position.bitboards[BLACK_KING] | \ - position.bitboards[BLACK_QUEEN] | \ - position.bitboards[BLACK_ROOK] | \ - position.bitboards[BLACK_BISHOP] | \ - position.bitboards[BLACK_KNIGHT] | \ - position.bitboards[BLACK_PAWN] - - -void print_bitboard(bitboard_t bitboard); - -#endif // BITBOARD_H diff --git a/src/engine/fen.c b/src/engine/fen.c deleted file mode 100644 index aa258c9..0000000 --- a/src/engine/fen.c +++ /dev/null @@ -1,197 +0,0 @@ -#include -#include -#include "fen.h" -#include "bitboard.h" - -int get_castling(char c) { - if (c == 'K') return WHITE_SHORT_CASTLE; - if (c == 'Q') return WHITE_LONG_CASTLE; - if (c == 'k') return BLACK_SHORT_CASTLE; - if (c == 'q') return BLACK_LONG_CASTLE; - return -1; -} - -int get_turn(char c) { - if (c == 'w') return WHITE_TURN; - if (c == 'b') return BLACK_TURN; - return -1; -} - -int get_piece_enum_item(char c) { - if (c == 'P') return WHITE_PAWN; - if (c == 'N') return WHITE_KNIGHT; - if (c == 'B') return WHITE_BISHOP; - if (c == 'R') return WHITE_ROOK; - if (c == 'Q') return WHITE_QUEEN; - if (c == 'K') return WHITE_KING; - - if (c == 'p') return BLACK_PAWN; - if (c == 'n') return BLACK_KNIGHT; - if (c == 'b') return BLACK_BISHOP; - if (c == 'r') return BLACK_ROOK; - if (c == 'q') return BLACK_QUEEN; - if (c == 'k') return BLACK_KING; - - return -1; -} - -/* - * from Wikipedia - * Piece placement data - * Each rank is described, starting with rank 8 and ending with rank 1, - * with a "/" between each one; within each rank, the contents of the - * squares are described in order from the a-file to the h-file. - * Each piece is identified by a single letter taken from the standard - * English names in algebraic notation - * (pawn = "P", knight = "N", bishop = "B", - * rook = "R", queen = "Q", and king = "K"). - * White pieces are designated using uppercase letters ("PNBRQK"), - * while black pieces use lowercase letters ("pnbrqk"). - * A set of one or more consecutive empty squares within a rank is denoted - * by a digit from "1" to "8", corresponding to the number of squares. - * Active color - * "w" means that White is to move; "b" means that Black is to move. - * Castling availability - * If neither side has the ability to castle, this field uses the character - * "-". Otherwise, this field contains one or more letters: - * "K" if White can castle kingside, - * "Q" if White can castle queenside, - * "k" if Black can castle kingside, - * and "q" if Black can castle queenside. - * A situation that temporarily prevents castling does not - * prevent the use of this notation. - * En passant target square - * This is a square over which a pawn has just passed while moving two - * squares; it is given in algebraic notation. - * If there is no en passant target square, this field uses the character "-". - * This is recorded regardless of whether there is a pawn in position to - * capture en passant. An updated version of the spec has since made it - * so the target square is recorded only if a legal en passant capture is - * possible, but the old version of the standard - * is the one most commonly used. - * Halfmove clock - * The number of halfmoves since the last capture or pawn advance, - * used for the fifty-move rule. - * Fullmove number - * The number of the full moves. - * It starts at 1 and is incremented after Black's move. - * - * e.g. 1B6/2n5/p1N1P2R/P1K3N1/4Pk2/1Q2p2p/6nP/1B4R1 w - - 0 1 - */ -struct fen_load load_fen(const char* fen) { - position_t position = {0}; - - int square = 56; - int i = -1; - char c; - while ((c = fen[++i]) != ' ') { - if (c >= '0' && c <= '9') { - if (c == '9') return (struct fen_load) { true, position }; - square += c - '0'; - continue; - } - if (c == '/') { - square -= 16; - continue; - } - - int piece_type = get_piece_enum_item(c); - if (piece_type == -1) return (struct fen_load) { true, position }; - position.bitboards[piece_type] |= (bitboard_t)1 << square++; - } - - c = fen[++i]; - int turn = get_turn(c); - if (turn == -1) return (struct fen_load) { true, position }; - position.turn = turn; - if (fen[++i] != ' ') return (struct fen_load) { true, position }; - - while ((c = fen[++i]) != ' ') { - if (c == '-') continue; - int castling = get_castling(c); - if (castling == -1) return (struct fen_load) { true, position }; - position.castling |= castling; - } - - c = fen[++i]; - if (c >= 'a' && c <= 'z') { - if (c > 'h') return (struct fen_load) { true, position }; - position.passantable_file = c - 'a' + 1; - c = fen[++i]; - if (c < '1' && c > '8') return (struct fen_load) { true, position }; - } else { - position.passantable_file = 0; - } - if (fen[++i] != ' ') return (struct fen_load) { true, position }; - - while ((c = fen[++i]) != ' ') { - if (c < '0' || c > '9') return (struct fen_load) { true, position }; - position.halfmove_clock *= 10; - position.halfmove_clock += c - '0'; - } - - while ((c = fen[++i]) != 0) { - if (c < '0' || c > '9') return (struct fen_load) { true, position }; - position.fullmove_clock *= 10; - position.fullmove_clock += c - '0'; - } - - bool error = !check_valid_position(position); - return (struct fen_load) { error, position }; -} - -#ifdef TEST_MOD -#include "bitboard.c" - -bool test_fen_no_passant() { - struct fen_load r = load_fen("1B6/2n5/p1N1P2R/P1K3N1/4Pk2/1Q2p2p/6nP/1B4R1 w - - 0 1"); - if (r.failed) return false; - - position_t p = r.position; - if (p.castling != 0) return false; - if (p.passantable_file != 0) return false; - return true; -} -bool test_fen_passant() { - struct fen_load r = load_fen("rnbqkbnr/ppp1p1pp/8/3pPp2/8/8/PPPP1PPP/RNBQKBNR w KQkq f6 0 3"); - if (r.failed) return false; - - position_t p = r.position; - if ( - p.castling != ( - WHITE_LONG_CASTLE | WHITE_SHORT_CASTLE | - BLACK_LONG_CASTLE | BLACK_SHORT_CASTLE - ) - ) return false; - if (p.passantable_file != 6) return false; - return true; -} - -bool test_starting_position() { - struct fen_load r = load_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); - if (r.failed) return false; - - position_t position = r.position; - position_t expected = position_starting(); - - if (position.castling != expected.castling) return false; - if (position.passantable_file != expected.passantable_file) return false; - if (position.turn != expected.turn) return false; - if (position.fullmove_clock != expected.fullmove_clock) return false; - if (position.halfmove_clock != expected.halfmove_clock) return false; - if (position.bitboards[0] != expected.bitboards[0]) return false; - if (position.bitboards[1] != expected.bitboards[1]) return false; - if (position.bitboards[2] != expected.bitboards[2]) return false; - if (position.bitboards[3] != expected.bitboards[3]) return false; - if (position.bitboards[4] != expected.bitboards[4]) return false; - if (position.bitboards[5] != expected.bitboards[5]) return false; - if (position.bitboards[6] != expected.bitboards[6]) return false; - if (position.bitboards[7] != expected.bitboards[7]) return false; - if (position.bitboards[8] != expected.bitboards[8]) return false; - if (position.bitboards[9] != expected.bitboards[9]) return false; - if (position.bitboards[10] != expected.bitboards[10]) return false; - if (position.bitboards[11] != expected.bitboards[11]) return false; - - return true; -} -#endif diff --git a/src/engine/fen.h b/src/engine/fen.h deleted file mode 100644 index d45240e..0000000 --- a/src/engine/fen.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef FEN_H -#define FEN_H - -#include "bitboard.h" - -struct fen_load { - bool failed; - position_t position; -}; -struct fen_load load_fen(const char* fen); - -#endif // FEN_H diff --git a/src/engine/ints.h b/src/engine/ints.h deleted file mode 100644 index 4a0cfe3..0000000 --- a/src/engine/ints.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef INTS_H -#define INTS_H - -#include -#include - -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; -typedef __uint128_t u128; -typedef int8_t i8; -typedef int16_t i16; -typedef int32_t i32; -typedef int64_t i64; -typedef __int128_t i128; -typedef float f32; -typedef double f64; - -#endif // !INTS_H diff --git a/src/engine/moves.c b/src/engine/moves.c index d338cc2..797e770 100644 --- a/src/engine/moves.c +++ b/src/engine/moves.c @@ -1,5 +1,5 @@ #include "moves.h" -#include "bitboard.h" +#include "../bitboard.h" #include "moves/vec.c" #include "moves/king.c" #include "moves/knight.c" diff --git a/src/engine/moves.h b/src/engine/moves.h index bd88eeb..86c4844 100644 --- a/src/engine/moves.h +++ b/src/engine/moves.h @@ -1,8 +1,8 @@ #ifndef MOVES_H #define MOVES_H -#include "ints.h" -#include "bitboard.h" +#include "../ints.h" +#include "../bitboard.h" typedef u8 square_t; diff --git a/src/fen.c b/src/fen.c new file mode 100644 index 0000000..cdbee49 --- /dev/null +++ b/src/fen.c @@ -0,0 +1,198 @@ +#include +#include + +#include "fen.h" +#include "bitboard.h" + +int get_castling(char c) { + if (c == 'K') return WHITE_SHORT_CASTLE; + if (c == 'Q') return WHITE_LONG_CASTLE; + if (c == 'k') return BLACK_SHORT_CASTLE; + if (c == 'q') return BLACK_LONG_CASTLE; + return -1; +} + +int get_turn(char c) { + if (c == 'w') return WHITE_TURN; + if (c == 'b') return BLACK_TURN; + return -1; +} + +int get_piece_enum_item(char c) { + if (c == 'P') return WHITE_PAWN; + if (c == 'N') return WHITE_KNIGHT; + if (c == 'B') return WHITE_BISHOP; + if (c == 'R') return WHITE_ROOK; + if (c == 'Q') return WHITE_QUEEN; + if (c == 'K') return WHITE_KING; + + if (c == 'p') return BLACK_PAWN; + if (c == 'n') return BLACK_KNIGHT; + if (c == 'b') return BLACK_BISHOP; + if (c == 'r') return BLACK_ROOK; + if (c == 'q') return BLACK_QUEEN; + if (c == 'k') return BLACK_KING; + + return -1; +} + +/* + * from Wikipedia + * Piece placement data + * Each rank is described, starting with rank 8 and ending with rank 1, + * with a "/" between each one; within each rank, the contents of the + * squares are described in order from the a-file to the h-file. + * Each piece is identified by a single letter taken from the standard + * English names in algebraic notation + * (pawn = "P", knight = "N", bishop = "B", + * rook = "R", queen = "Q", and king = "K"). + * White pieces are designated using uppercase letters ("PNBRQK"), + * while black pieces use lowercase letters ("pnbrqk"). + * A set of one or more consecutive empty squares within a rank is denoted + * by a digit from "1" to "8", corresponding to the number of squares. + * Active color + * "w" means that White is to move; "b" means that Black is to move. + * Castling availability + * If neither side has the ability to castle, this field uses the character + * "-". Otherwise, this field contains one or more letters: + * "K" if White can castle kingside, + * "Q" if White can castle queenside, + * "k" if Black can castle kingside, + * and "q" if Black can castle queenside. + * A situation that temporarily prevents castling does not + * prevent the use of this notation. + * En passant target square + * This is a square over which a pawn has just passed while moving two + * squares; it is given in algebraic notation. + * If there is no en passant target square, this field uses the character "-". + * This is recorded regardless of whether there is a pawn in position to + * capture en passant. An updated version of the spec has since made it + * so the target square is recorded only if a legal en passant capture is + * possible, but the old version of the standard + * is the one most commonly used. + * Halfmove clock + * The number of halfmoves since the last capture or pawn advance, + * used for the fifty-move rule. + * Fullmove number + * The number of the full moves. + * It starts at 1 and is incremented after Black's move. + * + * e.g. 1B6/2n5/p1N1P2R/P1K3N1/4Pk2/1Q2p2p/6nP/1B4R1 w - - 0 1 + */ +struct fen_load load_fen(const char* fen) { + position_t position = {0}; + + int square = 56; + int i = -1; + char c; + while ((c = fen[++i]) != ' ') { + if (c >= '0' && c <= '9') { + if (c == '9') return (struct fen_load) { true, position }; + square += c - '0'; + continue; + } + if (c == '/') { + square -= 16; + continue; + } + + int piece_type = get_piece_enum_item(c); + if (piece_type == -1) return (struct fen_load) { true, position }; + position.bitboards[piece_type] |= (bitboard_t)1 << square++; + } + + c = fen[++i]; + int turn = get_turn(c); + if (turn == -1) return (struct fen_load) { true, position }; + position.turn = turn; + if (fen[++i] != ' ') return (struct fen_load) { true, position }; + + while ((c = fen[++i]) != ' ') { + if (c == '-') continue; + int castling = get_castling(c); + if (castling == -1) return (struct fen_load) { true, position }; + position.castling |= castling; + } + + c = fen[++i]; + if (c >= 'a' && c <= 'z') { + if (c > 'h') return (struct fen_load) { true, position }; + position.passantable_file = c - 'a' + 1; + c = fen[++i]; + if (c < '1' && c > '8') return (struct fen_load) { true, position }; + } else { + position.passantable_file = 0; + } + if (fen[++i] != ' ') return (struct fen_load) { true, position }; + + while ((c = fen[++i]) != ' ') { + if (c < '0' || c > '9') return (struct fen_load) { true, position }; + position.halfmove_clock *= 10; + position.halfmove_clock += c - '0'; + } + + while ((c = fen[++i]) != 0) { + if (c < '0' || c > '9') return (struct fen_load) { true, position }; + position.fullmove_clock *= 10; + position.fullmove_clock += c - '0'; + } + + bool error = !check_valid_position(position); + return (struct fen_load) { error, position }; +} + +#ifdef TEST_MOD +#include "bitboard.c" + +bool test_fen_no_passant() { + struct fen_load r = load_fen("1B6/2n5/p1N1P2R/P1K3N1/4Pk2/1Q2p2p/6nP/1B4R1 w - - 0 1"); + if (r.failed) return false; + + position_t p = r.position; + if (p.castling != 0) return false; + if (p.passantable_file != 0) return false; + return true; +} +bool test_fen_passant() { + struct fen_load r = load_fen("rnbqkbnr/ppp1p1pp/8/3pPp2/8/8/PPPP1PPP/RNBQKBNR w KQkq f6 0 3"); + if (r.failed) return false; + + position_t p = r.position; + if ( + p.castling != ( + WHITE_LONG_CASTLE | WHITE_SHORT_CASTLE | + BLACK_LONG_CASTLE | BLACK_SHORT_CASTLE + ) + ) return false; + if (p.passantable_file != 6) return false; + return true; +} + +bool test_starting_position() { + struct fen_load r = load_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); + if (r.failed) return false; + + position_t position = r.position; + position_t expected = position_starting(); + + if (position.castling != expected.castling) return false; + if (position.passantable_file != expected.passantable_file) return false; + if (position.turn != expected.turn) return false; + if (position.fullmove_clock != expected.fullmove_clock) return false; + if (position.halfmove_clock != expected.halfmove_clock) return false; + if (position.bitboards[0] != expected.bitboards[0]) return false; + if (position.bitboards[1] != expected.bitboards[1]) return false; + if (position.bitboards[2] != expected.bitboards[2]) return false; + if (position.bitboards[3] != expected.bitboards[3]) return false; + if (position.bitboards[4] != expected.bitboards[4]) return false; + if (position.bitboards[5] != expected.bitboards[5]) return false; + if (position.bitboards[6] != expected.bitboards[6]) return false; + if (position.bitboards[7] != expected.bitboards[7]) return false; + if (position.bitboards[8] != expected.bitboards[8]) return false; + if (position.bitboards[9] != expected.bitboards[9]) return false; + if (position.bitboards[10] != expected.bitboards[10]) return false; + if (position.bitboards[11] != expected.bitboards[11]) return false; + + return true; +} +#endif diff --git a/src/fen.h b/src/fen.h new file mode 100644 index 0000000..d45240e --- /dev/null +++ b/src/fen.h @@ -0,0 +1,12 @@ +#ifndef FEN_H +#define FEN_H + +#include "bitboard.h" + +struct fen_load { + bool failed; + position_t position; +}; +struct fen_load load_fen(const char* fen); + +#endif // FEN_H diff --git a/src/ints.h b/src/ints.h new file mode 100644 index 0000000..4a0cfe3 --- /dev/null +++ b/src/ints.h @@ -0,0 +1,20 @@ +#ifndef INTS_H +#define INTS_H + +#include +#include + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; +typedef __uint128_t u128; +typedef int8_t i8; +typedef int16_t i16; +typedef int32_t i32; +typedef int64_t i64; +typedef __int128_t i128; +typedef float f32; +typedef double f64; + +#endif // !INTS_H diff --git a/src/ipc.c b/src/ipc.c index d7ef968..9c4dfcc 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -1,133 +1,40 @@ #ifndef IPC_C #define IPC_C -#include -#include - -#include "engine/fen.h" - -typedef struct { - struct uci_move *moves; - int count; - int capacity; -} comm_moves; - -void add_comm_move(comm_moves *moves, struct uci_move move) { - if (moves->count + 1 > moves->capacity) { - moves->capacity += 50; - moves->moves = realloc(moves->moves, moves->capacity * sizeof(struct uci_move)); - } - moves->moves[moves->count++] = move; -} - -typedef struct { - bool engine_message_ready; - int depth; - int seldepth; - int multipv; - int score_cp; - int nodes; - int nps; - int hashfull; - int tbhits; - int time; - comm_moves pv; - - bool uci_message_ready; - struct fen_load from_position; - comm_moves moves; -} comms; +#include "ipc.h" // https://stackoverflow.com/a/5656561 -comms* create_shared_memory() { +void* create_shared_memory(size_t size) { int protection = PROT_READ | PROT_WRITE; int visibility = MAP_SHARED | MAP_ANONYMOUS; - comms* state = (comms*)mmap( + return mmap( NULL, - sizeof(comms), + size, protection, visibility, -1, 0 ); - state->engine_message_ready = false; - state->depth = 0; - state->seldepth = 0; - state->multipv = 0; - state->score_cp = 0; - state->nodes = 0; - state->nps = 0; - state->hashfull = 0; - state->tbhits = 0; - state->time = 0; - state->pv = (comm_moves) { - (comms*)mmap( - NULL, - sizeof(struct uci_move) * 50, - protection, visibility, - -1, 0 - ), 0, 50 - }; - state->uci_message_ready = false; - state->from_position = {0}; - state->moves = (comm_moves) { - (comms*)mmap( - NULL, - sizeof(struct uci_move) * 50, - protection, visibility, - -1, 0 - ), 0, 50 - }; - - return state; -} - -void send_uci_message( - comms *comms, - struct fen_load from_position -) { - comms->from_position = from_position; - comms->uci_message_ready = true; -} - -void send_engine_message( - comms *comms, - int depth, - int seldepth, - int multipv, - int score_cp, - int nodes, - int nps, - int hashfull, - int tbhits, - int time -) { - comms->depth = depth; - comms->seldepth = seldepth; - comms->multipv = multipv; - comms->score_cp = score_cp; - comms->nodes = nodes; - comms->nps = nps; - comms->hashfull = hashfull; - comms->tbhits = tbhits; - comms->time = time; - comms->engine_message_ready = true; } -bool receive_uci_message(comms *comms) { - if (comms->uci_message_ready) { - comms->uci_message_ready = false; - return true; - } - return false; +comm_moves comm_moves_init() { + return (comm_moves) { + create_shared_memory(sizeof(struct uci_move) * 50), + 0, + 50 + }; } -// TODO: think about dealing with multiple engine messages -bool receive_engine_message(comms *comms) { - if (comms->engine_message_ready) { - comms->engine_message_ready = false; - return true; +void add_comm_move(comm_moves *moves, struct uci_move move) { + if (moves->count + 1 > moves->capacity) { + moves->capacity += 50; + moves->moves = realloc( + moves->moves, + moves->capacity * sizeof(struct uci_move) + ); } - return false; + moves->moves[moves->count++] = move; } +#include "fen.c" +#include "bitboard.c" #endif // IPC_C diff --git a/src/ipc.h b/src/ipc.h new file mode 100644 index 0000000..98ce6d3 --- /dev/null +++ b/src/ipc.h @@ -0,0 +1,45 @@ +#ifndef IPC_H +#define IPC_H + +#include +#include + +#include "fen.h" +#include "uci/state.h" + +void* create_shared_memory(size_t size); + +typedef struct { + struct uci_move *moves; + int count; + int capacity; +} comm_moves; + +struct engine_message { + int depth; + int seldepth; + int multipv; + int score_cp; + int nodes; + int nps; + int hashfull; + int tbhits; + int time; + comm_moves pv; + + struct engine_message *next; +}; + +enum { MESSAGE_FILLED, MESSAGE_READ, MESSAGE_PROCESSED }; +typedef struct { + struct engine_message engine_message; + + int uci_message_ready; + struct fen_load from_position; + comm_moves moves; +} comms; + +comm_moves comm_moves_init(); +void add_comm_move(comm_moves *moves, struct uci_move move); + +#endif // IPC_H diff --git a/src/uci.c b/src/uci.c index a31411f..3bfd8d3 100644 --- a/src/uci.c +++ b/src/uci.c @@ -4,11 +4,13 @@ #include #include #include -#include +#include #include "uci/state.h" #include "uci/command.h" #include "uci/response.h" +#include "uci.h" +#include "ipc.h" void load_from_message(ucicmd* cmd, const char* message) { char token[MAX_TOKEN_SIZE]; @@ -32,7 +34,9 @@ void load_from_message(ucicmd* cmd, const char* message) { ucicmd_add(cmd, token); } -int main(int argc, char** argv) { +int uci(comms *com) { + printf("%d\n", com->uci_message_ready); + // https://stackoverflow.com/a/41559081 fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); diff --git a/src/uci.h b/src/uci.h new file mode 100644 index 0000000..426ff77 --- /dev/null +++ b/src/uci.h @@ -0,0 +1,8 @@ +#ifndef UCI_H +#define UCI_H + +#include "ipc.h" + +int uci(comms *com); + +#endif // UCI_H diff --git a/src/uci/response.c b/src/uci/response.c index a7e53fd..83a8ee1 100644 --- a/src/uci/response.c +++ b/src/uci/response.c @@ -3,8 +3,8 @@ #include #include "response.h" -#include "fen.h" -#include "bitboard.h" +#include "../fen.h" +#include "../bitboard.h" void apply_option(uci_state *state, char *name, char *buffer) { int settings_count = sizeof(state->option_settings)/sizeof(option_setting_t); @@ -151,7 +151,7 @@ void handle_idle(uci_state *state, ucicmd cmd) { } else { assert(0); } if (cmd.args_count >= k) return; - assert(ucicmd_get_arg(cmd, k++), "moves") == 0); + assert(strcmp(ucicmd_get_arg(cmd, k++), "moves") == 0); struct uci_move *moves = malloc((cmd.args_count - k) * sizeof(struct uci_move)); int l = 0; for (; k < cmd.args_count; k++) { diff --git a/src/uci/state.h b/src/uci/state.h index cb0d63f..849a08a 100644 --- a/src/uci/state.h +++ b/src/uci/state.h @@ -1,7 +1,7 @@ #ifndef UCI_STATE_H #define UCI_STATE_H -#include "engine/fen.h" +#include "../fen.h" typedef struct { char* data; -- cgit v1.2.3