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

                                 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 "CapablancaGame.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
CapablancaKing CapablancaKing::capablancaKing;
CapablancaPawn CapablancaPawn::capablancaPawn;
CapablancaKnight CapablancaKnight::capablancaKnight;
CapablancaBishop CapablancaBishop::capablancaBishop;
CapablancaRook CapablancaRook::capablancaRook;
CapablancaQueen CapablancaQueen::capablancaQueen;
CapablancaArchbishop CapablancaArchbishop::capablancaArchbishop;
CapablancaChancellor CapablancaChancellor::capablancaChancellor;
CapablancaLamePawn CapablancaLamePawn::capablancaLamePawn;
CapablancaGeneral CapablancaGeneral::capablancaGeneral;
CapablancaElephantFerz CapablancaElephantFerz::capablancaElephantFerz;
CapablancaWoodyRook CapablancaWoodyRook::capablancaWoodyRook;
CapablancaMinister CapablancaMinister::capablancaMinister;
CapablancaHighPriestess CapablancaHighPriestess::capablancaHighPriestess;
CapablancaLion CapablancaLion::capablancaLion;
CapablancaSage CapablancaSage::capablancaSage;
CapablancaTower CapablancaTower::capablancaTower;
CapablancaDragonKing CapablancaDragonKing::capablancaDragonKing;
CapablancaDragonHorse CapablancaDragonHorse::capablancaDragonHorse;
CapablancaWildebeest CapablancaWildebeest::capablancaWildebeest;
CapablancaUnicorn CapablancaUnicorn::capablancaUnicorn;
CapablancaKnightGeneral CapablancaKnightGeneral::capablancaKnightGeneral;


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

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

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

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

