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

                                 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 "Game.h"
#include "Piece.h"
#include "ChessV.h"
#include "Personality.h"
#include "GameParameters.h"
#include "HistoricalMove.h"
#include "Games/Ultima/Ultima_types.h"


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


static int orthogonalDirections[4] = { DIRECTION_N, DIRECTION_S, DIRECTION_E, DIRECTION_W };


// ************************************ //
// ***                              *** //
// ***         CONSTRUCTION         *** //
// ***                              *** //
// ************************************ //

Game::Game
	( Board &theBoard, 
	  Player &whitePlayer, 
	  Player &blackPlayer ):
		board(theBoard), 
		player0(whitePlayer), 
		player1(blackPlayer),
		goalIsCheckmate(true),
		useQuiescentSearch(true),
		useStaticExchangeEvaluation(true),
		usePawnStructureEvaluation(false),
		endgameCaptureThreshold(1)
{
	stalemateResult = 0;
	moveHistoryLength = 0;
	moveCursor = 0;
	specialCheckTesting = false;
	drawScore = 0;
	autoDrawPeriod = 0;
	boardAverageSquareValue = 100;
	razorMargin = 10000;
	futilityMargin = 4500;
	extendedFutilityMargin = 6000;
	gameOver = false;
	immobilizedPiecesCanCommitSuicide = true;
	customMoveGeneration = false;
	customCaptureGeneration = false;
	piecesHaveChangingValues = true;
}

Game::~Game()
{
}

void Game::Initialize()
{
	char *book = NULL;	//	text filename of opening book
	char *array;		//	FEN notation of position setup

	//	make user-specified function calls (with priority 1-9)
	CallFunctions( 1, 10, this, &board );

	//	declare and set the name of the actual (internal) game; that is, 
	//	not the name of the derived game if this is a user-defined game
	char *gameName = selectedVariant->baseGameName == NULL ? 
		selectedVariant->name : selectedVariant->baseGameName;

	// *** ADD PIECE TYPES *** //
	AddPlayerPieceTypes( gameName );

	// *** set Personality *** //
	SetPersonality( PERSONALITY_A );

	// *** CHANGE RULES FOR PARTICULAR (BUILT-IN) VARIANT *** //
	ChangeRulesByVariant( gameName, array, book );

	//	make user-specified function calls (with priority 10-19)
	CallFunctions( 10, 20, this, &board );

	// *** PLACE PIECES *** //
	PlacePieces( array, book );

	// *** OPENING BOOK *** //

	//	allow variable definition use-opening-book to turn off usage of the 
	//	opening book, but not turn it on (or it could lead to bad results)
	bool userOpeningBook = true;
	if( LookupBoolParameter( "use-opening-book", userOpeningBook ) )
		useOpeningBook = useOpeningBook & userOpeningBook;
	if( useOpeningBook )
	{
		if( book == NULL )
			//	it is an unknown variant, and we have no filename specified, 
			//	so we cannot possibly use an opening book
			useOpeningBook = false;
		else
		{
			//	everything is ok.  we now can actually create and use the book
			Book *pBook = new Book( &board );
			board.SetOpeningBook( pBook, book );
		}
	}

	// *** implement RULE CHANGES by VARIABLE DEFINITION *** //
	ChangeRulesByVariableDefinition( gameName );

	// *** INITIALIZE the BOARD *** //
	board.PostInitialize();

	//	make user-specified function calls (with priority 20-29)
	CallFunctions( 20, 30, this, &board );

	//	notify the game that initialization has completed
	InitializationComplete( gameName );
}

void Game::InitializationComplete( char *gameName )
{
}


// ************************************ //
// ***                              *** //
// ***          OPERATIONS          *** //
// ***                              *** //
// ************************************ //

void Game::PlacePieces( char *array, char *&book )
{
	//	lookup user 'array' variable to see if a custom array is specified
	if( LookupStringParameter( "array", array ) )
	{
		//	if an array is specified by the user 'array' variable, 
		//	turn off the opening book, unless a new book is also specified
		if( !LookupStringParameter( "opening-book", book ) )
			useOpeningBook = false;
	}
	else
		//	see if the user sets or changes the opening book file.
		//	NOTE: the LookupStringParameter function does not change 
		//	the contents of the 'book' variable if no definition exists
		LookupStringParameter( "opening-book", book );

	//	place the pieces on the board
	board.PlacePiecesByFEN( array );
}

void Game::ChangeRulesByVariant
	( char *gameName, 
	  char *&array, 
	  char *&book )
{
}

void Game::ChangeRulesByVariableDefinition( char *gameName )
{
}

void Game::AddHistoricalMove
	( MoveInfo &move )
{
	char buffer[80];
	DescribeMove( move, NULL, buffer, NULL );
	if( moveCursor % 2 == 0 )
		sprintf( historicalMoveText[moveCursor], "%d.\t%s", moveCursor / 2 + 1, buffer );
	else
		sprintf( historicalMoveText[moveCursor], "      ...\t%s", buffer );
	::SendMessage( hMoveList, LB_ADDSTRING, 0, (LPARAM) historicalMoveText[moveCursor] );
	moveCursor++;
	moveHistoryLength = moveCursor;
}


// ************************************ //
// ***                              *** //
// ***           OVERRIDES          *** //
// ***                              *** //
// ************************************ //

Piece *Game::AddPiece
	( PieceType &pieceType,
	  int nPlayer,
	  int nRank,
	  int nFile )
{
	Piece *newPiece = new Piece( pieceType, GetPlayer(nPlayer) );
	board.AddPieceToBoard( *newPiece, nRank, nFile );
	newPiece->GetType().SetPieceDefaults( newPiece );
	return newPiece;
}

void Game::SetPersonality
	( int personality )
{
	//	re-initialize all piece types
	for( int nPieceType = 0; nPieceType < board.nPieceTypes; nPieceType++ )
		board.pieceTypes[nPieceType]->Initialize( personality );

	//	recalculate material values
	board.RecalculateMaterial();

	//	clear all hash tables
	board.hashTable.ClearAll();
	if( board.pEvalHashtable != NULL )
		board.pEvalHashtable->ClearAll();
}

PieceType **Game::GetPieceTypesRequired
	( int &nPieceTypes )
{
	nPieceTypes = board.GetPieceTypeCount();
	return board.GetPieceTypes();
}

bool Game::RemovePieceType
	( PieceType *pieceType )
{
	return true;
}

bool Game::AddPieceType
	( PieceType *pieceType,
	  int nPlayer )
{
	return true;
}

bool Game::MoveBeingMade
	( MoveInfo &moveInfo,
	  GameRec &gameRecord )
{
	return true;
}

void Game::AddSpecialMoves
	( int currentPlayer, 
	  MovementList &stack,
	  GameRec &gameRecord, 
	  bool quiescentSearch )
{
}

void Game::DeletePiece
	( Piece *piece )
{
}

bool Game::IsPositionForbidden()
{
	return false;
}

