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

                                 ChessV

                   COPYRIGHT (C) 2005 BY GREGORY STRONG

This file is part of ChessV.  ChessV is free software; you can redistribute
it and/or modify it under the terms of the GNU General Public License as 
published by the Free Software Foundation; either version 2 of the License, 
or (at your option) any later version.

ChessV is distributed in the hope that it will be useful, but WITHOUT ANY 
WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
more details; the file 'COPYING' contains the License text, but if for
some reason you need a copy, please write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

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


#include "StdAfx.h"
#include "PieceType.h"
#include "Player.h"
#include "Piece.h"
#include "Board.h"
#include "ChessV.h"
#include "Game.h"
#include "Games/ChessGames/ChessGame.h"


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


NullPieceType64 NullPieceType64::nullPieceType64;
NullPieceType96 NullPieceType96::nullPieceType96;
NullPieceType128 NullPieceType128::nullPieceType128;
OrthodoxRook OrthodoxRook::orthodoxRook;
OrthodoxBishop OrthodoxBishop::orthodoxBishop;
OrthodoxKnight OrthodoxKnight::orthodoxKnight;
OrthodoxQueen OrthodoxQueen::orthodoxQueen;
OrthodoxPawn OrthodoxPawn::orthodoxPawn;
OrthodoxKing OrthodoxKing::orthodoxKing;
SpartanKing SpartanKing::spartanKing;
LamePawn LamePawn::lamePawn;
Hoplite Hoplite::hoplite;
Elephant Elephant::elephant;
Ferz Ferz::ferz;
ElephantFerz ElephantFerz::elephantFerz;
Lieutenant Lieutenant::lieutenant;
General General::general;
Phoenix Phoenix::phoenix;
Cleric Cleric::cleric;
WarElephant WarElephant::warElephant;
Archbishop Archbishop::archbishop;
ChargingRook ChargingRook::chargingRook;
NarrowKnight NarrowKnight::narrowKnight;
ChargingKnight ChargingKnight::chargingKnight;
Colonel Colonel::colonel;
SilverGeneral SilverGeneral::silverGeneral;
ShortRook ShortRook::shortRook;
Bowman Bowman::bowman;
Lion Lion::lion;
Chancellor Chancellor::chancellor;
Forequeen Forequeen::forequeen;
Bishight Bishight::bishight;
Knishop Knishop::knishop;
B4nD B4nD::b4nD;
N2R4 N2R4::n2R4;
Fourfer Fourfer::fourfer;
SV7 SV7::sv7;
GreaterKnight GreaterKnight::greaterKnight;
ShortQueen ShortQueen::shortQueen;
DragonKing DragonKing::dragonKing;
DragonHorse DragonHorse::dragonHorse;
Tower Tower::tower;
Sage Sage::sage;
Unicorn Unicorn::unicorn;
Knightrider Knightrider::knightrider;
Tiger Tiger::tiger;
Templar Templar::templar;
Scout Scout::scout;
Benz Benz::benz;
Pioneer Pioneer::pioneer;
Cyborg Cyborg::cyborg;
KnightWazir KnightWazir::knightWazir;
KnightFerz KnightFerz::knightFerz;
KnightDabbabah KnightDabbabah::knightDabbabah;
KnightAlfil KnightAlfil::knightAlfil;
EnepKnight EnepKnight::enepKnight;

PieceType *PieceType::pFirstType = NULL;

extern bool testingBoolean;
extern bool testingBoolean2;


PieceType::PieceType
	( const char *extended_name, 
	  const char *name, 
	  const char *abbreviation,
	  int ranks, 
	  int files )
{
	statsInitialized = false;
	nRanks = ranks;
	nFiles = files;
	hBitmap[0] = NULL;
	hBitmap[1] = NULL;
	nMoveCapabilities = 0;
	moveCapabilities = new MovementCapability[MAX_DIRECTIONS];
	defaultExtendedName = new char[strlen(extended_name)+1];
	strcpy( defaultExtendedName, extended_name );
	defaultFullName = new char[strlen(name)+1];
	strcpy( defaultFullName, name );
	defaultAbbrev = new char[strlen(abbreviation)+1];
	strcpy( defaultAbbrev, abbreviation );
	extendedName = NULL;
	fullName = NULL;
	abbrev = NULL;
	squareValues = NULL;
	armyAdjustment = 0;
	fTotalSquaresAttacked = 0.0;
	fTotalCenterSquaresAttacked = 0.0;
	nTotalSafeChecks = 0;
	nTotalDirectionsAttacked = 0;
	nSquaresSeen = 0;
	isPawn = false;
	isRoyal = false;
	useSquareBonuses = false;
	perCaptureValueBonus = 0;
	perCaptureBonusThreshold = 1000;
	pBoard = NULL;
	optimization = NoOptimization;
	gameInt1 = 0;
	gameInt2 = 0;
	hasBeenInitialized = false;

	for( int x = 0; x < MAX_DIRECTIONS; x++ )
	{
		attackRange[0][x] = 0;
		attackRange[1][x] = 0;
		minAttackRange[0][x] = 128;
		minAttackRange[1][x] = 128;
	}

	for( int x = 0; x < MAX_PIECE_SETS; x++ )
	{
		bitmapFileNames[x][0] = NULL;
		bitmapFileNames[x][1] = NULL;
	}

	//	add to linked list of piece types
	pNextType = pFirstType;
	pFirstType = this;
}

PieceType::~PieceType()
{
	if( defaultExtendedName != NULL )
		delete[] defaultExtendedName;
	if( defaultFullName != NULL )
		delete[] defaultFullName;
	if( defaultAbbrev != NULL )
		delete[] defaultAbbrev;
	if( extendedName != NULL )
		delete[] extendedName;
	if( fullName != NULL )
		delete[] fullName;
	if( abbrev != NULL )
		delete[] abbrev;
}

void PieceType::Initialize
	( int personality )
{
	if( !hasBeenInitialized )
	{
		//	clear out old information, if any
		ClearMovementCapabilities();
		if( extendedName != NULL )
			delete[] extendedName;
		if( fullName != NULL )
			delete[] fullName;
		if( abbrev != NULL )
			delete[] abbrev;
		//	re-assign piece names
		int extendedNameSize = (int) strlen(defaultExtendedName) + 1;
		extendedName = new char[extendedNameSize];
		strcpy( extendedName, defaultExtendedName );
		int fullNameSize = (int) strlen(defaultFullName) + 1;
		fullName = new char[fullNameSize];
		strcpy( fullName, defaultFullName );
		int abbrevSize = (int) strlen(defaultAbbrev) + 1;
		abbrev = new char[abbrevSize];
		strcpy( abbrev, defaultAbbrev );
		hasBeenInitialized = true;
	}
}

void PieceType::SetExtendedName
	( char *exName )
{
	if( extendedName != NULL )
		delete[] extendedName;
	int extendedNameSize = (int) strlen(exName) + 1;
	extendedName = new char[extendedNameSize];
	strcpy( extendedName, exName );
}

void PieceType::SetFullName
	( char *name )
{
	if( fullName != NULL )
		delete[] fullName;
	int fullNameSize = (int) strlen(name) + 1;
	fullName = new char[fullNameSize];
	strcpy( fullName, name );
}

void PieceType::SetNotation
	( char *notation )
{
	if( abbrev != NULL )
		delete[] abbrev;
	int abbrevSize = (int) strlen(notation) + 1;
	abbrev = new char[abbrevSize];
	strcpy( abbrev, notation );
}

void PieceType::SetBoard( Board *pointerToBoard )
{
	pBoard = pointerToBoard;

	hashMap[0].Initialize( pBoard->GetNumberOfSquares() );
	hashMap[1].Initialize( pBoard->GetNumberOfSquares() );
	secondaryHashMap[0].Initialize( pBoard->GetNumberOfSquares() );
	secondaryHashMap[1].Initialize( pBoard->GetNumberOfSquares() );

	for( int x = 0; x < nMoveCapabilities; x++ )
	{
		MovementCapability &move = moveCapabilities[x];
		int oppositeDirection = pBoard->GetDirection( move.GetDirectionNumber() ).GetOppositeDirectionNumber();
		if( move.CanCapture() || move.CanIguiCapture() )
		{
			attackRange[0][move.GetDirectionNumber()] = move.GetMaxSteps();
			attackRange[1][oppositeDirection] = move.GetMaxSteps();
			minAttackRange[0][move.GetDirectionNumber()] = move.GetMinSteps();
			minAttackRange[1][oppositeDirection] = move.GetMinSteps();
		}
	}
}

void PieceType::SetPieceDefaults( Piece *piece )
{
}

bool PieceType::operator==( PieceType &other )
{
	return( !strcmp( extendedName, other.extendedName ) && 
		    nFiles == other.GetNumberOfFiles() && nRanks == other.GetNumberOfRanks() );
}

