//-*-c++-*-

/***************************************************************************
                          AlphaBeta.h  -  description
                             -------------------
    begin                : Tue May 22 2001
    copyright            : (C) 2001 by Sven Reichard
    email                : reichard@math.udel.edu
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
# ifndef AlphaBeta_h
# define AlphaBeta_h
# include <Game/Evaluation.h>
# include <SmartPointer.h>
# include <Pieces/Piece.h>
# include <Moves/Move.h>
# include <Moves/MoveList.h>
# include <PrincipalVariation.h>
namespace Alice
{
class Game;
/** Base class for search algorithms
*/
class AlphaBeta
{
public:
  typedef Evaluation::Score Score;
  typedef MoveList::iterator MoveIterator;

  AlphaBeta(Game& game);
  virtual ~AlphaBeta();
  virtual void search(int depth);
  Score score() const;
  SmartPointer<Move> bestMove() const;
  virtual long nodesSearched() {return mNodesSearched;};
  int getHeight() const
  {
    return height;
  };
  virtual void setGame(Game& g);

  int nextDepth( int depth );
  void resetNodesSearched();
protected:
  Game& game();
  virtual const Evaluation* getEvaluation() const = 0;
  struct SearchParameters;
  virtual Score recursiveSearch(int depth, Score alpha, Score beta);
  virtual Score recursiveSearch( SearchParameters& parameters );
  Score mScore;
  SmartPointer<Move> mBestMove;
  bool ownsEvaluation;
  long mNodesSearched;
  bool makeMove(MoveIterator& it);
  void takeBack(MoveIterator& it);
  Score stalemateScore();
  bool movedIntoCheck();
  int nextDepth( const SearchParameters& );
  virtual bool generateMoves(MoveList& moves);
  virtual Score initialScore(SearchParameters&);
  virtual Score staticEvaluation(Score alpha, Score beta);
  virtual void presearch();
  virtual bool cutOff(SearchParameters& param);
  
  virtual void finishNode(SearchParameters&);
  virtual void failHigh(int depth, Score score,
			SmartPointer<Move> bestMove);
  virtual bool stopSearch(SearchParameters&, SmartPointer<Move> move);
  struct SearchParameters
  {
    Score alpha;
    Score beta;
    Score max;
    Score result;
    int depth;
    SmartPointer<Move> bestMove;
    PrincipalVariation* pv;
    bool ownsPv;
    SearchParameters(int pDepth, Score pMax, Score pAlpha, Score pBeta):
      alpha(pAlpha), beta(pBeta), max(pMax), depth(pDepth)
    {
      pv = new PrincipalVariation;
      ownsPv = true;
    };
    SearchParameters(int pDepth, Score pMax, Score pAlpha, Score pBeta,
		     PrincipalVariation* priVar):
      alpha(pAlpha), beta(pBeta), max(pMax), depth(pDepth),
      pv(priVar)
    {
      
      ownsPv = false;
    };
    ~SearchParameters()
    {
      if (ownsPv)
	delete pv;
    };
    SearchParameters next( int newDepth )
    {
      return SearchParameters( newDepth,
			       Evaluation::mate(),
			       propagate(beta),
			       propagate(alpha),
			       pv->next());
    };
  };
  void printPV2();
  private:
  int height;
  std::vector<MoveList>moveLists;
  Game* mGame;
  AlphaBeta(const AlphaBeta&) {};
  AlphaBeta& operator=(const AlphaBeta){return *this;}
};

inline
Game&
AlphaBeta::game() 
{
  return *mGame;
};
} // namespace Alice
# endif