word32 Game::GetEnPassantHash
	( GameRec &gameRecord, 
	  HashMap *hashes )
{
	if( gameRecord.pieceMoved != NULL &&
		gameRecord.pieceMoved->IsPawn() &&
		gameRecord.pieceMoved->HasMoved() )
	{
		if( !gameRecord.pieceMoved->HasMovedTwice() &&
			(gameRecord.pieceMoved->GetSquareNumber() - (2 * board.GetNumberOfFiles()) == gameRecord.oldSquareNumber || 
			 gameRecord.pieceMoved->GetSquareNumber() - (3 * board.GetNumberOfFiles()) == gameRecord.oldSquareNumber) )
		{
			//	white pawn just moved two or three squares; see if there's
			//	a black pawn that can take it en passant
			int square1 = board.GetMovementMatrix( DIRECTION_W )[gameRecord.pieceMoved->GetSquareNumber()];
			int square2 = board.GetMovementMatrix( DIRECTION_E )[gameRecord.pieceMoved->GetSquareNumber()];
			int captureSquare = gameRecord.pieceMoved->GetSquareNumber();
			if( square1 != -1 && board.GetSquareContents( square1 ) != NULL )
			{
				Piece *piece = board.GetSquareContents( square1 );
				if( piece->IsPawn() && piece->GetPlayerNumber() == 1 )
					return hashes->GetHash( captureSquare - board.GetNumberOfFiles() );
			}
			if( square2 != -1 && board.GetSquareContents( square2 ) != NULL )
			{
				Piece *piece = board.GetSquareContents( square2 );
				if( piece->IsPawn() && piece->GetPlayerNumber() == 1 )
					return hashes->GetHash( captureSquare - board.GetNumberOfFiles() );
			}
			if( gameRecord.pieceMoved->GetSquareNumber() - (3 * board.GetNumberOfFiles()) == gameRecord.oldSquareNumber )
			{
				int square1 = board.GetMovementMatrix( DIRECTION_W )[captureSquare - board.GetNumberOfFiles()];
				int square2 = board.GetMovementMatrix( DIRECTION_E )[captureSquare - board.GetNumberOfFiles()];
				if( square1 != -1 && board.GetSquareContents( square1 ) != NULL )
				{
					Piece *piece = board.GetSquareContents( square1 );
					if( piece->IsPawn() && piece->GetPlayerNumber() == 1 )
						return hashes->GetHash( captureSquare - (board.GetNumberOfFiles()) );
				}
				if( square2 != -1 && board.GetSquareContents( square2 ) != NULL )
				{
					Piece *piece = board.GetSquareContents( square2 );
					if( piece->IsPawn() && piece->GetPlayerNumber() == 1 )
						return hashes->GetHash( captureSquare - (board.GetNumberOfFiles()) );
				}
				square1 = board.GetMovementMatrix( DIRECTION_W )[captureSquare - board.GetNumberOfFiles() - board.GetNumberOfFiles()];
				square2 = board.GetMovementMatrix( DIRECTION_E )[captureSquare - board.GetNumberOfFiles() - board.GetNumberOfFiles()];
				if( square1 != -1 && board.GetSquareContents( square1 ) != NULL )
				{
					Piece *piece = board.GetSquareContents( square1 );
					if( piece->IsPawn() && piece->GetPlayerNumber() == 1 )
						return hashes->GetHash( captureSquare - (2 * board.GetNumberOfFiles()) );
				}
				if( square2 != -1 && board.GetSquareContents( square2 ) != NULL )
				{
					Piece *piece = board.GetSquareContents( square2 );
					if( piece->IsPawn() && piece->GetPlayerNumber() == 1 )
						return hashes->GetHash( captureSquare - (2 * board.GetNumberOfFiles()) );
				}
			}
		}
		if( !gameRecord.pieceMoved->HasMovedTwice() &&
			(gameRecord.pieceMoved->GetSquareNumber() + (2 * board.GetNumberOfFiles()) == gameRecord.oldSquareNumber || 
			 gameRecord.pieceMoved->GetSquareNumber() + (3 * board.GetNumberOfFiles()) == gameRecord.oldSquareNumber) )
		{
			//	black pawn just moved two or three squares; see if there's
			//	a white pawn that can take it en passant
			int square1 = board.GetMovementMatrix( DIRECTION_W )[gameRecord.pieceMoved->GetSquareNumber()];
			int square2 = board.GetMovementMatrix( DIRECTION_E )[gameRecord.pieceMoved->GetSquareNumber()];
			int captureSquare = gameRecord.pieceMoved->GetSquareNumber();
			if( square1 != -1 && board.GetSquareContents( square1 ) != NULL )
			{
				Piece *piece = board.GetSquareContents( square1 );
				if( piece->IsPawn() && piece->GetPlayerNumber() == 0 )
					return hashes->GetHash( captureSquare + board.GetNumberOfFiles() );
			}
			if( square2 != -1 && board.GetSquareContents( square2 ) != NULL )
			{
				Piece *piece = board.GetSquareContents( square2 );
				if( piece->IsPawn() && piece->GetPlayerNumber() == 0 )
					return hashes->GetHash( captureSquare + board.GetNumberOfFiles() );
			}
			if( gameRecord.pieceMoved->GetSquareNumber() + (3 * board.GetNumberOfFiles()) == gameRecord.oldSquareNumber )
			{
				int square1 = board.GetMovementMatrix( DIRECTION_W )[captureSquare + board.GetNumberOfFiles()];
				int square2 = board.GetMovementMatrix( DIRECTION_E )[captureSquare + board.GetNumberOfFiles()];
				if( square1 != -1 && board.GetSquareContents( square1 ) != NULL )
				{
					Piece *piece = board.GetSquareContents( square1 );
					if( piece->IsPawn() && piece->GetPlayerNumber() == 0 )
						return hashes->GetHash( captureSquare + (board.GetNumberOfFiles()) );
				}
				if( square2 != -1 && board.GetSquareContents( square2 ) != NULL )
				{
					Piece *piece = board.GetSquareContents( square2 );
					if( piece->IsPawn() && piece->GetPlayerNumber() == 0 )
						return hashes->GetHash( captureSquare + (board.GetNumberOfFiles()) );
				}
				square1 = board.GetMovementMatrix( DIRECTION_W )[captureSquare + board.GetNumberOfFiles() + board.GetNumberOfFiles()];
				square2 = board.GetMovementMatrix( DIRECTION_E )[captureSquare + board.GetNumberOfFiles() + board.GetNumberOfFiles()];
				if( square1 != -1 && board.GetSquareContents( square1 ) != NULL )
				{
					Piece *piece = board.GetSquareContents( square1 );
					if( piece->IsPawn() && piece->GetPlayerNumber() == 0 )
						return hashes->GetHash( captureSquare + (2 * board.GetNumberOfFiles()) );
				}
				if( square2 != -1 && board.GetSquareContents( square2 ) != NULL )
				{
					Piece *piece = board.GetSquareContents( square2 );
					if( piece->IsPawn() && piece->GetPlayerNumber() == 0 )
						return hashes->GetHash( captureSquare + (2 * board.GetNumberOfFiles()) );
				}
			}
		}
	}
	return 0UL;
}

void Game::AddEnPassantMoves
	( MovementList &stack,
	  GameRec &gameRecord, 
	  bool quiescentSearch )
{
	if( gameRecord.pieceMoved != NULL &&
		gameRecord.pieceMoved->IsPawn() &&
		gameRecord.pieceMoved->HasMoved() )
	{
		if( !gameRecord.pieceMoved->HasMovedTwice() &&
			(gameRecord.pieceMoved->GetSquareNumber() - (2 * board.GetNumberOfFiles()) == gameRecord.oldSquareNumber || 
			 gameRecord.pieceMoved->GetSquareNumber() - (3 * board.GetNumberOfFiles()) == gameRecord.oldSquareNumber) )
		{
			//	white pawn just moved two or three squares; see if there's
			//	a black pawn that can take it en passant
			int square1 = board.GetMovementMatrix( DIRECTION_W )[gameRecord.pieceMoved->GetSquareNumber()];
			int square2 = board.GetMovementMatrix( DIRECTION_E )[gameRecord.pieceMoved->GetSquareNumber()];
			int captureSquare = gameRecord.pieceMoved->GetSquareNumber();
			if( square1 != -1 && board.GetSquareContents( square1 ) != NULL )
			{
				Piece *piece = board.GetSquareContents( square1 );
				if( piece->IsPawn() && piece->GetPlayerNumber() == 1 )
				{
					stack.BeginMoveAdd( EnPassant, square1, captureSquare - board.GetNumberOfFiles() );
					stack.AddPickUp( square1 );
					stack.AddPickUp( captureSquare );
					stack.AddDrop( piece, captureSquare - board.GetNumberOfFiles() );
					stack.EndMoveAdd();
				}
			}
			if( square2 != -1 && board.GetSquareContents( square2 ) != NULL )
			{
				Piece *piece = board.GetSquareContents( square2 );
				if( piece->IsPawn() && piece->GetPlayerNumber() == 1 )
				{
					stack.BeginMoveAdd( EnPassant, square2, captureSquare - board.GetNumberOfFiles() );
					stack.AddPickUp( square2 );
					stack.AddPickUp( captureSquare );
					stack.AddDrop( piece, captureSquare - board.GetNumberOfFiles() );
					stack.EndMoveAdd();
				}
			}
			if( gameRecord.pieceMoved->GetSquareNumber() - (3 * board.GetNumberOfFiles()) == gameRecord.oldSquareNumber )
			{
				int square1 = board.GetMovementMatrix( DIRECTION_W )[captureSquare - board.GetNumberOfFiles()];
				int square2 = board.GetMovementMatrix( DIRECTION_E )[captureSquare - board.GetNumberOfFiles()];
				if( square1 != -1 && board.GetSquareContents( square1 ) != NULL )
				{
					Piece *piece = board.GetSquareContents( square1 );
					if( piece->IsPawn() && piece->GetPlayerNumber() == 1 )
					{
						stack.BeginMoveAdd( EnPassant, square1, captureSquare - (2 * board.GetNumberOfFiles()) );
						stack.AddPickUp( square1 );
						stack.AddPickUp( captureSquare );
						stack.AddDrop( piece, captureSquare - (2 * board.GetNumberOfFiles()) );
						stack.EndMoveAdd();
					}
				}
				if( square2 != -1 && board.GetSquareContents( square2 ) != NULL )
				{
					Piece *piece = board.GetSquareContents( square2 );
					if( piece->IsPawn() && piece->GetPlayerNumber() == 1 )
					{
						stack.BeginMoveAdd( EnPassant, square2, captureSquare - (2 * board.GetNumberOfFiles()) );
						stack.AddPickUp( square2 );
						stack.AddPickUp( captureSquare );
						stack.AddDrop( piece, captureSquare - (2 * board.GetNumberOfFiles()) );
						stack.EndMoveAdd();
					}
				}
			}
		}
	}
	if( gameRecord.pieceMoved != NULL &&
		gameRecord.pieceMoved->IsPawn() &&
		gameRecord.pieceMoved->HasMoved() &&
		!gameRecord.pieceMoved->HasMovedTwice() &&
		(gameRecord.pieceMoved->GetSquareNumber() + (2 * board.GetNumberOfFiles()) == gameRecord.oldSquareNumber ||
		 gameRecord.pieceMoved->GetSquareNumber() + (3 * board.GetNumberOfFiles()) == gameRecord.oldSquareNumber) )
	{
		//	black pawn just moved two or three spaces; see if there's
		//	a white pawn that can take it en passant
		int captureSquare = gameRecord.pieceMoved->GetSquareNumber();
		int square1 = board.GetMovementMatrix( DIRECTION_W )[gameRecord.pieceMoved->GetSquareNumber()];
		int square2 = board.GetMovementMatrix( DIRECTION_E )[gameRecord.pieceMoved->GetSquareNumber()];
		if( square1 != -1 && board.GetSquareContents( square1 ) != NULL )
		{
			Piece *piece = board.GetSquareContents( square1 );
			if( piece->IsPawn() && piece->GetPlayerNumber() == 0 )
			{
				stack.BeginMoveAdd( EnPassant, square1, captureSquare + board.GetNumberOfFiles() );
				stack.AddPickUp( square1 );
				stack.AddPickUp( captureSquare );
				stack.AddDrop( piece, captureSquare + board.GetNumberOfFiles() );
				stack.EndMoveAdd();
			}
		}
		if( square2 != -1 && board.GetSquareContents( square2 ) != NULL )
		{
			Piece *piece = board.GetSquareContents( square2 );
			if( piece->IsPawn() && piece->GetPlayerNumber() == 0 )
			{
				stack.BeginMoveAdd( EnPassant, square2, captureSquare + board.GetNumberOfFiles() );
				stack.AddPickUp( square2 );
				stack.AddPickUp( captureSquare );
				stack.AddDrop( piece, captureSquare + board.GetNumberOfFiles() );
				stack.EndMoveAdd();
			}
		}
		if( gameRecord.pieceMoved->GetSquareNumber() + (3 * board.GetNumberOfFiles()) == gameRecord.oldSquareNumber )
		{
			int square1 = board.GetMovementMatrix( DIRECTION_W )[captureSquare + board.GetNumberOfFiles()];
			int square2 = board.GetMovementMatrix( DIRECTION_E )[captureSquare + board.GetNumberOfFiles()];
			if( square1 != -1 && board.GetSquareContents( square1 ) != NULL )
			{
				Piece *piece = board.GetSquareContents( square1 );
				if( piece->IsPawn() && piece->GetPlayerNumber() == 0 )
				{
					stack.BeginMoveAdd( EnPassant, square1, captureSquare + (2 * board.GetNumberOfFiles()) );
					stack.AddPickUp( square1 );
					stack.AddPickUp( captureSquare );
					stack.AddDrop( piece, captureSquare + (2 * board.GetNumberOfFiles()) );
					stack.EndMoveAdd();
				}
			}
			if( square2 != -1 && board.GetSquareContents( square2 ) != NULL )
			{
				Piece *piece = board.GetSquareContents( square2 );
				if( piece->IsPawn() && piece->GetPlayerNumber() == 0 )
				{
					stack.BeginMoveAdd( EnPassant, square2, captureSquare + (2 * board.GetNumberOfFiles()) );
					stack.AddPickUp( square2 );
					stack.AddPickUp( captureSquare );
					stack.AddDrop( piece, captureSquare + (2 * board.GetNumberOfFiles()) );
					stack.EndMoveAdd();
				}
			}
		}
	}
}