void PieceType::FindSquare( Board &board, Player &player, int rank, int file, int &nSquaresSeen )
{
	//	initialize reference to the square
	PieceSquareInfo &square = squareValues[rank * pBoard->GetNumberOfFiles() + file];

	//	mark square as 'found'
	square.found = true;
	nSquaresSeen++;

	//	iterate through each move capability (or move direction)
	for( int i = 0; i < nMoveCapabilities; i++ )
	{
		//	initialize move vector for this movement direction
		MovementCapability &move = moveCapabilities[i];

		//	initialize flag to stop our movement when we hit the edge of the board
		bool onBoard = true;

		//	iterate through the maximum number of steps we may move in this
		//	direction, or until we leave the edge of the board
		float factor = 1.0;
		for( int j = 1; j <= move.GetMaxSteps() && onBoard; j++ )
		{
			//	find new rank and file
			int nRank = rank + move.GetRankDifference( player ) * j;
			int nFile = file + move.GetFileDifference( player ) * j;

			//	are we still on the board?
			onBoard = nFile >= 0 && nFile < pBoard->GetNumberOfFiles() &&
			          nRank >= 0 && nRank < pBoard->GetNumberOfRanks();
				           
			if( onBoard && j <= move.GetMinSteps() )
			{
				if( j == 1 )
				{
					//	another direction attacked
					square.nDirectionsAttacked++;
				}

				if( move.GetFileDifference( player ) > 1 || move.GetFileDifference( player ) < -1 ||
					move.GetRankDifference( player ) > 1 || move.GetRankDifference( player ) < -1 || j > 1 )
				{
					square.nSafeChecks++;
				}

				//	another square attacked
				square.fSquaresAttacked += factor;

				if( nRank >= 2 && nRank <= 5 &&
					nFile >= 2 && nFile <= 5 )
					//	another center square attacked
					square.fCenterSquaresAttacked += factor;

				factor *= (float) 0.7;
			}
		}
	}
	
	//	iterate through each move capability (or move direction) again,
	//	this time recursively calling FindSquare() so that we calculate
	//	the statistics for that square as well.
	for( int i = 0; i < nMoveCapabilities; i++ )
	{
		//	initialize move vector for this movement direction
		MovementCapability &move = moveCapabilities[i];

		//	initialize flag to stop our movement when we hit the edge of the board
		bool onBoard = true;

		//	find new rank and file
		int nRank = rank + move.GetRankDifference( player );
		int nFile = file + move.GetFileDifference( player );

		//	are we still on the board?
		onBoard = nFile >= 0 && nFile < pBoard->GetNumberOfFiles() &&
			      nRank >= 0 && nRank < pBoard->GetNumberOfRanks();
				        
		if( onBoard )
		{
			//	initalize reference to this square
			PieceSquareInfo &squareValue = squareValues[nRank * pBoard->GetNumberOfFiles() + nFile];

			//	check to see if we've marked this square before
			if( !squareValue.found )
			{
				//	we haven't marked this square yet, so recursively call
				//	this function, so that we index and mark it.
				FindSquare( board, player, nRank, nFile, nSquaresSeen );
			}
		}
	}
}

void PieceType::ReduceBoardSize
	( int newRanks, 
	  int newFiles )
{
	ASSERT(newRanks <= nRanks);
	ASSERT(newFiles <= nFiles);
	nRanks = newRanks;
	nFiles = newFiles;
}

int PieceType::PlaceOnBoard
	( Board &board, 
	  Player &player, 
	  int rank, 
	  int file )
{
	if( statsInitialized )
		return 0;

	//	allocate space for all squares on the board; this space will store
	//	information about how much strength a piece has on any given square
	//	(i.e., how many squares it attacks, and in how many directions it attacks)
	squareValues = new PieceSquareInfo[pBoard->GetNumberOfSquares()];

	//	initialize pointer to the square the piece occupies initially
	PieceSquareInfo &square = squareValues[rank * pBoard->GetNumberOfFiles() + file];

	//	initialize counter of squares found
	nSquaresSeen = 0;

	if( !square.found )
		FindSquare( board, player, rank, file, nSquaresSeen );

	for( int f = 0; f < pBoard->GetNumberOfFiles(); f++ )
	{
		for( int r = 0; r < pBoard->GetNumberOfRanks(); r++ )
		{
			PieceSquareInfo &sq = squareValues[r * pBoard->GetNumberOfFiles() + f];
			if( sq.found )
			{
				nTotalDirectionsAttacked += sq.GetDirectionsAttacked();
				fTotalSquaresAttacked += sq.GetSquaresAttacked();
				nTotalSafeChecks += sq.GetSafeChecks();
			}
		}
	}

	aveDirectionsAttacked = (float) nTotalDirectionsAttacked / nSquaresSeen;
	aveSquaresAttacked = (float) fTotalSquaresAttacked / nSquaresSeen;
	aveSafeChecks = (float) nTotalSafeChecks / nSquaresSeen;

	return nSquaresSeen;
}

