# include "Game/Game.h"
# include "Pieces/Queen.h"
# include "EvaluationTestCase.h"
# include "TestHeader.h"
# include "Color.h"
# include "Square.h"
# include "Pieces/Piece.h"
# include "Moves/SimpleMove.h"
# include "Moves/CapturingMove.h"
# include "Moves/PromotingMove.h"
# include <Moves/PromotingCapture.h>
# include "Directions/Direction.h"
# include "Game/PositionalEvaluation.h"
# include <sstream>
using namespace Alice;
void
EvaluationTestCase::initializing()
{
  Game g;
  Evaluation eval;
  eval.startObserving(&g);
  assertLongsEqual(0, eval.score());
};

void
EvaluationTestCase::pawnCapture()
{
  Game g;
  g.forsytheString("k6K/p7/8/8/8/8/8/R7/");
  Evaluation eval;
  eval.startObserving(&g);
  Square a1(0,0);
  Square a7(0,6);
  Move* move = new CapturingMove(a1, a7);
  assertLongsEqual(4, eval.score());
  move->makeOn(g);
  assertLongsEqual(-5, eval.score());
};
void
EvaluationTestCase::knightCapture()
{
  Game g;
  g.forsytheString("k6K/n7/8/8/8/8/8/R7/");
  Evaluation eval;
  eval.startObserving(&g);
  Square a1(0,0);
  Square a7(0,6);
  Move* move = new CapturingMove(a1, a7);
  assertLongsEqual(2, eval.score());
  move->makeOn(g);
  assertLongsEqual(-5, eval.score());
};
void
EvaluationTestCase::bishopCapture()
{
  Game g;
  g.forsytheString("k6K/b7/8/8/8/8/8/R7/");
  Evaluation eval;
  eval.startObserving(&g);
  Square a1(0,0);
  Square a7(0,6);
  Move* move = new CapturingMove(a1, a7);
  assertLongsEqual(2, eval.score());
  move->makeOn(g);
  assertLongsEqual(-5, eval.score());
};
void
EvaluationTestCase::rookCapture()
{
  Game g;
  g.forsytheString("k6K/r7/8/8/8/8/8/R7/");
  Evaluation eval;
  eval.startObserving(&g);
  Square a1(0,0);
  Square a7(0,6);
  Move* move = new CapturingMove(a1, a7);
  assertLongsEqual(0, eval.score());
  move->makeOn(g);
  assertLongsEqual(-5, eval.score());
};
void
EvaluationTestCase::queenCapture()
{
  Game g;
  g.forsytheString("k6K/q7/8/8/8/8/8/R7/");
  Evaluation eval;
  eval.startObserving(&g);
  Square a1(0,0);
  Square a7(0,6);
  Move* move = new CapturingMove(a1, a7);
  assertLongsEqual(-4, eval.score());
  move->makeOn(g);
  assertLongsEqual(-5, eval.score());
};

void
EvaluationTestCase::pawnValue()
{
  Game g;
  g.forsytheString("k6K/8/8/8/8/8/P7/8/w");
  Evaluation eval;
  eval.setBasicValue(1000);
  eval.startObserving(&g);
  assertLongsEqual(1000, eval.score());
};

void
EvaluationTestCase::positional()
{
  PositionalEvaluation eval;
  assertLongsEqual(1000, eval.getBasicValue());
};

void
EvaluationTestCase::promotion()
{
  Game g;
  g.forsytheString("k6K/2P5/8/8/8/8/8/8/w");
  Evaluation eval;
  eval.startObserving(&g);
  Square c7(2,6);
  Square c8(2,7);
  Move* move = new PromotingMove(c7, c8, new Queen(Color::white()));
  CPPUNIT_ASSERT_EQUAL(Evaluation::Score(1), eval.score());
  move->makeOn(g);
  CPPUNIT_ASSERT_EQUAL(Evaluation::Score(-9), eval.score());
};

void
EvaluationTestCase::promotingCapture()
{
  //CPPUNIT_ASSERT(false);
  Game g;
  g.forsytheString("k2r3K/2P5/8/8/8/8/8/8/w");
  Evaluation eval;
  eval.startObserving(&g);
  Square c7(2,6);
  Square d8(3,7);
  Move* move = new PromotingCapture(c7, d8, new Queen(Color::white()));
  CPPUNIT_ASSERT_EQUAL(Evaluation::Score(-4), eval.score());
  move->makeOn(g);
  CPPUNIT_ASSERT_EQUAL(Evaluation::Score(-9), eval.score());
};

void 
EvaluationTestCase::twoGames()
{
  Evaluation eval;
  //std::cerr<<"evaluation: "<<&eval<<std::endl;
  {
    Game g;
    
    eval.startObserving(&g);
    eval.stopObserving();
  }
  {
    Game g;
    eval.startObserving(&g);
    eval.stopObserving();
  }
};

Test*
EvaluationTestCase::suite()
{
  TestSuite* testSuite = new TestSuite("EvaluationTestCase");
  AddTest(testSuite, EvaluationTestCase, initializing);
  AddTest(testSuite, EvaluationTestCase, pawnCapture);
  AddTest(testSuite, EvaluationTestCase, knightCapture);
  AddTest(testSuite, EvaluationTestCase, bishopCapture);
  AddTest(testSuite, EvaluationTestCase, rookCapture);
  AddTest(testSuite, EvaluationTestCase, queenCapture);
  AddTest(testSuite, EvaluationTestCase, pawnValue);
  AddTest(testSuite, EvaluationTestCase, positional);
  AddTest(testSuite, EvaluationTestCase, promotion);
  AddTest(testSuite, EvaluationTestCase, promotingCapture);
  AddTest(testSuite, EvaluationTestCase, twoGames);
  return testSuite;
};
