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

                                 ChessV

                   COPYRIGHT (C) 2006 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 "FalconChessGame.h"
#include "../../ChessV.h"
#include "../../PieceType.h"
#include "../../Piece.h"
#include "../../Direction.h"
#include "../../Rand.h"
#include "../../GameParameters.h"


#include "Capablanca_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


//	instances of the PieceTypes
CapablancaFalcon CapablancaFalcon::capablancaFalcon;

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


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

	//	implement 50-move draw rule (100 half-moves)
	autoDrawPeriod = 100;

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

	//	turn off null-move and futility pruning 
	//	after 30 pieces have been captured
	endgameCaptureThreshold = 30;

	//	razoring and futility pruning margins
	razorMargin = 4500;
	futilityMargin = 2700;
	extendedFutilityMargin = 3500;

	// *** 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( 0 );
	phases[0].SetMobilityFactor( 1 );
	phases[0].SetPawnDeficiencyFactor( 8 );
	phases[0].SetSquareValuesFactor( 1 );
	phases[0].SetKingSafetyFactor( 4 );
	phases[0].SetTropismFactor( 0 );

	//	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( 0 );
	phases[2].SetPawnDeficiencyFactor( 16 );
	phases[2].SetSquareValuesFactor( 1 );
	phases[2].SetKingSafetyFactor( 0 );
	phases[2].SetTropismFactor( 10 );

	// *** 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_10x8' array.
	CapablancaKnight::capablancaKnight.gameInt1 = 10;
	CapablancaFalcon::capablancaFalcon.gameInt1 = 10;
	CapablancaBishop::capablancaBishop.gameInt1 = 6;

	customMoveGeneration = true;
	customCaptureGeneration = true;

	// *** INITIALIZATION *** //
	for( int x = 0; x < 10; x++ )
	{
		secondRank.SetBit( x + 10 );
		seventhRank.SetBit( x + 60 );
	}
	for( int x = 0; x < 80; x++ )
	{
		if( (x + (x / 10)) % 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_96 );
}

void FalconChessGame::AddPlayerPieceTypes( char *gameName )
{
	//	add the piece types that each player may have
	board.AddPlayerPieceTypeBothPlayers( CapablancaRook::capablancaRook );
	board.AddPlayerPieceTypeBothPlayers( CapablancaBishop::capablancaBishop );
	board.AddPlayerPieceTypeBothPlayers( CapablancaKnight::capablancaKnight );
	board.AddPlayerPieceTypeBothPlayers( CapablancaQueen::capablancaQueen );
	board.AddPlayerPieceTypeBothPlayers( CapablancaKing::capablancaKing );
	board.AddPlayerPieceTypeBothPlayers( CapablancaPawn::capablancaPawn );
	board.AddPlayerPieceTypeBothPlayers( CapablancaFalcon::capablancaFalcon );
	//	add piece type references to the following arrays, 
	//	minorPieceTypes, etc., used for giving bonuses and 
	//	penalties in positional evaluation
	rookPieceTypes[0] = rookPieceTypes[1] = &CapablancaRook::capablancaRook;
	colorboundPieceTypes[0][0] = colorboundPieceTypes[1][0] = &CapablancaBishop::capablancaBishop;
	colorboundPieceTypes[0][1] = colorboundPieceTypes[1][1] = &NullPieceType96::nullPieceType96;
	minorPieceTypes[0][0] = minorPieceTypes[1][0] = &CapablancaKnight::capablancaKnight;
	minorPieceTypes[0][1] = minorPieceTypes[1][1] = &CapablancaBishop::capablancaBishop;
	minorPieceTypes[0][2] = minorPieceTypes[1][2] = &NullPieceType96::nullPieceType96;
	minorPieceTypes[0][3] = minorPieceTypes[1][3] = &NullPieceType96::nullPieceType96;
	majorPieceTypes[0][0] = majorPieceTypes[1][0] = &CapablancaQueen::capablancaQueen;
	majorPieceTypes[0][1] = majorPieceTypes[1][1] = &CapablancaFalcon::capablancaFalcon;
	majorPieceTypes[0][2] = majorPieceTypes[1][2] = &NullPieceType96::nullPieceType96;
	pawnPieceTypes[0] = pawnPieceTypes[1] = &CapablancaPawn::capablancaPawn;
}

// *** CHANGE RULES FOR PARTICULAR (BUILT-IN) VARIANT *** //
void FalconChessGame::ChangeRulesByVariant
	( char *gameName,
	  char *&array,
	  char *&book )
{
	//	assume for now standard castling and other rules
	castlingType = CASTLING_TYPE_FLEXIBLE;
	pawnPromotionType = PAWN_PROMOTION_TYPE_STANDARD;
	enPassant = true;

	// *** FALCON CHESS *** //
	if( stringCompNoCase( gameName, "Falcon Chess" ) )
	{
		//	place pieces
		array = "rnbfqkfbnr/pppppppppp/10/10/10/10/PPPPPPPPPP/RNBFQKFBNR";
		//	set name of opening book
		book = "openings\\FalconChess.txt";
	}
}

void FalconChessGame::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, "long" ) )
			castlingType = CASTLING_TYPE_LONG;
		else if( stringCompNoCase( castlingTypeName, "flexible" ) )
			castlingType = CASTLING_TYPE_FLEXIBLE;
		else if( stringCompNoCase( castlingTypeName, "close-rook" ) )
			castlingType = CASTLING_TYPE_CLOSE_ROOK;
		else if( stringCompNoCase( castlingTypeName, "free" ) )
			castlingType = CASTLING_TYPE_FREE;
		else
			ASSERT(FALSE);
	}
	// *** EN PASSANT *** //
	LookupBoolParameter( "en-passant", enPassant );
}

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

	if( &pieceType == pawnPieceTypes[nPlayer] )
	{
		if( newPiece->GetPlayerNumber() == 0 )
			newPiece->GetPromotionZone().AddToZone( 70, 79 );
		else
			newPiece->GetPromotionZone().AddToZone( 0, 9 );
	}

	if( !pieceType.IsPawn() && !pieceType.IsRoyal() && pieceType.GetBaseValue() <= 5000 )
		minorStartingSquares[nPlayer].SetBit( nRank * board.GetNumberOfFiles() + nFile );

	return newPiece;
}