void PieceType::GenerateAreaMoves
	( MovementList &moves,
	  Board &board,
	  Piece &piece,
	  int squareNumber,
	  int maxSteps )
{
#ifdef NOT_USED_AT_THIS_TIME
	static int squareFound[12];
	memset( squareFound, 0, sizeof(squareFound) );
	//	first step is NW
	int step1 = board.GetMovementMatrix( DIRECTION_NW )[squareNumber];
	if( step1 != -1 )
	{
		Piece *pieceOnSquare = board.GetSquareContents( step1 );
		if( pieceOnSquare != NULL )
		{
			if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
				moves.AddCapture( squareNumber, step1 );
		}
		else
		{
			moves.AddMove( squareNumber, step1 );
			int step2 = board.GetMovementMatrix( DIRECTION_NW )[step1];
			if( step2 != -1 )
			{
				pieceOnSquare = board.GetSquareContents( step2 );
				if( pieceOnSquare != NULL )
				{
					if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
						moves.AddCapture( squareNumber, step2 );
				}
				else
					moves.AddMove( squareNumber, step2 );
			}
			step2 = board.GetMovementMatrix( DIRECTION_N )[step1];
			if( step2 != -1 )
			{
				pieceOnSquare = board.GetSquareContents( step2 );
				if( pieceOnSquare != NULL )
				{
					if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
					{
						moves.AddCapture( squareNumber, step2 );
						squareFound[0] = 1;
					}
				}
				else
				{
					moves.AddMove( squareNumber, step2 );
					squareFound[0] = 1;
				}
			}
			step2 = board.GetMovementMatrix( DIRECTION_NE )[step1];
			if( step2 != -1 )
			{
				pieceOnSquare = board.GetSquareContents( step2 );
				if( pieceOnSquare != NULL )
				{
					if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
					{
						moves.AddCapture( squareNumber, step2 );
						squareFound[1] = 1;
					}
				}
				else
				{
					moves.AddMove( squareNumber, step2 );
					squareFound[1] = 1;
				}
			}
			step2 = board.GetMovementMatrix( DIRECTION_W )[step1];
			if( step2 != -1 )
			{
				pieceOnSquare = board.GetSquareContents( step2 );
				if( pieceOnSquare != NULL )
				{
					if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
					{
						moves.AddCapture( squareNumber, step2 );
						squareFound[3] = 1;
					}
				}
				else
				{
					moves.AddMove( squareNumber, step2 );
					squareFound[3] = 1;
				}
			}
			step2 = board.GetMovementMatrix( DIRECTION_SW )[step1];
			if( step2 != -1 )
			{
				pieceOnSquare = board.GetSquareContents( step2 );
				if( pieceOnSquare != NULL )
				{
					if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
					{
						moves.AddCapture( squareNumber, step2 );
						squareFound[5] = 1;
					}
				}
				else
				{
					moves.AddMove( squareNumber, step2 );
					squareFound[5] = 1;
				}
			}
		}
	}
	//	first step is SE
	step1 = board.GetMovementMatrix( DIRECTION_SE )[squareNumber];
	if( step1 != -1 )
	{
		Piece *pieceOnSquare = board.GetSquareContents( step1 );
		if( pieceOnSquare != NULL )
		{
			if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
				moves.AddCapture( squareNumber, step1 );
		}
		else
		{
			moves.AddMove( squareNumber, step1 );
			int step2 = board.GetMovementMatrix( DIRECTION_SE )[step1];
			if( step2 != -1 )
			{
				pieceOnSquare = board.GetSquareContents( step2 );
				if( pieceOnSquare != NULL )
				{
					if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
						moves.AddCapture( squareNumber, step2 );
				}
				else
					moves.AddMove( squareNumber, step2 );
			}
			step2 = board.GetMovementMatrix( DIRECTION_S )[step1];
			if( step2 != -1 )
			{
				pieceOnSquare = board.GetSquareContents( step2 );
				if( pieceOnSquare != NULL )
				{
					if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
					{
						moves.AddCapture( squareNumber, step2 );
						squareFound[11] = 1;
					}
				}
				else
				{
					moves.AddMove( squareNumber, step2 );
					squareFound[11] = 1;
				}
			}
			step2 = board.GetMovementMatrix( DIRECTION_SW )[step1];
			if( step2 != -1 )
			{
				pieceOnSquare = board.GetSquareContents( step2 );
				if( pieceOnSquare != NULL )
				{
					if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
					{
						moves.AddCapture( squareNumber, step2 );
						squareFound[10] = 1;
					}
				}
				else
				{
					moves.AddMove( squareNumber, step2 );
					squareFound[10] = 1;
				}
			}
			step2 = board.GetMovementMatrix( DIRECTION_E )[step1];
			if( step2 != -1 )
			{
				pieceOnSquare = board.GetSquareContents( step2 );
				if( pieceOnSquare != NULL )
				{
					if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
					{
						moves.AddCapture( squareNumber, step2 );
						squareFound[8] = 1;
					}
				}
				else
				{
					moves.AddMove( squareNumber, step2 );
					squareFound[8] = 1;
				}
			}
			step2 = board.GetMovementMatrix( DIRECTION_NE )[step1];
			if( step2 != -1 )
			{
				pieceOnSquare = board.GetSquareContents( step2 );
				if( pieceOnSquare != NULL )
				{
					if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
					{
						moves.AddCapture( squareNumber, step2 );
						squareFound[6] = 1;
					}
				}
				else
				{
					moves.AddMove( squareNumber, step2 );
					squareFound[6] = 1;
				}
			}
		}
	}
	//	first move NE
	step1 = board.GetMovementMatrix( DIRECTION_NE )[squareNumber];
	if( step1 != -1 )
	{
		Piece *pieceOnSquare = board.GetSquareContents( step1 );
		if( pieceOnSquare != NULL )
		{
			if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
				moves.AddCapture( squareNumber, step1 );
		}
		else
		{
			moves.AddMove( squareNumber, step1 );
			int step2 = board.GetMovementMatrix( DIRECTION_NE )[step1];
			if( step2 != -1 )
			{
				pieceOnSquare = board.GetSquareContents( step2 );
				if( pieceOnSquare != NULL )
				{
					if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
						moves.AddCapture( squareNumber, step2 );
				}
				else
					moves.AddMove( squareNumber, step2 );
			}
			step2 = board.GetMovementMatrix( DIRECTION_N )[step1];
			if( step2 != -1 )
			{
				pieceOnSquare = board.GetSquareContents( step2 );
				if( pieceOnSquare != NULL )
				{
					if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
					{
						moves.AddCapture( squareNumber, step2 );
						squareFound[2] = 1;
					}
				}
				else
				{
					moves.AddMove( squareNumber, step2 );
					squareFound[2] = 1;
				}
			}
			if( squareFound[1] == 0 )
			{
				step2 = board.GetMovementMatrix( DIRECTION_NW )[step1];
				if( step2 != -1 )
				{
					pieceOnSquare = board.GetSquareContents( step2 );
					if( pieceOnSquare != NULL )
					{
						if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
						{
							moves.AddCapture( squareNumber, step2 );
							squareFound[10] = 1;
						}
					}
					else
					{
						moves.AddMove( squareNumber, step2 );
						squareFound[10] = 1;
					}
				}
			}
			step2 = board.GetMovementMatrix( DIRECTION_E )[step1];
			if( step2 != -1 )
			{
				pieceOnSquare = board.GetSquareContents( step2 );
				if( pieceOnSquare != NULL )
				{
					if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
					{
						moves.AddCapture( squareNumber, step2 );
						squareFound[4] = 1;
					}
				}
				else
				{
					moves.AddMove( squareNumber, step2 );
					squareFound[4] = 1;
				}
			}
			if( squareFound[6] == 0 )
			{
				step2 = board.GetMovementMatrix( DIRECTION_SE )[step1];
				if( step2 != -1 )
				{
					pieceOnSquare = board.GetSquareContents( step2 );
					if( pieceOnSquare != NULL )
					{
						if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
						{
							moves.AddCapture( squareNumber, step2 );
							squareFound[6] = 1;
						}
					}
					else
					{
						moves.AddMove( squareNumber, step2 );
						squareFound[6] = 1;
					}
				}
			}
		}
	}
	//	first move SW
	step1 = board.GetMovementMatrix( DIRECTION_SW )[squareNumber];
	if( step1 != -1 )
	{
		Piece *pieceOnSquare = board.GetSquareContents( step1 );
		if( pieceOnSquare != NULL )
		{
			if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
				moves.AddCapture( squareNumber, step1 );
		}
		else
		{
			moves.AddMove( squareNumber, step1 );
			int step2 = board.GetMovementMatrix( DIRECTION_SW )[step1];
			if( step2 != -1 )
			{
				pieceOnSquare = board.GetSquareContents( step2 );
				if( pieceOnSquare != NULL )
				{
					if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
						moves.AddCapture( squareNumber, step2 );
				}
				else
					moves.AddMove( squareNumber, step2 );
			}
			step2 = board.GetMovementMatrix( DIRECTION_S )[step1];
			if( step2 != -1 )
			{
				pieceOnSquare = board.GetSquareContents( step2 );
				if( pieceOnSquare != NULL )
				{
					if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
					{
						moves.AddCapture( squareNumber, step2 );
						squareFound[9] = 1;
					}
				}
				else
				{
					moves.AddMove( squareNumber, step2 );
					squareFound[9] = 1;
				}
			}
			if( squareFound[10] == 0 )
			{
				step2 = board.GetMovementMatrix( DIRECTION_SE )[step1];
				if( step2 != -1 )
				{
					pieceOnSquare = board.GetSquareContents( step2 );
					if( pieceOnSquare != NULL )
					{
						if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
						{
							moves.AddCapture( squareNumber, step2 );
							squareFound[10] = 1;
						}
					}
					else
					{
						moves.AddMove( squareNumber, step2 );
						squareFound[10] = 1;
					}
				}
			}
			step2 = board.GetMovementMatrix( DIRECTION_W )[step1];
			if( step2 != -1 )
			{
				pieceOnSquare = board.GetSquareContents( step2 );
				if( pieceOnSquare != NULL )
				{
					if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
					{
						moves.AddCapture( squareNumber, step2 );
						squareFound[7] = 1;
					}
				}
				else
				{
					moves.AddMove( squareNumber, step2 );
					squareFound[7] = 1;
				}
			}
			if( squareFound[5] == 0 )
			{
				step2 = board.GetMovementMatrix( DIRECTION_NW )[step1];
				if( step2 != -1 )
				{
					pieceOnSquare = board.GetSquareContents( step2 );
					if( pieceOnSquare != NULL )
					{
						if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
						{
							moves.AddCapture( squareNumber, step2 );
							squareFound[5] = 1;
						}
					}
					else
					{
						moves.AddMove( squareNumber, step2 );
						squareFound[5] = 1;
					}
				}
			}
		}
	}
	//	first move N
	step1 = board.GetMovementMatrix( DIRECTION_N )[squareNumber];
	if( step1 != -1 )
	{
		Piece *pieceOnSquare = board.GetSquareContents( step1 );
		if( pieceOnSquare != NULL )
		{
			if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
				moves.AddCapture( squareNumber, step1 );
		}
		else
		{
			moves.AddMove( squareNumber, step1 );
			if( squareFound[0] == 0 )
			{
				int step2 = board.GetMovementMatrix( DIRECTION_NW )[step1];
				if( step2 != -1 )
				{
					pieceOnSquare = board.GetSquareContents( step2 );
					if( pieceOnSquare != NULL )
					{
						if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
							moves.AddCapture( squareNumber, step2 );
					}
					else
						moves.AddMove( squareNumber, step2 );
				}
			}
			if( squareFound[1] == 0 )
			{
				int step2 = board.GetMovementMatrix( DIRECTION_N )[step1];
				if( step2 != -1 )
				{
					pieceOnSquare = board.GetSquareContents( step2 );
					if( pieceOnSquare != NULL )
					{
						if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
							moves.AddCapture( squareNumber, step2 );
					}
					else
						moves.AddMove( squareNumber, step2 );
				}
			}
			if( squareFound[2] == 0 )
			{
				int step2 = board.GetMovementMatrix( DIRECTION_NE )[step1];
				if( step2 != -1 )
				{
					pieceOnSquare = board.GetSquareContents( step2 );
					if( pieceOnSquare != NULL )
					{
						if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
							moves.AddCapture( squareNumber, step2 );
					}
					else
						moves.AddMove( squareNumber, step2 );
				}
			}
		}
	}
	//	first move S
	step1 = board.GetMovementMatrix( DIRECTION_S )[squareNumber];
	if( step1 != -1 )
	{
		Piece *pieceOnSquare = board.GetSquareContents( step1 );
		if( pieceOnSquare != NULL )
		{
			if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
				moves.AddCapture( squareNumber, step1 );
		}
		else
		{
			moves.AddMove( squareNumber, step1 );
			if( squareFound[10] == 0 )
			{
				int step2 = board.GetMovementMatrix( DIRECTION_S )[step1];
				if( step2 != -1 )
				{
					pieceOnSquare = board.GetSquareContents( step2 );
					if( pieceOnSquare != NULL )
					{
						if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
							moves.AddCapture( squareNumber, step2 );
					}
					else
						moves.AddMove( squareNumber, step2 );
				}
			}
			if( squareFound[9] == 0 )
			{
				int step2 = board.GetMovementMatrix( DIRECTION_SW )[step1];
				if( step2 != -1 )
				{
					pieceOnSquare = board.GetSquareContents( step2 );
					if( pieceOnSquare != NULL )
					{
						if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
							moves.AddCapture( squareNumber, step2 );
					}
					else
						moves.AddMove( squareNumber, step2 );
				}
			}
			if( squareFound[11] == 0 )
			{
				int step2 = board.GetMovementMatrix( DIRECTION_SE )[step1];
				if( step2 != -1 )
				{
					pieceOnSquare = board.GetSquareContents( step2 );
					if( pieceOnSquare != NULL )
					{
						if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
							moves.AddCapture( squareNumber, step2 );
					}
					else
						moves.AddMove( squareNumber, step2 );
				}
			}
		}
	}
	//	first move E
	step1 = board.GetMovementMatrix( DIRECTION_E )[squareNumber];
	if( step1 != -1 )
	{
		Piece *pieceOnSquare = board.GetSquareContents( step1 );
		if( pieceOnSquare != NULL )
		{
			if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
				moves.AddCapture( squareNumber, step1 );
		}
		else
		{
			moves.AddMove( squareNumber, step1 );
			if( squareFound[6] == 0 )
			{
				int step2 = board.GetMovementMatrix( DIRECTION_E )[step1];
				if( step2 != -1 )
				{
					pieceOnSquare = board.GetSquareContents( step2 );
					if( pieceOnSquare != NULL )
					{
						if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
							moves.AddCapture( squareNumber, step2 );
					}
					else
						moves.AddMove( squareNumber, step2 );
				}
			}
			if( squareFound[4] == 0 )
			{
				int step2 = board.GetMovementMatrix( DIRECTION_NE )[step1];
				if( step2 != -1 )
				{
					pieceOnSquare = board.GetSquareContents( step2 );
					if( pieceOnSquare != NULL )
					{
						if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
							moves.AddCapture( squareNumber, step2 );
					}
					else
						moves.AddMove( squareNumber, step2 );
				}
			}
			if( squareFound[8] == 0 )
			{
				int step2 = board.GetMovementMatrix( DIRECTION_SE )[step1];
				if( step2 != -1 )
				{
					pieceOnSquare = board.GetSquareContents( step2 );
					if( pieceOnSquare != NULL )
					{
						if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
							moves.AddCapture( squareNumber, step2 );
					}
					else
						moves.AddMove( squareNumber, step2 );
				}
			}
		}
	}
	//	first move W
	step1 = board.GetMovementMatrix( DIRECTION_W )[squareNumber];
	if( step1 != -1 )
	{
		Piece *pieceOnSquare = board.GetSquareContents( step1 );
		if( pieceOnSquare != NULL )
		{
			if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
				moves.AddCapture( squareNumber, step1 );
		}
		else
		{
			moves.AddMove( squareNumber, step1 );
			if( squareFound[5] == 0 )
			{
				int step2 = board.GetMovementMatrix( DIRECTION_W )[step1];
				if( step2 != -1 )
				{
					pieceOnSquare = board.GetSquareContents( step2 );
					if( pieceOnSquare != NULL )
					{
						if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
							moves.AddCapture( squareNumber, step2 );
					}
					else
						moves.AddMove( squareNumber, step2 );
				}
			}
			if( squareFound[3] == 0 )
			{
				int step2 = board.GetMovementMatrix( DIRECTION_NW )[step1];
				if( step2 != -1 )
				{
					pieceOnSquare = board.GetSquareContents( step2 );
					if( pieceOnSquare != NULL )
					{
						if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
							moves.AddCapture( squareNumber, step2 );
					}
					else
						moves.AddMove( squareNumber, step2 );
				}
			}
			if( squareFound[7] == 0 )
			{
				int step2 = board.GetMovementMatrix( DIRECTION_SW )[step1];
				if( step2 != -1 )
				{
					pieceOnSquare = board.GetSquareContents( step2 );
					if( pieceOnSquare != NULL )
					{
						if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
							moves.AddCapture( squareNumber, step2 );
					}
					else
						moves.AddMove( squareNumber, step2 );
				}
			}
		}
	}
#endif
}