CapablancaGame::CapablancaGame( Board &board, Player &whitePlayer, Player &blackPlayer ):
	Game(board, whitePlayer, blackPlayer),
	enPassant(true),
	bareKingRule(false),
	greatShatranj(false),
	extendedPieces(false)
{
	// ***************************************** //
	// ***                                   *** //
	// ***  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 = 9500;
	futilityMargin = 3700;
	extendedFutilityMargin = 6500;

	// *** 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( 12 );
	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( 16 );
	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( 20 );
	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;
	CapablancaBishop::capablancaBishop.gameInt1 = 7;
	CapablancaWoodyRook::capablancaWoodyRook.gameInt1 = 7;
	CapablancaGeneral::capablancaGeneral.gameInt1 = 8;
	CapablancaElephantFerz::capablancaElephantFerz.gameInt1 = 9;
	CapablancaLion::capablancaLion.gameInt1 = 8;

	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 CapablancaGame::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( CapablancaChancellor::capablancaChancellor );
	board.AddPlayerPieceTypeBothPlayers( CapablancaArchbishop::capablancaArchbishop );
	//	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] = &CapablancaChancellor::capablancaChancellor;
	majorPieceTypes[0][2] = majorPieceTypes[1][2] = &CapablancaArchbishop::capablancaArchbishop;
	pawnPieceTypes[0] = pawnPieceTypes[1] = &CapablancaPawn::capablancaPawn;
}

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

	// *** CAPABLANCA CHESS *** //
	if( stringCompNoCase( gameName, "Capablanca Chess" ) )
	{
		//	place pieces
		array = "rnabqkbcnr/pppppppppp/10/10/10/10/PPPPPPPPPP/RNABQKBCNR";
		//	set name of opening book
		book = "openings\\CapablancaChess.txt";
	}
	// *** JANUS CHESS *** //
	else if( stringCompNoCase( gameName, "Janus Chess" ) )
	{
		//	implement rule changes
		castlingType = CASTLING_TYPE_LONG;
		//	change name of Archbishop to Janus
		CapablancaArchbishop::capablancaArchbishop.SetFullName( "Janus" );
		CapablancaArchbishop::capablancaArchbishop.SetNotation( "J" );
		//	no Chancellor in this game
		majorPieceTypes[0][1] = majorPieceTypes[1][1] = &NullPieceType96::nullPieceType96;
		board.RemovePieceType( CapablancaChancellor::capablancaChancellor );
		//	place pieces
		array = "rjnbkqbnjr/pppppppppp/10/10/10/10/PPPPPPPPPP/RJNBKQBNJR";
		//	set name of opening book
		book = "openings\\JanusChess.txt";
	}
	// *** NEW CHANCELLOR CHESS *** //
	else if( stringCompNoCase( gameName, "New Chancellor Chess" ) )
	{
		//	implement rule changes
		castlingType = CASTLING_TYPE_CLOSE_ROOK;
		//	no Archbishop in this game
		majorPieceTypes[0][2] = majorPieceTypes[1][2] = &NullPieceType96::nullPieceType96;
		board.RemovePieceType( CapablancaArchbishop::capablancaArchbishop );
		//	place pieces
		array = "crnbqkbnrc/pppppppppp/10/10/10/10/PPPPPPPPPP/CRNBQKBNRC";
		//	set name of opening book
		book = "openings\\NewChancellorChess.txt";
	}
	// *** ABERG'S VARIANT *** //
	else if( stringCompNoCase( gameName, "Capablanca Chess, Aberg variant" ) )
	{
		castlingType = CASTLING_TYPE_FREE;
		//	place pieces
		array = "ranbqkbncr/pppppppppp/10/10/10/10/PPPPPPPPPP/RANBQKBNCR";
		//	set name of opening book
		book = "openings\\AbergCapablancaChess.txt";
	}
	// *** PAULOWICH'S VARIANT *** //
	else if( stringCompNoCase( gameName, "Capablanca Chess, Paulowich variant" ) )
	{
		//	implement rule changes
		castlingType = CASTLING_TYPE_CLOSE_ROOK;
		pawnPromotionType = PAWN_PROMOTION_TYPE_MAJORS;
		//	place pieces
		array = "crnbakbnrq/pppppppppp/10/10/10/10/PPPPPPPPPP/CRNBAKBNRQ";
		//	set name of opening book
		book = "openings\\PaulowichCapablancaChess.txt";
	}
	// *** CARRERA'S CHESS *** //
	else if( stringCompNoCase( gameName, "Carrera's Chess" ) )
	{
		castlingType = CASTLING_TYPE_NONE;
		CapablancaArchbishop::capablancaArchbishop.SetFullName( "Centaur" );
		CapablancaArchbishop::capablancaArchbishop.SetNotation( "E" );
		CapablancaChancellor::capablancaChancellor.SetFullName( "Champion" );
		CapablancaChancellor::capablancaChancellor.SetNotation( "C" );
		//	change pawn promotion rule
		pawnPromotionType = PAWN_PROMOTION_TYPE_MAJORS;
		//	place pieces
		array = "rcnbkqbner/pppppppppp/10/10/10/10/PPPPPPPPPP/RCNBKQBNER";
		//	set name of opening book
		book = "openings\\CarrerasChess.txt";
	}
	// *** BIRD'S CHESS *** //
	else if( stringCompNoCase( gameName, "Bird's Chess" ) )
	{
		//	change name or pieces
		CapablancaArchbishop::capablancaArchbishop.SetFullName( "Equerry" );
		CapablancaArchbishop::capablancaArchbishop.SetNotation( "E" );
		CapablancaChancellor::capablancaChancellor.SetFullName( "Guard" );
		CapablancaChancellor::capablancaChancellor.SetNotation( "G" );
		//	place pieces
		array = "rnbgqkebnr/pppppppppp/10/10/10/10/PPPPPPPPPP/RNBGQKEBNR";
		//	set name of opening book
		book = "openings\\BirdsChess.txt";
	}
	// *** GROTESQUE CHESS *** //
	else if( stringCompNoCase( gameName, "Grotesque Chess" ) )
	{
		//	implement rule changes
		castlingType = CASTLING_TYPE_FLEXIBLE;
		//	change name or pieces
		CapablancaArchbishop::capablancaArchbishop.SetFullName( "Equerry" );
		CapablancaArchbishop::capablancaArchbishop.SetNotation( "E" );
		CapablancaChancellor::capablancaChancellor.SetFullName( "Guard" );
		CapablancaChancellor::capablancaChancellor.SetNotation( "G" );
		//	place pieces
		array = "rbqnkgnebr/pppppppppp/10/10/10/10/PPPPPPPPPP/RBQNKGNEBR";
		//	set name of opening book
		book = "openings\\GrotesqueChess.txt";
	}
	// *** LADOREAN CHESS *** //
	else if( stringCompNoCase( gameName, "Ladorean Chess" ) )
	{
		//	implement rule changes
		castlingType = CASTLING_TYPE_FLEXIBLE;
		//	change name of pieces
		CapablancaArchbishop::capablancaArchbishop.SetFullName( "Cardinal" );
		CapablancaArchbishop::capablancaArchbishop.SetNotation( "C" );
		CapablancaChancellor::capablancaChancellor.SetFullName( "Marshall" );
		CapablancaChancellor::capablancaChancellor.SetNotation( "M" );
		//	place pieces
		array = "rbqnkcnmbr/pppppppppp/10/10/10/10/PPPPPPPPPP/RBQNKCNMBR";
		//	set name of opening book
		book = "openings\\LadoreanChess.txt";
	}
	// *** EMBASSY CHESS *** //
	else if( stringCompNoCase( gameName, "Embassy Chess" ) )
	{
		//	change name of pieces
		CapablancaArchbishop::capablancaArchbishop.SetFullName( "Cardinal" );
		CapablancaArchbishop::capablancaArchbishop.SetNotation( "C" );
		CapablancaChancellor::capablancaChancellor.SetFullName( "Marshall" );
		CapablancaChancellor::capablancaChancellor.SetNotation( "M" );
		//	place pieces
		array = "rnbqkmcbnr/pppppppppp/10/10/10/10/PPPPPPPPPP/RNBQKMCBNR";
		//	set name of opening book
		book = "openings\\EmbassyChess.txt";
	}
	// *** UNIVERS CHESS *** //
	else if( stringCompNoCase( gameName, "Univers Chess" ) )
	{
		//	implement rule changes
		castlingType = CASTLING_TYPE_FLEXIBLE;
		//	change name of pieces
		CapablancaArchbishop::capablancaArchbishop.SetFullName( "Paladin" );
		CapablancaArchbishop::capablancaArchbishop.SetNotation( "A" );
		CapablancaChancellor::capablancaChancellor.SetFullName( "Marshall" );
		CapablancaChancellor::capablancaChancellor.SetNotation( "M" );
		//	place pieces
		array = "rbnmqkanbr/pppppppppp/10/10/10/10/PPPPPPPPPP/RBNMQKANBR";
		//	set name of opening book
		book = "openings\\UniversChess.txt";
	}
	// *** SCHOOLBOOK CHESS *** //
	else if( stringCompNoCase( gameName, "Schoolbook Chess" ) )
	{
		//	implement rule changes
		castlingType = CASTLING_TYPE_FLEXIBLE;
		//	change name of Chancellor
		CapablancaChancellor::capablancaChancellor.SetFullName( "Marshall" );
		CapablancaChancellor::capablancaChancellor.SetNotation( "M" );
		//	place pieces
		array = "rqnbakbnmr/pppppppppp/10/10/10/10/PPPPPPPPPP/RQNBAKBNMR";
		//	set name of opening book
		book = "openings\\SchoolbookChess.txt";
	}
	// *** OPTI CHESS *** //
	else if( stringCompNoCase( gameName, "Opti Chess (mirror I)" ) )
	{
		//	implement rule changes
		castlingType = CASTLING_TYPE_USER_CASTLING_1;
		//	place pieces
		array = "nrcbqkbarn/pppppppppp/10/10/10/10/PPPPPPPPPP/NRCBQKBARN";
		//	set name of opening book
		book = "openings\\OptiChessI.txt";
	}
	// *** LIONS AND UNICORNS CHESS *** //
	else if( stringCompNoCase( gameName, "Lions and Unicorns Chess" ) )
	{
		//	implement rule changes
		castlingType = CASTLING_TYPE_CLOSE_ROOK;
		pawnPromotionType = PAWN_PROMOTION_TYPE_MAJORS;
		//	Unicorn instead of Archbishop
		majorPieceTypes[0][2] = majorPieceTypes[1][2] = &CapablancaUnicorn::capablancaUnicorn;
		board.AddPlayerPieceTypeBothPlayers( CapablancaUnicorn::capablancaUnicorn );
		board.RemovePieceType( CapablancaArchbishop::capablancaArchbishop );
		//	add new piece type (the Lion)
		board.AddPlayerPieceTypeBothPlayers( CapablancaLion::capablancaLion );
		minorPieceTypes[0][2] = minorPieceTypes[1][2] = &CapablancaLion::capablancaLion;
		//	place pieces
		array = "lrcbqkburl/nppppppppn/10/10/10/10/NPPPPPPPPN/LRCBQKBURL";
		//	set name of opening book
		book = "openings\\LionsAndUnicorns.txt";
	}
	// *** LION'S CHESS *** //
	else if( stringCompNoCase( gameName, "Lion's Chess" ) )
	{
		//	add new piece type (the Lion)
		board.AddPlayerPieceTypeBothPlayers( CapablancaLion::capablancaLion );
		minorPieceTypes[0][2] = minorPieceTypes[1][2] = &CapablancaLion::capablancaLion;
		//	remove Archbishop and Chancellor
		board.RemovePieceType( CapablancaArchbishop::capablancaArchbishop );
		board.RemovePieceType( CapablancaChancellor::capablancaChancellor );
		majorPieceTypes[0][1] = majorPieceTypes[1][1] = &NullPieceType96::nullPieceType96;
		majorPieceTypes[0][2] = majorPieceTypes[1][2] = &NullPieceType96::nullPieceType96;
		//	place pieces
		array = "rlbnqknblr/pppppppppp/10/10/10/10/PPPPPPPPPP/RLBNQKNBLR";
		//	set name of opening book
		book = "openings\\LionsChess.txt";
	}
	// *** ROYAL COURT *** //
	else if( stringCompNoCase( gameName, "Royal Court" ) )
	{
		//	remove all unused piece types
		board.RemovePieceType( CapablancaChancellor::capablancaChancellor );
		board.RemovePieceType( CapablancaArchbishop::capablancaArchbishop );
		majorPieceTypes[0][1] = majorPieceTypes[1][1] = &NullPieceType96::nullPieceType96;
		majorPieceTypes[0][2] = majorPieceTypes[1][2] = &NullPieceType96::nullPieceType96;
		//	add Crowned Knight
		minorPieceTypes[0][2] = minorPieceTypes[1][2] = &CapablancaKnightGeneral::capablancaKnightGeneral;
		board.AddPlayerPieceTypeBothPlayers( CapablancaKnightGeneral::capablancaKnightGeneral );
		CapablancaKnightGeneral::capablancaKnightGeneral.SetFullName( "Crowned Knight" );
		CapablancaKnightGeneral::capablancaKnightGeneral.SetNotation( "C" );
		//	place pieces
		array = "rcnbqkbncr/pppppppppp/10/10/10/10/PPPPPPPPPP/RCNBQKBNCR";
		//	set name of opening book
		book = "openings\\RoyalCourt.txt";
	}
	// *** GREAT SHATRANJ *** //
	else if( stringCompNoCase( gameName, "Great Shatranj" ) )
	{
		//	lookup which variant we are playing
		char *variant = "D";
		LookupStringParameter( "variant", variant );
		//	implement rule changes
		castlingType = CASTLING_TYPE_NONE;
		bareKingRule = true;
		greatShatranj = true;
		//	remove all unused piece types
		board.RemovePieceType( CapablancaChancellor::capablancaChancellor );
		board.RemovePieceType( CapablancaArchbishop::capablancaArchbishop );
		board.RemovePieceType( CapablancaQueen::capablancaQueen );
		board.RemovePieceType( CapablancaBishop::capablancaBishop );
		majorPieceTypes[0][2] = majorPieceTypes[1][2] = &NullPieceType96::nullPieceType96;
		if( variant[0] == 'D' )
		{
			board.RemovePieceType( CapablancaRook::capablancaRook );
			rookPieceTypes[0] = rookPieceTypes[1] = &NullPieceType96::nullPieceType96;
		}
		//	pawn is lame
		enPassant = false;
		pawnPieceTypes[0] = pawnPieceTypes[1] = &CapablancaLamePawn::capablancaLamePawn;
		board.RemovePieceType( CapablancaPawn::capablancaPawn );
		board.AddPlayerPieceTypeBothPlayers( CapablancaLamePawn::capablancaLamePawn );
		//	change pawn promotion
		CapablancaLamePawn::capablancaLamePawn.SetPromotionType( PromoteByReplacementOrToVariableTypes );
		//	rook is more valuable
		CapablancaRook::capablancaRook.SetBaseValue( 5000 );
		//	add new piece types
		board.AddPlayerPieceTypeBothPlayers( CapablancaGeneral::capablancaGeneral );
		board.AddPlayerPieceTypeBothPlayers( CapablancaMinister::capablancaMinister );
		board.AddPlayerPieceTypeBothPlayers( CapablancaHighPriestess::capablancaHighPriestess );
		board.AddPlayerPieceTypeBothPlayers( CapablancaElephantFerz::capablancaElephantFerz );
		majorPieceTypes[0][0] = majorPieceTypes[1][0] = &CapablancaMinister::capablancaMinister;
		majorPieceTypes[0][1] = majorPieceTypes[1][1] = &CapablancaHighPriestess::capablancaHighPriestess;
		if( variant[0] == 'D' )
			board.AddPlayerPieceTypeBothPlayers( CapablancaWoodyRook::capablancaWoodyRook );
		//	adjust minor piece types
		minorPieceTypes[0][1] = minorPieceTypes[1][1] = &CapablancaElephantFerz::capablancaElephantFerz;
		minorPieceTypes[0][2] = minorPieceTypes[1][2] = &CapablancaGeneral::capablancaGeneral;
		if( variant[0] == 'D' )
			minorPieceTypes[0][3] = minorPieceTypes[1][3] = &CapablancaWoodyRook::capablancaWoodyRook;
		//	change piece names
		CapablancaWoodyRook::capablancaWoodyRook.SetFullName( "Dabbabah" );
		CapablancaWoodyRook::capablancaWoodyRook.SetNotation( "D" );
		//	place pieces
		if( variant[0] == 'R' )
			array = "rnegkmhenr/pppppppppp/10/10/10/10/PPPPPPPPPP/RNEGKMHENR";
		else
			array = "dnegkmhend/pppppppppp/10/10/10/10/PPPPPPPPPP/DNEGKMHEND";
		//	set name of opening book
		if( variant[0] == 'D' )
			book = "openings\\GreatShatranjD.txt";
		else
			book = "openings\\GreatShatranjR.txt";
	}
}