word32 Game::GetBerolinaEnPassantHash
	( GameRec &gameRecord, 
	  HashMap *hashes )
{
	if( gameRecord.pieceMoved != NULL &&
		gameRecord.pieceMoved->IsPawn() &&
		gameRecord.pieceMoved->HasMoved() )
	{
		if( !gameRecord.pieceMoved->HasMovedTwice() &&
			gameRecord.pieceMoved->GetSquareNumber() - board.GetNumberOfFiles() - board.GetNumberOfFiles() + 2 == gameRecord.oldSquareNumber )
		{
			//	white pawn just moved two squares; see if there's
			//	a black pawn that can take it en passant
			int square = gameRecord.pieceMoved->GetSquareNumber() - 1;
			if( square != -1 && board.GetSquareContents( square ) != NULL )
			{
				Piece *piece = board.GetSquareContents( square );
				if( piece->IsPawn() && piece->GetPlayerNumber() == 1 )
					return hashes->GetHash( square - board.GetNumberOfFiles() );
			}
		}
		else if( !gameRecord.pieceMoved->HasMovedTwice() &&
			gameRecord.pieceMoved->GetSquareNumber() - board.GetNumberOfFiles() - board.GetNumberOfFiles() - 2 == gameRecord.oldSquareNumber )
		{
			//	white pawn just moved two squares; see if there's
			//	a black pawn that can take it en passant
			int square = gameRecord.pieceMoved->GetSquareNumber() + 1;
			if( square != -1 && board.GetSquareContents( square ) != NULL )
			{
				Piece *piece = board.GetSquareContents( square );
				if( piece->IsPawn() && piece->GetPlayerNumber() == 1 )
					return hashes->GetHash( square - board.GetNumberOfFiles() );
			}
		}
		else if( !gameRecord.pieceMoved->HasMovedTwice() &&
			gameRecord.pieceMoved->GetSquareNumber() + board.GetNumberOfFiles() + board.GetNumberOfFiles() - 2 == gameRecord.oldSquareNumber )
		{
			//	black pawn just moved two squares; see if there's
			//	a white pawn that can take it en passant
			int square = gameRecord.pieceMoved->GetSquareNumber() + 1;
			if( square != -1 && board.GetSquareContents( square ) != NULL )
			{
				Piece *piece = board.GetSquareContents( square );
				if( piece->IsPawn() && piece->GetPlayerNumber() == 0 )
					return hashes->GetHash( square - board.GetNumberOfFiles() );
			}
		}
		else if( !gameRecord.pieceMoved->HasMovedTwice() &&
			gameRecord.pieceMoved->GetSquareNumber() + board.GetNumberOfFiles() + board.GetNumberOfFiles() + 2 == gameRecord.oldSquareNumber )
		{
			//	black pawn just moved two squares; see if there's
			//	a white pawn that can take it en passant
			int square = gameRecord.pieceMoved->GetSquareNumber() - 1;
			if( square != -1 && board.GetSquareContents( square ) != NULL )
			{
				Piece *piece = board.GetSquareContents( square );
				if( piece->IsPawn() && piece->GetPlayerNumber() == 0 )
					return hashes->GetHash( square - board.GetNumberOfFiles() );
			}
		}
	}
	return 0UL;
}

//	will add the specified castling move if the required squares 
//	are open, and the squares which the king visits are not 
//	attacked.  does NOT check to ensure that the king has not moved, 
//	the rook has not moved, and that the king is not castling out 
//	of check.  if game rules require this, test these conditions 
//	before calling this function
void Game::AddCastlingMove
	( MovementList &stack,
	  GameRec &gameRecord, 
	  Piece *king,
	  Piece *castlingPiece,
	  int newKingSquare,
	  int newCastlingPieceSquare )
{
	int kingSquare = king->GetSquareNumber();
	int castlingPieceSquare = castlingPiece->GetSquareNumber();
	int otherPlayer = FLIP(king->GetPlayerNumber());
	int x;

	if( castlingPieceSquare < kingSquare )
	{
		// *** CASTLING LEFT *** //

		//	make sure that squares are open
		for( x = kingSquare - 1; x >= castlingPieceSquare + 1; x-- )
			if( board.GetSquareContents( x ) != NULL )
				//	square is blockied; cannot castle
				return;

		//	make sure that squares the king will be 
		//	occupying are not attacked
		for( x = kingSquare - 1; x >= newKingSquare; x-- )
			if( IsSquareAttacked( x, otherPlayer ) )
				//	square is attacked; cannot castle
				return;
	}
	else
	{
		// *** CASTLING RIGHT *** //

		//	make sure that squares are open
		for( x = kingSquare + 1; x <= castlingPieceSquare - 1; x++ )
			if( board.GetSquareContents( x ) != NULL )
				//	square is blockied; cannot castle
				return;

		//	make sure that squares the king will be 
		//	occupying are not attacked
		for( x = kingSquare + 1; x <= newKingSquare; x++ )
			if( IsSquareAttacked( x, otherPlayer ) )
				//	square is attacked; cannot castle
				return;
	}
	//	everything is OK - add the move
	stack.BeginMoveAdd( Castling, kingSquare, newKingSquare );
	stack.AddPickUp( kingSquare );
	stack.AddPickUp( castlingPieceSquare );
	stack.AddDrop( king, newKingSquare );
	stack.AddDrop( castlingPiece, newCastlingPieceSquare );
	stack.EndMoveAdd( 1000 );
}

void Game::AddFreeCastlingMoves
	( MovementList &stack,
	  GameRec &gameRecord, 
	  Piece *king,
	  Piece *leftRook,
	  Piece *rightRook )
{
	int x, y;
	int kingSquare = king->GetSquareNumber();
	// *** CASTLING LEFT *** //
	if( leftRook != NULL )
	{
		for( x = kingSquare - 1; x > leftRook->GetSquareNumber(); x-- )
			if( board.GetSquareContents( x ) != NULL )
				//	squares not open
				goto castleRight;
		for( x = kingSquare - 1; x > leftRook->GetSquareNumber(); x-- )
		{
			//	make sure square is not attacked
			if( board.IsSquareAttacked( x, FLIP(king->GetPlayerNumber()) ) )
				goto castleRight;
			//	push castling all moves with the king moving to square x
			for( y = x + 1; y <= kingSquare; y++ )
			{
				stack.BeginMoveAdd( FreeCastling, kingSquare, x, y );
				stack.AddPickUp( king->GetSquareNumber() );
				stack.AddPickUp( leftRook->GetSquareNumber() );
				stack.AddDrop( king, x );
				stack.AddDrop( leftRook, y );
				stack.EndMoveAdd( 1000 );
			}
		}
	}
	// *** CASTLING RIGHT *** //
castleRight:
	if( rightRook != NULL )
	{
		for( x = kingSquare + 1; x < rightRook->GetSquareNumber(); x++ )
			if( board.GetSquareContents( x ) != NULL )
				//	squares not open
				return;
		for( x = kingSquare + 1; x < rightRook->GetSquareNumber(); x++ )
		{
			//	make sure square is not attacked
			if( board.IsSquareAttacked( x, FLIP(king->GetPlayerNumber()) ) )
				return;
			//	push castling all moves with the king moving to square x
			for( y = x - 1; y >= kingSquare; y-- )
			{
				stack.BeginMoveAdd( FreeCastling, kingSquare, x, y );
				stack.AddPickUp( king->GetSquareNumber() );
				stack.AddPickUp( rightRook->GetSquareNumber() );
				stack.AddDrop( king, x );
				stack.AddDrop( rightRook, y );
				stack.EndMoveAdd( 1000 );
			}
		}
	}
}

