Skip to content
This repository was archived by the owner on Dec 27, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
9d5159b
created API method stubs
Bonifatius94 Aug 4, 2021
4993b4d
refactored start formation with macro
Bonifatius94 Aug 6, 2021
7b583fd
added chessxformat code files
Bonifatius94 Aug 6, 2021
1268f34
beautified code
Bonifatius94 Aug 6, 2021
4feab6d
added exchange format functions (WIP)
Bonifatius94 Aug 6, 2021
4eec793
continued working on FEN parser (WIP)
Bonifatius94 Aug 6, 2021
261a9fb
finished parsing FEN (needs testing)
Bonifatius94 Aug 7, 2021
c38a774
added ChessGameContext type (WIP)
Bonifatius94 Aug 7, 2021
af0e735
continued work on chess game session and FEN (WIP)
Bonifatius94 Aug 7, 2021
2cb54d4
added bit masks, finished apply_draw func
Bonifatius94 Aug 9, 2021
16a8fe6
continued work on FEN parser / serializer
Bonifatius94 Aug 9, 2021
8c3fa34
refactored position parsing logic
Bonifatius94 Aug 10, 2021
aea5883
added en-passant parser logic
Bonifatius94 Aug 10, 2021
dcdd298
refactored position parsing function
Bonifatius94 Aug 10, 2021
4484352
added idea for saving some bits
Bonifatius94 Aug 10, 2021
a79c185
finished session to FEN (needs testing)
Bonifatius94 Aug 10, 2021
ad97e50
finalized implementation (needs more testing)
Bonifatius94 Aug 10, 2021
4d37535
moved chess board functions between code files
Bonifatius94 Aug 12, 2021
5528e0d
fixed header import warnings
Bonifatius94 Aug 12, 2021
78c9211
fixed typecast warnings for py_func declarations
Bonifatius94 Aug 12, 2021
f934380
minor changes
Bonifatius94 Aug 12, 2021
ad75935
fixed parser for 1st FEN section (chess pieces)
Bonifatius94 Aug 12, 2021
7c5a12a
fixed bug, bitwise OR instead of logical OR
Bonifatius94 Aug 12, 2021
6b3177b
fixed several bugs, can parse start formation now
Bonifatius94 Aug 12, 2021
c1f9f21
added ideas how to extend FEN parser unit tests
Bonifatius94 Aug 12, 2021
7381540
fixed bug in rochade game context parser
Bonifatius94 Aug 12, 2021
26fdcf1
beautified code
Bonifatius94 Aug 12, 2021
636a3f5
implemented FEN to game session (as tuple)
Bonifatius94 Aug 12, 2021
1aad307
added more test cases, FEN parser seems solid now
Bonifatius94 Aug 12, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions chesslib/include/chessboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@
D E F I N E M A K R O S
==================================================== */

/* The chess bitboards in start formation */
#define START_FORMATION {\
0x0000000000000010uLL, 0x0000000000000008uLL, 0x0000000000000081uLL,\
0x0000000000000024uLL, 0x0000000000000042uLL, 0x000000000000FF00uLL,\
0x1000000000000000uLL, 0x0800000000000000uLL, 0x8100000000000000uLL,\
0x2400000000000000uLL, 0x4200000000000000uLL, 0x00FF000000000000uLL,\
0x0000FFFFFFFF0000uLL }

/* row masks */
#define ROW_1 0x00000000000000FFuLL
#define ROW_2 0x000000000000FF00uLL
Expand Down Expand Up @@ -115,4 +123,8 @@ void to_simple_board(const Bitboard board[], ChessPiece* target);
void compress_pieces_array(const ChessPiece pieces[], uint8_t* compr_bytes);
void uncompress_pieces_array(const uint8_t compr_bytes[], ChessPiece* out_pieces);

Bitboard get_captured_fields(const Bitboard bitboards[], ChessColor side);
void get_board_positions(Bitboard bitboard, ChessPosition* out_positions, size_t* out_length);
ChessPosition get_board_position(Bitboard bitboard);

#endif
61 changes: 61 additions & 0 deletions chesslib/include/chessgamesession.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* MIT License
*
* Copyright(c) 2020 Marco Tröster
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#ifndef CHESSGAMESESSION_H
#define CHESSGAMESESSION_H

#include "chesstypes.h"
#include "chessboard.h"
#include "chessdraw.h"

/* A chess game session semantically at least as powerful as the FEN notation.
It is supposed to help carrying out professional chess matches. */
typedef struct _CHESS_GAME_SESSION {
Bitboard board[13];
ChessGameContext context;
} ChessGameSession;