void CapablancaGame::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);
	}
	// *** PAWN PROMOTION TYPE *** //
	char *pawnPromotionTypeName;
	if( !stringCompNoCase( gameName, "Great Shatranj" ) )
	{
		//	can't change pawn promotion in Great Shatranj
		if( LookupStringParameter( "pawn-promotion-type", pawnPromotionTypeName ) )
		{
			if( stringCompNoCase( pawnPromotionTypeName, "standard" ) )
				pawnPromotionType = PAWN_PROMOTION_TYPE_STANDARD;
			else if( stringCompNoCase( pawnPromotionTypeName, "majors" ) )
				pawnPromotionType = PAWN_PROMOTION_TYPE_MAJORS;
			else if( stringCompNoCase( pawnPromotionTypeName, "queen" ) )
				pawnPromotionType = PAWN_PROMOTION_TYPE_QUEEN;
		}
	}
	// *** EN PASSANT *** //
	LookupBoolParameter( "en-passant", enPassant );
	// *** BARE KING *** //
	LookupBoolParameter( "bare-king", bareKingRule );
}

void CapablancaGame::InitializationComplete( char *gameName )
{
	//	initialize bitboards for detecting posted pieces
	board.InitializeOutpost( outpost_10x8 );

	//	interate through all piece types included in 
	//	this game to determine if bitboard support is 
	//	possible, and whether extended pieces are used
	PieceType **types = board.GetPieceTypes();
	int count = board.GetPieceTypeCount();
	for( int x = 0; x < count; x++ )
	{
		PieceType *type = types[x];
		if( type == &CapablancaPawn::capablancaPawn || 
			type == &CapablancaLamePawn::capablancaLamePawn || 
			type == &CapablancaKing::capablancaKing || 
			type == &CapablancaRook::capablancaRook ||
			type == &CapablancaKnight::capablancaKnight || 
			type == &CapablancaBishop::capablancaBishop ||
			type == &CapablancaQueen::capablancaQueen || 
			type == &CapablancaChancellor::capablancaChancellor || 
			type == &CapablancaArchbishop::capablancaArchbishop )
			//	these types are fully supported
			continue;
		if( type == &CapablancaMinister::capablancaMinister || 
			type == &CapablancaHighPriestess::capablancaHighPriestess )
			//	these types are supported with extended support enabled
			extendedPieces = true;
		else
		{
			//	this is a type that is not supported
			customMoveGeneration = false;
			customCaptureGeneration = false;
		}
	}
}

bool CapablancaGame::RemovePieceType
	( PieceType *pieceType )
{
	for( int player = 0; player < 2; player++ )
	{
		if( rookPieceTypes[player] == pieceType )
			rookPieceTypes[player] = &NullPieceType96::nullPieceType96;
		if( pawnPieceTypes[player] == pieceType )
			pawnPieceTypes[player] = &NullPieceType96::nullPieceType96;
		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] = &NullPieceType96::nullPieceType96;
			}
			if( x < 3 )
			{
				if( majorPieceTypes[player][x] == pieceType )
				{
					for( int y = x; y < 2; y++ )
						majorPieceTypes[player][y] = majorPieceTypes[player][y+1];
					majorPieceTypes[player][2] = &NullPieceType96::nullPieceType96;
				}
			}
			if( x < 2 )
			{
				if( colorboundPieceTypes[player][x] == pieceType )
				{
					if( x == 0 )
						colorboundPieceTypes[player][0] = colorboundPieceTypes[player][1];
					colorboundPieceTypes[player][1] = &NullPieceType96::nullPieceType96;
				}
			}
		}
	}
	return( true );
}

bool CapablancaGame::AddPieceType
	( PieceType *pieceType,
	  int nPlayer )
{
	if( pieceType->IsPawn() )
	{
		if( pawnPieceTypes[nPlayer] == &NullPieceType96::nullPieceType96 )
			pawnPieceTypes[nPlayer] = (PieceType96 *) pieceType;
		else
			return false;
	}
	if( pieceType->GetBaseValue() >= 5500 )
	{
		if( majorPieceTypes[nPlayer][0] == &NullPieceType96::nullPieceType96 )
			majorPieceTypes[nPlayer][0] = (PieceType96 *) pieceType;
		else
		{
			if( majorPieceTypes[nPlayer][1] == &NullPieceType96::nullPieceType96 )
				majorPieceTypes[nPlayer][1] = (PieceType96 *) pieceType;
			else
			{
				if( majorPieceTypes[nPlayer][2] == &NullPieceType96::nullPieceType96 )
					majorPieceTypes[nPlayer][2] = (PieceType96 *) pieceType;
			}
		}
	}
	else if( pieceType->GetBaseValue() <= 4000 )
	{
		if( minorPieceTypes[nPlayer][0] == &NullPieceType96::nullPieceType96 )
			minorPieceTypes[nPlayer][0] = (PieceType96 *) pieceType;
		else
		{
			if( minorPieceTypes[nPlayer][1] == &NullPieceType96::nullPieceType96 )
				minorPieceTypes[nPlayer][1] = (PieceType96 *) pieceType;
			else
			{
				if( minorPieceTypes[nPlayer][2] == &NullPieceType96::nullPieceType96 )
					minorPieceTypes[nPlayer][2] = (PieceType96 *) pieceType;
				else
				{
					if( minorPieceTypes[nPlayer][3] == &NullPieceType96::nullPieceType96 )
						minorPieceTypes[nPlayer][3] = (PieceType96 *) pieceType;
				}
			}
		}
	}
	return true;
}

