- /* 
-     Protector -- a UCI chess engine 
-   
-     Copyright (C) 2009-2010 Raimund Heid (Raimund_Heid@yahoo.com) 
-   
-     This program is free software: you can redistribute it and/or modify 
-     it under the terms of the GNU General Public License as published by 
-     the Free Software Foundation, either version 3 of the License, or 
-     (at your option) any later version. 
-   
-     This program is distributed in the hope that it will be useful, 
-     but WITHOUT ANY WARRANTY; without even the implied warranty of 
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
-     GNU General Public License for more details. 
-   
-     You should have received a copy of the GNU General Public License 
-     along with this program.  If not, see <http://www.gnu.org/licenses/>. 
-   
- */ 
-   
- #include <assert.h> 
- #include <stdlib.h> 
- #include <string.h> 
- #include <ctype.h> 
- #include "io.h" 
- #include "pgn.h" 
- #include "bitboard.h" 
- #include "position.h" 
- #include "movegeneration.h" 
- #include "fen.h" 
-   
- #define BUFSIZE 8192 
- #define INCREMENT 1024 
-   
- #define STATE_INIT      0 
- #define STATE_1         1 
- #define STATE_2         2 
- #define STATE_IGNORE    3 
-   
- static char pieceName[16]; 
-   
- /* 
-  ****************************************************************************** 
-  * 
-  *   File operations 
-  * 
-  ****************************************************************************** 
-  */ 
-   
- static int scanForIndex(PGNFile * pgnfile, int state, char buffer[], 
-                         size_t bufsize, size_t offset) 
- { 
-    size_t i = 0; 
-   
-    while (i < bufsize) 
-    { 
-       switch (buffer[i++]) 
-       { 
-       case '\n': 
-   
-          if (state < STATE_IGNORE) 
-          { 
-             state++; 
-          } 
-   
-          break; 
-   
-       case '\r': 
-       case ' ': 
-          continue; 
-   
-       case '{': 
-   
-          if (state < STATE_IGNORE) 
-          { 
-             state = STATE_IGNORE; 
-          } 
-          else 
-          { 
-             state++; 
-          } 
-   
-          break; 
-   
-       case '}': 
-   
-          if (state > STATE_IGNORE) 
-          { 
-             state--; 
-          } 
-          else 
-          { 
-             state = 0; 
-          } 
-   
-          break; 
-   
-       case '[': 
-   
-          if (state == 2) 
-          { 
-             if (pgnfile->numGames + 1 == pgnfile->indexSize) 
-             { 
-                pgnfile->indexSize += INCREMENT; 
-                pgnfile ->- index  = (long *) realloc(- pgnfile ->- index ,
-                                                  pgnfile->indexSize * 
-                                                  sizeof(long)); 
-             } 
-   
-             pgnfile->index[pgnfile->numGames++] = (long) (i + offset - 1L); 
-             assert(- pgnfile ->- numGames  <-  pgnfile ->- indexSize );
 
-          } 
-   
-          break; 
-   
-       default: 
-   
-          if (state != STATE_IGNORE) 
-          { 
-             state = 0; 
-          } 
-       } 
-    } 
-   
-    return state; 
- } 
-   
- static void buildIndex(PGNFile * pgnfile) 
- { 
-    char buffer[BUFSIZE]; 
-    int state = STATE_2; 
-    size_t numRead; 
-   
-   
-    do 
-    { 
-       long-  pos  = ftell(- pgnfile ->- file );
 
-   
-       numRead  = fread(- buffer , 1,-  BUFSIZE ,-  pgnfile ->- file );
-       state = scanForIndex(pgnfile, state, buffer, numRead, pos); 
-    } 
-    while (numRead == BUFSIZE); 
-   
-    fseek(- pgnfile ->- file , 0,-  SEEK_END );
 
-    pgnfile ->- index [- pgnfile ->- numGames ] = ftell(- pgnfile ->- file ) + 1;
- } 
-   
- int openPGNFile(PGNFile * pgnfile, const char *filename) 
- { 
-    pgnfile ->- index  = (long *) malloc(- INCREMENT  * sizeof(long));
-   
-    pgnfile->indexSize = INCREMENT; 
-    pgnfile->numGames = 0; 
-    pgnfile ->- file  = fopen(- filename , "rb");
-   
-    if (pgnfile->index != 0 && pgnfile->file != 0) 
-    { 
-       buildIndex(pgnfile); 
-       return 0; 
-    } 
-    else 
-    { 
-       return -1; 
-    } 
- } 
-   
- void closePGNFile(PGNFile * pgnfile) 
- { 
-    if (pgnfile->index != 0) 
-    { 
-    } 
-   
-    pgnfile->indexSize = 0; 
-    pgnfile->numGames = 0; 
-   
-    if (pgnfile->file != 0) 
-    { 
-       pgnfile->file = 0; 
-    } 
- } 
-   
- static char *getGameText(PGNFile * pgnfile, int number) 
- { 
-    long start, end, length; 
-    char *buffer; 
-   
-    if (number < 1 || number > pgnfile->numGames) 
-    { 
-       return 0; 
-    } 
-   
-    start = pgnfile->index[number - 1]; 
-    end = pgnfile->index[number] - 1; 
-    length = (int) (end - start); 
-   
-    if ((- buffer  = malloc(- length  + 1)) ==-  NULL )
 
-    { 
-       return 0; 
-    } 
-   
-    fseek(- pgnfile ->- file ,-  start ,-  SEEK_SET );
 
-    fread(- buffer , 1,-  length ,-  pgnfile ->- file );
 
-    buffer[length] = '\0'; 
-    trim(buffer); 
-   
-    return buffer; 
- } 
-   
- /* 
-  ****************************************************************************** 
-  * 
-  *   Object generation and destruction 
-  * 
-  ****************************************************************************** 
-  */ 
-   
- static Gamemove *getGamemove(const Position * position, 
-                              Gamemove * previousMove, PGNGame * game) 
- { 
-    Gamemove *new = &(game->moveHeap[game->nextMoveFromHeap++]); 
-   
-    new->from = NO_SQUARE; 
-    new->to = NO_SQUARE; 
-    new->newPiece = NO_PIECE; 
-    new->position = *position; 
-    new->previousMove = previousMove; 
-    new->nextMove = new->alternativeMove = 0; 
-    new->comment = new->glyphs = 0; 
-   
-    return new; 
- } 
-   
- Move gameMove2Move(const Gamemove * gamemove) 
- { 
-    return getPackedMove(gamemove->from, gamemove->to, gamemove->newPiece); 
- } 
-   
- void initializePGNGame(PGNGame * game) 
- { 
-    game->setup[0] = game->fen[0] = '\0'; 
-    game->moveText = 0; 
-    game->firstMove = game->lastMove = 0; 
-    game->nextMoveFromHeap = 0; 
- } 
-   
- void resetPGNGame(PGNGame * game) 
- { 
-    if (game->moveText != 0) 
-    { 
-    } 
-   
-    initializePGNGame(game); 
- } 
-   
- void freePgnGame(PGNGame * game) 
- { 
-    resetPGNGame(game); 
- } 
-   
- /* 
-  ****************************************************************************** 
-  * 
-  *   Parser operations 
-  * 
-  ****************************************************************************** 
-  */ 
-   
- static Move parsePawnMove(const Position * position, const char *moveText) 
- { 
-    Square from = NO_SQUARE, to = NO_SQUARE; 
-    Piece newPiece = NO_PIECE; 
-    int pawnStep = (position->activeColor == WHITE ? 8 : -8); 
-    size_t-  textLength  = strlen(- moveText );
 
-   
-    if (textLength < 2) 
-    { 
-       return NO_MOVE; 
-    } 
-   
-   
-    /*  
-     * capture or push?  
-     */ 
-    if (textLength >= 4 && moveText[1] == 'x') 
-    { 
-       to = getSquare(moveText[2] - 'a', moveText[3] - '1'); 
-       from = (Square) 
-          (getSquare(moveText[0] - 'a', moveText[3] - '1') - pawnStep); 
-    } 
-    else 
-    { 
-       to = getSquare(moveText[0] - 'a', moveText[1] - '1'); 
-       from = (Square) (to - pawnStep); 
-   
-       if (position->piece[from] == NO_PIECE) 
-       { 
-          from = (Square) (from - pawnStep); 
-       } 
-    } 
-   
-    /*  
-     * promotion?  
-     */ 
-    if (textLength >= 4 && moveText[textLength - 2] == '=') 
-    { 
-       switch (moveText[textLength - 1]) 
-       { 
-       case 'R': 
-          newPiece = WHITE_ROOK; 
-          break; 
-       case 'B': 
-          newPiece = WHITE_BISHOP; 
-          break; 
-       case 'N': 
-          newPiece = WHITE_KNIGHT; 
-          break; 
-       default: 
-          newPiece = WHITE_QUEEN; 
-       } 
-    } 
-   
-    return getPackedMove(from, to, newPiece); 
- } 
-   
- static Move parseCastlingMove(const Position * position, const char *moveText) 
- { 
-    const Rank rank = (position->activeColor == WHITE ? RANK_1 : RANK_8); 
-    const-  File file  = (strcmp(- moveText , "O-O") == 0 ?-  FILE_G  :-  FILE_C );
 
-   
-   
-    return getPackedMove(getSquare(FILE_E, rank), getSquare(file, rank), 
-                         NO_PIECE); 
- } 
-   
- static Move parsePieceMove(const Position * position, 
-                            const char *moveText, const PieceType pieceType) 
- { 
-    Square from = NO_SQUARE, to = NO_SQUARE; 
-    Piece newPiece = NO_PIECE; 
-    size_t-  textLength  = strlen(- moveText );
 
-    int fromFile = -1, fromRank = -1; 
-    size_t pointer = 1; 
-    char currentChar; 
-    Bitboard candidates; 
-   
-    if (textLength < 3) 
-    { 
-       return NO_MOVE; 
-    } 
-   
-   
-    to = getSquare(moveText[textLength - 2] - 'a', 
-                   moveText[textLength - 1] - '1'); 
-   
-    while (pointer < textLength - 2) 
-    { 
-       currentChar = moveText[pointer++]; 
-   
-       if (currentChar >= 'a' && currentChar <= 'h') 
-       { 
-          fromFile = currentChar - 'a'; 
-       } 
-   
-       if (currentChar >= '1' && currentChar <= '8') 
-       { 
-          fromRank = currentChar - '1'; 
-       } 
-    } 
-   
-    if (fromFile != -1 && fromRank != -1) 
-    { 
-       from = getSquare(fromFile, fromRank); 
-    } 
-    else 
-    { 
-       candidates = 
-          getDirectAttackers(position, to, position->activeColor, 
-                             position->allPieces) & 
-          position->piecesOfType[pieceType | position->activeColor]; 
-   
-       if (fromFile != -1) 
-       { 
-          candidates &= getSquaresOfFile((File) fromFile); 
-       } 
-       else if (fromRank != -1) 
-       { 
-          candidates &= getSquaresOfRank((Rank) fromRank); 
-       } 
-   
-       if (candidates == EMPTY_BITBOARD) 
-       { 
-          return NO_MOVE; 
-       } 
-   
-       from = getLastSquare(&candidates); 
-   
-       while (candidates != EMPTY_BITBOARD) 
-       { 
-          const Move move = getPackedMove(from, to, newPiece); 
-   
-          if (moveIsLegal(position, move)) 
-          { 
-             return move; 
-          } 
-   
-          from = getLastSquare(&candidates); 
-       } 
-    } 
-   
-    return getPackedMove(from, to, newPiece); 
- } 
-   
- static Move parsePGNMove(const char *moveText, Position * position) 
- { 
-    char moveTextBuffer[16]; 
-    int i = 0; 
-   
-    while (i < 15 && moveText[i] != 0 && moveText[i] != '+' && 
-           moveText[i] != '#' && moveText[i] != '!' && 
-           moveText[i] != '?' && moveText[i] != ')' && 
-    { 
-       moveTextBuffer[i] = moveText[i]; 
-       i++; 
-    } 
-   
-    moveTextBuffer[i] = 0; 
-   
-    switch (moveTextBuffer[0]) 
-    { 
-    case 'a': 
-    case 'b': 
-    case 'c': 
-    case 'd': 
-    case 'e': 
-    case 'f': 
-    case 'g': 
-    case 'h': 
-       return parsePawnMove(position, moveTextBuffer); 
-       break; 
-    case 'K': 
-       return parsePieceMove(position, moveTextBuffer, KING); 
-       break; 
-    case 'Q': 
-       return parsePieceMove(position, moveTextBuffer, QUEEN); 
-       break; 
-    case 'R': 
-       return parsePieceMove(position, moveTextBuffer, ROOK); 
-       break; 
-    case 'B': 
-       return parsePieceMove(position, moveTextBuffer, BISHOP); 
-       break; 
-    case 'N': 
-       return parsePieceMove(position, moveTextBuffer, KNIGHT); 
-       break; 
-    case 'O': 
-       return parseCastlingMove(position, moveTextBuffer); 
-       break; 
-    default: 
-   
-       return NO_MOVE; 
-    } 
- } 
-   
- Move interpretPGNMove(const char *moveText, PGNGame * game) 
- { 
-    Variation variation; 
-   
-    initializeVariationFromGame(&variation, game); 
-   
-    return parsePGNMove(moveText, &variation.singlePosition); 
- } 
-   
- int appendMove(PGNGame * game, const Move move) 
- { 
-    Variation variation; 
-   
-    initializeVariationFromGame(&variation, game); 
-   
-    if (moveIsLegal(&variation.singlePosition, move)) 
-    { 
-       Gamemove *newMove = 
-          getGamemove(&variation.singlePosition, game->lastMove, game); 
-   
-       newMove->from = getFromSquare(move); 
-       newMove->to = getToSquare(move); 
-       newMove->newPiece = getNewPiece(move); 
-   
-       if (game->lastMove == 0) 
-       { 
-          game->firstMove = game->lastMove = newMove; 
-       } 
-       else 
-       { 
-          game->lastMove->nextMove = newMove; 
-          game->lastMove = newMove; 
-       } 
-   
-       return 0; 
-    } 
-    else 
-    { 
-       return -1; 
-    } 
- } 
-   
- void takebackLastMove(PGNGame * game) 
- { 
-    if (game->lastMove != 0) 
-    { 
-       if (game->lastMove == game->firstMove) 
-       { 
-          game->lastMove = 0; 
-       } 
-       else 
-       { 
-          game->lastMove = game->lastMove->previousMove; 
-       } 
-    } 
- } 
-   
- static void addAlternativeMove(Gamemove * move, Gamemove * alternative) 
- { 
-    if (move->alternativeMove != 0) 
-    { 
-       addAlternativeMove(move->alternativeMove, alternative); 
-    } 
-    else 
-    { 
-       move->alternativeMove = alternative; 
-       alternative->previousMove = move->previousMove; 
-    } 
- } 
-   
- static Gamemove *parseMoveText(const char *pgnMoveText, 
-                                size_t * offset, const Position * position, 
-                                PGNGame * game) 
- { 
-    bool variationTerminated = FALSE; 
-    Gamemove *baseMove = 0, *lastMove = 0; 
-    Variation variation; 
-    char currentChar; 
-    const char *token; 
-    const bool debugOutput = FALSE; 
-   
-    setBasePosition(&variation, position); 
-    prepareSearch(&variation); 
-   
-    if (debugOutput) 
-    { 
-       logDebug("Starting pgn parsing at: >%s<\n", &pgnMoveText[*offset]); 
-    } 
-   
-    while (variationTerminated == FALSE && 
-           (currentChar = pgnMoveText[(*offset)++]) != '\0') 
-    { 
-       if (strchr(" \r\n0123456789.",-  currentChar ) != 0)
 
-       { 
-          continue; 
-       } 
-   
-       token = &(pgnMoveText[*offset - 1]); 
-   
-       if (debugOutput) 
-       { 
-          logDebug("\nCurrent token: >%s<\n", token); 
-       } 
-   
-       if (currentChar == '{') 
-       { 
-          char *comment = getToken(token + 1, "}"); 
-   
-          if (debugOutput) 
-          { 
-             logDebug("Starting annotation: >%s<\n", comment); 
-          } 
-   
-   
-          if (lastMove != 0) 
-          { 
-             lastMove->comment = comment; 
-          } 
-          else 
-          { 
-          } 
-   
-          continue; 
-       } 
-   
-       if (currentChar == '(') 
-       { 
-          if (debugOutput) 
-          { 
-             logDebug("Starting subvariation.\n"); 
-          } 
-   
-          if (lastMove != 0) 
-          { 
-             addAlternativeMove(lastMove, 
-                                parseMoveText(pgnMoveText, offset, 
-                                              &lastMove->position, game)); 
-          } 
-       } 
-   
-       if (currentChar == ')') 
-       { 
-          variationTerminated = TRUE; 
-   
-          if (debugOutput) 
-          { 
-             logDebug("Subvariation terminated.\n"); 
-          } 
-       } 
-   
-       if (currentChar == '$') 
-       { 
-          char *glyph = getToken(token, " )\r\n"); 
-   
-          if (lastMove != 0) 
-          { 
-             if (lastMove->glyphs != 0) 
-             { 
-                if (debugOutput) 
-                { 
-                   logDebug("Existing glyphs: >%s<\n", lastMove->glyphs); 
-                } 
-   
-                lastMove ->- glyphs  = realloc(- lastMove ->- glyphs ,
-                strcat(- lastMove ->- glyphs , " ");
 
-                strcat(- lastMove ->- glyphs ,-  glyph );
 
-             } 
-             else 
-             { 
-                if (debugOutput) 
-                { 
-                   logDebug("Initializing glyphs...\n"); 
-                } 
-   
-                lastMove->glyphs = glyph; 
-             } 
-   
-             if (debugOutput) 
-             { 
-                logDebug("glyphs: >%s<\n", lastMove->glyphs); 
-             } 
-          } 
-          else 
-          { 
-          } 
-       } 
-   
-       if (strchr("KQRBNOabcdefgh",-  currentChar ) != 0)
 
-       { 
-          Move move; 
-   
-          /*dumpPosition(variation->currentPosition); */ 
-   
-          if (debugOutput) 
-          { 
-             logDebug("Move token: >%s<\n", token); 
-          } 
-   
-          move = parsePGNMove(token, &variation.singlePosition); 
-   
-          if (moveIsLegal(&variation.singlePosition, move)) 
-          { 
-             Gamemove *newMove = 
-                getGamemove(&variation.singlePosition, lastMove, game); 
-   
-             newMove->from = getFromSquare(move); 
-             newMove->to = getToSquare(move); 
-             newMove->newPiece = getNewPiece(move); 
-   
-             if (lastMove == 0) 
-             { 
-                baseMove = newMove; 
-             } 
-             else 
-             { 
-                lastMove->nextMove = newMove; 
-             } 
-   
-             lastMove = newMove; 
-             makeMove(&variation, move); 
-             setBasePosition(&variation, &variation.singlePosition); 
-          } 
-          else 
-          { 
-             logDebug("### Illegal move: %s\n", token); 
-             dumpMove(move); 
-             dumpPosition(&variation.singlePosition); 
-   
-             break; 
-          } 
-   
-          while (isspace((int)-  pgnMoveText [*- offset ]) ==-  FALSE  &&
 
-                 pgnMoveText[*offset] != ')') 
-          { 
-             (*offset)++; 
-          } 
-       } 
-    } 
-   
-    return baseMove; 
- } 
-   
- static Gamemove *parseMoveSection(const char *pgnMoveText, 
-                                   const Position * position, PGNGame * game) 
- { 
-    size_t offset = 0; 
-   
-    return parseMoveText(pgnMoveText, &offset, position, game); 
- } 
-   
- static void parseRoasterValue(const char *pgn, const char *name, 
-                               char value[PGN_ROASTERLINE_SIZE]) 
- { 
-    char *nameBegin, *valueBegin, *valueEnd; 
-    char buffer[2 * PGN_ROASTERLINE_SIZE]; 
-    size_t valueLength; 
-   
-   
-    if ((- nameBegin  = strstr(- pgn ,-  buffer )) == 0)
 
-    { 
-       return; 
-    } 
-   
-    if ((- valueBegin  = strstr(- nameBegin , "\"")) == 0)
 
-    { 
-       return; 
-    } 
-   
-    if ((- valueEnd  = strstr(- valueBegin , "\"]")) == 0)
 
-    { 
-       return; 
-    } 
-   
-    valueLength = min(PGN_ROASTERLINE_SIZE, valueEnd - valueBegin - 1); 
-    memcpy(- value ,-  valueBegin  + 1,-  valueLength );
 
-    value[valueLength] = '\0'; 
- } 
-   
- static void parseRoasterValues(const char *pgn, PGNGame * pgngame) 
- { 
-    char *moves; 
-    Variation variation; 
-   
-    parseRoasterValue(pgn, "Event", pgngame->event); 
-    parseRoasterValue(pgn, "Site", pgngame->site); 
-    parseRoasterValue(pgn, "Date", pgngame->date); 
-    parseRoasterValue(pgn, "Round", pgngame->round); 
-    parseRoasterValue(pgn, "White", pgngame->white); 
-    parseRoasterValue(pgn, "Black", pgngame->black); 
-    parseRoasterValue(pgn, "Result", pgngame->result); 
-    parseRoasterValue(pgn, "SetUp", pgngame->setup); 
-    parseRoasterValue(pgn, "FEN", pgngame->fen); 
-    parseRoasterValue(pgn, "WhiteTitle", pgngame->whiteTitle); 
-    parseRoasterValue(pgn, "BlackTitle", pgngame->blackTitle); 
-    parseRoasterValue(pgn, "WhiteElo", pgngame->whiteElo); 
-    parseRoasterValue(pgn, "BlackElo", pgngame->blackElo); 
-    parseRoasterValue(pgn, "ECO", pgngame->eco); 
-    parseRoasterValue(pgn, "NIC", pgngame->nic); 
-    parseRoasterValue(pgn, "TimeControl", pgngame->timeControl); 
-    parseRoasterValue(pgn, "Termination", pgngame->termination); 
-    pgngame->moveText = 0; 
-    pgngame->firstMove = 0; 
-   
-    initializeVariationFromGame(&variation, pgngame); 
-   
-    if ((- moves  = strstr(- pgn , "\n\n")) == 0)
 
-    { 
-       moves  = strstr(- pgn , "\r\n\r\n");
-    } 
-   
-    if (moves != 0) 
-    { 
-       { 
-          strcpy(- pgngame ->- moveText ,-  moves );
 
-          trim(pgngame->moveText); 
-   
-          pgngame->firstMove = 
-             parseMoveSection(pgngame->moveText, &variation.singlePosition, 
-                              pgngame); 
-       } 
-    } 
- } 
-   
- PGNGame *getGame(PGNFile * pgnfile, int number) 
- { 
-    PGNGame *pgngame; 
-    char *gameText = getGameText(pgnfile, number); 
-   
-    if (gameText == 0) 
-    { 
-       return 0; 
-    } 
-   
-    if ((- pgngame  = (- PGNGame  *) malloc(sizeof(- PGNGame ))) ==-  NULL )
 
-    { 
-       return 0; 
-    } 
-   
-    initializePGNGame(pgngame); 
-    parseRoasterValues(gameText, pgngame); 
-   
-    return pgngame; 
- } 
-   
- /* 
-  ****************************************************************************** 
-  * 
-  *   Generator operations 
-  * 
-  ****************************************************************************** 
-  */ 
-   
- #define SAME_PIECE 1 
- #define SAME_FILE 2 
- #define SAME_RANK 4 
-   
- static int examineAlternativeMoves(Variation * variation, const Move move) 
- { 
-    const Square from = getFromSquare(move); 
-    const Square to = getToSquare(move); 
-    const Piece newPiece = getNewPiece(move); 
-    int result = 0; 
-    Position *position = &variation->singlePosition; 
-    Piece piece = position->piece[from]; 
-    Square square; 
-    Bitboard candidates = 
-       getDirectAttackers(position, to, position->activeColor, 
-                          position->allPieces) & position->piecesOfType[piece]; 
-   
-    clearSquare(candidates, from); 
-   
-    ITERATE_BITBOARD(&candidates, square) 
-    { 
-       const Move tmp = getPackedMove(square, to, newPiece); 
-   
-       if (moveIsLegal(position, tmp)) 
-       { 
-          result |= SAME_PIECE; 
-   
-          if (file(square) == file(from)) 
-          { 
-             result |= SAME_FILE; 
-          } 
-   
-          if (rank(square) == rank(from)) 
-          { 
-             result |= SAME_RANK; 
-          } 
-       } 
-    } 
-   
-    return result; 
- } 
-   
- void generateMoveText(Variation * variation, const Move move, char *pgnMove) 
- { 
-    Position *position = &variation->singlePosition; 
-    const char *castlings[] = { "O-O", "O-O-O" }; 
-    const Square from = getFromSquare(move); 
-    const Square to = getToSquare(move); 
-    const Piece newPiece = getNewPiece(move); 
-   
-    Piece movingPiece = position->piece[from]; 
-    char pieceSign[2], origin[3], destination[6], captureSign[2]; 
-    char checkSign[2], promotionSign[3]; 
-    int ambiguityCheckResult; 
-   
-    getSquareName(to, destination); 
-    pieceSign[0] = origin[0] = captureSign[0] = checkSign[0] = 0; 
-    promotionSign[0] = 0; 
-   
-    if (!moveIsLegal(position, move)) 
-    { 
-       getSquareName(from, origin); 
-       sprintf(- pgnMove , "(illegal move: %s-%s)",-  origin ,-  destination );
 
-   
-       return; 
-    } 
-    else 
-    { 
-       makeMove(variation, move); 
-   
-       if (activeKingIsSafe(&variation->singlePosition) == FALSE) 
-       { 
-          Movelist legalMoves; 
-   
-          getLegalMoves(variation, &legalMoves); 
-   
-          if (legalMoves.numberOfMoves == 0) 
-          { 
-          } 
-          else 
-          { 
-          } 
-       } 
-   
-       unmakeLastMove(variation); 
-    } 
-   
-    if (pieceType(movingPiece) == PAWN) 
-    { 
-       if (file(from) != file(to)) 
-       { 
-          sprintf(- origin , "%c",-  fileName (- file (- from )));
 
-       } 
-   
-       if (newPiece != NO_PIECE) 
-       { 
-          sprintf(- promotionSign , "=%c",-  pieceName [- newPiece ]);
 
-       } 
-    } 
-    else 
-    { 
-       if (pieceType(movingPiece) == KING && _distance[from][to] > 1) 
-       { 
-          strcpy(- destination ,-  castlings [- file (- to ) ==-  FILE_G  ? 0 : 1]);
 
-       } 
-       else 
-       { 
-          sprintf(- pieceSign , "%c",-  pieceName [- pieceType (- movingPiece )]);
 
-   
-          if (position->piece[to] != NO_PIECE) 
-          { 
-          } 
-   
-          ambiguityCheckResult = examineAlternativeMoves(variation, move); 
-   
-          if (ambiguityCheckResult & SAME_PIECE) 
-          { 
-             switch (ambiguityCheckResult) 
-             { 
-             case SAME_PIECE | SAME_FILE | SAME_RANK: 
-                getSquareName(from, origin); 
-                break; 
-   
-             case SAME_PIECE | SAME_FILE: 
-                sprintf(- origin , "%c",-  rankName (- rank (- from )));
 
-                break; 
-   
-             default: 
-                sprintf(- origin , "%c",-  fileName (- file (- from )));
 
-             } 
-          } 
-       } 
-    } 
-   
-    sprintf(- pgnMove , "%s%s%s%s%s%s",-  pieceSign ,-  origin ,-  captureSign ,
 
-            destination, promotionSign, checkSign); 
- } 
-   
- static char *generateMoveSection(Gamemove * gamemove, const char *result) 
- { 
-    String moveText = getEmptyString(); 
-    char moveBuffer[64], *temp; 
-    Variation variation; 
-    bool restart = TRUE; 
-   
-    initializeVariation(&variation, FEN_GAMESTART); 
-   
-    while (gamemove != 0) 
-    { 
-       if (restart == TRUE && gamemove->position.activeColor == BLACK) 
-       { 
-          appendToString(&moveText, " %d...", gamemove->position.moveNumber); 
-       } 
-   
-       restart = FALSE; 
-   
-       setBasePosition(&variation, &gamemove->position); 
-       generateMoveText(&variation, 
-                        getPackedMove(gamemove->from, gamemove->to, 
-                                      gamemove->newPiece), moveBuffer); 
-   
-       if (gamemove->position.activeColor == WHITE) 
-       { 
-          appendToString(&moveText, " %d. %s", gamemove->position.moveNumber, 
-                         moveBuffer); 
-       } 
-       else 
-       { 
-          appendToString(&moveText, " %s", moveBuffer); 
-       } 
-   
-       if (gamemove->glyphs != 0) 
-       { 
-          appendToString(&moveText, " %s", gamemove->glyphs); 
-       } 
-   
-       if (gamemove->comment != 0) 
-       { 
-          appendToString(&moveText, " {%s}", gamemove->comment); 
-       } 
-   
-       if (gamemove->alternativeMove != 0) 
-       { 
-          temp = generateMoveSection(gamemove->alternativeMove, ""); 
-          appendToString(&moveText, " (%s)", temp); 
-   
-          restart = TRUE; 
-       } 
-   
-       gamemove = gamemove->nextMove; 
-    } 
-   
-    if (result[0] != '\0') 
-    { 
-       appendToString(&moveText, " %s", result); 
-    } 
-   
-    trim(moveText.buffer); 
-    breakLines(moveText.buffer, 79); 
-   
-    return moveText.buffer; 
- } 
-   
- static char *generateRoasterLine(const char *tag, const char *tagValue, 
-                                  char buffer[PGN_ROASTERLINE_SIZE]) 
- { 
-    if (tagValue[0] != '\0') 
-    { 
-       sprintf(- buffer , "[%s \"%s\"]\n",-  tag ,-  tagValue );
 
-    } 
-    else 
-    { 
-       buffer[0] = '\0'; 
-    } 
-   
-    return buffer; 
- } 
-   
- static char *generateRoaster(const PGNGame * pgngame) 
- { 
-    char tagbuffer[PGN_ROASTERLINE_SIZE]; 
-    String string = getEmptyString(); 
-   
-    appendToString(&string, 
-                   generateRoasterLine("Event", pgngame->event, tagbuffer)); 
-    appendToString(&string, 
-                   generateRoasterLine("Site", pgngame->site, tagbuffer)); 
-    appendToString(&string, 
-                   generateRoasterLine("Date", pgngame->date, tagbuffer)); 
-    appendToString(&string, 
-                   generateRoasterLine("Round", pgngame->round, tagbuffer)); 
-    appendToString(&string, 
-                   generateRoasterLine("White", pgngame->white, tagbuffer)); 
-    appendToString(&string, 
-                   generateRoasterLine("Black", pgngame->black, tagbuffer)); 
-    appendToString(&string, 
-                   generateRoasterLine("Result", pgngame->result, tagbuffer)); 
-    appendToString(&string, 
-                   generateRoasterLine("SetUp", pgngame->setup, tagbuffer)); 
-    appendToString(&string, 
-                   generateRoasterLine("FEN", pgngame->fen, tagbuffer)); 
-    appendToString(&string, 
-                   generateRoasterLine("WhiteTitle", pgngame->whiteTitle, 
-                                       tagbuffer)); 
-    appendToString(&string, 
-                   generateRoasterLine("BlackTitle", pgngame->blackTitle, 
-                                       tagbuffer)); 
-    appendToString(&string, 
-                   generateRoasterLine("WhiteElo", pgngame->whiteElo, 
-                                       tagbuffer)); 
-    appendToString(&string, 
-                   generateRoasterLine("BlackElo", pgngame->blackElo, 
-                                       tagbuffer)); 
-    appendToString(&string, 
-                   generateRoasterLine("ECO", pgngame->eco, tagbuffer)); 
-    appendToString(&string, 
-                   generateRoasterLine("NIC", pgngame->nic, tagbuffer)); 
-    appendToString(&string, 
-                   generateRoasterLine("TimeControl", pgngame->timeControl, 
-                                       tagbuffer)); 
-    appendToString(&string, 
-                   generateRoasterLine("Termination", pgngame->termination, 
-                                       tagbuffer)); 
-   
-    return string.buffer; 
- } 
-   
- char *generatePgn(PGNGame * game) 
- { 
-    String string = getEmptyString(); 
-    char *roaster = generateRoaster(game); 
-    char *moveText = generateMoveSection(game->firstMove, game->result); 
-   
-    appendToString(&string, "%s\n%s", roaster, moveText); 
-   
-    return string.buffer; 
- } 
-   
- void initializeVariationFromGame(Variation * variation, PGNGame * game) 
- { 
-    if (game->lastMove != 0) 
-    { 
-       Gamemove *currentMove = game->lastMove; 
-       int i = POSITION_HISTORY_OFFSET - 1; 
-   
-       setBasePosition(variation, &(game->lastMove->position)); 
-       makeMove(variation, gameMove2Move(game->lastMove)); 
-   
-       if (variation->singlePosition.activeColor == WHITE) 
-       { 
-          variation->singlePosition.moveNumber++; 
-       } 
-   
-       setBasePosition(variation, &variation->singlePosition); 
-       prepareSearch(variation); 
-   
-       while (i >= 0 && currentMove != 0) 
-       { 
-          variation->positionHistory[i--] = currentMove->position.hashKey; 
-          currentMove = currentMove->previousMove; 
-       } 
-    } 
-    else 
-    { 
-       if (strcmp(- game ->- setup , "") != 0)
 
-       { 
-          initializeVariation(variation, game->fen); 
-       } 
-       else 
-       { 
-          initializeVariation(variation, FEN_GAMESTART); 
-       } 
-    } 
- } 
-   
- void initializeGameFromVariation(const Variation * variation, PGNGame * game, 
-                                  bool copyPv) 
- { 
-    const PrincipalVariation *pv = &variation->pv[0]; 
-   
-    resetPGNGame(game); 
-    getFen(&variation->startPosition, game->fen); 
-   
-    if (copyPv != FALSE) 
-    { 
-       int i = 0; 
-   
-       for (i = 0; i < min(8, pv->length); i++) 
-       { 
-          Move move = (Move) pv->move[i]; 
-   
-          if (appendMove(game, move) != 0) 
-          { 
-             break; 
-          } 
-       } 
-    } 
- } 
-   
- char *getPrincipalVariation(const Variation * variation) 
- { 
-    PGNGame game; 
-    char *pv; 
-   
-    initializePGNGame(&game); 
-    initializeGameFromVariation(variation, &game, TRUE); 
-    pv = generateMoveSection(game.firstMove, ""); 
-    trim(pv); 
-    resetPGNGame(&game); 
-   
-    return pv; 
- } 
-   
- /* 
-  ****************************************************************************** 
-  * 
-  *   Module initialization and testing 
-  * 
-  ****************************************************************************** 
-  */ 
-   
- int initializeModulePgn() 
- { 
-    pieceName[WHITE_KING] = 'K'; 
-    pieceName[WHITE_QUEEN] = 'Q'; 
-    pieceName[WHITE_ROOK] = 'R'; 
-    pieceName[WHITE_BISHOP] = 'B'; 
-    pieceName[WHITE_KNIGHT] = 'N'; 
-    pieceName[WHITE_PAWN] = 'P'; 
-    pieceName[BLACK_KING] = 'K'; 
-    pieceName[BLACK_QUEEN] = 'Q'; 
-    pieceName[BLACK_ROOK] = 'R'; 
-    pieceName[BLACK_BISHOP] = 'B'; 
-    pieceName[BLACK_KNIGHT] = 'N'; 
-    pieceName[BLACK_PAWN] = 'P'; 
-   
-    return 0; 
- } 
-   
- static int testGeneration() 
- { 
-    char *p1 = "r2qkb1r/ppp2ppp/3p4/5b2/3PN3/n4N2/PPP1QPPP/R3K2R w KQkq - 0 1"; 
-    char *p2 = "r3k2r/n3nppp/3n2P1/8/1q1q4/2B5/1q1pRPPP/5RK1 b kq - 0 1"; 
-    Variation variation; 
-    char pgnMove[64]; 
-   
-    initializeVariation(&variation, p1); 
-   
-    generateMoveText(&variation, getPackedMove(D4, D5, NO_PIECE), pgnMove); 
-   
-    generateMoveText(&variation, getPackedMove(E1, G1, NO_PIECE), pgnMove); 
-   
-    generateMoveText(&variation, getPackedMove(E1, C1, NO_PIECE), pgnMove); 
-   
-    generateMoveText(&variation, getPackedMove(E4, D6, NO_PIECE), pgnMove); 
-   
-    generateMoveText(&variation, getPackedMove(E4, F6, NO_PIECE), pgnMove); 
-   
-    generateMoveText(&variation, getPackedMove(F3, G5, NO_PIECE), pgnMove); 
-   
-    generateMoveText(&variation, getPackedMove(E4, G5, NO_PIECE), pgnMove); 
-   
-    generateMoveText(&variation, getPackedMove(B2, A3, NO_PIECE), pgnMove); 
-   
-    initializeVariation(&variation, p2); 
-   
-    generateMoveText(&variation, getPackedMove(E7, F5, NO_PIECE), pgnMove); 
-   
-    generateMoveText(&variation, getPackedMove(D2, D1, WHITE_BISHOP), pgnMove); 
-   
-    generateMoveText(&variation, getPackedMove(B4, C3, NO_PIECE), pgnMove); 
-   
-    generateMoveText(&variation, getPackedMove(B2, C3, NO_PIECE), pgnMove); 
-   
-    generateMoveText(&variation, getPackedMove(D4, C3, NO_PIECE), pgnMove); 
-   
-    generateMoveText(&variation, getPackedMove(D6, F5, NO_PIECE), pgnMove); 
-   
-    generateMoveText(&variation, getPackedMove(D6, C8, NO_PIECE), pgnMove); 
-   
-    return 0; 
- } 
-   
- static int testParsing() 
- { 
-    char *p1 = "r2qkb1r/ppp2ppp/3p4/5b2/3PN3/n4N2/PPP1QPPP/R3K2R w KQkq - 0 1"; 
-    char *p2 = "r3k2r/n3nppp/3n2P1/8/1q1q4/2B5/1q1pRPPP/5RK1 b kq - 0 1"; 
-    Variation variation; 
-   
-    initializeVariation(&variation, p1); 
-   
-    assert(- parsePGNMove ("d5", &- variation. singlePosition) ==
 
-           getPackedMove(D4, D5, NO_PIECE)); 
-   
-    assert(- parsePGNMove ("b4", &- variation. singlePosition) ==
 
-           getPackedMove(B2, B4, NO_PIECE)); 
-   
-    assert(- parsePGNMove ("bxa3", &- variation. singlePosition) ==
 
-           getPackedMove(B2, A3, NO_PIECE)); 
-   
-    assert(- parsePGNMove ("O-O", &- variation. singlePosition) ==
 
-           getPackedMove(E1, G1, NO_PIECE)); 
-   
-    assert(- parsePGNMove ("O-O-O", &- variation. singlePosition) ==
 
-           getPackedMove(E1, C1, NO_PIECE)); 
-   
-    assert(- parsePGNMove ("Ng3+", &- variation. singlePosition) ==
 
-           getPackedMove(E4, G3, NO_PIECE)); 
-   
-    assert(- parsePGNMove ("Nf6#", &- variation. singlePosition) ==
 
-           getPackedMove(E4, F6, NO_PIECE)); 
-   
-    assert(- parsePGNMove ("Nfg5", &- variation. singlePosition) ==
 
-           getPackedMove(F3, G5, NO_PIECE)); 
-   
-    initializeVariation(&variation, p2); 
-   
-    assert(- parsePGNMove ("h6", &- variation. singlePosition) ==
 
-           getPackedMove(H7, H6, NO_PIECE)); 
-   
-    assert(- parsePGNMove ("f5", &- variation. singlePosition) ==
 
-           getPackedMove(F7, F5, NO_PIECE)); 
-   
-    assert(- parsePGNMove ("fxg6", &- variation. singlePosition) ==
 
-           getPackedMove(F7, G6, NO_PIECE)); 
-   
-    assert(- parsePGNMove ("d1=B", &- variation. singlePosition) ==
 
-           getPackedMove(D2, D1, BISHOP)); 
-   
-    assert(- parsePGNMove ("O-O", &- variation. singlePosition) ==
 
-           getPackedMove(E8, G8, NO_PIECE)); 
-   
-    assert(- parsePGNMove ("O-O-O", &- variation. singlePosition) ==
 
-           getPackedMove(E8, C8, NO_PIECE)); 
-   
-    assert(- parsePGNMove ("Nf5", &- variation. singlePosition) ==
 
-           getPackedMove(D6, F5, NO_PIECE)); 
-   
-    assert(- parsePGNMove ("Q2xc3", &- variation. singlePosition) ==
 
-           getPackedMove(B2, C3, NO_PIECE)); 
-   
-    assert(- parsePGNMove ("Qdxc3", &- variation. singlePosition) ==
 
-           getPackedMove(D4, C3, NO_PIECE)); 
-   
-    assert(- parsePGNMove ("Qb4xc3", &- variation. singlePosition) ==
 
-           getPackedMove(B4, C3, NO_PIECE)); 
-   
-    return 0; 
- } 
-   
- static int testLoading() 
- { 
-    PGNFile pgnfile; 
-    PGNGame *game, game2; 
-    char *gameText, *generatedGameText; 
-   
-    pgnfile.numGames = 0; 
-    pgnfile.index = 0; 
-    pgnfile.file = 0; 
-   
-    assert(- openPGNFile (&- pgnfile , "test.pgn") == 0);
 
-    game = getGame(&pgnfile, 1); 
-   
-    gameText = generatePgn(game); 
-    initializePGNGame(&game2); 
-    parseRoasterValues(gameText, &game2); 
-    generatedGameText = generatePgn(&game2); 
-    /* logDebug("\n>%s<\n", generatedGameText); */ 
-   
-    freePgnGame(game); 
-    resetPGNGame(&game2); 
-    closePGNFile(&pgnfile); 
-   
-    return 0; 
- } 
-   
- int testModulePgn() 
- { 
-    int result; 
-   
-    if ((result = testLoading()) != 0) 
-    { 
-       return result; 
-    } 
-   
-    if ((result = testGeneration()) != 0) 
-    { 
-       return result; 
-    } 
-   
-    if ((result = testParsing()) != 0) 
-    { 
-       return result; 
-    } 
-   
-    return 0; 
- } 
-