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

                                 ChessV

               COPYRIGHT (C) 2005, 2010 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 "../../ChessV.h"
#include "../../PieceType.h"
#include "../../Piece.h"
#include "../../Direction.h"
#include "../../Rand.h"
#include "../../GameParameters.h"
#include "DecimalChessGame.h"
#include "Decimal_Types.h"

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


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

DecimalChessGame::DecimalChessGame( Board &board, Player &whitePlayer, Player &blackPlayer ):
	Game(board, whitePlayer, blackPlayer),
	bareKingRule(false),
	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 = 10000;
	futilityMargin = 2800;
	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( 0 );
	phases[0].SetPawnDeficiencyFactor( 12 );
	phases[0].SetSquareValuesFactor( 1 );
	phases[0].SetKingSafetyFactor( 6 );
	phases[0].SetTropismFactor( 6 );

	//	settings for phase 1 (midgame)
	phases[1].SetNumber( 1 );
	phases[1].SetMobilityFactor( 0 );
	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' array.
	DecimalKnight::decimalKnight.gameInt1 = 10;
	DecimalLion::decimalLion.gameInt1 = 9;
	DecimalBishop::decimalBishop.gameInt1 = 7;


	//	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_128 );
}

void DecimalChessGame::AddPlayerPieceTypes( char *gameName )
{
	//	add the (default) piece types that each player may have
	board.AddPlayerPieceTypeBothPlayers( DecimalRook::decimalRook );
	board.AddPlayerPieceTypeBothPlayers( DecimalBishop::decimalBishop );
	board.AddPlayerPieceTypeBothPlayers( DecimalKnight::decimalKnight );
	board.AddPlayerPieceTypeBothPlayers( DecimalQueen::decimalQueen );
	board.AddPlayerPieceTypeBothPlayers( DecimalKing::decimalKing );
	board.AddPlayerPieceTypeBothPlayers( DecimalArchbishop::decimalArchbishop );
	board.AddPlayerPieceTypeBothPlayers( DecimalChancellor::decimalChancellor );
	//	add piece type references to the following arrays, 
	//	minorPieceTypes, etc., used for giving bonuses and 
	//	penalties in positional evaluation
	rookPieceTypes[0] = rookPieceTypes[1] = &DecimalRook::decimalRook;
	colorboundPieceTypes[0][0] = colorboundPieceTypes[1][0] = &DecimalBishop::decimalBishop;
	colorboundPieceTypes[0][1] = colorboundPieceTypes[1][1] = &NullPieceType128::nullPieceType128;
	minorPieceTypes[0][0] = minorPieceTypes[1][0] = &DecimalKnight::decimalKnight;
	minorPieceTypes[0][1] = minorPieceTypes[1][1] = &DecimalBishop::decimalBishop;
	minorPieceTypes[0][2] = minorPieceTypes[1][2] = &NullPieceType128::nullPieceType128;
	minorPieceTypes[0][3] = minorPieceTypes[1][3] = &NullPieceType128::nullPieceType128;
	majorPieceTypes[0][0] = majorPieceTypes[1][0] = &DecimalQueen::decimalQueen;
	majorPieceTypes[0][1] = majorPieceTypes[1][1] = &DecimalChancellor::decimalChancellor;
	majorPieceTypes[0][2] = majorPieceTypes[1][2] = &DecimalArchbishop::decimalArchbishop;
	majorPieceTypes[0][3] = majorPieceTypes[1][3] = &NullPieceType128::nullPieceType128;
}

