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

                                 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 "ChessGame.h"
#include "../../ChessV.h"
#include "../../PieceType.h"
#include "../../Piece.h"
#include "../../Direction.h"
#include "../../Rand.h"
#include "../../GameParameters.h"


#include "Chess_Data.h"
//	this include file contains data matricies for square bonuses,
//	outpost bonuses, etc.  it also contains some macros used here.


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


char *GetArrayForFRCByPositionNumber( int position );
char *GetArrayForChess256ByPositionNumber( int position );


void StartChessGame()
{
	if( (selectedVariant->baseGameName != NULL && 
		stringCompNoCase( selectedVariant->baseGameName, "Fischer Random Chess" )) || 
		stringCompNoCase( selectedVariant->name, "Fischer Random Chess" ) )
	{
		if( !justLoaded )
		{
			::DialogBox( theInstance, MAKEINTRESOURCE(IDD_FRC_DIALOG), NULL, 
				reinterpret_cast<DLGPROC>(FRC_SelectDlgProc) );
		}
	}
	else if( (selectedVariant->baseGameName != NULL && 
		stringCompNoCase( selectedVariant->baseGameName, "Chess 480" )) || 
		stringCompNoCase( selectedVariant->name, "Chess 480" ) )
	{
		if( !justLoaded )
		{
			::DialogBox( theInstance, MAKEINTRESOURCE(IDD_CHESS480_DIALOG), NULL, 
				reinterpret_cast<DLGPROC>(FRC_SelectDlgProc) );
		}
	}
	else if( (selectedVariant->baseGameName != NULL && 
		stringCompNoCase( selectedVariant->baseGameName, "Chess256" )) || 
		stringCompNoCase( selectedVariant->name, "Chess256" ) )
	{
		if( !justLoaded )
		{
			::DialogBox( theInstance, MAKEINTRESOURCE(IDD_CHESS256_DIALOG), NULL, 
				reinterpret_cast<DLGPROC>(Chess256_SelectDlgProc) );
		}
	}
	theBoard = new Board( 8, 8 );
	char *player0Name = "White";
	char *player1Name = "Black";
	LookupStringParameter( "player1", player0Name );
	LookupStringParameter( "player2", player1Name );
	CreatePlayers( player0Name, player1Name, whiteComp, blackComp );
}

Game *CreateChessGame( Board &brd, Player &plr0, Player &plr1 )
{
	return new ChessGame( brd, plr0, plr1 );
}

ChessGame::ChessGame( Board &board, Player &whitePlayer, Player &blackPlayer ):
	Game(board, whitePlayer, blackPlayer)
{
	// ***************************************** //
	// ***                                   *** //
	// ***  set rules and evaluation values  *** //
	// ***                                   *** //
	// ***************************************** //

	//	assume, for now, standard rules
	castlingType = CASTLING_TYPE_STANDARD;
	enPassant = true;
	derivedClassEP = false;
	bareKingRule = false;
	castlingPieceSquare0L = 0;
	castlingPieceSquare0R = 7;
	castlingPieceSquare1L = 56;
	castlingPieceSquare1R = 63;

	//	implement 50-move draw rule
	autoDrawPeriod = 100;

	//	turn on use of pawn structure evaluation
	usePawnStructureEvaluation = true;

	//	turn off null-move and futility pruning after 24 pieces 
	//	have been captured.  when the number of pieces remaining is 
	//	low, we risk a zugzwang situation, and trying null moves in 
	//	such situations is a recipe for disaster.
	endgameCaptureThreshold = 24;

	//	razoring and futility pruning margins
	razorMargin = 9500;
	futilityMargin = 3800;
	extendedFutilityMargin = 5800;


	// *** PHASES *** //

	//	we have to set up the phases we wish to have in this game;
	//	we will keep it simple and have 3: opening, midgame, and endgame
	nPhases = 3;

	//	settings for phase 0 (opening)
	phases[0].SetNumber( 1 );
	phases[0].SetMobilityFactor( 1 );
	phases[0].SetPawnDeficiencyFactor( 8 );
	phases[0].SetSquareValuesFactor( 1 );
	phases[0].SetKingSafetyFactor( 4 );
	phases[0].SetTropismFactor( 6 );

	//	settings for phase 1 (midgame)
	phases[1].SetNumber( 1 );
	phases[1].SetMobilityFactor( 1 );
	phases[1].SetPawnDeficiencyFactor( 10 );
	phases[1].SetSquareValuesFactor( 1 );
	phases[1].SetKingSafetyFactor( 8 );
	phases[1].SetTropismFactor( 10 );
	
	//	settings for phase 2 (endgame)
	phases[2].SetNumber( 2 );
	phases[2].SetMobilityFactor( 1 );
	phases[2].SetPawnDeficiencyFactor( 16 );
	phases[2].SetSquareValuesFactor( 1 );
	phases[2].SetKingSafetyFactor( 0 );
	phases[2].SetTropismFactor( 12 );


	// *** OUTPOSTS *** //

	//	we wish to be able to give bonuses to pieces that are 'posted'-
	//	that is, which are centrally located and cannot be reached by
	//	enemy pawns (because adjacent pawns are gone, or have advanced
	//	beyond the piece).  we also wish to be able to give different
	//	bonuses for different types of minor pieces (a posted Knight is
	//	worth more than a posted Bishop.)

	//	we will use the user variable 'gameInt1' in the PieceType class
	//	to store the 'outpost factor' for a given piece.  this value will
	//	be multiplied by the square-values stored in the 'outpost' array.
	OrthodoxKnight::orthodoxKnight.gameInt1 = 10;
	OrthodoxBishop::orthodoxBishop.gameInt1 = 6;
	Elephant::elephant.gameInt1 = 5;
	Ferz::ferz.gameInt1 = 3;
	ElephantFerz::elephantFerz.gameInt1 = 7;


	// *** INITIALIZATION *** //

	for( int x = 0; x < 8; x++ )
	{
		player0PawnTwoSpaceZone.SetBit( x );
		player0PawnTwoSpaceZone.SetBit( x + 8 );
		player1PawnTwoSpaceZone.SetBit( x + 48 );
		player1PawnTwoSpaceZone.SetBit( x + 56 );
	}
	for( int x = 0; x < 64; x++ )
	{
		if( (x + (x / 8)) % 2 )
			whiteSquares.SetBit( x );
		else
			blackSquares.SetBit( x );
	}

	//	initialize hashes
	enPassantHashMap = new HashMap( board.GetNumberOfSquares() );
	castlingHash0k = rand_32();
	castlingHash0q = rand_32();
	castlingHash1k = rand_32();
	castlingHash1q = rand_32();

	//	basic initialization
	board.Initialize( this, BITBOARD_64 );
}

void ChessGame::AddPlayerPieceTypes( char *gameName )
{
	//	add the piece types that each player may have
	board.AddPlayerPieceTypeBothPlayers( OrthodoxRook::orthodoxRook );
	board.AddPlayerPieceTypeBothPlayers( OrthodoxBishop::orthodoxBishop );
	board.AddPlayerPieceTypeBothPlayers( OrthodoxKnight::orthodoxKnight);
	board.AddPlayerPieceTypeBothPlayers( OrthodoxQueen::orthodoxQueen );
	board.AddPlayerPieceTypeBothPlayers( OrthodoxKing::orthodoxKing );
	board.AddPlayerPieceTypeBothPlayers( OrthodoxPawn::orthodoxPawn );
	//	add piece type references to the following arrays, 
	//	minorPieceTypes, etc., used for giving bonuses and 
	//	penalties in positional evaluation
	castlingPieceTypes[0] = &OrthodoxRook::orthodoxRook;
	castlingPieceTypes[1] = &OrthodoxRook::orthodoxRook;
	minorPieceTypes[0][0] = &OrthodoxKnight::orthodoxKnight;
	minorPieceTypes[1][0] = &OrthodoxKnight::orthodoxKnight;
	minorPieceTypes[0][1] = &OrthodoxBishop::orthodoxBishop;
	minorPieceTypes[1][1] = &OrthodoxBishop::orthodoxBishop;
	minorPieceTypes[0][2] = &NullPieceType64::nullPieceType64;
	minorPieceTypes[1][2] = &NullPieceType64::nullPieceType64;
	minorPieceTypes[0][3] = &NullPieceType64::nullPieceType64;
	minorPieceTypes[1][3] = &NullPieceType64::nullPieceType64;
	colorboundPieceTypes[0][0] = &OrthodoxBishop::orthodoxBishop;
	colorboundPieceTypes[1][0] = &OrthodoxBishop::orthodoxBishop;
	colorboundPieceTypes[0][1] = &NullPieceType64::nullPieceType64;
	colorboundPieceTypes[1][1] = &NullPieceType64::nullPieceType64;
	queenPieceTypes[0] = &OrthodoxQueen::orthodoxQueen;
	queenPieceTypes[1] = &OrthodoxQueen::orthodoxQueen;
	pawnPieceTypes[0] = &OrthodoxPawn::orthodoxPawn;
	pawnPieceTypes[1] = &OrthodoxPawn::orthodoxPawn;
	castlingPiecesSlideNorth[0] = true;
	castlingPiecesSlideNorth[1] = true;
}

