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

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

Card const Card::CLUB_QUEEN(Card::CLUB, Card::QUEEN);
Card const Card::CHARLIE(Card::CLUB, Card::JACK);
Card const Card::DOLLE(Card::HEART, Card::TEN);


/**
 **
 ** -> result
 **
 ** @param	-
 **
 ** @return	true if card is trump
 **
 ** @version	0.5.4
 **
 ** @author	Borg Enders
 ** @author	Diether Knof
 **
 ** @bug	not independent of the game
 **
 **/
bool
Card::istrump() const
{
  DEBUG_CALLING(INFO_CARD && INFO_VALUE,
	       	"Card::istrump()");

  DEBUG_RETURNING(this->istrump(::party.game().type()),
		  INFO_CARD && INFO_VALUE,
		  "Card::istrump()");
}

/**
 **
 ** -> result
 **
 ** @param	gametype	the gametype
 **
 ** @return	true if card is trump in a game of type 'gametype'
 **
 ** @version	0.5.4
 **
 ** @author	Borg Enders
 ** @author	Diether Knof
 **
 **/
bool
Card::istrump(GameType const gametype) const
{
  DEBUG_CALLING(INFO_CARD && INFO_VALUE,
		"Card::istrump(gametype)");

  if (this->isdolle())
    DEBUG_RETURNING(true,
		    INFO_CARD && INFO_VALUE,
		    "Card::istrump(gametype)");

  switch(gametype) {
  case GAMETYPE::FIVE_NINES:
    if (this->value() == NINE)
      DEBUG_RETURNING(true,
		      INFO_CARD && INFO_VALUE,
		      "Card::istrump(gametype)");
    break;
  case GAMETYPE::SIX_KINGS:
    if (this->value() == KING)
      DEBUG_RETURNING(true,
		      INFO_CARD && INFO_VALUE,
		      "Card::istrump(gametype)");
    break;
  case GAMETYPE::NORMAL:
  case GAMETYPE::POVERTY:
  case GAMETYPE::FOX_HIGHEST_TRUMP:
  case GAMETYPE::GENSCHER:
  case GAMETYPE::MARRIAGE:
  case GAMETYPE::MARRIAGE_SOLO:
  case GAMETYPE::MARRIAGE_SILENT:
  case GAMETYPE::SOLO_DIAMOND:
    if (this->color() == DIAMOND)
      DEBUG_RETURNING(true,
		      INFO_CARD && INFO_VALUE,
		      "Card::istrump(gametype)");
    if ((this->value() == JACK) || (this->value() == QUEEN))
      DEBUG_RETURNING(true,
		      INFO_CARD && INFO_VALUE,
		      "Card::istrump(gametype)");
    break;
  case GAMETYPE::SOLO_JACK:
    if (this->value() == JACK)
      DEBUG_RETURNING(true,
		      INFO_CARD && INFO_VALUE,
		      "Card::istrump(gametype)");
    break;
  case GAMETYPE::SOLO_QUEEN:
    if (this->value() == QUEEN)
      DEBUG_RETURNING(true,
		      INFO_CARD && INFO_VALUE,
		      "Card::istrump(gametype)");
    break;
  case GAMETYPE::SOLO_KING:
    if (this->value() == KING)
      DEBUG_RETURNING(true,
		      INFO_CARD && INFO_VALUE,
		      "Card::istrump(gametype)");
    break;
  case GAMETYPE::SOLO_QUEEN_JACK:
    if ((this->value() == JACK) || (this->value() == QUEEN))
      DEBUG_RETURNING(true,
		      INFO_CARD && INFO_VALUE,
		      "Card::istrump(gametype)");
    break;
  case GAMETYPE::SOLO_KING_JACK:
    if ((this->value() == JACK) || (this->value() == KING))
      DEBUG_RETURNING(true,
		      INFO_CARD && INFO_VALUE,
		      "Card::istrump(gametype)");
    break;
  case GAMETYPE::SOLO_KING_QUEEN:
    if ((this->value() == QUEEN) || (this->value() == KING))
      DEBUG_RETURNING(true,
		      INFO_CARD && INFO_VALUE,
		      "Card::istrump(gametype)");
    break;
  case GAMETYPE::SOLO_KOEHLER:
    if ((this->value() == JACK) || (this->value() == QUEEN) || (this->value() == KING))
      DEBUG_RETURNING(true,
		      INFO_CARD && INFO_VALUE,
		      "Card::istrump(gametype)");
    break;
  case GAMETYPE::SOLO_CLUB:
    if (this->color() == CLUB)
      DEBUG_RETURNING(true,
		      INFO_CARD && INFO_VALUE,
		      "Card::istrump(gametype)");
    if ((this->value() == JACK)
	|| (this->value() == QUEEN))
      DEBUG_RETURNING(true,
		      INFO_CARD && INFO_VALUE,
		      "Card::istrump(gametype)");
    break;
  case GAMETYPE::SOLO_HEART:
    if (this->color() == HEART)
      DEBUG_RETURNING(true,
		      INFO_CARD && INFO_VALUE,
		      "Card::istrump(gametype)");
    if ((this->value() == JACK)
	|| (this->value() == QUEEN))
      DEBUG_RETURNING(true,
		      INFO_CARD && INFO_VALUE,
		      "Card::istrump(gametype)");
    break;
  case GAMETYPE::SOLO_SPADE:
    if (this->color() == SPADE)
      DEBUG_RETURNING(true,
		      INFO_CARD && INFO_VALUE,
		      "Card::istrump(gametype)");
    if ((this->value() == JACK)
	|| (this->value() == QUEEN))
      DEBUG_RETURNING(true,
		      INFO_CARD && INFO_VALUE,
		      "Card::istrump(gametype)");
    break;
  case GAMETYPE::SOLO_MEATLESS:
    break;
  } // switch(gametype)

  DEBUG_RETURNING(false,
		  INFO_CARD && INFO_VALUE,
		  "Card::istrump(gametype)");
} // bool Card::istrump(GameType const gametype) const

