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

                                 ChessV

                   COPYRIGHT (C) 2006 BY GREGORY STRONG

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

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

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


#ifndef FILE__GAME_H
#define FILE__GAME_H


#include "Board.h"
#include "Player.h"
#include "PieceType.h"
#include "Direction.h"
#include "Movement.h"
#include "Phase.h"
#include "HistoricalMove.h"


//	constants identifying the types of castling
#define CASTLING_TYPE_NONE                          0
#define CASTLING_TYPE_STANDARD                      1
#define CASTLING_TYPE_LONG                          2
#define CASTLING_TYPE_FLEXIBLE                      3
#define CASTLING_TYPE_CLOSE_ROOK                    4
#define CASTLING_TYPE_LONG_CLOSE_ROOK               5
#define CASTLING_TYPE_FLEXIBLE_CLOSE_ROOK           6
#define CASTLING_TYPE_VERY_CLOSE_ROOK               7
#define CASTLING_TYPE_LONG_VERY_CLOSE_ROOK          8
#define CASTLING_TYPE_FREE                          9
#define CASTLING_TYPE_FISCHER_RANDOM               10
#define CASTLING_TYPE_CHESS480                     11
#define CASTLING_TYPE_USER_CASTLING_1             100


//	constants identifying tye types of pawn promotion
#define PAWN_PROMOTION_TYPE_STANDARD                1
#define PAWN_PROMOTION_TYPE_MAJORS                  2
#define PAWN_PROMOTION_TYPE_REPLACEMENT             3
#define PAWN_PROMOTION_TYPE_QUEEN                   4


class Game
{
  protected:
	//	data members
	Board &board;						//	the board
	Player &player0;					//	the white player
	Player &player1;					//	the black player


	// *** GAME RULES *** //

	bool goalIsCheckmate;
	//	is the goal of this game to checkmate a King?  if true,
	//	moves are automatically checked for legality (can't leave
	//	your king in check, etc.)  set this to false for games with
	//	other victory conditions, like capture the king or whatever

	bool specialCheckTesting;
	//	set specialCheckTesting to true in games where the goal is 
	//	to checkmate, but there are pieces with special attacks which 
	//	cannot be generated by the internal engine.  with this set to 
	//	true, you must overload the IsInCheck function

	int stalemateResult;
	//	set to zero if stalemate is a draw; set to +INFINITY if 
	//	stalemating your opponent is considered a win, and set it 
	//	to -INFINITY in games where you lose if you stalemate your opponent

	bool usePawnStructureEvaluation;
	//	set this to true for games with chess-pawns (any piece which
	//	moves forward slowly but can't capture forward, and can only
	//	capture sideways.)  when true, pawn formations will be evaluated

	bool useQuiescentSearch;
	//	normally set to true, this activates the Quiescent Search

	bool useStaticExchangeEvaluation;
	//	normally set to true, this activates SEE.  this should be turned 
	//	off for games with captures that cannot be generated by the internal
	//	chess engine.  does not apply if useQuiescentSearch is set to false.

	int autoDrawPeriod;
	//	set this to something greater than zero for games with a rule
	//	like chess's fifty-move draw rule.  to implement this chess rule,
	//	set autoDrawPeriod to 100, not 50, since it is the number of 
	//	game plys not game moves by the chess definition.  a value of
	//	zero disables this rule entirely.  (it's zero by default)

	bool immobilizedPiecesCanCommitSuicide;
	//	if set to true, pieces on immobilized squares may not move, but 
	//	may remove themselves as a move.  this is for Ultima support.

	int boardAverageSquareValue;
	//	this defaults to 100, or 1/10th of a pawn.  this value is used 
	//	to scale the default square values.  for piece types that you 
	//	provide piece square tables for, this value is ignored.

	bool piecesHaveChangingValues;
	//	does this game have any piece types that change material value 
	//	as the board clears out and the game progresses into endgame?

	bool customMoveGeneration;
	bool customCaptureGeneration;

	int drawScore;						//	score for a draw (normally zero)

	bool gameOver;						//	is the game over?