void ChessGame::ChangeRulesByVariant
	( char *gameName,
	  char *&array,
	  char *&book )
{
	// *** ORTHODOX CHESS *** //
	if( !strcmp( gameName, "Orthodox Chess" ) )
	{
		//	place pieces
		array = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR";
		//	set name of opening book
		book = "openings\\OrthodoxChess.txt";
		//	activate BitBoard move and capture generation
		customMoveGeneration = true;
		customCaptureGeneration = true;
	}
	// *** FISCHER RANDOM CHESS *** //
	else if( !strcmp( gameName, "Fischer Random Chess" ) )
	{
		castlingType = CASTLING_TYPE_FISCHER_RANDOM;
		//	no opening book support for Fischer Random Chess
		//	because there are 960 possible setups
		useOpeningBook = false;
		//	activate Bit Boards 
		customMoveGeneration = true;
		customCaptureGeneration = true;
		//	place pieces
		if( !LookupStringParameter( "array", array ) )
		{
			int positionNumber;
			LookupIntParameter( "position-number", positionNumber );
			array = GetArrayForFRCByPositionNumber( positionNumber );
		}
	}
	// *** CHESS 480 *** //
	else if( !strcmp( gameName, "Chess 480" ) )
	{
		castlingType = CASTLING_TYPE_CHESS480;
		//	no opening book support for Chess 480
		//	because there are 480 possible setups
		useOpeningBook = false;
		//	activate Bit Boards 
		customMoveGeneration = true;
		customCaptureGeneration = true;
		//	place pieces
		if( !LookupStringParameter( "array", array ) )
		{
			int positionNumber;
			LookupIntParameter( "position-number", positionNumber );
			array = GetArrayForFRCByPositionNumber( positionNumber );
		}
	}
	// *** CHESS256 *** //
	else if( !strcmp( gameName, "Chess256" ) )
	{
		//	no opening book support for Chess256
		//	because there are 256 possible setups
		useOpeningBook = false;
		//	activate Bit Boards 
		customMoveGeneration = true;
		customCaptureGeneration = true;
		//	place pieces
		if( !LookupStringParameter( "array", array ) )
		{
			int positionNumber;
			LookupIntParameter( "position-number", positionNumber );
			array = GetArrayForChess256ByPositionNumber( positionNumber );
		}
	}
	// *** ALMOST CHESS *** //
	else if( !strcmp( gameName, "Almost Chess" ) )
	{
		//	Queen is replaced by Chancellor
		board.RemovePieceType( OrthodoxQueen::orthodoxQueen );
		board.AddPlayerPieceTypeBothPlayers( Chancellor::chancellor );
		queenPieceTypes[0] = &Chancellor::chancellor;
		queenPieceTypes[1] = &Chancellor::chancellor;
		//	place pieces
		array = "rnbckbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBCKBNR";
		//	set name of opening book
		book = "openings\\AlmostChess.txt";
		//	activate Bit Boards 
		customMoveGeneration = true;
		customCaptureGeneration = true;
	}
	// *** LATRUNCULI DUO MILIA ET SEPTUM *** //
	else if( !strcmp( gameName, "Latrunculi Duo Milia et Septum" ) )
	{
		//	Rook is replaced by Dragon King
		board.RemovePieceType( OrthodoxRook::orthodoxRook );
		board.AddPlayerPieceTypeBothPlayers( DragonKing::dragonKing );
		castlingPieceTypes[0] = &DragonKing::dragonKing;
		castlingPieceTypes[1] = &DragonKing::dragonKing;
		//	Bishop is replaced by Dragon Horse
		board.RemovePieceType( OrthodoxBishop::orthodoxBishop );
		board.AddPlayerPieceTypeBothPlayers( DragonHorse::dragonHorse );
		minorPieceTypes[0][1] = &DragonHorse::dragonHorse;
		minorPieceTypes[1][1] = &DragonHorse::dragonHorse;
		colorboundPieceTypes[0][0] = &NullPieceType64::nullPieceType64;
		colorboundPieceTypes[1][0] = &NullPieceType64::nullPieceType64;
		//	place pieces
		array = "_dkn_dhqk_dhn_dk/pppppppp/8/8/8/8/PPPPPPPP/_DKN_DHQK_DHN_DK";
		//	set name of opening book
		book = "openings\\LatrunculiDuoMiliaEtSeptum.txt";
	}
	else if( !strcmp( gameName, "Knightmate" ) )
	{
		//	make the Knight royal
		OrthodoxKnight::orthodoxKnight.SetRoyal( true );
		OrthodoxKnight::orthodoxKnight.SetBaseValue( 25000 );
		//	and the King is not royal
		OrthodoxKing::orthodoxKing.SetRoyal( false );
		OrthodoxKing::orthodoxKing.SetBaseValue( 3500 );
		//	place pieces
		array = "rkbqnbkr/pppppppp/8/8/8/8/PPPPPPPP/RKBQNBKR";
		//	set name of opening book
		book = "openings\\Knightmate.txt";
		//	activate bit boards move generation
		customMoveGeneration = true;
		customCaptureGeneration = true;
	}
	// *** SHATRANJ *** //
	else if( !strcmp( gameName, "Shatranj" ) )
	{
		//	no castling in Shatranj
		castlingType = CASTLING_TYPE_NONE;
		//	no en-Passant
		enPassant = false;
		//	use 'bare king' rule
		bareKingRule = true;
		//	stalemate is a win
		stalemateResult = INFINITY;
		//	use historic 'lame' pawn (no 2-space initial move)
		//	NOTE: do not remove the OrthodoxPawn, though, because we need it 
		//	to be initialized, as its tables are used for bitboard move generation
		board.AddPlayerPieceTypeBothPlayers( LamePawn::lamePawn );
		pawnPieceTypes[0] = &LamePawn::lamePawn;
		pawnPieceTypes[1] = &LamePawn::lamePawn;
		//	pawns promote to Generals
		LamePawn::lamePawn.SetPromotionType( PromoteToSpecificType );
		LamePawn::lamePawn.SetTypeToPromoteTo( Ferz::ferz );
		//	Bishop is replaced by Elephant
		board.RemovePieceType( OrthodoxBishop::orthodoxBishop );
		board.AddPlayerPieceTypeBothPlayers( Elephant::elephant );
		minorPieceTypes[0][1] = &Elephant::elephant;
		minorPieceTypes[1][1] = &Elephant::elephant;
		//	Queen is replaced by General (Ferz)
		board.RemovePieceType( OrthodoxQueen::orthodoxQueen );
		board.AddPlayerPieceTypeBothPlayers( Ferz::ferz );
		queenPieceTypes[0] = &NullPieceType64::nullPieceType64;
		queenPieceTypes[1] = &NullPieceType64::nullPieceType64;
		minorPieceTypes[0][2] = &Ferz::ferz;
		minorPieceTypes[1][2] = &Ferz::ferz;
		//	Knights and Rooks are move valuble than usual
		OrthodoxKnight::orthodoxKnight.SetBaseValue( 4000 );
		OrthodoxRook::orthodoxRook.SetBaseValue( 5500 );
		//	place pieces
		array = "rnekgenr/pppppppp/8/8/8/8/PPPPPPPP/RNEKGENR";
		//	set name of opening book
		book = "openings\\Shatranj.txt";
		//	activate bit boards move generation
		customMoveGeneration = true;
		customCaptureGeneration = true;
	}
	// *** MODERN SHATRANJ *** //
	else if( !strcmp( gameName, "Modern Shatranj" ) )
	{
		//	no castling in Shatranj
		castlingType = CASTLING_TYPE_NONE;
		//	no en-Passant
		enPassant = false;
		//	use 'bare king' rule
		bareKingRule = true;
		//	stalemate is a win
		stalemateResult = INFINITY;
		//	use historic 'lame' pawn (no 2-space initial move)
		//	NOTE: do not remove the OrthodoxPawn, though, because we need it 
		//	to be initialized, as its tables are used for bitboard move generation
		board.AddPlayerPieceTypeBothPlayers( LamePawn::lamePawn );
		pawnPieceTypes[0] = &LamePawn::lamePawn;
		pawnPieceTypes[1] = &LamePawn::lamePawn;
		//	pawns promote to Generals
		LamePawn::lamePawn.SetPromotionType( PromoteToSpecificType );
		LamePawn::lamePawn.SetTypeToPromoteTo( General::general );
		//	Bishop is replaced by Elephant
		board.RemovePieceType( OrthodoxBishop::orthodoxBishop );
		board.AddPlayerPieceTypeBothPlayers( ElephantFerz::elephantFerz );
		minorPieceTypes[0][1] = &ElephantFerz::elephantFerz;
		minorPieceTypes[1][1] = &ElephantFerz::elephantFerz;
		//	Queen is replaced by General
		board.RemovePieceType( OrthodoxQueen::orthodoxQueen );
		board.AddPlayerPieceTypeBothPlayers( General::general );
		queenPieceTypes[0] = &NullPieceType64::nullPieceType64;
		queenPieceTypes[1] = &NullPieceType64::nullPieceType64;
		minorPieceTypes[0][2] = &General::general;
		minorPieceTypes[1][2] = &General::general;
		//	Rooks are move valuble than usual
		OrthodoxRook::orthodoxRook.SetBaseValue( 5000 );
		//	place pieces
		array = "rnekgenr/pppppppp/8/8/8/8/PPPPPPPP/RNEKGENR";
		//	set name of opening book
		book = "openings\\ModernShatranj.txt";
		//	activate bit boards move generation
		customMoveGeneration = true;
		customCaptureGeneration = true;
	}
}

void ChessGame::ChangeRulesByVariableDefinition( char *gameName )
{
	// *** CASTLING TYPE *** //
	char *castlingTypeName;
	if( LookupStringParameter( "castling-type", castlingTypeName ) )
	{
		if( stringCompNoCase( castlingTypeName, "none" ) )
			castlingType = CASTLING_TYPE_NONE;
		else if( stringCompNoCase( castlingTypeName, "standard" ) )
			castlingType = CASTLING_TYPE_STANDARD;
		else if( stringCompNoCase( castlingTypeName, "flexible" ) )
			castlingType = CASTLING_TYPE_FLEXIBLE;
		else if( stringCompNoCase( castlingTypeName, "free" ) )
			castlingType = CASTLING_TYPE_FREE;
		else if( stringCompNoCase( castlingTypeName, "FRC" ) )
			castlingType = CASTLING_TYPE_FISCHER_RANDOM;
		else if( stringCompNoCase( castlingTypeName, "Chess 480" ) )
			castlingType = CASTLING_TYPE_CHESS480;
		else
			ASSERT(FALSE);
	}
	// *** EN PASSANT *** //
	LookupBoolParameter( "en-passant", enPassant );
	// *** BARE KING *** //
	LookupBoolParameter( "bare-king", bareKingRule );
}