// *** CHANGE RULES FOR PARTICULAR (BUILT-IN) VARIANT *** //
void DecimalChessGame::ChangeRulesByVariant
	( char *gameName,
	  char *&array,
	  char *&book )
{
	//	assume, for now, standard castling and promotion rules
	pawnPromotionType = PAWN_PROMOTION_TYPE_STANDARD;
	pawnPromotionRank = 9;
	castlingType = CASTLING_TYPE_STANDARD;
	wackyPawnRestriction = false;
	castleOutOfCheck = false;
	kingsLeap = false;

	// *** (TURKISH) GREAT CHESS *** //
	if( !strcmp( selectedVariant->name, "Great Chess" ) )
	{
		//	implement rule changes
		castlingType = CASTLING_TYPE_NONE;
		enPassant = false;
		//	add correct pawn type
		pawnPieceTypes[0] = pawnPieceTypes[1] = &DecimalLamePawn::decimalLamePawn;
		board.AddPlayerPieceTypeBothPlayers( DecimalLamePawn::decimalLamePawn );
		//	place pieces
		array = "rnbqkgvbnr/ppppwwpppp/4pp4/10/10/10/10/4PP4/PPPPWWPPPP/RNBVGKQBNR";
		//	add the Amazon
		majorPieceTypes[0][3] = majorPieceTypes[1][3] = &DecimalAmazon::decimalAmazon;
		board.AddPlayerPieceTypeBothPlayers( DecimalAmazon::decimalAmazon );
		//	change pawn promotion type
		DecimalLamePawn::decimalLamePawn.SetPromotionType( PromoteToSpecificType );
		DecimalLamePawn::decimalLamePawn.SetTypeToPromoteTo( DecimalQueen::decimalQueen );
		//	change piece names
		DecimalAmazon::decimalAmazon.SetFullName( "Giraffe" );
		DecimalAmazon::decimalAmazon.SetNotation( "G" );
		DecimalChancellor::decimalChancellor.SetFullName( "War Machine" );
		DecimalChancellor::decimalChancellor.SetNotation( "W" );
		DecimalArchbishop::decimalArchbishop.SetFullName( "Vizir" );
		DecimalArchbishop::decimalArchbishop.SetNotation( "V" );
		//	set bitmaps for alternate piece set to show 
		//	more historically-appropriate images
		DecimalAmazon::decimalAmazon.SetBitmapFileName( PIECE_SET_ALTERNATE, 0, "images\\standard\\WGiraffe.bmp" );
		DecimalAmazon::decimalAmazon.SetBitmapFileName( PIECE_SET_ALTERNATE, 1, "images\\standard\\BGiraffe.bmp" );
		DecimalChancellor::decimalChancellor.SetBitmapFileName( PIECE_SET_ALTERNATE, 0, "images\\standard\\WWarMachine.bmp" );
		DecimalChancellor::decimalChancellor.SetBitmapFileName( PIECE_SET_ALTERNATE, 1, "images\\standard\\BWarMachine.bmp" );
		//	set name of opening book
		book = "openings\\GreatChess.txt";
	}
	// *** SHATRANJ KAMIL *** //
	else if( !strcmp( selectedVariant->name, "Shatranj Kamil" ) )
	{
		//	lookup which setup we are using
		int setup = 1;
		LookupIntParameter( "setup", setup );
		//	implement rule changes
		castlingType = CASTLING_TYPE_NONE;
		bareKingRule = true;
		enPassant = false;
		//	add correct pawn type
		pawnPieceTypes[0] = pawnPieceTypes[1] = &DecimalLamePawn::decimalLamePawn;
		board.AddPlayerPieceTypeBothPlayers( DecimalLamePawn::decimalLamePawn );
		//	change pawn promotion type
		DecimalLamePawn::decimalLamePawn.SetPromotionType( PromoteToSpecificType );
		DecimalLamePawn::decimalLamePawn.SetTypeToPromoteTo( DecimalFerz::decimalFerz );
		//	place pieces
		if( setup == 1 )
			array = "rneckgcenr/pppppppppp/10/10/10/10/10/10/PPPPPPPPPP/RNECKGCENR";
		else
			array = "crnekgenrc/pppppppppp/10/10/10/10/10/10/PPPPPPPPPP/CRNEKGENRC";
		//	no Bishop, Queen, Archbishop, or Chancellor
		board.RemovePieceType( DecimalQueen::decimalQueen );
		board.RemovePieceType( DecimalArchbishop::decimalArchbishop );
		board.RemovePieceType( DecimalChancellor::decimalChancellor );
		majorPieceTypes[0][0] = majorPieceTypes[1][0] = &NullPieceType128::nullPieceType128;
		majorPieceTypes[0][1] = majorPieceTypes[1][1] = &NullPieceType128::nullPieceType128;
		majorPieceTypes[0][2] = majorPieceTypes[1][2] = &NullPieceType128::nullPieceType128;
		//	add the Elephant
		minorPieceTypes[0][2] = minorPieceTypes[1][2] = &DecimalElephant::decimalElephant;
		board.AddPlayerPieceTypeBothPlayers( DecimalElephant::decimalElephant );
		//	add the Camel
		minorPieceTypes[0][1] = minorPieceTypes[1][1] = &DecimalDabbabah::decimalDabbabah;
		board.AddPlayerPieceTypeBothPlayers( DecimalDabbabah::decimalDabbabah );
		DecimalDabbabah::decimalDabbabah.SetFullName( "Camel" );
		DecimalDabbabah::decimalDabbabah.SetNotation( "C" );
		//	add the General
		minorPieceTypes[0][3] = minorPieceTypes[1][3] = &DecimalFerz::decimalFerz;
		board.AddPlayerPieceTypeBothPlayers( DecimalFerz::decimalFerz );
		DecimalFerz::decimalFerz.SetFullName( "General" );
		DecimalFerz::decimalFerz.SetNotation( "G" );
		//	set bitmaps for alternate piece set to show 
		//	more historically-appropriate images
		DecimalDabbabah::decimalDabbabah.SetBitmapFileName( PIECE_SET_OLD_WORLD, 0, "images\\old_world\\WCamel.bmp" );
		DecimalDabbabah::decimalDabbabah.SetBitmapFileName( PIECE_SET_OLD_WORLD, 1, "images\\old_world\\BCamel.bmp" );
		//	set name of opening book
		if( setup == 1 )
			book = "openings\\ShatranjKamil1.txt";
		else
			book = "openings\\ShatranjKamil2.txt";
	}
	// *** EMPEROR'S GAME *** //
	else if( !strcmp( selectedVariant->name, "Emperor's Game" ) )
	{
		//	implement rule changes
		castlingType = CASTLING_TYPE_LONG;
		pawnPromotionType = PAWN_PROMOTION_TYPE_REPLACEMENT;
		//	add correct pawn type
		pawnPieceTypes[0] = pawnPieceTypes[1] = &Decimal3StepPawn::decimal3StepPawn;
		board.AddPlayerPieceTypeBothPlayers( Decimal3StepPawn::decimal3StepPawn );
		Decimal3StepPawn::decimal3StepPawn.SetPromotionType( PromoteByReplacement );
		//	no chancellor in this game
		board.RemovePieceType( DecimalChancellor::decimalChancellor );
		//	add Amazon (called 'General')
		majorPieceTypes[0][1] = majorPieceTypes[1][1] = &DecimalAmazon::decimalAmazon;
		board.AddPlayerPieceTypeBothPlayers( DecimalAmazon::decimalAmazon );
		DecimalAmazon::decimalAmazon.SetFullName( "General" );
		DecimalAmazon::decimalAmazon.SetNotation( "G" );
		//	change name of Archbishop to 'Adjunct'
		DecimalArchbishop::decimalArchbishop.SetFullName( "Adjunct" );
		DecimalArchbishop::decimalArchbishop.SetNotation( "A" );
		//	place pieces
		array = "rnbaqkgbnr/pppppppppp/10/10/10/10/10/10/PPPPPPPPPP/RNBGKQABNR";
		//	set name of opening book
		book = "openings\\EmperorsGame.txt";
	}
	// *** UNICORN CHESS *** //
	else if( !strcmp( selectedVariant->name, "Unicorn Chess" ) )
	{
		//	implement rule changes
		castlingType = CASTLING_TYPE_CLOSE_ROOK;
		pawnPromotionType = PAWN_PROMOTION_TYPE_MAJORS;
		//	place pieces
		array = "crubqkburc/ppppnnpppp/4pp4/10/10/10/10/4PP4/PPPPNNPP/CRUBQKBURC";
		//	add correct pawn type
		pawnPieceTypes[0] = pawnPieceTypes[1] = &UnicornChessPawn::unicornChessPawn;
		board.AddPlayerPieceTypeBothPlayers( UnicornChessPawn::unicornChessPawn );
		//	Unicorn indead of Archbishop in this game
		majorPieceTypes[0][2] = majorPieceTypes[1][2] = &DecimalUnicorn::decimalUnicorn;
		board.RemovePieceType( DecimalArchbishop::decimalArchbishop );
		board.AddPlayerPieceTypeBothPlayers( DecimalUnicorn::decimalUnicorn );
		//	set name of opening book
		book = "openings\\UnicornChess.txt";
	}
	// *** UNICORN GREAT CHESS *** //
	else if( !strcmp( selectedVariant->name, "Unicorn Great Chess" ) )
	{
		//	implement rule changes
		castlingType = CASTLING_TYPE_CLOSE_ROOK;
		pawnPromotionType = PAWN_PROMOTION_TYPE_MAJORS;
		//	place pieces
		array = "crnbukbnrq/ppppllpppp/4pp4/10/10/10/10/4PP4/PPPPLLPPPP/CRNBUKBNRQ";
		//	add correct pawn type
		pawnPieceTypes[0] = pawnPieceTypes[1] = &UnicornChessPawn::unicornChessPawn;
		board.AddPlayerPieceTypeBothPlayers( UnicornChessPawn::unicornChessPawn );
		//	Unicorn indead of Archbishop in this game
		majorPieceTypes[0][2] = majorPieceTypes[1][2] = &DecimalUnicorn::decimalUnicorn;
		board.RemovePieceType( DecimalArchbishop::decimalArchbishop );
		board.AddPlayerPieceTypeBothPlayers( DecimalUnicorn::decimalUnicorn );
		//	add the Lion
		minorPieceTypes[0][2] = minorPieceTypes[1][2] = &DecimalLion::decimalLion;
		board.AddPlayerPieceTypeBothPlayers( DecimalLion::decimalLion );
		//	set name of opening book
		book = "openings\\UnicornGreatChess.txt";
	}
	// *** UNICORN GRAND CHESS *** //
	else if( !strcmp( selectedVariant->name, "Unicorn Grand Chess" ) )
	{
		//	implement rule changes
		castlingType = CASTLING_TYPE_NONE;
		pawnPromotionType = PAWN_PROMOTION_TYPE_REPLACEMENT;
		pawnPromotionRank = 7;
		//	place pieces
		array = "r8r/cnlbukblnq/pppppppppp/10/10/10/10/PPPPPPPPPP/CNLBUKBLNQ/R8R";
		//	add correct pawn type
		pawnPieceTypes[0] = pawnPieceTypes[1] = &GrandChessPawn::grandChessPawn;
		board.AddPlayerPieceTypeBothPlayers( GrandChessPawn::grandChessPawn );
		//	Unicorn indead of Archbishop in this game
		majorPieceTypes[0][2] = majorPieceTypes[1][2] = &DecimalUnicorn::decimalUnicorn;
		board.RemovePieceType( DecimalArchbishop::decimalArchbishop );
		board.AddPlayerPieceTypeBothPlayers( DecimalUnicorn::decimalUnicorn );
		//	add the Lion
		minorPieceTypes[0][2] = minorPieceTypes[1][2] = &DecimalLion::decimalLion;
		board.AddPlayerPieceTypeBothPlayers( DecimalLion::decimalLion );
		//	set name of opening book
		book = "openings\\UnicornGrandChess.txt";
	}
	// *** OPULENT CHESS *** //
	else if( !strcmp( selectedVariant->name, "Opulent Chess" ) )
	{
		//	implement rule changes
		castlingType = CASTLING_TYPE_NONE;
		pawnPromotionType = PAWN_PROMOTION_TYPE_REPLACEMENT;
		pawnPromotionRank = 7;
		//	place pieces
		array = "rw6wr/clnbqkbnla/pppppppppp/10/10/10/10/PPPPPPPPPP/CLNBQKBNLA/RW6WR";
		//	add correct pawn type
		pawnPieceTypes[0] = pawnPieceTypes[1] = &GrandChessPawn::grandChessPawn;
		board.AddPlayerPieceTypeBothPlayers( GrandChessPawn::grandChessPawn );
		//	add Wizard and Lion piece types
		minorPieceTypes[0][2] = minorPieceTypes[1][2] = &DecimalLion::decimalLion;
		minorPieceTypes[0][3] = minorPieceTypes[1][3] = &DecimalCamelFerz::decimalCamelFerz;
		board.AddPlayerPieceTypeBothPlayers( DecimalLion::decimalLion );
		board.AddPlayerPieceTypeBothPlayers( DecimalCamelFerz::decimalCamelFerz );
		//	change the Knight to the enhanced Knight (Knight+Wazir)
		minorPieceTypes[0][0] = minorPieceTypes[1][0] = &DecimalKnightWazir::decimalKnightWazir;
		board.RemovePieceType( DecimalKnight::decimalKnight );
		board.AddPlayerPieceTypeBothPlayers( DecimalKnightWazir::decimalKnightWazir );
		//	set name of opening book
		book = "openings\\OpulentChess.txt";
	}
	// *** TEN-CUBED CHESS *** //
	else if( !strcmp( selectedVariant->name, "TenCubed Chess" ) )
	{
		//	implement rule changes
		castlingType = CASTLING_TYPE_NONE;
		pawnPromotionType = PAWN_PROMOTION_TYPE_MAJORS;
		//	place pieces
		array = "2cwamwc2/1rnbqkbnr1/pppppppppp/10/10/10/10/PPPPPPPPPP/1RNBQKBNR1/2CWAMWC2";
		//	change name of Chancellor to Marshall
		DecimalChancellor::decimalChancellor.SetFullName( "Marshall" );
		DecimalChancellor::decimalChancellor.SetNotation( "M" );
		//	add correct pawn type
		pawnPieceTypes[0] = pawnPieceTypes[1] = &GrandChessPawn::grandChessPawn;
		board.AddPlayerPieceTypeBothPlayers( GrandChessPawn::grandChessPawn );
		//	add the Champion and Wizard
		minorPieceTypes[0][2] = minorPieceTypes[1][2] = &DecimalChampion::decimalChampion;
		minorPieceTypes[0][3] = minorPieceTypes[1][3] = &DecimalCamelFerz::decimalCamelFerz;
		board.AddPlayerPieceTypeBothPlayers( DecimalChampion::decimalChampion );
		board.AddPlayerPieceTypeBothPlayers( DecimalCamelFerz::decimalCamelFerz );
	}
	// *** TEST GAME *** //
	else if( !strcmp( selectedVariant->name, "Test Game" ) )
	{
		//	implement rule changes
		castlingType = CASTLING_TYPE_NONE;
		pawnPromotionType = PAWN_PROMOTION_TYPE_REPLACEMENT;
		pawnPromotionRank = 7;
		//	place pieces
		array = "r8r/2bnqknb2/pppppppppp/10/10/10/10/PPPPPPPPPP/2BNQKNB2/C8C";
		//	add correct pawn type
		pawnPieceTypes[0] = pawnPieceTypes[1] = &GrandChessPawn::grandChessPawn;
		board.AddPlayerPieceTypeBothPlayers( GrandChessPawn::grandChessPawn );
		//	remove archbishop and chancellor
		majorPieceTypes[0][1] = majorPieceTypes[1][1] = &NullPieceType128::nullPieceType128;
		majorPieceTypes[0][2] = majorPieceTypes[1][2] = &NullPieceType128::nullPieceType128;
		board.RemovePieceType( DecimalArchbishop::decimalArchbishop );
		board.RemovePieceType( DecimalChancellor::decimalChancellor );
		//	add cleric
		board.AddPlayerPieceTypeBothPlayers( DecimalCleric::decimalCleric );
		//	balance piece values
		DecimalRook::decimalRook.SetBaseValue( 6000 );
		DecimalRook::decimalRook.SetPerCaptureValueBonus( 0 );
		DecimalRook::decimalRook.SetPerCaptureBonusThreshold( 0 );
		DecimalCleric::decimalCleric.SetBaseValue( 5900 );
		DecimalCleric::decimalCleric.SetPerCaptureBonusThreshold( 0 );
		DecimalCleric::decimalCleric.SetPerCaptureBonusThreshold( 0 );
		//	set name of opening book
		book = "openings\\TestGame.txt";
	}
	// *** ARCHCHESS *** //
	else if( !strcmp( selectedVariant->name, "Archchess" ) )
	{
		//	implement rule changes
		wackyPawnRestriction = true;
		castleOutOfCheck = true;
		kingsLeap = true;
		//	place pieces
		array = "rnbckqdbnr/pppppppppp/10/10/10/10/10/10/PPPPPPPPPP/RNBCKQDBNR";
		//	add correct pawn type
		pawnPieceTypes[0] = pawnPieceTypes[1] = &DecimalPawn::decimalPawn;
		board.AddPlayerPieceTypeBothPlayers( DecimalPawn::decimalPawn );
		//	change pawn promotion
		DecimalPawn::decimalPawn.SetPromotionType( PromoteToSpecificType );
		DecimalPawn::decimalPawn.SetTypeToPromoteTo( DecimalQueen::decimalQueen );
		//	no chancellor or archbishop
		board.RemovePieceType( DecimalArchbishop::decimalArchbishop );
		board.RemovePieceType( DecimalChancellor::decimalChancellor );
		majorPieceTypes[0][1] = majorPieceTypes[1][1] = &NullPieceType128::nullPieceType128;
		majorPieceTypes[0][2] = majorPieceTypes[1][2] = &NullPieceType128::nullPieceType128;
		//	add the Centurion and Decurion
		minorPieceTypes[0][2] = minorPieceTypes[1][2] = &DecimalFerz::decimalFerz;
		minorPieceTypes[0][3] = minorPieceTypes[1][3] = &DecimalSquirrel::decimalSquirrel;
		board.AddPlayerPieceTypeBothPlayers( DecimalFerz::decimalFerz );
		board.AddPlayerPieceTypeBothPlayers( DecimalSquirrel::decimalSquirrel );
		//	change piece names and notations
		DecimalSquirrel::decimalSquirrel.SetFullName( "Centurion" );
		DecimalSquirrel::decimalSquirrel.SetNotation( "C" );
		DecimalFerz::decimalFerz.SetFullName( "Decurion" );
		DecimalFerz::decimalFerz.SetNotation( "D" );
	}
	// *** ROMAN CHESS *** //
	else if( !strcmp( selectedVariant->name, "Roman Chess" ) )
	{
		//	add correct pawn type
		pawnPieceTypes[0] = pawnPieceTypes[1] = &DecimalPawn::decimalPawn;
		board.AddPlayerPieceTypeBothPlayers( DecimalPawn::decimalPawn );
		//	place pieces
		array = "rncbqkbcnr/pppppppppp/10/10/10/10/10/10/PPPPPPPPPP/RNCBQKBCNR";
		//	no chancellor or archbishop
		board.RemovePieceType( DecimalArchbishop::decimalArchbishop );
		board.RemovePieceType( DecimalChancellor::decimalChancellor );
		majorPieceTypes[0][1] = majorPieceTypes[1][1] = &NullPieceType128::nullPieceType128;
		majorPieceTypes[0][2] = majorPieceTypes[1][2] = &NullPieceType128::nullPieceType128;
		//	add the Centurion piece type
		minorPieceTypes[0][2] = minorPieceTypes[1][2] = &DecimalGeneral::decimalGeneral;
		board.AddPlayerPieceTypeBothPlayers( DecimalGeneral::decimalGeneral );
		DecimalGeneral::decimalGeneral.SetFullName( "Centurion" );
		DecimalGeneral::decimalGeneral.SetNotation( "C" );
		//	set name of opening book
		book = "openings\\RomanChess.txt";
	}
	// *** MODERN KAMIL *** //
	else if( !strcmp( selectedVariant->name, "Modern Kamil" ) )
	{
		//	implement rule changes
		castlingType = CASTLING_TYPE_CLOSE_ROOK;
		pawnPromotionRank = 7;
		//	place pieces
		array = "10/crnbqkbnrc/pppppppppp/10/10/10/10/PPPPPPPPPP/CRNBQKBNRC/10";
		//	add correct pawn type
		pawnPieceTypes[0] = pawnPieceTypes[1] = &GrandChessPawn::grandChessPawn;
		board.AddPlayerPieceTypeBothPlayers( GrandChessPawn::grandChessPawn );
		GrandChessPawn::grandChessPawn.SetPromotionType( PromoteToVariableTypes );
		//	no chancellor or archbishop
		board.RemovePieceType( DecimalArchbishop::decimalArchbishop );
		board.RemovePieceType( DecimalChancellor::decimalChancellor );
		majorPieceTypes[0][1] = majorPieceTypes[1][1] = &NullPieceType128::nullPieceType128;
		majorPieceTypes[0][2] = majorPieceTypes[1][2] = &NullPieceType128::nullPieceType128;
		//	add the Camel piece type
		minorPieceTypes[0][2] = minorPieceTypes[1][2] = &DecimalCamel::decimalCamel;
		board.AddPlayerPieceTypeBothPlayers( DecimalCamel::decimalCamel );
		//	set name of opening book
		book = "openings\\ModernKamil.txt";
	}
}