	//	optimizations
	int endgameCaptureThreshold;		//	when this many pieces have been captured,
										//	we are in "endgame" and null-move will
										//	no longer be tried, lest we risk "zugzwang".
	int razorMargin;
	int futilityMargin;
	int extendedFutilityMargin;

	int moveHistoryLength;
	int moveCursor;

	char historicalMoveText[MAX_GAME_LENGTH][30];

	Phase phases[MAX_PHASES];
	int nPhases;


	//	helper functions
	int PenalizePiecesForMovingMultipleTimes();

	void AddEnPassantMoves
		( MovementList &stack,
		  GameRec &gameRecord, 
		  bool quiescentSearch );

	void AddCastlingMove
		( MovementList &stack,
		  GameRec &gameRecord, 
		  Piece *king,
		  Piece *castlingPiece,
		  int newKingSquare,
		  int newCastlingPieceSquare );

	void AddFreeCastlingMoves
		( MovementList &stack,
		  GameRec &gameRecord, 
		  Piece *king,
		  Piece *leftRook,
		  Piece *rightRook );

	void AddFlexibleCastlingMoves
		( MovementList &stack,
		  GameRec &gameRecord, 
		  Piece *king,
		  Piece *leftRook,
		  Piece *rightRook );

	word32 GetEnPassantHash
		( GameRec &gameRecord, 
		  HashMap *hashes );

	word32 GetBerolinaEnPassantHash
		( GameRec &gameRecord, 
		  HashMap *hashes );

	void RemovePieceFromSet
		( Piece *piece,
		  Piece *set[2][SET_SIZE],
		  int sizeOfSet );

	void AddPieceToSet
		( Piece *piece,
		  Piece *set[2][SET_SIZE],
		  int sizeOfSet );

	void GenerateMovesForCoordinator
		( Piece *piece,
		  Piece *king, 
		  MovementList &stack, 
		  GameRec &gameRecord, 
	  	  bool quiescentSearch );

	void GenerateMovesForLongLeaper
		( Piece *piece,
		  MovementList &stack, 
		  GameRec &gameRecord, 
	  	  bool quiescentSearch );

	void GenerateMovesForChameleon
		( Piece *piece,
		  Piece *king,
		  MovementList &stack, 
		  GameRec &gameRecord, 
		  bool quiescentSearch );

	void GenerateMovesForUltimaPawn
		( Piece *piece,
		  MovementList &stack, 
		  GameRec &gameRecord, 
		  bool quiescentSearch );

	void GenerateMovesForSwapper
		( Piece *piece,
		  MovementList &stack, 
		  GameRec &gameRecord, 
		  bool quiescentSearch );

	void GenerateMovesForCannon
		( int square,
		  int currentPlayer,
		  MovementList &list,
		  GameRec &gameRecord,
		  bool quiescentSearch,
		  int direction );


  public:
	//	construction
	Game( Board &theBoard, Player &whitePlayer, Player &blackPlayer );

	virtual void Initialize();

	virtual void AddPlayerPieceTypes( char *gameName );

	virtual void ChangeRulesByVariant( char *gameName, char *&array, char *&book );

	virtual void ChangeRulesByVariableDefinition( char *gameName );

	virtual void InitializationComplete( char *gameName );


	//	destruction
	virtual ~Game();


	//	attributes
	Player &GetPlayer( int nPlayer )
	{	return( nPlayer == 0 ? player0 : player1 );   }

	bool IsGoalToCheckmate() const 
	{	return goalIsCheckmate;   }

	bool HasSpecialCheckTesting() const 
	{	return specialCheckTesting;   }

	int GetAutoDrawPeriod() const 
	{	return autoDrawPeriod;   }

	bool UsePawnStructureEvaluation() const
	{	return usePawnStructureEvaluation;   }

	bool UseQuiescentSearch() const
	{	return useQuiescentSearch;   }

	bool UseStaticExchangeEvaluation() const 
	{	return useStaticExchangeEvaluation;   }

	int GetEndgameCaptureThreshold() const 
	{	return endgameCaptureThreshold;   }

	int GetAverageSquareValue() const 
	{	return boardAverageSquareValue;   }

	int GetMoveHistoryLength() const 
	{	return moveHistoryLength;   }

	int GetMoveHistoryCursor() const 
	{	return moveCursor;   }