void ChessGame::Initialize()
{
	//	first, let the base class Initialize() do its thing
	Game::Initialize();

	//	initialize bitboards for detecting posted pieces
	board.InitializeOutpost( outpost );

	//	now, find the castling pieces, if the game being played
	//	alows them to be somewhere other than in the corners
	if( castlingType == CASTLING_TYPE_FISCHER_RANDOM || 
		castlingType == CASTLING_TYPE_CHESS480 )
	{
		//	look for player 0's left rook (or other castling piece)
		int x;
		Piece *castlingPiece = NULL;
		Piece *king = board.GetKing( 0 );
		for( x = 0; x < king->GetSquareNumber(); x++ )
			if( board.GetSquareContents( x ) != NULL && 
				(PieceType64 *) &(board.GetSquareContents( x )->GetType()) == castlingPieceTypes[0] &&
				!board.GetSquareContents( x )->HasMoved() )
				//	found it
				castlingPiece = board.GetSquareContents( x );
		if( castlingPiece != NULL )
			castlingPieceSquare0L = castlingPiece->GetSquareNumber();
		else
			castlingPieceSquare0L = -1;

		//	look for player 0's right rook (or other castling piece)
		castlingPiece = NULL;
		for( x = 7; x > king->GetSquareNumber(); x-- )
			if( board.GetSquareContents( x ) != NULL && 
				(PieceType64 *) &(board.GetSquareContents( x )->GetType()) == castlingPieceTypes[0] &&
				!board.GetSquareContents( x )->HasMoved() )
				//	found it
				castlingPiece = board.GetSquareContents( x );
		if( castlingPiece != NULL )
			castlingPieceSquare0R = castlingPiece->GetSquareNumber();
		else
			castlingPieceSquare0R = -1;

		//	look for player 1's left rook (or other castling piece)
		castlingPiece = NULL;
		king = board.GetKing( 1 );
		for( x = 56; x < king->GetSquareNumber(); x++ )
			if( board.GetSquareContents( x ) != NULL && 
				(PieceType64 *) &(board.GetSquareContents( x )->GetType()) == castlingPieceTypes[0] &&
				!board.GetSquareContents( x )->HasMoved() )
				//	found it
				castlingPiece = board.GetSquareContents( x );
		if( castlingPiece != NULL )
			castlingPieceSquare1L = castlingPiece->GetSquareNumber();
		else
			castlingPieceSquare1L = -1;

		//	look for player 0's right rook (or other castling piece)
		castlingPiece = NULL;
		for( x = 63; x > king->GetSquareNumber(); x-- )
			if( board.GetSquareContents( x ) != NULL && 
				(PieceType64 *) &(board.GetSquareContents( x )->GetType()) == castlingPieceTypes[0] &&
				!board.GetSquareContents( x )->HasMoved() )
				//	found it
				castlingPiece = board.GetSquareContents( x );
		if( castlingPiece != NULL )
			castlingPieceSquare1R = castlingPiece->GetSquareNumber();
		else
			castlingPieceSquare1R = -1;
	}
}

Piece *ChessGame::AddPiece
	( PieceType &pieceType,
	  int nPlayer,
	  int nRank,
	  int nFile )
{
	Piece *newPiece = Game::AddPiece( pieceType, nPlayer, nRank, nFile );

	//	if Pawn, set the promotion zone
	if( &pieceType == pawnPieceTypes[nPlayer] )
	{
		if( newPiece->GetPlayerNumber() == 0 )
			newPiece->GetPromotionZone().AddToZone( 56, 63 );
		else
			newPiece->GetPromotionZone().AddToZone( 0, 7 );
	}

	return newPiece;
}

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

bool ChessGame::RemovePieceType
	( PieceType *pieceType )
{
	for( int player = 0; player < 2; player++ )
	{
		if( castlingPieceTypes[player] == pieceType )
			castlingPieceTypes[player] = &NullPieceType64::nullPieceType64;
		if( queenPieceTypes[player] == pieceType )
			queenPieceTypes[player] = &NullPieceType64::nullPieceType64;
		if( pawnPieceTypes[player] == pieceType )
			pawnPieceTypes[player] = &NullPieceType64::nullPieceType64;
		for( int x = 0; x < 4; x++ )
		{
			if( minorPieceTypes[player][x] == pieceType )
			{
				for( int y = x; y < 3; y++ )
					minorPieceTypes[player][y] = minorPieceTypes[player][y+1];
				minorPieceTypes[player][3] = &NullPieceType64::nullPieceType64;
			}
			if( x < 2 )
			{
				if( colorboundPieceTypes[player][x] == pieceType )
				{
					if( x == 0 )
						colorboundPieceTypes[player][0] = colorboundPieceTypes[player][1];
					colorboundPieceTypes[player][1] = &NullPieceType64::nullPieceType64;
				}
			}
		}
	}
	return( true );
}

bool ChessGame::AddPieceType
	( PieceType *pieceType,
	  int nPlayer )
{
	if( pieceType->IsPawn() )
	{
		if( pawnPieceTypes[nPlayer] == &NullPieceType64::nullPieceType64 )
			pawnPieceTypes[nPlayer] = (PieceType64 *) pieceType;
		else
			return false;
		return true;
	}
	if( pieceType == &ChargingRook::chargingRook )
	{
		if( castlingPieceTypes[nPlayer] == &NullPieceType64::nullPieceType64 )
		{
			castlingPieceTypes[nPlayer] = (PieceType64 *) pieceType;
			castlingPiecesSlideNorth[nPlayer] = true;
		}
	}
	if( pieceType->GetBaseValue() >= 7000 )
	{
		if( queenPieceTypes[nPlayer] == &NullPieceType64::nullPieceType64 )
			queenPieceTypes[nPlayer] = (PieceType64 *) pieceType;
	}
	else if( pieceType->GetBaseValue() <= 4000 )
	{
		if( minorPieceTypes[nPlayer][0] == &NullPieceType64::nullPieceType64 )
			minorPieceTypes[nPlayer][0] = (PieceType64 *) pieceType;
		else
		{
			if( minorPieceTypes[nPlayer][1] == &NullPieceType64::nullPieceType64 )
				minorPieceTypes[nPlayer][1] = (PieceType64 *) pieceType;
			else
			{
				if( minorPieceTypes[nPlayer][2] == &NullPieceType64::nullPieceType64 )
					minorPieceTypes[nPlayer][2] = (PieceType64 *) pieceType;
				else
				{
					if( minorPieceTypes[nPlayer][3] == &NullPieceType64::nullPieceType64 )
						minorPieceTypes[nPlayer][3] = (PieceType64 *) pieceType;
				}
			}
		}
	}
	return true;
}