void FalconChessGame::AddSpecialMoves
	( int currentPlayer, 
	  MovementList &stack,  
	  GameRec &gameRecord, 
	  bool quiescentSearch )
{
	// *** EN PASSANT *** //

	if( enPassant )
		Game::AddEnPassantMoves( stack, gameRecord, quiescentSearch );

	
	//	castling moves are added next; check for an early exit
	if( quiescentSearch || board.FastCheckTest() || castlingType == CASTLING_TYPE_NONE || 
		board.GetKing( currentPlayer )->IsCaptured() )
		//	return now, so we don't consider castling moves
		//	in quiescent search, or when we are in Check
		return;


	// *** CASTLING *** //

	if( castlingType == CASTLING_TYPE_STANDARD && board.GetCurrentPlayerNumber() == 0 )
	{
		//	white to move
		Piece *king = board.GetKing( 0 );
		if( !king->HasMoved() && king->GetSquareNumber() == 5 )
		{
			//	king side
			if( board.GetSquareContents( 9 ) != NULL &&
				!board.GetSquareContents( 9 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 9 ), 8, 7 );
			}
			//	queen side
			if( board.GetSquareContents( 0 ) != NULL &&
				!board.GetSquareContents( 0 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 0 ), 2, 3 );
			}
		}
		else if( !king->HasMoved() && king->GetSquareNumber() == 4 )
		{
			//	king side
			if( board.GetSquareContents( 9 ) != NULL &&
				!board.GetSquareContents( 9 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 9 ), 7, 6 );
			}
			//	queen side
			if( board.GetSquareContents( 0 ) != NULL &&
				!board.GetSquareContents( 0 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 0 ), 1, 2 );
			}
		}
	}
	else if( castlingType == CASTLING_TYPE_STANDARD && board.GetCurrentPlayerNumber() == 1 )
	{
		//	black to move
		Piece *king = board.GetKing( 1 );
		if( !king->HasMoved() && king->GetSquareNumber() == 75 )
		{
			//	king side
			if( board.GetSquareContents( 79 ) != NULL &&
				!board.GetSquareContents( 79 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 79 ), 78, 77 );
			}
			//	queen side
			if( board.GetSquareContents( 70 ) != NULL &&
				!board.GetSquareContents( 70 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 70 ), 72, 73 );
			}
		}
		else if( !king->HasMoved() && king->GetSquareNumber() == 74 )
		{
			//	king side
			if( board.GetSquareContents( 79 ) != NULL &&
				!board.GetSquareContents( 79 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 79 ), 77, 76 );
			}
			//	queen side
			if( board.GetSquareContents( 70 ) != NULL &&
				!board.GetSquareContents( 70 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 70 ), 71, 72 );
			}
		}
	}
	// *** CLOSE-ROOK CASTLING *** //
	else if( castlingType == CASTLING_TYPE_CLOSE_ROOK && board.GetCurrentPlayerNumber() == 0 )
	{
		//	white to move
		Piece *king = board.GetKing( 0 );
		if( !king->HasMoved() && king->GetSquareNumber() == 5 )
		{
			//	king side
			if( board.GetSquareContents( 8 ) != NULL &&
				!board.GetSquareContents( 8 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 8 ), 7, 6 );
			}
			//	queen side
			if( board.GetSquareContents( 1 ) != NULL &&
				!board.GetSquareContents( 1 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 1 ), 3, 4 );
			}
		}
		else if( !king->HasMoved() && king->GetSquareNumber() == 4 )
		{
			//	king side
			if( board.GetSquareContents( 8 ) != NULL &&
				!board.GetSquareContents( 8 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 8 ), 6, 5 );
			}
			//	queen side
			if( board.GetSquareContents( 1 ) != NULL &&
				!board.GetSquareContents( 1 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 8 ), 2, 3 );
			}
		}
	}
	else if( castlingType == CASTLING_TYPE_CLOSE_ROOK && board.GetCurrentPlayerNumber() == 1 )
	{
		//	white to move
		Piece *king = board.GetKing( 1 );
		if( !king->HasMoved() && king->GetSquareNumber() == 75 )
		{
			//	king side
			if( board.GetSquareContents( 78 ) != NULL &&
				!board.GetSquareContents( 78 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 78 ), 77, 76 );
			}
			//	queen side
			if( board.GetSquareContents( 71 ) != NULL &&
				!board.GetSquareContents( 71 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 71 ), 73, 74 );
			}
		}
		else if( !king->HasMoved() && king->GetSquareNumber() == 74 )
		{
			//	king side
			if( board.GetSquareContents( 78 ) != NULL &&
				!board.GetSquareContents( 78 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 78 ), 76, 75 );
			}
			//	queen side
			if( board.GetSquareContents( 71 ) != NULL &&
				!board.GetSquareContents( 71 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 71 ), 72, 73 );
			}
		}
	}
	// *** LONG CASTLING *** //
	else if( castlingType == CASTLING_TYPE_LONG && board.GetCurrentPlayerNumber() == 0 )
	{
		//	white to move
		Piece *king = board.GetKing( 0 );
		if( !king->HasMoved() && king->GetSquareNumber() == 4 )
		{
			//	king side
			if( board.GetSquareContents( 9 ) != NULL &&
				!board.GetSquareContents( 9 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 9 ), 8, 7 );
			}
			//	queen side
			if( board.GetSquareContents( 0 ) != NULL &&
				!board.GetSquareContents( 0 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 0 ), 1, 2 );
			}
		}
		else if( !king->HasMoved() && king->GetSquareNumber() == 5 )
		{
			//	king side
			if( board.GetSquareContents( 9 ) != NULL &&
				!board.GetSquareContents( 9 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 9 ), 8, 7 );
			}
			//	queen side
			if( board.GetSquareContents( 0 ) != NULL &&
				!board.GetSquareContents( 0 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 0 ), 1, 2 );
			}
		}
	}
	else if( castlingType == CASTLING_TYPE_LONG && board.GetCurrentPlayerNumber() == 1 )
	{
		//	black to move
		Piece *king = board.GetKing( 1 );
		if( !king->HasMoved() && king->GetSquareNumber() == 74 )
		{
			//	king side
			if( board.GetSquareContents( 79 ) != NULL &&
				!board.GetSquareContents( 79 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 79 ), 78, 77 );
			}
			//	queen side
			if( board.GetSquareContents( 70 ) != NULL &&
				!board.GetSquareContents( 70 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 70 ), 71, 72 );
			}
		}
		else if( !king->HasMoved() && king->GetSquareNumber() == 75 )
		{
			//	king side
			if( board.GetSquareContents( 79 ) != NULL &&
				!board.GetSquareContents( 79 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 79 ), 78, 77 );
			}
			//	queen side
			if( board.GetSquareContents( 70 ) != NULL &&
				!board.GetSquareContents( 70 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 70 ), 71, 72 );
			}
		}
	}
	// *** FLEXIBLE CASTLING *** //
	else if( castlingType == CASTLING_TYPE_FLEXIBLE )
	{
		if( board.GetCurrentPlayerNumber() == 0 )
		{
			//	white to move
			Piece *king = board.GetKing( 0 );
			if( !king->HasMoved() && king->GetSquareNumber() > 0 && king->GetSquareNumber() < 9 )
			{
				Piece *leftCastlingPiece = NULL;
				Piece *rightCastlingPiece = NULL;
				//	check right castling-piece
				if( board.GetSquareContents( 9 ) != NULL &&
					!board.GetSquareContents( 9 )->HasMoved() )
					//	right castling-piece is castling-elegible
					rightCastlingPiece = board.GetSquareContents( 9 );
				//	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->HasMoved() && king->GetSquareNumber() > 70 && king->GetSquareNumber() < 79 )
			{
				Piece *leftCastlingPiece = NULL;
				Piece *rightCastlingPiece = NULL;
				//	check right castling-piece
				if( board.GetSquareContents( 79 ) != NULL &&
					!board.GetSquareContents( 79 )->HasMoved() )
					//	right castling-piece is castling-elegible
					rightCastlingPiece = board.GetSquareContents( 79 );
				//	check left castling-piece
				if( board.GetSquareContents( 70 ) != NULL &&
					!board.GetSquareContents( 70 )->HasMoved() )
					//	left castling-piece is castling-elegible
					leftCastlingPiece = board.GetSquareContents( 70 );
				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->HasMoved() && king->GetSquareNumber() > 0 && king->GetSquareNumber() < 9 )
			{
				Piece *leftCastlingPiece = NULL;
				Piece *rightCastlingPiece = NULL;
				//	check right castling-piece
				if( board.GetSquareContents( 9 ) != NULL &&
					!board.GetSquareContents( 9 )->HasMoved() )
					//	right castling-piece is castling-elegible
					rightCastlingPiece = board.GetSquareContents( 9 );
				//	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->HasMoved() && king->GetSquareNumber() > 70 && king->GetSquareNumber() < 79 )
			{
				Piece *leftCastlingPiece = NULL;
				Piece *rightCastlingPiece = NULL;
				//	check right castling-piece
				if( board.GetSquareContents( 79 ) != NULL &&
					!board.GetSquareContents( 79 )->HasMoved() )
					//	right castling-piece is castling-elegible
					rightCastlingPiece = board.GetSquareContents( 79 );
				//	check left castling-piece
				if( board.GetSquareContents( 70 ) != NULL &&
					!board.GetSquareContents( 70 )->HasMoved() )
					//	left castling-piece is castling-elegible
					leftCastlingPiece = board.GetSquareContents( 70 );
				Game::AddFreeCastlingMoves( stack, gameRecord, king, leftCastlingPiece, rightCastlingPiece );
			}
		}
	}
}

bool FalconChessGame::MoveBeingMade
	( MoveInfo &moveInfo,
	  GameRec &gameRecord )
{
	// *** 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 3 to gameInt1
		if( moveInfo.type == Castling || 
			moveInfo.type == FlexibleCastling || 
			moveInfo.type == FreeCastling || 
			moveInfo.type == UserCastling )
			gameRecord.gameInt1 += 3;
		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++;
	}
}