// *** implement RULE CHANGES by VARIABLE DEFINITION *** //
void DecimalChessGame::ChangeRulesByVariableDefinition( char *gameName )
{
	// *** CASTLING *** //
	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);
	}
	LookupBoolParameter( "castle-out-of-check", castleOutOfCheck );

	// *** PAWN PROMOTION *** //
	char *pawnPromotionTypeName;
	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, "replacement" ) )
			pawnPromotionType = PAWN_PROMOTION_TYPE_REPLACEMENT;
	}
	if( pawnPromotionType == PAWN_PROMOTION_TYPE_STANDARD ||
		pawnPromotionType == PAWN_PROMOTION_TYPE_MAJORS )
	{
		pawnPieceTypes[0]->SetPromotionType( PromoteToVariableTypes );
		pawnPieceTypes[1]->SetPromotionType( PromoteToVariableTypes );
	}
	else if( pawnPromotionType == PAWN_PROMOTION_TYPE_REPLACEMENT )
	{
		pawnPieceTypes[0]->SetPromotionType( PromoteByReplacement );
		pawnPieceTypes[1]->SetPromotionType( PromoteByReplacement );
	}
	if( LookupIntParameter( "pawn-promotion-rank", pawnPromotionRank ) )
		//	if user sets the pawn promotion rank, subtract one, so that the 
		//	user doesn't have to use our zero-based rank numbering
		pawnPromotionRank--;

	// *** EN PASSANT *** //
	LookupBoolParameter( "en-passant", enPassant );

	// *** BARE KING *** //
	LookupBoolParameter( "bare-king", bareKingRule );

	// *** KING'S LEAP *** //
	LookupBoolParameter( "kings-leap", kingsLeap );
}

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

	//	initialize pawnStartRank array, which keeps track of the rank
	//	of the forward-most pawn for each file.  this is used later
	//	during evaluation of opening positions to penalize a player 
	//	for blocking development of center pawns (files D-G)
	for( int file = 0; file < 10; file++ )
	{
		pawnStartRank[0][file] = 10;
		int rank;
		for( rank = 9; rank >= 0; rank-- )
		{
			Piece *piece = board.GetSquareContents( rank, file );
			if( piece != NULL && &(piece->GetType()) == pawnPieceTypes[0] )
			{
				pawnStartRank[0][file] = rank;
				break;
			}
		}
		pawnStartRank[0][file] = -1;
		for( rank = 0; rank < 10; rank++ )
		{
			Piece *piece = board.GetSquareContents( rank, file );
			if( piece != NULL && &(piece->GetType()) == pawnPieceTypes[1] )
			{
				pawnStartRank[1][file] = rank;
				break;
			}
		}
	}
}

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

