//////////////////////////////////////////////////
// (c) MMIII Sven Reichard
// 

# include <BitboardTest.h>
# include <Board.h>
# include <Game/Game.h>
# include <iostream>
CPPUNIT_TEST_SUITE_REGISTRATION( BitboardTest );
using namespace Alice;
void
BitboardTest::testGetByte()
{
  Bitboard b( 0xffee887700112233ull );
  CPPUNIT_ASSERT_EQUAL( 0x33, (int) b.getByte(0) );
  CPPUNIT_ASSERT_EQUAL( 0x22, (int) b.getByte(1) );
  CPPUNIT_ASSERT_EQUAL( 0x11, (int) b.getByte(2) );
  CPPUNIT_ASSERT_EQUAL( 0x00, (int) b.getByte(3) );
  CPPUNIT_ASSERT_EQUAL( 0x77, (int) b.getByte(4) );
  CPPUNIT_ASSERT_EQUAL( 0x88, (int) b.getByte(5) );
  CPPUNIT_ASSERT_EQUAL( 0xee, (int) b.getByte(6) );
  CPPUNIT_ASSERT_EQUAL( 0xff, (int) b.getByte(7) );
};

void
BitboardTest::testGetRooks()
{
  Board b;
  b.initialPosition();
  Bitboard expected(0x0100000000000001ull);
  Bitboard result = b.getWhiteRooks();
  CPPUNIT_ASSERT_EQUAL( expected, result );
};

void
BitboardTest::testFirstBit()
{
  Bitboard b;
  b.set(15);
  b.set(37);
  CPPUNIT_ASSERT_EQUAL( 15, b.getFirstBit() );
  b.clear(15);
  CPPUNIT_ASSERT_EQUAL( 37, b.getFirstBit() );
};

void
BitboardTest::testLastBit()
{
  Bitboard b;
  b.set(15);
  b.set(37);
  CPPUNIT_ASSERT_EQUAL( 37, b.getLastBit() );
  b.clear(37);
  CPPUNIT_ASSERT_EQUAL( 15, b.getLastBit() );
};

void
BitboardTest::testIterator()
{
  Bitboard b;
  b.set(15);
  b.set(37);
  Bitboard::Iterator it(b);
  CPPUNIT_ASSERT( it );
  CPPUNIT_ASSERT_EQUAL( Square(15), *it );
  ++ it;
  CPPUNIT_ASSERT( it );
  CPPUNIT_ASSERT_EQUAL( Square(37), *it );
  ++ it;
  CPPUNIT_ASSERT( ! it );
};

void
BitboardTest::testFileAttacks()
{
  Bitboard b;
  int pos = 3;
  b.set(pos);
  b.set( 9 );
  b.set( 12 );
  Bitboard expected = 0xff & ~( 1<<pos );
  Bitboard result = b.getFileAttacks( pos );
  CPPUNIT_ASSERT_EQUAL( expected, result );
  Bitboard expected2 = 0x1600;
  Bitboard result2  = b.getFileAttacks( 11 );
  CPPUNIT_ASSERT_EQUAL(  expected2,  result2 );
};

void
BitboardTest::testRotatedNumber()
{
  Square sq(3,6);
  Square sq2(6,3);
  CPPUNIT_ASSERT_EQUAL((int)sq2.number(), (int)sq.flippedNumber());
};

void
BitboardTest::testRotated90()
{
  Bitboard b;
  b.setRotated90( 1 );
  b.setRotated90( 3 );
  Bitboard expected(0x0000000001000100ull);
  CPPUNIT_ASSERT_EQUAL( expected, b );
  expected.clear(8);
  b.clearRotated90( 1 );
  CPPUNIT_ASSERT_EQUAL( expected, b );
};

void
BitboardTest::testSetRank()
{
  Bitboard b;
  b.setRank(1, 0xb7);
  Bitboard expected(0x0200020200020202ull);
  CPPUNIT_ASSERT_EQUAL( expected, b );
};

void
BitboardTest::testRankMask()
{
  Bitboard expected(0x0404040404040404ull);
  CPPUNIT_ASSERT_EQUAL( expected,  Bitboard::getRankMask(2) );
};

void
BitboardTest::testRankAttacks()
{
  Board b;
  std::string forsythe("8/8/8/8/kp2R2K/8/8/8");
  std::istringstream stream( forsythe );
  b.readForsythe( stream );
  Bitboard rotated = b.getAllPiecesRotated90();
  Bitboard expected(0x0808080008080800ull);
  Bitboard result = rotated.getRankAttacks(Square(4, 3));
  CPPUNIT_ASSERT_EQUAL( expected, result );
};

void
BitboardTest::testKnightAttacks()
{
  Bitboard b;
  Bitboard expected(0x20400);
  Bitboard result = b.getKnightAttacks(Square (0,0));
  CPPUNIT_ASSERT_EQUAL( expected, result);
};

void
BitboardTest::testKingAttacks()
{
  Bitboard b;
  Bitboard result = b.getKingAttacks( Square(2,0) );
  Bitboard expected(0x03020300);
  CPPUNIT_ASSERT_EQUAL( expected, result );
};

void
BitboardTest::testDownDiagonalMasks()
{
  Bitboard expected1 = 0x01020408;
  Bitboard result = Bitboard::getDownDiagonalMask( 3 );
  CPPUNIT_ASSERT_EQUAL( expected1, result );
};

void
BitboardTest::testRotated45()
{
  Bitboard rotated;
  Bitboard expected(0x8001);
  Square a1(0,0), c8(2,7);
  rotated.setRotated45( a1 );
  rotated.setRotated45( c8 );
  CPPUNIT_ASSERT_EQUAL( expected, rotated );
  Bitboard expected2 = 1;
  rotated.clearRotated45( c8 );
  CPPUNIT_ASSERT_EQUAL( expected2, rotated );
};

void
BitboardTest::testRotated135()
{
  Bitboard rotated;
  Bitboard expected(0x0401);
  Square a1(0,0), b3(1,2);
  rotated.setRotated135( a1 );
  rotated.setRotated135( b3 );
  CPPUNIT_ASSERT_EQUAL( expected, rotated );
};

void
BitboardTest::testUpDiagonalMask()
{
  Bitboard expected = 0x8040201008040201ull;
  Bitboard upDiagonal8 = Bitboard::getUpDiagonalMask( 8 );
  CPPUNIT_ASSERT_EQUAL( expected, upDiagonal8 );
  expected = 0x80402010;
  Bitboard upDiagonal12 = Bitboard::getUpDiagonalMask( 12 );
  CPPUNIT_ASSERT_EQUAL( expected, upDiagonal12 );
  expected = 0x0804020100000000ull;
  Bitboard upDiagonal4 = Bitboard::getUpDiagonalMask(4);
  CPPUNIT_ASSERT_EQUAL( expected, upDiagonal4 );
  Square sq(upDiagonal12.getFirstBit());
  CPPUNIT_ASSERT_EQUAL( 12, (int)sq.getUpDiagonalNumber());
};

void
BitboardTest::testUpDiagonalAttacks()
{
  Board b;
  std::string forsythe("6k1/5p2/8/3B4/8/8/K7/8");
  std::stringstream in( forsythe);
  b.readForsythe( in );

  Bitboard pieces = b.getAllPiecesRotated135();
  Bitboard expected ;
  expected.set(Square(0,1));
  expected.set(Square(1,2));
  expected.set(Square(2,3));
  expected.set(Square(4,5));
  expected.set(Square(5,6));
  Square d5(3,4);
  CPPUNIT_ASSERT_EQUAL( 12, (int) d5.getNumberRotated135());
  Bitboard result = pieces.getUpDiagonalAttacks( d5 );
  CPPUNIT_ASSERT_EQUAL( expected, result );
};

void
BitboardTest::testDownDiagonalAttacks()
{
  Board b;
  std::string forsythe("8/k7/1p6/8/3B4/8/5P2/6K1");
  std::stringstream in( forsythe);
  b.readForsythe( in );
  
  Bitboard pieces = b.getAllPiecesRotated45();
  Bitboard expected = 0x0000020400102000ull;
  
  Square d4(3,3);
  Bitboard result = pieces.getDownDiagonalAttacks(d4);
  CPPUNIT_ASSERT_EQUAL( expected, result);
};