/**
 **
 ** -> result
 **
 ** @param	-
 **
 ** @return	true if card is a dolle
 **
 ** @version	0.5.4
 **
 ** @author	Borg Enders
 ** @author	Diether Knof
 **
 ** @bug	not independent of the game
 **
 **/
bool
Card::isdolle() const
{
  DEBUG_CALLING(INFO_CARD && INFO_VALUE,
		"Card::isdolle()");

  if (!::party.rule()(Rule::DOLLEN))
    DEBUG_RETURNING(false,
		    INFO_CARD && INFO_VALUE,
		    "Card::isdolle()");

  if (*this != Card::DOLLE)
    DEBUG_RETURNING(false,
		    INFO_CARD && INFO_VALUE,
		    "Card::isdolle()");

  bool value = false;

  switch (::party.game().type()) {
  case GAMETYPE::NORMAL:
  case GAMETYPE::POVERTY:
  case GAMETYPE::GENSCHER:
  case GAMETYPE::MARRIAGE:
  case GAMETYPE::MARRIAGE_SOLO:
  case GAMETYPE::MARRIAGE_SILENT:
  case GAMETYPE::SOLO_CLUB:
  case GAMETYPE::SOLO_HEART:
  case GAMETYPE::SOLO_SPADE:
  case GAMETYPE::SOLO_DIAMOND:
    value = true;
    break;
  case GAMETYPE::SIX_KINGS:
  case GAMETYPE::FOX_HIGHEST_TRUMP:
  case GAMETYPE::SOLO_MEATLESS:
  case GAMETYPE::SOLO_JACK:
  case GAMETYPE::SOLO_QUEEN:
  case GAMETYPE::SOLO_KING:
  case GAMETYPE::SOLO_QUEEN_JACK:
  case GAMETYPE::SOLO_KING_JACK:
  case GAMETYPE::SOLO_KING_QUEEN:
  case GAMETYPE::SOLO_KOEHLER:
  case GAMETYPE::FIVE_NINES:
    value = false;
    break;
  } // switch (::party.game().type())

  DEBUG_RETURNING(value,
		  INFO_CARD && INFO_VALUE,
		  "Card::isdolle()");
} // bool Card::isdolle() const

/**
 **
 ** -> result
 **
 ** @param	-
 **
 ** @return	true if card is a swine
 **
 ** @version	0.5.4
 **
 ** @author	Borg Enders
 ** @author	Diether Knof
 **
 ** @bug	not independent of the game (particularly 'first_fox_catcher()'
 **
 **/
