/**********************************************************************
 *
 *   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 "game.h"

#include "../player/player.h"
#include "../party/party.h"
#include "../party/rule.h"
#include "../ui/ui.h"

/**
 **
 ** -> result
 **
 ** @param	-
 **
 ** @return	the player who has swines
 **		NULL, if no player has swines	
 **
 ** @version	0.4.5
 **
 ** @author	Borg Enders
 ** @author	Diether Knof
 **
 **/
Player const*
Game::swines_owner() const
{
  DEBUG_CALLING(INFO_GAME && INFO_VALUE,
		"Game::swines_owner()"); 

  DEBUG_RETURNING(this->swines_owner_p,
		  INFO_GAME && INFO_VALUE,
		  "Game::swines_owner()");    
} // Player const* Game::swines_owner() const

/**
 **
 ** -> result
 **
 ** @param	-
 **
 ** @return	the player who has caught the first fox
 **		NULL, if none has done
 **
 ** @version	0.4.5
 **
 ** @author	Borg Enders
 ** @author	Diether Knof
 **
 **/
Player const*
Game::first_fox_catcher() const
{
  DEBUG_CALLING(INFO_GAME && INFO_VALUE,
		"Game::first_fox_catcher()"); 

  DEBUG_RETURNING(this->first_fox_catcher_p,
		  INFO_GAME && INFO_VALUE,
		  "Game::first_fox_catcher()");    
} // Player const* Game::first_fox_catcher() const

/**
 **
 ** -> result
 ** false, if no player has swines
 ** true, if Rule::SWINE_ONLY_SECOND if first fox is won by own team
 ** true, else if both fox are swines
 **
 ** @param	-
 **
 ** @return	whether the swines are valid
 **
 ** @version	0.4.5
 **
 ** @author	Borg Enders
 ** @author	Diether Knof
 **
 **/
bool
Game::swines_valid() const
{
  DEBUG_CALLING(INFO_GAME && INFO_VALUE,
		"Game::swines_valid()"); 

  if (this->swines_owner() == NULL)
    DEBUG_RETURNING(false,
		    INFO_GAME && INFO_GAMEPLAY,
		    "Game::swine_valid() = false");

  if (this->rule()(Rule::SWINE_ONLY_SECOND)) {
    // the fox must have been caught by the own team and the team of the
    // swines owner and of the catcher must be known to all.
    if (this->first_fox_catcher() 
	&& (this->first_fox_catcher()->team()
	    == this->swines_owner()->team())
	&& ((this->teaminfo(*(this->swines_owner())) == TEAM::RE)
	    || (this->teaminfo(*(this->swines_owner())) == TEAM::CONTRA))
	&& ((this->teaminfo(*(this->first_fox_catcher())) == TEAM::RE)
	    || (this->teaminfo(*(this->first_fox_catcher())) == TEAM::CONTRA))
       )
      DEBUG_RETURNING(true,
		      INFO_GAME && INFO_GAMEPLAY,
		      "Game::swine_valid() = true");
    else
      DEBUG_RETURNING(false,
		      INFO_GAME && INFO_GAMEPLAY,
		      "Game::swine_valid() = false");
  } // if (this->rule()(Rule::SWINE_ONLY_SECOND))


  DEBUG_RETURNING(true,
		  INFO_GAME && INFO_VALUE,
		  "Game::swine_valid()");
} // bool Game::swines_valid() const

/**
 **
 ** announce swines if they can be announced and they have not yet been
 ** announced
 **
 ** @param	-
 **
 ** @return	whether the swines are announced
 **
 ** @version	0.5.4
 **
 ** @author	Diether Knof
 **
 **/
bool
Game::swines_announce()
{
  DEBUG_CALLING(INFO_GAME && INFO_GAMEPLAY,
		"Game::swines_announce()"); 

#ifndef POSTPHONED
#ifndef POSTPHONED
  if (this->isvirtual()
      && this->swines_announced())
    return false;
#endif
  DEBUG_ASSERTION(!this->swines_announced(),
		  "Game::swines_announce():\n"
		  "  swines have already been announced.\n"
		  "  virtual = " << (this->isvirtual() ? "true" : "false"));
#endif

  if (this->swines_announced())
    DEBUG_RETURNING(false,
		    INFO_GAME && INFO_GAMEPLAY,
		    "Game::swines_announce() = false");

  // The following says, that the player can only announce swines,
  // when he has both trump aces still on his hand.
  if (!this->swines_owner()
      || (this->swines_owner()->hand().numberoftrumpaces()
	  != this->rule()(Rule::NUMBER_OF_SAME_CARDS)))
    DEBUG_RETURNING(false,
		    INFO_GAME && INFO_GAMEPLAY,
		    "Game::swines_announce() = false");

  if (this->rule()(Rule::SWINES_ANNOUNCEMENT_BEGIN)
      && (::game_status >= GAMESTATUS::GAME_PLAY))
    DEBUG_RETURNING(false,
		    INFO_GAME && INFO_GAMEPLAY,
		    "Game::swines_announce() = false");

  this->swines_announced_p = true;

  this->swines_owner_p->hand_sort();
  if (!this->isvirtual())
    ::ui->swines_announced(*(this->swines_owner()));

  DEBUG_RETURNING(true,
		  INFO_GAME && INFO_GAMEPLAY,
		  "Game::swines_announce() = true");
} // bool Game::swines_announce()