void PieceType::GenerateMoves
	( MovementList &moves,
	  Board &board,
	  Piece &piece,
	  int squareNumber )
{
	//	find starting square number
	int startSquareNumber = squareNumber;

	if( optimization == NoOptimization )
	{
		//	iterate through each move capability (or move direction)
		for( int i = 0; i < nMoveCapabilities; i++ )
		{
			//	initialize move vector for this movement direction
			MovementCapability &move = moveCapabilities[i];

			//	check to make sure we satisify the requirements for this move
			if( move.IsInZone( board.flipSquare[piece.GetPlayerNumber()][squareNumber] ) )
			{
				if( move.GetType() == AreaMover )
				{
					GenerateAreaMoves( moves, board, piece, squareNumber, move.GetMaxSteps() );
					continue;
				}

				int nSquare = squareNumber;

				//	initialize flag to stop our movement when we hit the edge of the board,
				//	or encounter an obstacle (friendly or enemy piece)
				bool hitObstacle = false;

				// *** CAPTURE by WITHDRAW *** //
				int withdrawCaptureSquare = -1;
				int withdrawCaptureValue;
				if( move.CapturesByWithdrawing() )
				{
					int oppositeDirectionNumber = pBoard->GetDirection( move.GetDirectionNumber() ).GetOppositeDirectionNumber();
					int *oppositeMatrix = piece.GetPlayerNumber() == 0 ? pBoard->GetMovementMatrix( oppositeDirectionNumber ) :
						pBoard->GetOppositeMovementMatrix( oppositeDirectionNumber );
					withdrawCaptureSquare = oppositeMatrix[squareNumber];
					if( withdrawCaptureSquare >= 0 )
						if( pBoard->GetSquareContents( withdrawCaptureSquare ) == NULL ||
							pBoard->GetSquareContents( withdrawCaptureSquare )->GetPlayerNumber() == piece.GetPlayerNumber() )
							//	nothing to capture by withdraw
							withdrawCaptureSquare = -1;
						else
							withdrawCaptureValue = pBoard->GetSquareContents( withdrawCaptureSquare )->GetBaseValue();
				}

				int directionNumber = move.GetDirectionNumber();
				int *movementMatrix = piece.GetPlayerNumber() == 0 ? pBoard->GetMovementMatrix( directionNumber ) :
					pBoard->GetOppositeMovementMatrix( directionNumber );

				//	iterate through the maximum number of steps we may move in this
				//	direction, or until we leave the edge of the board

				nSquare = movementMatrix[nSquare];

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

					if( pieceOnSquare == NULL && move.CanMove() && move.GetMinSteps() <= 1 )
					{
						//	square is empty; ok to add move
						if( withdrawCaptureSquare == -1 )
						{
							if( move.CapturesByAdvancing() &&
								movementMatrix[nSquare] != -1 && 
								pBoard->GetSquareContents( movementMatrix[nSquare] ) != NULL &&
								pBoard->GetSquareContents( movementMatrix[nSquare] )->GetPlayerNumber() != piece.GetPlayerNumber() )
							{
								// *** CAPTURE by ADVANCE *** //
								moves.BeginMoveAdd( CaptureByAdvance, startSquareNumber, nSquare );
								moves.AddPickUp( startSquareNumber );
								moves.AddPickUp( movementMatrix[nSquare] );
								moves.AddDrop( &piece, nSquare );
								moves.EndMoveAdd( pBoard->GetSquareContents( movementMatrix[nSquare] )->GetBaseValue() + 750 );
							}
							else
								//	perfectly normal move
								moves.AddMove( startSquareNumber, nSquare );
						}
						else
						{
							if( move.CapturesByAdvancing() &&
								movementMatrix[nSquare] != -1 && 
								pBoard->GetSquareContents( movementMatrix[nSquare] ) != NULL &&
								pBoard->GetSquareContents( movementMatrix[nSquare] )->GetPlayerNumber() != piece.GetPlayerNumber() )
							{
								// *** CAPTURE by WITHDRAW and ADVANCE *** //
								moves.BeginMoveAdd( CaptureByAdvanceAndWithdrawl, startSquareNumber, nSquare );
								moves.AddPickUp( startSquareNumber );
								moves.AddPickUp( withdrawCaptureSquare );
								moves.AddPickUp( movementMatrix[nSquare] );
								moves.AddDrop( &piece, nSquare );
								moves.EndMoveAdd( pBoard->GetSquareContents( withdrawCaptureSquare )->GetBaseValue() + 
									withdrawCaptureValue + 900 );
							}
							else
							{
								// *** CAPTURE by WITHDRAW *** //
								moves.BeginMoveAdd( CaptureByWithdrawl, startSquareNumber, nSquare );
								moves.AddPickUp( startSquareNumber );
								moves.AddPickUp( withdrawCaptureSquare );
								moves.AddDrop( &piece, nSquare );
								moves.EndMoveAdd( withdrawCaptureValue + 300 );
							}
						}
					}
					else if( pieceOnSquare != NULL )
					{
						//	hit an obsticle; we're done moving in this direction
						hitObstacle = true;

						if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() && 
							move.GetMinSteps() <= 1 )
						{
							//	square has enemy
							if( move.CanCapture() )
								moves.AddCapture( startSquareNumber, nSquare );
							if( move.CanIguiCapture() )
								moves.AddIguiCapture( startSquareNumber, nSquare );
						}
					}
				}
				else
					//	edge of board; we're done
					hitObstacle = true;

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

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

						if( pieceOnSquare == NULL && move.CanMove() && move.GetMinSteps() <= j )
						{
							//	square is empty; ok to add move
							if( withdrawCaptureSquare == -1 )
							{
								if( move.CapturesByAdvancing() &&
									movementMatrix[nSquare] != -1 && 
									pBoard->GetSquareContents( movementMatrix[nSquare] ) != NULL &&
									pBoard->GetSquareContents( movementMatrix[nSquare] )->GetPlayerNumber() != piece.GetPlayerNumber() )
								{
									// *** CAPTURE by ADVANCE *** //
									moves.BeginMoveAdd( CaptureByAdvance, startSquareNumber, nSquare );
									moves.AddPickUp( startSquareNumber );
									moves.AddPickUp( movementMatrix[nSquare] );
									moves.AddDrop( &piece, nSquare );
									moves.EndMoveAdd( pBoard->GetSquareContents( movementMatrix[nSquare] )->GetBaseValue() + 750 );
								}
								else
									//	perfectly normal move
									moves.AddMove( startSquareNumber, nSquare );
							}
							else
							{
								if( move.CapturesByAdvancing() &&
									movementMatrix[nSquare] != -1 && 
									pBoard->GetSquareContents( movementMatrix[nSquare] ) != NULL &&
									pBoard->GetSquareContents( movementMatrix[nSquare] )->GetPlayerNumber() != piece.GetPlayerNumber() )
								{
									// *** CAPTURE by WITHDRAWL and ADVANCE *** //
									moves.BeginMoveAdd( CaptureByAdvanceAndWithdrawl, startSquareNumber, nSquare );
									moves.AddPickUp( startSquareNumber );
									moves.AddPickUp( withdrawCaptureSquare );
									moves.AddPickUp( movementMatrix[nSquare] );
									moves.AddDrop( &piece, nSquare );
									moves.EndMoveAdd( pBoard->GetSquareContents( movementMatrix[nSquare] )->GetBaseValue() + 
										withdrawCaptureValue + 900 );
								}
								else
								{
									// *** CAPTURE by WITHDRAWL *** //
									moves.BeginMoveAdd( CaptureByWithdrawl, startSquareNumber, nSquare );
									moves.AddPickUp( startSquareNumber );
									moves.AddPickUp( withdrawCaptureSquare );
									moves.AddDrop( &piece, nSquare );
									moves.EndMoveAdd( withdrawCaptureValue + 300 );
								}
							}
						}
						else if( pieceOnSquare != NULL )
						{
							//	hit an obsticle; we're done moving in this direction
							hitObstacle = true;

							if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() && 
								move.GetMinSteps() <= j )
							{
								//	square has enemy
								if( move.CanCapture() )
									moves.AddCapture( startSquareNumber, nSquare );
								else if( move.CanIguiCapture() )
									moves.AddIguiCapture( startSquareNumber, nSquare );
							}
						}
					}
					else
						//	edge of board; we're done
						hitObstacle = true;
				}
			}
		}
	}
	else if( optimization == SimpleSingleStep )
	{
		//	iterate through each move capability (or move direction)
		for( int i = 0; i < nMoveCapabilities; i++ )
		{
			//	initialize move vector for this movement direction
			MovementCapability &move = moveCapabilities[i];

			int directionNumber = move.GetDirectionNumber();
			int *movementMatrix = piece.GetPlayerNumber() == 0 ? pBoard->GetMovementMatrix( directionNumber ) :
				pBoard->GetOppositeMovementMatrix( directionNumber );
			int nSquare = movementMatrix[startSquareNumber];

			//	are we still on the board?
			if( nSquare >= 0 )
			{
				Piece *pieceOnSquare = pBoard->GetSquareContents( nSquare );
				if( pieceOnSquare == NULL )
				{
					//	square is empty; ok to add move
					moves.AddMove( startSquareNumber, nSquare );
				}
				else if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
				{
					//	square has enemy; add move
					moves.AddCapture( startSquareNumber, nSquare );
				}
			}
		}
	}
	else if( optimization == SimpleSlider )
	{
		//	iterate through each move capability (or move direction)
		for( int i = 0; i < nMoveCapabilities; i++ )
		{
			//	initialize move vector for this movement direction
			MovementCapability &move = moveCapabilities[i];

			int nSquare = squareNumber;

			int directionNumber = move.GetDirectionNumber();
			int *movementMatrix = piece.GetPlayerNumber() == 0 ? pBoard->GetMovementMatrix( directionNumber ) :
				pBoard->GetOppositeMovementMatrix( directionNumber );

			//	iterate through the maximum number of steps we may move in this
			//	direction, or until we leave the edge of the board
			nSquare = movementMatrix[nSquare];

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

				if( pieceOnSquare == NULL )
				{
					moves.AddMove( startSquareNumber, nSquare );
				}
				else
				{
					if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
						//	square has enemy; push capture
						moves.AddCapture( startSquareNumber, nSquare );

					//	hit an obsticle; we're done moving in this direction
					nSquare = -1;
				}
			}

			//	keep "stepping" in this direction as long as we can
			while( nSquare != -1 )
			{
				//	find new rank and file
				nSquare = movementMatrix[nSquare];

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

					if( pieceOnSquare == NULL )
					{
						moves.AddMove( startSquareNumber, nSquare );
					}
					else
					{
						if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
							//	square has enemy; push capture
							moves.AddCapture( startSquareNumber, nSquare );

						//	hit an obsticle; we're done moving in this direction
						nSquare = -1;
					}
				}
			}
		}
	}
}

void PieceType::GenerateCaptures
	( MovementList &moves,
	  Board &board,
	  Piece &piece,
	  int squareNumber )
{
	if( optimization == NoOptimization )
	{
		//	iterate through each move capability (or move direction)
		for( int i = 0; i < nMoveCapabilities; i++ )
		{
			//	initialize move vector for this movement direction
			MovementCapability &move = moveCapabilities[i];

			if( move.CanCapture() || move.CanIguiCapture() )
			{
				if( move.IsInZone( board.flipSquare[piece.GetPlayerNumber()][squareNumber] ) )
				{
					int nStartSquare = squareNumber;
					int nSquare = squareNumber;

					//	initialize flag to stop our movement when we hit the edge of the board,
					//	or encounter an obstacle (friendly or enemy piece)
					bool hitObstacle = false;

					int directionNumber;
					int *movementMatrix;
					directionNumber = move.GetDirectionNumber();
					movementMatrix = piece.GetPlayerNumber() == 0 ? pBoard->GetMovementMatrix( directionNumber ) :
						pBoard->GetOppositeMovementMatrix( directionNumber );

					//	iterate through the maximum number of steps we may move in this
					//	direction, or until we leave the edge of the board

					//	find new square
					nSquare = movementMatrix[nSquare];

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

						if( pieceOnSquare != NULL )
						{
							//	hit an obsticle; we're done moving in this direction
							hitObstacle = true;

							if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() && 
								move.GetMinSteps() <= 1 )
							{
								//	obsticle is an enemy; add this capture
								if( move.CanCapture() )
									moves.AddCapture( nStartSquare, nSquare );
								if( move.CanIguiCapture() )
									moves.AddIguiCapture( nStartSquare, nSquare );
							}
						}
					}
					else
						//	edge of board; we're done
						hitObstacle = true;

					//	now keep "stepping" in this direction as needed
					for( int j = 2; !hitObstacle && j <= move.GetMaxSteps(); j++ )
					{
						//	find new square
						nSquare = movementMatrix[nSquare];

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

							if( pieceOnSquare != NULL )
							{
								//	hit an obsticle; we're done moving in this direction
								hitObstacle = true;

								if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() && 
									move.GetMinSteps() <= j )
								{
									//	obsticle is an enemy; add this capture
									if( move.CanCapture() )
										moves.AddCapture( nStartSquare, nSquare );
									if( move.CanIguiCapture() )
										moves.AddIguiCapture( nStartSquare, nSquare );
								}
							}
						}
						else
							//	edge of board; we're done
							hitObstacle = true;
					}
				}
			}
			else if( move.CapturesByWithdrawing() )
			{
				if( move.IsInZone( board.flipSquare[piece.GetPlayerNumber()][squareNumber] ) )
				{
					int nStartSquare = squareNumber;
					int nSquare = squareNumber;

					//	initialize flag to stop our movement when we hit the edge of the board,
					//	or encounter an obstacle (friendly or enemy piece)
					bool hitObstacle = false;

					// *** CAPTURE by WITHDRAWL *** //
					int withdrawCaptureSquare = -1;
					int oppositeDirectionNumber = pBoard->GetDirection( move.GetDirectionNumber() ).GetOppositeDirectionNumber();
					int *oppositeMatrix = piece.GetPlayerNumber() == 0 ? pBoard->GetMovementMatrix( oppositeDirectionNumber ) :
						pBoard->GetOppositeMovementMatrix( oppositeDirectionNumber );
					withdrawCaptureSquare = oppositeMatrix[squareNumber];
					if( withdrawCaptureSquare >= 0 )
						if( pBoard->GetSquareContents( withdrawCaptureSquare ) == NULL ||
							pBoard->GetSquareContents( withdrawCaptureSquare )->GetPlayerNumber() == piece.GetPlayerNumber() )
							//	nothing to capture by withdraw
							withdrawCaptureSquare = -1;

					if( withdrawCaptureSquare >= 0 )
					{
						int directionNumber;
						int *movementMatrix;
						directionNumber = move.GetDirectionNumber();
						movementMatrix = piece.GetPlayerNumber() == 0 ? pBoard->GetMovementMatrix( directionNumber ) :
							pBoard->GetOppositeMovementMatrix( directionNumber );

						//	iterate through the maximum number of steps we may move in this
						//	direction, or until we leave the edge of the board

						//	find new square
						nSquare = movementMatrix[nSquare];

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

							if( pieceOnSquare != NULL )
							{
								//	hit an obsticle; we're done moving in this direction
								hitObstacle = true;
							}
							else if( move.GetMinSteps() <= 1 )
							{
								//	we have a capture by withdrawl
								moves.BeginMoveAdd( CaptureByWithdrawl, nStartSquare, nSquare );
								moves.AddPickUp( nStartSquare );
								moves.AddPickUp( withdrawCaptureSquare );
								moves.AddDrop( &piece, nSquare );
								moves.EndMoveAdd( piece.GetBaseValue() + 500 );
							}
						}
						else
							//	edge of board; we're done
							hitObstacle = true;

						//	now keep "stepping" in this direction as needed
						for( int j = 2; !hitObstacle && j <= move.GetMaxSteps(); j++ )
						{
							//	find new square
							nSquare = movementMatrix[nSquare];

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

								if( pieceOnSquare != NULL )
								{
									//	hit an obsticle; we're done moving in this direction
									hitObstacle = true;
								}
								else if( move.GetMinSteps() <= j )
								{
									//	we have a capture by withdrawl
									moves.BeginMoveAdd( CaptureByWithdrawl, nStartSquare, nSquare );
									moves.AddPickUp( nStartSquare );
									moves.AddPickUp( withdrawCaptureSquare );
									moves.AddDrop( &piece, nSquare );
									moves.EndMoveAdd( piece.GetBaseValue() + 500 );
								}
							}
							else
								//	edge of board; we're done
								hitObstacle = true;
						}
					}
				}
			}
			else if( move.CapturesByAdvancing() )
			{
				if( move.IsInZone( board.flipSquare[piece.GetPlayerNumber()][squareNumber] ) )
				{
					int nStartSquare = squareNumber;
					int nSquare = squareNumber;
					bool hitObstacle = false;
					int directionNumber;
					int *movementMatrix;
					directionNumber = move.GetDirectionNumber();
					movementMatrix = piece.GetPlayerNumber() == 0 ? pBoard->GetMovementMatrix( directionNumber ) :
						pBoard->GetOppositeMovementMatrix( directionNumber );
					nSquare = movementMatrix[nSquare];
					if( nSquare >= 0 )
					{
						Piece *pieceOnSquare = pBoard->GetSquareContents( nSquare );

						if( pieceOnSquare != NULL )
						{
							//	hit an obsticle; we're done moving in this direction
							hitObstacle = true;
						}
						else
						{
							if( movementMatrix[nSquare] != -1 && 
								move.GetMinSteps() <= 1 && 
								pBoard->GetSquareContents( movementMatrix[nSquare] ) != NULL && 
								pBoard->GetSquareContents( movementMatrix[nSquare] )->GetPlayerNumber() != piece.GetPlayerNumber() )
							{
								// *** CAPTURE by ADVANCE *** //
								moves.BeginMoveAdd( CaptureByAdvance, nStartSquare, nSquare );
								moves.AddPickUp( nStartSquare );
								moves.AddPickUp( movementMatrix[nSquare] );
								moves.AddDrop( &piece, nSquare );
								moves.EndMoveAdd( pBoard->GetSquareContents( movementMatrix[nSquare] )->GetBaseValue() + 750 );
							}
						}
					}
					else
						hitObstacle = true;

					for( int j = 2; !hitObstacle && j <= move.GetMaxSteps(); j++ )
					{
						nSquare = movementMatrix[nSquare];
						if( nSquare >= 0 )
						{
							Piece *pieceOnSquare = pBoard->GetSquareContents( nSquare );

							if( pieceOnSquare != NULL )
							{
								hitObstacle = true;
							}
							else
							{
								if( movementMatrix[nSquare] != -1 && 
									move.GetMinSteps() <= j && 
									pBoard->GetSquareContents( movementMatrix[nSquare] ) != NULL && 
									pBoard->GetSquareContents( movementMatrix[nSquare] )->GetPlayerNumber() != piece.GetPlayerNumber() )
								{
									// *** CAPTURE by ADVANCE *** //
									moves.BeginMoveAdd( CaptureByAdvance, nStartSquare, nSquare );
									moves.AddPickUp( nStartSquare );
									moves.AddPickUp( movementMatrix[nSquare] );
									moves.AddDrop( &piece, nSquare );
									moves.EndMoveAdd( pBoard->GetSquareContents( movementMatrix[nSquare] )->GetBaseValue() + 750 );
								}
							}
						}
						else
							hitObstacle = true;
					}
				}
			}
		}
	}
	else if( optimization == SimpleSingleStep )
	{
		//	iterate through each move capability (or move direction)
		for( int i = 0; i < nMoveCapabilities; i++ )
		{
			//	initialize move vector for this movement direction
			MovementCapability &move = moveCapabilities[i];

			int directionNumber = move.GetDirectionNumber();
			int *movementMatrix = piece.GetPlayerNumber() == 0 ? pBoard->GetMovementMatrix( directionNumber ) :
				pBoard->GetOppositeMovementMatrix( directionNumber );

			//	find new square
			int nSquare = movementMatrix[squareNumber];

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

				if( pieceOnSquare != NULL &&
					pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
					//	obsticle is an enemy; add this capture
					moves.AddCapture( squareNumber, nSquare );
			}
		}
	}
	else if( optimization == SimpleSlider )
	{
		//	iterate through each move capability (or move direction)
		for( int i = 0; i < nMoveCapabilities; i++ )
		{
			//	initialize move vector for this movement direction
			MovementCapability &move = moveCapabilities[i];

			int nSquare = squareNumber;

			int directionNumber = move.GetDirectionNumber();
			int *movementMatrix = piece.GetPlayerNumber() == 0 ? pBoard->GetMovementMatrix( directionNumber ) :
				pBoard->GetOppositeMovementMatrix( directionNumber );

			//	iterate through the maximum number of steps we may move in this
			//	direction, or until we leave the edge of the board
			nSquare = movementMatrix[nSquare];

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

				if( pieceOnSquare != NULL )
				{
					if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
						//	square has enemy; push capture
						moves.AddCapture( squareNumber, nSquare );

					//	hit an obsticle; we're done moving in this direction
					nSquare = -1;
				}
			}

			//	keep "stepping" in this direction as long as we can
			while( nSquare != -1 )
			{
				//	find new rank and file
				nSquare = movementMatrix[nSquare];

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

					if( pieceOnSquare != NULL )
					{
						if( pieceOnSquare->GetPlayerNumber() != piece.GetPlayerNumber() )
							//	square has enemy; push capture
							moves.AddCapture( squareNumber, nSquare );

						//	hit an obsticle; we're done moving in this direction
						nSquare = -1;
					}
				}
			}
		}
	}
}

