/**********************************************************************
 *
 *   FreeDoko a Doppelkopf-Game
 *    
 *   Copyright (C) 2001-2004  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 "human.h"

#include "humanDb.h"
#include "../../ui/ui.h"

/**
 **
 ** Construktor
 **
 ** @param	-
 **
 ** @return	-
 **
 ** @author	Diether Knof
 **
 ** @version	0.4.4
 **
 **/
Human::Human() :
Ai()
{
  DEBUG_CALLING(INFO_HUMAN && INFO_INIT,
		"Human::Human()");

  // *** HACK
  this->type_set(HUMAN);
  this->name_set("");
#ifndef RELEASE
#ifdef BENDERS
  this->db_ = new HumanDb();
#endif
#endif

  DEBUG_RETURNING(VOID,
		  INFO_HUMAN && INFO_INIT,
		  "Human::Human()");
} // Human::Human()

/**
 **
 ** Construktor
 **
 ** @param	istr	stream with the infos
 **
 ** @return	-
 **
 ** @author	Diether Knof
 **
 ** @version	0.5.2
 **
 **/
Human::Human(istream& istr) :
Ai(istr)
{
  DEBUG_CALLING(INFO_HUMAN && INFO_INIT,
		"Human::Human(istr)");

  this->type_set(HUMAN);
  this->name_set("");

  DEBUG_RETURNING(VOID,
		  INFO_HUMAN && INFO_INIT,
		  "Human::Human(istr)");
} // Human::Human(istream& istr)

/**
 **
 ** copy-constructor
 **
 ** @param	player	player to copy
 **
 ** @return	-
 **
 ** @author	Diether Knof
 **
 ** @version	0.5.3
 **
 **/
Human::Human(Player const& player) :
Ai(player)
{
  DEBUG_CALLING(INFO_HUMAN && INFO_INIT,
		"Human::Human(player)");

  this->type_set(HUMAN);

  DEBUG_RETURNING(VOID,
		  INFO_HUMAN && INFO_INIT,
		  "Human::Human(player)");
} // Human::Human(Player const& player)

/**
 **
 ** copy-constructor
 **
 ** @param	human	human to copy
 **
 ** @return	-
 **
 ** @author	Diether Knof
 **
 ** @version	0.5.3
 **
 **/
Human::Human(Human const& human) :
Ai(static_cast<Ai const&>(human))
{
  DEBUG_CALLING(INFO_HUMAN && INFO_INIT,
		"Human::Human(human)");

  this->type_set(HUMAN);

  DEBUG_RETURNING(VOID,
		  INFO_HUMAN && INFO_INIT,
		  "Human::Human(human)");
} // Human::Human(Human const& human)

/**
 **
 ** clone the player
 **
 ** @param       -
 **
 ** @return      pointer of a clone
 **
 ** @author      Diether Knof
 **
 ** @version     0.5.3
 **
 **/
Human*
Human::clone() const
{  
  DEBUG_CALLING(INFO_HUMAN && INFO_INIT,
		"Human::clone()");

  DEBUG_RETURNING(new Human(*this),
		  INFO_HUMAN && INFO_INIT,
		  "Human::clone()");
} // virtual Human* Human::clone() const

/**
 **
 ** Destruktor
 **
 ** @param	-
 **
 ** @param	-
 **
 ** @author	Diether Knof
 **
 ** @version	0.4.4
 **
 **/
Human::~Human()
{
  DEBUG_CALLING(INFO_HUMAN && INFO_INIT,
		"Human::~Human()");

  DEBUG_RETURNING(VOID,
		  INFO_HUMAN && INFO_INIT,
		  "Human::~Human()");
} // Human::~Human()

/**
 **
 ** returns the reservation of the player
 ** (taken from the ui)
 **
 ** @param	is_duty		the player has to play a duty solo
 **				(default: false)
 **
 ** @return	reservation of the player
 **
 ** @author	Diether Knof
 **
 ** @version	0.6.1
 **
 **/
Reservation
Human::reservation_get(bool is_duty)
{ 
  DEBUG_CALLING(INFO_HUMAN && INFO_GAMEPLAY,
		"Human::reservation_get(is_duty)");

  DEBUG_ASSERTION(!this->game().isvirtual(),
		  "Human::reservation_get():\n"
		  "  Game is virtual");

  (void)is_duty;

  DEBUG_RETURNING(::ui->reservation_get(*this),
		  INFO_HUMAN && INFO_GAMEPLAY,
		  "Human::reservation_get(is_duty)");
} // Reservation Human::reservation_get(bool is_duty = false)

/**
 **
 ** returns save announcements
 **
 ** @param	-
 **
 ** @return	safe announcement
 **
 ** @author	Diether Knof
 **
 ** @version	0.5.1
 **
 **/
Announcement
Human::announcement_request() const
{
  DEBUG_CALLING(INFO_HUMAN && INFO_GAMEPLAY,
		"Human::announcement_request()");

#ifdef OUTDATED
  // 2004-05-06 (0.6.4)
  // no automatic announcement

  // points of the own team
  unsigned points = 0;

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

  if (points > 240 - 0)
    DEBUG_RETURNING(ANNOUNCEMENT::NO0,
		    INFO_HUMAN && INFO_GAMEPLAY,
		    "Human::announcement_request()");
  if (points > 240 - 30)
    DEBUG_RETURNING(ANNOUNCEMENT::NO30,
		    INFO_HUMAN && INFO_GAMEPLAY,
		    "Human::announcement_request()");
  if (points > 240 - 60)
    DEBUG_RETURNING(ANNOUNCEMENT::NO60,
		    INFO_HUMAN && INFO_GAMEPLAY,
		    "Human::announcement_request()");
  if (points > 240 - 90)
    DEBUG_RETURNING(ANNOUNCEMENT::NO90,
		    INFO_HUMAN && INFO_GAMEPLAY,
		    "Human::announcement_request()");
  if (points > 240 - 120)
    DEBUG_RETURNING(ANNOUNCEMENT::NO120,
		    INFO_HUMAN && INFO_GAMEPLAY,
		    "Human::announcement_request()");
#endif

  DEBUG_RETURNING(ANNOUNCEMENT::NOANNOUNCEMENT,
		  INFO_HUMAN && INFO_GAMEPLAY,
		  "Human::announcement_request()");
} // Announcement Human::announcement_request() const

