/**********************************************************************
 *
 *   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 "gameplay.h"
#include "gameplay_actions.h"

#include "game.h"
#include "../card/trick.h"
#include "../card/hand.h"
#include "../player/player.h"

/**
 **
 ** constructor
 **
 ** @param	-
 **
 ** @return	-
 ** 
 ** @version	0.6.8
 **
 ** @author	Diether Knof
 **
 **/
Gameplay::Gameplay() :
  OS(OS_TYPE::GAMEPLAY),
  seed_(UINT_MAX),
  gametype_(),
  soloplayer_(UINT_MAX),
  actions_()
{
  return ;
} // Gameplay::Gameplay()

/**
 **
 ** destructor
 **
 ** @param	-
 **
 ** @return	-
 ** 
 ** @version	0.7.1
 **
 ** @author	Diether Knof
 **
 **/
Gameplay::~Gameplay()
{
  for (list<GameplayAction*>::iterator a = this->actions_.begin();
       a != this->actions_.end();
       ++a)
    delete *a;
  return ;
} // Gameplay::~Gameplay()

/**
 **
 ** writes the gameplay in the output stream
 **
 ** @param	ostr		output stream
 **
 ** @return	output stream
 ** 
 ** @version	0.6.8
 **
 ** @author	Diether Knof
 **
 **/
ostream&
Gameplay::write(ostream& ostr) const
{
  ostr
    << "seed = " << this->seed() << '\n'
    << "gametype = " << this->gametype() << '\n'
    << "soloplayer = " << this->soloplayer() << '\n';

  ostr
    << "hands\n"
    << "{\n";
  for (vector<Hand>::const_iterator h = this->hands().begin();
       h != this->hands().end();
       ++h)
    ostr
      << "{\n"
      << *h
      << "}\n";
  ostr << "}\n";

  ostr
    << "actions\n"
    << "{\n";
  for (list<GameplayAction*>::const_iterator a = this->actions().begin();
       a != this->actions().end();
       ++a)
    ostr << "  " << **a << '\n';
  ostr << "}\n";

  return ostr;
} // ostream& Gameplay::write(ostream& ostr) const

/**
 **
 ** the game is opened
 **
 ** @param	game	game that is opened
 **
 ** @return	-
 ** 
 ** @version	0.6.8
 **
 ** @author	Diether Knof
 **
 **/
void
Gameplay::game_open(Game const& game)
{
  this->OS::game_open(game);

  for (list<GameplayAction*>::iterator a = this->actions_.begin();
       a != this->actions_.end();
       ++a)
    delete *a;
  this->actions_.clear();

  return ;
} // void Gameplay::game_open(Game const& game)

/**
 **
 ** the cards are distributed
 **
 ** @param	-
 **
 ** @return	-
 ** 
 ** @version	0.6.8
 **
 ** @author	Diether Knof
 **
 **/
void
Gameplay::game_cards_distributed()
{
  this->seed_ = this->game().seed();

  this->hands_.clear();
  for (unsigned p = 0; p < this->game().playerno(); ++p)
    this->hands_.push_back(this->game().player(p).hand());

  return ;
} // void Gameplay::game_cards_distributed()

/**
 **
 ** the game is redistributed
 **
 ** @param	-
 **
 ** @return	-
 ** 
 ** @version	0.6.8
 **
 ** @author	Diether Knof
 **
 **/
void
Gameplay::game_redistribute()
{
  for (list<GameplayAction*>::iterator a = this->actions_.begin();
       a != this->actions_.end();
       ++a)
    delete *a;
  this->actions_.clear();

  return ;
} // void Gameplay::game_redistribute()

/**
 **
 ** the game is started
 **
 ** @param	-
 **
 ** @return	-
 ** 
 ** @version	0.6.8
 **
 ** @author	Diether Knof
 **
 **/
void
Gameplay::game_start()
{
  this->gametype_ = this->game().type();

  if (is_solo(this->gametype()))
    this->soloplayer_ = this->game().soloplayer().no();
  else
    this->soloplayer_ = UINT_MAX;

  return ;
} // void Gameplay::game_start()

/**
 **
 ** the game is closed
 **
 ** @param	-
 **
 ** @return	-
 ** 
 ** @version	0.6.8
 **
 ** @author	Diether Knof
 **
 **/
void
Gameplay::game_close()
{
  this->OS::game_close();

  return ;
} // void Gameplay::game_close()

/**
 **
 ** 'player' has played 'card'
 **
 ** @param	card	the played card
 **
 ** @return	-
 ** 
 ** @version	0.6.8
 **
 ** @author	Diether Knof
 **
 **/
void
Gameplay::card_played(HandCard const& card)
{ 
  this->actions_.push_back(new GameplayAction::CardPlayed(card.player().no(),
							  card));

  return ;
} // void Gameplay::card_played(HandCard card)

