1 /**********************************************************************
2  *
3  *   FreeDoko a Doppelkopf-Game
4  *
5  *   Copyright (C) 2001 – 2018 by Diether Knof and Borg Enders
6  *
7  *   This program is free software; you can redistribute it and/or
8  *   modify it under the terms of the GNU General Public License as
9  *   published by the Free Software Foundation; either version 2 of
10  *   the License, or (at your option) any later version.
11  *
12  *   This program is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *   You can find this license in the file 'gpl.txt'.
17  *
18  *   You should have received a copy of the GNU General Public License
19  *   along with this program; if not, write to the Free Software
20  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  *   MA  02111-1307  USA
22  *
23  *  Contact:
24  *    Diether Knof dknof@posteo.de
25  *
26  *********************************************************************/
27 
28 #include "constants.h"
29 #include "card.h"
30 
31 #include "hand_card.h"
32 #include "../game/game.h"
33 #include "../party/rule.h"
34 
35 Card const Card::empty{};
36 Card const Card::unknown(Card::unknowncardcolor, Card::unknowncardvalue);
37 Card const Card::fox(Card::diamond, Card::ace);
38 Card const Card::dulle(Card::heart, Card::ten);
39 Card const Card::charlie(Card::club, Card::jack);
40 Card const Card::club_ace(Card::club, Card::ace);
41 Card const Card::spade_ace(Card::spade, Card::ace);
42 Card const Card::heart_ace(Card::heart, Card::ace);
43 Card const Card::diamond_ace(Card::diamond, Card::ace);
44 Card const Card::club_ten(Card::club, Card::ten);
45 Card const Card::spade_ten(Card::spade, Card::ten);
46 Card const Card::heart_ten(Card::heart, Card::ten);
47 Card const Card::diamond_ten(Card::diamond, Card::ten);
48 Card const Card::club_king(Card::club, Card::king);
49 Card const Card::spade_king(Card::spade, Card::king);
50 Card const Card::heart_king(Card::heart, Card::king);
51 Card const Card::diamond_king(Card::diamond, Card::king);
52 Card const Card::club_queen(Card::club, Card::queen);
53 Card const Card::spade_queen(Card::spade, Card::queen);
54 Card const Card::heart_queen(Card::heart, Card::queen);
55 Card const Card::diamond_queen(Card::diamond, Card::queen);
56 Card const Card::club_jack(Card::club, Card::jack);
57 Card const Card::spade_jack(Card::spade, Card::jack);
58 Card const Card::heart_jack(Card::heart, Card::jack);
59 Card const Card::diamond_jack(Card::diamond, Card::jack);
60 Card const Card::club_nine(Card::club, Card::nine);
61 Card const Card::spade_nine(Card::spade, Card::nine);
62 Card const Card::heart_nine(Card::heart, Card::nine);
63 Card const Card::diamond_nine(Card::diamond, Card::nine);
64 
65 /** -> result
66  **
67  ** @param    color_name   name of the color
68  **
69  ** @return   color 'name'
70  **/
71 Card::Color
color(string const & color_name)72 Card::color(string const& color_name)
73 {
74   if (color_name == to_string(Card::club))
75     return Card::club;
76   else if (color_name == to_string(Card::spade))
77     return Card::spade;
78   else if (color_name == to_string(Card::heart))
79     return Card::heart;
80   else if (color_name == to_string(Card::diamond))
81     return Card::diamond;
82   else
83     DEBUG_ASSERTION(false,
84                     "Card::color(color_name):\n"
85                     "  color '" << color_name << "' unknown");
86 
87   return Card::nocardcolor;
88 } // static Card::Color Card::color(string color_name)
89 
90 /** -> result
91  **
92  ** @param    value_name   name of the value
93  **
94  ** @return   value 'name'
95  **/
96 Card::Value
value(string const & value_name)97 Card::value(string const& value_name)
98 {
99   if (value_name == to_string(Card::nine))
100     return Card::nine;
101   else if (value_name == to_string(Card::jack))
102     return Card::jack;
103   else if (value_name == to_string(Card::queen))
104     return Card::queen;
105   else if (value_name == to_string(Card::king))
106     return Card::king;
107   else if (value_name == to_string(Card::ten))
108     return Card::ten;
109   else if (value_name == to_string(Card::ace))
110     return Card::ace;
111   else
112     DEBUG_ASSERTION(false,
113 		    "Card::value(value_name):\n"
114 		    "  value '" << value_name << "' unknown");
115 
116   return nocardvalue;
117 } // static Card::Value Card::value(string value_name)
118 
119 /** constructor
120  ** reads 'color' and 'value' from 'name'
121  **
122  ** @param    name   the card name
123  **/
Card(string const & name)124 Card::Card(string const& name)
125 {
126   istringstream istr(name);
127   this->read(istr);
128 } // Card::Card(string name)
129 
130 /** read the card from the stream
131  **
132  ** @param    istr   stream to read the card from
133  **
134  ** @return   stream
135  **/
136 istream&
read(istream & istr)137 Card::read(istream& istr)
138 {
139   Color color;
140   Value value;
141   istr >> color >> value;
142   *this = Card(color, value);
143   return istr;
144 } // istrean& Card::read(istream& istr)
145 
146 /** -> result
147  ** This value is used to use 'vector<.>' instead of 'map<Card, .>'
148  ** because of performance reasons (~15% better when using in 'CardCounter')
149  **
150  ** @return   integer value of the card
151  **/
152 int
to_int() const153 Card::to_int() const noexcept
154 {
155   if (this->color() == nocardcolor)
156     return 0;
157   switch (this->value()) {
158   case Card::nocardvalue:
159   case Card::unknowncardvalue:
160     return 0;
161   case Card::nine:
162     return (this->color() * 6 + 1);
163   case Card::jack:
164     return (this->color() * 6 + 2);
165   case Card::queen:
166     return (this->color() * 6 + 3);
167   case Card::king:
168     return (this->color() * 6 + 4);
169   case Card::ten:
170     return (this->color() * 6 + 5);
171   case Card::ace:
172     return (this->color() * 6 + 6);
173   }; // switch (this->value())
174 
175   return 0;
176 } // int Card::to_int() const
177 
178 /** -> result
179  **
180  ** @param    game   the game
181  **
182  ** @return   the tcolor of the card
183  **/
184 Card::TColor
tcolor(Game const & game) const185 Card::tcolor(Game const& game) const
186 {
187   if (this->istrump(game))
188     return Card::trump;
189   else
190     return this->color();
191 } // Card::TColor Card::tcolor(Game game) const
192 
193 /** -> result
194  **
195  ** @param    game   the game
196  **
197  ** @return   true if card is trump in the game
198  **/
199 bool
istrump(Game const & game) const200 Card::istrump(Game const& game) const
201 {
202   return this->istrump(game.type(), game.rule()(Rule::Type::dullen));
203 } // bool Card::istrump(Game game) const
204 
205 /** -> result
206  **
207  ** @param    gametype   the gametype
208  ** @param    dullen   whether dullen are allowed
209  **
210  ** @return   true if card is trump in the game
211  **/
212 bool
istrump(GameType const gametype,bool const dullen) const213 Card::istrump(GameType const gametype, bool const dullen) const
214 {
215   if (this->isdulle(gametype, dullen))
216     return true;
217 
218   switch (gametype) {
219   case GameType::thrown_nines:
220     return (this->value() == nine);
221   case GameType::thrown_kings:
222     return (this->value() == king);
223   case GameType::thrown_nines_and_kings:
224     return (   (this->value() == nine)
225             || (this->value() == king) );
226   case GameType::thrown_richness:
227     return true;
228   case GameType::normal:
229   case GameType::poverty:
230   case GameType::fox_highest_trump:
231   case GameType::redistribute:
232   case GameType::genscher:
233   case GameType::marriage:
234   case GameType::marriage_solo:
235   case GameType::marriage_silent:
236   case GameType::solo_diamond:
237     return (   (this->color() == diamond)
238             || (this->value() == jack)
239             || (this->value() == queen) );
240   case GameType::solo_jack:
241     return (this->value() == jack);
242   case GameType::solo_queen:
243     return (this->value() == queen);
244   case GameType::solo_king:
245     return (this->value() == king);
246   case GameType::solo_queen_jack:
247     return (   (this->value() == jack)
248             || (this->value() == queen) );
249     break;
250   case GameType::solo_king_jack:
251     return (   (this->value() == jack)
252             || (this->value() == king) );
253   case GameType::solo_king_queen:
254     return (   (this->value() == queen)
255             || (this->value() == king) );
256   case GameType::solo_koehler:
257     return (   (this->value() == jack)
258             || (this->value() == queen)
259             || (this->value() == king) );
260   case GameType::solo_club:
261     return (   (this->color() == club)
262             || (this->value() == jack)
263             || (this->value() == queen) );
264   case GameType::solo_heart:
265     return (   (this->color() == heart)
266             || (this->value() == jack)
267             || (this->value() == queen) );
268   case GameType::solo_spade:
269     return (   (this->color() == spade)
270             || (this->value() == jack)
271             || (this->value() == queen) );
272   case GameType::solo_meatless:
273     return false;
274   } // switch(gametype)
275 
276   return false;
277 } // bool Card::istrump(GameType gametype, bool dullen) const
278 
279 /** -> result
280  **
281  ** @param    game   the game
282  **
283  ** @return   true if card is a dulle
284  **/
285 bool
isdulle(Game const & game) const286 Card::isdulle(Game const& game) const
287 {
288   return this->isdulle(game.type(), game.rule()(Rule::Type::dullen));
289 } // bool Card::isdulle(Game game) const
290 
291 /** -> result
292  **
293  ** @param    gametype   the gametype
294  ** @param    dullen   whether dullen are allowed
295  **
296  ** @return   true if card is a dulle
297  **/
298 bool
isdulle(GameType const gametype,bool const dullen) const299 Card::isdulle(GameType const gametype, bool const dullen) const
300 {
301   if (!dullen)
302     return false;
303 
304   if (*this != Card::dulle)
305     return false;
306 
307   switch (gametype) {
308   case GameType::normal:
309   case GameType::poverty:
310   case GameType::genscher:
311   case GameType::marriage:
312   case GameType::marriage_solo:
313   case GameType::marriage_silent:
314   case GameType::solo_club:
315   case GameType::solo_heart:
316   case GameType::solo_spade:
317   case GameType::solo_diamond:
318     return true;
319   case GameType::solo_meatless:
320   case GameType::solo_jack:
321   case GameType::solo_queen:
322   case GameType::solo_king:
323   case GameType::solo_queen_jack:
324   case GameType::solo_king_jack:
325   case GameType::solo_king_queen:
326   case GameType::solo_koehler:
327   case GameType::thrown_nines:
328   case GameType::thrown_kings:
329   case GameType::thrown_nines_and_kings:
330   case GameType::thrown_richness:
331   case GameType::fox_highest_trump:
332   case GameType::redistribute:
333     return false;
334   } // switch (gametype)
335 
336   return false;
337 } // bool Card::isdulle(GameType gametype, bool dullen) const
338 
339 /** -> result
340  **
341  ** @note   if both cards are equal, the first (this) is not less than
342  **   the second (card)
343  **   (but the dullen -- see rules)
344  **
345  ** @param    card   the card to compare with
346  **
347  ** @return   true, if the card is less than 'b', else false
348  **
349  ** @todo       is this function still called?
350  **/
351 bool
less(HandCard const & card) const352 Card::less(HandCard const& card) const
353 {
354   if (card.is_empty())
355     return false;
356 
357   if (card.possible_hyperswine())
358     return (*this != card);
359   if (   card.game().swines().hyperswines_announced()
360       && (*this == card.game().cards().hyperswine()))
361       return false;
362   if (card.possible_swine())
363     return (*this != card);
364 
365   return card.game().cards().less(*this, card);
366 } // bool HandCard::less(Card card) const
367 
368 /** -> result
369  **
370  ** @param    tcolor              tcolor
371  ** @param    marriage_selector   marriage selector
372  **
373  ** @result    whether the marriage is determined by a 'tcolor'-trick
374  **/
375 bool
is_selector(Card::TColor const tcolor,MarriageSelector const marriage_selector)376 is_selector(Card::TColor const tcolor,
377             MarriageSelector const marriage_selector)
378 {
379   switch (marriage_selector) {
380   case MarriageSelector::team_set:
381   case MarriageSelector::silent:
382     return false;
383   case MarriageSelector::first_foreign:
384     return true;
385   case MarriageSelector::first_trump:
386     return (tcolor == Card::trump);
387   case MarriageSelector::first_color:
388     return (tcolor != Card::trump);
389   case MarriageSelector::first_club:
390     return (tcolor == Card::club);
391   case MarriageSelector::first_spade:
392     return (tcolor == Card::spade);
393   case MarriageSelector::first_heart:
394     return (tcolor == Card::heart);
395   } // switch (marriage_selector)
396 
397   return false;
398 } // bool is_selector(Card::TColor tcolor, MarriageSelector marriage_selector)
399 
400 /** @return   the corresponding single picture solo
401  **/
402 GameType
solo(Card::Value const picture)403 solo(Card::Value const picture) noexcept
404 {
405   switch (picture) {
406   case Card::jack:
407     return GameType::solo_jack;
408   case Card::queen:
409     return GameType::solo_queen;
410   case Card::king:
411     return GameType::solo_king;
412   default:
413     DEBUG_ASSERTION(false,
414                     "solo(picture = " << picture << ")\n"
415                     "   no picture");
416     return GameType::normal;
417   }
418 }
419 
420 /** @return   the corresponding color solo
421  **/
422 GameType
solo(Card::Value const picture1,Card::Value const picture2)423 solo(Card::Value const picture1, Card::Value const picture2) noexcept
424 {
425   if (picture1 == Card::jack  && picture2 == Card::queen)
426     return GameType::solo_queen_jack;
427   if (picture2 == Card::jack  && picture1 == Card::queen)
428     return GameType::solo_queen_jack;
429   if (picture1 == Card::jack  && picture2 == Card::king)
430     return GameType::solo_king_jack;
431   if (picture2 == Card::jack && picture1 == Card::king)
432     return GameType::solo_king_jack;
433   if (picture1 == Card::queen  && picture2 == Card::king)
434     return GameType::solo_king_queen;
435   if (picture2 == Card::queen && picture1 == Card::king)
436     return GameType::solo_king_queen;
437   DEBUG_ASSERTION(false,
438                   "solo(picture1 = " << picture1 << ", picture2 = " << picture2 << ")\n"
439                   "   picture1 and picture2 no pictures or equal");
440   return GameType::normal;
441 }
442 
443 /** @return   the corresponding color solo
444  **/
445 GameType
solo(Card::Color const color)446 solo(Card::Color const color) noexcept
447 {
448   switch (color) {
449   case Card::club:
450     return GameType::solo_club;
451   case Card::spade:
452     return GameType::solo_spade;
453   case Card::heart:
454     return GameType::solo_heart;
455   case Card::diamond:
456     return GameType::solo_diamond;
457   default:
458     DEBUG_ASSERTION(false,
459                     "solo(color = " << color << ")\n"
460                     "   no color");
461     return GameType::normal;
462   }
463 }
464 
465 /** -> result
466  **
467  ** @param    value   card value
468  **
469  ** @return   name of the value
470  **/
471 string
to_string(Card::Value const value)472 to_string(Card::Value const value) noexcept
473 {
474   switch(value) {
475   case Card::nine:
476     return "nine";
477     (void)_("Card::Value::nine");
478   case Card::jack:
479     return "jack";
480     (void)_("Card::Value::jack");
481   case Card::queen:
482     return "queen";
483     (void)_("Card::Value::queen");
484   case Card::king:
485     return "king";
486     (void)_("Card::Value::king");
487   case Card::ten:
488     return "ten";
489     (void)_("Card::Value::ten");
490   case Card::ace:
491     return "ace";
492     (void)_("Card::Value::ace");
493   case Card::nocardvalue:
494     return "no card value";
495     (void)_("Card::Value::no card value");
496   case Card::unknowncardvalue:
497     return "unknown card value";
498     (void)_("Card::Value::unknown card value");
499   } // switch(value)
500 
501   return {};
502 } // string to_string(Card::Value value)
503 
504 /** -> result
505  **
506  ** @param    tcolor   card tcolor
507  **
508  ** @return   name of the tcolor
509  **/
510 string
to_string(Card::TColor const tcolor)511 to_string(Card::TColor const tcolor) noexcept
512 {
513   switch(tcolor) {
514   case Card::club:
515     return "club";
516     (void)_("Card::Color::club");
517   case Card::spade:
518     return "spade";
519     (void)_("Card::Color::spade");
520   case Card::heart:
521     return "heart";
522     (void)_("Card::Color::heart");
523   case Card::diamond:
524     return "diamond";
525     (void)_("Card::Color::diamond");
526   case Card::trump:
527     return "trump";
528     (void)_("Card::Color::trump");
529   case Card::nocardcolor:
530     return "no card color";
531     (void)_("Card::Color::no card color");
532   case Card::unknowncardcolor:
533     return "unknown card color";
534     (void)_("Card::Color::unknown card color");
535   } // switch(tcolor)
536 
537   return {};
538 } // string to_string(Card::TColor tcolor)
539 
540 /** @result    the name of the card
541  **/
542 string
to_string(Card const & card)543 to_string(Card const& card) noexcept
544 {
545   if (card.is_empty())
546     return "empty";
547   else if (card.is_unknown())
548     return "unknown";
549   else
550     return (to_string(card.color()) + " " + to_string(card.value()));
551 } // string to_string(Card card)
552 
553 /** translation
554  **
555  ** @param    value   card value
556  **
557  ** @return   translation
558  **/
559 string
gettext(Card::Value const value)560 gettext(Card::Value const value)
561 {
562   return gettext("Card::Value::" + to_string(value));
563 }
564 
565 /** translation
566  **
567  ** @param    color   card color
568  **
569  ** @return   translation
570  **/
571 string
gettext(Card::Color const color)572 gettext(Card::Color const color)
573 {
574   return gettext("Card::Color::" + to_string(color));
575 }
576 
577 /** translation
578  **
579  ** @param    value   card value
580  **
581  ** @return   translation
582  **/
583 string
gettext(Card const & card)584 gettext(Card const& card)
585 {
586   // gettext: %t = color, %t = value
587   return _("Card::%t %t",
588            _(card.color()), _(card.value()));
589 }
590 
591 /** -> result
592  **
593  ** @param    lhs   left hand side
594  ** @param    rhs   right hand side
595  **
596  ** @return   whether 'lhs' is greater than 'rhs'
597  **          (in the order: 'club', 'spade', 'heart', 'diamond'
598  **/
599 bool
operator >(Card::Color const lhs,Card::Color const rhs)600 operator>(Card::Color const lhs, Card::Color const rhs)
601 {
602   switch (lhs) {
603   case Card::club:
604     return (   (rhs == Card::spade)
605             || (rhs == Card::heart)
606             || (rhs == Card::diamond) );
607   case Card::spade:
608     return (   (rhs == Card::heart)
609             || (rhs == Card::diamond) );
610   case Card::heart:
611     return (rhs == Card::diamond);
612   case Card::diamond:
613     return false;
614   default:
615     DEBUG_ASSERTION(false,
616                     "operator>(lhs, rhs): illegal value");
617 
618     break;
619   } // switch (lhs)
620 
621   return false;
622 } // bool operator>(Card::Color lhs, Card::Color rhs)
623 
624 /** writes the card value in the output stream
625  **
626  ** @param    ostr    output stream
627  ** @param    value   card value
628  **
629  ** @return   output stream
630  **/
631 ostream&
operator <<(ostream & ostr,Card::Value const value)632 operator<<(ostream& ostr, Card::Value const value)
633 {
634   return (ostr << to_string(value));
635 } // ostream& operator<<(ostream& ostr, Card::Value value);
636 
637 /** read the card value out of the stream
638  **
639  ** @param    istr    input stream
640  ** @param    value   card value
641  **
642  ** @return   output stream
643  **/
644 istream&
operator >>(istream & istr,Card::Value & value)645 operator>>(istream& istr, Card::Value& value)
646 {
647   string value_name;
648   istr >> value_name;
649 
650   value = Card::value(value_name);
651 
652   return istr;
653 } // istream& operator>>(istream& istr, Card::Value& value);
654 
655 /** writes the card color in the output stream
656  **
657  ** @param    ostr     output stream
658  ** @param    tcolor   card color
659  **
660  ** @return   output stream
661  **/
662 ostream&
operator <<(ostream & ostr,Card::TColor const tcolor)663 operator<<(ostream& ostr, Card::TColor const tcolor)
664 {
665   return (ostr << to_string(tcolor));
666 } // ostream& operator<<(ostream& ostr, Card::TColor tcolor);
667 
668 /** read the card color out of the stream
669  **
670  ** @param    istr    input stream
671  ** @param    color   card color
672  **
673  ** @return   output stream
674  **/
675 istream&
operator >>(istream & istr,Card::Color & color)676 operator>>(istream& istr, Card::Color& color)
677 {
678   string color_name;
679   istr >> color_name;
680   color = Card::color(color_name);
681 
682   return istr;
683 } // istream& operator>>(istream& istr, Card::Color& color);
684 
685 /** writes the card in the output stream
686  **
687  ** @param    ostr   output stream
688  ** @param    card   card
689  **
690  ** @return   output stream
691  **/
692 ostream&
operator <<(ostream & ostr,Card const & card)693 operator<<(ostream& ostr, Card const& card)
694 {
695   return (ostr << to_string(card));
696 } // ostream& operator<<(ostream& ostr, Card const& card);
697 
698 /** read the card out of the stream
699  **
700  ** @param    istr   input stream
701  ** @param    card   card
702  **
703  ** @return   output stream
704  **/
705 istream&
operator >>(istream & istr,Card & card)706 operator>>(istream& istr, Card& card)
707 {
708   return card.read(istr);
709 } // istream& operator>>(istream& istr, Card& card);
710 
711