void Game::AddFlexibleCastlingMoves
	( MovementList &stack,
	  GameRec &gameRecord, 
	  Piece *king,
	  Piece *leftRook,
	  Piece *rightRook )
{
	int kingSquare = king->GetSquareNumber();
	int x;

	// *** CASTLING LEFT *** //
	if( leftRook != NULL )
	{
		for( x = kingSquare - 1; x > leftRook->GetSquareNumber(); x-- )
			if( board.GetSquareContents( x ) != NULL )
				//	squares not open
				goto castleRight;
		for( x = kingSquare - 1; x > leftRook->GetSquareNumber(); x-- )
		{
			//	make sure square is not attacked
			if( board.IsSquareAttacked( x, FLIP(king->GetPlayerNumber()) ) )
				goto castleRight;
			if( x < kingSquare - 1 )
			{
				stack.BeginMoveAdd( FlexibleCastling, kingSquare, x );
				stack.AddPickUp( king->GetSquareNumber() );
				stack.AddPickUp( leftRook->GetSquareNumber() );
				stack.AddDrop( king, x );
				stack.AddDrop( leftRook, x + 1 );
				stack.EndMoveAdd( 1000 );
			}
		}
	}
	// *** CASTLING RIGHT *** //
castleRight:
	if( rightRook != NULL )
	{
		for( x = kingSquare + 1; x < rightRook->GetSquareNumber(); x++ )
			if( board.GetSquareContents( x ) != NULL )
				//	squares not open
				return;
		for( x = kingSquare + 1; x < rightRook->GetSquareNumber(); x++ )
		{
			//	make sure square is not attacked
			if( board.IsSquareAttacked( x, FLIP(king->GetPlayerNumber()) ) )
				return;
			//	push castling all moves with the king moving to square x
			if( x > kingSquare + 1 )
			{
				stack.BeginMoveAdd( FlexibleCastling, kingSquare, x );
				stack.AddPickUp( king->GetSquareNumber() );
				stack.AddPickUp( rightRook->GetSquareNumber() );
				stack.AddDrop( king, x );
				stack.AddDrop( rightRook, x - 1 );
				stack.EndMoveAdd( 1000 );
			}
		}
	}
}

void Game::AddPieceToSet
	( Piece *piece,
	  Piece *set[2][SET_SIZE],
	  int sizeOfSet )
{
	int cursor = 0;
	while( cursor < sizeOfSet && set[piece->GetPlayerNumber()][cursor] != NULL )
		cursor++;
	if( cursor < sizeOfSet )
		set[piece->GetPlayerNumber()][cursor] = piece;
}

void Game::RemovePieceFromSet
	( Piece *piece,
	  Piece *set[2][SET_SIZE],
	  int count )
{
	for( int x = 0; x < count; x++ )
	{
		if( set[0][x] == piece )
		{
			for( int y = x; y < count - 1; y++ )
				set[0][y] = set[0][y+1];
			set[0][count-1] = NULL;
		}
		if( set[1][x] == piece )
		{
			for( int y = x; y < count - 1; y++ )
				set[1][y] = set[1][y+1];
			set[1][count-1] = NULL;
		}
	}
}

word32 Game::AdjustPrimaryHash
	( word32 primaryHash )
{
	return primaryHash;
}

Phase &Game::AdjustEvaluation
	( int &eval,
	  PawnHash *pPawnHash )
{
	return phases[0];
}

bool Game::IsSquareAttacked
	( int squareNumber, 
	  int playerNumber )
{
	return board.IsSquareAttacked( squareNumber, playerNumber );
}

bool Game::TestForWinLossDraw
	( int &eval )
{
	if( board.GetMaterial( 0 ) + board.GetMaterial( 1 ) == 0 )
	{
		//	no pieces left; it's a draw
		eval = GetDrawScore();
		return true;
	}
	return false;
}

int Game::EnumeratePromotions
	( Piece *piece,
	  int fromSquare,
	  int toSquare,
	  PieceType **promotions,
	  bool quiescentSearch )
{
	int count = 0;
	for( int i = 0; i < board.GetPlayerPieceTypeCount( piece->GetPlayerNumber() ); i++ )
	{
		PieceType *pieceType = board.GetPlayerPieceTypes( piece->GetPlayerNumber() )[i];
		if( !pieceType->IsPawn() &&
			!pieceType->IsRoyal() )
		{
			promotions[count++] = pieceType;
		}
	}
	return count;
}

int Game::EnumeratePromotions
	( Piece *piece,
	  int fromSquare,
	  int toSquare,
	  Piece **promotions,
	  bool quiescentSearch )
{
	return 0;
}

void Game::GenerateCaptures
	( int currentPlayer, 
	  MovementList &list )
{
}

void Game::GenerateMoves
	( int currentPlayer, 
	  MovementList &list )
{
}

void Game::DescribeMove
	( Movement &movement,
	  char *description )
{
	int fromRank = board.ranks[0][movement.GetFromSquare()];
	int fromFile = board.files[0][movement.GetFromSquare()];
	int toRank;
	int toFile;

	if( movement.GetToSquare() >= 0 )
	{
		toRank = board.ranks[0][movement.GetToSquare()];
		toFile = board.files[0][movement.GetToSquare()];
	}

	if( !movement.IsValid() )
		description[0] = '\0';
	else if( movement.GetMoveType() == StandardCapture || 
		movement.GetMoveType() == CaptureWithReplacement || 
		movement.GetMoveType() == EnPassant )
	{
		sprintf( description, "%s%sx%s%s", 
			board.GetNameOfFile( fromFile ),
			board.GetNameOfRank( fromRank ),
			board.GetNameOfFile( toFile ),
			board.GetNameOfRank( toRank ) );
	}
	else if( movement.GetMoveType() == IguiCapture )
	{
		sprintf( description, "%s%s!%s%s", 
			board.GetNameOfFile( fromFile ),
			board.GetNameOfRank( fromRank ),
			board.GetNameOfFile( toFile ),
			board.GetNameOfRank( toRank ) );
	}
	else if( movement.GetMoveType() == Castling )
	{
		if( movement.GetTag() == 0 )
		{
			if( movement.GetFromSquare() < movement.GetToSquare() )
				strcpy( description, "O-O" );
			else
				strcpy( description, "O-O-O" );
		}
		else
		{
			if( movement.GetFromSquare() < movement.GetToSquare() )
				sprintf( description, "O-O(%s%s)", 
					board.GetNameOfFile( board.files[0][movement.GetTag()] ),
					board.GetNameOfRank( board.ranks[0][movement.GetTag()] ) );
			else
				sprintf( description, "O-O-O(%s%s)", 
					board.GetNameOfFile( movement.GetTag() ),
					board.GetNameOfRank( movement.GetTag() ) );
		}
	}
	else if( movement.GetMoveType() == SuicideMove )
	{
		sprintf( description, "!%s%s", 
			board.GetNameOfFile( fromFile ),
			board.GetNameOfRank( fromRank ) );
	}
	else
	{
		sprintf( description, "%s%s-%s%s", 
			board.GetNameOfFile( fromFile ),
			board.GetNameOfRank( fromRank ),
			board.GetNameOfFile( toFile ),
			board.GetNameOfRank( toRank ) );
	}
}

