/**********************************************************************
 *
 *   FreeDoko a Doppelkopf-Game
 *    
 *   Copyright (C) 2001-2006  by Diether Knof and Borg Enders
 *
 *   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.
 *
 *   This program 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. 
 *   You can find this license in the file 'gpl.txt'.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
 *   MA  02111-1307  USA
 *
 *  Contact:
 *    Diether Knof dknof@gmx.de
 *    Borg Enders  borg@borgsoft.de
 *
 *********************************************************************/

#include "constants.h"

#include "ai.h"

#include "../../game/game.h"
#include "../../party/rule.h"
#include "../../card/trick.h"

/**
 **
 ** Constructor
 **
 ** @param	-
 **
 ** @return	-
 **
 ** @version	0.5.4
 **
 ** @author	Diether Knof
 **
 **/
AiDummy::AiDummy() :
Player(Player::AI_DUMMY),
Aiconfig()
{
  //  this->set_name(::generate_name(RAND(4) + 5));

  return ;
} // AiDummy::AiDummy()

/**
 **
 ** Construktor
 **
 ** @param	istr	stream with the infos
 **
 ** @return	-
 **
 ** @author	Diether Knof
 **
 ** @version	0.5.2
 **
 ** @todo	all
 **
 **/
AiDummy::AiDummy(istream& istr) :
Player(AI_DUMMY),
Aiconfig()
{
  (void)istr;
  DEBUG_ASSERTION(false,
		  "AiDummy::AiDummy(istr):\n"
		  "  Contructor not implemented");

  return ;
} // AiDummy::AiDummy(istream& istr)

/**
 **
 ** copy constructor
 **
 ** @param	player	player to copy
 **
 ** @return	-
 **
 ** @version	0.5.3
 **
 ** @author	Diether Knof
 **      
 **
 **/
AiDummy::AiDummy(Player const& player) :
Player(player),
Aiconfig()
{
  this->set_type(AI_DUMMY);

  return ;
} // AiDummy::AiDummy(Player const& player)

/**
 **
 ** copy constructor
 **
 ** @param	player		player to copy
 ** @param	aiconfig	configuration to copy
 **
 ** @return	-
 **
 ** @version	0.6.7
 **
 ** @author	Diether Knof
 **      
 **
 **/
AiDummy::AiDummy(Player const& player, Aiconfig const& aiconfig) :
Player(player),
Aiconfig(aiconfig)
{
  this->set_type(AI_DUMMY);

  return ;
} // AiDummy::AiDummy(Player const& player, Aiconfig const& aiconfig)

/**
 **
 ** copy constructor
 **
 ** @param	ai_dummy	ai to copy
 **
 ** @return	-
 **
 ** @version	0.5.3
 **
 ** @author	Diether Knof
 **      
 **
 **/
AiDummy::AiDummy(AiDummy const& ai_dummy) :
Player(ai_dummy),
Aiconfig(ai_dummy)
{
  this->set_type(AI_DUMMY);

  return ;
} // AiDummy::AiDummy(AiDummy const& ai_dummy)

/**
 **
 ** clone the player
 **
 ** @param       -
 **
 ** @return      pointer of a clone
 **
 ** @author      Diether Knof
 **
 ** @version     0.5.3
 **
 **/
AiDummy*
AiDummy::clone() const
{  
  return new AiDummy(*this);
} // virtual AiDummy* AiDummy::clone() const

/**
 **
 ** copy operator
 **
 ** @param	ai_dummy	ai to copy
 **
 ** @return	copied ai
 **
 ** @version	0.5.4
 **
 ** @author	Diether Knof
 **      
 **
 **/
AiDummy&
AiDummy::operator=(AiDummy const& ai_dummy)
{
  static_cast<Player&>(*this) = static_cast<Player const&>(ai_dummy);
  static_cast<Aiconfig&>(*this) = static_cast<Aiconfig const&>(ai_dummy);

  return *this;
} // AiDummy& AiDummy::operator=(AiDummy const& ai_dummy)

/**
 **
 ** Destructor
 **
 ** @param	-
 **
 ** @return	-
 **
 ** @version	0.5.4
 **
 ** @author	Diether Knof
 **      
 **
 **/
AiDummy::~AiDummy()
{
  return ;
} // AiDummy::~AiDummy()

/**
 ** -> result
 ** (test of poverty, marriage, swines, hyperswines)
 **
 ** @param	duty_solo	whether the player has to play a solo
 ** 				(default: false)
 **
 ** @return	simple Reservation
 **
 ** @author	Diether Knof
 **
 ** @version	0.5.3
 **/
