How to Create Games from Custom FEN Positions
This guide shows how to initialise a chess game starting from an arbitrary Forsyth-Edwards Notation (FEN) position, such as endgame studies or tactical puzzle setups, ensuring that the PGN output automatically includes the appropriate SetUp and FEN header tags.
1. Overview of Symbols
scid_position_create_from_fen: Parses a FEN string and constructs an initial board position.scid_game_create_blank: Initialises a game whose root state matches the provided board position rather than the standard starting setup.scid_game_tag_get: Queries header tags, including automatically generatedFENandSetUptags.scid_game_to_pgn: Formats and exports the nonstandard game to valid PGN text.
2. Complete Recipe
#include <scid/scid.h>
#include <stdio.h>
#include <string.h>
static int
check(
scid_error error,
const char* call)
{
if (error == SCID_OK)
{
return 1;
}
fprintf(stderr, "%s failed with scid_error %hu\n", call, error);
return 0;
}
static int
contains(
const char* text,
const char* needle)
{
return strstr(text, needle) != NULL;
}
int
main(void)
{
const char* fen = "8/K7/8/8/7k/8/8/8 w - - 45 25";
scid_position* position = NULL;
scid_game* game = NULL;
char text[4096];
size_t text_size = 0;
size_t tag_count = 0;
if (!check(scid_position_create_from_fen(fen, &position), "scid_position_create_from_fen") ||
!check(scid_game_create_blank(position, &game), "scid_game_create_blank") ||
!check(scid_game_tag_set(game, "Event", "Study position"), "scid_game_tag_set") ||
!check(scid_game_tag_get(game, "FEN", text, sizeof(text), &text_size), "scid_game_tag_get"))
{
scid_game_free(game);
scid_position_free(position);
return 1;
}
printf("start fen: %.*s\n", (int)text_size, text);
if (text_size != strlen(fen) || strncmp(text, fen, text_size) != 0)
{
scid_game_free(game);
scid_position_free(position);
return 1;
}
if (!check(scid_game_tag_count_get(game, &tag_count), "scid_game_tag_count_get") ||
tag_count != 8 ||
!check(scid_game_to_pgn(game, NULL, text, sizeof(text), &text_size), "scid_game_to_pgn"))
{
scid_game_free(game);
scid_position_free(position);
return 1;
}
printf("%.*s", (int)text_size, text);
if (!contains(text, "[Event \"Study position\"]") ||
!contains(text, "[FEN \"8/K7/8/8/7k/8/8/8 w - - 45 25\"]"))
{
scid_game_free(game);
scid_position_free(position);
return 1;
}
scid_game_free(game);
scid_position_free(position);
return 0;
}
3. Key Concepts and Patterns
Handling Nonstandard Start Positions
When a game is created from a non-standard board state via scid_game_create_blank(position, &game), libscid automatically sets the SetUp tag to "1" and populates the FEN tag with the exact board descriptor:
const char* fen = "8/K7/8/8/7k/8/8/8 w - - 45 25";
scid_position* position = NULL;
scid_game* game = NULL;
scid_position_create_from_fen(fen, &position);
scid_game_create_blank(position, &game);
When exported to PGN, the resulting text contains: