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

                                 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

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


#ifndef FILE__PIECE_H
#define FILE__PIECE_H


#include "PieceType.h"
#include "Player.h"
#include "Zone.h"


#define FLAGS_HAS_MOVED					 1UL
#define FLAGS_HAS_MOVED_TWICE			 2UL
#define FLAGS_HAS_MOVED_THREE_TIMES		 4UL
#define FLAGS_HAS_MOVED_MASK			 7UL
#define FLAGS_HAS_CASTLED				 8UL
#define FLAGS_IS_PROMOTED				16UL

;
class Piece
{
  protected:
	//	data members
	PieceType *pPieceType;					//	pointer to current type of this piece
	Player *pPlayer;						//	pointer to player currently owning this piece
	Board *pBoard;							//	pointer to the Board
	bool captured;							//	still on the board, or captured?
	unsigned flags;							//	misc flags, like the has-moved flag
	int playerNumber;						//	number of player owning this piece
	int squareNumber;						//	square number currently occupied
	int realSquareNumber;					//	square number currently occupied, and unchanged 
											//	during move search - used for drawing board
	bool reallyCaptured;					//	captured flag - unchanged during move search 
	PieceType *pRealPieceType;				//	type of piece - unchanged during move search

	int squaresVisible;						//	number of squares of the board that can be reached

	PieceSquareInfo *squareValues;			//	info about this piece's power on each square
	int nTotalSquaresAttacked;				//	statistical info (currently unused)
	int nTotalSafeChecks;
	int nTotalDirectionsAttacked;
	int nSquaresSeen;
	float fTotalMobility;
	float aveDirectionsAttacked;
	float aveSquaresAttacked;
	float aveSafeChecks;
	float aveMobility;

	//	promotion
	Promotion promotion;					//	promotion capabilities (if any)
	Zone promotionZone;
	static Promotion noPromotion;

	IntVector mobilityMatrix;				
	//	this is used for calculating default square values for board squares,
	//	although you should always provide custom piece-square-tables, in which 
	//	case the default table is never used.


	//	helper functions
	virtual void SetBoard( Board &board, int rank, int file );
	void FindSquare( Board &board, int square, int &nSquaresSeen );


  public:

#ifdef _DEBUG
	int dbg_squareNumber[MAX_DEPTH];
#endif

	//	construction
	Piece( PieceType &typeOfPiece, Player &player ):
		pPieceType(&typeOfPiece),
		pRealPieceType(&typeOfPiece),
		pPlayer(&player)
	{
		playerNumber = player.GetPlayerNumber();
		pBoard = NULL;
		captured = false;
		reallyCaptured = false;
		flags = 0U;
		promotion = typeOfPiece.GetPromotion();
	}


	//	attributes
	PieceType &GetType()
	{	return *pPieceType;   }

	Player &GetPlayer()
	{	return *pPlayer;   }

	int GetPlayerNumber()
	{	return playerNumber;   }

	int GetSquareNumber()
	{	return( squareNumber );  }

	int GetRealSquareNumber()
	{	return( realSquareNumber );  }

	int GetRank();

	int GetFile();

	bool IsCaptured()
	{	return captured;   }

	bool IsReallyCaptured()
	{	return reallyCaptured;   }

	PieceType *GetRealPieceType()
	{	return pRealPieceType;   }

	bool HasMoved()
	{	return (flags & FLAGS_HAS_MOVED) != 0;   }

	bool HasMovedTwice()
	{	return (flags & FLAGS_HAS_MOVED_TWICE) != 0;   }

	bool HasCastled()
	{	return (flags & FLAGS_HAS_CASTLED) != 0;   }

	bool IsPromoted()
	{	return (flags & FLAGS_IS_PROMOTED) != 0;   }

	bool IsPawn()
	{	return pPieceType->IsPawn();   }

	unsigned GetFlags()
	{	return flags;   }

	int GetBaseValue()
	{	return pPieceType->GetBaseValue();   }

	Promotion &GetPromotion()
	{	if( flags & FLAGS_IS_PROMOTED ) return noPromotion; else return promotion;   }

	Zone &GetPromotionZone()
	{	return promotionZone;   }

	HBITMAP GetBitmap()
	{	return( pRealPieceType->GetBitmap( GetPlayerNumber() ) );  }

	word32 GetPrimaryHash()
	{	return pPieceType->GetPrimaryHash( pPlayer->GetPlayerNumber(), squareNumber );   }

	word32 GetPrimaryHash( int squareNumber )
	{	return pPieceType->GetPrimaryHash( pPlayer->GetPlayerNumber(), squareNumber );   }

	word32 GetSecondaryHash()
	{	return pPieceType->GetSecondaryHash( pPlayer->GetPlayerNumber(), squareNumber );   }

	word32 GetSecondaryHash( int squareNumber )
	{	return pPieceType->GetSecondaryHash( pPlayer->GetPlayerNumber(), squareNumber );   }

	IntVector &GetMobilityMatrix()
	{	return mobilityMatrix;   }

	int GetSquaresVisible()
	{	return squaresVisible;   }

	float GetAverageSquaresAttacked()
	{	return aveSquaresAttacked;  }

	float GetAverageDirectionsAttacked()
	{	return aveDirectionsAttacked;  }

	float GetAverageSafeChecks()
	{	return aveSafeChecks;  }

	float GetAverageMobility()
	{	return aveMobility;  }

	int GetSignOfPlayer();
	//	returns 1 for white pieces, -1 for black pieces



	//	operations
	void SetSquare( int square_number )
	{	squareNumber = square_number;  }

	void SetRealSquare( int square_number )
	{	realSquareNumber = square_number;  }

	void SetRealPieceType()
	{	pRealPieceType = pPieceType;   }

	void SetSquare( int rank, int file );

	void SetCapturedStatus( bool isCaptured )
	{	captured = isCaptured;  }

	void SetReallyCapturedStatus( bool isReallyCaptured )
	{	reallyCaptured = isReallyCaptured;   }

	void GenerateMoves
		( MovementList &moves,
		  Board &board );

	void GenerateCaptures
		( MovementList &moves,
		  Board &board );

	bool DoesAttackSquare
		( int targetRank,
		  int targetFile );

	int CountMoves
		( int &pseudoLegal );

	void SwitchType
		( PieceType *newType );

	int CompleteSetup();


	//	debug output
	void Output( FILE *f );


	//	friends
	friend class Board;
	friend class ChessGame;
	friend class MovementList;
};


#endif