void ChessGame::AddSpecialMoves
	( int currentPlayer, 
	  MovementList &stack, 
	  GameRec &gameRecord,
	  bool quiescentSearch )
{
	int x;

	//	check for en-passant
	if( enPassant && !derivedClassEP )
		Game::AddEnPassantMoves( stack, gameRecord, quiescentSearch );

	if( quiescentSearch || castlingType == CASTLING_TYPE_NONE || 
		(board.FastCheckTest() && goalIsCheckmate) )
		return;

	// *** CASTLING *** //

	if( castlingType == CASTLING_TYPE_STANDARD )
	{
		if( board.GetCurrentPlayerNumber() == 0 )
		{
			//	white to move
			Piece *king = board.GetKing( 0 );
			if( !king->IsCaptured() && !king->HasMoved() && king->GetSquareNumber() == 4 )
			{
				//	king side
				if( board.GetSquareContents( 7 ) != NULL &&
					!board.GetSquareContents( 7 )->HasMoved() )
				{
					AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 7 ), 6, 5 );
				}
				//	queen side
				if( board.GetSquareContents( 0 ) != NULL &&
					!board.GetSquareContents( 0 )->HasMoved() )
				{
					AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 0 ), 2, 3 );
				}
			}
			else if( !king->IsCaptured() && !king->HasMoved() && king->GetSquareNumber() == 3 )
			{
				//	king side
				if( board.GetSquareContents( 7 ) != NULL &&
					!board.GetSquareContents( 7 )->HasMoved() )
				{
					AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 7 ), 5, 4 );
				}
				//	queen side
				if( board.GetSquareContents( 0 ) != NULL &&
					!board.GetSquareContents( 0 )->HasMoved() )
				{
					AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 0 ), 1, 2 );
				}
			}
		}
		else
		{
			//	black to move
			Piece *king = board.GetKing( 1 );
			if( !king->IsCaptured() && !king->HasMoved() && king->GetSquareNumber() == 60 )
			{
				//	king side
				if( board.GetSquareContents( 63 ) != NULL &&
					!board.GetSquareContents( 63 )->HasMoved() )
				{
					AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 63 ), 62, 61 );
				}
				//	queen side
				if( board.GetSquareContents( 56 ) != NULL &&
					!board.GetSquareContents( 56 )->HasMoved() )
				{
					AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 56 ), 58, 59 );
				}
			}
			else if( !king->IsCaptured() && !king->HasMoved() && king->GetSquareNumber() == 59 )
			{
				//	king side
				if( board.GetSquareContents( 63 ) != NULL &&
					!board.GetSquareContents( 63 )->HasMoved() )
				{
					AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 63 ), 61, 60 );
				}
				//	queen side
				if( board.GetSquareContents( 56 ) != NULL &&
					!board.GetSquareContents( 56 )->HasMoved() )
				{
					AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 56 ), 57, 58 );
				}
			}
		}
	}
	else if( castlingType == CASTLING_TYPE_FISCHER_RANDOM )
	{
		if( board.GetCurrentPlayerNumber() == 0 )
		{
			//	CASTLING in FISCHER RANDOM CHESS - white to move
			Piece *king = board.GetKing( 0 );
			if( !king->IsCaptured() && !king->HasMoved() )
			{
				// *** A-SIDE CASTLING *** //
				Piece *castlingPiece = NULL;
				if( castlingPieceSquare0L >= 0 )
					castlingPiece = board.GetSquareContents( castlingPieceSquare0L );

				if( castlingPiece != NULL && !castlingPiece->HasMoved() )
				{
					//	check to see if all squares are vacant
					bool canCastle = true;
					int leftmostSquare = min(C1, castlingPiece->GetSquareNumber());
					for( x = king->GetSquareNumber() - 1; x >= leftmostSquare; x-- )
						if( board.GetSquareContents( x ) != NULL && 
							board.GetSquareContents( x ) != castlingPiece )
							//	piece in the way
							canCastle = false;
					if( board.GetSquareContents( D1 ) != NULL && 
						board.GetSquareContents( D1 ) != king )
						//	piece in the way
						canCastle = false;

					if( canCastle )
					{
						//	check to see if king's square are attacked
						for( x = king->GetSquareNumber() - 1; x >= C1; x-- )
							if( goalIsCheckmate && IsSquareAttacked( x, 1 ) )
								//	square is attacked; can't castle
								canCastle = false;

						if( canCastle )
						{
							stack.BeginMoveAdd( Castling, king->GetSquareNumber(), C1 );
							stack.AddPickUp( king->GetSquareNumber() );
							stack.AddPickUp( castlingPiece->GetSquareNumber() );
							stack.AddDrop( king, C1 );
							stack.AddDrop( castlingPiece, D1 );
							stack.EndMoveAdd( 1000 );
						}
					}
				}

				// *** H-SIDE CASTLING *** //
				castlingPiece = NULL;
				if( castlingPieceSquare0R >= 0 )
					castlingPiece = board.GetSquareContents( castlingPieceSquare0R );

				if( castlingPiece != NULL && !castlingPiece->HasMoved() )
				{
					//	check to see if all squares are vacant
					bool canCastle = true;
					for( x = king->GetSquareNumber() + 1; x <= G1; x++ )
						if( board.GetSquareContents( x ) != NULL && 
							board.GetSquareContents( x ) != castlingPiece )
							//	piece in the way
							canCastle = false;
					if( board.GetSquareContents( F1 ) != NULL && 
						board.GetSquareContents( F1 ) != king )
						//	piece in the way
						canCastle = false;

					if( canCastle )
					{
						//	check to see if king's square are attacked
						for( x = king->GetSquareNumber() + 1; x <= G1; x++ )
							if( goalIsCheckmate && IsSquareAttacked( x, 1 ) )
								//	square is attacked; can't castle
								canCastle = false;

						if( canCastle )
						{
							stack.BeginMoveAdd( Castling, king->GetSquareNumber(), G1 );
							stack.AddPickUp( king->GetSquareNumber() );
							stack.AddPickUp( castlingPiece->GetSquareNumber() );
							stack.AddDrop( king, G1 );
							stack.AddDrop( castlingPiece, F1 );
							stack.EndMoveAdd( 1000 );
						}
					}
				}
			}
		}
		else
		{
			//	CASTLING in FISCHER RANDOM CHESS - black to move
			Piece *king = board.GetKing( 1 );
			if( !king->IsCaptured() && !king->HasMoved() )
			{
				// *** A-SIDE CASTLING *** //
				Piece *castlingPiece = NULL;
				if( castlingPieceSquare1L >= 0 )
					castlingPiece = board.GetSquareContents( castlingPieceSquare1L );

				if( castlingPiece != NULL && !castlingPiece->HasMoved() )
				{
					//	check to see if all squares are vacant
					bool canCastle = true;
					int leftmostSquare = min(C8, castlingPiece->GetSquareNumber());
					for( x = king->GetSquareNumber() - 1; x >= leftmostSquare; x-- )
						if( board.GetSquareContents( x ) != NULL && 
							board.GetSquareContents( x ) != castlingPiece )
							//	piece in the way
							canCastle = false;
					if( board.GetSquareContents( D8 ) != NULL && 
						board.GetSquareContents( D8 ) != king )
						//	piece in the way
						canCastle = false;

					if( canCastle )
					{
						//	check to see if king's square are attacked
						for( x = king->GetSquareNumber() - 1; x >= C8; x-- )
							if( goalIsCheckmate && IsSquareAttacked( x, 0 ) )
								//	square is attacked; can't castle
								canCastle = false;

						if( canCastle )
						{
							stack.BeginMoveAdd( Castling, king->GetSquareNumber(), C8 );
							stack.AddPickUp( king->GetSquareNumber() );
							stack.AddPickUp( castlingPiece->GetSquareNumber() );
							stack.AddDrop( king, C8 );
							stack.AddDrop( castlingPiece, D8 );
							stack.EndMoveAdd( 1000 );
						}
					}
				}

				// *** H-SIDE CASTLING *** //
				castlingPiece = NULL;
				if( castlingPieceSquare1R >= 0 )
					castlingPiece = board.GetSquareContents( castlingPieceSquare1R );

				if( castlingPiece != NULL && !castlingPiece->HasMoved() )
				{
					//	check to see if all squares are vacant
					bool canCastle = true;
					for( x = king->GetSquareNumber() + 1; x <= G8; x++ )
						if( board.GetSquareContents( x ) != NULL && 
							board.GetSquareContents( x ) != castlingPiece )
							//	piece in the way
							canCastle = false;
					if( board.GetSquareContents( F8 ) != NULL && 
						board.GetSquareContents( F8 ) != king )
						//	piece in the way
						canCastle = false;

					if( canCastle )
					{
						//	check to see if king's square are attacked
						for( x = king->GetSquareNumber() + 1; x <= G8; x++ )
							if( goalIsCheckmate && IsSquareAttacked( x, 0 ) )
								//	square is attacked; can't castle
								canCastle = false;

						if( canCastle )
						{
							stack.BeginMoveAdd( Castling, king->GetSquareNumber(), G8 );
							stack.AddPickUp( king->GetSquareNumber() );
							stack.AddPickUp( castlingPiece->GetSquareNumber() );
							stack.AddDrop( king, G8 );
							stack.AddDrop( castlingPiece, F8 );
							stack.EndMoveAdd( 1000 );
						}
					}
				}
			}
		}
	}
	else if( castlingType == CASTLING_TYPE_CHESS480 )
	{
		if( board.GetCurrentPlayerNumber() == 0 )
		{
			//	CASTLING in CHESS 480 - white to move
			Piece *king = board.GetKing( 0 );
			if( !king->IsCaptured() && !king->HasMoved() )
			{
				// *** A-SIDE CASTLING *** //
				Piece *castlingPiece = NULL;
				if( castlingPieceSquare0L >= 0 )
					castlingPiece = board.GetSquareContents( castlingPieceSquare0L );

				if( castlingPiece != NULL && !castlingPiece->HasMoved() )
				{
					//	special case when King and Rook are in the corner
					if( king->GetSquareNumber() == 1 )
					{
						if( !board.IsSquareAttacked( 0, 1 ) )
						{
							stack.BeginMoveAdd( Castling, 1, 0 );
							stack.AddPickUp( 1 );
							stack.AddPickUp( 0 );
							stack.AddDrop( king, 0 );
							stack.AddDrop( castlingPiece, 1 );
							stack.EndMoveAdd( 1000 );
						}
					}
					//	check to see if all squares are vacant and not attacked
					bool canCastle = true;
					for( x = king->GetSquareNumber() - 1; x > king->GetSquareNumber() - 3 && canCastle; x-- )
					{
						if( board.GetSquareContents( x ) != NULL && 
							board.GetSquareContents( x ) != castlingPiece )
							//	square is blocked; cannot castle
							canCastle = false;
						if( canCastle && board.IsSquareAttacked( x, 1 ) )
							canCastle = false;
					}
					for( ; x > castlingPiece->GetSquareNumber(); x-- )
					{
						if( board.GetSquareContents( x ) != NULL )
							//	square is blocked; cannot castle
							canCastle = false;
					}
					if( canCastle )
					{
						stack.BeginMoveAdd( Castling, king->GetSquareNumber(), king->GetSquareNumber() - 2 );
						stack.AddPickUp( king->GetSquareNumber() );
						stack.AddPickUp( castlingPiece->GetSquareNumber() );
						stack.AddDrop( king, king->GetSquareNumber() - 2 );
						stack.AddDrop( castlingPiece, king->GetSquareNumber() - 1 );
						stack.EndMoveAdd( 1000 );
					}
				}

				// *** H-SIDE CASTLING *** //
				castlingPiece = NULL;
				if( castlingPieceSquare0R >= 0 )
					castlingPiece = board.GetSquareContents( castlingPieceSquare0R );

				if( castlingPiece != NULL && !castlingPiece->HasMoved() )
				{
					//	special case when King and Rook are in the corner
					if( king->GetSquareNumber() == 6 )
					{
						if( !board.IsSquareAttacked( 7, 1 ) )
						{
							stack.BeginMoveAdd( Castling, 6, 7 );
							stack.AddPickUp( 6 );
							stack.AddPickUp( 7 );
							stack.AddDrop( king, 7 );
							stack.AddDrop( castlingPiece, 6 );
							stack.EndMoveAdd( 1000 );
						}
					}
					//	check to see if all squares are vacant and not attacked
					bool canCastle = true;
					for( x = king->GetSquareNumber() + 1; x < king->GetSquareNumber() + 3 && canCastle; x++ )
					{
						if( board.GetSquareContents( x ) != NULL && 
							board.GetSquareContents( x ) != castlingPiece )
							//	square is blocked; cannot castle
							canCastle = false;
						if( canCastle && board.IsSquareAttacked( x, 1 ) )
							canCastle = false;
					}
					for( ; x < castlingPiece->GetSquareNumber(); x++ )
					{
						if( board.GetSquareContents( x ) != NULL )
							//	square is blocked; cannot castle
							canCastle = false;
					}
					if( canCastle )
					{
						stack.BeginMoveAdd( Castling, king->GetSquareNumber(), king->GetSquareNumber() + 2 );
						stack.AddPickUp( king->GetSquareNumber() );
						stack.AddPickUp( castlingPiece->GetSquareNumber() );
						stack.AddDrop( king, king->GetSquareNumber() + 2 );
						stack.AddDrop( castlingPiece, king->GetSquareNumber() + 1 );
						stack.EndMoveAdd( 1000 );
					}
				}
			}
		}
		else
		{
			//	CASTLING in CHESS 480 - black to move
			Piece *king = board.GetKing( 1 );
			if( !king->IsCaptured() && !king->HasMoved() )
			{
				// *** A-SIDE CASTLING *** //
				Piece *castlingPiece = NULL;
				if( castlingPieceSquare0R >= 0 )
					castlingPiece = board.GetSquareContents( castlingPieceSquare0R );

				if( castlingPiece != NULL && !castlingPiece->HasMoved() )
				{
					//	special case when King and Rook are in the corner
					if( king->GetSquareNumber() == 57 )
					{
						if( !board.IsSquareAttacked( 56, 0 ) )
						{
							stack.BeginMoveAdd( Castling, 57, 56 );
							stack.AddPickUp( 57 );
							stack.AddPickUp( 56 );
							stack.AddDrop( king, 56 );
							stack.AddDrop( castlingPiece, 57 );
							stack.EndMoveAdd( 1000 );
						}
					}
					//	check to see if all squares are vacant and not attacked
					bool canCastle = true;
					for( x = king->GetSquareNumber() - 1; x > king->GetSquareNumber() - 3 && canCastle; x-- )
					{
						if( board.GetSquareContents( x ) != NULL && 
							board.GetSquareContents( x ) != castlingPiece )
							//	square is blocked; cannot castle
							canCastle = false;
						if( canCastle && board.IsSquareAttacked( x, 0 ) )
							canCastle = false;
					}
					for( ; x > castlingPiece->GetSquareNumber(); x-- )
					{
						if( board.GetSquareContents( x ) != NULL )
							//	square is blocked; cannot castle
							canCastle = false;
					}
					if( canCastle )
					{
						stack.BeginMoveAdd( Castling, king->GetSquareNumber(), king->GetSquareNumber() - 2 );
						stack.AddPickUp( king->GetSquareNumber() );
						stack.AddPickUp( castlingPiece->GetSquareNumber() );
						stack.AddDrop( king, king->GetSquareNumber() - 2 );
						stack.AddDrop( castlingPiece, king->GetSquareNumber() - 1 );
						stack.EndMoveAdd( 1000 );
					}
				}

				// *** H-SIDE CASTLING *** //
				castlingPiece = NULL;
				if( castlingPieceSquare1R >= 0 )
					castlingPiece = board.GetSquareContents( castlingPieceSquare1R );

				if( castlingPiece != NULL && !castlingPiece->HasMoved() )
				{
					//	special case when King and Rook are in the corner
					if( king->GetSquareNumber() == 62 )
					{
						if( !board.IsSquareAttacked( 63, 0 ) )
						{
							stack.BeginMoveAdd( Castling, 62, 63 );
							stack.AddPickUp( 62 );
							stack.AddPickUp( 63 );
							stack.AddDrop( king, 63 );
							stack.AddDrop( castlingPiece, 62 );
							stack.EndMoveAdd( 1000 );
						}
					}
					//	check to see if all squares are vacant and not attacked
					bool canCastle = true;
					for( x = king->GetSquareNumber() + 1; x < king->GetSquareNumber() + 3 && canCastle; x++ )
					{
						if( board.GetSquareContents( x ) != NULL && 
							board.GetSquareContents( x ) != castlingPiece )
							//	square is blocked; cannot castle
							canCastle = false;
						if( canCastle && board.IsSquareAttacked( x, 0 ) )
							canCastle = false;
					}
					for( ; x < castlingPiece->GetSquareNumber(); x++ )
					{
						if( board.GetSquareContents( x ) != NULL )
							//	square is blocked; cannot castle
							canCastle = false;
					}
					if( canCastle )
					{
						stack.BeginMoveAdd( Castling, king->GetSquareNumber(), king->GetSquareNumber() + 2 );
						stack.AddPickUp( king->GetSquareNumber() );
						stack.AddPickUp( castlingPiece->GetSquareNumber() );
						stack.AddDrop( king, king->GetSquareNumber() + 2 );
						stack.AddDrop( castlingPiece, king->GetSquareNumber() + 1 );
						stack.EndMoveAdd( 1000 );
					}
				}
			}
		}
	}
	// *** FLEXIBLE CASTLING *** //
	else if( castlingType == CASTLING_TYPE_FLEXIBLE )
	{
		if( board.GetCurrentPlayerNumber() == 0 )
		{
			//	white to move
			Piece *king = board.GetKing( 0 );
			if( !king->IsCaptured() && !king->HasMoved() && king->GetSquareNumber() > 1 && king->GetSquareNumber() < 6 )
			{
				Piece *leftCastlingPiece = NULL;
				Piece *rightCastlingPiece = NULL;
				//	check right castling-piece
				if( board.GetSquareContents( 7 ) != NULL &&
					!board.GetSquareContents( 7 )->HasMoved() )
					//	right castling-piece is castling-elegible
					rightCastlingPiece = board.GetSquareContents( 7 );
				//	check left castling-piece
				if( board.GetSquareContents( 0 ) != NULL &&
					!board.GetSquareContents( 0 )->HasMoved() )
					//	left castling-piece is castling-elegible
					leftCastlingPiece = board.GetSquareContents( 0 );
				Game::AddFlexibleCastlingMoves( stack, gameRecord, king, leftCastlingPiece, rightCastlingPiece );
			}
		}
		else
		{
			//	black to move
			Piece *king = board.GetKing( 1 );
			if( !king->IsCaptured() && !king->HasMoved() && king->GetSquareNumber() > 57 && king->GetSquareNumber() < 62 )
			{
				Piece *leftCastlingPiece = NULL;
				Piece *rightCastlingPiece = NULL;
				//	check right castling-piece
				if( board.GetSquareContents( 63 ) != NULL &&
					!board.GetSquareContents( 63 )->HasMoved() )
					//	right castling-piece is castling-elegible
					rightCastlingPiece = board.GetSquareContents( 63 );
				//	check left castling-piece
				if( board.GetSquareContents( 56 ) != NULL &&
					!board.GetSquareContents( 56 )->HasMoved() )
					//	left castling-piece is castling-elegible
					leftCastlingPiece = board.GetSquareContents( 56 );
				Game::AddFlexibleCastlingMoves( stack, gameRecord, king, leftCastlingPiece, rightCastlingPiece );
			}
		}
	}
	// *** FREE CASTLING *** //
	else if( castlingType == CASTLING_TYPE_FREE )
	{
		if( board.GetCurrentPlayerNumber() == 0 )
		{
			//	white to move
			Piece *king = board.GetKing( 0 );
			if( !king->IsCaptured() && !king->HasMoved() && king->GetSquareNumber() > 0 && king->GetSquareNumber() < 7 )
			{
				Piece *leftCastlingPiece = NULL;
				Piece *rightCastlingPiece = NULL;
				//	check right castling-piece
				if( board.GetSquareContents( 7 ) != NULL &&
					!board.GetSquareContents( 7 )->HasMoved() )
					//	right castling-piece is castling-elegible
					rightCastlingPiece = board.GetSquareContents( 7 );
				//	check left castling-piece
				if( board.GetSquareContents( 0 ) != NULL &&
					!board.GetSquareContents( 0 )->HasMoved() )
					//	left castling-piece is castling-elegible
					leftCastlingPiece = board.GetSquareContents( 0 );
				Game::AddFreeCastlingMoves( stack, gameRecord, king, leftCastlingPiece, rightCastlingPiece );
			}
		}
		else
		{
			//	black to move
			Piece *king = board.GetKing( 1 );
			if( !king->IsCaptured() && !king->HasMoved() && king->GetSquareNumber() > 56 && king->GetSquareNumber() < 63 )
			{
				Piece *leftCastlingPiece = NULL;
				Piece *rightCastlingPiece = NULL;
				//	check right castling-piece
				if( board.GetSquareContents( 63 ) != NULL &&
					!board.GetSquareContents( 63 )->HasMoved() )
					//	right castling-piece is castling-elegible
					rightCastlingPiece = board.GetSquareContents( 63 );
				//	check left castling-piece
				if( board.GetSquareContents( 56 ) != NULL &&
					!board.GetSquareContents( 56 )->HasMoved() )
					//	left castling-piece is castling-elegible
					leftCastlingPiece = board.GetSquareContents( 56 );
				Game::AddFreeCastlingMoves( stack, gameRecord, king, leftCastlingPiece, rightCastlingPiece );
			}
		}
	}
}