bool PieceType::DoesAttackSquare
	( Player &player,
	  int myRank,
	  int myFile,
	  int targetRank,
	  int targetFile )
{
	//	find starting square number
	int nStartSquare = myRank * pBoard->GetNumberOfFiles() + myFile;
	int nRank = myRank;
	int nFile = myFile;

	//	iterate through each move capability (or move direction)
	for( int i = 0; i < nMoveCapabilities; i++ )
	{
		//	initialize move vector for this movement direction
		MovementCapability &move = moveCapabilities[i];

		if( move.CanCapture() || move.CanIguiCapture() )
		{
			//	check to make sure we satisify the requirements for this move
			if( move.IsInZone( pBoard->flipSquare[player.GetPlayerNumber()][myRank * pBoard->GetNumberOfFiles() + myFile] ) )
			{
				//	initialize flag to stop our movement when we hit the edge of the board,
				//	or encounter an obstacle (friendly or enemy piece)
				bool hitObstacle = false;

				//	iterate through the maximum number of steps we may move in this
				//	direction, or until we leave the edge of the board
				for( int j = 1; j <= move.GetMaxSteps() && !hitObstacle; j++ )
				{
					//	find new rank and file
					nRank += move.GetRankDifference( player );
					nFile += move.GetFileDifference( player );

					//	are we still on the board?
					if( nFile >= 0 && nFile < pBoard->GetNumberOfFiles() &&
						nRank >= 0 && nRank < pBoard->GetNumberOfRanks() )
					{
						int squareNum = nRank * pBoard->GetNumberOfFiles() + nFile;

						Piece *pieceOnSquare = pBoard->GetSquareContents( squareNum );

						if( nRank == targetRank && nFile == targetFile && j >= move.GetMinSteps() )
						{
							return true;
						}
						else if( pieceOnSquare != NULL )
						{
							//	square is occupied; we cannot move any further in this direciton
							hitObstacle = true;
						}
					}
					else
						hitObstacle = true;
				}
			}
			//	reset position before going on to next move capability
			nRank = myRank;
			nFile = myFile;
		}
	}
	return false;
}

bool PieceType::DoesAttackSquare
	( Player &player,
	  int mySquare,
	  int targetSquare )
{
	//	iterate through each move capability (or move direction)
	for( int i = 0; i < nMoveCapabilities; i++ )
	{
		//	initialize move vector for this movement direction
		MovementCapability &move = moveCapabilities[i];

		if( move.CanCapture() || move.CanIguiCapture() )
		{
			//	check to make sure we satisify the requirements for this move
			if( move.IsInZone( pBoard->flipSquare[player.GetPlayerNumber()][mySquare] ) )
			{
				int nSquare = mySquare;

				//	initialize flag to stop our movement when we hit the edge of the board,
				//	or encounter an obstacle (friendly or enemy piece)
				bool hitObstacle = false;

				int *movementMatrix = player.GetPlayerNumber() == 0 ? pBoard->GetMovementMatrix( move.GetDirectionNumber() ) :
					pBoard->GetOppositeMovementMatrix( move.GetDirectionNumber() );

				//	iterate through the maximum number of steps we may move in this
				//	direction, or until we leave the edge of the board
				for( int j = 1; j <= move.GetMaxSteps() && !hitObstacle; j++ )
				{
					//	find new rank and file
					nSquare = movementMatrix[nSquare];

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

						if( nSquare == targetSquare && j >= move.GetMinSteps() )
						{
							return true;
						}
						else if( pieceOnSquare != NULL )
						{
							//	square is occupied; we cannot move any further in this direciton
							hitObstacle = true;
						}
					}
					else
						hitObstacle = true;
				}
			}
		}
	}
	return false;
}

int PieceType::CountMoves
	( const Player &player,
	  int myRank,
	  int myFile,
	  int &pseudoLegal )
{
	int count = 0;
	pseudoLegal = 0;

	//	find starting square number
	int nStartSquare = myRank * pBoard->GetNumberOfFiles() + myFile;
	int nRank = myRank;
	int nFile = myFile;

	//	iterate through each move capability (or move direction)
	for( int i = 0; i < nMoveCapabilities; i++ )
	{
		//	initialize move vector for this movement direction
		MovementCapability &move = moveCapabilities[i];

		//	check to make sure we satisify the requirements for this move
		if( move.IsInZone( pBoard->flipSquare[player.GetPlayerNumber()][myRank * pBoard->GetNumberOfFiles() + myFile] ) )
		{
			//	initialize flag to stop our movement when we hit the edge of the board,
			//	or encounter an obstacle (friendly or enemy piece)
			bool hitObstacle = false;

			//	iterate through the maximum number of steps we may move in this
			//	direction, or until we leave the edge of the board
			for( int j = 1; j <= move.GetMaxSteps() && !hitObstacle; j++ )
			{
				//	find new rank and file
				nRank += move.GetRankDifference( player );
				nFile += move.GetFileDifference( player );

				//	are we still on the board?
				if( nFile >= 0 && nFile < pBoard->GetNumberOfFiles() &&
					nRank >= 0 && nRank < pBoard->GetNumberOfRanks() )
				{
					int squareNum = nRank * pBoard->GetNumberOfFiles() + nFile;
					Piece *pieceOnSquare = pBoard->GetSquareContents( squareNum );

					if( (pieceOnSquare == NULL && move.CanMove() && j >= move.GetMinSteps()) || 
						(pieceOnSquare != NULL && pieceOnSquare->GetPlayerNumber() != player.GetPlayerNumber() && 
						(move.CanCapture() || move.CanIguiCapture())) )
					{
						pseudoLegal++;
						if( !theGame->IsGoalToCheckmate() || theBoard->IsMoveLegal( nStartSquare, squareNum ) )
							count++;
					}
					if( pieceOnSquare != NULL )
					{
						//	square is occupied; we cannot move any further in this direciton
						hitObstacle = true;
					}
				}
				else
					hitObstacle = true;
			}
			//	reset position before going on to next move capability
			nRank = myRank;
			nFile = myFile;
		}
	}
	return count;
}