/**
 **
 ** -> result
 **
 ** @param	-
 **
 ** @return	whether the swines have been announced
 **
 ** @version	0.5.4
 **
 ** @author	Diether Knof
 **
 **/
bool
Game::swines_announced() const
{
  DEBUG_CALLING(INFO_GAME && INFO_VALUE,
		"Game::swines_announced()"); 

  DEBUG_RETURNING(this->swines_announced_p,
		  INFO_GAME && INFO_VALUE,
		  "Game::swines_announced()"); 
} // bool Game::swines_announced() const

/**
 **
 ** -> result
 **
 ** @param	-
 **
 ** @return	the player who has hyperswines
 **		NULL, if no player has hyperswines	
 **
 ** @version	0.4.5
 **
 ** @author	Borg Enders
 ** @author	Diether Knof
 **
 **/
Player const*
Game::hyperswines_owner() const
{
  DEBUG_CALLING(INFO_GAME && INFO_VALUE,
		"Game::hyperswines_owner()"); 

  DEBUG_RETURNING(this->hyperswines_owner_p,
		  INFO_GAME && INFO_VALUE,
		  "Game::hyperswines_owner()");    
} // Player const* Game::hyperswines_owner() const

/**
 **
 ** -> result
 ** false, if no player has swines
 ** true, else
 **
 ** @param	-
 **
 ** @return	whether the hyperswines are valid
 **
 ** @version	0.4.5
 **
 ** @author	Borg Enders
 ** @author	Diether Knof
 **
 **/
bool
Game::hyperswines_valid() const
{
  DEBUG_CALLING(INFO_GAME && INFO_VALUE,
		"Game::hyperswines_valid()"); 

  if (!this->swines_valid()
      || !this->swines_announced())
    DEBUG_RETURNING(false,
		    INFO_GAME && INFO_VALUE,
		    "Game::hyperswine_valid()");

  if (this->hyperswines_owner() == NULL)
    DEBUG_RETURNING(false,
		    INFO_GAME && INFO_VALUE,
		    "Game::hyperswine_valid()");

  DEBUG_RETURNING(true,
		  INFO_GAME && INFO_VALUE,
		  "Game::hyperswine_valid()");
} // bool Game::hyperswines_valid() const

/**
 **
 ** announce hyperswines if they can be announced and they have not yet been
 ** announced
 **
 ** @param	-
 **
 ** @return	whether the hyperswines are announced
 **
 ** @version	0.5.4
 **
 ** @author	Diether Knof
 **
 **/
bool
Game::hyperswines_announce()
{
  DEBUG_CALLING(INFO_GAME && INFO_GAMEPLAY,
		"Game::hyperswines_announce()"); 

#ifndef POSTPHONED
#ifndef POSTPHONED
  if (this->isvirtual()
      && this->swines_announced())
    return false;
#endif
  if (this->hyperswines_announced())
    DEBUG_RETURNING(false,
		    INFO_GAME && INFO_GAMEPLAY,
		    "Game::hyperswines_announce() = false");
#endif

  if (!this->hyperswines_valid())
    DEBUG_RETURNING(false,
		    INFO_GAME && INFO_GAMEPLAY,
		    "Game::hyperswines_announce() = false");

  if (!this->swines_announced())
    DEBUG_RETURNING(false,
		    INFO_GAME && INFO_GAMEPLAY,
		    "Game::hyperswines_announce() = false");

  if (this->rule()(Rule::HYPERSWINES_ANNOUNCEMENT_BEGIN)
      && (::game_status >= GAMESTATUS::GAME_PLAY))
    DEBUG_RETURNING(false,
		    INFO_GAME && INFO_GAMEPLAY,
		    "Game::hyperswines_announce() = false");

  this->hyperswines_announced_p = true;

  this->hyperswines_owner_p->hand_sort();
  if (this == &(::party.game()))
    ::ui->hyperswines_announced(*(this->hyperswines_owner()));


  DEBUG_RETURNING(false,
		  INFO_GAME && INFO_GAMEPLAY,
		  "Game::hyperswines_announce() = true"); 
} // bool Game::hyperswines_announce()

/**
 **
 ** -> result
 **
 ** @param	-
 **
 ** @return	whether the hyperswines have been announced
 **
 ** @version	0.5.4
 **
 ** @author	Diether Knof
 **
 **/
bool
Game::hyperswines_announced() const
{
  DEBUG_CALLING(INFO_GAME && INFO_VALUE,
		"Game::hyperswines_announced()"); 

  DEBUG_RETURNING(this->hyperswines_announced_p,
		  INFO_GAME && INFO_VALUE,
		  "Game::hyperswines_announced()"); 
} // bool Game::hyperswines_announced() const
