]> git.sesse.net Git - pgn-extract/blobdiff - apply.c
Add support for outputting positions in my own bit-packed FEN format.
[pgn-extract] / apply.c
diff --git a/apply.c b/apply.c
index 53118d28fa601b0642df9a42d72db60dab383b3d..bd7b4721e2467974ad26db29c97a05f2e0d31d9b 100644 (file)
--- a/apply.c
+++ b/apply.c
@@ -714,6 +714,9 @@ apply_move(Colour colour,Move *move_details, Board *board)
             move_details->epd = (char *) MallocOrDie(FEN_SPACE);
             build_basic_EPD_string(board,move_details->epd);
         }
+        else if(GlobalState.output_format == SESSE_BIN){
+            build_BPFEN_string(board, &move_details->bpfen, &move_details->bpfen_len);
+        }
 
        if(move_details->class != NULL_MOVE) {
            make_move(move_details->class, move_details->from_col,move_details->from_rank,
@@ -1792,6 +1795,104 @@ build_FEN_string(const Board *board,char *fen)
     sprintf(&fen[ix],"%u", full_move_number);
 }
 
+void
+build_BPFEN_string(const Board *board,char **bpfen, int* bpfen_len)
+{   static int bits[256];   /* Max six bits per piece, 32 blanks, and then some. */
+    int bit_pos = 0;
+    Rank rank;
+    int ix = 0;
+    for(rank = LASTRANK; rank >= FIRSTRANK; rank--){
+        Col col;
+        for(col = FIRSTCOL; col <= LASTCOL; col++){
+            int coloured_piece = board->board[RankConvert(rank)]
+                                             [ColConvert(col)];
+            if(coloured_piece == EMPTY){
+                bits[bit_pos++] = 0;
+                continue;
+            }
+            bits[bit_pos++] = 1;
+            bits[bit_pos++] = (EXTRACT_COLOUR(coloured_piece) == WHITE) ? 1 : 0;
+            switch(EXTRACT_PIECE(coloured_piece)) {
+                case PAWN:
+                    bits[bit_pos++] = 0;
+                    break;
+                case KNIGHT:
+                    bits[bit_pos++] = 1;
+                    bits[bit_pos++] = 0;
+                    bits[bit_pos++] = 0;
+                    break;
+                case BISHOP:
+                    bits[bit_pos++] = 1;
+                    bits[bit_pos++] = 0;
+                    bits[bit_pos++] = 1;
+                    break;
+                case ROOK:
+                    bits[bit_pos++] = 1;
+                    bits[bit_pos++] = 1;
+                    bits[bit_pos++] = 1;
+                    bits[bit_pos++] = 0;
+                    break;
+                case QUEEN:
+                    bits[bit_pos++] = 1;
+                    bits[bit_pos++] = 1;
+                    bits[bit_pos++] = 1;
+                    bits[bit_pos++] = 1;
+                    bits[bit_pos++] = 0;
+                    break;
+                case KING:
+                    bits[bit_pos++] = 1;
+                    bits[bit_pos++] = 1;
+                    bits[bit_pos++] = 1;
+                    bits[bit_pos++] = 1;
+                    bits[bit_pos++] = 1;
+                    break;
+            }
+        }
+    }
+    /* Pad board. */
+    while ((bit_pos % 8) != 0) {
+        bits[bit_pos++] = 0;
+    }
+
+    /* Non-board information. */
+    bits[bit_pos++] = (board->to_move == WHITE) ? 0 : 1;
+    bits[bit_pos++] = board->WKingCastle ? 1 : 0;
+    bits[bit_pos++] = board->WQueenCastle ? 1 : 0;
+    bits[bit_pos++] = board->BKingCastle ? 1 : 0;
+    bits[bit_pos++] = board->BQueenCastle ? 1 : 0;
+
+    if(board->EnPassant){
+        int col_index = board->ep_col - COLBASE;
+        bits[bit_pos++] = 1;
+        bits[bit_pos++] = (col_index >> 2) & 1;
+        bits[bit_pos++] = (col_index >> 1) & 1;
+        bits[bit_pos++] = col_index & 1;
+    }
+    else{
+        bits[bit_pos++] = 0;
+    }
+
+    /* Pad non-board. */
+    while ((bit_pos % 8) != 0) {
+        bits[bit_pos++] = 0;
+    }
+
+    /* Convert from bits to binary form. */
+    *bpfen = (char *)malloc(bit_pos / 8);
+    *bpfen_len = bit_pos / 8;
+
+    for (ix = 0; ix < bit_pos / 8; ++ix) {
+        unsigned char ch = 0;
+        int jx;
+
+        for (jx = 0; jx < 8; ++jx) {
+            ch |= (bits[ix * 8 + jx] << jx);
+        }
+
+        (*bpfen)[ix] = ch;
+    }
+}
+
     /* Append to move_details a FEN comment of the board.
      * The board state is immediately following application of the
      * given move.