/**
 **
 ** returns the card played by the human
 **
 ** @param	-
 **
 ** @return	the card choosen by a human player
 **
 ** @author	Diether Knof
 **
 ** @version	0.5.2
 **
 **/
Card
Human::card_get()
{
  DEBUG_CALLING(INFO_HUMAN && INFO_VALUE,
		"Human::card_get()");

#ifndef RELEASE
  // print the suggested card to stdout
  cout << this->Ai::card_get() << " --"
    << " suggested card for human" << endl;
#endif

  DEBUG_ASSERTION(!this->game().isvirtual(),
		  "Human::card_get():\n"
		  "  Game is virtual");

  Card const card = ::ui->card_get(*this);

  if (::game_status != GAMESTATUS::GAME_PLAY)
    DEBUG_RETURNING(Card(),
		    INFO_HUMAN && INFO_VALUE,
		    "Human::card_get()");

  DEBUG_ASSERTION(card,
		  "Human::card_get():\n"
		  "  result of 'ui->card_get()' is an empty card");

  DEBUG_RETURNING(card,
		  INFO_HUMAN && INFO_GAMEPLAY,
		  "Human::card_get()");
} // Card Human::card_get()

/**
 **
 ** returns which cards the player shifts
 **
 ** @param	-
 **
 ** @return	the cards that are to be shifted
 **
 ** @author	Diether Knof
 **
 ** @version	0.4.5
 **
 **/
Hand
Human::poverty_shift()
{ 
  DEBUG_CALLING(INFO_HUMAN && INFO_GAMEPLAY,
		"Human::poverty_shift()");

  DEBUG_RETURNING(::ui->poverty_shift(*this),
		  INFO_HUMAN && INFO_GAMEPLAY,
		  "Human::poverty_shift()");
} // void Human::poverty_shift(Player const& player)

/**
 **
 ** returns whether 'player' accepts the shifted cards
 **
 ** @param	cardno	the number of shifted cards
 **
 ** @return	whether to accept the cards
 **
 ** @author	Diether Knof
 **
 ** @version	0.4.5
 **
 **/
bool
Human::poverty_take_accept(unsigned const cardno)
{ 
  DEBUG_CALLING(INFO_HUMAN && INFO_GAMEPLAY,
		"Human::poverty_take_accept(cardno)");

  DEBUG_RETURNING(::ui->poverty_take_accept(*this, cardno),
		  INFO_HUMAN && INFO_GAMEPLAY,
		  "Human::poverty_take_accept(cardno)");
} // void Human::poverty_take_accept(unsigned const cardno)

/**
 **
 ** changes the cards from the poverty-player
 **
 ** @param	cards	the cards that are given to the player
 **
 ** @return	the cards that are returned to the poverty-player
 **
 ** @author	Diether Knof
 **
 ** @version	0.4.5
 **
 **/
Hand
Human::poverty_cards_change(Hand const& cards)
{ 
  DEBUG_CALLING(INFO_HUMAN && INFO_GAMEPLAY,
		"Human::poverty_cards_change(cards)");

#ifdef WORKAROUND
  // the ai has to update the cards
  Hand const cards_returned = ::ui->poverty_cards_change(*this, cards);
  this->hand_set(this->hand());

  DEBUG_RETURNING(cards_returned,
		  INFO_HUMAN && INFO_GAMEPLAY,
		  "Human::poverty_cards_change(cards)");
#else
  DEBUG_RETURNING(::ui->poverty_cards_change(*this, cards),
		  INFO_HUMAN && INFO_GAMEPLAY,
		  "Human::poverty_cards_change(cards)");
#endif
} // Hand Human::poverty_cards_change(Hand const& cards)

/**
 **
 ** gets the cards from the partner and add them to the hand
 **
 ** @param	cards	the cards that are given to the player
 **
 ** @return	-
 **
 ** @author	Diether Knof
 **
 ** @version	0.5
 **
 **/
void
Human::poverty_cards_get_back(Hand const& cards)
{ 
  DEBUG_CALLING(INFO_HUMAN && INFO_GAMEPLAY,
		"Human::poverty_cards_get_back(cards)");

  ::ui->poverty_cards_get_back(*this, cards);
#ifdef WORKAROUND
  // the ai has to update the cards
  this->hand_set(this->hand());
#endif

  DEBUG_RETURNING(VOID,
		  INFO_HUMAN && INFO_GAMEPLAY,
		  "Human::poverty_cards_get_back(cards)");
} // void Human::poverty_cards_get_back(Hand const& cards)

/**
 **
 ** genscher: -> result
 **
 ** @param	-
 **
 ** @return	pointer to the new teammate,
 **		NULL if the genscher is not to be announced
 **
 ** @author	Diether Knof
 **
 ** @version	0.5.4
 **
 **/
Player const*
Human::genscher_partner()
{ 
  DEBUG_CALLING(INFO_HUMAN && INFO_GAMEPLAY,
		"Human::genscher_partner()");

  DEBUG_RETURNING(::ui->genscher_partner(),
		  INFO_HUMAN && INFO_GAMEPLAY,
		  "Human::genscher_partner()");
} // Player const* Human::genscher_partner()
