- /* 
-     Texel - A UCI chess engine. 
-     Copyright (C) 2012-2014  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/>. 
- */ 
-   
- /* 
-  * transpositionTable.cpp 
-  * 
-  *  Created on: Feb 25, 2012 
-  *      Author: petero 
-  */ 
-   
- #include "transpositionTable.hpp" 
- #include "position.hpp" 
- #include "moveGen.hpp" 
- #include "textio.hpp" 
-   
- #include <iostream> 
- #include <iomanip> 
-   
- using namespace std; 
-   
-   
- void 
- TranspositionTable::reSize(int log2Size) { 
-     const size_t numEntries = ((size_t)1) << log2Size; 
-     table.resize(numEntries); 
-     generation = 0; 
- } 
-   
- void 
- TranspositionTable::insert(U64 key, const Move& sm, int type, int ply, int depth, int evalScore) { 
-     if (depth < 0) depth = 0; 
-     size_t idx0 = getIndex(key); 
-     U64 key2 = getStoredKey(key); 
-     TTEntry ent0, ent1; 
-     ent0.load(table[idx0]); 
-     size_t idx = idx0; 
-     TTEntry* ent = &ent0; 
-     if (ent0.getKey() != key2) { 
-         size_t idx1 = idx0 ^ 1; 
-         ent1.load(table[idx1]); 
-         idx = idx1; 
-         ent = &ent1; 
-         if (ent1.getKey() != key2) 
-             if (ent1.betterThan(ent0, generation)) { 
-                 idx = idx0; 
-                 ent = &ent0; 
-             } 
-     } 
-     bool doStore = true; 
-     if ((ent->getKey() == key2) && (ent->getDepth() > depth) && (ent->getType() == type)) { 
-         if (type == TType::T_EXACT) 
-             doStore = false; 
-         else if ((type == TType::T_GE) && (sm.score() <= ent->getScore(ply))) 
-             doStore = false; 
-         else if ((type == TType::T_LE) && (sm.score() >= ent->getScore(ply))) 
-             doStore = false; 
-     } 
-     if (doStore) { 
-         if ((ent->getKey() != key2) || (sm.from() != sm.to())) 
-             ent->setMove(sm); 
-         ent->setKey(key2); 
-         ent->setScore(sm.score(), ply); 
-         ent->setDepth(depth); 
-         ent->setGeneration((S8)generation); 
-         ent->setType(type); 
-         ent->setEvalScore(evalScore); 
-         ent->store(table[idx]); 
-     } 
- } 
-   
- void 
- TranspositionTable::extractPVMoves(const Position& rootPos, const Move& mFirst, std::vector<Move>& pv) { 
-     Position pos(rootPos); 
-     Move m(mFirst); 
-     UndoInfo ui; 
-     std::vector<U64> hashHistory; 
-     while (true) { 
-         pv.push_back(m); 
-         pos.makeMove(m, ui); 
-         if (contains(hashHistory, pos.zobristHash())) 
-             break; 
-         hashHistory.push_back(pos.zobristHash()); 
-         TTEntry ent; 
-         ent.clear(); 
-         probe(pos.historyHash(), ent); 
-         if (ent.getType() == TType::T_EMPTY) 
-             break; 
-         ent.getMove(m); 
-         MoveList moves; 
-         MoveGen::pseudoLegalMoves(pos, moves); 
-         MoveGen::removeIllegal(pos, moves); 
-         bool contains = false; 
-         for (int mi = 0; mi < moves.size; mi++) 
-             if (moves[mi].equals(m)) { 
-                 contains = true; 
-                 break; 
-             } 
-         if  (!contains) 
-             break; 
-     } 
- } 
-   
- /** Extract the PV starting from posIn, using hash entries, both exact scores and bounds. */ 
- std::string 
- TranspositionTable::extractPV(const Position& posIn) { 
-     std::string ret; 
-     Position pos(posIn); 
-     bool first = true; 
-     TTEntry ent; 
-     ent.clear(); 
-     probe(pos.historyHash(), ent); 
-     UndoInfo ui; 
-     std::vector<U64> hashHistory; 
-     bool repetition = false; 
-     while (ent.getType() != TType::T_EMPTY) { 
-         Move m; 
-         ent.getMove(m); 
-         MoveList moves; 
-         MoveGen::pseudoLegalMoves(pos, moves); 
-         MoveGen::removeIllegal(pos, moves); 
-         bool valid = false; 
-         for (int mi = 0; mi < moves.size; mi++) 
-             if (moves[mi].equals(m)) { 
-                 valid = true; 
-                 break; 
-             } 
-         if  (!valid) 
-             break; 
-         if (repetition) 
-             break; 
-         if (!first) 
-             ret += ' '; 
-         if (ent.getType() == TType::T_LE) 
-             ret += '<'; 
-         else if (ent.getType() == TType::T_GE) 
-             ret += '>'; 
-         std::string moveStr = TextIO::moveToString(pos, m, false); 
-         ret += moveStr; 
-         pos.makeMove(m, ui); 
-         if (contains(hashHistory, pos.zobristHash())) 
-             repetition = true; 
-         hashHistory.push_back(pos.zobristHash()); 
-         probe(pos.historyHash(), ent); 
-         first = false; 
-     } 
-     return ret; 
- } 
-   
- void 
- TranspositionTable::printStats() const { 
-     int unused = 0; 
-     int thisGen = 0; 
-     std::vector<int> depHist; 
-     const int maxDepth = 20*8; 
-     depHist.resize(maxDepth); 
-     for (size_t i = 0; i < table.size(); i++) { 
-         TTEntry ent; 
-         ent.load(table[i]); 
-         if (ent.getType() == TType::T_EMPTY) { 
-             unused++; 
-         } else { 
-             if (ent.getGeneration() == generation) 
-                 thisGen++; 
-             if (ent.getDepth() < maxDepth) 
-                 depHist[ent.getDepth()]++; 
-         } 
-     } 
-     double w = 100.0 / table.size(); 
-     std::stringstream ss; 
-     ss.precision(2); 
-     ss << std::fixed << "hstat: size:" << table.size() 
-        << " unused:" << unused << " (" << (unused*w) << "%)" 
-        << " thisGen:" << thisGen << " (" << (thisGen*w) << "%)" << std::endl; 
-     cout << ss.str(); 
-     for (int i = 0; i < maxDepth; i++) { 
-         int c = depHist[i]; 
-         if (c > 0) { 
-             std::stringstream ss; 
-             ss.precision(2); 
-             ss << std::setw(4) << i 
-                << ' ' << std::setw(8) << c 
-                << " " << std::setw(6) << std::fixed << (c*w); 
-             std::cout << "hstat:" << ss.str() << std::endl; 
-         } 
-     } 
- } 
-