int PieceType::CalculateMobility
	( int playerNumber, 
	  int squareNumber )
{
	int totalMoves = mobilityOffset;
	int lineupBonus = 0;

	if( mobilityType == StandardMobility )
	{
		if( optimization == NoOptimization )
		{
			//	iterate through each move capability (or move direction)
			for( int i = 0; i < GetMoveCapabilityCount(); i++ )
			{
				//	initialize move vector for this movement direction
				MovementCapability &move = GetMoveCapability( i );

				//	check to make sure we satisify the requirements for this move
				if( move.IsInZone( pBoard->flipSquare[playerNumber][squareNumber] ) )
				{
					int *moveMatrix = pBoard->GetMovementMatrix( move.GetDirectionNumber() );

					//	initialize flag to stop our movement when we hit the edge of the board,
					//	or encounter an obstacle (friendly or enemy piece)
					bool hitObstacle = false;

					//	iterate through the maximum number of steps we may move in this
					//	direction, or until we leave the edge of the board
					int currentSquare = squareNumber;

					for( int j = 1; j <= move.GetMaxSteps() && !hitObstacle; j++ )
					{
						//	find new square number
						currentSquare = moveMatrix[currentSquare];

						//	are we still on the board?
						hitObstacle = true;
						if( currentSquare >= 0 && j <= move.GetMaxSteps() )
						{
							Piece *pieceOnSquare = pBoard->GetSquareContents( currentSquare );
							if( pieceOnSquare == NULL )
							{
								hitObstacle = false;
								if( move.CanMove() )
								{
									totalMoves++;
									#ifdef SKEPTICAL_MOBILITY
									if( move.CanCapture() || move.CanIguiCapture() )
										pBoard->squaresAttacked[pPlayer->GetPlayerNumber()][currentSquare] = 1;
									#endif
								}
							}
							else if( pieceOnSquare != NULL && pieceOnSquare->GetPlayerNumber() != playerNumber )
							{
								//	enemy piece
								if( move.CanCapture() || move.CanIguiCapture() )
								{
									totalMoves++;
									#ifdef SKEPTICAL_MOBILITY
									pBoard->squaresAttacked[pPlayer->GetPlayerNumber()][currentSquare] = 1;
									#endif
								}
							}
							else
							{
								//	square is occupied by a friend; check to see
								//	if it also can attack in this direction
								if( pieceOnSquare->GetType().GetAttackRange( playerNumber, move.GetDirectionNumber() ) > j )
									lineupBonus += MIN(MIN(pieceOnSquare->GetType().GetAttackRange( playerNumber, move.GetDirectionNumber() ) - j,
										move.GetMaxSteps() - j), 4) * 10;
								//	count defending this piece toward mobility,
								//	as long as it isn't a pawn
								if( !pieceOnSquare->IsPawn() )
									totalMoves++;
							}
						}
					}
				}
			}
		}
		else if( optimization == SimpleSingleStep )
		{
			//	iterate through each move capability (or move direction)
			for( int i = 0; i < GetMoveCapabilityCount(); i++ )
			{
				//	initialize move vector for this movement direction
				MovementCapability &move = GetMoveCapability( i );

				//	check to make sure we satisify the requirements for this move
				int *moveMatrix = pBoard->GetMovementMatrix( move.GetDirectionNumber() );

				int currentSquare = moveMatrix[squareNumber];

				//	are we still on the board?
				if( currentSquare >= 0 )
				{
					Piece *pieceOnSquare = pBoard->GetSquareContents( currentSquare );
					if( pieceOnSquare == NULL )
					{
						totalMoves++;
						#ifdef SKEPTICAL_MOBILITY
						pBoard->squaresAttacked[pPlayer->GetPlayerNumber()][currentSquare] = 1;
						#endif
					}
					else if( pieceOnSquare != NULL && pieceOnSquare->GetPlayerNumber() != playerNumber )
					{
						totalMoves++;
						#ifdef SKEPTICAL_MOBILITY
						pBoard->squaresAttacked[pPlayer->GetPlayerNumber()][currentSquare] = 1;
						#endif
					}
					else
					{
						//	count defending this piece toward mobility,
						//	as long as it isn't a pawn
						if( !pieceOnSquare->IsPawn() )
							totalMoves++;
					}
				}
			}
		}
	}
	#ifdef SKEPTICAL_MOBILITY
	else if( mobilityType == SkepticalMobility )
	{
		//	iterate through each move capability (or move direction)
		for( int i = 0; i < GetMoveCapabilityCount(); i++ )
		{
			//	initialize move vector for this movement direction
			MovementCapability &move = GetMoveCapability( i );;

			//	check to make sure we satisify the requirements for this move
			bool canMakeMove = true;
			if( move.HasRankRestriction() )
			{
				int myRank = squareNumber / pBoard->GetNumberOfFiles();
				int effectiveRank = pPlayer->GetPlayerNumber() == 0 ? myRank : pBoard->GetNumberOfRanks() - myRank - 1;
				if( effectiveRank < move.GetMinRank() || effectiveRank > move.GetMaxRank() )
					canMakeMove = false;
			}
			if( canMakeMove )
			{
				int *moveMatrix = pBoard->GetMovementMatrix( move.GetDirectionNumber() );

				//	initialize flag to stop our movement when we hit the edge of the board,
				//	or encounter an obstacle (friendly or enemy piece)
				bool hitObstacle = false;

				//	iterate through the maximum number of steps we may move in this
				//	direction, or until we leave the edge of the board
				int currentSquare = squareNumber;

				for( int j = 1; j <= move.GetMaxSteps() && !hitObstacle; j++ )
				{
					//	find new square number
					currentSquare = moveMatrix[currentSquare];

					//	are we still on the board?
					hitObstacle = true;
					if( currentSquare >= 0 && j <= move.GetMaxSteps() )
					{
						Piece *pieceOnSquare = pBoard->GetSquareContents( currentSquare );
						if( pieceOnSquare == NULL )
						{
							hitObstacle = false;
							if( move.CanMove() )
							{
								if( pBoard->squaresAttacked[FLIP(pPlayer->GetPlayerNumber())][currentSquare] == 0 )
									totalMoves++;
									
							}
						}
						else if( pieceOnSquare != NULL && pieceOnSquare->GetPlayerNumber() != pPlayer->GetPlayerNumber() )
						{
							//	enemy piece
							if( move.CanCapture() || move.CanIguiCapture() )
							{
								if( pBoard->squaresAttacked[FLIP(pPlayer->GetPlayerNumber())][currentSquare] == 0 )
									totalMoves++;
							}
						}
					}
				}
			}
		}
	}
	#endif
	return totalMoves * mobilityFactor + lineupBonus;
}

void PieceType::SetSquareBonuses
	( int phaseNumber, 
	  int *bonuses )
{
	useSquareBonuses = true;
	squareBonuses[phaseNumber] = bonuses;
}

void PieceType::Output( FILE *f )
{
	fprintf( f, "%s, %f, %f, %f, %f\n", fullName, fTotalSquaresAttacked / nSquaresSeen, fTotalCenterSquaresAttacked / nSquaresSeen, (float) nTotalDirectionsAttacked / nSquaresSeen, (float) nTotalSafeChecks / nSquaresSeen );
}

void PieceType::PostPaintMoveDiagram
	( LPPAINTSTRUCT ps, 
	  HDC hdc )
{
}

void PieceType64::BB64_Initialize()
{
	int nSquares = nRanks * nFiles;
	bb64_attack[0].Free();
	bb64_attack[1].Free();
	bb64_direct_move[0].Free();
	bb64_direct_move[1].Free();
	bb64_direct_move_no_capture[0].Free();
	bb64_direct_move_no_capture[1].Free();
	bb64_direct_move_capture_only[0].Free();
	bb64_direct_move_capture_only[1].Free();
	bb64_attack[0].SetSize( nSquares );
	bb64_attack[1].SetSize( nSquares );
	bb64_direct_move[0].SetSize( nSquares );
	bb64_direct_move[1].SetSize( nSquares );
	bb64_direct_move_no_capture[0].SetSize( nSquares );
	bb64_direct_move_no_capture[1].SetSize( nSquares );
	bb64_direct_move_capture_only[0].SetSize( nSquares );
	bb64_direct_move_capture_only[1].SetSize( nSquares );

	for( int player = 0; player < 2; player++ )
	{
		for( int sq = 0; sq < nSquares; sq++ )
		{
			bb64_attack[player][sq].Clear();
			bb64_direct_move[player][sq].Clear();
			bb64_direct_move_no_capture[player][sq].Clear();
			bb64_direct_move_capture_only[player][sq].Clear();

			//	iterate through each move capability (or move direction)
			for( int i = 0; i < nMoveCapabilities; i++ )
			{
				//	initialize move vector for this movement direction
				MovementCapability &move = moveCapabilities[i];

				if( (move.CanCapture() || move.CanIguiCapture()) && move.GetMinSteps() == 1 )
				{
					if( move.IsInZone( pBoard->flipSquare[player][sq] ) )
					{
						int nSquare = sq;
						int directionNumber = move.GetDirectionNumber();
						int *movementMatrix = player == 0 ? pBoard->GetMovementMatrix( directionNumber ) :
							pBoard->GetOppositeMovementMatrix( directionNumber );

						//	iterate through the maximum number of steps we may move in this
						//	direction, or until we leave the edge of the board

						//	find new square
						nSquare = movementMatrix[nSquare];
						int nSteps = 1;

						//	are we still on the board?
						while( nSquare >= 0 && nSteps <= move.GetMaxSteps() )
						{
							bb64_attack[player][sq].SetBit( nSquare );
							if( move.GetMaxSteps() == 1 && move.CanCapture() )
							{
								if( move.CanMove() )
									bb64_direct_move[player][sq].SetBit( nSquare );
								else
									bb64_direct_move_capture_only[player][sq].SetBit( nSquare );
							}
							nSquare = movementMatrix[nSquare];
							nSteps++;
						}
					}
				}
				else if( move.CanMove() && move.GetMaxSteps() == 1 )
				{
					if( move.IsInZone( pBoard->flipSquare[player][sq] ) )
					{
						int nSquare = sq;
						int directionNumber = move.GetDirectionNumber();
						int *movementMatrix = player == 0 ? pBoard->GetMovementMatrix( directionNumber ) :
							pBoard->GetOppositeMovementMatrix( directionNumber );
						//	find new square
						nSquare = movementMatrix[nSquare];
						//	are we still on the board?
						if( nSquare >= 0 )
						{
							bb64_direct_move_no_capture[player][sq].SetBit( nSquare );
						}
					}
				}
			}
		}
	}
}

void PieceType64::BB64_GenerateDirectMoves
	( MovementList &stack, 
	  int nPlayer, 
	  int nSquare )
{
	BitBoard64 targetSquares = bb64_direct_move[nPlayer][nSquare];

	while( targetSquares )
	{
		int target = targetSquares.ExtractLSB();
		Piece *pieceToCapture = pBoard->GetSquareContents( target );
		if( pieceToCapture == NULL )
			stack.AddMove( nSquare, target );
		else
			if( pieceToCapture->GetPlayerNumber() != nPlayer )
				stack.AddCapture( nSquare, target );
	}
}

void PieceType64::BB64_GenerateDirectCaptures
	( MovementList &stack, 
	  int nPlayer, 
	  int nSquare )
{
	BitBoard64 targetSquares = 
		(bb64_direct_move[nPlayer][nSquare] | 
		 bb64_direct_move_capture_only[nPlayer][nSquare]) & 
		pBoard->BB64_GetFriends( FLIP(nPlayer) );

	while( targetSquares )
	{
		int target = targetSquares.ExtractLSB();
		stack.AddCapture( nSquare, target );
	}
}