bool
Card::isswine() const
{
  DEBUG_CALLING(INFO_CARD && INFO_VALUE,
		"Card::isswine()");

  if (this->istrumpace()
      && ((::party.game().swines_valid()) 
	  || ((::party.game().swines_owner())
	      && !(::party.game().rule()(Rule::SWINE_ONLY_SECOND))
	     )
	  || ((::party.game().swines_owner())
	      && ::party.game().first_fox_catcher()
	      && (::party.game().swines_owner()
		  ->teaminfo(*(::party.game().first_fox_catcher()))
		  == ::party.game().swines_owner()->team())

	     )
	 )
     ) {
    DEBUG_RETURNING(true,
		    INFO_CARD && INFO_VALUE,
		    "Card::isswine()");
  }

  DEBUG_RETURNING(false,
		  INFO_CARD && INFO_VALUE,
		  "Card::isswine()");
} // bool Card::isswine()

/**
 **
 ** -> result
 **
 ** @param	-
 **
 ** @return	true if card is a hyperswine
 **
 ** @version	0.5.4
 **
 ** @author	Borg Enders
 ** @author	Diether Knof
 **
 ** @bug	not independent of the game
 **
 **/
bool
Card::ishyperswine() const
{
  DEBUG_CALLING(INFO_CARD && INFO_VALUE,
		"Card::ishyperswine()");

  if (this->istrumpnine()
      && (::party.game().hyperswines_valid()
	  || (::party.game().hyperswines_valid()
	      && ::party.game().hyperswines_owner())
	 )) {
    DEBUG_RETURNING(true,
		    INFO_CARD && INFO_VALUE,
		    "Card::ishyperswine()");
  }

  DEBUG_RETURNING(false,
		  INFO_CARD && INFO_VALUE,
		  "Card::ishyperswine()");
} // bool Card::ishyperswine()

/**
 **
 ** -> result
 **
 ** @param	-
 **
 ** @return	true if card is a fox
 **
 ** @version	0.5.4
 **
 ** @author	Diether Knof
 ** @author	Borg Enders
 **
 **/
bool
Card::isfox() const
{
  DEBUG_CALLING(INFO_CARD && INFO_VALUE,
		"Card::isfox()");

  DEBUG_RETURNING(GAMETYPE::is_normal(::party.game().type())
		  && this->istrumpace()
		  && !this->isswine(),
		  INFO_CARD && INFO_VALUE,
		  "Card::isfox()");
} // bool Card::isfox()

/**
 **
 ** -> result
 **
 ** @param	-
 **
 ** @return	true if card is a trump ace
 **
 ** @version	0.5.4
 **
 ** @author	Diether Knof
 ** @author	Borg Enders
 **
 **/
bool
Card::istrumpace() const
{
  DEBUG_CALLING(INFO_CARD && INFO_VALUE,
		"Card::istrumpace()");

  DEBUG_RETURNING((this->istrump()
		   && (this->value() == ACE)),
		  INFO_CARD && INFO_VALUE,
		  "Card::istrumpace()");
} // bool Card::istrumpace()

/**
 **
 ** -> result
 **
 ** @param	-
 **
 ** @return	true if card is a trump nine
 **
 ** @version	0.5.4
 **
 ** @author	Diether Knof
 ** @author	Borg Enders
 **
 **/
bool
Card::istrumpnine() const
{
  DEBUG_CALLING(INFO_CARD && INFO_VALUE,
		"Card::istrumpnine()");

  DEBUG_RETURNING((this->istrump()
		   && (this->value() == NINE)),
		  INFO_CARD && INFO_VALUE,
		  "Card::istrumpnine()");
} // bool Card::istrumpnine()

/**
 **
 ** -> result
 **
 ** @param	-
 **
 ** @return	true if card is a trump king
 **
 ** @version	0.5.4
 **
 ** @author	Diether Knof
 **
 **/
bool
Card::istrumpking() const
{
  DEBUG_CALLING(INFO_CARD && INFO_VALUE,
		"Card::istrumpking()");

  DEBUG_RETURNING((this->istrump()
		   && this->value() == KING),
		  INFO_CARD && INFO_VALUE,
		  "Card::istrumpking()");
} // bool Card::istrumpking() const