Piece *CapablancaGame::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 CapablancaGame::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 );
			}
		}
	}
	// *** USER CASTLING *** //
	else if( castlingType == CASTLING_TYPE_USER_CASTLING_1 && 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 ), 8, 7 );
			}
			//	queen side
			if( board.GetSquareContents( 1 ) != NULL &&
				!board.GetSquareContents( 1 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 1 ), 1, 2 );
			}
		}
		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 ), 8, 7 );
			}
			//	queen side
			if( board.GetSquareContents( 1 ) != NULL &&
				!board.GetSquareContents( 1 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 1 ), 1, 2 );
			}
		}
	}
	else if( castlingType == CASTLING_TYPE_USER_CASTLING_1 && board.GetCurrentPlayerNumber() == 1 )
	{
		//	black 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 ), 78, 77 );
			}
			//	queen side
			if( board.GetSquareContents( 71 ) != NULL &&
				!board.GetSquareContents( 71 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 71 ), 71, 72 );
			}
		}
		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 ), 78, 77 );
			}
			//	queen side
			if( board.GetSquareContents( 71 ) != NULL &&
				!board.GetSquareContents( 71 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 71 ), 71, 72 );
			}
		}
	}
}

bool CapablancaGame::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.BB96_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.BB96_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 < 25 )
	{
		//	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++;
	}

	if( !greatShatranj )
		return true;

	// *** UPDATE gameInt2 *** //

	//	the gameInt2 user field is used in this game to keep track 
	//	of which pieces have been promoted by replacement.  this game 
	//	has a special rule that a player can only promote by replacement 
	//	to an elephant once in a game, to a rook once in a game, and to	
	//	a knight once in a game, once to minister or high priestess

	#define WHITE_ROOK_PROMOTION         1
	#define WHITE_KNIGHT_PROMOTION	     2
	#define WHITE_ELEPHANT_PROMOTION	 4
	#define WHITE_MINISTER_PROMOTION     8
	#define BLACK_ROOK_PROMOTION        16
	#define BLACK_KNIGHT_PROMOTION      32
	#define BLACK_ELEPHANT_PROMOTION    64
	#define BLACK_MINISTER_PROMOTION   128

	if( moveInfo.type == Replacement || 
		moveInfo.type == CaptureWithReplacement )
	{
		if( moveInfo.pPieceMoved->GetPlayerNumber() == 0 )
		{
			if( (moveInfo.promotion) == &CapablancaRook::capablancaRook )
			{
				if( gameRecord.gameInt2 & WHITE_ROOK_PROMOTION )
					//	already promoted to a rook once, therefore move is illegal 
					return false;
				gameRecord.gameInt2 |= WHITE_ROOK_PROMOTION;
			}
			else if( (moveInfo.promotion) == &CapablancaKnight::capablancaKnight )
			{
				if( gameRecord.gameInt2 & WHITE_KNIGHT_PROMOTION )
					//	already promoted to a knight once, therefore move is illegal 
					return false;
				gameRecord.gameInt2 |= WHITE_KNIGHT_PROMOTION;
			}
			else if( (moveInfo.promotion) == &CapablancaElephantFerz::capablancaElephantFerz )
			{
				if( gameRecord.gameInt2 & WHITE_ELEPHANT_PROMOTION )
					//	already promoted to an elephant once, therefore move is illegal 
					return false;
				//	make sure this doesn't result in another Elephant on the same color
				if( (CapablancaElephantFerz::capablancaElephantFerz.GetPieces( 0 ) &
					 whiteSquares).GetBitCount() > 1 )
					return false;
				if( (CapablancaElephantFerz::capablancaElephantFerz.GetPieces( 0 ) &
					 blackSquares).GetBitCount() > 1 )
					return false;
				gameRecord.gameInt2 |= WHITE_ELEPHANT_PROMOTION;
			}
			else if( (moveInfo.promotion) == &CapablancaMinister::capablancaMinister )
			{
				if( gameRecord.gameInt2 & WHITE_MINISTER_PROMOTION )
					//	already promoted to a minister or high priestess, therefore move is illegal 
					return false;
				gameRecord.gameInt2 |= WHITE_MINISTER_PROMOTION;
			}
			else if( (moveInfo.promotion) == &CapablancaHighPriestess::capablancaHighPriestess )
			{
				if( gameRecord.gameInt2 & WHITE_MINISTER_PROMOTION )
					//	already promoted to a minister or high priestess, therefore move is illegal 
					return false;
				gameRecord.gameInt2 |= WHITE_MINISTER_PROMOTION;
			}
		}
		else
		{
			if( (moveInfo.promotion) == &CapablancaRook::capablancaRook )
			{
				if( gameRecord.gameInt2 & BLACK_ROOK_PROMOTION )
					//	already promoted to a rook once, therefore move is illegal 
					return false;
				gameRecord.gameInt2 |= BLACK_ROOK_PROMOTION;
			}
			else if( (moveInfo.promotion) == &CapablancaKnight::capablancaKnight )
			{
				if( gameRecord.gameInt2 & BLACK_KNIGHT_PROMOTION )
					//	already promoted to a knight once, therefore move is illegal 
					return false;
				gameRecord.gameInt2 |= BLACK_KNIGHT_PROMOTION;
			}
			else if( (moveInfo.promotion) == &CapablancaElephantFerz::capablancaElephantFerz )
			{
				if( gameRecord.gameInt2 & BLACK_ELEPHANT_PROMOTION )
					//	already promoted to an elephant once, therefore move is illegal 
					return false;
				//	make sure this doesn't result in another Elephant on the same color
				if( (CapablancaElephantFerz::capablancaElephantFerz.GetPieces( 1 ) &
					 whiteSquares).GetBitCount() > 1 )
					return false;
				if( (CapablancaElephantFerz::capablancaElephantFerz.GetPieces( 1 ) &
					 blackSquares).GetBitCount() > 1 )
					return false;
				gameRecord.gameInt2 |= BLACK_ELEPHANT_PROMOTION;
			}
			else if( (moveInfo.promotion) == &CapablancaMinister::capablancaMinister )
			{
				if( gameRecord.gameInt2 & BLACK_MINISTER_PROMOTION )
					//	already promoted to a minister or high priestess, therefore move is illegal 
					return false;
				gameRecord.gameInt2 |= BLACK_MINISTER_PROMOTION;
			}
			else if( (moveInfo.promotion) == &CapablancaHighPriestess::capablancaHighPriestess )
			{
				if( gameRecord.gameInt2 & BLACK_MINISTER_PROMOTION )
					//	already promoted to a minister or high priestess, therefore move is illegal 
					return false;
				gameRecord.gameInt2 |= BLACK_MINISTER_PROMOTION;
			}
		}
	}

	return true;
}

