/********************************************************************** * * FreeDoko a Doppelkopf-Game * * Copyright (C) 2001-2007 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 "hand_card.h" #include "../game/game.h" #include "../party/rule.h" Card const Card::CLUB_QUEEN(Card::CLUB, Card::QUEEN); Card const Card::FOX(Card::DIAMOND, Card::ACE); Card const Card::DOLLE(Card::HEART, Card::TEN); Card const Card::CHARLIE(Card::CLUB, Card::JACK); // 4 colors * 6 values int const Card::MAX_INT = 4 * 6; /********************************************************************** * ** Card:Card() * ** Parameters: None * ** Result: None * ** Version: Alpha * ** Description: ** initizializing of color NOCARDCOLOR and value NOCARDVALUE * **********************************************************************/ Card::Card() : color_(NOCARDCOLOR), value_(NOCARDVALUE) { } /********************************************************************** * ** Card:Card(Card const& c) * ** Parameters: ** c: Card * ** Result: None * ** Version: Alpha * ** Description: ** initizializing of color and value as c * **********************************************************************/ Card::Card(Card const& c): color_(c.color()), value_(c.value()) { } /********************************************************************** * ** Card:Card(Color c, Value v) * ** Parameters: ** c: Color of to be created Card ** v: Value of to be created Card * ** Result: None * ** Version: Alpha * ** Description: ** initizializing of color with c and of value with v * **********************************************************************/ Card::Card(Color const c, Value const v): color_(c), value_(v) { DEBUG_CALLING(INFO_CARD && INFO_INIT,"Card::Card(c,v)"); if ((color() == NOCARDCOLOR) || (value() == NOCARDVALUE)) color_ = NOCARDCOLOR, value_ = NOCARDVALUE; DEBUG_RETURNING_N(INFO_CARD && INFO_INIT,"Card::Card(c,v)"); } #ifdef OUTDATED /********************************************************************** * ** Card:Card(unsigned const color_u, unsigned const value_u) * ** Parameters: color_u - number of the color * value_u - number of the value * ** Result: - * ** Version: 0.4.2 * ** Description: constructor * **********************************************************************/ Card::Card(unsigned const color_u, unsigned const value_u) : color_(NOCARDCOLOR), value_(NOCARDVALUE) { DEBUG_CALLING(INFO_CARD && INFO_INIT,"Card::Card(c,v)"); switch(color_u) { case 0: this->color_ = DIAMOND; break; case 1: this->color_ = HEART; break; case 2: this->color_ = SPADE; break; case 3: this->color_ = CLUB; break; default: DEBUG_ASSERTION(false, "Card::Card(unsigned color_u, unsigned value_u):\n" " invalid 'color_u'"); break; } // switch(color_u) switch(value_u) { case 0: this->value_ = NINE; break; case 1: this->value_ = JACK; break; case 2: this->value_ = QUEEN; break; case 3: this->value_ = KING; break; case 4: this->value_ = TEN; break; case 5: this->value_ = ACE; break; default: DEBUG_ASSERTION(false, "Card::Card(unsigned color_u, unsigned value_u):\n" " invalid 'value_u'"); break; } // switch(value_u) if ((color() == NOCARDCOLOR) || (value() == NOCARDVALUE)) { color_ = NOCARDCOLOR; value_ = NOCARDVALUE; } DEBUG_RETURNING(VOID, INFO_CARD && INFO_INIT, "Card::Card(c,v)"); } // Card::Card(unsigned const color_u, unsigned const value_u) #endif /** ** ** Konstruktor: ** reads 'color' and 'value' from 'name' ** ** @param name the card name ** ** @return - ** ** @version 0.5.2 ** ** @author Diether Knof ** **/ Card::Card(string const& name) : color_(NOCARDCOLOR), value_(NOCARDVALUE) { DEBUG_CALLING(INFO_CARD && INFO_VALUE, "Card::Card(name)"); istringstream istr(name); istr >> *this; DEBUG_RETURNING(VOID, INFO_CARD && INFO_VALUE, "Card::Card(name)"); } // Card::Card(string const& name) /********************************************************************** * ** Card::~Card() * ** Parameters: None * ** Result: None * ** Version: Alpha * ** Description: ** Destructor for Card * **********************************************************************/ Card::~Card() { DEBUG_CALLING(INFO_CARD && INFO_INIT,"Card::~Card()"); DEBUG_RETURNING_N(INFO_CARD && INFO_INIT,"Card::~Card()"); } /** ** ** copy operator ** ** @param card card to copy ** ** @return copy of the card ** ** @version 0.5.4 ** ** @author Borg Enders ** @author Diether Knof ** **/ Card& Card::operator=(Card const& card) { DEBUG_CALLING(INFO_CARD && INFO_VALUE, "Card::operator=(Card const& card)"); this->color_ = card.color(); this->value_ = card.value(); DEBUG_RETURNING(*this, INFO_CARD && INFO_VALUE, "Card::operator=(Card const& card)"); } // Card& Card::operator=(Card const& card) /** ** read the card from the stream ** ** @param istr stream to read the card from ** ** @return stream ** ** @author Diether Knof ** ** @version 0.5.4 **/ istream& Card::read(istream& istr) { istr >> this->color_ >> this->value_; return istr; } // istrean& Card::read(istream& istr) /********************************************************************** * ** Card::operator bool() const * ** Parameters: None * ** Result: if the card is a real card * ** Version: Alpha * ** Description: ** * **********************************************************************/ Card::operator bool() const { DEBUG_CALLING(INFO_CARD && INFO_VALUE, "Card::operator bool()"); DEBUG_RETURNING( (color() != NOCARDCOLOR) && (value() != NOCARDVALUE) , INFO_CARD && INFO_VALUE, "Card::operator bool()"); } /** ** -> result ** This value is used to use 'vector<.>' instead of 'map' ** because of performance reasons (~15% better when using in 'CardCounter') ** ** @param - ** ** @return integer value of the card ** ** @author Diether Knof ** ** @version 0.7.4 **/ int Card::to_int() const { if (this->color() == NOCARDCOLOR) return 0; switch (this->value()) { case Card::NOCARDVALUE: return 0; case Card::NINE: return (this->color() * 6 + 1); case Card::JACK: return (this->color() * 6 + 2); case Card::QUEEN: return (this->color() * 6 + 3); case Card::KING: return (this->color() * 6 + 4); case Card::TEN: return (this->color() * 6 + 5); case Card::ACE: return (this->color() * 6 + 6); }; // switch (this->value()) return 0; } // int Card::to_int() const /********************************************************************** * ** unsigned Card::points() const * ** Parameters: - * ** Result: points of card * ** Version: 0.4.2 * ** Description: -> result ** * **********************************************************************/ unsigned Card::points() const { DEBUG_CALLING(INFO_CARD && INFO_VALUE, "Card::points()"); // based on structure of enum type card values // here can value be direct returned DEBUG_RETURNING(value(), INFO_CARD && INFO_VALUE, "Card::points()"); } // unsigned Card::points() const /** ** ** -> result ** ** @param game the game ** ** @return true if card is trump in the game ** ** @version 0.6.8 ** ** @author Diether Knof ** **/ bool Card::istrump(Game const& game) const { return this->istrump(game.type(), game.rule()(Rule::DOLLEN)); } // bool Card::istrump(Game game) const /** ** ** -> result ** ** @param gametype the gametype ** @param dollen whether dollen are allowed ** ** @return true if card is trump in the game ** ** @version 0.5.4 ** ** @author Borg Enders ** @author Diether Knof ** **/ bool Card::istrump(GameType const gametype, bool const dollen) const { if (this->isdolle(gametype, dollen)) return true; switch (gametype) { case GAMETYPE::THROWN_NINES: return (this->value() == NINE); case GAMETYPE::THROWN_KINGS: return (this->value() == KING); case GAMETYPE::THROWN_NINES_AND_KINGS: return ( (this->value() == NINE) || (this->value() == KING) ); 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: return ( (this->color() == DIAMOND) || (this->value() == JACK) || (this->value() == QUEEN) ); case GAMETYPE::SOLO_JACK: return (this->value() == JACK); case GAMETYPE::SOLO_QUEEN: return (this->value() == QUEEN); case GAMETYPE::SOLO_KING: return (this->value() == KING); case GAMETYPE::SOLO_QUEEN_JACK: return ( (this->value() == JACK) || (this->value() == QUEEN) ); break; case GAMETYPE::SOLO_KING_JACK: return ( (this->value() == JACK) || (this->value() == KING) ); case GAMETYPE::SOLO_KING_QUEEN: return ( (this->value() == QUEEN) || (this->value() == KING) ); case GAMETYPE::SOLO_KOEHLER: return ( (this->value() == JACK) || (this->value() == QUEEN) || (this->value() == KING) ); case GAMETYPE::SOLO_CLUB: return ( (this->color() == CLUB) || (this->value() == JACK) || (this->value() == QUEEN) ); case GAMETYPE::SOLO_HEART: return ( (this->color() == HEART) || (this->value() == JACK) || (this->value() == QUEEN) ); case GAMETYPE::SOLO_SPADE: return ( (this->color() == SPADE) || (this->value() == JACK) || (this->value() == QUEEN) ); case GAMETYPE::SOLO_MEATLESS: return false; } // switch(gametype) return false; } // bool Card::istrump(GameType gametype, bool dollen) const /** ** ** -> result ** ** @param game the game ** ** @return true if card is a dolle ** ** @version 0.6.8 ** ** @author Diether Knof ** **/ bool Card::isdolle(Game const& game) const { return this->isdolle(game.type(), game.rule()(Rule::DOLLEN)); } // bool Card::isdolle(Game game) const /** ** ** -> result ** ** @param gametype the gametype ** @param dollen whether dollen are allowed ** ** @return true if card is a dolle ** ** @version 0.6.8 ** ** @author Diether Knof ** **/ bool Card::isdolle(GameType const gametype, bool const dollen) const { if (!dollen) return false; if (*this != Card::DOLLE) return false; switch (gametype) { 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: return true; 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::THROWN_NINES: case GAMETYPE::THROWN_KINGS: case GAMETYPE::THROWN_NINES_AND_KINGS: return false; } // switch (gametype) return false; } // bool Card::isdolle(GameType gametype, bool dollen) const /** ** ** -> result ** ** @note if both cards are equal, the first (this) is not less than ** the second (card) ** (but the dollen -- see rules) ** ** @param card the card to compare with ** ** @return true, if the card is less than 'b', else false ** ** @version 0.6.8 ** ** @author Diether Knof ** **/ bool Card::less(HandCard const& card) const { if (card.possible_hyperswine()) return (*this != card); if (card.possible_swine()) return (*this != card); return card.game().less(*this, card); } // bool HandCard::less(Card card) const /** ** ** -> result ** ** @param a first card ** @param b second card ** ** @result whether the two cards are equal ** ** @author Diether Knof ** ** @version 0.6.8 ** **/ bool operator==(Card const& a, Card const& b) { return ((a.value() == b.value()) && (a.color() == b.color())); } // bool operator==(Card a, Card b) /** ** -> result ** ** @param a first card ** @param b second card ** ** @result whether 'a' is lexicographical smaller than 'b' ** ** @author Diether Knof ** ** @version 0.6.9 **/ bool operator<(Card const& a, Card const& b) { return ((a.color() < b.color()) || ((a.color() == b.color()) && (a.value() < b.value()))); } // bool operator<(Card a, Card b) /** ** -> result ** ** @param tcolor tcolor ** @param marriage_selector marriage selector ** ** @result whether the marriage is determined by a 'tcolor'-trick ** ** @author Diether Knof ** ** @version 0.7.4 **/ bool is_selector(Card::TColor const tcolor, MarriageSelector const marriage_selector) { switch (marriage_selector) { case MARRIAGE_SELECTOR::TEAM_SET: case MARRIAGE_SELECTOR::SILENT: return false; case MARRIAGE_SELECTOR::FIRST_FOREIGN: return true; case MARRIAGE_SELECTOR::FIRST_TRUMP: return (tcolor == Card::TRUMP); case MARRIAGE_SELECTOR::FIRST_COLOR: return (tcolor != Card::TRUMP); case MARRIAGE_SELECTOR::FIRST_CLUB: return (tcolor == Card::CLUB); case MARRIAGE_SELECTOR::FIRST_SPADE: return (tcolor == Card::SPADE); case MARRIAGE_SELECTOR::FIRST_HEART: return (tcolor == Card::HEART); } // switch (marriage_selector) return false; } // bool is_selector(Card::TColor tcolor, MarriageSelector marriage_selector) /********************************************************************** * ** string name(Card const& card) * ** Parameters: card - the card * ** Result: name of the card * ** Version: 0.4.1 * ** Description: -> result * **********************************************************************/ string name(Card const& card) { return (name(card.color()) + " " + name(card.value())); } // string name(Card const& card) /** ** writes the card in the output stream ** ** @param ostr output stream ** @param card card ** ** @return output stream ** ** @author Diether Knof ** ** @version 0.5.4 **/ ostream& operator<<(ostream& ostr, Card const& card) { ostr << name(card); return ostr; } // ostream& operator<<(ostream& ostr, Card const& card); /** ** read the card out of the stream ** ** @param istr input stream ** @param card card ** ** @return output stream ** ** @author Diether Knof ** ** @version 0.5.4 **/ istream& operator>>(istream& istr, Card& card) { card.read(istr); return istr; } // istream& operator>>(istream& istr, Card& card);