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

                                 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__MOVEMENT_LIST_H
#define FILE__MOVEMENT_LIST_H


#define MOVEMENT_LIST_SIZE		256


#include "MoveInfo.h"
#include "PickUp.h"
#include "Drop.h"
#include "ExchangeEvaluator.h"
#include "BitBoard64.h"
#include "BitBoard96.h"


class MovementList
{
  protected:
	// *** DATA MEMBERS *** //

	Board *board;			/*	pointer to the Board object  */									NO_MANS_LAND(1)

	MoveInfo *moves;		/*	pointer to MoveInfos for all moves on stack  */
	int moveCursor;			/*	current index into moves array (for additions)  */

    PickUp *pickups;		/*	pointer to array of Pickup objects   */
	int pickupCursor;		/*	current index into pickups array  */

	Drop *drops;			/*	pointer to array of Drop objects  */
	int dropCursor;			/*	current index into drops array  */

	bool checkForLegality;	/*	if true, all moves pushed onto the stack are
								made and unmade to check for legality, and if
								not legal, the move will not really be pushed  */

	int tempPickupCursor;
	int tempDropCursor;																			NO_MANS_LAND(2)

	int moveOrder[MAX_MOVES];																	NO_MANS_LAND(3)
	//	move order array; the integers stored here are indexes
	//	into the moves array, ordered from the (probably) best move
	//	to the (probably) worst move

	int currentMove;		
	//	index into the moveOrder array of the next move to be
	//	executed, or the move that was just executed

	int indexOfMoveMade;
	//	index into the moves array of the move that has been make, 
	//	or -1 if no move is currently made

	bool quiescentSearch;
	//	true if we are in quiescent search, or false otherwise.
	//	in quiescent search, we don't order the captures first,
	//	we pick the best one one-at-a-time as we need them.  since
	//	cut-offs are common, we often save the time of sorting.

	Movement hashtableMove; 
	//	move suggested by the Transposition Table (if any).
	//	this move gets the highest ordering.

	Movement secondMove;
	//	move suggested by the Alternate Move Table (if any).
	//	this move gets the second highest ordering.

	bool hashtableMoveFound;


	// *** HELPER FUNCTIONS *** //
	void PerformPickUp( int index, MoveInfo &info );
	void PerformDrop( int index, MoveInfo &info );
	void UndoPickUp( int index, MoveInfo &info );
	void UndoDrop( int index, MoveInfo &info );
	bool MakeMove( int moveNumber );
	bool MakeMove( Movement movement );
	void UnmakeMove( int moveNumber );
	int EvaluateExchange( int moveNumber );
	void PretendMoveWasBeingMade( Movement move, word32 &priHash, word32 &secHash );


	// *** MOVE ORDERING *** //
	void OrderMoves( Movement hashMove, NodeType nodeType );
	void OrderCaptures( Movement hashMove, NodeType nodeType );

	//	these are used internally by the
	//	EvaluateExchange function
	AttackVector *playerAttackers[2];
	int *playerAttackOrder[2];
	int swapList[48];


  public:
	//	construction
	MovementList()
	{
		INIT_NO_MANS_LAND(1)
		INIT_NO_MANS_LAND(2)
		INIT_NO_MANS_LAND(3)

		moves = new MoveInfo[MOVEMENT_LIST_SIZE];
		pickups = new PickUp[MOVEMENT_LIST_SIZE];
		drops = new Drop[MOVEMENT_LIST_SIZE];
		playerAttackers[0] = new AttackVector[MAX_DIRECTIONS];
		playerAttackers[1] = new AttackVector[MAX_DIRECTIONS];
		playerAttackOrder[0] = new int[MAX_DIRECTIONS];
		playerAttackOrder[1] = new int[MAX_DIRECTIONS];
		moveCursor = 0;
		indexOfMoveMade = -1;
		pickupCursor = 0;
		dropCursor = 0;
		checkForLegality = false;
		currentMove = 0;
		quiescentSearch = false;
	}

	~MovementList()
	{
		delete[] moves;
		delete[] pickups;
		delete[] drops;
		delete[] playerAttackers[0];
		delete[] playerAttackers[1];
		delete[] playerAttackOrder[0];
		delete[] playerAttackOrder[1];
	}


	void SetBoard( Board *theBoard )
	{	board = theBoard;   }


	// *** ATTRIBUTES *** //
	Board *GetBoard()
	{	return board;   }

	int GetCount()
	{	return moveCursor;   }

	int GetCurrentMoveIndex()
	{	return moveOrder[currentMove];   }

	int GetCurrentUnorderedMoveIndex()
	{	return currentMove;   }

	MoveInfo &GetCurrentMove()
	{	return moves[indexOfMoveMade];   }

	MoveInfo &GetMove( int nMove )
	{	return moves[nMove];   }

	MoveInfo &GetOrderedMove( int nMove )
	{	return moves[moveOrder[nMove]];   }

	MoveInfo &GetMove( int nMove, int &nCaptures )
	{
		int nPickups = nMove == 0 ? moves[0].pickupCursor : 
			moves[nMove].pickupCursor - moves[nMove-1].pickupCursor;
		int nDrops = nMove == 0 ? moves[0].dropCursor : 
			moves[nMove].dropCursor - moves[nMove-1].dropCursor;
		nCaptures = nPickups - nDrops;
		return moves[nMove];   
	}

	void ResetCurrentMove()
	{	currentMove = 0;  }

	void CheckMovesForLegality()
	{	checkForLegality = true;   }


	int CopyMoveToList
		( int moveNumber,
		  MovementList &other );


	// *** ADDING MOVES TO THE LIST *** //
	void AddMove
		( int fromSquareNumber,
		  int toSquareNumber );

	void AddCapture
		( int fromSquareNumber,
		  int toSquareNumber );

	void AddIguiCapture
		( int fromSquareNumber,
		  int toSquareNumber );

	void BeginMoveAdd
		( MoveType moveType,
		  int fromSquareNumber,
		  int toSquareNumber,
		  byte tag = 0 );

	void AddPickUp( int squareNumber );

	void AddDrop
		( Piece *piece, 
		  int squareNumber,
		  PieceType *newType = NULL );

	int EndMoveAdd( int evaluation = 25000 );

	void BeginMoveCopy
		( MoveType moveType,
		  int fromSquareNumber,
		  int toSquareNumber,
		  byte tag, 
		  PieceType *promotion );

	int EndMoveCopy( int evaluation );

	void AddBitBoard64Moves( int fromSquare, BitBoard64 toSquares );
	void AddBitBoard64Captures( int fromSquare, BitBoard64 toSquares );
	void AddBitBoard96Moves( int fromSquare, BitBoard96 toSquares );
	void AddBitBoard96Captures( int fromSquare, BitBoard96 toSquares );

	// *** USER INTERFACE *** //
	void AdjustUIElements( int moveNumber );


	// *** MOVE GENERATION *** //
	void GenerateMoves( NodeType nodeType );
	void GenerateMoves( Movement lookupMove, Movement secondaryMove, NodeType nodeType );
	void GenerateCaptures( Movement lookupMove, NodeType nodeType );

	// *** MOVE ORDERING *** //
	void ReorderRoot( int currentIDepth );

	//	operations - move making and unmaking
	void ResetMoveOrdering();
	bool MakeNextMove();
	void UnmakeMove();

	void Clear(); 
	
	void Pop( int moveCount = 1 );


	// *** DIAGNOSTICS *** //
	void AssertValid();

	void Output( FILE *fi );


	//	friends
	friend class Board;
};


#endif