bool ChessGame::MoveBeingMade
	( MoveInfo &moveInfo,
	  GameRec &gameRecord )
{
	// *** BARE KING *** //

	if( bareKingRule )
	{
		//	a bare king is a lost game unless the player can bare the opponent's 
		//	king on the following move.  we will address this situation here.  if 
		//	the player to move has only a king, all moves are ruled illegal unless 
		//	the move is one that captures the opponent's last non-royal piece
		int nPieces = board.BB64_GetFriends( board.GetCurrentPlayerNumber() ).GetBitCount();
		if( nPieces == 1 )
		{
			//	just a king left.  if this move does not capture the 
			//	opponent's last royal piece, then it is illegal
			int nOpponentPieces = board.BB64_GetFriends( FLIP(board.GetCurrentPlayerNumber()) ).GetBitCount();
			if( gameRecord.materialCaptured == 0 || nOpponentPieces > 1 )
				return false;
		}
	}

	// *** UPDATE gameInt1 *** //

	//	gameInt1 is a 'user' field in the game records that a game can use
	//	for any purpose.  we will use it to track the forward progress of 
	//	the game, so we can determine which Phase we are in ('opening', 
	//	'midgame', or 'endgame' in our case)

	if( gameRecord.gameInt1 < 15 )
	{
		//	we are in the opening until gameInt1 reaches 15;
		//	in the opening, we increment gameInt1 for the following moves:
		//		- any capture
		//		- the first move of any piece
		//		- any pawn push to rank 5+ (code value of 4+)
		//		- in the special case of castling, add 4 to gameInt1
		if( moveInfo.type == Castling )
			gameRecord.gameInt1 += 4;
		else if( gameRecord.materialCaptured > 0 ||
			(gameRecord.pieceMoved->GetFlags() & (FLAGS_HAS_MOVED | FLAGS_HAS_MOVED_TWICE)) == FLAGS_HAS_MOVED ||
			(gameRecord.pieceMoved->IsPawn() && 
				board.ranks[gameRecord.pieceMoved->GetPlayerNumber()][gameRecord.pieceMoved->GetSquareNumber()] >= 4) )
			gameRecord.gameInt1++;
	}

	return true;
}

bool ChessGame::TestForWinLossDraw
	( int &eval )
{
	if( bareKingRule )
	{
		//	only one thing needs to be changed here.  if there are only 
		//	the two kings left, then the game is a draw.  without this 
		//	adjustment here, if bare king rules is in effect, then the 
		//	bare king of the player to move would be considered stalemated, 
		//	because he has no legal moves (caused by the MoveBeingMade() 
		//	adjustment for bare king rule)
		if( board.GetMaterial( 0 ) == 0 && 
			board.GetMaterial( 1 ) == 0 )
		{
			eval = 0;
			return true;
		}
	}
	return Game::TestForWinLossDraw( eval );
}

