LCOV - code coverage report
Current view: top level - src - game.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 130 136 95.6 %
Date: 2019-01-29 11:06:41 Functions: 60 61 98.4 %

          Line data    Source code
       1             : //////////////////////////////////////////////////////////////////////
       2             : //
       3             : //  FILE:       game.h
       4             : //              Game class for Scid.
       5             : //
       6             : //  Part of:    Scid (Shane's Chess Information Database)
       7             : //  Version:    3.5
       8             : //
       9             : //  Notice:     Copyright (c) 2000-2003 Shane Hudson.  All rights reserved.
      10             : //
      11             : //  Author:     Shane Hudson (sgh@users.sourceforge.net)
      12             : //
      13             : //////////////////////////////////////////////////////////////////////
      14             : 
      15             : 
      16             : #ifndef SCID_GAME_H
      17             : #define SCID_GAME_H
      18             : 
      19             : #include "common.h"
      20             : #include "date.h"
      21             : #include "indexentry.h"
      22             : #include "matsig.h"
      23             : #include "movetree.h"
      24             : #include "namebase.h"
      25             : #include "position.h"
      26             : #include <forward_list>
      27             : #include <memory>
      28             : #include <string>
      29             : #include <vector>
      30             : class ByteBuffer;
      31             : class TextBuffer;
      32             : 
      33             : void transPieces(char *s);
      34             : char transPiecesChar(char c);
      35             : 
      36             : // Piece letters translation
      37             : extern int language; // default to english
      38             : //  0 = en, 1 = fr, 2 = es, 3 = de
      39             : extern const char * langPieces[];
      40             : 
      41             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      42             : //  Game: Constants
      43             : 
      44             : // Common NAG Annotation symbol values:
      45             : const byte
      46             :     NAG_GoodMove = 1,
      47             :     NAG_PoorMove = 2,
      48             :     NAG_ExcellentMove = 3,
      49             :     NAG_Blunder = 4,
      50             :     NAG_InterestingMove = 5,
      51             :     NAG_DubiousMove = 6,
      52             :     NAG_OnlyMove = 8, // new
      53             :     NAG_Equal = 10,
      54             :     NAG_Unclear = 13,
      55             :     NAG_WhiteSlight = 14,
      56             :     NAG_BlackSlight = 15,
      57             :     NAG_WhiteClear = 16,
      58             :     NAG_BlackClear = 17,
      59             :     NAG_WhiteDecisive = 18,
      60             :     NAG_BlackDecisive = 19,
      61             :     NAG_WhiteCrushing = 20,
      62             :     NAG_BlackCrushing = 21,
      63             :     NAG_ZugZwang = 22, // new
      64             :     NAG_BlackZugZwang = 23, // new
      65             :     NAG_MoreRoom = 26, // new
      66             :     NAG_DevelopmentAdvantage = 35,  // new
      67             :     NAG_WithInitiative = 36, //new
      68             :     NAG_WithAttack = 40, // new
      69             :     NAG_WithBlackAttack = 41, // new
      70             :     NAG_Compensation = 44,      // from Whites perspective
      71             :     NAG_SlightCentre = 48,      // from Whites perspective
      72             :     NAG_Centre = 50,            // new
      73             :     NAG_SlightKingSide = 54,    // from Whites perspective
      74             :     NAG_ModerateKingSide = 56,  // from Whites perspective
      75             :     NAG_KingSide = 58,          // from Whites perspective
      76             :     NAG_SlightQueenSide = 60,   // from Whites perspective
      77             :     NAG_ModerateQueenSide = 62, // from Whites perspective
      78             :     NAG_QueenSide = 64,         // from Whites perspective
      79             :     NAG_SlightCounterPlay = 130, // new
      80             :     NAG_CounterPlay = 132, // new
      81             :     NAG_DecisiveCounterPlay = 134, // new
      82             :     NAG_BlackSlightCounterPlay = 131, // new
      83             :     NAG_BlackCounterPlay = 133, // new
      84             :     NAG_BlackDecisiveCounterPlay = 135, // new
      85             :     NAG_TimeLimit = 136, // new
      86             :     NAG_WithIdea = 140, // new
      87             :     NAG_BetterIs = 142, // new
      88             :     NAG_VariousMoves = 144, // new
      89             :     NAG_Comment = 145, // new
      90             :     NAG_Novelty = 146,
      91             :     NAG_WeakPoint = 147, // new
      92             :     NAG_Ending = 148, // new
      93             :     NAG_File = 149, // new
      94             :     NAG_Diagonal = 150, // new
      95             :     NAG_BishopPair = 151, // new
      96             :     NAG_OppositeBishops = 153, // new
      97             :     NAG_SameBishops = 154, // new
      98             :     NAG_Etc = 190, // new
      99             :     NAG_DoublePawns = 191, // new
     100             :     NAG_SeparatedPawns = 192, // new
     101             :     NAG_UnitedPawns = 193, // new
     102             :     NAG_Diagram = 201,  // Scid-specific NAGs start at 201.
     103             :     NAG_See = 210,  // new
     104             :     NAG_Mate = 211, // new 
     105             :     NAG_PassedPawn = 212, // new
     106             :     NAG_MorePawns = 213, //new
     107             :     NAG_With = 214, // new
     108             :     NAG_Without = 215;
     109             : 
     110             : // MAX_NAGS: Maximum id of NAG codes
     111             : const byte MAX_NAGS_ARRAY = 215;
     112             : 
     113             : // patternT structure: a pattern filter for material searches.
     114             : //    It can specify, for example, a white Pawn on the f-fyle, or
     115             : //    a black Bishop on f2 and white King on e1.
     116             : struct patternT
     117             : {
     118             :     pieceT     pieceMatch;  // EMPTY, WK, BK, etc...
     119             :     rankT      rankMatch;   // RANK_1 .. RANK_8 or NO_RANK
     120             :     fyleT      fyleMatch;   // A_FYLE .. H_FYLE or NO_FYLE
     121             :     byte       flag;        // 0 means this pattern must NOT occur.
     122             :     patternT * next;
     123             : };
     124             : 
     125             : #define GAME_DECODE_NONE 0
     126             : #define GAME_DECODE_TAGS 1
     127             : #define GAME_DECODE_COMMENTS 2
     128             : #define GAME_DECODE_ALL 3
     129             : 
     130             : enum gameExactMatchT {
     131             :     GAME_EXACT_MATCH_Exact = 0,
     132             :     GAME_EXACT_MATCH_Pawns,
     133             :     GAME_EXACT_MATCH_Fyles,
     134             :     GAME_EXACT_MATCH_Material
     135             : };
     136             : 
     137             : enum gameFormatT {
     138             :     PGN_FORMAT_Plain = 0,   // Plain regular PGN output
     139             :     PGN_FORMAT_HTML = 1,    // HTML format
     140             :     PGN_FORMAT_LaTeX = 2,   // LaTeX (with chess12 package) format
     141             :     PGN_FORMAT_Color = 3    // PGN, with color tags <red> etc
     142             : };
     143             : 
     144             : #define PGN_STYLE_TAGS             1
     145             : #define PGN_STYLE_COMMENTS         2
     146             : #define PGN_STYLE_VARS             4
     147             : #define PGN_STYLE_INDENT_COMMENTS  8
     148             : #define PGN_STYLE_INDENT_VARS     16
     149             : #define PGN_STYLE_SYMBOLS         32   // e.g. "! +-" instead of "$2 $14"
     150             : #define PGN_STYLE_SHORT_HEADER    64
     151             : #define PGN_STYLE_MOVENUM_SPACE  128   // Space after move numbers.
     152             : #define PGN_STYLE_COLUMN         256   // Column style: one move per line.
     153             : #define PGN_STYLE_SCIDFLAGS      512
     154             : #define PGN_STYLE_STRIP_MARKS   1024   // Strip [%mark] and [%arrow] codes.
     155             : #define PGN_STYLE_NO_NULL_MOVES 2048   // Convert null moves to comments.
     156             : #define PGN_STYLE_UNICODE       4096   // Use U+2654..U+2659 for figurine
     157             : 
     158             : 
     159             : void  game_printNag (byte nag, char * str, bool asSymbol, gameFormatT format);
     160             : byte game_parseNag(std::pair<const char*, const char*> strview);
     161             : 
     162             : uint strGetRatingType (const char * name);
     163             : 
     164             : //////////////////////////////////////////////////////////////////////
     165             : //  Game:  Class Definition
     166             : 
     167        2142 : class Game {
     168             :     // Header data: tag pairs
     169             :     std::vector<std::pair<std::string, std::string> > extraTags_;
     170             :     std::string WhiteStr;
     171             :     std::string BlackStr;
     172             :     std::string EventStr;
     173             :     std::string SiteStr;
     174             :     std::string RoundStr;
     175             :     dateT       Date;
     176             :     dateT       EventDate;
     177             :     ecoT        EcoCode;
     178             :     eloT        WhiteElo;
     179             :     eloT        BlackElo;
     180             :     byte        WhiteRatingType;
     181             :     byte        BlackRatingType;
     182             :     resultT     Result;
     183             :     char        ScidFlags[22];
     184             : 
     185             :     // Position and moves
     186             :     byte        moveChunkUsed_;
     187             :     std::forward_list<std::unique_ptr<moveT[]> > moveChunks_;
     188             :     std::unique_ptr<Position> StartPos;
     189        2142 :     std::unique_ptr<Position> CurrentPos{new Position};
     190             :     moveT*      FirstMove;
     191             :     moveT*      CurrentMove;
     192             :     uint        VarDepth;     // Current variation depth.
     193             :     ushort      NumHalfMoves; // Total half moves in the main line.
     194             : 
     195             :     // TODO: The following variables should not be part of this class.
     196             :     bool        PromotionsFlag;   // Used by MaterialMatch
     197             :     bool        KeepDecodedMoves; // Used by MaterialMatch end ExactMatch
     198             : 
     199             :     eloT        WhiteEstimateElo;
     200             :     eloT        BlackEstimateElo;
     201             : 
     202             :     uint        NumMovesPrinted; // Used in recursive WriteMoveList method.
     203             :     uint        PgnStyle;        // see PGN_STYLE macros above.
     204             :     gameFormatT PgnFormat;       // see PGN_FORMAT macros above.
     205             :     uint        HtmlStyle;       // HTML diagram style, see DumpHtmlBoard method in position.cpp.
     206             : 
     207             : private:
     208             :     Game(const Game&);
     209             :     moveT* allocMove();
     210             :     moveT* NewMove(markerT marker);
     211             :     void ClearMoves();
     212             :     bool MakeHomePawnList(byte* pbPawnList);
     213             :     errorT DecodeVariation(ByteBuffer* buf, byte flags, uint level);
     214             :     errorT WritePGN(TextBuffer* tb);
     215             : 
     216             :     /**
     217             :      * Contains the information of the current position in the game, so that
     218             :      * after an operation that alters the location, it can be restored.
     219             :      */
     220             :     struct GameSavedPos {
     221             :         Position pos;
     222             :         moveT* move;
     223             :         uint varDepth;
     224             :     };
     225             : 
     226             : public:
     227        4278 :     Game() { Clear(); }
     228             :     void Clear();
     229             :     void strip(bool variations, bool comments, bool NAGs);
     230             : 
     231      177267 :     bool HasNonStandardStart(char* outFEN = nullptr) const {
     232      177267 :         if (!StartPos)
     233      177266 :             return false;
     234           1 :         if (outFEN)
     235           1 :             StartPos->PrintFEN(outFEN, FEN_ALL_FIELDS);
     236           1 :         return true;
     237             :     }
     238             : 
     239             :     /// Setup the start position from a FEN string and remove all the moves.
     240             :     /// If the FEN is invalid the game is not changed.
     241             :     errorT SetStartFen(const char* fenStr);
     242             : 
     243           0 :     void SetScidFlags(const char* s, size_t len) {
     244           0 :         constexpr size_t size = sizeof(ScidFlags) / sizeof(*ScidFlags);
     245           0 :         std::fill_n(ScidFlags, size, 0);
     246           0 :         std::copy_n(s, std::min(size - 1, len), ScidFlags);
     247           0 :     }
     248             :     void SetScidFlags(const char* s) { SetScidFlags(s, std::strlen(s)); }
     249             : 
     250             :     ushort GetNumHalfMoves() { return NumHalfMoves; }
     251             : 
     252             :     //////////////////////////////////////////////////////////////
     253             :     // Functions to add or delete moves:
     254             :     //
     255             :     errorT AddMove(const simpleMoveT* sm);
     256             :     errorT AddVariation();
     257             :     errorT DeleteVariation();
     258             :     errorT FirstVariation();
     259             :     errorT MainVariation();
     260             :     void Truncate();
     261             :     void TruncateStart();
     262             : 
     263             :     //////////////////////////////////////////////////////////////
     264             :     // Functions that move the current location (only CurrentPos,
     265             :     // CurrentMove and VarDepth are modified by these functions):
     266             :     //
     267             :     errorT MoveForward();
     268             :     errorT MoveBackup();
     269             :     errorT MoveIntoVariation(uint varNumber);
     270             :     errorT MoveExitVariation();
     271             :     errorT MoveForwardInPGN();
     272             :     errorT MoveToLocationInPGN(unsigned stopLocation);
     273             :     void MoveToStart();
     274       13645 :     void MoveToPly(int hmNumber) { // Move to a specified
     275       13645 :         MoveToStart();             // mainline ply in the game.
     276       13645 :         for (int i = 0; i < hmNumber; ++i)
     277           0 :             MoveForward();
     278       13645 :     }
     279        2037 :     GameSavedPos currentLocation() const {
     280        2037 :         return GameSavedPos{*CurrentPos, CurrentMove, VarDepth};
     281             :     }
     282        2037 :     void restoreLocation(const GameSavedPos& savedPos) {
     283        2037 :         *CurrentPos = savedPos.pos;
     284        2037 :         CurrentMove = savedPos.move;
     285        2037 :         VarDepth = savedPos.varDepth;
     286        2037 :     }
     287             : 
     288             :     //////////////////////////////////////////////////////////////
     289             :     // Functions that get information about the current location.
     290             :     //
     291      784181 :     const Position* currentPos() const { return CurrentPos.get(); }
     292     2345906 :     Position* GetCurrentPos() { // Deprecated, use the const version
     293     2345906 :         return CurrentPos.get();
     294             :     }
     295             :     simpleMoveT* GetCurrentMove() { // Deprecated
     296             :         return CurrentMove->endMarker() ? nullptr : &CurrentMove->moveData;
     297             :     }
     298        3162 :     ushort GetCurrentPly() const {
     299        3162 :         auto ply = CurrentPos->GetPlyCounter();
     300        3162 :         return StartPos ? ply - StartPos->GetPlyCounter() : ply;
     301             :     }
     302             :     uint GetNumVariations() const { return CurrentMove->numVariations; }
     303             : 
     304             :     // Each variation has a "level" and a "number".
     305             :     // - "level" is the number of times that is necessary to call
     306             :     //   MoveExitVariation() to reach the main line.
     307             :     // - "number" is the ordered position in the list of variations for the
     308             :     // current root position (first variation is number 0).
     309             :     // The main line is 0,0.
     310      780189 :     uint GetVarLevel() const { return VarDepth; }
     311       40541 :     uint GetVarNumber() const {
     312       40541 :         if (VarDepth != 0) {
     313       40115 :             uint varNumber = 0;
     314       40115 :             auto moves = CurrentMove->getParent();
     315       47193 :             for (auto parent = moves.first; parent; varNumber++) {
     316       47193 :                 parent = parent->varChild;
     317       47193 :                 if (parent == moves.second)
     318       40115 :                     return varNumber;
     319             :             }
     320             :         }
     321         426 :         return 0; // returns 0 if in main line
     322             :     }
     323             : 
     324             :     unsigned GetLocationInPGN() const;
     325             :     unsigned GetPgnOffset() const;
     326             : 
     327        2863 :     bool AtVarStart() const { return CurrentMove->prev->startMarker(); }
     328        9015 :     bool AtVarEnd() const { return CurrentMove->endMarker(); }
     329         158 :     bool AtStart() const { return (VarDepth == 0 && AtVarStart()); }
     330        9015 :     bool AtEnd() const { return (VarDepth == 0 && AtVarEnd()); }
     331             : 
     332             :     //////////////////////////////////////////////////////////////
     333             :     // Functions that get/set information about the last/next move.
     334             :     // Notice: when location is at the start of the game or a variation,
     335             :     // infomation are stored into the START_MARKER.
     336             :     //
     337             :     errorT AddNag(byte nag);
     338             :     errorT RemoveNag(bool isMoveNag);
     339             :     void ClearNags() {
     340             :         CurrentMove->prev->nagCount = 0;
     341             :         CurrentMove->prev->nags[0] = 0;
     342             :     }
     343        1124 :     byte* GetNags() const { return CurrentMove->prev->nags; }
     344             :     byte* GetNextNags() const { return CurrentMove->nags; }
     345             : 
     346             :     /**
     347             :      * Return the comment on the move previously played by CurrentPos->ToMove
     348             :      * If there are no previous moves, return an empty comment.
     349             :      */
     350             :     const char* GetPreviousMoveComment() const {
     351             :         const moveT* move = CurrentMove->getPrevMove();
     352             :         if (move)
     353             :             move = move->getPrevMove();
     354             : 
     355             :         return (move) ? move->comment.c_str() : "";
     356             :     }
     357        1147 :     const char* GetMoveComment() const {
     358        1147 :         return CurrentMove->prev->comment.c_str();
     359             :     }
     360      224036 :     std::string& accessMoveComment() { return CurrentMove->prev->comment; }
     361             :     void SetMoveComment(const char* comment);
     362             : 
     363             :     const char* GetNextSAN();
     364             :     void GetSAN(char* str);
     365             :     void GetPrevSAN(char* str);
     366             :     void GetPrevMoveUCI(char* str) const;
     367             :     void GetNextMoveUCI(char* str);
     368             : 
     369             :     //////////////////////////////////////////////////////////////
     370             :     // Functions that get/set the tag pairs:
     371             :     //
     372             :     void AddPgnTag(const char* tag, const char* value);
     373             :     bool RemoveExtraTag(const char* tag);
     374             :     const char* FindExtraTag(const char* tag) const;
     375             :     std::string& accessTagValue(const char* tag, size_t tagLen);
     376       10020 :     const decltype(extraTags_) & GetExtraTags() const { return extraTags_; }
     377             :     void ClearExtraTags() { extraTags_.clear(); }
     378             : 
     379             :     errorT LoadStandardTags(const IndexEntry* ie, const NameBase* nb);
     380             : 
     381        1001 :     void     SetEventStr (const char * str) { EventStr = str; }
     382        1001 :     void     SetSiteStr  (const char * str) { SiteStr  = str; }
     383        1001 :     void     SetWhiteStr (const char * str) { WhiteStr = str; }
     384        1001 :     void     SetBlackStr (const char * str) { BlackStr = str; }
     385        1001 :     void     SetRoundStr (const char * str) { RoundStr = str; }
     386        3040 :     void     SetDate (dateT date)    { Date = date; }
     387        1037 :     void     SetEventDate (dateT date)  { EventDate = date; }
     388        3037 :     void     SetResult (resultT res) { Result = res; }
     389        1037 :     void     SetWhiteElo (eloT elo)  { WhiteElo = elo; }
     390        1037 :     void     SetBlackElo (eloT elo)  { BlackElo = elo; }
     391        1037 :     void     SetWhiteRatingType (byte b) { WhiteRatingType = b; }
     392        1036 :     void     SetBlackRatingType (byte b) { BlackRatingType = b; }
     393             :     int setRating(colorT col, const char* ratingType, size_t ratingTypeLen,
     394             :                   std::pair<const char*, const char*> rating);
     395        1037 :     void     SetEco (ecoT eco)       { EcoCode = eco; }
     396       11055 :     const char* GetEventStr () const { return EventStr.c_str(); }
     397       11054 :     const char* GetSiteStr ()  const { return SiteStr.c_str();  }
     398       11054 :     const char* GetWhiteStr () const { return WhiteStr.c_str(); }
     399       11054 :     const char* GetBlackStr () const { return BlackStr.c_str(); }
     400       11054 :     const char* GetRoundStr () const { return RoundStr.c_str(); }
     401          30 :     dateT    GetDate ()        const { return Date; }
     402           3 :     dateT    GetEventDate ()   const { return EventDate; }
     403        2036 :     resultT  GetResult ()      const { return Result; }
     404         234 :     eloT     GetWhiteElo ()    const { return WhiteElo; }
     405         234 :     eloT     GetBlackElo ()    const { return BlackElo; }
     406             :     eloT     GetWhiteEstimateElo() const { return WhiteEstimateElo; }
     407             :     eloT     GetBlackEstimateElo() const { return BlackEstimateElo; }
     408           1 :     byte     GetWhiteRatingType () const { return WhiteRatingType; }
     409           1 :     byte     GetBlackRatingType () const { return BlackRatingType; }
     410           3 :     ecoT     GetEco ()         const { return EcoCode; }
     411             :     eloT     GetAverageElo ();
     412             : 
     413             :     // PGN conversion
     414             :     bool      CommentEmpty ( const char * comment);
     415             :     void      WriteComment (TextBuffer * tb, const char * preStr,
     416             :                             const char * comment, const char * postStr);
     417             :     errorT    WriteMoveList(TextBuffer* tb, moveT* oldCurrentMove,
     418             :                             bool printMoveNum, bool inComment);
     419             :     std::pair<const char*, unsigned> WriteToPGN (uint lineWidth = 0,
     420             :                                                  bool NewLineAtEnd = false,
     421             :                                                  bool newLineToSpaces = true);
     422             : 
     423             :     void      ResetPgnStyle (void) { PgnStyle = 0; }
     424        2037 :     void      ResetPgnStyle (uint flag) { PgnStyle = flag; }
     425             : 
     426             :     uint      GetPgnStyle () { return PgnStyle; }
     427             :     void      SetPgnStyle (uint mask, bool setting) {
     428             :         if (setting) { AddPgnStyle (mask); } else { RemovePgnStyle (mask); }
     429             :     }
     430             :     void      AddPgnStyle (uint mask) { PgnStyle |= mask; }
     431             :     void      RemovePgnStyle (uint mask) { PgnStyle &= ~mask; }
     432             : 
     433        2037 :     void      SetPgnFormat (gameFormatT gf) { PgnFormat = gf; }
     434             :     bool      SetPgnFormatFromString (const char * str);
     435             :     static bool PgnFormatFromString (const char * str, gameFormatT * fmt);
     436      533984 :     bool      IsPlainFormat () { return (PgnFormat == PGN_FORMAT_Plain); }
     437     2007661 :     bool      IsHtmlFormat  () { return (PgnFormat == PGN_FORMAT_HTML); }
     438     1554613 :     bool      IsLatexFormat () { return (PgnFormat == PGN_FORMAT_LaTeX); }
     439    10034947 :     bool      IsColorFormat () { return (PgnFormat == PGN_FORMAT_Color); }
     440             : 
     441             :     void      SetHtmlStyle (uint style) { HtmlStyle = style; }
     442             :     uint      GetHtmlStyle () { return HtmlStyle; }
     443             : 
     444             :     errorT    GetPartialMoveList (DString * str, uint plyCount);
     445             : 
     446             :     bool      MaterialMatch (ByteBuffer * buf, byte * min, byte * max,
     447             :                              patternT * pattern, int minPly, int maxPly,
     448             :                              int matchLength,
     449             :                              bool oppBishops, bool sameBishops,
     450             :                              int minDiff, int maxDiff);
     451             :     bool      ExactMatch (Position * pos, ByteBuffer * buf, simpleMoveT * sm,
     452             :                           gameExactMatchT searchType, bool * neverMatch);
     453             :     bool      VarExactMatch (Position * searchPos, gameExactMatchT searchType);
     454             :     inline bool ExactMatch (Position * pos, ByteBuffer * buf, simpleMoveT * sm)
     455             :       { return ExactMatch (pos, buf, sm, GAME_EXACT_MATCH_Exact, NULL); }
     456             :     inline bool ExactMatch (Position * pos, ByteBuffer * buf, simpleMoveT * sm,
     457             :                             bool * neverMatch)
     458             :       { return ExactMatch (pos, buf, sm, GAME_EXACT_MATCH_Exact, neverMatch); }
     459             :     inline bool ExactMatch (Position * pos, ByteBuffer * buf, simpleMoveT * sm,
     460             :                             gameExactMatchT searchType)
     461             :       { return ExactMatch (pos, buf, sm, searchType, NULL); }
     462             : 
     463             :     errorT    Encode (ByteBuffer * buf, IndexEntry * ie);
     464             :     errorT    DecodeStart(ByteBuffer* buf, bool decodeTags = false);
     465             :     errorT    DecodeNextMove (ByteBuffer * buf, simpleMoveT * sm);
     466             :     errorT    Decode (ByteBuffer * buf, byte flags);
     467             :     errorT    DecodeTags (ByteBuffer * buf, bool storeTags);
     468             : 
     469             :     Game* clone();
     470             : };
     471             : 
     472             : namespace gamevisit {
     473             : 
     474           2 : template <typename TFunc> void tags_STR(const Game& game, TFunc visitor) {
     475             :         char dateBuf[16];
     476           2 :         visitor("Event", game.GetEventStr());
     477           2 :         visitor("Site", game.GetSiteStr());
     478           2 :         date_DecodeToString(game.GetDate(), dateBuf);
     479           2 :         visitor("Date", dateBuf);
     480           2 :         visitor("Round", game.GetRoundStr());
     481           2 :         visitor("White", game.GetWhiteStr());
     482           2 :         visitor("Black", game.GetBlackStr());
     483           2 :         visitor("Result", RESULT_LONGSTR[game.GetResult()]);
     484           2 : }
     485             : 
     486           2 : template <typename TFunc> void tags_extra(const Game& game, TFunc visitor) {
     487             :         char strBuf[256];
     488           2 :         if (auto elo = game.GetWhiteElo()) {
     489           2 :                 std::string rType = "White";
     490           1 :                 rType.append(ratingTypeNames[game.GetWhiteRatingType()]);
     491           1 :                 visitor(rType.c_str(), std::to_string(elo).c_str());
     492             :         }
     493           2 :         if (auto elo = game.GetBlackElo()) {
     494           2 :                 std::string rType = "Black";
     495           1 :                 rType.append(ratingTypeNames[game.GetBlackRatingType()]);
     496           1 :                 visitor(rType.c_str(), std::to_string(elo).c_str());
     497             :         }
     498           2 :         if (game.GetEco() != ECO_None) {
     499           1 :                 eco_ToExtendedString(game.GetEco(), strBuf);
     500           1 :                 visitor("ECO", strBuf);
     501             :         }
     502           2 :         if (game.GetEventDate() != ZERO_DATE) {
     503           1 :                 date_DecodeToString(game.GetEventDate(), strBuf);
     504           1 :                 visitor("EventDate", strBuf);
     505             :         }
     506             :         // TODO:
     507             :         // if (*ScidFlags)
     508             :         //      visitor("ScidFlags", ScidFlags);
     509             : 
     510           5 :         for (auto& e : game.GetExtraTags()) {
     511           3 :                 visitor(e.first.c_str(), e.second.c_str());
     512             :         }
     513           2 :         if (game.HasNonStandardStart(strBuf)) {
     514           1 :                 visitor("FEN", strBuf);
     515             :         }
     516           2 : }
     517             : 
     518             : } // namespace gamevisit
     519             : 
     520             : namespace gamepos {
     521             : 
     522        6436 : struct GamePos {
     523             :         uint32_t RAVdepth;
     524             :         uint32_t RAVnum;
     525             :         std::string FEN; // "Forsyth-Edwards Notation" describing the position.
     526             :         std::vector<int> NAGs;   // "Numeric Annotation Glyph"
     527             :         std::string comment;     // text annotation of the position.
     528             :         std::string lastMoveSAN; // move that was played to reach the position.
     529             : };
     530             : 
     531             : /**
     532             :  * Iterate all the positions of a game and store the corresponding GamePos
     533             :  * objects into a container.
     534             :  *
     535             :  * The order of positions and of Recursive Annotation Variations (RAV) follows
     536             :  * the PGN standard: "The alternate move sequence given by an RAV is one that
     537             :  * may be legally played by first unplaying the move that appears immediately
     538             :  * prior to the RAV. Because the RAV is a recursive construct, it may be nested"
     539             :  * Each position have a RAVdepth and a RAVnum that allows to follow a
     540             :  * variation from any given position:
     541             :  * - skip all the next positions with a bigger RAVdepth
     542             :  * - the variation ends with:
     543             :  *   - a lower RAVdepth or
     544             :  *   - an equal RAVdepth but different RAVnum or
     545             :  *   - the end of @e dest
     546             :  * @param game: reference to the Game object where the positions are read.
     547             :  * @param dest: the container where the GamePos objects are appended.
     548             :  */
     549             : template <typename TCont>
     550        1270 : inline void collectPositions(Game& game, TCont& dest) {
     551        1258 :         do {
     552        1270 :                 if (game.AtVarStart() && !game.AtStart())
     553         146 :                         continue;
     554             : 
     555        1124 :                 dest.emplace_back();
     556        1124 :                 auto& gamepos = dest.back();
     557        1124 :                 gamepos.RAVdepth = game.GetVarLevel();
     558        1124 :                 gamepos.RAVnum = game.GetVarNumber();
     559             :                 char strBuf[256];
     560        1124 :                 game.currentPos()->PrintFEN(strBuf, FEN_ALL_FIELDS);
     561        1124 :                 gamepos.FEN = strBuf;
     562        1348 :                 for (byte* nag = game.GetNags(); *nag; nag++) {
     563         224 :                         gamepos.NAGs.push_back(*nag);
     564             :                 }
     565        1124 :                 gamepos.comment = game.GetMoveComment();
     566        1124 :                 game.GetPrevSAN(strBuf);
     567        1124 :                 gamepos.lastMoveSAN = strBuf;
     568             : 
     569        1270 :         } while (game.MoveForwardInPGN() == OK);
     570          12 : }
     571             : 
     572             : /**
     573             :  * Returns all the positions of a game
     574             :  * @param game: reference to the Game object where the positions are read.
     575             :  * @returns a std::vector containing the GamePos objects corresponding to all
     576             :  * the positions of @e game.
     577             :  */
     578          12 : inline std::vector<GamePos> collectPositions(Game& game) {
     579          12 :         std::vector<GamePos> res;
     580          12 :         game.MoveToStart();
     581          12 :         collectPositions(game, res);
     582          12 :         return res;
     583             : }
     584             : 
     585             : } // namespace gamepos
     586             : 
     587             : #endif  // #ifndef SCID_GAME_H
     588             : 
     589             : //////////////////////////////////////////////////////////////////////
     590             : //  EOF:    game.h
     591             : //////////////////////////////////////////////////////////////////////

Generated by: LCOV version 1.13