bool DecimalChessGame::AddPieceType
	( PieceType *pieceType,
	  int nPlayer )
{
	if( pieceType->IsPawn() )
	{
		if( pawnPieceTypes[nPlayer] == &NullPieceType128::nullPieceType128 )
			pawnPieceTypes[nPlayer] = (PieceType128 *) pieceType;
		else
			return false;
	}
	if( pieceType->GetBaseValue() >= 6000 )
	{
		if( majorPieceTypes[nPlayer][0] == &NullPieceType128::nullPieceType128 )
			majorPieceTypes[nPlayer][0] = (PieceType128 *) pieceType;
		else
		{
			if( majorPieceTypes[nPlayer][1] == &NullPieceType128::nullPieceType128 )
				majorPieceTypes[nPlayer][1] = (PieceType128 *) pieceType;
			else
			{
				if( majorPieceTypes[nPlayer][2] == &NullPieceType128::nullPieceType128 )
					majorPieceTypes[nPlayer][2] = (PieceType128 *) pieceType;
				else
				{
					if( majorPieceTypes[nPlayer][3] == &NullPieceType128::nullPieceType128 )
						majorPieceTypes[nPlayer][3] = (PieceType128 *) pieceType;
				}
			}
		}
	}
	else if( pieceType->GetBaseValue() <= 4000 )
	{
		if( minorPieceTypes[nPlayer][0] == &NullPieceType128::nullPieceType128 )
			minorPieceTypes[nPlayer][0] = (PieceType128 *) pieceType;
		else
		{
			if( minorPieceTypes[nPlayer][1] == &NullPieceType128::nullPieceType128 )
				minorPieceTypes[nPlayer][1] = (PieceType128 *) pieceType;
			else
			{
				if( minorPieceTypes[nPlayer][2] == &NullPieceType128::nullPieceType128 )
					minorPieceTypes[nPlayer][2] = (PieceType128 *) pieceType;
				else
				{
					if( minorPieceTypes[nPlayer][3] == &NullPieceType128::nullPieceType128 )
						minorPieceTypes[nPlayer][3] = (PieceType128 *) pieceType;
				}
			}
		}
	}
	return true;
}

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

	if( &pieceType == pawnPieceTypes[nPlayer] )
	{
		if( pawnPromotionRank == 7 )
		{
			if( newPiece->GetPlayerNumber() == 0 )
				newPiece->GetPromotionZone().AddToZone( 70, 99 );
			else
				newPiece->GetPromotionZone().AddToZone( 0, 29 );
		}
		else if( pawnPromotionRank == 8 )
		{
			if( newPiece->GetPlayerNumber() == 0 )
				newPiece->GetPromotionZone().AddToZone( 80, 99 );
			else
				newPiece->GetPromotionZone().AddToZone( 0, 19 );
		}
		else
		{
			if( newPiece->GetPlayerNumber() == 0 )
				newPiece->GetPromotionZone().AddToZone( 90, 99 );
			else
				newPiece->GetPromotionZone().AddToZone( 0, 9 );
		}
	}
	return newPiece;
}

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

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


	if( quiescentSearch )
		//	return now, so we don't consider castling moves
		//	or king's leap in quiescent search
		return;


	// *** KING'S LEAP *** //

	if( kingsLeap )
	{
		Piece *king = board.GetKing( currentPlayer );
		if( !king->HasMoved() )
		{
			int kingSquare = king->GetSquareNumber();
			//	leap left
			if( kingSquare - 2 >= 0 && 
				board.GetSquareContents( kingSquare - 2 ) == NULL &&
				!board.IsSquareAttacked( kingSquare - 2, FLIP(currentPlayer) ) )
			{
				stack.BeginMoveAdd( UserMove1, kingSquare, kingSquare - 2 );
				stack.AddPickUp( kingSquare );
				stack.AddDrop( king, kingSquare - 2 );
				stack.EndMoveAdd( -100 );
			}
			//	leap right
			if( kingSquare + 2 < 100 && 
				board.GetSquareContents( kingSquare + 2 ) == NULL &&
				!board.IsSquareAttacked( kingSquare + 2, FLIP(currentPlayer) ) )
			{
				stack.BeginMoveAdd( UserMove1, kingSquare, kingSquare + 2 );
				stack.AddPickUp( kingSquare );
				stack.AddDrop( king, kingSquare + 2 );
				stack.EndMoveAdd( -100 );
			}
			//	leap north
			if( kingSquare + 20 < 100 && 
				board.GetSquareContents( kingSquare + 20 ) == NULL &&
				!board.IsSquareAttacked( kingSquare + 20, FLIP(currentPlayer) ) )
			{
				stack.BeginMoveAdd( UserMove1, kingSquare, kingSquare + 20 );
				stack.AddPickUp( kingSquare );
				stack.AddDrop( king, kingSquare + 20 );
				stack.EndMoveAdd( -1000 );
			}
			//	leap south
			if( kingSquare - 20 >= 0 && 
				board.GetSquareContents( kingSquare - 20 ) == NULL &&
				!board.IsSquareAttacked( kingSquare - 20, FLIP(currentPlayer) ) )
			{
				stack.BeginMoveAdd( UserMove1, kingSquare, kingSquare - 20 );
				stack.AddPickUp( kingSquare );
				stack.AddDrop( king, kingSquare - 20 );
				stack.EndMoveAdd( -1000 );
			}
		}
	}


	// *** CASTLING *** //

	//	castling moves are added next; check for an early exit
	if( castlingType == CASTLING_TYPE_NONE || 
		(board.FastCheckTest() && !castleOutOfCheck) )
		//	return now, so we don't consider castling moves when
		//	we are in Check, or if there is no castling in this game
		return;

	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( !king->HasMoved() && king->GetSquareNumber() == 15 )
		{
			//	king side
			if( board.GetSquareContents( 19 ) != NULL &&
				!board.GetSquareContents( 19 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 19 ), 18, 17 );
			}
			//	queen side
			if( board.GetSquareContents( 10 ) != NULL &&
				!board.GetSquareContents( 10 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 10 ), 12, 13 );
			}
		}
		else if( !king->HasMoved() && king->GetSquareNumber() == 14 )
		{
			//	king side
			if( board.GetSquareContents( 19 ) != NULL &&
				!board.GetSquareContents( 19 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 19 ), 17, 16 );
			}
			//	queen side
			if( board.GetSquareContents( 10 ) != NULL &&
				!board.GetSquareContents( 10 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 10 ), 11, 12 );
			}
		}
	}
	else if( castlingType == CASTLING_TYPE_STANDARD && board.GetCurrentPlayerNumber() == 1 )
	{
		//	black to move
		Piece *king = board.GetKing( 1 );
		if( !king->HasMoved() && king->GetSquareNumber() == 95 )
		{
			//	king side
			if( board.GetSquareContents( 99 ) != NULL &&
				!board.GetSquareContents( 99 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 99 ), 98, 97 );
			}
			//	queen side
			if( board.GetSquareContents( 90 ) != NULL &&
				!board.GetSquareContents( 90 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 90 ), 92, 93 );
			}
		}
		else if( !king->HasMoved() && king->GetSquareNumber() == 94 )
		{
			//	king side
			if( board.GetSquareContents( 99 ) != NULL &&
				!board.GetSquareContents( 99 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 99 ), 97, 96 );
			}
			//	queen side
			if( board.GetSquareContents( 90 ) != NULL &&
				!board.GetSquareContents( 90 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 90 ), 91, 92 );
			}
		}
		else if( !king->HasMoved() && king->GetSquareNumber() == 85 )
		{
			//	king side
			if( board.GetSquareContents( 89 ) != NULL &&
				!board.GetSquareContents( 89 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 89 ), 88, 87 );
			}
			//	queen side
			if( board.GetSquareContents( 80 ) != NULL &&
				!board.GetSquareContents( 80 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 80 ), 82, 83 );
			}
		}
		else if( !king->HasMoved() && king->GetSquareNumber() == 94 )
		{
			//	king side
			if( board.GetSquareContents( 89 ) != NULL &&
				!board.GetSquareContents( 89 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 89 ), 87, 86 );
			}
			//	queen side
			if( board.GetSquareContents( 80 ) != NULL &&
				!board.GetSquareContents( 80 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 80 ), 81, 82 );
			}
		}
	}
	// *** 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( !king->HasMoved() && king->GetSquareNumber() == 15 )
		{
			//	king side
			if( board.GetSquareContents( 18 ) != NULL &&
				!board.GetSquareContents( 18 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 18 ), 17, 16 );
			}
			//	queen side
			if( board.GetSquareContents( 11 ) != NULL &&
				!board.GetSquareContents( 11 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 11 ), 13, 14 );
			}
		}
		else if( !king->HasMoved() && king->GetSquareNumber() == 14 )
		{
			//	king side
			if( board.GetSquareContents( 18 ) != NULL &&
				!board.GetSquareContents( 18 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 18 ), 16, 15 );
			}
			//	queen side
			if( board.GetSquareContents( 11 ) != NULL &&
				!board.GetSquareContents( 11 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 18 ), 12, 13 );
			}
		}
	}
	else if( castlingType == CASTLING_TYPE_CLOSE_ROOK && board.GetCurrentPlayerNumber() == 1 )
	{
		//	white to move
		Piece *king = board.GetKing( 1 );
		if( !king->HasMoved() && king->GetSquareNumber() == 95 )
		{
			//	king side
			if( board.GetSquareContents( 98 ) != NULL &&
				!board.GetSquareContents( 98 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 98 ), 97, 96 );
			}
			//	queen side
			if( board.GetSquareContents( 91 ) != NULL &&
				!board.GetSquareContents( 91 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 91 ), 93, 94 );
			}
		}
		else if( !king->HasMoved() && king->GetSquareNumber() == 94 )
		{
			//	king side
			if( board.GetSquareContents( 98 ) != NULL &&
				!board.GetSquareContents( 98 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 98 ), 96, 95 );
			}
			//	queen side
			if( board.GetSquareContents( 91 ) != NULL &&
				!board.GetSquareContents( 91 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 91 ), 92, 93 );
			}
		}
		else if( !king->HasMoved() && king->GetSquareNumber() == 85 )
		{
			//	king side
			if( board.GetSquareContents( 88 ) != NULL &&
				!board.GetSquareContents( 88 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 88 ), 87, 86 );
			}
			//	queen side
			if( board.GetSquareContents( 81 ) != NULL &&
				!board.GetSquareContents( 81 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 81 ), 83, 84 );
			}
		}
		else if( !king->HasMoved() && king->GetSquareNumber() == 84 )
		{
			//	king side
			if( board.GetSquareContents( 88 ) != NULL &&
				!board.GetSquareContents( 88 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 88 ), 86, 85 );
			}
			//	queen side
			if( board.GetSquareContents( 81 ) != NULL &&
				!board.GetSquareContents( 81 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 81 ), 82, 83 );
			}
		}
	}
	// *** 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( !king->HasMoved() && king->GetSquareNumber() == 14 )
		{
			//	king side
			if( board.GetSquareContents( 19 ) != NULL &&
				!board.GetSquareContents( 19 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 19 ), 18, 17 );
			}
			//	queen side
			if( board.GetSquareContents( 10 ) != NULL &&
				!board.GetSquareContents( 10 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 10 ), 11, 12 );
			}
		}
		else if( !king->HasMoved() && king->GetSquareNumber() == 15 )
		{
			//	king side
			if( board.GetSquareContents( 19 ) != NULL &&
				!board.GetSquareContents( 19 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 19 ), 18, 17 );
			}
			//	queen side
			if( board.GetSquareContents( 10 ) != NULL &&
				!board.GetSquareContents( 10 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 10 ), 11, 12 );
			}
		}
	}
	else if( castlingType == CASTLING_TYPE_LONG && board.GetCurrentPlayerNumber() == 1 )
	{
		//	black to move
		Piece *king = board.GetKing( 1 );
		if( !king->HasMoved() && king->GetSquareNumber() == 94 )
		{
			//	king side
			if( board.GetSquareContents( 99 ) != NULL &&
				!board.GetSquareContents( 99 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 99 ), 98, 97 );
			}
			//	queen side
			if( board.GetSquareContents( 90 ) != NULL &&
				!board.GetSquareContents( 90 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 90 ), 91, 92 );
			}
		}
		else if( !king->HasMoved() && king->GetSquareNumber() == 95 )
		{
			//	king side
			if( board.GetSquareContents( 99 ) != NULL &&
				!board.GetSquareContents( 99 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 99 ), 98, 97 );
			}
			//	queen side
			if( board.GetSquareContents( 90 ) != NULL &&
				!board.GetSquareContents( 90 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 90 ), 91, 92 );
			}
		}
		else if( !king->HasMoved() && king->GetSquareNumber() == 84 )
		{
			//	king side
			if( board.GetSquareContents( 89 ) != NULL &&
				!board.GetSquareContents( 89 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 89 ), 88, 87 );
			}
			//	queen side
			if( board.GetSquareContents( 80 ) != NULL &&
				!board.GetSquareContents( 80 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 80 ), 81, 82 );
			}
		}
		else if( !king->HasMoved() && king->GetSquareNumber() == 85 )
		{
			//	king side
			if( board.GetSquareContents( 89 ) != NULL &&
				!board.GetSquareContents( 89 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 89 ), 88, 87 );
			}
			//	queen side
			if( board.GetSquareContents( 80 ) != NULL &&
				!board.GetSquareContents( 80 )->HasMoved() )
			{
				AddCastlingMove( stack, gameRecord, king, board.GetSquareContents( 80 ), 81, 82 );
			}
		}
	}
	// *** 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() > 90 && king->GetSquareNumber() < 99 )
			{
				Piece *leftCastlingPiece = NULL;
				Piece *rightCastlingPiece = NULL;
				//	check right castling-piece
				if( board.GetSquareContents( 99 ) != NULL &&
					!board.GetSquareContents( 99 )->HasMoved() )
					//	right castling-piece is castling-elegible
					rightCastlingPiece = board.GetSquareContents( 99 );
				//	check left castling-piece
				if( board.GetSquareContents( 90 ) != NULL &&
					!board.GetSquareContents( 90 )->HasMoved() )
					//	left castling-piece is castling-elegible
					leftCastlingPiece = board.GetSquareContents( 90 );
				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() > 90 && king->GetSquareNumber() < 99 )
			{
				Piece *leftCastlingPiece = NULL;
				Piece *rightCastlingPiece = NULL;
				//	check right castling-piece
				if( board.GetSquareContents( 99 ) != NULL &&
					!board.GetSquareContents( 99 )->HasMoved() )
					//	right castling-piece is castling-elegible
					rightCastlingPiece = board.GetSquareContents( 99 );
				//	check left castling-piece
				if( board.GetSquareContents( 90 ) != NULL &&
					!board.GetSquareContents( 90 )->HasMoved() )
					//	left castling-piece is castling-elegible
					leftCastlingPiece = board.GetSquareContents( 90 );
				Game::AddFreeCastlingMoves( stack, gameRecord, king, leftCastlingPiece, rightCastlingPiece );
			}
		}
	}
}

