- /* 
-     Texel - A UCI chess engine. 
-     Copyright (C) 2012-2013  Peter Ă–sterlund, peterosterlund2@gmail.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/>. 
- */ 
-   
- /* 
-  * treeLogger.cpp 
-  * 
-  *  Created on: Feb 25, 2012 
-  *      Author: petero 
-  */ 
-   
- #include "treeLogger.hpp" 
- #include "transpositionTable.hpp" 
- #include "textio.hpp" 
- #include "position.hpp" 
- #include "constants.hpp" 
-   
- #include <iostream> 
- #include <iomanip> 
- #include <cassert> 
-   
- void 
- TreeLoggerWriter::open(const std::string& filename, 
-                        ParallelData& pd0, int threadNo0) { 
-     auto fn = filename + std::string(".") + num2Str(threadNo0); 
-     os.open(fn.c_str(), std::ios_base::out | 
-                         std::ios_base::binary | 
-                         std::ios_base::trunc); 
-     opened = true; 
-   
-     pd = &pd0; 
-     threadNo = threadNo0; 
- } 
-   
- void 
- TreeLoggerWriter::close() { 
-     if (opened) { 
-         if (nInWriteCache > 0) { 
-             os.write((const char*)writeCache, Entry::bufSize * nInWriteCache); 
-             nInWriteCache = 0; 
-         } 
-         opened = false; 
-         os.close(); 
-     } 
- } 
-   
- void 
- TreeLoggerWriter::writePosition(const Position& pos, int owningThread, U64 parentIndex, int moveNo) { 
-     Position::SerializeData data; 
-     pos.serialize(data); 
-   
-     entry.type = (nextIndex == 0) ? EntryType::POSITION_INCOMPLETE : EntryType::POSITION_PART0; 
-     entry.p0.nextIndex = endMark; 
-     entry.p0.word0 = data.v[0]; 
-     entry.p0.word1 = data.v[1]; 
-     appendEntry(entry); 
-     nextIndex++; 
-   
-     entry.type = EntryType::POSITION_PART1; 
-     entry.p1.t0Index = pd->t0Index; 
-     entry.p1.word2 = data.v[2]; 
-     entry.p1.word3 = data.v[3]; 
-     appendEntry(entry); 
-     nextIndex++; 
-   
-     entry.type = EntryType::POSITION_PART2; 
-     entry.p2.word4 = data.v[4]; 
-     entry.p2.owningThread = owningThread; 
-     entry.p2.parentIndex = (U32)parentIndex; // Pierre-Marie Baty -- added type cast 
-     entry.p2.moveNo = moveNo; 
-     appendEntry(entry); 
-     nextIndex++; 
- } 
-   
- void 
- TreeLoggerWriter::appendEntry(const Entry& entry) { 
-     entry.serialize(entryBuffer); 
-     memcpy(&writeCache[Entry::bufSize * nInWriteCache], entryBuffer, Entry::bufSize); 
-     nInWriteCache++; 
-     if (nInWriteCache == writeCacheSize) { 
-         os.write((const char*)writeCache, Entry::bufSize * nInWriteCache); 
-         nInWriteCache = 0; 
-     } 
- } 
-   
-   
- TreeLoggerReader::TreeLoggerReader(const std::string& filename) 
-     : fs(filename.c_str(), std::ios_base::out | 
-                            std::ios_base::in | 
-                            std::ios_base::binary), 
-       filePos(-1), numEntries(0) { 
-     fs.exceptions(std::ifstream::failbit | std::ifstream::badbit); 
-     fs.seekg(0, std::ios_base::end); 
-     S64 fileLen = fs.tellg(); 
-     numEntries = fileLen / Entry::bufSize; 
-     computeForwardPointers(); 
- } 
-   
- void 
- TreeLoggerReader::close() { 
-     fs.close(); 
- } 
-   
- void 
- TreeLoggerReader::main(const std::string& filename) { 
-     try { 
-         TreeLoggerReader an(filename); 
-         an.mainLoop(); 
-         an.close(); 
-     } catch (const std::exception& ex) { 
-         std::cout << "Error: " << ex.what() << std::endl; 
-     } 
- } 
-   
- void 
- TreeLoggerReader::computeForwardPointers() { 
-     readEntry(0, entry); 
-     if (entry.type != EntryType::POSITION_INCOMPLETE) 
-         return; 
-   
-     std::cout << "Computing forward pointers..." << std::endl; 
-     const size_t batchSize = 1000000; 
-     std::vector<std::pair<U64,U64>> toWrite; 
-     toWrite.reserve(batchSize); 
-     U64 prevPosIdx = 0; 
-     for (U64 i = 0; i < numEntries; i++) { 
-         readEntry(i, entry); 
-         if (entry.type == EntryType::NODE_END) { 
-             U64 idx = entry.ee.startIndex; 
-             toWrite.push_back(std::make_pair(idx, i)); 
-         } else if (entry.type == EntryType::POSITION_PART0) { 
-             if (i > prevPosIdx) 
-                 toWrite.push_back(std::make_pair(prevPosIdx, i)); 
-             prevPosIdx = i; 
-         } 
-         if (toWrite.size() >= batchSize) { 
-             flushForwardPointerData(toWrite); 
-             toWrite.clear(); 
-             toWrite.reserve(batchSize); 
-         } 
-     } 
-     flushForwardPointerData(toWrite); 
-   
-     readEntry(0, entry); 
-     assert(entry.type == EntryType::POSITION_INCOMPLETE); 
-     entry.type = EntryType::POSITION_PART0; 
-     writeEntry(0, entry); 
-   
-     fs.flush(); 
-     std::cout << "Computing forward pointers... done" << std::endl; 
- } 
-   
- void 
- TreeLoggerReader::flushForwardPointerData(std::vector<std::pair<U64,U64>>& toWrite) { 
-     if (toWrite.empty()) 
-         return; 
-     std::sort(toWrite.begin(), toWrite.end()); 
-     const U64 eSize = Entry::bufSize; 
-     const U64 cacheSize = 512; 
-     U8 cacheBuf[eSize * cacheSize]; 
-     const U64 emptyMark = std::numeric_limits<U64>::max(); 
-     U64 cacheStart = emptyMark; // Index for first entry in cache 
-   
-     for (auto p : toWrite) { 
-         const U64 startIdx = p.first; 
-         const U64 endIdx = p.second; 
-   
-         if ((cacheStart != emptyMark) && 
-             ((startIdx < cacheStart) || (startIdx >= cacheStart + cacheSize))) { // flush 
-             int nWrite = (int)std::min(cacheSize, numEntries - cacheStart); // Pierre-Marie Baty -- added type cast 
-             fs.seekp(cacheStart * eSize, std::ios_base::beg); 
-             fs.write((const char*)cacheBuf, nWrite * eSize); 
-             cacheStart = emptyMark; 
-         } 
-         if (cacheStart == emptyMark) { 
-             cacheStart = startIdx; 
-             int nRead = (int)std::min(cacheSize, numEntries - cacheStart); // Pierre-Marie Baty -- added type cast 
-             fs.seekg(cacheStart * eSize, std::ios_base::beg); 
-             fs.read((char*)cacheBuf, nRead * eSize); 
-         } 
-   
-         U8* entAddr = &cacheBuf[(startIdx - cacheStart) * eSize]; 
-         entry.deSerialize(entAddr); 
-         if (entry.type == EntryType::NODE_START) { 
-             entry.se.endIndex = (U32)endIdx; // Pierre-Marie Baty -- added type cast 
-         } else if ((entry.type == EntryType::POSITION_PART0) || 
-                    (entry.type == EntryType::POSITION_INCOMPLETE)) { 
-             entry.p0.nextIndex = (U32)endIdx; // Pierre-Marie Baty -- added type cast 
-         } else 
-             assert(false); 
-         entry.serialize(entAddr); 
-     } 
-     if (cacheStart != emptyMark) { // flush 
-         int nWrite = (int)std::min(cacheSize, numEntries - cacheStart); // Pierre-Marie Baty -- added type cast 
-         fs.seekp(cacheStart * eSize, std::ios_base::beg); 
-         fs.write((const char*)cacheBuf, nWrite * eSize); 
-     } 
-     filePos = -1; 
- } 
-   
- void 
- TreeLoggerReader::getRootNode(U64 index, Position& pos, int& owningThread, 
-                               U64& parentIndex, int& moveNo, U64& t0Index) { 
-     readEntry(index, entry); 
-     if (entry.type == EntryType::POSITION_PART1) { 
-         index--; 
-         readEntry(index, entry); 
-     } else if (entry.type == EntryType::POSITION_PART2) { 
-         index -= 2; 
-         readEntry(index, entry); 
-     } 
-     assert((entry.type == EntryType::POSITION_INCOMPLETE) || 
-            (entry.type == EntryType::POSITION_PART0)); 
-   
-     Position::SerializeData data; 
-     data.v[0] = entry.p0.word0; 
-     data.v[1] = entry.p0.word1; 
-   
-     readEntry(index + 1, entry); 
-     assert(entry.type == EntryType::POSITION_PART1); 
-     t0Index = entry.p1.t0Index; 
-     data.v[2] = entry.p1.word2; 
-     data.v[3] = entry.p1.word3; 
-   
-     readEntry(index + 2, entry); 
-     assert(entry.type == EntryType::POSITION_PART2); 
-     data.v[4] = entry.p2.word4; 
-     owningThread = entry.p2.owningThread; 
-     parentIndex = entry.p2.parentIndex; 
-     moveNo = entry.p2.moveNo; 
-   
-     pos.deSerialize(data); 
- } 
-   
- void 
- TreeLoggerReader::readEntry(U64 index, Entry& entry) { 
-     S64 offs = index * Entry::bufSize; 
-     if (offs != filePos) 
-         fs.seekg(offs, std::ios_base::beg); 
-     fs.read((char*)entryBuffer, sizeof(entryBuffer)); 
-     filePos = offs + sizeof(entryBuffer); 
-     entry.deSerialize(entryBuffer); 
- } 
-   
- void 
- TreeLoggerReader::writeEntry(U64 index, const Entry& entry) { 
-     entry.serialize(entryBuffer); 
-     S64 offs = index * Entry::bufSize; 
-     fs.seekp(offs, std::ios_base::beg); 
-     fs.write((const char*)entryBuffer, sizeof(entryBuffer)); 
- } 
-   
- static bool isNoMove(const Move& m) { 
-     return (m.from() == 1) && (m.to() == 1); 
- } 
-   
- std::string moveToStr(const Move& m) { 
-     if (m.isEmpty()) 
-         return "null"; 
-     else if (isNoMove(m)) 
-         return "----"; 
-     else 
-         return TextIO::moveToUCIString(m); 
- } 
-   
- void 
- TreeLoggerReader::mainLoop() { 
-     S64 currIndex = -1; 
-     std::string prevStr = ""; 
-   
-     bool doPrint = true; 
-     while (true) { 
-         if (doPrint) { 
-             if (currIndex >= 0) { 
-                 std::vector<Move> moves; 
-                 U64 rootIdx = getMoveSequence(currIndex, moves); 
-                 if (currIndex != (S64)rootIdx) { 
-                     printNodeInfo(rootIdx); 
-                     for (size_t i = 0; i < moves.size(); i++) { 
-                         const Move& m = moves[i]; 
-                         std::cout << " " << moveToStr(m); 
-                     } 
-                     std::cout << std::endl; 
-                 } 
-                 printNodeInfo(currIndex); 
-                 Position pos = getPosition(currIndex); 
-                 std::cout << TextIO::asciiBoard(pos); 
-                 std::cout << TextIO::toFEN(pos) << std::endl; 
-                 std::cout << num2Hex(pos.historyHash()) << std::endl; 
-                 if (currIndex != (S64)rootIdx) { 
-                     std::vector<U64> children; 
-                     findChildren(currIndex, children); 
-                     for (size_t i = 0; i < children.size(); i++) 
-                         printNodeInfo(children[i], i); 
-                 } 
-             } else { 
-                 std::cout << std::setw(8) << currIndex << " entries:" << numEntries << std::endl; 
-             } 
-         } 
-         doPrint = true; 
-         std::cout << "Command:" << std::flush; 
-         std::string cmdStr; 
-         std::getline(std::cin, cmdStr); 
-         if (!std::cin) 
-             return; 
-         if (cmdStr.length() == 0) 
-             cmdStr = prevStr; 
-         if (startsWith(cmdStr, "q")) { 
-             return; 
-         } else if (startsWith(cmdStr, "?")) { 
-             printHelp(); 
-             doPrint = false; 
-         } else if (isMove(cmdStr)) { 
-             if (currIndex >= 0) { 
-                 std::vector<U64> children; 
-                 findChildren(currIndex, children); 
-                 std::string m = cmdStr; 
-                 StartEntry se {}; 
-                 EndEntry ee {}; 
-                 std::vector<U64> found; 
-                 for (size_t i = 0; i < children.size(); i++) { 
-                     readEntries((int)children[i], se, ee); // Pierre-Marie Baty -- added type cast 
-                     if (moveToStr(se.getMove()) == m) 
-                         found.push_back(children[i]); 
-                 } 
-                 if (found.empty()) { 
-                     std::cout << "No such move" << std::endl; 
-                     doPrint = false; 
-                 } else if (found.size() > 1) { 
-                     std::cout << "Ambiguous move" << std::endl; 
-                     for (size_t i = 0; i < found.size(); i++) 
-                         printNodeInfo(found[i]); 
-                     doPrint = false; 
-                 } else { 
-                     currIndex = found[0]; 
-                 } 
-             } else 
-                 doPrint = false; 
-         } else if (startsWith(cmdStr, "u")) { 
-             int n = getArg(cmdStr, 1); 
-             for (int i = 0; i < n; i++) 
-                 currIndex = findParent(currIndex); 
-         } else if (startsWith(cmdStr, "lp")) { 
-             std::vector<int> args; 
-             getArgs(cmdStr, 0, args); 
-             if (args.size() == 2) { 
-                 int th = args[0]; 
-                 U64 idx = args[1]; 
-                 std::vector<U64> positions; 
-                 findChildren(-1, positions); 
-                 for (size_t p = 0; p < positions.size(); p++) { 
-                     U64 posIdx = positions[p]; 
-                     Position pos; 
-                     int owningThread, moveNo; 
-                     U64 parentIndex; 
-                     U64 t0Index; 
-                     getRootNode(posIdx, pos, owningThread, parentIndex, moveNo, t0Index); 
-                     if ((owningThread == th) && (parentIndex == idx)) { 
-                         printNodeInfo(posIdx, p); 
-                         std::vector<U64> children; 
-                         findChildren(posIdx, children); 
-                         for (size_t c = 0; c < children.size(); c++) 
-                             printNodeInfo(children[c], c); 
-                     } 
-                 } 
-             } 
-             doPrint = false; 
-         } else if (startsWith(cmdStr, "l")) { 
-             std::vector<U64> children; 
-             findChildren(currIndex, children); 
-             if (currIndex >= 0) { 
-                 bool onlyBest = startsWith(cmdStr, "lb"); 
-                 std::string m = getArgStr(cmdStr, ""); 
-                 if (onlyBest) { 
-                     int bestDepth = -1; 
-                     int bestScore = std::numeric_limits<int>::min(); 
-                     for (size_t i = 0; i < children.size(); i++) { 
-                         StartEntry se {}; 
-                         EndEntry ee {}; 
-                         bool haveEE = readEntries((int)children[i], se, ee); // Pierre-Marie Baty -- added type cast 
-                         if (!haveEE || (ee.scoreType == TType::T_GE) || isNoMove(se.getMove())) 
-                             continue; 
-                         int d = se.depth; 
-                         if ((ee.scoreType == TType::T_EXACT) && (ee.score > se.beta)) 
-                             continue; 
-                         if ((d > bestDepth) || ((d == bestDepth) && (-ee.score > bestScore))) { 
-                             bool falseFH = false; 
-                             if (ee.scoreType == TType::T_LE) { 
-                                 for (size_t ci = i+1; ci < children.size(); ci++) { 
-                                     StartEntry se2 {}; 
-                                     EndEntry ee2 {}; 
-                                     bool haveEE2 = readEntries((int)children[ci], se2, ee2); // Pierre-Marie Baty -- added type cast 
-                                     if (!haveEE2 || !(se2.move == se.move)) 
-                                         break; 
-                                     if ((ee2.scoreType == TType::T_GE) || 
-                                         ((ee2.scoreType == TType::T_EXACT) && (ee2.score > ee.score))) { 
-                                         falseFH = true; 
-                                         break; 
-                                     } 
-                                     if (ee2.scoreType == TType::T_EXACT) 
-                                         break; 
-                                 } 
-                             } 
-                             if (!falseFH) { 
-                                 printNodeInfo(children[i], i, m); 
-                                 bestDepth = d; 
-                                 bestScore = -ee.score; 
-                             } 
-                         } 
-                     } 
-                 } else { 
-                     for (size_t i = 0; i < children.size(); i++) 
-                         printNodeInfo(children[i], i, m); 
-                 } 
-             } else { 
-                 for (size_t i = 0; i < children.size(); i++) 
-                     printNodeInfo(children[i], i); 
-             } 
-             doPrint = false; 
-         } else if (startsWith(cmdStr, "n")) { 
-             if (currIndex >= 0) { 
-                 std::vector<U64> nodes; 
-                 getNodeSequence(currIndex, nodes); 
-                 for (size_t i = 0; i < nodes.size(); i++) 
-                     printNodeInfo(nodes[i]); 
-             } 
-             doPrint = false; 
-         } else if (startsWith(cmdStr, "d")) { 
-             std::vector<int> nVec; 
-             getArgs(cmdStr, 0, nVec); 
-             for (int n : nVec) { 
-                 std::vector<U64> children; 
-                 findChildren(currIndex, children); 
-                 if ((n >= 0) && (n < (int)children.size())) { 
-                     currIndex = children[n]; 
-                 } else 
-                     break; 
-             } 
-         } else if (startsWith(cmdStr, "p")) { 
-             if (currIndex >= 0) { 
-                 std::vector<Move> moves; 
-                 getMoveSequence(currIndex, moves); 
-                 for (size_t i = 0; i < moves.size(); i++) 
-                     std::cout << ' ' << moveToStr(moves[i]); 
-                 std::cout << std::endl; 
-             } 
-             doPrint = false; 
-         } else if (startsWith(cmdStr, "h")) { 
-             bool onlyPrev = startsWith(cmdStr, "hp"); 
-             U64 hashKey = currIndex >= 0 ? getPosition(currIndex).historyHash() : (U64)-1; 
-             hashKey = getHashKey(cmdStr, hashKey); 
-             std::vector<U64> nodes; 
-             getNodesForHashKey(hashKey, nodes, onlyPrev ? currIndex+1 : numEntries); 
-             for (size_t i = 0; i < nodes.size(); i++) 
-                 printNodeInfo(nodes[i]); 
-             doPrint = false; 
-         } else { 
-             S64 i; 
-             if (str2Num(cmdStr, i)) 
-                 if ((i >= -1) && (i < (S64)numEntries)) 
-                     currIndex = i; 
-         } 
-         prevStr = cmdStr; 
-     } 
- } 
-   
- bool 
- TreeLoggerReader::isMove(std::string cmdStr) const { 
-     if (cmdStr.length() != 4) 
-         return false; 
-     cmdStr = toLowerCase(cmdStr); 
-     for (int i = 0; i < 4; i++) { 
-         int c = cmdStr[i]; 
-         if ((i == 0) || (i == 2)) { 
-             if ((c < 'a') || (c > 'h')) 
-                 return false; 
-         } else { 
-             if ((c < '1') || (c > '8')) 
-                 return false; 
-         } 
-     } 
-     return true; 
- } 
-   
- void 
- TreeLoggerReader::getNodesForHashKey(U64 hashKey, std::vector<U64>& nodes, U64 maxEntry) { 
-     Position pos; 
-     for (U64 index = 0; index < maxEntry; index++) { 
-         readEntry(index, entry); 
-         if (entry.type == EntryType::NODE_END) { 
-             if (entry.ee.hashKey == hashKey) 
-                 nodes.push_back(entry.ee.startIndex); 
-         } else if (entry.type == EntryType::POSITION_PART0) { 
-             getRootNode(index, pos); 
-             if (pos.historyHash() == hashKey) 
-                 nodes.push_back(index); 
-         } 
-     } 
-     std::sort(nodes.begin(), nodes.end()); 
- } 
-   
- U64 
- TreeLoggerReader::getHashKey(std::string& s, U64 defKey) const { 
-     U64 key = defKey; 
-     size_t idx = s.find_first_of(' '); 
-     if (idx != s.npos) { 
-         s = s.substr(idx + 1); 
-         if (startsWith(s, "0x")) 
-             s = s.substr(2); 
-         hexStr2Num(s, key); 
-     } 
-     return key; 
- } 
-   
- int 
- TreeLoggerReader::getArg(const std::string& s, int defVal) { 
-     size_t idx = s.find_first_of(' '); 
-     if (idx != s.npos) { 
-         int tmp; 
-         if (str2Num(s.substr(idx+1), tmp)) 
-             return tmp; 
-     } 
-     return defVal; 
- } 
-   
- void 
- TreeLoggerReader::getArgs(const std::string& s, int defVal, std::vector<int>& args) { 
-     std::vector<std::string> split; 
-     splitString(s, split); 
-     for (size_t i = 1; i < split.size(); i++) { 
-         int tmp; 
-         if (!str2Num(split[i], tmp)) { 
-             args.clear(); 
-             break; 
-         } 
-         args.push_back(tmp); 
-     } 
-     if (args.empty()) 
-         args.push_back(defVal); 
- } 
-   
- std::string 
- TreeLoggerReader::getArgStr(const std::string& s, const std::string& defVal) { 
-     size_t idx = s.find_first_of(' '); 
-     if (idx != s.npos) 
-         return s.substr(idx+1); 
-     return defVal; 
- } 
-   
- void 
- TreeLoggerReader::printHelp() { 
-     std::cout << "  p              - Print move sequence" << std::endl; 
-     std::cout << "  n              - Print node info corresponding to move sequence" << std::endl; 
-     std::cout << "  l [move]       - List child nodes, optionally only for one move" << std::endl; 
-     std::cout << "  lb [move]      - List best child nodes, optionally only for one move" << std::endl; 
-     std::cout << "  lp th idx      - List positions requested by thread th at index idx" << std::endl; 
-     std::cout << "  d [n1 [n2...]] - Go to child \"n\"" << std::endl; 
-     std::cout << "  move           - Go to child \"move\", if unique" << std::endl; 
-     std::cout << "  u [levels]     - Move up" << std::endl; 
-     std::cout << "  h [key]        - Find nodes with current or given hash key" << std::endl; 
-     std::cout << "  hp [key]       - Find nodes with current or given hash key before current node" << std::endl; 
-     std::cout << "  num            - Go to node \"num\"" << std::endl; 
-     std::cout << "  q              - Quit" << std::endl; 
-     std::cout << "  ?              - Print this help" << std::endl; 
- } 
-   
- bool 
- TreeLoggerReader::readEntries(int index, StartEntry& se, EndEntry& ee) { 
-     readEntry(index, entry); 
-     if (entry.type == EntryType::NODE_START) { 
-         se = entry.se; 
-         U32 eIdx = se.endIndex; 
-         if (eIdx == endMark) 
-             return false; 
-         readEntry(eIdx, entry); 
-         assert(entry.type == EntryType::NODE_END); 
-         ee = entry.ee; 
-     } else { 
-         assert(entry.type == EntryType::NODE_END); 
-         ee = entry.ee; 
-         readEntry(ee.startIndex, entry); 
-         assert(entry.type == EntryType::NODE_START); 
-         se = entry.se; 
-     } 
-     return true; 
- } 
-   
- S64 
- TreeLoggerReader::findParent(S64 index) { 
-     if (index < 0) 
-         return -1; 
-     readEntry(index, entry); 
-     if (entry.type == EntryType::NODE_END) { 
-         index = entry.ee.startIndex; 
-         readEntry(index, entry); 
-     } 
-     if (entry.type == EntryType::NODE_START) { 
-         return entry.se.parentIndex; 
-     } else if ((entry.type == EntryType::POSITION_PART0) || 
-                (entry.type == EntryType::POSITION_PART1) || 
-                (entry.type == EntryType::POSITION_PART2)) { 
-         return -1; 
-     } else { 
-         assert(false); 
-         return -1; 
-     } 
- } 
-   
- void 
- TreeLoggerReader::findChildren(S64 index, std::vector<U64>& childs) { 
-     if (index < 0) { 
-         if (numEntries == 0) 
-             return; 
-         U64 child = 0; 
-         while (child < numEntries - 1) { 
-             readEntry(child, entry); 
-             assert(entry.type == EntryType::POSITION_PART0); 
-             childs.push_back(child); 
-             child = entry.p0.nextIndex; 
-         } 
-     } else { 
-         readEntry(index, entry); 
-         U64 child; 
-         switch (entry.type) { 
-         case EntryType::NODE_END: 
-             index = entry.ee.startIndex; 
-             // Fall through 
-         case EntryType::NODE_START: 
-             child = index + 1; 
-             break; 
-         case EntryType::POSITION_PART2: 
-             index--; 
-             // Fall through 
-         case EntryType::POSITION_PART1: 
-             index--; 
-             // Fall through 
-         case EntryType::POSITION_PART0: 
-             child = index + 3; 
-             break; 
-         default: 
-             assert(false); 
-         } 
-         StartEntry se {}; 
-         EndEntry ee {}; 
-         while (child < numEntries) { 
-             readEntry(child, entry); 
-             if (entry.type != EntryType::NODE_START) 
-                 break; 
-             bool haveEE = readEntries((int)child, se, ee); // Pierre-Marie Baty -- added type cast 
-             if (se.parentIndex == index) 
-                 childs.push_back(child); 
-             if (!haveEE) 
-                 break; 
-             if (se.endIndex == endMark) 
-                 break; 
-             child = se.endIndex + 1; 
-         } 
-     } 
- } 
-   
- int 
- TreeLoggerReader::getChildNo(U64 index) { 
-     readEntry(index, entry); 
-     if (entry.type == EntryType::NODE_END) { 
-         index = entry.ee.startIndex; 
-         readEntry(index, entry); 
-     } else if (entry.type == EntryType::POSITION_PART1) { 
-         index--; 
-         readEntry(index, entry); 
-     } else if (entry.type == EntryType::POSITION_PART2) { 
-         index -= 2; 
-         readEntry(index, entry); 
-     } 
-     std::vector<U64> childs; 
-     if (entry.type == EntryType::NODE_START) { 
-         findChildren(entry.se.parentIndex, childs); 
-     } else if (entry.type == EntryType::POSITION_PART0) { 
-         findChildren(-1, childs); 
-     } else 
-         assert(false); 
-   
-     for (int i = 0; i < (int)childs.size(); i++) 
-         if (childs[i] == index) 
-             return i; 
-     return -1; 
- } 
-   
- void 
- TreeLoggerReader::getNodeSequence(U64 index, std::vector<U64>& nodes) { 
-     nodes.push_back(index); 
-     while (true) { 
-         readEntry(index, entry); 
-         if (entry.type == EntryType::NODE_END) { 
-             index = entry.ee.startIndex; 
-             readEntry(index, entry); 
-         } 
-         if (entry.type == EntryType::NODE_START) { 
-             index = entry.se.parentIndex; 
-             nodes.push_back(index); 
-         } else 
-             break; 
-     } 
-     std::reverse(nodes.begin(), nodes.end()); 
- } 
-   
- U64 
- TreeLoggerReader::getMoveSequence(U64 index, std::vector<Move>& moves) { 
-     StartEntry se {}; 
-     EndEntry ee {}; 
-     while (true) { 
-         readEntry(index, entry); 
-         if ((entry.type == EntryType::NODE_START) || 
-             (entry.type == EntryType::NODE_END)) { 
-             readEntries((int)index, se, ee); // Pierre-Marie Baty -- added type cast 
-             moves.push_back(se.getMove()); 
-             index = findParent(index); 
-         } else 
-             break; 
-     } 
-     std::reverse(moves.begin(), moves.end()); 
-     return index; 
- } 
-   
- Position 
- TreeLoggerReader::getPosition(U64 index) { 
-     std::vector<Move> moves; 
-     U64 rootPosIdx = getMoveSequence(index, moves); 
-     Position pos; 
-     getRootNode(rootPosIdx, pos); 
-     UndoInfo ui; 
-     for (size_t i = 0; i < moves.size(); i++) 
-         if (!isNoMove(moves[i])) 
-             pos.makeMove(moves[i], ui); 
-     return pos; 
- } 
-   
- void 
- TreeLoggerReader::printNodeInfo(U64 index, int childNo, const std::string& filterMove) { 
-     if (childNo == -1) 
-         childNo = getChildNo(index); 
-     readEntry(index, entry); 
-     if ((entry.type == EntryType::NODE_START) || 
-         (entry.type == EntryType::NODE_END)) { 
-         StartEntry se {}; 
-         EndEntry ee {}; 
-         bool haveEE = readEntries((int)index, se, ee); // Pierre-Marie Baty -- added type cast 
-         std::string m = moveToStr(se.getMove()); 
-         if ((filterMove.length() > 0) && (m != filterMove)) 
-             return; 
-         using SearchConst::plyScale; 
-         std::cout << std::setw(3) << childNo 
-                   << ' '   << std::setw(8) << index 
-                   << ' '   << std::setw(8) << se.t0Index 
-                   << ' '   << std::setw(8) << ee.t0Index 
-                   << ' '   << m 
-                   << " a:" << std::setw(6) << se.alpha 
-                   << " b:" << std::setw(6) << se.beta 
-                   << " p:" << std::setw(2) << (int)se.ply 
-                   << " d:" << std::setw(2) << (int)se.depth/plyScale 
-                            << '.' << ((int)se.depth % plyScale); 
-         if (haveEE) { 
-             int subTreeNodes = (se.endIndex - ee.startIndex - 1) / 2; 
-             std::string type; 
-             switch (ee.scoreType) { 
-             case TType::T_EXACT: type = "= "; break; 
-             case TType::T_GE   : type = ">="; break; 
-             case TType::T_LE   : type = "<="; break; 
-             default            : type = "  "; break; 
-             } 
-             std::cout << " s:" << type << std::setw(6) << ee.score 
-                     << " e:" << std::setw(6) << ee.evalScore 
-                     << " sub:" << subTreeNodes; 
-         } 
-         std::cout << std::endl; 
-     } else if ((entry.type == EntryType::POSITION_PART0) || 
-                (entry.type == EntryType::POSITION_PART1) || 
-                (entry.type == EntryType::POSITION_PART2)) { 
-         Position pos; 
-         int owningThread, moveNo; 
-         U64 parentIndex; 
-         U64 t0Index; 
-         getRootNode(index, pos, owningThread, parentIndex, moveNo, t0Index); 
-         std::cout << std::setw(3) << childNo 
-                   << ' ' << std::setw(8) << index 
-                   << ' ' << owningThread 
-                   << ' ' << std::setw(8) << parentIndex 
-                   << ' ' << std::setw(2) << moveNo 
-                   << ' ' << std::setw(8) << t0Index 
-                   << ' ' << TextIO::toFEN(pos) << std::endl; 
-     } else 
-         assert(false); 
- } 
-