void Game::DescribeMove
	( MoveInfo &move,
	  char *queryDescription,
	  char *description,
	  char *notation )
{
	int fromRank = board.ranks[0][move.fromSquare];
	int fromFile = board.files[0][move.fromSquare];
	int toRank = board.ranks[0][move.toSquare];
	int toFile = board.files[0][move.toSquare];

	//	notation
	if( notation != NULL )
	{
		if( move.type == SuicideMove )
		{
			sprintf( notation, "!%s%s", board.GetNameOfFile( fromFile ),
				board.GetNameOfRank( fromRank ) );
		}
		else if( move.type == FreeCastling )
		{
			sprintf( description, "%s%s%s%s[%s%s]", 
				board.GetNameOfFile( fromFile ),
				board.GetNameOfRank( fromRank ),
				board.GetNameOfFile( toFile ),
				board.GetNameOfRank( toRank ),
				board.GetNameOfFile( board.files[0][move.tag] ),
				board.GetNameOfRank( board.ranks[0][move.tag] ) );
		}
		else
		{
			sprintf( notation, "%s%s%s%s", 
				board.GetNameOfFile( fromFile ),
				board.GetNameOfRank( fromRank ), 
				board.GetNameOfFile( toFile ), 
				board.GetNameOfRank( toRank ) );
		}
		if( move.promotion != NULL )
		{
			int len = (int) strlen( notation );
			notation[len++] = '=';
			strcpy( notation + len, move.promotion->GetNotation() );
		}
	}

	//	description
	if( description != NULL ||
		queryDescription != NULL )
	{
		if( description == NULL )
			description = queryDescription;

		if( move.type == StandardCapture ||
			move.type == CaptureWithReplacement )
		{
			sprintf( description, "%s %s%s x %s%s", 
				move.originalType->GetFullName(),
				board.GetNameOfFile( fromFile ),
				board.GetNameOfRank( fromRank ),
				board.GetNameOfFile( toFile ),
				board.GetNameOfRank( toRank ) );
		}
		else if( move.type == IguiCapture )
		{
			sprintf( description, "%s %s%s ! %s%s", 
				move.originalType->GetFullName(),
				board.GetNameOfFile( fromFile ),
				board.GetNameOfRank( fromRank ),
				board.GetNameOfFile( toFile ),
				board.GetNameOfRank( toRank ) );
		}
		else if( move.type == EnPassant )
		{
			sprintf( description, "%s %s%s x %s%s ep", 
				move.originalType->GetFullName(),
				board.GetNameOfFile( fromFile ),
				board.GetNameOfRank( fromRank ),
				board.GetNameOfFile( toFile ),
				board.GetNameOfRank( toRank ) );
		}
		else if( move.type == Castling )
		{
			if( move.fromSquare < move.toSquare )
				strcpy( description, "O - O" );
			else
				strcpy( description, "O - O - O" );
		}
		else if( move.type == FlexibleCastling )
		{
			if( move.fromSquare < move.toSquare )
				sprintf( description, "O - O, king to %s%s", 
					board.GetNameOfFile( toFile ),
					board.GetNameOfRank( toRank ) );
			else
				sprintf( description, "O - O - O, king to %s%s", 
					board.GetNameOfFile( toFile ),
					board.GetNameOfRank( toRank ) );
		}
		else if( move.type == FreeCastling )
		{
			if( move.fromSquare < move.toSquare )
				sprintf( description, "O - O, rook to %s%s",
					board.GetNameOfFile( board.files[0][move.tag] ),
					board.GetNameOfRank( board.ranks[0][move.tag] ) );
			else
				sprintf( description, "O - O - O, rook to %s%s",
					board.GetNameOfFile( board.files[0][move.tag] ),
					board.GetNameOfRank( board.ranks[0][move.tag] ) );
		}
		else if( move.type == SuicideMove )
		{
			sprintf( description, "%s %s%s suicide", 
				move.originalType->GetFullName(),
				board.GetNameOfFile( fromFile ),
				board.GetNameOfRank( fromRank ) );
		}
		else
		{
			sprintf( description, "%s %s%s - %s%s", 
				move.originalType->GetFullName(),
				board.GetNameOfFile( fromFile ),
				board.GetNameOfRank( fromRank ),
				board.GetNameOfFile( toFile ),
				board.GetNameOfRank( toRank ) );
		}
		if( move.promotion != NULL )
		{
			int len = (int) strlen( description );
			description[len++] = ' ';
			description[len++] = '=';
			description[len++] = ' ';
			strcpy( description + len, move.promotion->GetFullName() );
		}
	}

	//	query description
	if( description != NULL && 
		queryDescription != NULL &&
		description != queryDescription )
	{
		strcpy( queryDescription, description );
	}
}

int Game::TranslateMove
	( MovementList &list,
	  char *notation )
{
	int fromSquare;
	int toSquare;
	int cursor = 0;

	int fromFile;
	int fromRank;
	int toFile;
	int toRank;

	//	parse the file where the move starts
	fromFile = board.GetFileByCharPair( notation[cursor], notation[cursor+1] );
	if( fromFile == -1 )
	{
		fromFile = board.GetFileByChar( notation[cursor] );
		if( fromFile == -1 )
			//	error in move notation
			return -1;
		cursor++;
	}
	else
	{
		cursor += 2;
	}
	//	parse the rank where the move starts
	fromRank = board.GetRankByCharPair( notation[cursor], notation[cursor+1] );
	if( fromRank == -1 )
	{
		fromRank = board.GetRankByChar( notation[cursor] );
		if( fromRank == -1 )
			//	error in move notation
			return -1;
		cursor++;
	}
	else
	{
		cursor += 2;
	}
	//	parse the file where the move ends
	toFile = board.GetFileByCharPair( notation[cursor], notation[cursor+1] );
	if( toFile == -1 )
	{
		toFile = board.GetFileByChar( notation[cursor] );
		if( toFile == -1 )
			//	error in move notation
			return -1;
		cursor++;
	}
	else
	{
		cursor += 2;
	}
	//	parse the rank where the move ends
	toRank = board.GetRankByCharPair( notation[cursor], notation[cursor+1] );
	if( toRank == -1 )
	{
		toRank = board.GetRankByChar( notation[cursor] );
		if( toRank == -1 )
			//	error in move notation
			return -1;
		cursor++;
	}
	else
	{
		cursor += 2;
	}

	//	calculate the numbers of the start and end squares
	fromSquare = fromRank * board.GetNumberOfFiles() + fromFile;
	toSquare = toRank * board.GetNumberOfFiles() + toFile;

	//	look up the move
	char *promotionType = NULL;
	if( notation[cursor] == '=' )
		promotionType = notation + cursor + 1;
	for( int x = 0; x < list.GetCount(); x++ )
	{
		MoveInfo &move = list.GetMove( x );
		if( move.fromSquare == fromSquare &&
			move.toSquare == toSquare )
		{
			if( move.promotion == NULL && promotionType == NULL )
				return x;
			else if( promotionType != NULL )
			{
				bool matched = true;
				for( int y = 0; y < (int) strlen(move.promotion->GetNotation()) && 
					y < (int) strlen(promotionType) && matched; y++ )
					if( move.promotion->GetNotation()[y] != promotionType[y] )
						matched = false;
				if( matched )
					return x;
			}
		}
	}

	//	move not found
	return -1;
}

void Game::SaveGame
	( HANDLE fileHandle )
{
	DWORD bytesWritten;
	char buffer[1200] = "\0";
	int cursor;
	int x, y;

	//	write out the name of this game / variant
	if( selectedVariant->baseGameName != NULL )
		sprintf( buffer, "%s:%s\r\n", selectedVariant->name, selectedVariant->baseGameName );
	else
	{
		if( (int) strlen( newVariantName ) > 0 )
			sprintf( buffer, "%s:%s\r\n", newVariantName, selectedVariant->name );
		else
			sprintf( buffer, "%s\r\n", selectedVariant->name );
	}
	::WriteFile( fileHandle, buffer, (DWORD) strlen(buffer), &bytesWritten, NULL );

	//	write out all game parameters
	for( int i = 0; i < nGameParameters; i++ )
	{
		GameParameter &param = gameParameters[i];
		switch( param.type )
		{
		  case int_Parameter:
			sprintf( buffer, "#%s = %d\r\n", param.parameterName, param.parameterValue.intValue );
			break;
		  case bool_Parameter:
			sprintf( buffer, "?%s = %s\r\n", param.parameterName, (param.parameterValue.boolValue ? "true" : "false") );
			break;
		  case string_Parameter:
			sprintf( buffer, "$%s = \"%s\"\r\n", param.parameterName, param.parameterValue.pCharValue );
			break;
		}
		::WriteFile( fileHandle, buffer, (DWORD) strlen(buffer), &bytesWritten, NULL );
	}

	//	write out all function calls
	for( x = 0; x < nFunctionCalls; x++ )
	{
		FunctionCall *call = &(functionCalls[x]);
		FunctionDecl *fn = call->pFunctionDecl;
		sprintf( buffer, "%s(", call->pFunctionDecl->name );
		for( y = 0; y < call->pFunctionDecl->nArgs - 1; y++ )
		{
			cursor = (int) strlen( buffer );
			if( call->pFunctionDecl->argType[y] == FN_ARG_TYPE__INTEGER )
				sprintf( buffer + cursor, " %d,", call->args[y].integerArg );
			else if( call->pFunctionDecl->argType[y] == FN_ARG_TYPE__STRING )
				sprintf( buffer + cursor, " \"%s\",", call->args[y].stringArg );
			else if( call->pFunctionDecl->argType[y] == FN_ARG_TYPE__BOOLEAN )
				if( call->args[y].booleanArg )
					sprintf( buffer + cursor, " true," );
				else
					sprintf( buffer + cursor, " false," );
		}
		cursor = (int) strlen( buffer );
		if( call->pFunctionDecl->nArgs > 0 )
		{
			buffer[cursor++] = ' ';
			if( call->pFunctionDecl->argType[y] == FN_ARG_TYPE__INTEGER )
				sprintf( buffer + cursor, " %d )", call->args[y].integerArg );
			else if( call->pFunctionDecl->argType[y] == FN_ARG_TYPE__STRING )
				sprintf( buffer + cursor, " \"%s\" )", call->args[y].stringArg );
			else if( call->pFunctionDecl->argType[y] == FN_ARG_TYPE__BOOLEAN )
				if( call->args[y].booleanArg )
					sprintf( buffer + cursor, " true )" );
				else
					sprintf( buffer + cursor, " false )" );
		}
		else
		{
			buffer[cursor++] = ')';
		}
		cursor = (int) strlen( buffer );
		sprintf( buffer + cursor, "\r\n" );
		::WriteFile( fileHandle, buffer, (DWORD) strlen(buffer), &bytesWritten, NULL );
	}

	//	write out moves
	cursor = 0;
	buffer[cursor++] = '{';
	buffer[cursor++] = ' ';
	for( int j = 0; j < board.historicalMoves.GetCount(); j++ )
	{
		MoveInfo &move = board.historicalMoves.GetMove( j );
		DescribeMove( move, NULL, NULL, buffer + cursor );
		cursor = (int) strlen( buffer );
		buffer[cursor++] = ' ';
	}
	buffer[cursor++] = '}';
	buffer[cursor++] = '\r';
	buffer[cursor++] = '\n';
	::WriteFile( fileHandle, buffer, cursor, &bytesWritten, NULL );

	//	close the file
	::CloseHandle( fileHandle );
}

