/***************************************************************************
                          TableEntry.cpp  -  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.                                   *
 *                                                                         *
 ***************************************************************************/
# include "TranspositionTable/TableEntry.h"
using namespace Alice;

TableEntry::TableEntry():
  mCost(0),
  mDepth(-1),
  lowerScore(Evaluation::stalemate()),
  upperScore(Evaluation::stalemate()),
  mIdentifier( 0 )
{

};

void
TableEntry::clear()
{
  mCost = 0;
  mDepth = -1;
  mBestMove = 0;
};

uint64
TableEntry::identifier() const
{
  return mIdentifier;
};

int
TableEntry::cost() const
{
  return mCost;
};

int 
TableEntry::depth() const
{
  return mDepth;
};

Evaluation::Score
TableEntry::score() const
{
  return lowerScore;
};

SmartPointer<Move>
TableEntry::bestMove() const
{
  return mBestMove;
};

bool
TableEntry::cutsOff(int depth,
		    Evaluation::Score alpha, 
		    Evaluation::Score beta,
		    Evaluation::Score& result) const
{
  if (this->depth() < depth)
    return false;
  
  if (upperScore <= alpha)
    {
      result = upperScore;
      return true;
    }
  if (lowerScore >= beta)
    {
      result = lowerScore;
      return true;
    }
  return false;
};
/** stores a score

	\param type what kind of a bound is established
	\param cost how valuable is the information
	\param depth the depth to which the node was searched
	\param score the score determined by the search
	\param identifier a fingerprint of the position
	
	\returns true if the storing was successful

*/
bool 
TableEntry::store(BoundType type, int cost, int depth, 
		  Evaluation::Score score,
		  SmartPointer<Move> move,
		  uint64 identifier)
{
  switch(type){
  case EXACT: storeExact(cost, depth, score, move, identifier); break;
  case UPPER: storeUpper(cost, depth, score, move, identifier); break;
  case LOWER: storeLower(cost, depth, score, move, identifier); break;
  }
  return identifier == this->mIdentifier;
};
void
TableEntry::storeExact(int cost, int depth, Evaluation::Score score,
						SmartPointer<Move> move, uint64 identifier)
{
  if (cost >= mCost && identifier != mIdentifier || depth >= mDepth) { // new entry
	  mCost = cost;
	  mDepth = depth;
	  lowerScore = upperScore  = score;
	  mBestMove = move;
	  mIdentifier = identifier;
	  return;
	}
};

void
TableEntry::storeLower(int cost, int depth, Evaluation::Score score,
			SmartPointer<Move> move, uint64 identifier)
{
  if (((cost >= mCost) && (identifier != mIdentifier)) || (depth > mDepth)) 
    { 
      // new entry
      mCost = cost;
      mDepth = depth;
      lowerScore  = score;
      upperScore = propagate(Evaluation::mate());
      mBestMove = move;
      mIdentifier = identifier;
      return;
    }
  if (identifier != mIdentifier) return;
  if (depth < mDepth) return;
  if (score < lowerScore) return;
  mCost = cost;
  lowerScore = score;
  mBestMove = move;
}

void
TableEntry::storeUpper(int cost, int depth, Evaluation::Score score,
			SmartPointer<Move> move, uint64 identifier)
{
  if (((identifier != mIdentifier) && (cost >= mCost)) || (depth > mDepth) )
    { // new entry
      mCost = cost;
      mDepth = depth;
      upperScore  = score;
      lowerScore = Evaluation::mate();
      if (identifier != mIdentifier)
	mBestMove = move;
      mIdentifier = identifier;
      return;
    }
  if (identifier != mIdentifier) return;
  if (depth < mDepth) return;
  if (score > upperScore) return;
  mCost = cost;
  upperScore = score;
  mBestMove = move;
}

void
TableEntry::printScore(std::ostream& out)const
{
  /*
  switch(mType){
  case EXACT: out<<"="; break;
  case LOWER:out<<">="; break;
  case UPPER: out<<"<="; break;
  default:
    //out<<"unknown type "<<mType << " ";
    break;
  }
  */
  out<<"["<<lowerScore<<","<<upperScore<<"], "<<mDepth<<";";
};