void ChessGame::GenerateMoves
	( int currentPlayer, 
	  MovementList &list )
{
	BitBoard64 pieces;

	// *** PAWNS *** //
	pieces = OrthodoxPawn::orthodoxPawn.GetPieces( currentPlayer ) | 
		     LamePawn::lamePawn.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.ExtractLSB();
		OrthodoxPawn::orthodoxPawn.BB64_GenerateDirectCaptures( list, currentPlayer, square );
		OrthodoxPawn::orthodoxPawn.BB64_GenerateDirectMovesNoCapture( list, currentPlayer, square );
	}
	//	handle the initial 2-step pawn move
	if( currentPlayer == 0 )
	{
		BitBoard64 firstAndSecondRankPawns = player0PawnTwoSpaceZone & 
			OrthodoxPawn::orthodoxPawn.GetPieces( 0 );
		while( firstAndSecondRankPawns )
		{
			int square = firstAndSecondRankPawns.ExtractLSB();
			if( board.GetSquareContents( square + 8 ) == NULL && 
				board.GetSquareContents( square + 16 ) == NULL )
				//	squares are open; add the two-step move
				list.AddMove( square, square + 16 );
		}
	}
	else
	{
		BitBoard64 seventhAndEigthRankPawns = player1PawnTwoSpaceZone & 
			OrthodoxPawn::orthodoxPawn.GetPieces( 1 );
		while( seventhAndEigthRankPawns )
		{
			int square = seventhAndEigthRankPawns.ExtractLSB();
			if( board.GetSquareContents( square - 8 ) == NULL && 
				board.GetSquareContents( square - 16 ) == NULL )
				//	squares are open; add the two-step move
				list.AddMove( square, square - 16 );
		}
	}

	// *** KNIGHTS *** //
	pieces = OrthodoxKnight::orthodoxKnight.GetPieces( currentPlayer ) |
		     Chancellor::chancellor.GetPieces( currentPlayer ) | 
			 Archbishop::archbishop.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.ExtractLSB();
		OrthodoxKnight::orthodoxKnight.BB64_GenerateDirectMoves( list, currentPlayer, square );
	}

	// *** ELEPHANTS *** //
	pieces = Elephant::elephant.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.ExtractLSB();
		Elephant::elephant.BB64_GenerateDirectMoves( list, currentPlayer, square );
	}

	// *** FIRZAN ** //
	pieces = Ferz::ferz.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.ExtractLSB();
		Ferz::ferz.BB64_GenerateDirectMoves( list, currentPlayer, square );
	}

	// *** ELEPHANT FERZ *** //
	pieces = ElephantFerz::elephantFerz.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.ExtractLSB();
		ElephantFerz::elephantFerz.BB64_GenerateDirectMoves( list, currentPlayer, square );
	}

	// *** KINGS *** //
	pieces = OrthodoxKing::orthodoxKing.GetPieces( currentPlayer ) | 
		     General::general.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.ExtractLSB();
		OrthodoxKing::orthodoxKing.BB64_GenerateDirectMoves( list, currentPlayer, square );
	}

	// *** ROOK sliders *** //
	BitBoard64 friends = board.bb64_friends[currentPlayer];
	pieces = OrthodoxRook::orthodoxRook.GetPieces( currentPlayer ) |  
		     OrthodoxQueen::orthodoxQueen.GetPieces( currentPlayer ) |
			 Chancellor::chancellor.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.ExtractLSB();
		BitBoard64 moves;
		moves = board.bb64_rook00attack[square * board.rook00attackWidth + 
			((board.bb64_blocker >> board.shift00[square]) & board.mask00[square])] | 
			board.bb64_rook90attack[square * board.rook90attackWidth + 
			((board.bb64_blocker90 >> board.shift90[square]) & board.mask90[square])];
		moves = moves & (~friends);
		if( moves )
			list.AddBitBoard64Moves( square, moves );
	}

	// *** BISHOP sliders *** // 
	pieces = OrthodoxBishop::orthodoxBishop.GetPieces( currentPlayer ) | 
		     OrthodoxQueen::orthodoxQueen.GetPieces( currentPlayer ) |
			 Archbishop::archbishop.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.ExtractLSB();
		BitBoard64 moves;
		moves = board.bb64_bishop45attack[square * board.bishop45attackWidth + 
			((board.bb64_blocker45 >> board.shift45[square]) & board.mask45[square])] | 
			board.bb64_bishop135attack[square * board.bishop135attackWidth + 
			((board.bb64_blocker135 >> board.shift135[square]) & board.mask135[square])];
		moves = moves & (~friends);
		if( moves )
			list.AddBitBoard64Moves( square, moves );
	}

	//	add castling moves
	AddSpecialMoves( currentPlayer, list, board.GetCurrentGameRecord(), false );
}

void ChessGame::GenerateCaptures
	( int currentPlayer, 
	  MovementList &list )
{
	BitBoard64 pieces;

	// *** PAWNS *** //
	pieces = OrthodoxPawn::orthodoxPawn.GetPieces( currentPlayer ) | 
		     LamePawn::lamePawn.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.ExtractLSB();
		OrthodoxPawn::orthodoxPawn.BB64_GenerateDirectCaptures( list, currentPlayer, square );
	}

	// *** KNIGHTS *** //
	pieces = OrthodoxKnight::orthodoxKnight.GetPieces( currentPlayer ) | 
		     Chancellor::chancellor.GetPieces( currentPlayer ) |
		     Archbishop::archbishop.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.ExtractLSB();
		OrthodoxKnight::orthodoxKnight.BB64_GenerateDirectCaptures( list, currentPlayer, square );
	}

	// *** ELEPHANTS *** //
	pieces = Elephant::elephant.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.ExtractLSB();
		Elephant::elephant.BB64_GenerateDirectCaptures( list, currentPlayer, square );
	}

	// *** FIRZAN ** //
	pieces = Ferz::ferz.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.ExtractLSB();
		Ferz::ferz.BB64_GenerateDirectCaptures( list, currentPlayer, square );
	}

	// *** ELEPHANT FERZ *** //
	pieces = ElephantFerz::elephantFerz.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.ExtractLSB();
		ElephantFerz::elephantFerz.BB64_GenerateDirectCaptures( list, currentPlayer, square );
	}

	// *** KINGS *** //
	pieces = OrthodoxKing::orthodoxKing.GetPieces( currentPlayer ) |
		     General::general.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.ExtractLSB();
		OrthodoxKing::orthodoxKing.BB64_GenerateDirectCaptures( list, currentPlayer, square );
	}

	// *** ROOK sliders *** //
	BitBoard64 enemies = board.bb64_friends[FLIP(currentPlayer)];
	pieces = OrthodoxRook::orthodoxRook.GetPieces( currentPlayer ) |  
		     OrthodoxQueen::orthodoxQueen.GetPieces( currentPlayer ) | 
		     Chancellor::chancellor.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.ExtractLSB();
		BitBoard64 moves;
		moves = board.bb64_rook00attack[square * board.rook00attackWidth + 
			((board.bb64_blocker >> board.shift00[square]) & board.mask00[square])] | 
			board.bb64_rook90attack[square * board.rook90attackWidth + 
			((board.bb64_blocker90 >> board.shift90[square]) & board.mask90[square])];
		moves = moves & enemies;
		if( moves )
			list.AddBitBoard64Captures( square, moves );
	}

	// *** BISHOP sliders *** // 
	pieces = OrthodoxBishop::orthodoxBishop.GetPieces( currentPlayer ) | 
		     OrthodoxQueen::orthodoxQueen.GetPieces( currentPlayer ) | 
		     Archbishop::archbishop.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.ExtractLSB();
		BitBoard64 moves;
		moves = board.bb64_bishop45attack[square * board.bishop45attackWidth + 
			((board.bb64_blocker45 >> board.shift45[square]) & board.mask45[square])] | 
			board.bb64_bishop135attack[square * board.bishop135attackWidth + 
			((board.bb64_blocker135 >> board.shift135[square]) & board.mask135[square])];
		moves = moves & enemies;
		if( moves )
			list.AddBitBoard64Captures( square, moves );
	}

	//	check for en-passant
	if( enPassant )
		Game::AddEnPassantMoves( list, board.GetCurrentGameRecord(), true );
}

bool ChessGame::IsSquareAttacked
	( int squareNumber, 
	  int playerNumber )
{
	BitBoard64 pieces;
	int otherPlayer = FLIP(playerNumber);

	if( !customCaptureGeneration )
		return board.IsSquareAttacked( squareNumber, playerNumber );

	// *** PAWNS *** //
	if( OrthodoxPawn::orthodoxPawn.bb64_attack[otherPlayer][squareNumber] &
		(OrthodoxPawn::orthodoxPawn.GetPieces( playerNumber ) |
		 LamePawn::lamePawn.GetPieces( playerNumber )) )
		return true;

	// *** KNIGHTS *** //
	if( OrthodoxKnight::orthodoxKnight.bb64_attack[otherPlayer][squareNumber] &
		(OrthodoxKnight::orthodoxKnight.GetPieces( playerNumber ) |
		 Chancellor::chancellor.GetPieces( playerNumber ) |
		 Archbishop::archbishop.GetPieces( playerNumber )) )
		return true;

	// *** ELEPHANTS *** //
	if( Elephant::elephant.bb64_attack[otherPlayer][squareNumber] &
		(Elephant::elephant.GetPieces( playerNumber ) | 
		 ElephantFerz::elephantFerz.GetPieces( playerNumber )) )
		return true;

	// *** FIRZAN *** //
	if( Ferz::ferz.bb64_attack[otherPlayer][squareNumber] &
		(Ferz::ferz.GetPieces( playerNumber ) |
		 ElephantFerz::elephantFerz.GetPieces( playerNumber )) )
		return true;

	// *** KINGS *** //
	if( OrthodoxKing::orthodoxKing.bb64_attack[otherPlayer][squareNumber] &
		(OrthodoxKing::orthodoxKing.GetPieces( playerNumber ) | 
		 General::general.GetPieces( playerNumber )) )
		return true;

	// *** ROOKS *** //
	pieces = OrthodoxRook::orthodoxRook.bb64_attack[otherPlayer][squareNumber] & 
		(OrthodoxRook::orthodoxRook.GetPieces( playerNumber ) | 
		 OrthodoxQueen::orthodoxQueen.GetPieces( playerNumber ) |
		 Chancellor::chancellor.GetPieces( playerNumber ));
	while( pieces )
	{
		int square = pieces.ExtractLSB();
		if( ! ((bool) (board.bb64_rays[(squareNumber * board.nSquares) + square] & 
			  board.bb64_blocker & ~BitBoard64::GetPositionBitBoard( square ))) )
			return true;
	}

	// *** BISHOPS *** //
	pieces = OrthodoxBishop::orthodoxBishop.bb64_attack[otherPlayer][squareNumber] & 
		(OrthodoxBishop::orthodoxBishop.GetPieces( playerNumber ) | 
		 OrthodoxQueen::orthodoxQueen.GetPieces( playerNumber ) |
		 Archbishop::archbishop.GetPieces( playerNumber ));
	while( pieces )
	{
		int square = pieces.ExtractLSB();
		if( ! ((bool) (board.bb64_rays[(squareNumber * board.nSquares) + square] & 
			  board.bb64_blocker & ~BitBoard64::GetPositionBitBoard( square ))) )
			return true;
	}

	return false;
}