bool TryStep3( square, player, dir1, dir2, dir3 )
{
	int p1 = board.GetMovementMatrix( dir1 )[square];
	if( p1 >= 0 && board.GetSquareContents( p1 ) == NULL )
	{
		int p2 = board.GetMovementMatrix( dir2 )[p1];
		if( p2 >= 0 && board.GetSquareContents( p2 ) == NULL )
		{
			int p3 = board.GetMovementMatrix( dir3 )[p2];
			if( p3 >= 0 )
			{
				if( board.GetSquareContents( p3 ) == NULL )
				{
					list.AddMove( square, p3 );
					return true;
				}
				else if( board.GetSquareContents( p3 )->GetPlayerNumber() != player )
				{
					list.AddCapture( square, p3 );
					return true;
				}
			}
		}
	}
	return false;
}
	
bool TryStep3Capture( square, player, dir1, dir2, dir3 )
{
	int p1 = board.GetMovementMatrix( dir1 )[square];
	if( p1 >= 0 && board.GetSquareContents( p1 ) == NULL )
	{
		int p2 = board.GetMovementMatrix( dir2 )[p1];
		if( p2 >= 0 && board.GetSquareContents( p2 ) == NULL )
		{
			int p3 = board.GetMovementMatrix( dir3 )[p2];
			if( p3 >= 0 )
			{
				if( board.GetSquareContents( p3 ) == NULL )
					return true;
				else if( board.GetSquareContents( p3 )->GetPlayerNumber() != player )
				{
					list.AddCapture( square, p3 );
					return true;
				}
			}
		}
	}
	return false;
}

