/**********************************************************************
 *
 *   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
 **
 **/
AiRandom::AiRandom() :
  Player(Player::AI_RANDOM),
  Aiconfig()
{
  //  this->set_name(::generate_name(RAND(4) + 5));

  return ;
} // AiRandom::AiRandom()

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

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

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

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

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

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

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

  return ;
} // AiRandom::AiRandom(AiRandom const& ai_random)

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

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

  return *this;
} // AiRandom& AiRandom::operator=(AiRandom const& ai_random)

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

/**
 ** -> 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
AiRandom::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 AiRandom::reservation_get(bool const duty_solo)

/**
 ** -> result:
 ** take a random card of all valid ones
 **
 ** @param	-
 **
 ** @return	valid card
 **
 ** @author	Diether Knof
 **
 ** @version	0.6.8
 **
 **/
HandCard
AiRandom::card_get()
{
  HandCard card;
  do
    card = this->hand().card(RAND(this->hand().cardsnumber() - 1));
  while (!this->game().trick_current().isvalid(card));

  return card;
} // HandCard AiRandom::card_get()

/**
 ** -> result
 **
 ** @param	-
 **
 ** @return	announcement of the player
 **
 ** @author	Diether Knof
 **
 ** @version	0.5.4
 **
 **/
Announcement
AiRandom::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 AiRandom::announcement_request() const