Phase &ChessGame::AdjustEvaluation
	( int &eval,
	  PawnHash *pPawnHash )
{
	Phase *currentPhase = phases;

	if( board.GetCurrentGameRecord().gameInt1 < 15 )
	{
		// *** The OPENING *** //
		int factor = MAX(board.GetCurrentGameRecord().gameInt1 - 10, 0) * 2;
		int factor6 = 640 - (factor << 6);  //   \    
		int factor5 = 320 - (factor << 5);  //    \_  different adjustments
		int factor4 = 160 - (factor << 4);  //    /   from large to small
		int factor3 = 80 - (factor << 3);   //   / 

		// *** CASTLING *** //
		if( castlingType != CASTLING_TYPE_NONE )
		{
			if( board.GetKing( 0 )->GetFlags() & FLAGS_HAS_CASTLED )
				eval += (personality <= PERSONALITY_B ? factor5 : factor6);
			else
			{
				if( board.GetKing( 0 )->HasMoved() || 
					((board.GetSquareContents( 7 ) == NULL ||
					board.GetSquareContents( 7 )->HasMoved()) &&
					(board.GetSquareContents( 0 ) == NULL ||
					board.GetSquareContents( 0 )->HasMoved())) )
					eval -= (personality <= PERSONALITY_B ? factor4 : factor5);
			}
			if( board.GetKing( 1 )->GetFlags() & FLAGS_HAS_CASTLED )
				eval -= (personality <= PERSONALITY_B ? factor5 : factor6);
			else
			{
				if( board.GetKing( 1 )->HasMoved() || 
					((board.GetSquareContents( 63 ) == NULL ||
					board.GetSquareContents( 63 )->HasMoved()) &&
					(board.GetSquareContents( 56 ) == NULL ||
					board.GetSquareContents( 56 )->HasMoved())) )
					eval += (personality <= PERSONALITY_B ? factor4 : factor5);
			}
		}

		//	penalty for moving the same piece twice
		BitBoard64 bb = board.BB64_GetFriends( 0 );
		while( bb )
		{
			int square = bb.ExtractLSB();
			if( board.GetSquareContents( square )->HasMovedTwice() )
				eval -= (personality == PERSONALITY_C ? factor5 : factor6);
		}
		bb = board.BB64_GetFriends( 1 );
		while( bb )
		{
			int square = bb.ExtractLSB();
			if( board.GetSquareContents( square )->HasMovedTwice() )
				eval += (personality == PERSONALITY_C ? factor5 : factor6);
		}

		//	don't block the king or queen's pawns in the opening!!!
		if( personality == PERSONALITY_A )
		{
			if( board.GetSquareContents( D3 ) != NULL &&
				board.GetSquareContents( D2 ) != NULL &&
				!board.GetSquareContents( D2 )->HasMoved() )
				eval -= factor5;
			if( board.GetSquareContents( E3 ) != NULL &&
				board.GetSquareContents( E2 ) != NULL &&
				!board.GetSquareContents( E2 )->HasMoved() )
				eval -= factor5;
			if( board.GetSquareContents( D6 ) != NULL &&
				board.GetSquareContents( D7 ) != NULL &&
				!board.GetSquareContents( D7 )->HasMoved() )
				eval += factor5;
			if( board.GetSquareContents( E6 ) != NULL &&
				board.GetSquareContents( E7 ) != NULL &&
				!board.GetSquareContents( E7 )->HasMoved() )
				eval += factor5;
		}
		else
		{
			if( board.GetSquareContents( D3 ) != NULL &&
				board.GetSquareContents( D2 ) != NULL &&
				!board.GetSquareContents( D2 )->HasMoved() )
				eval -= factor6;
			if( board.GetSquareContents( E3 ) != NULL &&
				board.GetSquareContents( E2 ) != NULL &&
				!board.GetSquareContents( E2 )->HasMoved() )
				eval -= factor6;
			if( board.GetSquareContents( D6 ) != NULL &&
				board.GetSquareContents( D7 ) != NULL &&
				!board.GetSquareContents( D7 )->HasMoved() )
				eval += factor6;
			if( board.GetSquareContents( E6 ) != NULL &&
				board.GetSquareContents( E7 ) != NULL &&
				!board.GetSquareContents( E7 )->HasMoved() )
				eval += factor6;
		}
	}
	else if( board.GetNumberOfCapturedPieces() > 24 ||
		board.GetMaterial( 0 ) - board.GetPawnMaterial( 0 ) + 
		board.GetMaterial( 1 ) - board.GetPawnMaterial( 1 ) < 18000 )
		//	we are in the end-game
		currentPhase = phases + 2;
	else
		//	we are in the mid-game
		currentPhase = phases + 1;


	// *** OUTPOSTS *** //

	//	outposts are minor pieces in central squares that cannot be driven off by enemy pawns.
	//	the basic output bonus is the value of the piece's square in the 'outpost' array, times
	//	the value of the piece type's 'outpost factor' (stored in 'gameInt1'.)

	//	a posted piece that is protected by one of its own pawns is extra good, so
	//	it gets 150% of the above bonus.  a posted piece protected by two of its
	//	own pawns is really, really good, because if the posted piece is captured,
	//	the player will have a protected, passed pawn.  a posted piece that is thus
	//	protected by 2 pawns gets double the standard output bonus.

	if( usePawnStructureEvaluation )
	{
		BitBoard64 bb64 = minorPieceTypes[0][0]->GetPieces( 0 ) | 
						  minorPieceTypes[0][1]->GetPieces( 0 ) | 
						  minorPieceTypes[0][2]->GetPieces( 0 ) | 
						  minorPieceTypes[0][3]->GetPieces( 0 );
		//	loop through all player 0's minor pieces
		while( bb64 )
		{
			int square = bb64.ExtractLSB();
			Piece *minorPiece = board.GetSquareContents( square );

			int outpostBonus = board.GetPiecePostedBonus( 0, square, *(pawnPieceTypes[0]) );
			if( outpostBonus )
			{
				//	basic bonus for player 0's posted piece
				eval += outpostBonus * minorPiece->GetType().gameInt1;
				//	additional bonus if defended by pawn
				if( pawnPieceTypes[0]->GetAttackMatrix( 1, square ) & pawnPieceTypes[0]->GetPieces( 0 ) )
					eval += outpostBonus * minorPiece->GetType().gameInt1;
			}
		}
		bb64 = minorPieceTypes[1][0]->GetPieces( 1 ) | 
			   minorPieceTypes[1][1]->GetPieces( 1 ) | 
			   minorPieceTypes[1][2]->GetPieces( 1 ) | 
			   minorPieceTypes[1][3]->GetPieces( 1 );
		//	loop through all player 1's minor pieces
		while( bb64 )
		{
			int square = bb64.ExtractLSB();
			Piece *minorPiece = board.GetSquareContents( square );

			int outpostBonus = board.GetPiecePostedBonus( 1, square, *(pawnPieceTypes[1]) );
			if( outpostBonus )
			{
				//	basic bonus for player 0's posted piece
				eval -= outpostBonus * minorPiece->GetType().gameInt1;
				//	additional bonus if defended by pawn
				if( pawnPieceTypes[1]->GetAttackMatrix( 0, square ) & pawnPieceTypes[0]->GetPieces( 1 ) )
					eval -= outpostBonus * minorPiece->GetType().gameInt1;
			}
		}
	}

	// *** CASTLING PIECES (that slide north) ON OPEN and SEMI-OPEN FILE BONUS *** //

	if( castlingPiecesSlideNorth[0] && pPawnHash != NULL )
	{
		BitBoard64 castlingPieces = castlingPieceTypes[0]->GetPieces( 0 );
		while( castlingPieces )
		{
			int square = castlingPieces.ExtractLSB();
			if( pPawnHash->nPawnsPerFile[0][board.files[0][square]] == 0 )
			{
				//	file at least semi-open
				eval += 50;
				if( pPawnHash->nPawnsPerFile[1][board.files[0][square]] == 0 )
					//	fully open file
					eval += 20;
			}
		}
	}
	if( castlingPiecesSlideNorth[1] && pPawnHash != NULL )
	{
		BitBoard64 castlingPieces = castlingPieceTypes[1]->GetPieces( 1 );
		while( castlingPieces )
		{
			int square = castlingPieces.ExtractLSB();
			if( pPawnHash->nPawnsPerFile[1][board.files[0][square]] == 0 )
			{
				//	file at least semi-open
				eval -= 50;
				if( pPawnHash->nPawnsPerFile[0][board.files[0][square]] == 0 )
					//	fully open file
					eval -= 20;
			}
		}
	}

	//	TWO-BISHOPS BONUS
	BitBoard64 colorboundPieces;
	if( colorboundPieceTypes[0][1] != &NullPieceType64::nullPieceType64 )
	{
		colorboundPieces = colorboundPieceTypes[0][0]->GetPieces( 0 ) | colorboundPieceTypes[0][1]->GetPieces( 0 );
		if( colorboundPieces.GetBitCount() >= 2 && !((colorboundPieces & whiteSquares) && (colorboundPieces & blackSquares)) )
			eval -= 1000;
	}
	else
	{
		colorboundPieces = colorboundPieceTypes[0][0]->GetPieces( 0 );
		if( (colorboundPieces & whiteSquares) && (colorboundPieces & blackSquares) )
			eval += 350;
	}
	if( colorboundPieceTypes[1][1] != &NullPieceType64::nullPieceType64 )
	{
		colorboundPieces = colorboundPieceTypes[1][0]->GetPieces( 1 ) | colorboundPieceTypes[1][1]->GetPieces( 1 );
		if( colorboundPieces.GetBitCount() && !((colorboundPieces & whiteSquares) && (colorboundPieces & blackSquares)) )
			eval += 1000;
	}
	else
	{
		colorboundPieces = colorboundPieceTypes[1][0]->GetPieces( 1 );
		if( (colorboundPieces & whiteSquares) && (colorboundPieces & blackSquares) )
			eval -= 350;
	}

	//	try to keep our queens, for their viscious attack value! (ASYMMETRY)
	//	THIS HAS BEEN REMOVED.

	//	Fianchetto bishop bonus (given to Lions and War Elephants too)
	if( personality >= PERSONALITY_B )
	{
		if( board.GetKing( 0 )->GetSquareNumber() >= F1 &&
			board.GetKing( 0 )->GetSquareNumber() <= H1 &&
			board.GetSquareContents( G2 ) != NULL &&
			(board.GetSquareContents( G2 )->GetType() == OrthodoxBishop::orthodoxBishop ||
			board.GetSquareContents( G2 )->GetType() == WarElephant::warElephant ||
			board.GetSquareContents( G2 )->GetType() == Lion::lion) )
			eval += 120;
		else if( board.GetKing( 0 )->GetSquareNumber() >= A1 &&
			board.GetKing( 0 )->GetSquareNumber() <= C1 &&
			board.GetSquareContents( B2 ) != NULL &&
			(board.GetSquareContents( B2 )->GetType() == OrthodoxBishop::orthodoxBishop ||
			board.GetSquareContents( B2 )->GetType() == WarElephant::warElephant ||
			board.GetSquareContents( B2 )->GetType() == Lion::lion) )
			eval += 120;
		if( board.GetKing( 0 )->GetSquareNumber() >= F8 &&
			board.GetKing( 0 )->GetSquareNumber() <= H8 &&
			board.GetSquareContents( G7 ) != NULL &&
			(board.GetSquareContents( G7 )->GetType() == OrthodoxBishop::orthodoxBishop ||
			board.GetSquareContents( G7 )->GetType() == WarElephant::warElephant ||
			board.GetSquareContents( G7 )->GetType() == Lion::lion) )
			eval -= 120;
		else if( board.GetKing( 0 )->GetSquareNumber() >= A8 &&
			board.GetKing( 0 )->GetSquareNumber() <= C8 &&
			board.GetSquareContents( B7 ) != NULL &&
			(board.GetSquareContents( B7 )->GetType() == OrthodoxBishop::orthodoxBishop ||
			board.GetSquareContents( B7 )->GetType() == WarElephant::warElephant ||
			board.GetSquareContents( B7 )->GetType() == Lion::lion) )
			eval -= 120;
	}

	return *currentPhase;
}