void FalconChessGame::GenerateMoves
	( int currentPlayer, 
	  MovementList &list )
{
	BitBoard96 pieces;

	// *** PAWNS *** //
	pieces = CapablancaPawn::capablancaPawn.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.GetFirstBit();
		pieces.ClearBit( square );
		CapablancaPawn::capablancaPawn.BB96_GenerateDirectCaptures( list, currentPlayer, square );
		CapablancaPawn::capablancaPawn.BB96_GenerateDirectMovesNoCapture( list, currentPlayer, square );
	}

	//	handle the initial 2-step pawn move
	if( currentPlayer == 0 )
	{
		BitBoard96 secondRankPawns = secondRank & 
			CapablancaPawn::capablancaPawn.GetPieces( 0 );
		while( secondRankPawns )
		{
			int square = secondRankPawns.GetFirstBit();
			secondRankPawns.ClearBit( square );
			if( board.GetSquareContents( square + 10 ) == NULL && 
				board.GetSquareContents( square + 20 ) == NULL )
				//	squares are open; add the two-step move
				list.AddMove( square, square + 20 );
		}
	}
	else
	{
		BitBoard96 seventhRankPawns = seventhRank & 
			CapablancaPawn::capablancaPawn.GetPieces( 1 );
		while( seventhRankPawns )
		{
			int square = seventhRankPawns.GetFirstBit();
			seventhRankPawns.ClearBit( square );
			if( board.GetSquareContents( square - 10 ) == NULL && 
				board.GetSquareContents( square - 20 ) == NULL )
				//	squares are open; add the two-step move
				list.AddMove( square, square - 20 );
		}
	}

	// *** KNIGHTS *** //
	pieces = CapablancaKnight::capablancaKnight.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.GetFirstBit();
		pieces.ClearBit( square );
		CapablancaKnight::capablancaKnight.BB96_GenerateDirectMoves( list, currentPlayer, square );
	}

	// *** KINGS *** //
	pieces = CapablancaKing::capablancaKing.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.GetFirstBit();
		pieces.ClearBit( square );
		CapablancaKing::capablancaKing.BB96_GenerateDirectMoves( list, currentPlayer, square );
	}

	// *** ROOK sliders *** //
	BitBoard96 friends = board.bb96_friends[currentPlayer];
	pieces = CapablancaRook::capablancaRook.GetPieces( currentPlayer ) |  
		CapablancaQueen::capablancaQueen.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.GetFirstBit();
		pieces.ToggleBit( square );

		BitBoard96 moves;
		moves = board.bb96_rook00attack[square * board.rook00attackWidth + 
			((board.bb96_blocker >> board.shift00[square]) & board.mask00[square])] | 
			board.bb96_rook90attack[square * board.rook90attackWidth + 
			((board.bb96_blocker90 >> board.shift90[square]) & board.mask90[square])];
		moves = moves & (~friends);
		if( moves )
			list.AddBitBoard96Moves( square, moves );
	}

	// *** BISHOP sliders *** // 
	pieces = CapablancaBishop::capablancaBishop.GetPieces( currentPlayer ) | 
		CapablancaQueen::capablancaQueen.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.GetFirstBit();
		pieces.ToggleBit( square );

		BitBoard96 moves;
		moves = board.bb96_bishop45attack[square * board.bishop45attackWidth + 
			((board.bb96_blocker45 >> board.shift45[square]) & board.mask45[square])] | 
			board.bb96_bishop135attack[square * board.bishop135attackWidth + 
			((board.bb96_blocker135 >> board.shift135[square]) & board.mask135[square])];
		moves = moves & (~friends);
		if( moves )
			list.AddBitBoard96Moves( square, moves );
	}

	// *** FALCONS *** //
	pieces = CapablancaFalcon::capablancaFalcon.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.GetFirstBit();
		pieces.ToggleBit( square );

		if( !TryStep3( square, currentPlayer, DIRECTION_N, DIRECTION_N, DIRECTION_NE ) )
		{
			if( !TryStep3( square, currentPlayer, DIRECTION_N, DIRECTION_NE, DIRECTION_N ) )
			{
				TryStep3( square, currentPlayer, DIRECTION_NE, DIRECTION_N, DIRECTION_N );
			}
		}
		if( !TryStep3( square, currentPlayer, DIRECTION_N, DIRECTION_N, DIRECTION_NW ) )
		{
			if( !TryStep3( square, currentPlayer, DIRECTION_N, DIRECTION_NW, DIRECTION_N ) )
			{
				TryStep3( square, currentPlayer, DIRECTION_NW, DIRECTION_N, DIRECTION_N );
			}
		}
		if( !TryStep3( square, currentPlayer, DIRECTION_S, DIRECTION_S, DIRECTION_SE ) )
		{
			if( !TryStep3( square, currentPlayer, DIRECTION_S, DIRECTION_SE, DIRECTION_S ) )
			{
				TryStep3( square, currentPlayer, DIRECTION_SE, DIRECTION_S, DIRECTION_S );
			}
		}
		if( !TryStep3( square, currentPlayer, DIRECTION_S, DIRECTION_S, DIRECTION_SW ) )
		{
			if( !TryStep3( square, currentPlayer, DIRECTION_S, DIRECTION_SW, DIRECTION_S ) )
			{
				TryStep3( square, currentPlayer, DIRECTION_SW, DIRECTION_S, DIRECTION_S );
			}
		}
		if( !TryStep3( square, currentPlayer, DIRECTION_E, DIRECTION_E, DIRECTION_NE ) )
		{
			if( !TryStep3( square, currentPlayer, DIRECTION_E, DIRECTION_NE, DIRECTION_E ) )
			{
				TryStep3( square, currentPlayer, DIRECTION_NE, DIRECTION_E, DIRECTION_E );
			}
		}
		if( !TryStep3( square, currentPlayer, DIRECTION_W, DIRECTION_W, DIRECTION_NW ) )
		{
			if( !TryStep3( square, currentPlayer, DIRECTION_W, DIRECTION_NW, DIRECTION_W ) )
			{
				TryStep3( square, currentPlayer, DIRECTION_NW, DIRECTION_W, DIRECTION_W );
			}
		}
		if( !TryStep3( square, currentPlayer, DIRECTION_E, DIRECTION_E, DIRECTION_SE ) )
		{
			if( !TryStep3( square, currentPlayer, DIRECTION_E, DIRECTION_SE, DIRECTION_E ) )
			{
				TryStep3( square, currentPlayer, DIRECTION_SE, DIRECTION_E, DIRECTION_E );
			}
		}
		if( !TryStep3( square, currentPlayer, DIRECTION_W, DIRECTION_W, DIRECTION_SW ) )
		{
			if( !TryStep3( square, currentPlayer, DIRECTION_W, DIRECTION_SW, DIRECTION_W ) )
			{
				TryStep3( square, currentPlayer, DIRECTION_SW, DIRECTION_W, DIRECTION_W );
			}
		}
	}

	//	check for en-passant
	if( enPassant )
		AddSpecialMoves( currentPlayer, list, board.GetCurrentGameRecord(), false );
}

