/*
 
    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/>.
 
*/
 
 
 
/*
 
 * enginecontrol.hpp
 
 *
 
 *  Created on: Mar 4, 2012
 
 *      Author: petero
 
 */
 
 
 
#ifndef ENGINECONTROL_HPP_
 
#define ENGINECONTROL_HPP_
 
 
 
#include "search.hpp"
 
#include "transpositionTable.hpp"
 
#include "position.hpp"
 
#include "move.hpp"
 
 
 
#include <vector>
 
#include <iosfwd>
 
#include <thread>
 
#include <mutex>
 
#include <memory>
 
#include <atomic>
 
 
 
class SearchParams;
 
 
 
 
 
/**
 
 * Control the search thread.
 
 */
 
class EngineControl {
 
public:
 
    EngineControl(std::ostream& o);
 
    ~EngineControl();
 
 
 
    void startSearch(const Position& pos, const std::vector<Move>& moves, const SearchParams& sPar);
 
 
 
    void startPonder(const Position& pos, const std::vector<Move>& moves, const SearchParams& sPar);
 
 
 
    void ponderHit();
 
 
 
    void stopSearch();
 
 
 
    void newGame();
 
 
 
    /**
 
     * Compute thinking time for current search.
 
     */
 
    void computeTimeLimit(const SearchParams& sPar);
 
 
 
    static void printOptions(std::ostream& os);
 
 
 
    void setOption(const std::string& optionName, const std::string& optionValue,
 
                   bool deferIfBusy);
 
 
 
private:
 
    /**
 
     * This class is responsible for sending "info" strings during search.
 
     */
 
    class SearchListener : public Search::Listener {
 
    public:
 
        SearchListener(std::ostream& os0);
 
 
 
        void notifyDepth(int depth) override;
 
 
 
        void notifyCurrMove(const Move& m, int moveNr) override;
 
 
 
        void notifyPV(int depth, int score, int time, U64 nodes, int nps, bool isMate,
 
                      bool upperBound, bool lowerBound, const std::vector<Move>& pv,
 
                      int multiPVIndex, U64 tbHits) override;
 
 
 
        void notifyStats(U64 nodes, int nps, U64 tbHits, int time) override;
 
 
 
    private:
 
        std::ostream& os;
 
    };
 
 
 
    void startThread(int minTimeLimit, int maxTimeLimit, int maxDepth, int maxNodes);
 
 
 
    void stopThread();
 
 
 
    void setupTT();
 
 
 
    void setupPosition(Position pos, const std::vector<Move>& moves);
 
 
 
    /**
 
     * Try to find a move to ponder from the transposition table.
 
     */
 
    Move getPonderMove(Position pos, const Move& m);
 
 
 
    static std::string moveToString(const Move& m);
 
 
 
 
 
    std::ostream& os;
 
 
 
    int hashParListenerId;
 
    int clearHashParListenerId;
 
    std::map<std::string, std::string> pendingOptions;
 
 
 
    std::shared_ptr<std::thread> engineThread;
 
    std::mutex threadMutex;
 
    std::atomic<bool> shouldDetach;
 
    std::shared_ptr<Search> sc;
 
    TranspositionTable tt;
 
    ParallelData pd;
 
    KillerTable kt;
 
    History ht;
 
    std::shared_ptr<Evaluate::EvalHashTables> et;
 
    TreeLogger treeLog;
 
 
 
    Position pos;
 
    std::vector<U64> posHashList;
 
    int posHashListSize;
 
    std::atomic<bool> ponder;     // True if currently doing pondering
 
    bool onePossibleMove;
 
    std::atomic<bool> infinite;
 
 
 
    int minTimeLimit;
 
    int maxTimeLimit;
 
    int maxDepth;
 
    int maxNodes;
 
    std::vector<Move> searchMoves;
 
 
 
    // Random seed for reduced strength
 
    U64 randomSeed;
 
};
 
 
 
 
 
#endif /* ENGINECONTROL_HPP_ */