int ChessGame::EnumeratePromotions
	( Piece *piece,
	  int fromSquare,
	  int toSquare,
	  PieceType **promotions,
	  bool quiescentSearch )
{
	if( quiescentSearch && queenPieceTypes[piece->GetPlayerNumber()] != &NullPieceType64::nullPieceType64 )
	{
		//	in quiescent search, we only consider promotion to Queen 
		//	(or most powerful piece - any other consideration is a waste 
		//	of time, since we do not detect checkmate or stalemate in Q.S.)
		promotions[0] = queenPieceTypes[piece->GetPlayerNumber()];
		return 1;
	}
	else
	{
		return Game::EnumeratePromotions( piece, fromSquare, toSquare, promotions, quiescentSearch );
	}
}

word32 ChessGame::AdjustPrimaryHash
	( word32 primaryHash )
{
	//	check for castling privledges
	if( castlingType != CASTLING_TYPE_NONE )
	{
		if( !board.GetKing( 0 )->HasMoved() )
		{
			if( castlingPieceSquare0L >= 0 )
			{
				Piece *castlingPiece = board.GetSquareContents( castlingPieceSquare0L );
				if( castlingPiece != NULL && !castlingPiece->HasMoved() )
					primaryHash ^= castlingHash0q;
			}
			if( castlingPieceSquare0R >= 0 )
			{
				Piece *castlingPiece = board.GetSquareContents( castlingPieceSquare0R );
				if( castlingPiece != NULL && !castlingPiece->HasMoved() )
					primaryHash ^= castlingHash0k;
			}
		}
		else if( !board.GetKing( 1 )->HasMoved() )
		{
			if( castlingPieceSquare1L >= 0 )
			{
				Piece *castlingPiece = board.GetSquareContents( castlingPieceSquare1L );
				if( castlingPiece != NULL && !castlingPiece->HasMoved() )
					primaryHash ^= castlingHash1q;
			}
			if( castlingPieceSquare1R >= 0 )
			{
				Piece *castlingPiece = board.GetSquareContents( castlingPieceSquare1R );
				if( castlingPiece != NULL && !castlingPiece->HasMoved() )
					primaryHash ^= castlingHash1k;
			}
		}
	}

	//	include hash value for en-Passant square (if any)
	if( enPassant && !derivedClassEP )
		return primaryHash ^ GetEnPassantHash( board.GetGameRecord( board.GetGamePly() - 1 ), enPassantHashMap );

	return primaryHash;
}

void ChessGame::AboutToStartThinking
	( int currentPlayer )
{
}

void ChessGame::DefaultSettings()
{
	if( !strcmp( selectedVariant->name, "Shatranj" ) )
	{
		squareColor1 = RGB(255, 255, 204);
		squareColor2 = RGB(211, 211, 126);
		squareColor3 = RGB(224, 224, 132);
		pieceColor1 = RGB(255, 255, 255);
		pieceColor2 = RGB(0, 0, 0);
		borderColor = RGB(158, 124, 52);
		boardDisplayType = BOARD_IS_UNCHECKERED;
		selectedPieceSet = PIECE_SET_OLD_WORLD;
	}
	else if( !strcmp( selectedVariant->name, "Orthodox Chess" ) )
	{
		squareColor1 = RGB(255, 255, 204);
		squareColor2 = RGB(93, 126, 126);
		LoadSquareTextureBitmaps( 0, "White Marble" );
		LoadSquareTextureBitmaps( 1, "Dark Marble" );
		pieceColor1 = RGB(255, 255, 255);
		pieceColor2 = RGB(136, 180, 183);
		borderColor = RGB(87, 98, 87);
		boardDisplayType = BOARD_IS_CHECKERED;
		selectedPieceSet = PIECE_SET_STANDARD;
	}
	else
		Game::DefaultSettings();
}

char *GetArrayForFRCByPositionNumber
	( int position )
{
	static char FEN[44];
	strcpy( FEN, "01234567/pppppppp/8/8/8/8/PPPPPPPP/01234567" );
	bool occupied[8];
	for( int x = 0; x < 8; x++ )
		occupied[x] = false;
	int positionNumber = position;
	int lightBishopSquare = positionNumber % 4;
	switch( lightBishopSquare )
	{
	  case 0:
		FEN[1] = 'b';
		FEN[36] = 'B';
		occupied[1] = true;
		break;

	  case 1:
		FEN[3] = 'b';
		FEN[38] = 'B';
		occupied[3] = true;
		break;

	  case 2:
		FEN[5] = 'b';
		FEN[40] = 'B';
		occupied[5] = true;
		break;

	  case 3:
		FEN[7] = 'b';
		FEN[42] = 'B';
		occupied[7] = true;
		break;
	}
	positionNumber = positionNumber / 4;
	int darkBishopSquare = positionNumber % 4;
	switch( darkBishopSquare )
	{
	  case 0:
		FEN[0] = 'b';
		FEN[35] = 'B';
		occupied[0] = true;
		break;

	  case 1:
		FEN[2] = 'b';
		FEN[37] = 'B';
		occupied[2] = true;
		break;

	  case 2:
		FEN[4] = 'b';
		FEN[39] = 'B';
		occupied[4] = true;
		break;

	  case 3:
		FEN[6] = 'b';
		FEN[41] = 'B';
		occupied[6] = true;
		break;
	}
	positionNumber = positionNumber / 4;
	int skip = positionNumber % 6;
	int index = 0;
	while( occupied[index] )
		index++;
	while( skip > 0 )
	{
		index++;
		skip--;
		while( occupied[index] )
			index++;
	}
	occupied[index] = true;
	FEN[index] = 'q';
	FEN[index+35] = 'Q';
	positionNumber = positionNumber / 6;
	char krnCode[6];
	switch( positionNumber )
	{
	  case 0:
		strcpy( krnCode, "nnrkr" );
		break;

	  case 1:
		strcpy( krnCode, "nrnkr" );
		break;

	  case 2:
		strcpy( krnCode, "nrknr" );
		break;

	  case 3:
		strcpy( krnCode, "nrkrn" );
		break;

	  case 4:
		strcpy( krnCode, "rnnkr" );
		break;

	  case 5:
		strcpy( krnCode, "rnknr" );
		break;

	  case 6:
		strcpy( krnCode, "rnkrn" );
		break;

	  case 7:
		strcpy( krnCode, "rknnr" );
		break;

	  case 8:
		strcpy( krnCode, "rknrn" );
		break;

	  case 9:
		strcpy( krnCode, "rkrnn" );
		break;
	}
	index = 0;
	int file = 0;
	while( true )
	{
		while( occupied[file] )
			file++;
		FEN[file] = krnCode[index];
		FEN[file+35] = (char) toupper( krnCode[index] );
		occupied[file] = true;
		index++;
		if( index == 5 )
			break;
	}
	return FEN;
}

char *GetArrayForChess256ByPositionNumber
	( int position )
{
	static char FEN[60];
	strcpy( FEN, "rnbqkbnr/" );
	//	determine Black's second-row pawns
	{
		int bitNumber = 0;
		char notation[12];
		int cursor = 0;
		while( bitNumber < 8 )
		{
			if( !(position & (1 << bitNumber)) )
			{
				notation[cursor++] = 'p';
				bitNumber++;
			}
			else
			{
				int emptySpaceCount = 1;
				bitNumber++;
				while( bitNumber < 8 && (position & (1 << bitNumber)) )
				{
					emptySpaceCount++;
					bitNumber++;
				}
				notation[cursor++] = '0' + emptySpaceCount;
			}
		}
		notation[cursor++] = '/';
		notation[cursor++] = '\0';
		//	append this text to the FEN
		strcpy( FEN + strlen( FEN ), notation );
	}
	//	determine Black's third-row pawns
	{
		int bitNumber = 0;
		char notation[12];
		int cursor = 0;
		while( bitNumber < 8 )
		{
			if( position & (1 << bitNumber) )
			{
				notation[cursor++] = 'p';
				bitNumber++;
			}
			else
			{
				int emptySpaceCount = 1;
				bitNumber++;
				while( bitNumber < 8 && !(position & (1 << bitNumber)) )
				{
					emptySpaceCount++;
					bitNumber++;
				}
				notation[cursor++] = '0' + emptySpaceCount;
			}
		}
		notation[cursor++] = '/';
		notation[cursor] = '\0';
		//	append this text to the FEN
		strcpy( FEN + strlen( FEN ), notation );
	}
	strcpy( FEN + strlen( FEN ), "8/8/" );
	//	determine White's third-row pawns
	{
		int bitNumber = 0;
		char notation[12];
		int cursor = 0;
		while( bitNumber < 8 )
		{
			if( position & (1 << bitNumber) )
			{
				notation[cursor++] = 'P';
				bitNumber++;
			}
			else
			{
				int emptySpaceCount = 1;
				bitNumber++;
				while( bitNumber < 8 && !(position & (1 << bitNumber)) )
				{
					emptySpaceCount++;
					bitNumber++;
				}
				notation[cursor++] = '0' + emptySpaceCount;
			}
		}
		notation[cursor++] = '/';
		notation[cursor] = '\0';
		//	append this text to the FEN
		strcpy( FEN + strlen( FEN ), notation );
	}
	//	determine White's second-row pawns
	{
		int bitNumber = 0;
		char notation[12];
		int cursor = 0;
		while( bitNumber < 8 )
		{
			if( !(position & (1 << bitNumber)) )
			{
				notation[cursor++] = 'P';
				bitNumber++;
			}
			else
			{
				int emptySpaceCount = 1;
				bitNumber++;
				while( bitNumber < 8 && (position & (1 << bitNumber)) )
				{
					emptySpaceCount++;
					bitNumber++;
				}
				notation[cursor++] = '0' + emptySpaceCount;
			}
		}
		notation[cursor++] = '/';
		notation[cursor++] = '\0';
		//	append this text to the FEN
		strcpy( FEN + strlen( FEN ), notation );
	}
	strcpy( FEN + strlen( FEN ), "RNBQKBNR" );
	return FEN;
}

void ChessGame::SetPersonality
	( int personality )
{
	//	call base class implementation of SetPersonality
	Game::SetPersonality( personality );

	if( personality >= PERSONALITY_C )
	{
		piecesHaveChangingValues = false;
		phases[0].SetPawnDeficiencyFactor( 12 );
		phases[1].SetPawnDeficiencyFactor( 14 );
		phases[2].SetPawnDeficiencyFactor( 20 );
	}
	else
	{
		piecesHaveChangingValues = true;
		phases[0].SetPawnDeficiencyFactor( 8 );
		phases[1].SetPawnDeficiencyFactor( 10 );
		phases[2].SetPawnDeficiencyFactor( 16 );
	}
}
