/***************************************************************************
                          Pawn.cpp  -  description
                             -------------------
    begin                : Tue May 22 2001
    copyright            : (C) 2001 by Sven Reichard
    email                : reichard@math.udel.edu
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program 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.                                   *
 *                                                                         *
 ***************************************************************************/
# include "Pieces/Pawn.h"
# include "Directions/Direction.h"
# include "Color.h"
# include "Board.h"
# include "Square.h"
# include "Moves/SimpleMove.h"
# include "Moves/CapturingMove.h"
# include "Moves/PromotingMove.h"
# include "Moves/PromotingCapture.h"
# include "Moves/DoubleStep.h"
using namespace Alice;
Pawn::Pawn(Color* aColor):
  Piece(aColor, 'P')
{};

Pawn::~Pawn()
{};

char
Pawn::displayLetter() const
{
  return 'P';
};

void 
Pawn::pseudolegalMoves (MoveList& moves, 
			const Square& sq, const Board& b,
			bool capturesOnly) const
{
  const Direction* forward;
  (color()->isWhite())?
   forward = &Direction::up():
   forward = & Direction::down();
  Square destination(forward->appliedTo(sq));
  if (! capturesOnly) {
    if (b.at(destination)->isNull()){
      allMoves(moves, sq, destination);
      bool doubleStep;
      if (color()->isWhite())
        doubleStep = (sq.rank() == 1);
      else
        doubleStep = (sq.rank() == 6);
      if (doubleStep) {
        Square doubleDestination = forward->appliedTo(destination);
        if (b.at(doubleDestination)->isNull()){
  				MoveList::value_type newMove(DoubleStep::createInstance(sq, doubleDestination, destination));
  				moves.push_back(newMove);
        }
      }
  	
    }
  }
  Square capture(destination.left());
  if (capture.isValid()){
  	if( b.at(capture)->color() == color()->otherColor())
    	allCaptures(moves, sq, capture);
   }
  capture = destination.right();
  if (capture.isValid()) {
  	if( b.at(capture)->color() == color()->otherColor())
    	allCaptures(moves, sq, capture);
   }
  //delete forward;
};

void 
Pawn::allMoves(MoveList& moves, const Square& source,
		const Square& destination) const
{
  if ((color()->isWhite() && (destination.rank() != 7)) ||
      (color()->isBlack() && (destination.rank() != 0))) {
    moves.push_back(MoveList::value_type(SimpleMove::createInstance(source, destination)));
    return;
  }
  moves.push_back(MoveList::value_type(new PromotingMove(source, destination, newQueen(color()))));
  moves.push_back(MoveList::value_type(new PromotingMove(source, destination, newRook(color()))));
  moves.push_back(MoveList::value_type(new PromotingMove(source, destination, newBishop(color()))));
  moves.push_back(MoveList::value_type(new PromotingMove(source, destination, newKnight(color()))));
};
void 
Pawn::allCaptures(MoveList& moves, const Square& source,
		const Square& destination) const
{
  if ((color()->isWhite() && (destination.rank() != 7)) ||
      (color()->isBlack() && (destination.rank() != 0))) {
    moves.push_back(MoveList::value_type(new CapturingMove(source, destination)));
    return;
  }
  moves.push_back(MoveList::value_type(new PromotingCapture(source, 
				       destination, 
				       newQueen(color()))));
  moves.push_back(MoveList::value_type(new PromotingCapture(source, 
				       destination, 
				       newRook(color()))));
  moves.push_back(MoveList::value_type(new PromotingCapture(source, 
				       destination, 
				       newBishop(color()))));
  moves.push_back(MoveList::value_type(new PromotingCapture(source, 
				       destination, 
				       newKnight(color()))));
};
bool
Pawn::isPawn() const
{
  return true;
};
Evaluation::Score 
Pawn::basicValue() const
{
  return Evaluation::Score(1);
};

bool 
Pawn::attacks(const Direction* dir, const Square& location,
		       const Square& target) const
{
  if (! dir->isDiagonal())
    return false;
  if (color()->isWhite())
    return location.rank() + 1 == target.rank();
  else
    return location.rank()-1 == target.rank();
};

int
Pawn::centralizationFactor() const
{
  return 10;
}; 

Piece*
Pawn::clone() const
{
  return newPawn( color() );
};