/**
 **
 ** the announcement 'announcement' has been made by player 'player'
 **
 ** @param	announcement	the announcement
 ** @param	player		the player, who has made the announcement
 **
 ** @return	-
 **
 ** @version	0.6.8
 **
 ** @author	Diether Knof
 **
 **/
void
Gameplay::announcement_made(Announcement const& announcement,
			    Player const& player)
{
  this->actions_.push_back(new GameplayAction::Announcement(player.no(),
							    announcement));

  return ;
} // void Gameplay::announcement_made(Announcement announcement, Player player)

/**
 **
 ** the player has swines
 **
 ** @param	player		the player with the swines
 **
 ** @return	-
 **
 ** @version	0.6.8
 **
 ** @author	Diether Knof
 **
 **/
void
Gameplay::swines_announced(Player const& player)
{
  this->actions_.push_back(new GameplayAction::Swines(player.no()));

  return ;
} // void Gameplay::swines_announced(Player player)

/**
 **
 ** the player has hyperswines
 **
 ** @param	player		the player with the swines
 **
 ** @return	-
 **
 ** @version	0.6.8
 **
 ** @author	Diether Knof
 **
 **/
void
Gameplay::hyperswines_announced(Player const& player)
{
  this->actions_.push_back(new GameplayAction::Hyperswines(player.no()));

  return ;
} // void Gameplay::hyperswines_announced(Player player)

/**
 **
 ** 'player' shifts 'cardno' cards
 **
 ** @param	player	the player who shifts the cards
 ** @param	cardno	the number of cards that are shifted
 **
 ** @return	-
 **
 ** @version	0.6.8
 **
 ** @author	Diether Knof
 **
 **/
void
Gameplay::poverty_shift(Player const& player, unsigned const cardno)
{ 
  this->actions_.push_back(new GameplayAction::PovertyShift(player.no(),
							    static_cast<vector<Card> >(*this->game().poverty_cards())));

  return ;
} // void Gameplay::poverty_shift(Player player, unsigned cardno)

/**
 **
 ** 'player' accepts to take the shifted cards
 ** and returns 'cardno' cards with 'trumpno' trumps
 **
 ** @param	player	the player who has denied to take the cards
 ** @param	cardno	number of cards that are given back
 ** @param	trumpno	number of trumps of the cards
 **
 ** @return	-
 **
 ** @version	0.6.8
 **
 ** @author	Diether Knof
 **
 **/
void
Gameplay::poverty_take_accepted(Player const& player,
				unsigned const cardno,
				unsigned const trumpno)
{ 
  this->actions_.push_back(new GameplayAction::PovertyReturned(player.no(),
							       static_cast<vector<Card> >(*this->game().poverty_cards())));

  return ;
} // void Gameplay::poverty_take_accepted(Player player, unsigned cardno, unsigned trumpno)

/**
 ** the poverty was denied by all players
 **
 ** @param	-
 **
 ** @return	-
 **
 ** @author	Diether Knof
 **
 ** @version	0.7.1
 **/
void
Gameplay::poverty_denied_by_all()
{
  this->actions_.push_back(new GameplayAction::PovertyDeniedByAll());

  return ;
} // void Gameplay::poverty_denied_by_all()

/**
 **
 ** marriage: Information of the new team
 **
 ** @param	bridegroom	the player with the marriage
 ** @param	bride		the bride
 **
 ** @return	-
 **
 ** @author	Diether Knof
 **
 ** @version	0.6.8
 **
 **/
void
Gameplay::marriage(Player const& bridegroom,
		   Player const& bride)
{
  this->actions_.push_back(new GameplayAction::Marriage(bridegroom.no(), bride.no()));

  return ;
} // void Gameplay::marriage(Player bridegroom, Player bride)

/**
 **
 ** genscher: Information of the new team
 **
 ** @param	player	genscher player
 ** @param	partner	partner of the gensher player
 **
 ** @return	-
 **
 ** @author	Diether Knof
 **
 ** @version	0.6.8
 **
 **/
void
Gameplay::genscher(Player const& player,
		   Player const& partner)
{
  this->actions_.push_back(new GameplayAction::Genscher(player.no(),
							partner.no()));

  return ;
} // void Gameplay::genscher(Player player, Player partner)

/**
 **
 ** the trick is closed
 **
 ** @param	-
 **
 ** @return	-
 **
 ** @author	Diether Knof
 **
 ** @version	0.6.8
 **
 **/
void
Gameplay::trick_full()
{
  this->OS::trick_full();

  this->actions_.push_back(new GameplayAction::TrickFull(this->game().trick_current()));

  return ;
} // void Gameplay::trick_full()

/**
 **
 ** writes the gameplay in the output stream
 **
 ** @param	ostr		output stream
 ** @param	gameplay	gameplay
 **
 ** @return	output stream
 ** 
 ** @version	0.6.8
 **
 ** @author	Diether Knof
 **
 **/
ostream&
operator<<(ostream& ostr, Gameplay const& gameplay)
{
  gameplay.write(ostr);

  return ostr;
} // ostream& operator<<(ostream& ostr, Gameplay gameplay)