void FalconChessGame::GenerateCaptures
	( int currentPlayer, 
	  MovementList &list )
{
	BitBoard96 pieces;

	// *** PAWNS *** //
	pieces = CapablancaPawn::capablancaPawn.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.GetFirstBit();
		pieces.ClearBit( square );
		CapablancaPawn::capablancaPawn.BB96_GenerateDirectCaptures( list, currentPlayer, square );
	}

	// *** KNIGHTS *** //
	pieces = CapablancaKnight::capablancaKnight.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.GetFirstBit();
		pieces.ClearBit( square );
		CapablancaKnight::capablancaKnight.BB96_GenerateDirectCaptures( list, currentPlayer, square );
	}

	// *** KINGS *** //
	pieces = CapablancaKing::capablancaKing.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.GetFirstBit();
		pieces.ClearBit( square );
		CapablancaKing::capablancaKing.BB96_GenerateDirectCaptures( list, currentPlayer, square );
	}

	// *** ROOK sliders *** //
	BitBoard96 enemies = board.bb96_friends[FLIP(currentPlayer)];
	pieces = CapablancaRook::capablancaRook.GetPieces( currentPlayer ) |  
		CapablancaQueen::capablancaQueen.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.GetFirstBit();
		pieces.ToggleBit( square );

		BitBoard96 moves;
		moves = board.bb96_rook00attack[square * board.rook00attackWidth + 
			((board.bb96_blocker >> board.shift00[square]) & board.mask00[square])] | 
			board.bb96_rook90attack[square * board.rook90attackWidth + 
			((board.bb96_blocker90 >> board.shift90[square]) & board.mask90[square])];
		moves = moves & enemies;
		if( moves )
			list.AddBitBoard96Captures( square, moves );
	}

	// *** BISHOP sliders *** // 
	pieces = CapablancaBishop::capablancaBishop.GetPieces( currentPlayer ) | 
		CapablancaQueen::capablancaQueen.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.GetFirstBit();
		pieces.ToggleBit( square );

		BitBoard96 moves;
		moves = board.bb96_bishop45attack[square * board.bishop45attackWidth + 
			((board.bb96_blocker45 >> board.shift45[square]) & board.mask45[square])] | 
			board.bb96_bishop135attack[square * board.bishop135attackWidth + 
			((board.bb96_blocker135 >> board.shift135[square]) & board.mask135[square])];
		moves = moves & enemies;
		if( moves )
			list.AddBitBoard96Captures( square, moves );
	}


	// *** FALCONS *** //
	pieces = CapablancaFalcon::capablancaFalcon.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.GetFirstBit();
		pieces.ToggleBit( square );

		if( !TryStep3Capture( square, currentPlayer, DIRECTION_N, DIRECTION_N, DIRECTION_NE ) )
		{
			if( !TryStep3Capture( square, currentPlayer, DIRECTION_N, DIRECTION_NE, DIRECTION_N ) )
			{
				TryStep3Capture( square, currentPlayer, DIRECTION_NE, DIRECTION_N, DIRECTION_N );
			}
		}
		if( !TryStep3Capture( square, currentPlayer, DIRECTION_N, DIRECTION_N, DIRECTION_NW ) )
		{
			if( !TryStep3Capture( square, currentPlayer, DIRECTION_N, DIRECTION_NW, DIRECTION_N ) )
			{
				TryStep3Capture( square, currentPlayer, DIRECTION_NW, DIRECTION_N, DIRECTION_N );
			}
		}
		if( !TryStep3Capture( square, currentPlayer, DIRECTION_S, DIRECTION_S, DIRECTION_SE ) )
		{
			if( !TryStep3Capture( square, currentPlayer, DIRECTION_S, DIRECTION_SE, DIRECTION_S ) )
			{
				TryStep3Capture( square, currentPlayer, DIRECTION_SE, DIRECTION_S, DIRECTION_S );
			}
		}
		if( !TryStep3Capture( square, currentPlayer, DIRECTION_S, DIRECTION_S, DIRECTION_SW ) )
		{
			if( !TryStep3Capture( square, currentPlayer, DIRECTION_S, DIRECTION_SW, DIRECTION_S ) )
			{
				TryStep3Capture( square, currentPlayer, DIRECTION_SW, DIRECTION_S, DIRECTION_S );
			}
		}
		if( !TryStep3Capture( square, currentPlayer, DIRECTION_E, DIRECTION_E, DIRECTION_NE ) )
		{
			if( !TryStep3Capture( square, currentPlayer, DIRECTION_E, DIRECTION_NE, DIRECTION_E ) )
			{
				TryStep3Capture( square, currentPlayer, DIRECTION_NE, DIRECTION_E, DIRECTION_E );
			}
		}
		if( !TryStep3Capture( square, currentPlayer, DIRECTION_W, DIRECTION_W, DIRECTION_NW ) )
		{
			if( !TryStep3Capture( square, currentPlayer, DIRECTION_W, DIRECTION_NW, DIRECTION_W ) )
			{
				TryStep3Capture( square, currentPlayer, DIRECTION_NW, DIRECTION_W, DIRECTION_W );
			}
		}
		if( !TryStep3Capture( square, currentPlayer, DIRECTION_E, DIRECTION_E, DIRECTION_SE ) )
		{
			if( !TryStep3Capture( square, currentPlayer, DIRECTION_E, DIRECTION_SE, DIRECTION_E ) )
			{
				TryStep3Capture( square, currentPlayer, DIRECTION_SE, DIRECTION_E, DIRECTION_E );
			}
		}
		if( !TryStep3Capture( square, currentPlayer, DIRECTION_W, DIRECTION_W, DIRECTION_SW ) )
		{
			if( !TryStep3Capture( square, currentPlayer, DIRECTION_W, DIRECTION_SW, DIRECTION_W ) )
			{
				TryStep3Capture( square, currentPlayer, DIRECTION_SW, DIRECTION_W, DIRECTION_W );
			}
		}
	}

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

