diff options
| author | Aargh Rai <aargh.rai+git@gmail.com> | 2026-07-06 23:39:55 +0530 |
|---|---|---|
| committer | Aargh Rai <aargh.rai+git@gmail.com> | 2026-07-06 23:39:55 +0530 |
| commit | 3c540db464f4034d0a393b076c79a26851f68f47 (patch) | |
| tree | e9e94fb838b05818948f4f4596f0db6acba4402c /src/fen.c | |
| parent | 1876294f217d7faa2a07dbaaaab82d142ce42803 (diff) | |
removed unnescessary stuff + ipc with shared memory + somehow the build is faster?
Diffstat (limited to 'src/fen.c')
| -rw-r--r-- | src/fen.c | 198 |
1 files changed, 198 insertions, 0 deletions
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 <assert.h> +#include <stdbool.h> + +#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 |