void Game::GameLoaded()
{
}

void Game::DefaultSettings()
{
	squareColor1 = RGB(255, 255, 204);
	squareColor2 = RGB(93, 126, 126);
	pieceColor1 = RGB(255, 255, 255);
	pieceColor2 = RGB(89, 132, 189);
	borderColor = RGB(128, 70, 70);
	boardDisplayType = BOARD_IS_CHECKERED;
	selectedPieceSet = PIECE_SET_STANDARD;
}

void Game::AboutToStartThinking
	( int currentPlayer )
{
}

void Game::AboutToDeepenSearch
	( int currentPlayer )
{
}

void Game::AboutToGenerateMoves
	( int currentPlayer, 
	  int currentDepth )
{
}

bool Game::IsInCheck
	( Piece *king )
{
	specialCheckTesting = false;
	bool inCheck = board.IsInCheck();
	specialCheckTesting = true;
	return inCheck;
}

void Game::AddPlayerPieceTypes( char *gameName )
{
}

int Game::PenalizePiecesForMovingMultipleTimes()
{
	int eval = 0;
	int factor = MAX(board.GetCurrentGameRecord().gameInt1 - 10, 0);
	int factor6 = 640 - (factor << 6);
	int factor5 = 320 - (factor << 5);

	//	give a penalty for pieces for moving twice, 
	//	and a larger penalty for pieces moving three times
	for( int i = 0; i < board.GetNumberOfPieces( 0 ); i++ )
	{
		Piece *piece = board.GetPiece( 0, i );
		if( !piece->IsCaptured() )
		{
			if( !piece->GetType().IsRoyal() )
			{
				switch( piece->GetFlags() & FLAGS_HAS_MOVED_MASK ) 
				{
				case FLAGS_HAS_MOVED | FLAGS_HAS_MOVED_TWICE:
					eval -= factor5;
					break;
				case FLAGS_HAS_MOVED | FLAGS_HAS_MOVED_TWICE | FLAGS_HAS_MOVED_THREE_TIMES:
					eval -= factor6;
					break;
				default:
					break;
				}
			}
		}
	}
	for( int i = 0; i < board.GetNumberOfPieces( 1 ); i++ )
	{
		Piece *piece = board.GetPiece( 1, i );
		if( !piece->IsCaptured() )
		{
			if( !piece->GetType().IsRoyal() )
			{
				switch( piece->GetFlags() & FLAGS_HAS_MOVED_MASK ) 
				{
				case FLAGS_HAS_MOVED | FLAGS_HAS_MOVED_TWICE:
					eval += factor5;
					break;
				case FLAGS_HAS_MOVED | FLAGS_HAS_MOVED_TWICE | FLAGS_HAS_MOVED_THREE_TIMES:
					eval += factor6;
					break;
				default:
					break;
				}
			}
		}
	}
	return eval;
}

void Game::GenerateMovesForCoordinator
	( Piece *piece,
	  Piece *king,
	  MovementList &stack, 
	  GameRec &gameRecord, 
	  bool quiescentSearch )
{
	for( int y = 0; y < 8; y++ )
	{
		int nSquare = piece->GetSquareNumber();
		int player = piece->GetPlayerNumber();
		bool hitObstacle = false;
		int *movementMatrix = player == 0 ? board.GetMovementMatrix( y ) :
			board.GetOppositeMovementMatrix( y );

		nSquare = movementMatrix[nSquare];

		if( nSquare >= 0 )
		{
			Piece *pieceOnSquare = board.GetSquareContents( nSquare );

			if( pieceOnSquare == NULL )
			{
				int square1 = board.ranks[0][nSquare] * board.GetNumberOfFiles() + 
								board.files[0][king->GetSquareNumber()];
				int square2 = board.ranks[0][king->GetSquareNumber()] * board.GetNumberOfFiles() + 
								board.files[0][nSquare];
				if( (board.GetSquareContents( square1 ) == NULL || 
						board.GetSquareContents( square1 )->GetPlayerNumber() == player) && 
					(board.GetSquareContents( square2 ) == NULL || 
						board.GetSquareContents( square2 )->GetPlayerNumber() == player) )
				{
					//	perfectly normal move
					if( !quiescentSearch )
						stack.AddMove( piece->GetSquareNumber(), nSquare );
				}
				else
				{
					stack.BeginMoveAdd( UserMove1, piece->GetSquareNumber(), nSquare );
					stack.AddPickUp( piece->GetSquareNumber() );
					if( board.GetSquareContents( square1 ) != NULL && 
						board.GetSquareContents( square1 )->GetPlayerNumber() != player )
						stack.AddPickUp( square1 );
					if( board.GetSquareContents( square2 ) != NULL && 
						board.GetSquareContents( square2 )->GetPlayerNumber() != player )
						stack.AddPickUp( square2 );
					stack.AddDrop( piece, nSquare );
					stack.EndMoveAdd( 1000 );
				}
			}
			else if( pieceOnSquare != NULL )
			{
				hitObstacle = true;
			}
		}
		else
			//	edge of board; we're done
			hitObstacle = true;

		//	keep "stepping" in this direction as long as we can
		for( int j = 2; !hitObstacle; j++ )
		{
			//	find new rank and file
			nSquare = movementMatrix[nSquare];

			//	are we still on the board?
			if( nSquare >= 0 )
			{
				Piece *pieceOnSquare = board.GetSquareContents( nSquare );

				if( pieceOnSquare == NULL )
				{
					int square1 = board.ranks[0][nSquare] * board.GetNumberOfFiles() + 
								board.files[0][king->GetSquareNumber()];
					int square2 = board.ranks[0][king->GetSquareNumber()] * board.GetNumberOfFiles() + 
								board.files[0][nSquare];
					if( (board.GetSquareContents( square1 ) == NULL || 
							board.GetSquareContents( square1 )->GetPlayerNumber() == player) && 
						(board.GetSquareContents( square2 ) == NULL || 
							board.GetSquareContents( square2 )->GetPlayerNumber() == player) )
					{
						//	perfectly normal move
						if( !quiescentSearch )
							stack.AddMove( piece->GetSquareNumber(), nSquare );
					}
					else
					{
						stack.BeginMoveAdd( UserMove1, piece->GetSquareNumber(), nSquare );
						stack.AddPickUp( piece->GetSquareNumber() );
						if( board.GetSquareContents( square1 ) != NULL && 
							board.GetSquareContents( square1 )->GetPlayerNumber() != player )
							stack.AddPickUp( square1 );
						if( board.GetSquareContents( square2 ) != NULL && 
							board.GetSquareContents( square2 )->GetPlayerNumber() != player )
							stack.AddPickUp( square2 );
						stack.AddDrop( piece, nSquare );
						stack.EndMoveAdd( 1000 );
					}
				}
				else if( pieceOnSquare != NULL )
				{
					//	hit an obsticle; we're done moving in this direction
					hitObstacle = true;
				}
			}
			else
				//	edge of board; we're done
				hitObstacle = true;
		}
	}
}

void Game::GenerateMovesForLongLeaper
	( Piece *piece,
	  MovementList &stack, 
	  GameRec &gameRecord, 
	  bool quiescentSearch )
{
	int player = board.GetCurrentPlayerNumber();
	int captureSquares[6];
	int nCaptures;

	for( int y = 0; y < 8; y++ )
	{
		int nSquare = piece->GetSquareNumber();
		bool hitObstacle = false;
		nCaptures = 0;
		int *movementMatrix = player == 0 ? board.GetMovementMatrix( y ) :
			board.GetOppositeMovementMatrix( y );

		nSquare = movementMatrix[nSquare];

		if( nSquare >= 0 )
		{
			Piece *pieceOnSquare = board.GetSquareContents( nSquare );

			if( pieceOnSquare == NULL )
			{
				if( !quiescentSearch )
					stack.AddMove( piece->GetSquareNumber(), nSquare );
			}
			else
			{
				if( pieceOnSquare->GetPlayerNumber() == piece->GetPlayerNumber() )
					//	cannot jump a friendly piece
					hitObstacle = true;
				else
					//	take a peek and see if we have a landing square
					if( movementMatrix[nSquare] != -1 &&
						board.GetSquareContents( movementMatrix[nSquare] ) == NULL )
						//	we have a landing square so add to captures
						captureSquares[nCaptures++] = nSquare;
					else
						//	can't jump two adjacent pieces
						hitObstacle = true;
			}
		}
		else
			//	edge of board; we're done
			hitObstacle = true;

		//	keep "stepping" in this direction as long as we can
		for( int j = 2; !hitObstacle; j++ )
		{
			//	find new rank and file
			nSquare = movementMatrix[nSquare];

			//	are we still on the board?
			if( nSquare >= 0 )
			{
				Piece *pieceOnSquare = board.GetSquareContents( nSquare );

				if( pieceOnSquare == NULL )
				{
					if( nCaptures == 0 )
					{
						if( !quiescentSearch )
							stack.AddMove( piece->GetSquareNumber(), nSquare );
					}
					else
					{
						stack.BeginMoveAdd( UserMove1, piece->GetSquareNumber(), nSquare );
						stack.AddPickUp( piece->GetSquareNumber() );
						int captureValue = 0;
						for( int k = 0; k < nCaptures; k++ )
						{
							stack.AddPickUp( captureSquares[k] );
							captureValue += board.GetSquareContents( captureSquares[k] )->GetBaseValue();
						}
						stack.AddDrop( piece, nSquare );
						stack.EndMoveAdd( captureValue + 600 );
					}
				}
				else if( pieceOnSquare != NULL )
				{
					if( pieceOnSquare->GetPlayerNumber() == piece->GetPlayerNumber() )
						//	can't jump a friendly piece
						hitObstacle = true;
					else
						//	take a peek and see if we have a landing square
						if( movementMatrix[nSquare] != -1 && 
							board.GetSquareContents( movementMatrix[nSquare] ) == NULL )
							//	we have a landing square so add to captures
							captureSquares[nCaptures++] = nSquare;
						else
							//	can't jump two adjacent pieces
							hitObstacle = true;
				}
			}
			else
				//	edge of board; we're done
				hitObstacle = true;
		}
	}
}