bool FalconChessGame::IsSquareAttacked
	( int squareNumber, 
	  int playerNumber )
{
	//	hand off to the Board class if we are playing a variant 
	//	that does not have bitboard support for capture detection
	if( !customCaptureGeneration )
		return board.IsSquareAttacked( squareNumber, playerNumber );

	BitBoard96 pieces;
	int otherPlayer = FLIP(playerNumber);

	// *** PAWNS *** //
	if( CapablancaPawn::capablancaPawn.bb96_attack[otherPlayer][squareNumber] &
		CapablancaPawn::capablancaPawn.GetPieces( playerNumber ) )
		return true;

	// *** KNIGHTS *** //
	if( CapablancaKnight::capablancaKnight.bb96_attack[otherPlayer][squareNumber] &
		CapablancaKnight::capablancaKnight.GetPieces( playerNumber ) )
		return true;

	// *** KINGS *** //
	if( CapablancaKing::capablancaKing.bb96_attack[otherPlayer][squareNumber] &
		CapablancaKing::capablancaKing.GetPieces( playerNumber ) )
		return true;

	// *** ROOKS *** //
	pieces = CapablancaRook::capablancaRook.bb96_attack[otherPlayer][squareNumber] & 
		(CapablancaRook::capablancaRook.GetPieces( playerNumber ) | 
		 CapablancaQueen::capablancaQueen.GetPieces( playerNumber ));
	while( pieces )
	{
		int square = pieces.GetFirstBit();
		if( ! ((bool) (board.bb96_rays[(squareNumber * board.GetNumberOfSquares()) + square] & 
			  board.bb96_blocker & ~BitBoard96::GetPositionBitBoard( square ))) )
			return true;
		pieces.ClearBit( square );
	}

	// *** BISHOPS *** //
	pieces = CapablancaBishop::capablancaBishop.bb96_attack[otherPlayer][squareNumber] & 
		(CapablancaBishop::capablancaBishop.GetPieces( playerNumber ) | 
		 CapablancaQueen::capablancaQueen.GetPieces( playerNumber ));
	while( pieces )
	{
		int square = pieces.GetFirstBit();
		if( ! ((bool) (board.bb96_rays[(squareNumber * board.GetNumberOfSquares()) + square] & 
			  board.bb96_blocker & ~BitBoard96::GetPositionBitBoard( square ))) )
			return true;
		pieces.ClearBit( square );
	}

	return false;
}

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

	if( board.GetCurrentGameRecord().gameInt1 < 25 )
	{
		// *** The OPENING *** //

		//	these opening adjustments are made until gameInt1 reaches 25;
		//	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 3 to gameInt1

		//	in the opening we consider the following things:
		//		- give a bonus for castling; give a penalty for losing the ability to castle
		//		- give a bonus for developing minor pieces, penalty for moving major pieces early
		//		- penalize any piece for moving twice, with a bigger penalty for moving three times

		//	use this "factor" to scale down the adjustments to be applied here, 
		//	so that the adjustments become smaller and smaller as we leave the 
		//	opening and enter the mid-game
		int factor = MAX(board.GetCurrentGameRecord().gameInt1 - 15, 0);
		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 adjustment *** //
		if( castlingType != CASTLING_TYPE_NONE )
		{
			//	if we are playing Paulowich's variant, we need to 
			//	adjust the castling squares of the rooks
			int adjustment = 0;
			if( castlingType == CASTLING_TYPE_CLOSE_ROOK )
				adjustment = 1;

			// *** CASTLING bonus/penalty *** //
			if( board.GetKing( 0 )->GetFlags() & FLAGS_HAS_CASTLED )
				eval += factor6;
			else
			{
				if( board.GetKing( 0 )->HasMoved() || 
					((board.GetSquareContents( 9 - adjustment ) == NULL ||
					  board.GetSquareContents( 9 - adjustment )->HasMoved()) &&
					 (board.GetSquareContents( 0 + adjustment ) == NULL ||
					  board.GetSquareContents( 0 + adjustment )->HasMoved())) )
					eval -= factor5;
			}
			if( board.GetKing( 1 )->GetFlags() & FLAGS_HAS_CASTLED )
				eval -= factor6;
			else
			{
				if( board.GetKing( 1 )->HasMoved() || 
					((board.GetSquareContents( 79 - adjustment ) == NULL ||
					  board.GetSquareContents( 79 - adjustment )->HasMoved()) &&
					 (board.GetSquareContents( 70 + adjustment ) == NULL ||
					  board.GetSquareContents( 70 + adjustment )->HasMoved())) )
					eval += factor5;
			}
		}

		//	give a significant bonus for developing minor pieces
		BitBoard96 minors;
		minors = minorStartingSquares[0] & board.BB96_GetFriends( 0 );
		eval -= (factor6 * minors.GetBitCount());
		minors = minorStartingSquares[1] & board.BB96_GetFriends( 1 );
		eval += (factor6 * minors.GetBitCount());

		//	give a penalty for the Queen or Chancellor moving early
		if( board.GetRootCurrentPlayerNumber() == 0 )
		{
		BitBoard96 majors;
		majors = majorPieceTypes[0][0]->GetPieces( 0 ) | 
			     majorPieceTypes[0][1]->GetPieces( 0 );
		while( majors )
		{
			int square = majors.GetFirstBit();
			majors.ToggleBit( square );
			if( board.GetSquareContents( square )->GetFlags() & FLAGS_HAS_MOVED )
				eval -= factor5;
		}
		majors = majorPieceTypes[1][0]->GetPieces( 1 ) | 
			     majorPieceTypes[1][1]->GetPieces( 1 );
		while( majors )
		{
			int square = majors.GetFirstBit();
			majors.ToggleBit( square );
			if( board.GetSquareContents( square )->GetFlags() & FLAGS_HAS_MOVED )
				eval += factor5;
		}
		}

		//	don't block the king's or queen's pawns in the opening!!!
		if( board.GetSquareContents( 24 ) != NULL &&
			board.GetSquareContents( 14 ) != NULL &&
			!board.GetSquareContents( 14 )->HasMoved() )
			eval -= factor6;
		if( board.GetSquareContents( 25 ) != NULL &&
			board.GetSquareContents( 15 ) != NULL &&
			!board.GetSquareContents( 15 )->HasMoved() )
			eval -= factor6;
		if( board.GetSquareContents( 54 ) != NULL &&
			board.GetSquareContents( 64 ) != NULL &&
			!board.GetSquareContents( 64 )->HasMoved() )
			eval += factor6;
		if( board.GetSquareContents( 55 ) != NULL &&
			board.GetSquareContents( 65 ) != NULL &&
			!board.GetSquareContents( 65 )->HasMoved() )
			eval += factor6;
	}

	//	determine if we are in the mid-game or endgame (rather than the opening)
	if( board.GetNumberOfCapturedPieces() > 28 ||
		board.GetMaterial( 0 ) - board.GetPawnMaterial( 0 ) + 
		board.GetMaterial( 1 ) - board.GetPawnMaterial( 1 ) < 24000 )
		//	we are in the end-game
		currentPhase = phases + 2;
	else
		currentPhase = phases + 1;


	if( pPawnHash != NULL && currentPhase != phases )
	{
		// *** 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.

		//	loop through all minor pieces
		BitBoard96 minors;
		minors = minorPieceTypes[0][0]->GetPieces( 0 ) | 
				 minorPieceTypes[0][1]->GetPieces( 0 ) | 
				 minorPieceTypes[0][2]->GetPieces( 0 ) | 
				 minorPieceTypes[0][3]->GetPieces( 0 );
		while( minors )
		{
			int square = minors.GetFirstBit();
			minors.ToggleBit( square );
			Piece *piece = board.GetSquareContents( square );
			if( outpost_10x8[square] > 0 && piece->GetType().gameInt1 > 0 &&
				((int) (pPawnHash->nPawnsPerFile[1][board.files[0][square]-1]) == 0 ||
				(int) (pPawnHash->backPawnRank[1][board.files[0][square]-1]) <= board.ranks[0][square]) &&
				((int) (pPawnHash->nPawnsPerFile[1][board.files[0][square]+1]) == 0 ||
				(int) (pPawnHash->backPawnRank[1][board.files[0][square]+1]) <= board.ranks[0][square]) )
			{
				//	basic bonus for player 0's posted piece
				eval += outpost_10x8[square] * piece->GetType().gameInt1;
				int pawnSquare1 = board.GetMovementMatrix( DIRECTION_SE )[square];
				int pawnSquare2 = board.GetMovementMatrix( DIRECTION_SW )[square];
				if( board.GetSquareContents( pawnSquare1 ) != NULL &&
					board.GetSquareContents( pawnSquare1 )->GetPlayerNumber() == 0 && 
					board.GetSquareContents( pawnSquare1 )->GetType().IsPawn() )
					//	additional 50% bonus for this pawn defender
					eval += (outpost_10x8[square] * piece->GetType().gameInt1) >> 1;
				if( board.GetSquareContents( pawnSquare2 ) != NULL &&
					board.GetSquareContents( pawnSquare2 )->GetPlayerNumber() == 0 && 
					board.GetSquareContents( pawnSquare2 )->GetType().IsPawn() )
					//	additional 50% bonus for this pawn defender
					eval += (outpost_10x8[square] * piece->GetType().gameInt1) >> 1;
			}
		}
		minors = minorPieceTypes[1][0]->GetPieces( 1 ) | 
				 minorPieceTypes[1][1]->GetPieces( 1 ) | 
				 minorPieceTypes[1][2]->GetPieces( 1 ) | 
				 minorPieceTypes[1][3]->GetPieces( 1 );
		while( minors )
		{
			int square = minors.GetFirstBit();
			minors.ToggleBit( square );
			Piece *piece = board.GetSquareContents( square );
			if( outpost_10x8[board.flipSquare[1][square]] > 0 && piece->GetType().gameInt1 > 0 &&
				((int) (pPawnHash->nPawnsPerFile[0][board.files[0][square]-1]) == 0 ||
				(int) (pPawnHash->backPawnRank[0][board.files[0][square]-1]) <= board.ranks[0][square]) &&
				((int) (pPawnHash->nPawnsPerFile[0][board.files[0][square]+1]) == 0 ||
				(int) (pPawnHash->backPawnRank[0][board.files[0][square]+1]) <= board.ranks[0][square]) )
			{
				//	basic bonus for player 1's posted piece
				eval -= outpost_10x8[board.flipSquare[1][square]] * piece->GetType().gameInt1;
				int pawnSquare1 = board.GetMovementMatrix( DIRECTION_SE )[square];
				int pawnSquare2 = board.GetMovementMatrix( DIRECTION_SW )[square];
				if( board.GetSquareContents( pawnSquare1 ) != NULL && 
					board.GetSquareContents( pawnSquare1 )->GetPlayerNumber() == 1 && 
					board.GetSquareContents( pawnSquare1 )->GetType().IsPawn() )
					//	additional 50% bonus for this pawn defender
					eval -= (outpost_10x8[board.flipSquare[1][square]] * piece->GetType().gameInt1) >> 1;
				if( board.GetSquareContents( pawnSquare2 ) != NULL &&
					board.GetSquareContents( pawnSquare2 )->GetPlayerNumber() == 1 && 
					board.GetSquareContents( pawnSquare2 )->GetType().IsPawn() )
					//	additional 50% bonus for this pawn defender
					eval -= (outpost_10x8[board.flipSquare[1][square]] * piece->GetType().gameInt1) >> 1;
			}
		}

		// *** ROOK ON OPEN and SEMI-OPEN FILE BONUS *** //
		BitBoard96 rooks;
		rooks = rookPieceTypes[0]->GetPieces( 0 );
		while( rooks )
		{
			int square = rooks.GetFirstBit();
			rooks.ToggleBit( square );
			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;
			}
		}
		rooks = rookPieceTypes[1]->GetPieces( 1 );
		while( rooks )
		{
			int square = rooks.GetFirstBit();
			rooks.ToggleBit( square );
			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
	BitBoard96 colorboundPieces;
	colorboundPieces = colorboundPieceTypes[0][0]->GetPieces( 0 ) | colorboundPieceTypes[0][1]->GetPieces( 0 );
	if( (colorboundPieces & whiteSquares) && (colorboundPieces & blackSquares) )
		eval += 150;
	colorboundPieces = colorboundPieceTypes[1][0]->GetPieces( 1 ) | colorboundPieceTypes[1][1]->GetPieces( 1 );
	if( (colorboundPieces & whiteSquares) && (colorboundPieces & blackSquares) )
		eval -= 150;

	return *currentPhase;
}

