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,
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.
void set_output_piece_characters(const char *letters);
char coloured_piece_to_SAN_letter(Piece coloured_piece);
void build_basic_EPD_string(const Board *board,char *fen);
+void build_BPFEN_string(const Board *board,char **bpfen, int* bpfen_len);
char SAN_piece_letter(Piece piece);
const char *piece_str(Piece piece);
void build_FEN_string(const Board *board,char *fen);
if(next->epd != NULL){
(void) free((void *)next->epd);
}
+ if(next->bpfen != NULL){
+ (void) free((void *)next->bpfen);
+ }
if(next->terminating_result != NULL){
(void) free((void *)next->terminating_result);
}
static void print_algebraic_game(Game current_game,FILE *outputfile,
unsigned move_number,Boolean white_to_move,
Board *final_board);
+static void output_sesse_bin_game(Game current_game,FILE *outputfile,
+ unsigned move_number,Boolean white_to_move);
static void print_epd_game(Game current_game,FILE *outputfile,
unsigned move_number,Boolean white_to_move,
Board *final_board);
{ "elalg", ELALG },
{ "uci", UCI },
{ "cm", CM },
+ { "sessebin", SESSE_BIN },
{ "", SOURCE },
/* Add others before the terminating NULL. */
{ (const char *) NULL, SAN }
static const char PGN_suffix[] = ".pgn";
static const char EPD_suffix[] = ".epd";
static const char CM_suffix[] = ".cm";
+ static const char BIN_suffix[] = ".bin";
switch(format){
case SOURCE:
return EPD_suffix;
case CM:
return CM_suffix;
+ case SESSE_BIN:
+ return BIN_suffix;
default:
return PGN_suffix;
}
case CM:
output_cm_game(outputfile,move_number,white_to_move,current_game);
break;
+ case SESSE_BIN:
+ output_sesse_bin_game(current_game,outputfile,move_number,white_to_move);
+ break;
default:
fprintf(GlobalState.logfile,
"Internal error: unknown output type %d in output_game().\n",
putc('\n',outputfile);
}
+static void
+output_sesse_bin_game(Game current_game,FILE *outputfile,
+ unsigned move_number,Boolean white_to_move)
+{
+ const char *result = NULL;
+ Move *move;
+
+ // Find the result. Skip games with no result.
+ for (move = current_game.moves; move != NULL; move = move->next) {
+ if (move->terminating_result) {
+ result = move->terminating_result;
+ }
+ }
+ if (result == NULL || strcmp(result, "*") == 0) {
+ return;
+ }
+
+ int result_int = -1;
+ if (strcmp(result, "1-0") == 0) {
+ result_int = 0;
+ } else if (strcmp(result, "1/2-1/2") == 0) {
+ result_int = 1;
+ } else if (strcmp(result, "0-1") == 0) {
+ result_int = 2;
+ } else {
+ fprintf(stderr, "Unknown result '%s'\n", result);
+ return;
+ }
+
+ // Find Black and White Elos. Skip games with no Elo.
+ const char *white_elo_tag = current_game.tags[WHITE_ELO_TAG];
+ const char *black_elo_tag = current_game.tags[BLACK_ELO_TAG];
+ if (white_elo_tag == NULL || black_elo_tag == NULL) {
+ return;
+ }
+
+ int white_elo = atoi(white_elo_tag);
+ int black_elo = atoi(black_elo_tag);
+
+ for (move = current_game.moves; move != NULL; move = move->next) {
+ unsigned int opening = 0; // TODO
+
+ // key
+ putc(move->bpfen_len + strlen((char *)move->move), outputfile);
+ fwrite(move->bpfen, move->bpfen_len, 1, outputfile);
+ fwrite(move->move, strlen((char *)move->move), 1, outputfile);
+
+ // value
+ putc(result_int, outputfile);
+ fwrite(&white_elo, sizeof(white_elo), 1, outputfile);
+ fwrite(&black_elo, sizeof(black_elo), 1, outputfile);
+ fwrite(&opening, sizeof(opening), 1, outputfile);
+ }
+}
+
static void
print_epd_move_list(Game current_game,FILE *outputfile,
unsigned move_number, Boolean white_to_move,
* and en-passant notation.
* UCI: UCI-compatible format - actually LALG.
*/
-typedef enum { SOURCE, SAN, EPD, CM, LALG, HALG, ELALG, UCI } OutputFormat;
+typedef enum { SOURCE, SAN, EPD, CM, LALG, HALG, ELALG, UCI, SESSE_BIN } OutputFormat;
/* Define a type to specify whether a move gives check, checkmate,
* or nocheck.
* has been played.
*/
char *epd;
+ /* Same as epd, but in our special binary packed format.
+ * Not zero-terminated, since it is binary.
+ */
+ char *bpfen;
+ int bpfen_len;
StringList *Nags;
CommentList *Comment;
/* terminating_result hold the result of the current list of moves. */