bool DecimalChessGame::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.BB128_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.BB128_GetFriends( FLIP(board.GetCurrentPlayerNumber()) ).GetBitCount();
			if( gameRecord.materialCaptured == 0 || nOpponentPieces > 1 )
				return false;
		}
	}


	// *** Archchess 2-space pawn move restriction *** //
	
	//	special 2-move pawn rule restriction;  a 
	//	a 2-move pawn move is illegal when it may 
	//	be taken en passant, and also blocks check,
	//	so we render those moves illegal here
	if( wackyPawnRestriction && board.FastCheckTest() && 
		gameRecord.pieceMoved->IsPawn() &&
		(gameRecord.pieceMoved->GetFlags() & (FLAGS_HAS_MOVED | FLAGS_HAS_MOVED_TWICE)) == FLAGS_HAS_MOVED && 
		((gameRecord.pieceMoved->GetPlayerNumber() == 0 && gameRecord.pieceMoved->GetSquareNumber() >= 30 && 
		  gameRecord.pieceMoved->GetSquareNumber() < 40) ||
	     (gameRecord.pieceMoved->GetPlayerNumber() == 1 && gameRecord.pieceMoved->GetSquareNumber() >= 60 && 
		  gameRecord.pieceMoved->GetSquareNumber() < 70)) )
	{
		//	possible illegal move; see if there's a pawn 
		//	that can capture this piece en passant
		int sq = board.GetMovementMatrix( DIRECTION_E )[gameRecord.pieceMoved->GetSquareNumber()];
		if( sq != -1 && board.GetSquareContents( sq ) != NULL )
			if( board.GetSquareContents( sq )->IsPawn() && 
				board.GetSquareContents( sq )->GetPlayerNumber() != gameRecord.pieceMoved->GetPlayerNumber() )
				//	illegal move
				return false;
		sq = board.GetMovementMatrix( DIRECTION_W )[gameRecord.pieceMoved->GetSquareNumber()];
		if( sq != -1 && board.GetSquareContents( sq ) != NULL )
			if( board.GetSquareContents( sq )->IsPawn() && 
				board.GetSquareContents( sq )->GetPlayerNumber() != gameRecord.pieceMoved->GetPlayerNumber() )
				//	illegal move
				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++;
	}

	return true;
}