word32 FalconChessGame::AdjustPrimaryHash
	( word32 primaryHash )
{
	// *** adjust for castling privledges *** //

	if( castlingType == CASTLING_TYPE_CLOSE_ROOK )
	{
		if( !board.GetKing( 0 )->HasMoved() )
		{
			Piece *castlingPiece = board.GetSquareContents( 1 );
			if( castlingPiece != NULL && 
				!castlingPiece->HasMoved() )
				primaryHash ^= castlingHash0q;
			castlingPiece = board.GetSquareContents( 8 );
			if( castlingPiece != NULL && 
				!castlingPiece->HasMoved() && 
				&(castlingPiece->GetType()) == rookPieceTypes[0] )
				primaryHash ^= castlingHash0k;
		}
		else if( !board.GetKing( 1 )->HasMoved() )
		{
			Piece *castlingPiece = board.GetSquareContents( 71 );
			if( castlingPiece != NULL && 
				!castlingPiece->HasMoved() )
				primaryHash ^= castlingHash1q;
			castlingPiece = board.GetSquareContents( 78 );
			if( castlingPiece != NULL && 
				!castlingPiece->HasMoved() && 
				&(castlingPiece->GetType()) == rookPieceTypes[1] )
				primaryHash ^= castlingHash1k;
		}
	}
	else if( castlingType != CASTLING_TYPE_NONE )
	{
		if( !board.GetKing( 0 )->HasMoved() )
		{
			Piece *castlingPiece = board.GetSquareContents( 0 );
			if( castlingPiece != NULL && 
				!castlingPiece->HasMoved() )
				primaryHash ^= castlingHash0q;
			castlingPiece = board.GetSquareContents( 9 );
			if( castlingPiece != NULL && 
				!castlingPiece->HasMoved() )
				primaryHash ^= castlingHash0k;
		}
		else if( !board.GetKing( 1 )->HasMoved() )
		{
			Piece *castlingPiece = board.GetSquareContents( 70 );
			if( castlingPiece != NULL && 
				!castlingPiece->HasMoved() )
				primaryHash ^= castlingHash1q;
			castlingPiece = board.GetSquareContents( 79 );
			if( castlingPiece != NULL && 
				!castlingPiece->HasMoved() )
				primaryHash ^= castlingHash1k;
		}
	}
	
	// *** adjust for en passant square *** //
	if( enPassant )
		return primaryHash ^ GetEnPassantHash( board.GetCurrentGameRecord(), enPassantHashMap );
	return primaryHash;
}