bool CapablancaGame::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 CapablancaGame::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 );
	}
	pieces = CapablancaLamePawn::capablancaLamePawn.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.GetFirstBit();
		pieces.ClearBit( square );
		CapablancaLamePawn::capablancaLamePawn.BB96_GenerateDirectCaptures( list, currentPlayer, square );
		CapablancaLamePawn::capablancaLamePawn.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 ) | 
		CapablancaChancellor::capablancaChancellor.GetPieces( currentPlayer ) | 
		CapablancaArchbishop::capablancaArchbishop.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 ) | 
		CapablancaChancellor::capablancaChancellor.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 ) | 
		CapablancaArchbishop::capablancaArchbishop.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 );
	}

	if( extendedPieces )
	{
		// *** MINISTERS *** //
		pieces = CapablancaMinister::capablancaMinister.GetPieces( currentPlayer );
		while( pieces )
		{
			int square = pieces.GetFirstBit();
			pieces.ClearBit( square );
			CapablancaMinister::capablancaMinister.BB96_GenerateDirectMoves( list, currentPlayer, square );
		}
		// *** HIGH PRIESTESSES *** //
		pieces = CapablancaHighPriestess::capablancaHighPriestess.GetPieces( currentPlayer );
		while( pieces )
		{
			int square = pieces.GetFirstBit();
			pieces.ClearBit( square );
			CapablancaHighPriestess::capablancaHighPriestess.BB96_GenerateDirectMoves( list, currentPlayer, square );
		}
	}

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