bool DecimalChessGame::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 );
}

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

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

		//	in the opening we consider the following things:
		//		- give bonus for developing the knights
		//		- penalize the queen, unicorn(s), and lions for moving early
		//		- give a bonus for castling; give a penalty for losing the ability to castle
		//		- give a penalty for moving pieces twice, and a bigger penalty for moving 3 times
		//		- penalize the blocking of center pawns

		//	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 += factor5;
			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 -= factor5;
			else
			{
				if( board.GetKing( 1 )->HasMoved() || 
					((board.GetSquareContents( 99 - adjustment ) == NULL ||
					  board.GetSquareContents( 99 - adjustment )->HasMoved()) &&
					 (board.GetSquareContents( 90 + adjustment ) == NULL ||
					  board.GetSquareContents( 90 + adjustment )->HasMoved())) )
					eval += (personality >= PERSONALITY_C ? factor6 : factor5);
			}
		}

		//	give a penalty for the major pieces moving early
		if( personality >= PERSONALITY_C )
		{
			BitBoard128 majors;
			majors = majorPieceTypes[0][0]->GetPieces( 0 ) | 
					majorPieceTypes[0][1]->GetPieces( 0 ) | 
					majorPieceTypes[0][2]->GetPieces( 0 ) |
					majorPieceTypes[0][3]->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 ) | 
					majorPieceTypes[1][2]->GetPieces( 1 ) |
					majorPieceTypes[1][3]->GetPieces( 1 );
			while( majors )
			{
				int square = majors.GetFirstBit();
				majors.ToggleBit( square );
				if( board.GetSquareContents( square )->GetFlags() & FLAGS_HAS_MOVED )
					eval += factor5;
			}
		}

		//	penalty for moving the same piece twice
		BitBoard128 bb = board.BB128_GetFriends( 0 );
		while( bb )
		{
			int square = bb.GetFirstBit();
			bb.ToggleBit( square );
			if( board.GetSquareContents( square )->HasMovedTwice() )
				eval -= (personality >= PERSONALITY_C ? factor6 : factor5);
		}
		bb = board.BB128_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 CENTER PAWNS IN OPENING *** //
		if( pawnStartRank[0][3] == 1 )
		{
			if( board.GetSquareContents( 23 ) != NULL &&
				board.GetSquareContents( 13 ) != NULL &&
				!board.GetSquareContents( 13 )->HasMoved() )
				eval -= factor5;
		}
		else if( pawnStartRank[0][3] == 2 )
		{
			if( board.GetSquareContents( 33 ) != NULL &&
				board.GetSquareContents( 23 ) != NULL &&
				!board.GetSquareContents( 23 )->HasMoved() )
				eval -= factor5;
		}
		if( pawnStartRank[0][4] == 1 )
		{
			if( board.GetSquareContents( 24 ) != NULL &&
				board.GetSquareContents( 14 ) != NULL &&
				!board.GetSquareContents( 14 )->HasMoved() )
				eval -= factor6;
		}
		else if( pawnStartRank[0][4] == 2 )
		{
			if( board.GetSquareContents( 34 ) != NULL &&
				board.GetSquareContents( 24 ) != NULL &&
				!board.GetSquareContents( 24 )->HasMoved() )
				eval -= factor6;
		}
		if( pawnStartRank[0][5] == 1 )
		{
			if( board.GetSquareContents( 25 ) != NULL &&
				board.GetSquareContents( 15 ) != NULL &&
				!board.GetSquareContents( 15 )->HasMoved() )
				eval -= factor6;
		}
		else if( pawnStartRank[0][5] == 2 )
		{
			if( board.GetSquareContents( 35 ) != NULL &&
				board.GetSquareContents( 25 ) != NULL &&
				!board.GetSquareContents( 25 )->HasMoved() )
				eval -= factor6;
		}
		if( pawnStartRank[0][6] == 1 )
		{
			if( board.GetSquareContents( 26 ) != NULL &&
				board.GetSquareContents( 16 ) != NULL &&
				!board.GetSquareContents( 16 )->HasMoved() )
				eval -= factor5;
		}
		else if( pawnStartRank[0][6] == 2 )
		{
			if( board.GetSquareContents( 36 ) != NULL &&
				board.GetSquareContents( 26 ) != NULL &&
				!board.GetSquareContents( 26 )->HasMoved() )
				eval -= factor5;
		}
		if( pawnStartRank[1][3] == 8 )
		{
			if( board.GetSquareContents( 73 ) != NULL &&
				board.GetSquareContents( 83 ) != NULL &&
				!board.GetSquareContents( 83 )->HasMoved() )
				eval += factor5;
		}
		else if( pawnStartRank[1][3] == 7 )
		{
			if( board.GetSquareContents( 63 ) != NULL &&
				board.GetSquareContents( 73 ) != NULL &&
				!board.GetSquareContents( 73 )->HasMoved() )
				eval += factor5;
		}
		if( pawnStartRank[1][4] == 8 )
		{
			if( board.GetSquareContents( 74 ) != NULL &&
				board.GetSquareContents( 84 ) != NULL &&
				!board.GetSquareContents( 84 )->HasMoved() )
				eval += factor6;
		}
		else if( pawnStartRank[1][4] == 7 )
		{
			if( board.GetSquareContents( 64 ) != NULL &&
				board.GetSquareContents( 74 ) != NULL &&
				!board.GetSquareContents( 74 )->HasMoved() )
				eval += factor6;
		}
		if( pawnStartRank[1][5] == 8 )
		{
			if( board.GetSquareContents( 75 ) != NULL &&
				board.GetSquareContents( 85 ) != NULL &&
				!board.GetSquareContents( 85 )->HasMoved() )
				eval += factor6;
		}
		else if( pawnStartRank[1][5] == 7 )
		{
			if( board.GetSquareContents( 65 ) != NULL &&
				board.GetSquareContents( 75 ) != NULL &&
				!board.GetSquareContents( 75 )->HasMoved() )
				eval += factor6;
		}
		if( pawnStartRank[1][6] == 8 )
		{
			if( board.GetSquareContents( 76 ) != NULL &&
				board.GetSquareContents( 86 ) != NULL &&
				!board.GetSquareContents( 86 )->HasMoved() )
				eval += factor5;
		}
		else if( pawnStartRank[1][6] == 7 )
		{
			if( board.GetSquareContents( 66 ) != NULL &&
				board.GetSquareContents( 76 ) != NULL &&
				!board.GetSquareContents( 76 )->HasMoved() )
				eval += factor5;
		}
	}	
	else if( board.GetNumberOfCapturedPieces() > 30 ||
		board.GetMaterial( 0 ) - board.GetPawnMaterial( 0 ) + 
		board.GetMaterial( 1 ) - board.GetPawnMaterial( 1 ) < 20000 )
		//	we are in the end-game
		currentPhase = phases + 2;
	else
		//	we are in the mid-game
		currentPhase = phases + 1;


	if( pPawnHash != NULL )
	{
		// *** 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.
		BitBoard128 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_10x10[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_10x10[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_10x10[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_10x10[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_10x10[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_10x10[board.flipSquare[1][square]] * piece->GetType().gameInt1;
				int pawnSquare1 = board.GetMovementMatrix( DIRECTION_NE )[square];
				int pawnSquare2 = board.GetMovementMatrix( DIRECTION_NW )[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_10x10[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_10x10[board.flipSquare[1][square]] * piece->GetType().gameInt1) >> 1;
			}
		}

		// *** ROOK ON OPEN and SEMI-OPEN FILE BONUS *** //
		BitBoard128 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
	//		TODO: temporarily removed

	return *currentPhase;
}

int DecimalChessGame::EnumeratePromotions
	( Piece *piece, 
	  int fromSquare,
	  int toSquare,
	  PieceType **promotions,
	  bool quiescentSearch )
{
	// *** 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] != &NullPieceType128::nullPieceType128 )
		{
			promotionTypeCount++;
			promotions[0] = majorPieceTypes[piece->GetPlayerNumber()][0];
			if( majorPieceTypes[piece->GetPlayerNumber()][1] != &NullPieceType128::nullPieceType128 )
			{
				promotionTypeCount++;
				promotions[1] = majorPieceTypes[piece->GetPlayerNumber()][1];
				if( majorPieceTypes[piece->GetPlayerNumber()][2] != &NullPieceType128::nullPieceType128 )
				{
					promotionTypeCount++;
					promotions[2] = majorPieceTypes[piece->GetPlayerNumber()][2];
					if( majorPieceTypes[piece->GetPlayerNumber()][3] != &NullPieceType128::nullPieceType128 )
					{
						promotionTypeCount++;
						promotions[3] = majorPieceTypes[piece->GetPlayerNumber()][3];
					}
				}
			}
		}
		return promotionTypeCount;
	}
	// *** STANDARD pawn promotion *** //
	return( Game::EnumeratePromotions( piece, fromSquare, toSquare, promotions, quiescentSearch ) );
}

int DecimalChessGame::EnumeratePromotions
	( Piece *piece, 
	  int fromSquare,
	  int toSquare,
	  Piece **pieces,
	  bool quiescentSearch )
{
	int count = 0;

	if( toSquare >= 10 && toSquare < 90 )
		//	promotion is optional here, so push "exchange" to same piece
		pieces[count++] = piece;

	int nTypesFound = 0;
	int typesFound[20];

	for( int x = 0; x < board.GetNumberOfPieces( piece->GetPlayerNumber() ); x++ )
	{
		Piece *currentPiece = board.GetPiece( piece->GetPlayerNumber(), x );
		if( currentPiece->IsCaptured() )
		{
			bool alreadyFound = false;
			for( int x = 0; x < nTypesFound; x++ )
				if( typesFound[x] == currentPiece->GetType().GetTypeID() )
				{
					alreadyFound = true;
					break;
				}
			if( !alreadyFound && !currentPiece->GetType().IsPawn() && 
				!currentPiece->GetType().IsRoyal() )
			{
				typesFound[nTypesFound++] = currentPiece->GetType().GetTypeID();
				pieces[count++] = currentPiece;
			}
		}
	}

	return count;
}

word32 DecimalChessGame::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( 91 );
			if( castlingPiece != NULL && 
				!castlingPiece->HasMoved() )
				primaryHash ^= castlingHash1q;
			castlingPiece = board.GetSquareContents( 98 );
			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( 90 );
			if( castlingPiece != NULL && 
				!castlingPiece->HasMoved() )
				primaryHash ^= castlingHash1q;
			castlingPiece = board.GetSquareContents( 99 );
			if( castlingPiece != NULL && 
				!castlingPiece->HasMoved() )
				primaryHash ^= castlingHash1k;
		}
	}
	
	// *** adjust for en passant square *** //
	if( enPassant )
		return primaryHash ^ GetEnPassantHash( board.GetCurrentGameRecord(), enPassantHashMap );
	return primaryHash;
}

