
/***************************************************************************

                                 ChessV

                   COPYRIGHT (C) 2005 BY GREGORY STRONG

This file is part of ChessV.  ChessV 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.

ChessV 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; the file 'COPYING' contains the License text, but if for
some reason you need a copy, please write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

****************************************************************************/


#include "StdAfx.h"
#include "Board.h"
#include "Book.h"


#define MAX_BOOK_POSITIONS		2500


// *** DEBUG MEMORY ALLOCATION *** //
#ifdef _DEBUG
#define new SAFE_NEW
#endif


Book::Book( Board *board )
{
	pBoard = board;
	pPositions = new SBookPosition[MAX_BOOK_POSITIONS];
	pMoves = new Movement[MAX_BOOK_POSITIONS];
	nPositions = 0;
	nMoves = 0;

	for( int x = 0; x < MAX_BOOK_POSITIONS; x++ )
	{
		pPositions[x].moveCount = 0;
		pPositions[x].primaryHash = 0UL;
		pPositions[x].secondaryHash = 0UL;
		pPositions[x].questionableFlag = 0UL;
	}
}

Book::~Book()
{
	delete[] pPositions;
	delete[] pMoves;
}

bool Book::Lookup
	( Movement &move )
{
	for( int x = 0; x < nPositions; x++ )
	{
		if( pBoard->GetPrimaryHash() == pPositions[x].primaryHash && 
			pBoard->GetSecondaryHash() == pPositions[x].secondaryHash )
		{
			int moveCount = pPositions[x].moveCount;
			int selection = rand() % moveCount;
			move = pMoves[pPositions[x].moveIndexes[selection]];
			return true;
		}
	}
	return false;
}

void Book::AddMove
	( Movement &move,
	  bool questionable )
{
	bool found = false;
	for( int x = 0; x < nPositions && !found; x++ )
	{
		if( pBoard->GetPrimaryHash() == pPositions[x].primaryHash && 
			pBoard->GetSecondaryHash() == pPositions[x].secondaryHash )
		{
			found = true;
			//	check to make sure we don't have this move already
			bool foundMove = false;
			for( int y = 0; y < pPositions[x].moveCount && !foundMove; y++ )
			{
				if( pMoves[pPositions[x].moveIndexes[y]] == move )
					foundMove = true;
			}
			//	add the move if we don't have it already
			if( !foundMove )
			{
				pMoves[nMoves] = move;
				pPositions[x].moveIndexes[pPositions[x].moveCount] = nMoves;
				if( questionable )
					pPositions[x].questionableFlag |= 1 << pPositions[x].moveCount;
				pPositions[x].moveCount++;
				nMoves++;
			}
		}
	}
	if( !found )
	{
		//	add this position
		pPositions[nPositions].primaryHash = pBoard->GetPrimaryHash();
		pPositions[nPositions].secondaryHash = pBoard->GetSecondaryHash();
		pPositions[nPositions].moveCount = 1;
		pPositions[nPositions].questionableFlag = questionable ? 1UL : 0UL;
		pMoves[nMoves] = move;
		pPositions[nPositions].moveIndexes[0] = nMoves;
		nMoves++;
		nPositions++;
	}
}