void Game::GenerateMovesForChameleon
	( Piece *piece,
	  Piece *king,
	  MovementList &stack, 
	  GameRec &gameRecord, 
	  bool quiescentSearch )
{
	int player = board.GetCurrentPlayerNumber();
	int leapingCaptureSquares[6];
	int nLeapingCaptures;
	int otherCaptureSquares[12];
	int nOtherCaptures;

	for( int y = 0; y < 8; y++ )
	{
		int nSquare = piece->GetSquareNumber();
		bool hitObstacle = false;
		nLeapingCaptures = 0;
		int *movementMatrix = player == 0 ? board.GetMovementMatrix( y ) :
			board.GetOppositeMovementMatrix( y );
		int *oppositeMovementMatrix = player == 1 ? board.GetMovementMatrix( y ) :
			board.GetOppositeMovementMatrix( y );
		int nOppositeSquare = oppositeMovementMatrix[nSquare];

		//	check in the opposite direction of movement to see if it contains 
		//	a Withdrawer.  if it does, we capture it ...
		Piece *withdrawCapture = NULL;
		if( nOppositeSquare != -1 && 
			board.GetSquareContents( nOppositeSquare ) != NULL && 
			&(board.GetSquareContents( nOppositeSquare )->GetType()) == &Withdrawer::withdrawer &&
			board.GetSquareContents( nOppositeSquare )->GetPlayerNumber() != piece->GetPlayerNumber() )
			//	withdraw capture this piece
			withdrawCapture = board.GetSquareContents( nOppositeSquare );

		//	take first "step"
		nSquare = movementMatrix[nSquare];
		if( nSquare >= 0 )
		{
			nOtherCaptures = 0;
			Piece *pieceOnSquare = board.GetSquareContents( nSquare );

			if( pieceOnSquare == NULL )
			{
				//	check for coordination capture
				int square1 = board.ranks[0][nSquare] * board.GetNumberOfFiles() + 
								board.files[0][king->GetSquareNumber()];
				int square2 = board.ranks[0][king->GetSquareNumber()] * board.GetNumberOfFiles() + 
								board.files[0][nSquare];
				if( board.GetSquareContents( square1 ) != NULL && 
					board.GetSquareContents( square1 )->GetPlayerNumber() != player && 
					&(board.GetSquareContents( square1 )->GetType()) == &Coordinator::coordinator )
					//	capture this piece by coordination
					otherCaptureSquares[nOtherCaptures++] = square1;
				if( board.GetSquareContents( square2 ) != NULL && 
					board.GetSquareContents( square2 )->GetPlayerNumber() != player && 
					&(board.GetSquareContents( square2 )->GetType()) == &Coordinator::coordinator )
					//	capture this piece by coordination
					otherCaptureSquares[nOtherCaptures++] = square2;
				
				if( y == DIRECTION_N || y == DIRECTION_S || y == DIRECTION_E || y == DIRECTION_W )
				{
					//	check for capture of pincer pawns by "pinching"
					for( int x = 0; x < 4; x++ )
					{
						int *newMovementMatrix = board.GetMovementMatrix( orthogonalDirections[x] );
						if( newMovementMatrix[nSquare] != -1 && 
							board.GetSquareContents( newMovementMatrix[nSquare] ) != NULL && 
							board.GetSquareContents( newMovementMatrix[nSquare] )->GetPlayerNumber() != player && 
							&(board.GetSquareContents( newMovementMatrix[nSquare] )->GetType()) == &UltimaPawn::ultimaPawn && 
							newMovementMatrix[newMovementMatrix[nSquare]] != -1 && 
							board.GetSquareContents( newMovementMatrix[newMovementMatrix[nSquare]] ) != NULL && 
							board.GetSquareContents( newMovementMatrix[newMovementMatrix[nSquare]] )->GetPlayerNumber() == player )
							//	this pawn is captured
							otherCaptureSquares[nOtherCaptures++] = newMovementMatrix[nSquare];
					}
				}

				if( withdrawCapture == NULL && nOtherCaptures == 0 )
				{
					if( !quiescentSearch )
						stack.AddMove( piece->GetSquareNumber(), nSquare );
				}
				else
				{
					stack.BeginMoveAdd( UserMove1, piece->GetSquareNumber(), nSquare );
					stack.AddPickUp( piece->GetSquareNumber() );
					int captureValue = 0;
					if( withdrawCapture != NULL )
					{
						stack.AddPickUp( withdrawCapture->GetSquareNumber() );
						captureValue += withdrawCapture->GetBaseValue();
					}
					for( int k = 0; k < nOtherCaptures; k++ )
					{
						stack.AddPickUp( otherCaptureSquares[k] );
						captureValue += board.GetSquareContents( otherCaptureSquares[k] )->GetBaseValue();
					}
					stack.AddDrop( piece, nSquare );
					stack.EndMoveAdd( captureValue + 600 );
				}
			}
			else
			{
				if( pieceOnSquare->GetPlayerNumber() == piece->GetPlayerNumber() || 
					&(pieceOnSquare->GetType()) != &LongLeaper::longLeaper )
					//	cannot jump a friendly piece, or any piece other than a Long Leaper
					hitObstacle = true;
				else
					//	take a peek and see if we have a landing square
					if( movementMatrix[nSquare] != -1 &&
						board.GetSquareContents( movementMatrix[nSquare] ) == NULL )
						//	we have a landing square so add to captures
						leapingCaptureSquares[nLeapingCaptures++] = nSquare;
					else
						//	can't jump two adjacent pieces
						hitObstacle = true;
			}
		}
		else
			//	edge of board; we're done
			hitObstacle = true;

		//	keep "stepping" in this direction as long as we can
		for( int j = 2; !hitObstacle; j++ )
		{
			//	find new rank and file
			nSquare = movementMatrix[nSquare];

			//	are we still on the board?
			if( nSquare >= 0 )
			{
				nOtherCaptures = 0;
				Piece *pieceOnSquare = board.GetSquareContents( nSquare );

				if( pieceOnSquare == NULL )
				{
					//	check for coordination capture
					int square1 = board.ranks[0][nSquare] * board.GetNumberOfFiles() + 
									board.files[0][king->GetSquareNumber()];
					int square2 = board.ranks[0][king->GetSquareNumber()] * board.GetNumberOfFiles() + 
									board.files[0][nSquare];
					if( board.GetSquareContents( square1 ) != NULL && 
						board.GetSquareContents( square1 )->GetPlayerNumber() != player && 
						&(board.GetSquareContents( square1 )->GetType()) == &Coordinator::coordinator )
						//	capture this piece by coordination
						otherCaptureSquares[nOtherCaptures++] = square1;
					if( board.GetSquareContents( square2 ) != NULL && 
						board.GetSquareContents( square2 )->GetPlayerNumber() != player && 
						&(board.GetSquareContents( square2 )->GetType()) == &Coordinator::coordinator )
						//	capture this piece by coordination
						otherCaptureSquares[nOtherCaptures++] = square2;
					
					if( y == DIRECTION_N || y == DIRECTION_S || y == DIRECTION_E || y == DIRECTION_W )
					{
						//	check for capture of pincer pawns by "pinching"
						for( int x = 0; x < 4; x++ )
						{
							int *newMovementMatrix = board.GetMovementMatrix( orthogonalDirections[x] );
							if( newMovementMatrix[nSquare] != -1 && 
								board.GetSquareContents( newMovementMatrix[nSquare] ) != NULL && 
								board.GetSquareContents( newMovementMatrix[nSquare] )->GetPlayerNumber() != player && 
								&(board.GetSquareContents( newMovementMatrix[nSquare] )->GetType()) == &UltimaPawn::ultimaPawn && 
								newMovementMatrix[newMovementMatrix[nSquare]] != -1 && 
								board.GetSquareContents( newMovementMatrix[newMovementMatrix[nSquare]] ) != NULL && 
								board.GetSquareContents( newMovementMatrix[newMovementMatrix[nSquare]] )->GetPlayerNumber() == player )
								//	this pawn is captured
								otherCaptureSquares[nOtherCaptures++] = newMovementMatrix[nSquare];
						}
					}

					if( withdrawCapture == NULL && nLeapingCaptures == 0 && nOtherCaptures == 0 )
					{
						if( !quiescentSearch )
							stack.AddMove( piece->GetSquareNumber(), nSquare );
					}
					else
					{
						stack.BeginMoveAdd( UserMove1, piece->GetSquareNumber(), nSquare );
						stack.AddPickUp( piece->GetSquareNumber() );
						int captureValue = 0;
						if( withdrawCapture != NULL )
						{
							stack.AddPickUp( withdrawCapture->GetSquareNumber() );
							captureValue += withdrawCapture->GetBaseValue();
						}
						for( int j = 0; j < nLeapingCaptures; j++ )
						{
							stack.AddPickUp( leapingCaptureSquares[j] );
							captureValue += board.GetSquareContents( leapingCaptureSquares[j] )->GetBaseValue();
						}
						for( int k = 0; k < nOtherCaptures; k++ )
						{
							stack.AddPickUp( otherCaptureSquares[k] );
							captureValue += board.GetSquareContents( otherCaptureSquares[k] )->GetBaseValue();
						}
						stack.AddDrop( piece, nSquare );
						stack.EndMoveAdd( captureValue + 600 );
					}
				}
				else if( pieceOnSquare != NULL )
				{
					if( pieceOnSquare->GetPlayerNumber() == piece->GetPlayerNumber() || 
						&(pieceOnSquare->GetType()) != &LongLeaper::longLeaper )
						//	cannot jump a friendly piece, or any piece other than a Long Leaper
						hitObstacle = true;
					else
						//	take a peek and see if we have a landing square
						if( movementMatrix[nSquare] != -1 && 
							board.GetSquareContents( movementMatrix[nSquare] ) == NULL )
							//	we have a landing square so add to captures
							leapingCaptureSquares[nLeapingCaptures++] = nSquare;
						else
							//	can't jump two adjacent pieces
							hitObstacle = true;
				}
			}
			else
				//	edge of board; we're done
				hitObstacle = true;
		}
	}
}