void DecimalChessGame::DefaultSettings()
{
	if( !strcmp( selectedVariant->name, "Shatranj Kamil" ) )
	{
		squareColor1 = RGB(255, 255, 204);
		squareColor2 = RGB(211, 211, 126);
		squareColor3 = RGB(224, 224, 132);
		pieceColor1 = RGB(255, 255, 255);
		pieceColor2 = RGB(89, 132, 189);
		borderColor = RGB(158, 124, 52);
		boardDisplayType = BOARD_IS_UNCHECKERED;
		selectedPieceSet = PIECE_SET_OLD_WORLD;
	}
	else if( !strcmp( selectedVariant->name, "Archchess" ) )
	{
		squareColor1 = RGB(255, 255, 220);
		squareColor2 = RGB(150, 175, 161);
		squareColor3 = RGB(51, 200, 51);
		pieceColor1 = RGB(255, 255, 255);
		pieceColor2 = RGB(0, 0, 0);
		borderColor = RGB(108, 0, 0);
		boardDisplayType = BOARD_IS_CHECKERED;
		selectedPieceSet = PIECE_SET_OLD_WORLD;
	}
	else if( !strcmp( selectedVariant->name, "Unicorn Chess" ) || 
		     !strcmp( selectedVariant->name, "Unicorn Great Chess" ) || 
		     !strcmp( selectedVariant->name, "Unicorn Grand 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 DecimalChessGame::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 );
	}
}
