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

                                 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__BITBOARD96_H
#define FILE__BITBOARD96_H


#include "Vector.h"


class BitBoard96;


typedef Vector<int> IntVector;
typedef Vector<BitBoard96> BitBoard96Vector;


class BitBoard96
{
  protected:
	bit_data data;	//	must be first data-memeber
	word32 hiData;	//	hi-order 32 bits of bitboard

	//	helper structures
	static IntVector bitCount;
	static IntVector firstBit;


  public:
	// *** CONSTRUCTION *** //
	BitBoard96( word32 hi_order_bits = 0UL, bit_data bits = 0ULL )
	{	hiData = hi_order_bits;  data = bits;   }

	BitBoard96( BitBoard96 const &other )
	{	hiData = other.hiData;  data = other.data;   }

	static void InitializeData( int nRanks, int nFiles );


	// *** ATTRIBUTES *** //
	word32 GetHiOrderBits() const
	{	return hiData;   }

	bit_data GetLowOrderBits() const
	{	return data;   }

	int GetBitCount() const
	{	return bitCount.GetElement( (unsigned) (hiData >> 16) ) + 
		       bitCount.GetElement( (unsigned)  hiData & 0xFFFFUL ) + 
		       bitCount.GetElement( (unsigned) (data >> 48) ) + 
		       bitCount.GetElement( (unsigned) (data >> 32) & 0xFFFFUL ) + 
		       bitCount.GetElement( (unsigned) (data >> 16) & 0xFFFFUL ) + 
		       bitCount.GetElement( (unsigned)  data & 0xFFFFUL );   }

	static BitBoard96 GetNullBitBoard()
	{	return BitBoard96();   }

	static BitBoard96 GetTrueBitBoard()
	{	return BitBoard96( 0xFFFFFFFFUL, 0xFFFFFFFFFFFFFFFFULL );   }

	static BitBoard96 GetPositionBitBoard( int nBit )
	{
		if( nBit < 64 )
			return BitBoard96( 0UL, 1ULL << nBit );
		return BitBoard96( 1UL << (nBit - 64), 0ULL );
	}


	// *** OPERATIONS *** //
	void Clear()
	{	hiData = 0UL;  data = 0ULL;   }

	BitBoard96 operator ~()
	{	return BitBoard96( ~hiData, ~data );   }

	BitBoard96 operator &( BitBoard96 const &other ) const
	{	return BitBoard96( GetHiOrderBits() & other.GetHiOrderBits(), GetLowOrderBits() & other.GetLowOrderBits() );   }

	BitBoard96 operator &( int intBitMask ) const
	{	return BitBoard96( GetHiOrderBits(), GetLowOrderBits() & intBitMask );   }

	BitBoard96 operator |( BitBoard96 const &other ) const
	{	return BitBoard96( GetHiOrderBits() | other.GetHiOrderBits(), GetLowOrderBits() | other.GetLowOrderBits() );   }

	BitBoard96 operator ^( BitBoard96 const &other ) const
	{	return BitBoard96( GetHiOrderBits() ^ other.GetHiOrderBits(), GetLowOrderBits() ^ other.GetLowOrderBits() );   }

	bool operator &&( BitBoard96 const &other ) const
	{	return( (bool) (*this) && (bool) other );   }

	bool operator ||( BitBoard96 const &other ) const
	{	return( (bool) (*this) || (bool) other );   }

	word32 operator >>( int shift ) const
	{
		if( shift < 48 )
			return (word32) (GetLowOrderBits() >> shift);
		if( shift >= 64 )
			return (word32) (GetHiOrderBits() >> (shift - 64));
		return (word32) (GetLowOrderBits() >> shift) | (word32) (GetHiOrderBits() << (64 - shift));
	}

	word32 operator >>( unsigned shift ) const
	{
		if( shift < 48 )
			return (word32) (GetLowOrderBits() >> shift);
		if( shift >= 64 )
			return (word32) (GetHiOrderBits() >> (shift - 64));
		return (word32) (GetLowOrderBits() >> shift) | (word32) (GetHiOrderBits() << (64 - shift));
	}

	BitBoard96 &operator=( BitBoard96 const &other )
	{	data = other.GetLowOrderBits();  hiData = other.GetHiOrderBits();   return *this;   }

	BitBoard96 operator &=( BitBoard96 const &other ) 
	{	data &= other.GetLowOrderBits();  hiData &= other.GetHiOrderBits();  return *this;   }

	BitBoard96 operator |=( BitBoard96 const &other ) 
	{	data |= other.GetLowOrderBits();  hiData |= other.GetHiOrderBits();  return *this;   }

	BitBoard96 operator ^=( BitBoard96 const &other ) 
	{	data ^= other.GetLowOrderBits();  hiData ^= other.GetHiOrderBits();  return *this;   }

	operator bool() const 
	{	return data != 0ULL || hiData != 0UL;   }

	bool operator[]( int nBit ) const
	{
		if( nBit < 64 )
			return (data & (1ULL << nBit)) != 0ULL;
		return (hiData & (1UL << (nBit - 64))) != 0ULL;
	}

	bool GetBit( int nBit ) const
	{
		if( nBit < 64 )
			return (data & (1ULL << nBit)) != 0ULL;
		return (hiData & (1UL << (nBit - 64))) != 0ULL;
	}

	void SetBit( int nBit )
	{
		if( nBit < 64 )
			data = data | (1ULL << nBit);
		else
			hiData = hiData | (1UL << (nBit - 64));
	}

	void ClearBit( int nBit )
	{
		if( nBit < 64 )
			data = data & (0xFFFFFFFFFFFFFFFFULL ^ (1ULL << nBit));
		else
			hiData = hiData & (0xFFFFFFFFUL ^ (1UL << (nBit - 64)));
	}

	void ToggleBit( int nBit )
	{
		if( nBit < 64 )
			data = data ^ (1ULL << nBit);
		else
			hiData = hiData ^ (1UL << (nBit - 64));
	}

	int GetFirstBit()
	{
		if( hiData )
		{
			if( hiData >> 16 )
				return firstBit[(int) (hiData >> 16)] + 80;
			return firstBit[(int) hiData] + 64;
		}
		if( data & 0xFFFFFFFF00000000ULL )
		{
			if( data >> 48 )
				return firstBit[(int) (data >> 48)] + 48;
			return firstBit[(int) (data >> 32)] + 32;
		}
		if( data >> 16 )
			return firstBit[(int) (data >> 16)] + 16;
		return firstBit[(int) data];
	}

	void PrintToFile
		( FILE *file, 
		  int nRanks, 
		  int nFiles );
};


#endif