Reservation
AiDummy::reservation_get(bool const duty_solo)
{
  (void)duty_solo;

  Reservation reservation;

  if (this->game().rule()(Rule::HYPERSWINES)
      && (this->hand().numberoftrumpnines() == 2))
    reservation.hyperswines = true;
  if (this->game().rule()(Rule::SWINES)
      && (this->hand().numberoftrumpaces() == 2))
    reservation.swines = true;

  if (this->hand().numberofclubqueens() == 2) {
    reservation.game_type = GAMETYPE::MARRIAGE;
    reservation.marriage_selector = MARRIAGE_SELECTOR::FIRST_FOREIGN;
  } // if (marriage)

  if (this->game().rule()(Rule::POVERTY)
      && !this->game().rule()(Rule::POVERTY_SHIFT)
      && (this->hand().numberoftrumps() <= Rule::MAX_NUMBER_OF_POVERTY_TRUMPS))
    reservation.game_type = GAMETYPE::POVERTY;

  if (this->game().rule()(Rule::THROW_WITH_FIVE_NINES)
      && (this->hand().numberofnines() >= Rule::MIN_NUMBER_OF_THROWING_NINES))
    reservation.game_type = GAMETYPE::FIVE_NINES;

  return reservation;
} // Reservation AiDummy::reservation_get(bool duty_solo = false)

/**
 ** -> result:
 ** if the dummy ai can get the trick, it takes its best card
 ** (also, if its the first card in the trick)
 ** else (if the dummy ai has no better than the winning card of the trick)
 ** the worst card is taken
 **
 **
 ** @param	-
 **
 ** @return	valid card
 **
 ** @author	Diether Knof
 **
 ** @version	0.5.2
 **
 **/
HandCard
AiDummy::card_get()
{
  // the first card -- play the highest
  // if the ai cannot get the trick: play the lowest
  // if the ai can get the trick: play the highest

  HandCard card;
  bool can_win = false;

  for (vector<HandCard>::const_iterator c = this->hand().cards().begin();
       c != this->hand().cards().end();
       c++) {
    if (this->game().trick_current().isvalid(*c, this->hand())) {
      if (!card) {
	card = *c;
      } else { // if !(!card)
	bool const is_winnercard
	  = (this->game().trick_current().isempty()
	     ? true
	     : this->game().trick_current().winnercard().less(*c)
	    );
	can_win |= is_winnercard;

	if (this->game().trick_current().isempty()) {
	  // take the smallest card
	  if (card.less(*c))
	    card = *c;
	} else if (this->game().trick_current().islastcard()) {
	  // if the player can win the trick take the smallest winnercard,
	  // else take the smallest card.

	  if (can_win
	      && is_winnercard
	      && c->less(card))
	    card = *c;
	  if (!can_win
	      && !is_winnercard
	      && c->less(card))
	    card = *c;
	} else { // if !(is first or last card in trick)
	  // if the player can win the trick take the greatest winnercard,
	  // else take the smallest card.

	  if (can_win
	      && is_winnercard
	      && card.less(*c))
	    card = *c;
	  if (!can_win
	      && !is_winnercard
	      && c->less(card))
	    card = *c;
	} // if !(is first or last card in trick)
      } // if !(!card)
    } // if (this->game().trick_current().isvalid(*c, this->hand()))
  } // for (c \in this->hand().cardsnumber())

  // valid_cards.card(RAND(valid_cards.cardsnumber()))
  return card;
} // HandCard AiDummy::card_get()

/**
 ** -> result
 **
 ** @param	-
 **
 ** @return	announcement of the player
 **
 ** @author	Diether Knof
 **
 ** @version	0.5.4
 **
 **/
Announcement
AiDummy::announcement_request() const
{
  // points of the own team
  unsigned points = 0;

  // count the points, the own team has made 
  for(vector<Player*>::const_iterator player = this->game().players_begin();
      player != this->game().players_end();
      player++)
    if (this->game().teaminfo(**player) == this->team())
      points += this->game().points_of_player(**player);

  if (points == 240)
    return ANNOUNCEMENT::NO0;
  if (points > 240 - 30)
    return ANNOUNCEMENT::NO30;
  if (points > 240 - 60)
    return ANNOUNCEMENT::NO60;
  if (points > 240 - 90)
    return ANNOUNCEMENT::NO90;
  if (points > 240 - 120)
    return ANNOUNCEMENT::NO120;

  return ANNOUNCEMENT::NOANNOUNCEMENT;
} // Announcement AiDummy::announcement_request() const