void CapablancaGame::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 );
	}
	pieces = CapablancaLamePawn::capablancaLamePawn.GetPieces( currentPlayer );
	while( pieces )
	{
		int square = pieces.GetFirstBit();
		pieces.ClearBit( square );
		CapablancaLamePawn::capablancaLamePawn.BB96_GenerateDirectCaptures( list, currentPlayer, square );
	}

	// *** KNIGHTS *** //
	pieces = CapablancaKnight::capablancaKnight.GetPieces( currentPlayer ) | 
		CapablancaChancellor::capablancaChancellor.GetPieces( currentPlayer ) | 
		CapablancaArchbishop::capablancaArchbishop.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 ) | 
		CapablancaChancellor::capablancaChancellor.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 ) | 
		CapablancaArchbishop::capablancaArchbishop.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 );
	}

	if( extendedPieces )
	{
		// *** MINISTERS *** //
		pieces = CapablancaMinister::capablancaMinister.GetPieces( currentPlayer );
		while( pieces )
		{
			int square = pieces.GetFirstBit();
			pieces.ClearBit( square );
			CapablancaMinister::capablancaMinister.BB96_GenerateDirectCaptures( list, currentPlayer, square );
		}
		// *** HIGH PRIESTESSES *** //
		pieces = CapablancaHighPriestess::capablancaHighPriestess.GetPieces( currentPlayer );
		while( pieces )
		{
			int square = pieces.GetFirstBit();
			pieces.ClearBit( square );
			CapablancaHighPriestess::capablancaHighPriestess.BB96_GenerateDirectCaptures( list, currentPlayer, square );
		}
	}

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

bool CapablancaGame::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;
	if( CapablancaLamePawn::capablancaLamePawn.bb96_attack[otherPlayer][squareNumber] &
		CapablancaLamePawn::capablancaLamePawn.GetPieces( playerNumber ) )
		return true;

	// *** KNIGHTS *** //
	if( CapablancaKnight::capablancaKnight.bb96_attack[otherPlayer][squareNumber] &
		(CapablancaKnight::capablancaKnight.GetPieces( playerNumber ) | 
		 CapablancaChancellor::capablancaChancellor.GetPieces( playerNumber ) | 
		 CapablancaArchbishop::capablancaArchbishop.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 ) | 
		 CapablancaChancellor::capablancaChancellor.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 ) | 
		 CapablancaArchbishop::capablancaArchbishop.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 );
	}

	if( extendedPieces )
	{
		// *** MINISTERS *** //
		if( CapablancaMinister::capablancaMinister.bb96_attack[otherPlayer][squareNumber] &
			CapablancaMinister::capablancaMinister.GetPieces( playerNumber ) )
			return true;

		// *** HIGH PRIESTESSES *** //
		if( CapablancaHighPriestess::capablancaHighPriestess.bb96_attack[otherPlayer][squareNumber] &
			CapablancaHighPriestess::capablancaHighPriestess.GetPieces( playerNumber ) )
			return true;
	}

	return false;
}

Phase &CapablancaGame::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 -= (personality >= PERSONALITY_C ? factor6 : 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 += (personality >= PERSONALITY_C ? factor6 : factor5);
			}
		}

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

		//	don't block the center 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;
		if( board.GetSquareContents( 23 ) != NULL &&
			board.GetSquareContents( 13 ) != NULL &&
			!board.GetSquareContents( 13 )->HasMoved() )
			eval -= factor5;
		if( board.GetSquareContents( 26 ) != NULL &&
			board.GetSquareContents( 16 ) != NULL &&
			!board.GetSquareContents( 16 )->HasMoved() )
			eval -= factor5;
		if( board.GetSquareContents( 53 ) != NULL &&
			board.GetSquareContents( 63 ) != NULL &&
			!board.GetSquareContents( 63 )->HasMoved() )
			eval += factor5;
		if( board.GetSquareContents( 56 ) != NULL &&
			board.GetSquareContents( 66 ) != NULL &&
			!board.GetSquareContents( 66 )->HasMoved() )
			eval += factor5;
	}

	//	we are not in the opening phase - 
	//	determine if the phase is the mid-game or endgame
	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 *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;
			}
		}
		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 *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;
			}
		}

		// *** 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 += 40 + (12 * personality);
				if( pPawnHash->nPawnsPerFile[1][board.files[0][square]] == 0 )
					//	fully open file
					eval += 20 + (5 * personality);
			}
		}
		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 -= 40 + (12 * personality);
				if( pPawnHash->nPawnsPerFile[0][board.files[0][square]] == 0 )
					//	fully open file
					eval -= 20 + (5 * personality);
			}
		}
	}

	//	TWO-BISHOPS BONUS
	BitBoard96 colorboundPieces;
	colorboundPieces = colorboundPieceTypes[0][0]->GetPieces( 0 ) | colorboundPieceTypes[0][1]->GetPieces( 0 );
	if( (colorboundPieces & whiteSquares) && (colorboundPieces & blackSquares) )
		eval += 100 + (50 * personality);
	colorboundPieces = colorboundPieceTypes[1][0]->GetPieces( 1 ) | colorboundPieceTypes[1][1]->GetPieces( 1 );
	if( (colorboundPieces & whiteSquares) && (colorboundPieces & blackSquares) )
		eval -= 100 + (50 * personality);

	return *currentPhase;
}

