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

                                 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_H
#define FILE__MOVEMENT_H


//	***********************
//	**                   **
//	**      MoveType     **
//	**                   **
//	***********************
//
//	this enum identifies the "type" of move.  for games similar to chess, 
//	this is usually StandardMove or StandardCapture, but extra types are 
//	defined so Game-derived classes can use them for custom moves. 

enum MoveType
{
	Invalid = 0,
	StandardMove = 1,
	StandardCapture = 2,
	IguiCapture = 3,
	Castling = 4,
	FlexibleCastling = 5,
	FreeCastling = 6,
	EnPassant = 7,
	CaptureByWithdrawl = 8,
	CaptureByAdvance = 9,
	CaptureByAdvanceAndWithdrawl = 10,
	Swap = 11,
	SuicideMove = 12,
	MutualDestruction = 13,
	Replacement = 14,
	CaptureWithReplacement = 15,
	NullMove = 20,
	UserCastling = 100,
	UserMove1 = 101,
	UserMove2 = 102,
	UserMove3 = 103,
	UserMove4 = 104
};


//	***********************
//	**                   **
//	**      Movement     **
//	**                   **
//	***********************
//
//	the Movement class stores enough information to uniquely identify a 
//	move.  the Movement class is how killer-moves and hashtable moves are 
//	stored.  moves on the MovementList are not stored as Movements, they 
//	use the MoveInfo class instead, which stores lots of extra information 
//	needed for making and unmaking the move.  
//
//	the data is stored in 8 bytes - data, a byte[4], and newType, a pointer 
//	to a PieceType.  the bytes of the data structure are used as follows:
//
//		data[0] - square number of the square moved from 
//		data[1] - square number of the square moved to
//		data[2] - the MoveType (cast into a byte)
//		data[3] - user-defined; used by Game-derived classes to 
//				  uniquely identify moves that would otherwise overlap. 
//				  see Extended Castling in Capablanca Chess Aberg Variant's 
//				  variant for an example
//
//		newType - in cases of a promotion, or if the moving piece otherwise 
//				  changes type, this points to the new type.  otherwise, it 
//				  is set to NULL.

class Movement
{
  protected:
	byte data[4];
	PieceType *newType;

  public:
	//	construction
	Movement()
	{
		*((unsigned *) data) = 0UL;
		newType = NULL;
	}

	Movement( const MoveInfo &moveInfo );

	Movement( int fromSquare, int toSquare, MoveType type, byte tag = 0 )
	{
		data[0] = (byte) fromSquare;
		data[1] = (byte) toSquare;
		data[2] = (byte) type;
		data[3] = tag;
		newType = NULL;
	}

	Movement( unsigned int moveData )
	{
		*((unsigned int *) data) = moveData;
	}


	//	attributes
	int GetFromSquare() const
	{	return (int) data[0];   }

	int GetToSquare() const
	{	return (int) data[1];   }

	MoveType GetMoveType() const
	{	return (MoveType) data[2];   }

	byte GetTag() const
	{	return data[3];   }

	PieceType *GetNewType() const
	{	return newType;   }

	bool IsValid() const
	{	return data[2] != Invalid;   }

	bool operator==( Movement &other )
	{	return *(reinterpret_cast<int *>(data)) == *(reinterpret_cast<int *>(other.data)) && 
		       newType == other.newType;   }

	bool operator!=( Movement &other )
	{	return *(reinterpret_cast<int *>(data)) != *(reinterpret_cast<int *>(other.data)) ||
		       newType != other.newType;   }

	unsigned int GetData()
	{	return *(reinterpret_cast<unsigned int *>(data));   }


	//	operations
	void Clear()
	{	*((unsigned *) data) = 0UL;   newType = NULL;   }


	//	assignment
	Movement &operator=( Movement &other )
	{
		*(reinterpret_cast<int *>(data)) = *(reinterpret_cast<int *>(other.data));
		newType = other.newType;
		return( *this );
	}
};


#endif