void PieceType64::BB64_GenerateDirectMovesNoCapture
	( MovementList &stack, 
	  int nPlayer, 
	  int nSquare )
{
	BitBoard64 targetSquares = bb64_direct_move_no_capture[nPlayer][nSquare] &
		~pBoard->BB64_GetBlockers();

	while( targetSquares )
	{
		int target = targetSquares.ExtractLSB();
		stack.AddMove( nSquare, target );
	}
}

void PieceType64::BB64_GenerateDirectMovesCaptureOnly
	( MovementList &stack, 
	  int nPlayer, 
	  int nSquare )
{
	BitBoard64 targetSquares = bb64_direct_move_capture_only[nPlayer][nSquare] & 
		pBoard->BB64_GetFriends( FLIP(nPlayer) );

	while( targetSquares )
	{
		int target = targetSquares.ExtractLSB();
		stack.AddCapture( nSquare, target );
	}
}

void PieceType96::BB96_Initialize()
{
	int nSquares = nRanks * nFiles;
	bb96_attack[0].Free();
	bb96_attack[1].Free();
	bb96_direct_move[0].Free();
	bb96_direct_move[1].Free();
	bb96_direct_move_no_capture[0].Free();
	bb96_direct_move_no_capture[1].Free();
	bb96_direct_move_capture_only[0].Free();
	bb96_direct_move_capture_only[1].Free();
	bb96_attack[0].SetSize( nSquares );
	bb96_attack[1].SetSize( nSquares );
	bb96_direct_move[0].SetSize( nSquares );
	bb96_direct_move[1].SetSize( nSquares );
	bb96_direct_move_no_capture[0].SetSize( nSquares );
	bb96_direct_move_no_capture[1].SetSize( nSquares );
	bb96_direct_move_capture_only[0].SetSize( nSquares );
	bb96_direct_move_capture_only[1].SetSize( nSquares );

	for( int player = 0; player < 2; player++ )
	{
		for( int sq = 0; sq < nSquares; sq++ )
		{
			bb96_attack[player][sq].Clear();
			bb96_direct_move[player][sq].Clear();
			bb96_direct_move_no_capture[player][sq].Clear();
			bb96_direct_move_capture_only[player][sq].Clear();

			//	iterate through each move capability (or move direction)
			for( int i = 0; i < nMoveCapabilities; i++ )
			{
				//	initialize move vector for this movement direction
				MovementCapability &move = moveCapabilities[i];

				if( (move.CanCapture() || move.CanIguiCapture()) && move.GetMinSteps() == 1 )
				{
					if( move.IsInZone( pBoard->flipSquare[player][sq] ) )
					{
						int nSquare = sq;
						int directionNumber = move.GetDirectionNumber();
						int *movementMatrix = player == 0 ? pBoard->GetMovementMatrix( directionNumber ) :
							pBoard->GetOppositeMovementMatrix( directionNumber );

						//	iterate through the maximum number of steps we may move in this
						//	direction, or until we leave the edge of the board

						//	find new square
						nSquare = movementMatrix[nSquare];
						int nSteps = 1;

						//	are we still on the board?
						while( nSquare >= 0 && nSteps <= move.GetMaxSteps() )
						{
							bb96_attack[player][sq].SetBit( nSquare );
							if( move.GetMaxSteps() == 1 && move.CanCapture() )
							{
								if( move.CanMove() )
									bb96_direct_move[player][sq].SetBit( nSquare );
								else
									bb96_direct_move_capture_only[player][sq].SetBit( nSquare );
							}
							nSquare = movementMatrix[nSquare];
							nSteps++;
						}
					}
				}
				else if( move.CanMove() && move.GetMaxSteps() == 1 )
				{
					if( move.IsInZone( pBoard->flipSquare[player][sq] ) )
					{
						int nSquare = sq;
						int directionNumber = move.GetDirectionNumber();
						int *movementMatrix = player == 0 ? pBoard->GetMovementMatrix( directionNumber ) :
							pBoard->GetOppositeMovementMatrix( directionNumber );
						//	find new square
						nSquare = movementMatrix[nSquare];
						//	are we still on the board?
						if( nSquare >= 0 )
						{
							bb96_direct_move_no_capture[player][sq].SetBit( nSquare );
						}
					}
				}
			}
		}
	}
}

void PieceType96::BB96_GenerateDirectMoves
	( MovementList &stack, 
	  int nPlayer, 
	  int nSquare )
{
	BitBoard96 targetSquares = bb96_direct_move[nPlayer][nSquare];

	while( targetSquares )
	{
		int target = targetSquares.GetFirstBit();
		targetSquares.ClearBit( target );
		Piece *pieceToCapture = pBoard->GetSquareContents( target );
		if( pieceToCapture == NULL )
			stack.AddMove( nSquare, target );
		else
			if( pieceToCapture->GetPlayerNumber() != nPlayer )
				stack.AddCapture( nSquare, target );
	}
}

void PieceType96::BB96_GenerateDirectCaptures
	( MovementList &stack, 
	  int nPlayer, 
	  int nSquare )
{
	BitBoard96 targetSquares = 
		(bb96_direct_move[nPlayer][nSquare] | 
		 bb96_direct_move_capture_only[nPlayer][nSquare]) & 
		pBoard->BB96_GetFriends( FLIP(nPlayer) );

	while( targetSquares )
	{
		int target = targetSquares.GetFirstBit();
		targetSquares.ClearBit( target );
		stack.AddCapture( nSquare, target );
	}
}

void PieceType96::BB96_GenerateDirectMovesNoCapture
	( MovementList &stack, 
	  int nPlayer, 
	  int nSquare )
{
	BitBoard96 targetSquares = bb96_direct_move_no_capture[nPlayer][nSquare];

	while( targetSquares )
	{
		int target = targetSquares.GetFirstBit();
		targetSquares.ClearBit( target );
		Piece *pieceToCapture = pBoard->GetSquareContents( target );
		if( pieceToCapture == NULL )
			stack.AddMove( nSquare, target );
	}
}

void PieceType96::BB96_GenerateDirectMovesCaptureOnly
	( MovementList &stack, 
	  int nPlayer, 
	  int nSquare )
{
	BitBoard96 targetSquares = bb96_direct_move_capture_only[nPlayer][nSquare];

	while( targetSquares )
	{
		int target = targetSquares.GetFirstBit();
		targetSquares.ClearBit( target );
		Piece *pieceToCapture = pBoard->GetSquareContents( target );
		if( pieceToCapture != NULL && 
			pieceToCapture->GetPlayerNumber() != nPlayer )
			stack.AddCapture( nSquare, target );
	}
}



void PieceType128::BB128_Initialize()
{
/*	int nSquares = nRanks * nFiles;
	bb128_attack[0].Free();
	bb128_attack[1].Free();
	bb128_direct_move[0].Free();
	bb128_direct_move[1].Free();
	bb128_direct_move_no_capture[0].Free();
	bb128_direct_move_no_capture[1].Free();
	bb128_direct_move_capture_only[0].Free();
	bb128_direct_move_capture_only[1].Free();
	bb128_attack[0].SetSize( nSquares );
	bb128_attack[1].SetSize( nSquares );
	bb128_direct_move[0].SetSize( nSquares );
	bb128_direct_move[1].SetSize( nSquares );
	bb128_direct_move_no_capture[0].SetSize( nSquares );
	bb128_direct_move_no_capture[1].SetSize( nSquares );
	bb128_direct_move_capture_only[0].SetSize( nSquares );
	bb128_direct_move_capture_only[1].SetSize( nSquares );

	for( int player = 0; player < 2; player++ )
	{
		for( int sq = 0; sq < nSquares; sq++ )
		{
			bb128_attack[player][sq].Clear();
			bb128_direct_move[player][sq].Clear();
			bb128_direct_move_no_capture[player][sq].Clear();
			bb128_direct_move_capture_only[player][sq].Clear();

			//	iterate through each move capability (or move direction)
			for( int i = 0; i < nMoveCapabilities; i++ )
			{
				//	initialize move vector for this movement direction
				MovementCapability &move = moveCapabilities[i];

				if( (move.CanCapture() || move.CanIguiCapture()) && move.GetMinSteps() == 1 )
				{
					if( move.IsInZone( pBoard->flipSquare[player][sq] ) )
					{
						int nSquare = sq;
						int directionNumber = move.GetDirectionNumber();
						int *movementMatrix = player == 0 ? pBoard->GetMovementMatrix( directionNumber ) :
							pBoard->GetOppositeMovementMatrix( directionNumber );

						//	iterate through the maximum number of steps we may move in this
						//	direction, or until we leave the edge of the board

						//	find new square
						nSquare = movementMatrix[nSquare];
						int nSteps = 1;

						//	are we still on the board?
						while( nSquare >= 0 && nSteps <= move.GetMaxSteps() )
						{
							bb128_attack[player][sq].SetBit( nSquare );
							if( move.GetMaxSteps() == 1 && move.CanCapture() )
							{
								if( move.CanMove() )
									bb128_direct_move[player][sq].SetBit( nSquare );
								else
									bb128_direct_move_capture_only[player][sq].SetBit( nSquare );
							}
							nSquare = movementMatrix[nSquare];
							nSteps++;
						}
					}
				}
				else if( move.CanMove() && move.GetMaxSteps() == 1 )
				{
					if( move.IsInZone( pBoard->flipSquare[player][sq] ) )
					{
						int nSquare = sq;
						int directionNumber = move.GetDirectionNumber();
						int *movementMatrix = player == 0 ? pBoard->GetMovementMatrix( directionNumber ) :
							pBoard->GetOppositeMovementMatrix( directionNumber );
						//	find new square
						nSquare = movementMatrix[nSquare];
						//	are we still on the board?
						if( nSquare >= 0 )
						{
							bb128_direct_move_no_capture[player][sq].SetBit( nSquare );
						}
					}
				}
			}
		}
	}*/
}