/* default game context bits: 00000000 00001000 00011110 00000000
*
* meaning:
* first game round, all rochades possible, no en-passant possible,
* white drawing and zero halfdraws since the last pawn draw.
*/
#define DEFAULT_GAME_CONTEXT 0x00081E00uL

/* initial game session: board in start formation and initial game context */
#define INIT_GAME_SESSION {START_FORMATION, DEFAULT_GAME_CONTEXT}

ChessGameContext create_context(ChessColor side, uint8_t en_passants,
uint8_t rochades, uint8_t halfdraws_since_last_pawn_draw, int game_round);

Bitboard get_en_passant_mask(ChessGameContext context);
Bitboard get_rochade_mask(ChessGameContext context);
uint8_t get_hdslpd(ChessGameContext context);
int get_game_rounds(ChessGameContext context);

void apply_draw_to_context(ChessDraw draw, ChessGameContext* context);
void apply_game_context_to_board(Bitboard* board, ChessGameContext context);

#endif
1 change: 1 addition & 0 deletions chesslib/include/chesslibmodule.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,6 @@
#include "chesspieceatpos.h"
#include "chessposition.h"
#include "chesstypes.h"
#include "chessxformat.h"

#endif
2 changes: 2 additions & 0 deletions chesslib/include/chessposition.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

#include <stdint.h>
#include <stdlib.h>
#include <ctype.h>

/* ====================================================
D E F I N E F U N C T I O N S
Expand All @@ -45,6 +46,7 @@ ChessPosition create_position(int8_t row, int8_t column);
int8_t get_row(ChessPosition position);
int8_t get_column(ChessPosition position);

int position_from_string(const char* pos_str, ChessPosition* pos);
void position_to_string(ChessPosition position, char* pos_str);

#endif
11 changes: 11 additions & 0 deletions chesslib/include/chesstypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,15 @@ typedef uint16_t CompactChessDraw;
highest bit as H8 (indexes A1=0, B1=1, ..., A2=8, ..., H8=63). */
typedef uint64_t Bitboard;

/* TODO: add a definition for a FEN game session context to replace the was_moved bitboards
e.g. 1 bit for drawing_side, 8 bits for en-passants, 4 bits for rochades,
6 bits for draws_since_last_pawn_draw, remaining bits for game_round
-> new 32-bit integer bitwise type */

/* | game round | halfdraws since pawn draw | rochades | en-passants | side |
| ------------- | ------------------------- | -------- | ----------- | ---- |
| xxxxxxxxxxxxx | xxxxxx | xxxx | xxxxxxxx | x | */
typedef uint32_t ChessGameContext;
/* TODO: think of compressing the en-passant part to 3 bits, pos indices [0-7] */

#endif
45 changes: 45 additions & 0 deletions chesslib/include/chessxformat.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* MIT License
*
* Copyright(c) 2020 Marco Tröster
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#ifndef CHESSXFORMAT_H
#define CHESSXFORMAT_H

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#include "chesstypes.h"
#include "chesspiece.h"
#include "chessboard.h"
#include "chessgamesession.h"

/* TODO: move the board hashing code here */

int chess_session_from_fen(const char fen_str[], ChessGameSession* session);
int chess_session_to_fen(char* fen_str, const ChessGameSession* session);
int chess_session_from_pgn(const char pgn_str[], ChessGameSession* session);
int chess_session_to_pgn(char* pgn_str, const ChessGameSession* session);

#endif
64 changes: 64 additions & 0 deletions chesslib/src/chessboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -350,3 +350,67 @@ void uncompress_pieces_array(const uint8_t compr_bytes[], ChessPiece* out_pieces
out_pieces[pos] = piece_bits;
}
}

/* ====================================================
C H E S S P O S I T I O N S
O N B I T B O A R D
==================================================== */

Bitboard get_captured_fields(const Bitboard bitboards[], ChessColor side)
{
uint8_t offset = SIDE_OFFSET(side);

return bitboards[offset] | bitboards[offset + 1] | bitboards[offset + 2]
| bitboards[offset + 3] | bitboards[offset + 4] | bitboards[offset + 5];
}

void get_board_positions(Bitboard bitboard, ChessPosition* out_positions, size_t* out_length)
{
uint8_t pos;
*out_length = 0;

/* loop through all bits of the board */
for (pos = 0; pos < 64; pos++)
{
if ((bitboard & 0x1uLL << pos)) { out_positions[(*out_length)++] = (ChessPosition)pos; }
}
}