word32 CapablancaGame::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;
}

int CapablancaGame::EnumeratePromotions
	( Piece *piece, 
	  int fromSquare,
	  int toSquare,
	  PieceType **promotions,
	  bool quiescentSearch )
{
	// *** GREAT SHATRANJ *** //
	if( greatShatranj )
	{
		promotions[0] = &CapablancaGeneral::capablancaGeneral;
		return 1;
	}
	// *** MAJORS pawn promotion *** //
	if( pawnPromotionType == PAWN_PROMOTION_TYPE_MAJORS )
	{
		//	with this type of pawn promotion, pawns may only 
		//	promote to major piece types
		int promotionTypeCount = 0;
		if( majorPieceTypes[piece->GetPlayerNumber()][0] != &NullPieceType96::nullPieceType96 )
		{
			promotionTypeCount++;
			promotions[0] = majorPieceTypes[piece->GetPlayerNumber()][0];
			if( !quiescentSearch && majorPieceTypes[piece->GetPlayerNumber()][1] != &NullPieceType96::nullPieceType96 )
			{
				promotionTypeCount++;
				promotions[1] = majorPieceTypes[piece->GetPlayerNumber()][1];
				if( majorPieceTypes[piece->GetPlayerNumber()][2] != &NullPieceType96::nullPieceType96 )
				{
					promotionTypeCount++;
					promotions[2] = majorPieceTypes[piece->GetPlayerNumber()][2];
				}
			}
		}
		return promotionTypeCount;
	}
	if( pawnPromotionType == PAWN_PROMOTION_TYPE_QUEEN )
	{
		promotions[0] = majorPieceTypes[piece->GetPlayerNumber()][0];
		return 1;
	}
	// *** STANDARD pawn promotion *** //
	return( Game::EnumeratePromotions( piece, fromSquare, toSquare, promotions, quiescentSearch ) );
}

int CapablancaGame::EnumeratePromotions
	( Piece *piece, 
	  int fromSquare,
	  int toSquare,
	  Piece **pieces,
	  bool quiescentSearch )
{
	// *** Function only used in GREAT SHATRANJ *** //

	int count = 0;

	bool rookOrDabbabahFound = false;
	bool knightFound = false;
	bool elephantFound = false;
	bool ministerFound = false;
	bool highPriestessFound = false;

	for( int x = 0; x < board.GetNumberOfPieces( piece->GetPlayerNumber() ) && count < 4; x++ )
	{
		Piece *currentPiece = board.GetPiece( piece->GetPlayerNumber(), x );
		if( currentPiece->IsCaptured() )
		{
			if( &(currentPiece->GetType()) == &(CapablancaRook::capablancaRook) && !rookOrDabbabahFound )
			{
				rookOrDabbabahFound = true;
				pieces[count++] = currentPiece;
			}
			else if( &(currentPiece->GetType()) == &(CapablancaWoodyRook::capablancaWoodyRook) && !rookOrDabbabahFound )
			{
				rookOrDabbabahFound = true;
				pieces[count++] = currentPiece;
			}
			else if( &(currentPiece->GetType()) == &(CapablancaKnight::capablancaKnight) && !knightFound )
			{
				knightFound = true;
				pieces[count++] = currentPiece;
			}
			else if( &(currentPiece->GetType()) == &(CapablancaElephantFerz::capablancaElephantFerz) && !elephantFound )
			{
				elephantFound = true;
				pieces[count++] = currentPiece;
			}
			else if( &(currentPiece->GetType()) == &(CapablancaMinister::capablancaMinister) && !ministerFound )
			{
				ministerFound = true;
				pieces[count++] = currentPiece;
			}
			else if( &(currentPiece->GetType()) == &(CapablancaHighPriestess::capablancaHighPriestess) && !highPriestessFound )
			{
				highPriestessFound = true;
				pieces[count++] = currentPiece;
			}
		}
	}

	return count;
}

void CapablancaGame::DefaultSettings()
{
	if( !strcmp( selectedVariant->name, "Grotesque Chess" ) )
	{
		squareColor1 = RGB(254, 239, 205);
		squareColor2 = RGB(173, 118, 101);
		squareColor3 = RGB(206, 148, 130);
		pieceColor1 = RGB(255, 255, 255);
		pieceColor2 = RGB(234, 0, 0);
		borderColor = RGB(84, 54, 54);
		boardDisplayType = BOARD_IS_CHECKERED;
		selectedPieceSet = PIECE_SET_ABSTRACT;
	}
	else if( !strcmp( selectedVariant->name, "Lions and Unicorns Chess" ) )
	{
		squareColor1 = RGB(255, 255, 221);
		squareColor2 = RGB(34, 153, 34);
		squareColor3 = RGB(51, 200, 51);
		pieceColor1 = RGB(255, 255, 255);
		pieceColor2 = RGB(89, 132, 189);
		borderColor = RGB(128, 70, 70);
		boardDisplayType = BOARD_IS_THREE_COLORED;
		selectedPieceSet = PIECE_SET_STANDARD;
	}
	else
		Game::DefaultSettings();
}

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

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