	void SetMoveHistoryCursor( int cursor )
	{	moveCursor = cursor;   }

	char *GetHistoricalMoveText( int moveNumber )
	{	return historicalMoveText[moveNumber];   }

	int GetDrawScore() const 
	{	return drawScore;   }

	int GetStalemateScore() const 
	{	return stalemateResult;   }

	int GetRazorMargin() const 
	{	return razorMargin;   }

	int GetFutilityMargin() const 
	{	return futilityMargin;   }

	int GetExtendedFutilityMargin() const 
	{	return extendedFutilityMargin;   }

	void SetRazorMargin( int newMargin )
	{	razorMargin = newMargin;   }

	void SetFutilityMargin( int newMargin )
	{	futilityMargin = newMargin;   }

	void SetExtendedFutilityMargin( int newMargin )
	{	extendedFutilityMargin = newMargin;   }

	bool IsGameOver() const
	{	return gameOver;   }

	int DoPiecesHaveChangingValues() const
	{	return piecesHaveChangingValues;   }

	bool ImmobilizedPiecesCanCommitSuicide() const
	{	return immobilizedPiecesCanCommitSuicide;   }

	bool HasCustomMoveGeneration() const 
	{	return customMoveGeneration;   }

	bool HasCustomCaptureGeneration() const 
	{	return customCaptureGeneration;   }


	//	operations
	virtual void PlacePieces( char *array, char *&book );

	void AddHistoricalMove( MoveInfo &move );

	void GameOver( bool isGameOver )
	{	gameOver = isGameOver;   }


	// ******************************* //
	// ***                         *** //
	// ***     VIRTUAL METHODS     *** //
	// ***  for customizing games  *** //
	// ***                         *** //
	// ******************************* //

	virtual void SetPersonality
		( int personality );

	virtual PieceType **GetPieceTypesRequired
		( int &nPieceTypes );

	virtual Piece *AddPiece
		( PieceType &pieceType,
		  int nPlayer,
		  int nRank,
		  int nFile );

	virtual void DeletePiece
		( Piece *piece );

	virtual bool RemovePieceType
		( PieceType *pieceType );

	virtual bool AddPieceType
		( PieceType *pieceType,
		  int nPlayer );

	virtual bool MoveBeingMade
		( MoveInfo &moveInfo,
		  GameRec &gameRecord );

	virtual void AddSpecialMoves
		( int currentPlayer, 
		  MovementList &stack,
		  GameRec &gameRecord, 
		  bool quiescentSearch );

	virtual word32 AdjustPrimaryHash
		( word32 primaryHash );

	virtual Phase &AdjustEvaluation
		( int &eval,
		  PawnHash *pPawnHash );

	virtual bool TestForWinLossDraw
		( int &eval );

	virtual int EnumeratePromotions
		( Piece *piece,
		  int fromSquare,
		  int toSquare,
		  PieceType **promotions,
		  bool quiescentSearch );

	virtual int EnumeratePromotions
		( Piece *piece,
		  int fromSquare,
		  int toSquare,
		  Piece **promotions,
		  bool quiescentSearch );

	virtual void GenerateCaptures
		( int currentPlayer, 
		  MovementList &list );

	virtual void GenerateMoves
		( int currentPlayer, 
		  MovementList &list );

	virtual bool IsSquareAttacked
		( int squareNumber, 
		  int playerNumber );

	virtual void DescribeMove
		( MoveInfo &move,
		  char *queryDescription,
		  char *description,
		  char *notation );

	virtual void DescribeMove
		( Movement &movement,
		  char *description );

	virtual int TranslateMove
		( MovementList &stack,
		  char *notation );

	virtual void SaveGame
		( HANDLE fileHandle );

	virtual void GameLoaded();

	virtual void DefaultSettings();

	virtual void AboutToStartThinking
		( int currentPlayer );

	virtual void AboutToDeepenSearch
		( int currentPlayer );

	virtual void AboutToGenerateMoves
		( int currentPlayer, 
		  int currentDepth );

	virtual bool IsInCheck( Piece *king );

	virtual bool IsPositionForbidden();

	friend class CapablancaGame;
	friend class Board;
};


#endif