/**************************************************************************************************
this returns the index of the highest bit set on the given bitboard.
if the given bitboard has multiple bits set, only the position of the highest bit is returned.
info: the result is mathematically equal to floor(log2(x))
**************************************************************************************************/
ChessPosition get_board_position(Bitboard bitboard)
{
/* code was taken from https://stackoverflow.com/questions/11376288/fast-computing-of-log2-for-64-bit-integers */

#ifdef __GNUC__
/* use built-in leading zeros function for GCC Linux build
(this compiles to the very fast 'bsr' instruction on x86 AMD processors) */
return (ChessPosition)((unsigned)(8 * sizeof(unsigned long long) - __builtin_clzll(bitboard) - 1));
#else
/* use abstract DeBruijn algorithm with table lookup */
/* TODO: think of implementing this as assembler code */

const uint8_t tab64[64] = {
63, 0, 58, 1, 59, 47, 53, 2,
60, 39, 48, 27, 54, 33, 42, 3,
61, 51, 37, 40, 49, 18, 28, 20,
55, 30, 34, 11, 43, 14, 22, 4,
62, 57, 46, 52, 38, 26, 32, 41,
50, 36, 17, 19, 29, 10, 13, 21,
56, 45, 25, 31, 35, 16, 9, 12,
44, 24, 15, 8, 23, 7, 6, 5
};

bitboard |= bitboard >> 1;
bitboard |= bitboard >> 2;
bitboard |= bitboard >> 4;
bitboard |= bitboard >> 8;
bitboard |= bitboard >> 16;
bitboard |= bitboard >> 32;

return (ChessPosition)tab64[((Bitboard)((bitboard - (bitboard >> 1)) * 0x07EDD5E59A4E28C2uLL)) >> 58];
#endif
}
64 changes: 0 additions & 64 deletions chesslib/src/chessdrawgen.c
Original file line number Diff line number Diff line change
Expand Up @@ -490,67 +490,3 @@ Bitboard get_peasant_draw_positions(const Bitboard bitboards[],

return draws;
}

/* ====================================================
C H E S S P O S I T I O N S
O N B I T B O A R D
==================================================== */

Bitboard get_captured_fields(const Bitboard bitboards[], ChessColor side)
{
uint8_t offset = SIDE_OFFSET(side);

return bitboards[offset] | bitboards[offset + 1] | bitboards[offset + 2]
| bitboards[offset + 3] | bitboards[offset + 4] | bitboards[offset + 5];
}

void get_board_positions(Bitboard bitboard, ChessPosition* out_positions, size_t* out_length)
{
uint8_t pos;
*out_length = 0;

/* loop through all bits of the board */
for (pos = 0; pos < 64; pos++)
{
if ((bitboard & 0x1uLL << pos)) { out_positions[(*out_length)++] = (ChessPosition)pos; }
}
}

/**************************************************************************************************
this returns the index of the highest bit set on the given bitboard.
if the given bitboard has multiple bits set, only the position of the highest bit is returned.
info: the result is mathematically equal to floor(log2(x))
**************************************************************************************************/
ChessPosition get_board_position(Bitboard bitboard)
{
/* code was taken from https://stackoverflow.com/questions/11376288/fast-computing-of-log2-for-64-bit-integers */

#ifdef __GNUC__
/* use built-in leading zeros function for GCC Linux build
(this compiles to the very fast 'bsr' instruction on x86 AMD processors) */
return (ChessPosition)((unsigned)(8 * sizeof(unsigned long long) - __builtin_clzll(bitboard) - 1));
#else
/* use abstract DeBruijn algorithm with table lookup */
/* TODO: think of implementing this as assembler code */

const uint8_t tab64[64] = {
63, 0, 58, 1, 59, 47, 53, 2,
60, 39, 48, 27, 54, 33, 42, 3,
61, 51, 37, 40, 49, 18, 28, 20,
55, 30, 34, 11, 43, 14, 22, 4,
62, 57, 46, 52, 38, 26, 32, 41,
50, 36, 17, 19, 29, 10, 13, 21,
56, 45, 25, 31, 35, 16, 9, 12,
44, 24, 15, 8, 23, 7, 6, 5
};

bitboard |= bitboard >> 1;
bitboard |= bitboard >> 2;
bitboard |= bitboard >> 4;
bitboard |= bitboard >> 8;
bitboard |= bitboard >> 16;
bitboard |= bitboard >> 32;

return (ChessPosition)tab64[((Bitboard)((bitboard - (bitboard >> 1)) * 0x07EDD5E59A4E28C2uLL)) >> 58];
#endif
}
Loading