void Game::GenerateMovesForUltimaPawn
	( Piece *piece,
	  MovementList &stack, 
	  GameRec &gameRecord, 
	  bool quiescentSearch )
{
	for( int x = 0; x < 4; x++ )
	{
		int nSquare = piece->GetSquareNumber();
		int player = piece->GetPlayerNumber();
		bool hitObstacle = false;
		int *movementMatrix = board.GetMovementMatrix( orthogonalDirections[x] );

		nSquare = movementMatrix[nSquare];

		if( nSquare >= 0 )
		{
			Piece *pieceOnSquare = board.GetSquareContents( nSquare );

			if( pieceOnSquare == NULL )
			{
				//	check for capture of pincer pawns by "pinching"
				int captureSquares[4];
				int nCaptures = 0;
				for( int y = 0; y < 4; y++ )
				{
					int *newMovementMatrix = board.GetMovementMatrix( orthogonalDirections[y] );
					if( newMovementMatrix[nSquare] != -1 && 
						board.GetSquareContents( newMovementMatrix[nSquare] ) != NULL && 
						board.GetSquareContents( newMovementMatrix[nSquare] )->GetPlayerNumber() != player && 
						newMovementMatrix[newMovementMatrix[nSquare]] != -1 && 
						board.GetSquareContents( newMovementMatrix[newMovementMatrix[nSquare]] ) != NULL && 
						board.GetSquareContents( newMovementMatrix[newMovementMatrix[nSquare]] )->GetPlayerNumber() == player )
						//	this pawn is captured
						captureSquares[nCaptures++] = newMovementMatrix[nSquare];
				}
				if( nCaptures == 0 )
				{
					if( !quiescentSearch )
						stack.AddMove( piece->GetSquareNumber(), nSquare );
				}
				else
				{
					stack.BeginMoveAdd( UserMove1, piece->GetSquareNumber(), nSquare );
					stack.AddPickUp( piece->GetSquareNumber() );
					int captureValue = 0;
					for( int k = 0; k < nCaptures; k++ )
					{
						stack.AddPickUp( captureSquares[k] );
						captureValue += board.GetSquareContents( captureSquares[k] )->GetBaseValue();
					}
					stack.AddDrop( piece, nSquare );
					stack.EndMoveAdd( captureValue + 600 );
				}
			}
			else if( pieceOnSquare != NULL )
			{
				hitObstacle = true;
			}
		}
		else
			//	edge of board; we're done
			hitObstacle = true;

		//	keep "stepping" in this direction as long as we can
		for( int j = 2; !hitObstacle; j++ )
		{
			//	find new rank and file
			nSquare = movementMatrix[nSquare];

			//	are we still on the board?
			if( nSquare >= 0 )
			{
				Piece *pieceOnSquare = board.GetSquareContents( nSquare );

				if( pieceOnSquare == NULL )
				{
					//	check for capture of pincer pawns by "pinching"
					int captureSquares[4];
					int nCaptures = 0;
					for( int y = 0; y < 4; y++ )
					{
						int *newMovementMatrix = board.GetMovementMatrix( orthogonalDirections[y] );
						if( newMovementMatrix[nSquare] != -1 && 
							board.GetSquareContents( newMovementMatrix[nSquare] ) != NULL && 
							board.GetSquareContents( newMovementMatrix[nSquare] )->GetPlayerNumber() != player && 
							newMovementMatrix[newMovementMatrix[nSquare]] != -1 && 
							board.GetSquareContents( newMovementMatrix[newMovementMatrix[nSquare]] ) != NULL && 
							board.GetSquareContents( newMovementMatrix[newMovementMatrix[nSquare]] )->GetPlayerNumber() == player )
							//	this pawn is captured
							captureSquares[nCaptures++] = newMovementMatrix[nSquare];
					}
					if( nCaptures == 0 )
					{
						if( !quiescentSearch )
							stack.AddMove( piece->GetSquareNumber(), nSquare );
					}
					else
					{
						stack.BeginMoveAdd( UserMove1, piece->GetSquareNumber(), nSquare );
						stack.AddPickUp( piece->GetSquareNumber() );
						int captureValue = 0;
						for( int k = 0; k < nCaptures; k++ )
						{
							stack.AddPickUp( captureSquares[k] );
							captureValue += board.GetSquareContents( captureSquares[k] )->GetBaseValue();
						}
						stack.AddDrop( piece, nSquare );
						stack.EndMoveAdd( captureValue + 600 );
					}
				}
				else if( pieceOnSquare != NULL )
				{
					//	hit an obsticle; we're done moving in this direction
					hitObstacle = true;
				}
			}
			else
				//	edge of board; we're done
				hitObstacle = true;
		}
	}
}

void Game::GenerateMovesForSwapper
	( Piece *piece,
	  MovementList &stack, 
	  GameRec &gameRecord, 
	  bool quiescentSearch )
{
	for( int x = 0; x < 8; x++ )
	{
		int nSquare = piece->GetSquareNumber();
		int player = piece->GetPlayerNumber();
		int *movementMatrix = board.GetMovementMatrix( x );

		nSquare = movementMatrix[nSquare];

		if( nSquare >= 0 )
		{
			Piece *pieceOnSquare = board.GetSquareContents( nSquare );

			if( pieceOnSquare == NULL )
			{
				if( !quiescentSearch )
					stack.AddMove( piece->GetSquareNumber(), nSquare );
				nSquare = movementMatrix[nSquare];
			}
			else
			{
				// *** SWAP MOVE *** //
				stack.BeginMoveAdd( Swap, piece->GetSquareNumber(), nSquare );
				stack.AddPickUp( piece->GetSquareNumber() );
				stack.AddPickUp( nSquare );
				stack.AddDrop( piece, nSquare );
				stack.AddDrop( pieceOnSquare, piece->GetSquareNumber() );
				stack.EndMoveAdd( 0 );

				// *** MUTUAL DESTRUCTION *** //
				if( pieceOnSquare->GetPlayerNumber() != player )
				{
					stack.BeginMoveAdd( MutualDestruction, piece->GetSquareNumber(), nSquare );
					stack.AddPickUp( piece->GetSquareNumber() );
					stack.AddPickUp( nSquare );
					stack.EndMoveAdd( -5000 );
				}
				nSquare = -1;
			}
		}

		while( nSquare >= 0 )
		{
			Piece *pieceOnSquare = board.GetSquareContents( nSquare );

			if( pieceOnSquare == NULL )
			{
				if( !quiescentSearch )
					stack.AddMove( piece->GetSquareNumber(), nSquare );
				nSquare = movementMatrix[nSquare];
			}
			else
			{
				// *** SWAP MOVE *** //
				stack.BeginMoveAdd( Swap, piece->GetSquareNumber(), nSquare );
				stack.AddPickUp( piece->GetSquareNumber() );
				stack.AddPickUp( nSquare );
				stack.AddDrop( piece, nSquare );
				stack.AddDrop( pieceOnSquare, piece->GetSquareNumber() );
				stack.EndMoveAdd( 0 );
				nSquare = -1;
			}
		}
	}
}

void Game::GenerateMovesForCannon
	( int square,
	  int currentPlayer,
	  MovementList &list,
	  GameRec &gameRecord,
	  bool quiescentSearch,
	  int direction )
{
	int *matrix = board.GetMovementMatrix( direction );
	int current = matrix[square];
	bool screened = false;
	while( current != -1 && !screened )
	{
		if( board.GetSquareContents( current ) == NULL )
		{
			if( !quiescentSearch )
				list.AddMove( square, current );
		}
		else
			screened = true;
		current = matrix[current];
	}
	while( current != -1 )
	{
		if( board.GetSquareContents( current ) != NULL )
		{
            if( board.GetSquareContents( current )->GetPlayerNumber() != currentPlayer )
				list.AddCapture( square, current );
			current = -1;
		}
		else
			current = matrix[current];
	}
}
