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
30 #include "cards_information.of_player.h"
31 #include "cards_information.heuristics.h"
32 #include "ai.h"
33
34 #include "../../party/rule.h"
35 #ifdef DEBUG_ASSERT
36 #include "../../card/trick.h"
37 #endif
38 #include "../../card/weighted_card_list.h"
39
40 #ifdef CHECK_RUNTIME
41 #include "../../runtime.h"
42 #endif
43
44 // whether to print information of the throwing
45 #ifndef RELEASE
46 #ifdef DKNOF
47 // whether to print information of the information flow
48 #define CONDITION_INFORMATION_FLOW \
49 false \
50 && (this->cards_information().player().no() == 1) \
51 && (this->playerno() == 3)
52 #define CONDITION_INFORMATION_ESTIMATED_HAND \
53 false \
54 && (this->cards_information().player().no() == 1) \
55 && (this->playerno() == 3)
56
57 #endif
58 #endif
59
60 /*
61 * CardsInformation::OfPlayer contains the information an ai has about the
62 * cards a specific player can / must / cannot have.
63 * The class contains four counters and a weighting
64 * - played
65 * what cards the player has played
66 * - must have
67 * which and how many cards the player must have
68 * (p.e. if he has announced 're' and not played a club queen, he must
69 * have one (but can have two) )
70 * - can have
71 * which and how many cards the player can have at max
72 * (p.e. if another player has annouced 're' he can only have one club queen)
73 * - does not have tcolor
74 * just remembers the colors the player cannot have anymore
75 * (because he could not serve).
76 * This should not really be necessary anymore, but I feel more sure with this
77 * code (should check someday)
78 * - cards weighting
79 * According to the gameplay the cards are weighted.
80 * positive weight means higher probability for the card,
81 * negative weight means lower probability for the card.
82 *
83 * The easy part of the code is to add the information gotten by the game
84 * (see CardsInformation).
85 * Complicated is to update the information over the players.
86 * - if the cards a player has to play == the number he must have
87 * the player can only have the cards he must have
88 * (must have --> can have)
89 * A bit more information is gained, like:
90 * If the player has only one free card (the rest to play are 'must') he
91 * can only have at most one card from each card he must not have).
92 * - if the cards a player has to play == the number he can have
93 * the player must have the cards he can have
94 * (can have --> must have)
95 * This is analogous to the previous case, so here also a bit more information
96 * can be gained (and yes, there was at least one case I needed this), p.e.
97 * The player has to play two cards
98 * and he can have one diamond jack and two heart jacks,
99 * he must have at least one heart jack.
100 * - count data for a single card
101 * Sum up how many times the card was played and the other players must have
102 * it. Then the player can at max have the remaining number of cards.
103 * If p.e. a player has announced 're' he must have a club queen. So the other
104 * players can only have at max one club queen in their hands.
105 * And again this can be viewed from the opposite side:
106 * If for a card the sum of 'played' and 'can have' of the other players
107 * are less than two, then the player must have the remaining ones.
108 * A simple (and most common) example is that three players do not have
109 * spade, so the fourth player must have all remaining spade cards.
110 */
111
112 /** constructor
113 **
114 ** @param cards_information corresponding cards information
115 ** @param playerno number of the player of this information
116 **/
OfPlayer(CardsInformation & cards_information,unsigned const playerno)117 CardsInformation::OfPlayer::OfPlayer(CardsInformation& cards_information,
118 unsigned const playerno) :
119 cards_information_(&cards_information),
120 playerno_(playerno)
121 { this->reset(); }
122
123 /** copy constructor
124 **
125 ** @param of_player object to be copied
126 **/
127 CardsInformation::OfPlayer::OfPlayer(OfPlayer const& of_player) = default;
128
129 /** copy operator
130 **
131 ** @param of_player object to be copied
132 **
133 ** @return object
134 **/
135 CardsInformation::OfPlayer&
136 CardsInformation::OfPlayer::operator=(OfPlayer const& of_player) = default;
137
138 /** destructor
139 **/
140 CardsInformation::OfPlayer::~OfPlayer() = default;
141
142 /** resets all information
143 **/
144 void
reset()145 CardsInformation::OfPlayer::reset()
146 {
147 // cards
148 this->played_.clear();
149 this->must_have_.clear();
150 this->cards_weighting_.clear();
151 for (const auto & c : this->game().rule().cards()) {
152 this->can_have_.set(c, this->game().rule()(Rule::Type::number_of_same_cards));
153 this->cards_weighting_[c] = 0;
154 } // for (c \in cards)
155
156 // tcolors
157 this->tcolor_played_.clear();
158 this->tcolor_must_have_.clear();
159 for (unsigned c = 0; c < Card::number_of_tcolors; ++c)
160 this->tcolor_can_have_.set(static_cast<Card::TColor>(c),
161 min(this->game().rule()(Rule::Type::number_of_cards_on_hand),
162 this->game().cards().count(static_cast<Card::TColor>(c))));
163
164 return ;
165 } // void CardsInformation::OfPlayer::reset()
166
167 /** writes 'of_player' in 'ostr'
168 **
169 ** @param ostr output stream
170 ** @param of_player object to write into 'ostr'
171 **
172 ** @return the output stream
173 **/
174 ostream&
operator <<(ostream & ostr,CardsInformation::OfPlayer const & of_player)175 operator<<(ostream& ostr, CardsInformation::OfPlayer const& of_player)
176 {
177 of_player.write(ostr);
178 return ostr;
179 } // ostream& operator<<(ostream& ostr, CardsInformation::OfPlayer of_player)
180
181 /** writes 'of_player' in 'ostr'
182 **
183 ** @param ostr output stream
184 **/
185 void
write(ostream & ostr) const186 CardsInformation::OfPlayer::write(ostream& ostr) const
187 {
188 ostr << "player = " << this->playerno() << " (" << this->player().name() << ")\n";
189
190 ostr << "{\n";
191
192 ostr << " played\n"
193 << " {\n"
194 << this->played_
195 << " }\n";
196
197 ostr << " must_have\n"
198 << " {\n"
199 << this->must_have_
200 << " }\n";
201
202 ostr << " can_have\n"
203 << " {\n"
204 << "cardno = " << this->can_have_.cards_no() << '\n';
205 for (const auto & c : this->game().rule().cards()) {
206 if (this->can_have(c) > 0) {
207 ostr << setw(14)
208 << c << " = "
209 << this->can_have(c) << ' '
210 << "(" << this->weighting(c, false) << ")\n";
211 }
212 } // for (c \in cards)
213 ostr << " }\n";
214
215 ostr << " tcolors played\n"
216 << " {\n"
217 << this->tcolor_played_
218 << " }\n";
219
220 ostr << " tcolors must_have\n"
221 << " {\n"
222 << this->tcolor_must_have_
223 << " }\n";
224
225 ostr << " tcolors can_have\n"
226 << " {\n"
227 << this->tcolor_can_have_
228 << " }\n";
229
230 ostr << '\n';
231 ostr << "estimated hand\n"
232 << this->estimated_hand() << '\n';
233 ostr << "}\n";
234
235 return ;
236 } // void CardsInformation::OfPlayer::write(ostream& ostr) const
237
238 /** @return the corresponding cards information
239 **/
240 CardsInformation const&
cards_information() const241 CardsInformation::OfPlayer::cards_information() const
242 { return *this->cards_information_; }
243
244 /** @return the corresponding cards information
245 **/
246 CardsInformation&
cards_information()247 CardsInformation::OfPlayer::cards_information()
248 { return *this->cards_information_; }
249
250 /** @return the number of the player
251 **/
252 unsigned
playerno() const253 CardsInformation::OfPlayer::playerno() const
254 { return this->playerno_; }
255
256 /** @return the corresponding game
257 **/
258 Game const&
game() const259 CardsInformation::OfPlayer::game() const
260 {
261 return this->cards_information().game();
262 }
263
264 /** @return the corresponding player
265 **/
266 Player const&
player() const267 CardsInformation::OfPlayer::player() const
268 {
269 return this->game().player(this->playerno());
270 }
271
272 /** sets the corresponding cards information
273 **
274 ** @param cards_information new cards information
275 **/
276 void
set_cards_information(CardsInformation & cards_information)277 CardsInformation::OfPlayer::set_cards_information(CardsInformation&
278 cards_information)
279 { this->cards_information_ = &cards_information; }
280
281 /** @return whether all cards are known
282 **/
283 bool
all_known() const284 CardsInformation::OfPlayer::all_known() const
285 {
286 return (this->can_have_.cards_no() == this->must_have_.cards_no());
287 }
288
289 /** -> result
290 **
291 ** @param card card
292 **
293 ** @return how many of 'card' the player has played
294 **/
295 unsigned
played(Card const card) const296 CardsInformation::OfPlayer::played(Card const card) const
297 {
298 return this->played_[card];
299 }
300
301 /** -> result
302 **
303 ** @param tcolor tcolor
304 **
305 ** @return how many cards of the tcolor 'tcolor' the player has played
306 **/
307 unsigned
played(Card::TColor const tcolor) const308 CardsInformation::OfPlayer::played(Card::TColor const tcolor) const
309 {
310 DEBUG_ASSERTION(tcolor != Card::unknowncardcolor,
311 "CardsInformation::OfPlayer::played(" << tcolor << ")\n"
312 " tcolor 'unknown' is forbidden");
313
314 return this->tcolor_played_[tcolor];
315 }
316
317 /** -> result
318 **
319 ** @param card card
320 **
321 ** @return how many cards of 'card' the player must still have on the hand
322 **/
323 unsigned
must_have(Card const card) const324 CardsInformation::OfPlayer::must_have(Card const card) const
325 {
326 return this->must_have_[card];
327 }
328
329 /** -> result
330 **
331 ** @param tcolor tcolor
332 **
333 ** @return how many cards of 'tcolor' the player must still have on the hand
334 **/
335 unsigned
must_have(Card::TColor const tcolor) const336 CardsInformation::OfPlayer::must_have(Card::TColor const tcolor) const
337 {
338 DEBUG_ASSERTION(tcolor != Card::unknowncardcolor,
339 "CardsInformation::OfPlayer::must_have(" << tcolor << ")\n"
340 " tcolor 'unknown' is forbidden");
341 return this->tcolor_must_have_[tcolor];
342 }
343
344 /** -> result
345 **
346 ** @param card card
347 **
348 ** @return how many cards of 'card' the player can still have on the hand
349 **/
350 unsigned
can_have(Card const card) const351 CardsInformation::OfPlayer::can_have(Card const card) const
352 {
353 return this->can_have_[card];
354 }
355
356 /** -> result
357 **
358 ** @param tcolor tcolor
359 **
360 ** @return how many cards of 'tcolor' the player can still have on the hand
361 **/
362 unsigned
can_have(Card::TColor const tcolor) const363 CardsInformation::OfPlayer::can_have(Card::TColor const tcolor) const
364 {
365 DEBUG_ASSERTION(tcolor != Card::unknowncardcolor,
366 "CardsInformation::OfPlayer::can_have(" << tcolor << ")\n"
367 " tcolor 'unknown' is forbidden");
368 return this->tcolor_can_have_[tcolor];
369 }
370
371 /** -> result
372 **
373 ** @param card card
374 **
375 ** @return whether the player cannot have the card still on the hand
376 **/
377 bool
cannot_have(Card const card) const378 CardsInformation::OfPlayer::cannot_have(Card const card) const
379 {
380 return (this->can_have(card) == 0);
381 }
382
383 /** -> result
384 **
385 ** @param tcolor tcolor to check
386 **
387 ** @return whether the player does not have anymore the tcolor
388 **/
389 bool
does_not_have(Card::TColor const tcolor) const390 CardsInformation::OfPlayer::does_not_have(Card::TColor const tcolor) const
391 {
392 return (this->can_have(tcolor) == 0);
393 }
394
395 /** -> result
396 **
397 ** @param card card
398 **
399 ** @return the number of unkown cards 'card'
400 **/
401 unsigned
unknown(Card const card) const402 CardsInformation::OfPlayer::unknown(Card const card) const
403 {
404 return (this->can_have(card) - this->must_have(card));
405 }
406
407 /** -> result
408 **
409 ** @param tcolor tcolor
410 **
411 ** @return the number of unknown cards of 'tcolor'
412 **/
413 unsigned
unknown(Card::TColor const tcolor) const414 CardsInformation::OfPlayer::unknown(Card::TColor const tcolor) const
415 {
416 return (this->can_have(tcolor) - this->must_have(tcolor));
417 }
418
419 /** -> result
420 **
421 ** @param card card
422 ** @param modify whether to modify the weighting (t.i. of the club queen) (default: true)
423 **
424 ** @return weighting for the card
425 ** positive means more probability for having the card
426 **/
427 int
weighting(Card const card,bool const modify) const428 CardsInformation::OfPlayer::weighting(Card const card, bool const modify) const
429 {
430 if (this->cannot_have(card))
431 return 0;
432
433 int modifier = 0;
434
435 // take the announcement into account:
436 // if the player has announced, he will likely have less color cards
437 if (!card.istrump(this->game())) {
438 switch (this->game().announcements().last(this->player()).announcement) {
439 case Announcement::reply:
440 case Announcement::no120_reply:
441 modifier -= 10;
442 break;
443 case Announcement::no120:
444 modifier -= 15;
445 break;
446 case Announcement::no90:
447 modifier -= 30;
448 break;
449 case Announcement::no60:
450 modifier -= 100;
451 break;
452 case Announcement::no30:
453 modifier -= 500;
454 break;
455 case Announcement::no0:
456 modifier -= 1000;
457 break;
458 default:
459 break;
460 } // switch (announcement)
461 } // if (!card.istrump(this->game()))
462
463 if (modify) {
464 if ( (card == Card::club_queen)
465 && (this->game().type() == GameType::normal) ) {
466 modifier += (10 // *Value*
467 * this->cards_information().player().team_information().team_value(this->playerno()));
468 if (maybe_to_team(this->cards_information().player().team_information().team(this->playerno())) == Team::re) {
469 if (this->played(Card::club_queen))
470 modifier -= 500;
471 else
472 modifier += 1000;
473 } else if (maybe_to_team(this->cards_information().player().team_information().team(this->playerno())) == Team::contra)
474 modifier -= 1000;
475 } // if (club queen in normal game)
476 } // if (modify)
477
478 return (this->cards_weighting_[card] + modifier);
479 } // int CardsInformation::OfPlayer::weighting(Card card, bool modify = true) const
480
481 /** @return the cards the player has played
482 **/
483 Hand
played_cards() const484 CardsInformation::OfPlayer::played_cards() const
485 {
486 Hand cards(this->player());
487
488 for (const auto & c : this->played_.cards())
489 cards.add(c);
490
491 return cards;
492 }
493
494 /** @return the cards the player must have
495 **/
496 Hand
must_have_cards() const497 CardsInformation::OfPlayer::must_have_cards() const
498 {
499 Hand cards(this->player());
500
501 for (const auto & c : this->must_have_.cards())
502 cards.add(c);
503
504 return cards;
505 }
506
507 /** @return the cards the player cannot have
508 **/
509 Hand
cannot_have_cards() const510 CardsInformation::OfPlayer::cannot_have_cards() const
511 {
512 Hand cards(this->player());
513
514 for (const auto & c : this->game().rule().cards()) {
515 for (unsigned i = 0;
516 i < this->game().rule()(Rule::Type::number_of_same_cards) - this->can_have(c);
517 ++i) {
518 cards.add(c);
519 }
520 }
521
522 return cards;
523 }
524
525 /** @return the possible hand of the player
526 **
527 ** @todo check whether the cards the player must have are as many as the
528 ** player can only have
529 ** @todo add the played cards
530 **/
531 Hand
possible_hand() const532 CardsInformation::OfPlayer::possible_hand() const
533 {
534 DEBUG_ASSERTION((this->can_have_.cards_no()
535 >= this->player().cards_to_play()),
536 "CardsInformation(" << this->cards_information().player().no() << ")::OfPlayer(" << this->playerno() << ")::possible_hand():\n"
537 " can_have.cards_no() = " << this->can_have_.cards_no()
538 << " < " << this->player().cards_to_play()
539 << " = this->player().cards_to_play()");
540
541 DEBUG_ASSERTION((this->can_have_.cards().size()
542 == this->can_have_.cards_no()),
543 "CardsInformation::OfPlayer::possible_hand():\n"
544 " the number of cards is not valid");
545
546 return Hand(this->player(),
547 this->can_have_.cards(), this->played_.cards());
548 }
549
550 /** -> result
551 ** the estimation is based by the weighting
552 **
553 ** @return estimated hand for the player
554 **
555 ** @todo check tcolor (can have, must have)
556 ** @todo better alogrithm for the estimation
557 ** @todo ensure, that all cards are distributed
558 ** @todo ensure, that each player has enough cards
559 ** @todo maybe contra -> no club queen
560 ** @todo two re -> both one club queen
561 **/
562 Hand
estimated_hand() const563 CardsInformation::OfPlayer::estimated_hand() const
564 {
565 #ifdef CONDITION_INFORMATION_ESTIMATED_HAND
566 if (CONDITION_INFORMATION_ESTIMATED_HAND) {
567 clog << __FILE__ << '#' << __LINE__ << " " << "start CardsInformation(" << this->cards_information().player().no() << ")::OfPlayer(" << this->player().no() << ")::estimate_hand()\n";
568 }
569 #endif
570
571 if (this->cards_information().player().value(Aiconfig::Type::hands_known))
572 return this->player().hand();
573
574 Hand hand(this->player());
575
576 // start with the played cards
577 hand.add_played(this->played_.cards());
578
579 #ifdef WORKAROUND
580 // all cards known
581 if (this->can_have_.cards_no() == this->player().cards_to_play()) {
582 hand.add(this->can_have_.cards());
583 return hand;
584 }
585 #endif
586
587 auto const& game = this->game();
588 auto const& rule = game.rule();
589
590 { // 1) add all 'must have' cards
591 // ToDo: use must_have for the cards directly
592 for (auto c : rule.cards()) {
593 hand.add(c, this->must_have(c));
594 }
595 #ifdef CONDITION_INFORMATION_ESTIMATED_HAND
596 if (CONDITION_INFORMATION_ESTIMATED_HAND) {
597 //clog << __FILE__ << '#' << __LINE__ << " " << "hand after 1) must have\n" << hand << '\n';
598 }
599 #endif
600 } // 1) add all 'must have' cards
601
602 // all cards of the player are known
603 if (hand.cardsnumber() == this->player().cards_to_play())
604 return hand;
605
606 // the cards to distribute
607 WeightedCardList cards(this->game());
608 { // Put all remaining can_have-cards in the list 'cards'.
609 for (const auto & c : rule.cards()) {
610 if (this->cannot_have(c))
611 continue;
612 int w = INT_MIN; // the weighting from the other players
613 // take the weighting of the other players into account
614 for (unsigned p = 0; p < game.playerno(); ++p) {
615 if ( (p != this->playerno())
616 && this->cards_information().of_player(p).unknown(c)) {
617 w = max(w, this->cards_information().of_player(p).weighting(c));
618 }
619 } // for (p)
620
621 // '2 * i' reflects the probability to have two of the same cards
622 for (int i = 0;
623 #ifdef WORKAROUND
624 // ToDo: remaining(*c) should always be >= can_have(*c)
625 i < static_cast<int>(min(this->can_have(c) - this->must_have(c),
626 this->cards_information().remaining_unknown(c)));
627 #else
628 i < static_cast<int>(this->can_have(*c) - this->must_have(*c));
629 #endif
630 ++i) {
631 if (w == INT_MIN) {
632 cards.add(c, INT_MAX);
633 continue;
634 }
635 if ( (c == Card::club_queen)
636 && (this->game().type() == GameType::normal) ) {
637 // in a normal game, a player will most surely not have two club queens
638 cards.add(c,
639 this->weighting(c)
640 - w / static_cast<int>(this->cards_information().remaining_unknown(c))
641 - 10000 * (i + this->must_have(c))); // *Value*
642 } else {
643 cards.add(c,
644 this->weighting(c)
645 - w / static_cast<int>(this->cards_information().remaining_unknown(c))
646 - 10 * i); // *Value*
647 }
648 }
649 } // for (c \in cards)
650 } // Put all remaining can_have-cards in the list 'cards'.
651 #ifdef CONDITION_INFORMATION_ESTIMATED_HAND
652 if (CONDITION_INFORMATION_ESTIMATED_HAND) {
653 clog << __FILE__ << '#' << __LINE__ << " " << "weighted cards\n" << cards << '\n';
654 }
655 #endif
656
657 { // 2) add to each player the cards with the greates weighting
658 // (a card can be distributed multible times)
659 // Now fill up the hand in the order of weighting.
660 while ( !cards.empty()
661 // '- 1' here, so that in the next block 'w' is the right weighting
662 // (the next card is always added)
663 && (hand.cardsnumber() + 1 < this->player().cards_to_play()) ) {
664 #ifdef CONDITION_INFORMATION_ESTIMATED_HAND
665 if (CONDITION_INFORMATION_ESTIMATED_HAND) {
666 clog << __FILE__ << '#' << __LINE__ << " " << "2a) add card " << cards.highest() << '\n';
667 }
668 #endif
669 hand.add(cards.highest());
670 cards.pop_highest();
671 }
672
673 // Also add the cards with a weighting nearly the same as the lowest so far.
674 int const w = cards.highest_weighting();
675 while ( !cards.empty()
676 && (cards.highest_weighting() > w - 40)) { // *Value*
677 #ifdef CONDITION_INFORMATION_ESTIMATED_HAND
678 if (CONDITION_INFORMATION_ESTIMATED_HAND) {
679 clog << __FILE__ << '#' << __LINE__ << " " << "2b) add card " << cards.highest() << '\n';
680 }
681 #endif
682 hand.add(cards.highest());
683 cards.pop_highest();
684 }
685 } // 2) add each player the cards with the greates weighting
686
687 { // 3) for each color add enough cards according to 'tcolor_must_have' and 'tcolor_can_have'
688 // single tcolors
689 for (unsigned tc = 0; tc < Card::number_of_tcolors; ++tc) {
690 Card::TColor tcolor = static_cast<Card::TColor>(tc);
691 unsigned n = hand.count(tcolor);
692 unsigned const min = this->must_have(tcolor);
693 if (n >= min)
694 continue;
695 // add at least 'min' cards of 'tcolor'
696 while (!cards.highest(tcolor).is_empty()
697 && (n + 1 < min)) {
698 #ifdef CONDITION_INFORMATION_ESTIMATED_HAND
699 if (CONDITION_INFORMATION_ESTIMATED_HAND) {
700 clog << __FILE__ << '#' << __LINE__ << " " << "3) add card " << cards.highest(tcolor) << '\n';
701 }
702 #endif
703 hand.add(cards.highest(tcolor));
704 cards.pop_highest(tcolor);
705 n += 1;
706 }
707
708 // Also add the cards with a weighting nearly the same as the lowest so far.
709 int const w = cards.highest_weighting(tcolor);
710 while ( !cards.highest(tcolor).is_empty()
711 && (cards.highest_weighting(tcolor) > w - 40)) { // *Value*
712 #ifdef CONDITION_INFORMATION_ESTIMATED_HAND
713 if (CONDITION_INFORMATION_ESTIMATED_HAND) {
714 clog << __FILE__ << '#' << __LINE__ << " " << "3) add card " << cards.highest(tcolor) << '\n';
715 }
716 #endif
717 hand.add(cards.highest(tcolor));
718 cards.pop_highest(tcolor);
719 }
720 } // for (tcolor)
721
722 // single tcolors inverted
723 for (unsigned tc = 0; tc < Card::number_of_tcolors; ++tc) {
724 Card::TColor tcolor = static_cast<Card::TColor>(tc);
725 if (this->player().cards_to_play() <= this->can_have(tcolor))
726 continue;
727 unsigned n = hand.cardsnumber() - hand.count(tcolor);
728 unsigned const min = (this->player().cards_to_play()
729 - this->can_have(tcolor));
730 if (n >= min)
731 continue;
732 if (cards.cards_no() < min - n) {
733 DEBUG("throw") << __FILE__ << '#' << __LINE__ << " " << "\n CardsInformation(" << this->cards_information().player().no()
734 << ")::OfPlayer(" << this->playerno() << ")::"
735 << "throw in estimated_hand()\n";
736 DEBUG_THROW(InvalidGameException, InvalidGameException());
737 } // if (cards.size() < min - n)
738
739 // add at least 'min' cards of not 'tcolor'
740 while (!cards.highest_not_of(tcolor).is_empty()
741 && (n + 1 < min)) {
742 #ifdef CONDITION_INFORMATION_ESTIMATED_HAND
743 if (CONDITION_INFORMATION_ESTIMATED_HAND) {
744 clog << __FILE__ << '#' << __LINE__ << " " << "3) add card " << cards.highest_not_of(tcolor) << '\n';
745 }
746 #endif
747 hand.add(cards.highest_not_of(tcolor));
748 cards.pop_highest_not_of(tcolor);
749 n += 1;
750 }
751
752 // Also add the cards with a weighting nearly the same as the lowest so far.
753 int const w = cards.highest_weighting(tcolor);
754 while ( !cards.highest_not_of(tcolor).is_empty()
755 && (cards.highest_weighting_not_of(tcolor) > w - 40)) { // *Value*
756 #ifdef CONDITION_INFORMATION_ESTIMATED_HAND
757 if (CONDITION_INFORMATION_ESTIMATED_HAND) {
758 clog << __FILE__ << '#' << __LINE__ << " " << "3) add card " << cards.highest_not_of(tcolor) << '\n';
759 }
760 #endif
761 hand.add(cards.highest_not_of(tcolor));
762 cards.pop_highest_not_of(tcolor);
763 }
764 } // for (tcolor)
765 } // 3) for each color add enough cards according to 'tcolor_must_have' and 'tcolor_can_have'
766
767 { // 4) add the cards this player has the greates weighting of
768 // this must be the last part to make use of 'cards', since 'cards' is empty after this part
769
770 while (!cards.empty()) {
771 Card const& card = cards.highest();
772 // player with the maximal weighting
773 int weighting_max = INT_MIN;
774 for (unsigned p = 0; p < game.playerno(); ++p) {
775 if ( !this->cards_information().of_player(p).all_known()
776 && this->cards_information().of_player(p).can_have(card)
777 && (this->cards_information().of_player(p).weighting(card)
778 > weighting_max) )
779 weighting_max
780 = this->cards_information().of_player(p).weighting(card);
781 }
782
783 #ifdef CONDITION_INFORMATION_ESTIMATED_HAND
784 if (CONDITION_INFORMATION_ESTIMATED_HAND) {
785 clog << __FILE__ << '#' << __LINE__ << " " << "4) " << setw(5) << cards.highest_weighting() << " -- "
786 << setw(5) << weighting_max << " - 40: " << card << '\n';
787 }
788 #endif
789 if (cards.highest_weighting() >= weighting_max - 40) { // *Value* (same below, 2 times)
790 #ifdef CONDITION_INFORMATION_ESTIMATED_HAND
791 if (CONDITION_INFORMATION_ESTIMATED_HAND) {
792 clog << __FILE__ << '#' << __LINE__ << " " << "4) add card " << card << '\n';
793 }
794 #endif
795 hand.add(card);
796 }
797
798 cards.pop_highest();
799 } // while (!cards.empty())
800 } // 4) add the cards this player has the greates weighting of
801
802 #ifdef CONDITION_INFORMATION_ESTIMATED_HAND
803 if (CONDITION_INFORMATION_ESTIMATED_HAND) {
804 clog << __FILE__ << '#' << __LINE__ << " " << "end CardsInformation(" << this->cards_information().player().no() << ")::OfPlayer(" << this->player().no() << ")::estimate_hand()\n";
805 }
806 #endif
807
808 return hand;
809 } // Hand CardsInformation::OfPlayer::estimated_hand() const
810
811 /** -> result
812 **
813 ** @param hand hand to check
814 **
815 ** @return whether the hand is valid
816 **/
817 bool
hand_valid(Hand const & hand) const818 CardsInformation::OfPlayer::hand_valid(Hand const& hand) const
819 {
820 map<Card, unsigned> const counter = hand.counted_cards();
821
822 for (auto const& c : counter) {
823 Card const& card = c.first;
824 unsigned const& n = c.second;
825 if (!( (this->must_have(card) <= n)
826 && (this->can_have(card) >= n)) )
827 return false;
828 } // for (c : counter)
829
830 for (unsigned c = 0; c < Card::number_of_tcolors; ++c) {
831 Card::TColor const tcolor = static_cast<Card::TColor>(c);
832 unsigned const n = hand.count(tcolor);
833 if (!( (this->must_have(tcolor) <= n)
834 && (this->can_have(tcolor) >= n)) )
835 return false;
836 } // for (c < Card::number_of_tcolors)
837
838 return true;
839 } // bool CardsInformation::OfPlayer::hand_valid(Hand hand) const
840
841 /** the game starts
842 **/
843 void
game_start()844 CardsInformation::OfPlayer::game_start()
845 {
846 #ifdef CONDITION_INFORMATION_FLOW
847 if (CONDITION_INFORMATION_FLOW)
848 cout << "CardsInformation(" << this->cards_information().player().no() << ")::OfPlayer(" << this->playerno() << ")::game_start()\n";
849 #endif
850 switch (this->game().type()) {
851 case GameType::marriage:
852 if (this->player() == this->game().players().soloplayer()) {
853 this->add_must_have(Card::club_queen, 2);
854 // tcolor is set in CardsInformation::do_update()
855 }
856 break;
857 case GameType::poverty:
858 /// the player who takes the poverty
859 if (this->player() == this->game().players().poverty_partner())
860 CardsInformationHeuristics::poverty_returned
861 (this->player(),
862 this->cards_information().player(),
863 this->cards_weighting_,
864 this->game().poverty().returned_trumpno());
865 if (this->player() == this->game().players().soloplayer())
866 if (this->game().poverty().returned_trumpno() == 0)
867 this->add_must_exactly_have(Card::trump, this->game().poverty().returned_trumpno());
868 break;
869 default:
870 break;
871 } // switch (this->game().type())
872
873 return ;
874 } // void CardsInformation::OfPlayer::game_start()
875
876 /** the player has played 'card'
877 **
878 ** @param card card that has been played
879 ** @param trick current trick
880 **/
881 void
card_played(HandCard const & card,Trick const & trick)882 CardsInformation::OfPlayer::card_played(HandCard const& card,
883 Trick const& trick)
884 {
885 if (card.is_unknown()) {
886 this->played_.inc(card);
887 this->tcolor_played_.inc(card.tcolor());
888 return ;
889 }
890
891 #ifdef CONDITION_INFORMATION_FLOW
892 if (CONDITION_INFORMATION_FLOW)
893 cout << "CardsInformation(" << this->cards_information().player().no() << ")::OfPlayer(" << this->playerno() << ")::"
894 << "card_played(card = " << card << ", trick)\n";
895 #endif
896 if (!this->can_have(card)) {
897 #ifdef DEBUG_ASSERT
898 if (!this->cards_information().is_virtual()) {
899 cerr << "--\n"
900 << __FILE__ << "#" << __LINE__ << ": "
901 << "Error in 'CardsInformation(" << this->cards_information().player().no() << ")::OfPlayer(" << this->playerno() << ")"
902 << "::card_played(" << card << ")\n";
903 cerr << '\n';
904 cerr << "trick " << this->game().tricks().current_no() << '\n';
905 cerr << card.game().tricks().current() << '\n';
906 cerr << '\n';
907 cerr << this->cards_information() << endl;
908 cerr << "Hand:\n" << this->player().hand();
909 cerr << '\n';
910 //cerr << *this;
911 cerr << endl;
912 }
913 #endif
914 DEBUG_ASSERTION(this->cards_information().is_virtual(),
915 "CardsInformation"
916 << "(" << this->cards_information().player().no() << ")"
917 << "::OfPlayer(" << this->playerno() << ")"
918 << "::card_played(" << card << "):\n"
919 " card cannot be on the hand.\n"
920 << " trick = " << this->game().tricks().current_no() << '\n'
921 //<< " Game:\n" << this->game()
922 //<< " Information:\n" << this->cards_information()
923 //<< " Hand:\n" << this->player().hand()
924 );
925 DEBUG("throw") << __FILE__ << '#' << __LINE__ << " " << "\n CardsInformation(" << this->cards_information().player().no()
926 << ")::OfPlayer(" << this->playerno() << ")::"
927 << "throw in card_played(" << card << ", trick" << ")\n"
928 << trick;
929 DEBUG_THROW(InvalidGameException, InvalidGameException());
930 } // if (!this->can_have(card))
931
932 this->played_.inc(card);
933 if (this->must_have(card))
934 this->must_have_.dec(card);
935 this->can_have_.dec(card);
936 Card::TColor const tcolor = card.tcolor();
937 this->tcolor_played_.inc(tcolor);
938 if (this->must_have(tcolor))
939 this->tcolor_must_have_.dec(tcolor);
940 this->tcolor_can_have_.dec(tcolor);
941
942 if (!this->cards_information().in_recalcing)
943 this->update_remaining_cards();
944
945 return ;
946 } // void CardsInformation::OfPlayer::card_played(HandCard card, Trick trick)
947
948 /** change the weightings according to the played card
949 ** call some heuristics which
950 **
951 ** @param card played_card
952 ** @param trick current trick
953 **
954 ** @todo better name: all cards can be weighted
955 **/
956 void
weight_played_card(HandCard const & card,Trick const & trick)957 CardsInformation::OfPlayer::weight_played_card(HandCard const& card,
958 Trick const& trick)
959 {
960 // no information from unknown cards
961 if (card.is_unknown())
962 return ;
963 // I do not get more information from my own cardplay
964 if (card.player() == this->cards_information().player())
965 return ;
966
967 #ifdef CONDITION_INFORMATION_FLOW
968 if (CONDITION_INFORMATION_FLOW)
969 cout << "CardsInformation(" << this->cards_information().player().no() << ")::OfPlayer(" << this->playerno() << ")::"
970 << "weight_played_card(card = " << card << ", trick)\n";
971 #endif
972
973 CardsInformationHeuristics::card_played(card, trick,
974 this->cards_information().player(),
975 this->cards_weighting_);
976
977 return ;
978 } // void CardsInformation::OfPlayer::weight_played_card(HandCard const& card)
979
980 /** adds the information that the player must have the card 'no' times
981 **
982 ** @param card card that the player must have
983 ** @param no how many times the player must have the card
984 ** default: 1
985 **/
986 void
add_must_have(Card const card,unsigned const no)987 CardsInformation::OfPlayer::add_must_have(Card const card, unsigned const no)
988 {
989 #ifdef CONDITION_INFORMATION_FLOW
990 if (CONDITION_INFORMATION_FLOW) {
991 if (this->must_have(card) < no) {
992 cout << "CardsInformation(" << this->cards_information().player().no() << ")::OfPlayer(" << this->playerno() << ")::"
993 << "add_must_have(card = " << card << ", no = " << no << ")\n";
994 }
995 }
996 #endif
997 if (no > this->can_have(card)) {
998 DEBUG_ASSERTION(this->cards_information().is_virtual(),
999 "CardsInformation"
1000 << "(" << this->cards_information().player().no() << ")"
1001 << "::OfPlayer(" << this->playerno() << ")"
1002 << "::add_must_have(" << card << ", " << no << ")\n"
1003 " player = " << this->playerno() << "\n"
1004 " can_have(" << card << ") = " << this->can_have(card)
1005 << " < " << no << " = no");
1006 DEBUG("throw") << __FILE__ << '#' << __LINE__ << " " << "\n CardsInformation(" << this->cards_information().player().no()
1007 << ")::OfPlayer(" << this->playerno() << ")::"
1008 << "throw in add_must_have(" << card << ", " << no << ")\n";
1009 DEBUG_THROW(InvalidGameException, InvalidGameException());
1010 } // if (no > this->can_have(card))
1011
1012 if (this->must_have_.min_set(card, no))
1013 this->cards_information().queue_update(card);
1014
1015 return ;
1016 } // void CardsInformation::OfPlayer::add_must_have(Card card, unsigned no = 1)
1017
1018 /** adds the information that the player must have the cards
1019 **
1020 ** @param cards cards the player must have
1021 **/
1022 void
add_must_have(vector<Card> const & cards)1023 CardsInformation::OfPlayer::add_must_have(vector<Card> const& cards)
1024 {
1025 map<Card, unsigned> number;
1026 for (const auto & card : cards)
1027 number[card] += 1;
1028
1029 for (map<Card, unsigned>::const_iterator n = number.begin();
1030 n != number.end();
1031 ++n)
1032 this->add_must_have(n->first, n->second);
1033
1034 return ;
1035 } // void CardsInformation::OfPlayer::add_must_have(vector<Card> cards)
1036
1037 /** adds the information that the player must have the tcolor 'no' times
1038 **
1039 ** @param tcolor tcolor that the player must have
1040 ** @param no how many times the player must have the tcolor
1041 **/
1042 void
add_must_have(Card::TColor const tcolor,unsigned const no)1043 CardsInformation::OfPlayer::add_must_have(Card::TColor const tcolor,
1044 unsigned const no)
1045 {
1046 #ifdef CONDITION_INFORMATION_FLOW
1047 if (CONDITION_INFORMATION_FLOW) {
1048 if (this->must_have(tcolor) < no) {
1049 cout << "CardsInformation(" << this->cards_information().player().no() << ")::OfPlayer(" << this->playerno() << ")::"
1050 << "add_must_have(tcolor = " << tcolor << ", no = " << no << ")\n";
1051 }
1052 }
1053 #endif
1054
1055 if (no > this->can_have(tcolor)) {
1056 DEBUG_ASSERTION(this->cards_information().is_virtual(),
1057 "CardsInformation"
1058 << "(" << this->cards_information().player().no() << ")"
1059 << "::OfPlayer(" << this->playerno() << ")"
1060 << "::add_must_have(" << tcolor << ", " << no << "):\n"
1061 " no = " << no << " < " << this->can_have(tcolor) << " = can have\n"
1062 " player = " << this->playerno());
1063 DEBUG("throw") << __FILE__ << '#' << __LINE__ << " " << "\n CardsInformation(" << this->cards_information().player().no()
1064 << ")::OfPlayer(" << this->playerno() << ")::"
1065 << "throw in add_must_have(" << tcolor << ", " << no << ")\n";
1066 DEBUG_THROW(InvalidGameException, InvalidGameException());
1067 } // if (no < this->must_have(card))
1068
1069 if (this->tcolor_must_have_.cards_no()
1070 - this->must_have(tcolor)
1071 + no
1072 > this->player().cards_to_play() ) {
1073 DEBUG_ASSERTION(this->cards_information().is_virtual(),
1074 "CardsInformation"
1075 << "(" << this->cards_information().player().no() << ")"
1076 << "::OfPlayer(" << this->playerno() << ")"
1077 << "::add_must_have(" << tcolor << ", " << no << "):\n"
1078 " no too great" << '\n');
1079 DEBUG("throw") << __FILE__ << '#' << __LINE__ << " " << "\n CardsInformation(" << this->cards_information().player().no()
1080 << ")::OfPlayer(" << this->playerno() << ")::"
1081 << "throw in add_must_have(" << tcolor << ", " << no << ")\n";
1082 DEBUG_THROW(InvalidGameException, InvalidGameException());
1083 } // if (tcolor_must_have - must_have(tcolor) + no > cards to play)
1084
1085 if (this->tcolor_must_have_.min_set(tcolor, no)) {
1086 this->cards_information().queue_update(tcolor);
1087 }
1088
1089 return ;
1090 } // void CardsInformation::OfPlayer::add_must_have(Card::TColor tcolor, unsigned no)
1091
1092 /** adds the information that the player must have the tcolor exactly 'no' times
1093 **
1094 ** @param tcolor tcolor that the player must have
1095 ** @param no how many times exactly the player must have the tcolor
1096 **/
1097 void
add_must_exactly_have(Card::TColor const tcolor,unsigned const no)1098 CardsInformation::OfPlayer::add_must_exactly_have(Card::TColor const tcolor,
1099 unsigned const no)
1100 {
1101 #ifdef CONDITION_INFORMATION_FLOW
1102 if (CONDITION_INFORMATION_FLOW)
1103 if ( (this->must_have(tcolor) < no)
1104 || (this->can_have(tcolor) > no) )
1105 cout << "CardsInformation(" << this->cards_information().player().no() << ")::OfPlayer(" << this->playerno() << ")::"
1106 << "add_must_exactly_have(tcolor = " << tcolor << ", no = " << no << ")\n";
1107 #endif
1108
1109 this->add_can_have(tcolor, no);
1110 this->add_must_have(tcolor, no);
1111
1112 return ;
1113 } // void CardsInformation::OfPlayer::add_must_exactly_have(Card::TColor tcolor, unsigned no)
1114
1115 /** adds the information that the player can have the card at max 'no' times
1116 **
1117 ** @param card card that the player can have
1118 ** @param no how many times the player can have the card at max
1119 **/
1120 void
add_can_have(Card const card,unsigned const no)1121 CardsInformation::OfPlayer::add_can_have(Card const card, unsigned const no)
1122 {
1123 #ifdef CONDITION_INFORMATION_FLOW
1124 if (CONDITION_INFORMATION_FLOW)
1125 if (this->can_have(card) > no)
1126 cout << "CardsInformation(" << this->cards_information().player().no() << ")::OfPlayer(" << this->playerno() << ")::"
1127 << "add_can_have(card = " << card << ", no = " << no << ")\n";
1128 #endif
1129 if (no < this->must_have(card)) {
1130 DEBUG_ASSERTION(this->cards_information().is_virtual(),
1131 "CardsInformation"
1132 << "(" << this->cards_information().player().no() << ")"
1133 << "::OfPlayer(" << this->playerno() << ")"
1134 << "::add_can_have(" << card << ", " << no << "):\n"
1135 " no < " << this->must_have(card) << " = must have\n"
1136 " player = " << this->playerno());
1137 DEBUG("throw") << __FILE__ << '#' << __LINE__ << " " << "\n CardsInformation(" << this->cards_information().player().no()
1138 << ")::OfPlayer(" << this->playerno() << ")::"
1139 << "throw in add_can_have(" << card << ", " << no << ")\n";
1140 DEBUG_THROW(InvalidGameException, InvalidGameException());
1141 } // if (no < this->must_have(card))
1142
1143 if (this->can_have_.max_set(card, no))
1144 this->cards_information().queue_update(card);
1145
1146 // now erase the 'can_have' for all cards of 'tcolor'
1147
1148 return ;
1149 } // void CardsInformation::OfPlayer::add_can_have(Card card, unsigned no)
1150
1151 /** adds the information that the player can have the cards at max 'no' times
1152 **
1153 ** @param cards cards that the player can have
1154 ** @param no how many times the player can have the card at max
1155 **/
1156 void
add_can_have(vector<Card> const & cards,unsigned const no)1157 CardsInformation::OfPlayer::add_can_have(vector<Card> const& cards,
1158 unsigned const no)
1159 {
1160 for (const auto & card : cards)
1161 this->add_can_have(card, no);
1162
1163 return ;
1164 } // void CardsInformation::OfPlayer::add_can_have(vector<Card> cards, unsigned no)
1165
1166 /** adds the information that the player can only have the cards
1167 **
1168 ** @param cards cards the player can only have
1169 **/
1170 void
add_can_only_have(vector<Card> const & cards)1171 CardsInformation::OfPlayer::add_can_only_have(vector<Card> const& cards)
1172 {
1173 #ifdef CONDITION_INFORMATION_FLOW
1174 if (CONDITION_INFORMATION_FLOW) {
1175 #if 0
1176 cout << "CardsInformation(" << this->cards_information().player().no() << ")::OfPlayer(" << this->playerno() << ")::"
1177 << "add_can_only_have(cards)\n";
1178 #else
1179 cout << "CardsInformation(" << this->cards_information().player().no() << ")::OfPlayer(" << this->playerno() << ")::"
1180 << "add_can_only_have(cards = ";
1181 for (auto c = cards.begin(); c != cards.end(); ++c)
1182 cout << ((c == cards.begin()) ? "" : ", ") << *c;
1183 cout << ")" << endl;
1184 #endif
1185 }
1186 #endif
1187 map<Card, unsigned> number;
1188 for (const auto & card : cards) {
1189 number[card] += 1;
1190 }
1191
1192 unsigned const unknown_no = std::count(cards.begin(), cards.end(), Card::unknown);
1193 if (unknown_no == 0) {
1194 // remove all entries in 'can_have' which have the value '0'
1195 // count the number of cards the player can have
1196 vector<Card> to_remove;
1197 for (auto x = this->can_have_.begin();
1198 x != this->can_have_.end();
1199 ++x) {
1200 map<Card, unsigned>::const_iterator n = number.find(x->first);
1201 if (n == number.end()) {
1202 if (this->must_have(x->first)) {
1203 DEBUG_ASSERTION(this->cards_information().is_virtual(),
1204 "CardsInformation"
1205 << "(" << this->cards_information().player().no() << ")"
1206 << "::OfPlayer(" << this->playerno() << ")"
1207 "::add_can_only_have():\n"
1208 " card '" << x->first << "':\n"
1209 " new number = 0 < "
1210 << this->must_have(x->first) << " = must_have");
1211 if (::debug("throw")) {
1212 DEBUG("throw") << __FILE__ << '#' << __LINE__ << " " << x->first << ": " << this->must_have(x->first) << endl;
1213 DEBUG("throw") << *this << endl;
1214 DEBUG("throw") << __FILE__ << '#' << __LINE__ << " " << "\n CardsInformation(" << this->cards_information().player().no()
1215 << ")::OfPlayer(" << this->playerno() << ")::"
1216 << "throw in add_can_only_have(cards): " << x->first << "\n";
1217 }
1218 DEBUG_THROW(InvalidGameException, InvalidGameException());
1219 } // if (this->must_have(x->first))
1220 to_remove.push_back(x->first);
1221 continue;
1222 }
1223
1224 if (n->second < this->must_have(x->first)) {
1225 DEBUG_ASSERTION(this->cards_information().is_virtual(),
1226 "CardsInformation"
1227 << "(" << this->cards_information().player().no() << ")"
1228 << "::OfPlayer(" << this->playerno() << ")"
1229 "::add_can_only_have():\n"
1230 " card '" << x->first << "':\n"
1231 " new number = " << n->second << " < "
1232 << this->must_have(x->first) << " = must_have");
1233 DEBUG("throw") << __FILE__ << '#' << __LINE__ << " " << "\n CardsInformation(" << this->cards_information().player().no()
1234 << ")::OfPlayer(" << this->playerno() << ")::"
1235 << "throw in add_can_only_have(cards)\n";
1236 DEBUG_THROW(InvalidGameException, InvalidGameException());
1237 } // if (n->second < this->must_have(x->first))
1238 } // for (x \in can_have)
1239
1240 // remove the cards with value '0' from the list
1241 if (!to_remove.empty()) {
1242 for (vector<Card>::const_iterator c = to_remove.begin();
1243 c != to_remove.end();
1244 ++c) {
1245 if (this->must_have(*c)) {
1246 DEBUG_ASSERTION(this->cards_information().is_virtual(),
1247 "CardsInformation"
1248 << "(" << this->cards_information().player().no() << ")"
1249 << "::OfPlayer(" << this->playerno() << ")"
1250 << "):\n"
1251 " card '" << *c << "':\n"
1252 " new number = 0 < "
1253 << this->must_have(*c) << " = must_have");
1254 DEBUG("throw") << __FILE__ << '#' << __LINE__ << " " << "\n CardsInformation(" << this->cards_information().player().no()
1255 << ")::OfPlayer(" << this->playerno() << ")::"
1256 << "throw in add_can_only_have(cards)\n";
1257 DEBUG_THROW(InvalidGameException, InvalidGameException());
1258 } // if (this->must_have(*c))
1259
1260 this->add_cannot_have(*c);
1261 } // for (c \in to_remove)
1262 } // if (!to_remove.empty())
1263 } // if (no unknown card)
1264
1265 // set the maximal number of the cards
1266 for (map<Card, unsigned>::const_iterator n = number.begin();
1267 n != number.end();
1268 ++n) {
1269 if (this->can_have_.max_set(n->first, n->second + unknown_no))
1270 this->cards_information().queue_update(n->first);
1271 } // for (n \in number)
1272
1273 if ( (::game_status != GameStatus::game_redistribute)
1274 && (this->can_have_.cards_no() < this->player().cards_to_play())) {
1275 DEBUG_ASSERTION(this->cards_information().is_virtual(),
1276 "CardsInformation"
1277 << "(" << this->cards_information().player().no() << ")"
1278 << "::OfPlayer(" << this->playerno() << ")"
1279 << "::add_can_only_have(cards)\n"
1280 " can_have.cards_no() = " << this->can_have_.cards_no()
1281 << " < "
1282 << this->player().cards_to_play() << " = cards to play");
1283 DEBUG("throw") << __FILE__ << '#' << __LINE__ << " " << "\n CardsInformation(" << this->cards_information().player().no()
1284 << ")::OfPlayer(" << this->playerno() << ")::"
1285 << "throw in add_can_only_have(cards)\n";
1286 DEBUG_THROW(InvalidGameException, InvalidGameException());
1287 }
1288
1289 return ;
1290 } // void CardsInformation::OfPlayer::add_can_only_have(vector<Card> cards)
1291
1292 /** adds the information that the player cannot have the card
1293 **
1294 ** @param card card the player cannot have
1295 **/
1296 void
add_cannot_have(Card const card)1297 CardsInformation::OfPlayer::add_cannot_have(Card const card)
1298 {
1299 #ifdef CONDITION_INFORMATION_FLOW
1300 if (CONDITION_INFORMATION_FLOW)
1301 if (this->can_have(card) > 0)
1302 cout << "CardsInformation(" << this->cards_information().player().no() << ")::OfPlayer(" << this->playerno() << ")::"
1303 << "add_cannot_have(card = " << card << ")\n";
1304 #endif
1305 if (this->must_have(card)) {
1306 DEBUG_ASSERTION(this->cards_information().is_virtual(),
1307 "CardsInformation"
1308 << "(" << this->cards_information().player().no() << ")"
1309 << "::OfPlayer(" << this->playerno() << ")"
1310 << "::add_cannot_have(" << card << ")\n"
1311 " player = " << this->playerno() << "\n"
1312 " must_have(card) = " << this->must_have(card) << " > 0");
1313 DEBUG("throw") << __FILE__ << '#' << __LINE__ << " " << "\n CardsInformation(" << this->cards_information().player().no()
1314 << ")::OfPlayer(" << this->playerno() << ")::"
1315 << "throw in add_cannot_have(" << card << ")\n";
1316 DEBUG_THROW(InvalidGameException, InvalidGameException());
1317 } // if (this->must_have(card))
1318
1319 if (this->can_have_.erase(card)) {
1320 if (this->must_have(card) > 0) {
1321 DEBUG_ASSERTION(this->cards_information().is_virtual(),
1322 "CardsInformation"
1323 << "(" << this->cards_information().player().no() << ")"
1324 << "::OfPlayer(" << this->playerno() << ")"
1325 << "::add_cannot_have(" << card << "):\n"
1326 << " must_have = " << this->must_have(card) << '\n'
1327 << " player = " << this->playerno());
1328 DEBUG("throw") << __FILE__ << '#' << __LINE__ << " " << "\n CardsInformation(" << this->cards_information().player().no()
1329 << ")::OfPlayer(" << this->playerno() << ")::"
1330 << "throw in add_cannot_have(" << card << ")\n";
1331 DEBUG_THROW(InvalidGameException, InvalidGameException());
1332 } // if (this->must_have(card))
1333 if (this->can_have_.cards_no() < this->player().cards_to_play()) {
1334 DEBUG_ASSERTION(this->cards_information().is_virtual(),
1335 "CardsInformation"
1336 << "(" << this->cards_information().player().no() << ")"
1337 << "::OfPlayer(" << this->playerno() << ")"
1338 << "::add_cannot_have(" << card << ")\n"
1339 " player = " << this->playerno() << "\n"
1340 " can_have.cards_no() = " << this->can_have_.cards_no()
1341 << " < "
1342 << this->player().cards_to_play() << " = cards to play");
1343 if (::debug("throw")) {
1344 DEBUG("throw") << __FILE__ << '#' << __LINE__ << " " << "\n CardsInformation(" << this->cards_information().player().no()
1345 << ")::OfPlayer(" << this->playerno() << ")::"
1346 << "throw in add_cannot_have(" << card << ")\n"
1347 << "can have = " << this->can_have_.cards_no()
1348 << " < " << this->player().cards_to_play() << " = cards to play\n";
1349 }
1350 DEBUG_THROW(InvalidGameException, InvalidGameException());
1351 } // if (this->can_have_.cards_no() < this->player().cards_to_play())
1352
1353 #ifdef WORKAROUND
1354 // if only one player can have the card, he must have it (see 'update_card')
1355 { // check whether all cards of 'card' are either played,
1356 // one player has it or it can be forgotten
1357 unsigned distributed = this->cards_information().played(card);
1358 for (unsigned p = 0; p < this->game().playerno(); ++p)
1359 distributed += this->cards_information().of_player(p).can_have(card);
1360 distributed += this->cards_information().forgotten_cards_no();
1361
1362 if (distributed < this->game().rule()(Rule::Type::number_of_same_cards)) {
1363 DEBUG_ASSERTION(this->cards_information().is_virtual(),
1364 "CardsInformation"
1365 << "(" << this->cards_information().player().no() << ")"
1366 << "::OfPlayer(" << this->playerno() << ")"
1367 << "::add_cannot_have"
1368 "(" << card << ")\n"
1369 " player = " << this->playerno() << "\n"
1370 " the card is not distributed");
1371 DEBUG("throw") << __FILE__ << '#' << __LINE__ << " " << "\n CardsInformation(" << this->cards_information().player().no()
1372 << ")::OfPlayer(" << this->playerno() << ")::"
1373 << "throw in add_cannot_have(" << card << ")\n";
1374 DEBUG_THROW(InvalidGameException, InvalidGameException());
1375 } // if (distributed < this->game().rule()(Rule::Type::number_of_same_cards))
1376
1377
1378 } // check whether all cards of 'card' are somewhere
1379 #endif
1380 this->cards_information().queue_update(card);
1381 } // if (this->can_have_.erase(card))
1382
1383 return ;
1384 } // void CardsInformation::OfPlayer::add_cannot_have(Card card)
1385
1386 /** adds the information that the player can have the tcolor at max 'no' times
1387 **
1388 ** @param tcolor tcolor that the player can have
1389 ** @param no how many times the player can have the tcolor at max
1390 **/
1391 void
add_can_have(Card::TColor const tcolor,unsigned const no)1392 CardsInformation::OfPlayer::add_can_have(Card::TColor const tcolor,
1393 unsigned const no)
1394 {
1395 #ifdef CONDITION_INFORMATION_FLOW
1396 if (CONDITION_INFORMATION_FLOW)
1397 if (this->can_have(tcolor) > no)
1398 cout << "CardsInformation(" << this->cards_information().player().no() << ")::OfPlayer(" << this->playerno() << ")::"
1399 << "add_can_have(tcolor = " << tcolor << ", no = " << no << ")\n";
1400 #endif
1401 DEBUG_ASSERTION(no <= this->game().cards().count(),
1402 "CardsInformation"
1403 << "(" << this->cards_information().player().no() << ")"
1404 << "::OfPlayer(" << this->playerno() << ")"
1405 << "::add_can_have(" << tcolor << ", " << no << "):\n"
1406 " no = " << no << " too great");
1407 if (no < this->must_have(tcolor)) {
1408 DEBUG_ASSERTION(this->cards_information().is_virtual(),
1409 "CardsInformation"
1410 << "(" << this->cards_information().player().no() << ")"
1411 << "::OfPlayer(" << this->playerno() << ")"
1412 << "::add_can_have(" << tcolor << ", " << no << "):\n"
1413 " no = " << no << " < " << this->must_have(tcolor) << " = must have\n"
1414 " player = " << this->playerno() << '\n'
1415 << *this
1416 );
1417 DEBUG("throw") << __FILE__ << '#' << __LINE__ << " " << "\n CardsInformation(" << this->cards_information().player().no()
1418 << ")::OfPlayer(" << this->playerno() << ")::"
1419 << "throw in add_can_have(" << tcolor << ", " << no << ")\n";
1420 DEBUG_THROW(InvalidGameException, InvalidGameException());
1421 } // if (no < this->must_have(card))
1422
1423 if (this->tcolor_can_have_.max_set(tcolor, no)) {
1424 this->cards_information().queue_update(tcolor);
1425 }
1426
1427 return ;
1428 } // void CardsInformation::OfPlayer::add_can_have(Card::TColor tcolor, unsigned no)
1429
1430 /** adds the information that the player cannot have the cards
1431 **
1432 ** @param cards cards the player cannot have
1433 **/
1434 void
add_cannot_have(vector<Card> const & cards)1435 CardsInformation::OfPlayer::add_cannot_have(vector<Card> const& cards)
1436 {
1437 for (const auto & card : cards)
1438 this->add_cannot_have(card);
1439
1440 return ;
1441 } // void CardsInformation::OfPlayer::add_cannot_have(vector<Card> cards)
1442
1443 /** adds the information that the player cannot have the tcolor
1444 **
1445 ** @param tcolor tcolor the player cannot have
1446 **/
1447 void
add_cannot_have(Card::TColor const tcolor)1448 CardsInformation::OfPlayer::add_cannot_have(Card::TColor const tcolor)
1449 {
1450 #ifdef CONDITION_INFORMATION_FLOW
1451 if (CONDITION_INFORMATION_FLOW) {
1452 cout << "CardsInformation(" << this->cards_information().player().no() << ")::OfPlayer(" << this->playerno() << ")::"
1453 << "add_does_not_have(tcolor = " << tcolor << ")\n";
1454 COUT << this->player().hand() << endl;
1455 }
1456 #endif
1457
1458 this->add_must_exactly_have(tcolor, 0);
1459
1460 return ;
1461 } // void CardsInformation::OfPlayer::add_cannot_have(Card::TColor tcolor)
1462
1463 /** updates the information of the card
1464 ** throws InvalidGameException
1465 **
1466 ** @param card card to update the information of
1467 **/
1468 void
update_information(Card const card)1469 CardsInformation::OfPlayer::update_information(Card const card)
1470 {
1471 if (card.is_unknown())
1472 return;
1473
1474 #ifdef CONDITION_INFORMATION_FLOW
1475 if (CONDITION_INFORMATION_FLOW) {
1476 cout << "CardsInformation(" << this->cards_information().player().no() << ")::OfPlayer(" << this->playerno() << ")::"
1477 << "update_information(card = " << card << ")\n";
1478 }
1479 #endif
1480 if (this->cards_information().in_recalcing)
1481 return ;
1482
1483 // how many times this card was played
1484 unsigned const played = this->cards_information().played(card);
1485 // the number of forgotten cards
1486 unsigned const forgotten_cards
1487 = this->cards_information().forgotten_cards_no();
1488 // count how many of the card the other player must have
1489 unsigned must_have = 0;
1490 // count how many of the card the other player can have
1491 unsigned can_have = 0;
1492 for (unsigned p = 0; p < this->game().playerno(); ++p) {
1493 if (p != this->playerno()) {
1494 must_have += this->cards_information().of_player(p).must_have(card);
1495 can_have += this->cards_information().of_player(p).can_have(card);
1496 }
1497 } // for (p < this->game().playerno())
1498
1499 #ifdef WORKAROUND
1500 // see bug report 232744
1501 // the cards distribution shall be sufficient
1502 // so that this case does not happen
1503 if ( (played + must_have > this->game().rule()(Rule::Type::number_of_same_cards))
1504 && !card.is_unknown()
1505 && this->cards_information().is_virtual()) {
1506 DEBUG("throw") << __FILE__ << '#' << __LINE__ << " " << "\n CardsInformation(" << this->cards_information().player().no()
1507 << ")::OfPlayer(" << this->playerno() << ")::"
1508 << "throw in update_information(" << card << ")\n";
1509 DEBUG_THROW(InvalidGameException, InvalidGameException());
1510 }
1511 #endif
1512
1513 if (played + must_have
1514 > this->game().rule()(Rule::Type::number_of_same_cards)) {
1515 DEBUG_ASSERTION(this->cards_information().is_virtual(),
1516 "CardsInformation"
1517 << "(" << this->cards_information().player().no() << ")"
1518 << "::OfPlayer(" << this->playerno() << ")"
1519 << "::update_information(" << card << ")\n"
1520 " played + must_have > max number:\n"
1521 " " << played
1522 << " + " << must_have << " > "
1523 << this->game().rule()(Rule::Type::number_of_same_cards)
1524 );
1525 DEBUG("throw") << __FILE__ << '#' << __LINE__ << " " << "\n CardsInformation(" << this->cards_information().player().no()
1526 << ")::OfPlayer(" << this->playerno() << ")::"
1527 << "throw in update_information(" << card << ")\n";
1528 DEBUG_THROW(InvalidGameException, InvalidGameException());
1529 } // if (played + must_have > number_of_same_cards)
1530
1531
1532 // the number of cards this player can at most have
1533 unsigned const n = min(this->game().rule()(Rule::Type::number_of_same_cards)
1534 - played
1535 - must_have,
1536 this->can_have(card.tcolor(this->game()))
1537 - this->must_have_(card.tcolor(this->game()),
1538 this->game())
1539 + this->must_have(card)
1540 );
1541 if (n < this->must_have(card)) {
1542 DEBUG_ASSERTION(this->cards_information().is_virtual(),
1543 "CardsInformation"
1544 << "(" << this->cards_information().player().no() << ")"
1545 << "::OfPlayer(" << this->playerno() << ")"
1546 << "::update_information(" << card << ")\n"
1547 " player = " << this->playerno() << "\n"
1548 " card = " << card << "\n"
1549 " number of same cards - played - must_have total"
1550 " < must_have(card):\n"
1551 << this->game().rule()(Rule::Type::number_of_same_cards)
1552 << " - " << played
1553 << " - " << must_have
1554 << " < " << this->must_have(card));
1555 DEBUG("throw") << __FILE__ << '#' << __LINE__ << " " << "\n CardsInformation(" << this->cards_information().player().no()
1556 << ")::OfPlayer(" << this->playerno() << ")::"
1557 << "throw in update_information(" << card << ")\n";
1558 DEBUG_THROW(InvalidGameException, InvalidGameException());
1559 } // if (n < this->must_have(card))
1560
1561 if (this->can_have_.max_set(card, n))
1562 this->cards_information().queue_update(card);
1563
1564 // check whether a player must have the remaining cards of 'card'
1565 if (can_have + played + this->must_have(card) + forgotten_cards
1566 < this->game().rule()(Rule::Type::number_of_same_cards)) {
1567 this->add_must_have(card,
1568 this->game().rule()(Rule::Type::number_of_same_cards)
1569 - can_have - played - forgotten_cards);
1570 }
1571
1572
1573 if (this->cards_information().is_virtual()) {
1574 if ( (this->can_have_.cards_no() < this->player().cards_to_play())
1575 || (this->must_have_.cards_no() > this->player().cards_to_play()) ) {
1576 DEBUG("throw") << __FILE__ << '#' << __LINE__ << " " << "\n CardsInformation(" << this->cards_information().player().no()
1577 << ")::OfPlayer(" << this->playerno() << ")::"
1578 << "throw in update_information(" << card << ")\n";
1579 DEBUG_THROW(InvalidGameException, InvalidGameException());
1580 }
1581 } // if (this->cards_information().is_virtual(),
1582
1583 if (this->can_have_.cards_no() < this->player().cards_to_play()) {
1584 DEBUG_ASSERTION(this->cards_information().is_virtual(),
1585 "CardsInformation"
1586 << "(" << this->cards_information().player().no() << ")"
1587 << "::OfPlayer(" << this->playerno() << ")"
1588 << "::update_information(" << card << ")\n"
1589 << " can_have.cards_no() = "
1590 << this->can_have_.cards_no()
1591 << " < "
1592 << this->player().cards_to_play() << " = cards to play");
1593 DEBUG("throw") << __FILE__ << '#' << __LINE__ << " " << "\n CardsInformation(" << this->cards_information().player().no()
1594 << ")::OfPlayer(" << this->playerno() << ")::"
1595 << "throw in update_information(" << card << ")\n";
1596 DEBUG_THROW(InvalidGameException, InvalidGameException());
1597 } // if (this->can_have_.cards_no() < this->player().cards_to_play())
1598
1599 if (this->must_have_.cards_no() > this->player().cards_to_play()) {
1600 DEBUG_ASSERTION(this->cards_information().is_virtual(),
1601 "CardsInformation"
1602 << "(" << this->cards_information().player().no() << ")"
1603 << "::OfPlayer(" << this->playerno() << ")"
1604 << "::update_information(" << card << ")\n"
1605 << " must_have.cards_no() = "
1606 << this->must_have_.cards_no()
1607 << " > "
1608 << this->player().cards_to_play() << " = cards to play");
1609 DEBUG("throw") << __FILE__ << '#' << __LINE__ << " " << "\n CardsInformation(" << this->cards_information().player().no()
1610 << ")::OfPlayer(" << this->playerno() << ")::"
1611 << "throw in update_information(" << card << ")\n";
1612 DEBUG_THROW(InvalidGameException, InvalidGameException());
1613 } // if ((this->must_have_.cards_no() > this->player().cards_to_play())
1614
1615 return ;
1616 } // void CardsInformation::OfPlayer::update_information(Card card)
1617
1618 /** updates the information of the tcolor
1619 **
1620 ** @param tcolor tcolor to update the information of
1621 **/
1622 void
update_information(Card::TColor const tcolor)1623 CardsInformation::OfPlayer::update_information(Card::TColor const tcolor)
1624 {
1625 if (tcolor == Card::unknowncardcolor)
1626 return ;
1627
1628 #ifdef CONDITION_INFORMATION_FLOW
1629 if (CONDITION_INFORMATION_FLOW)
1630 cout << "CardsInformation(" << this->cards_information().player().no() << ")::OfPlayer(" << this->playerno() << ")::"
1631 << "update_information(" << tcolor << ")\n";
1632 #endif
1633
1634 // the number of forgotten cards
1635 unsigned const forgotten_cards = this->cards_information().forgotten_cards_no();
1636
1637 { // maximum can have
1638 // the number of cards still to be played minus must have of other colors
1639 if (this->player().cards_to_play()
1640 + this->must_have(tcolor)
1641 < this->tcolor_must_have_.cards_no()) {
1642 DEBUG_ASSERTION(this->game().isvirtual(),
1643 "CardsInformation(" << this->cards_information().player().no()
1644 << ")::OfPlayer(" << this->playerno() << ")::"
1645 << "update_information(" << tcolor << ")\n"
1646 << " cards to play + must have(" << tcolor << ") = "
1647 << this->player().cards_to_play()
1648 << " + " << this->must_have(tcolor)
1649 << " < " << this->tcolor_must_have_.cards_no() << " = "
1650 << tcolor_must_have_.cards_no());
1651
1652 DEBUG("throw") << __FILE__ << '#' << __LINE__ << " " << "\n CardsInformation(" << this->cards_information().player().no()
1653 << ")::OfPlayer(" << this->playerno() << ")::"
1654 << "update_information(" << tcolor << ")\n";
1655 DEBUG_THROW(InvalidGameException, InvalidGameException());
1656 }
1657
1658 this->add_can_have(tcolor,
1659 this->player().cards_to_play()
1660 - this->tcolor_must_have_.cards_no()
1661 + this->must_have(tcolor));
1662 } // maximum can have
1663 { // minimum must have
1664 // the number of cards still to be played minus can have of other colors
1665 if (this->player().cards_to_play()
1666 > this->tcolor_can_have_.cards_no()
1667 - this->can_have(tcolor)) {
1668 this->add_must_have(tcolor,
1669 this->player().cards_to_play()
1670 - (this->tcolor_can_have_.cards_no()
1671 - this->can_have(tcolor)));
1672 }
1673 } // minimum must have
1674 { // maximum can have
1675 // number of cards still in game but not must have of the other players
1676 unsigned sum_must_have = 0;
1677 for (unsigned p = 0; p < this->game().playerno(); ++p)
1678 if (p != this->playerno())
1679 sum_must_have += this->cards_information().of_player(p).must_have(tcolor);
1680 if (this->game().cards().count(tcolor)
1681 < this->cards_information().played(tcolor)
1682 + sum_must_have) {
1683 DEBUG_ASSERTION(this->game().isvirtual(),
1684 "CardsInformation::OfPlayer::update_information(" << tcolor << ")\n"
1685 << " numberof = " << this->game().cards().count(tcolor)
1686 << " > " << this->cards_information().played(tcolor)
1687 << " + " << sum_must_have
1688 << " = played + sum_must_have");
1689 DEBUG_THROW(InvalidGameException, InvalidGameException());
1690 }
1691 this->add_can_have(tcolor,
1692 this->game().cards().count(tcolor)
1693 - this->cards_information().played(tcolor)
1694 - sum_must_have);
1695 } // maximum can have
1696 { // minimum must have
1697 // number of cards of the color - played - can have of others
1698 unsigned sum_can_have = 0;
1699 for (unsigned p = 0; p < this->game().playerno(); ++p)
1700 if (p != this->playerno())
1701 sum_can_have += this->cards_information().of_player(p).can_have(tcolor);
1702 if (this->game().cards().count(tcolor)
1703 > (forgotten_cards
1704 + this->cards_information().played(tcolor)
1705 + sum_can_have) ) {
1706
1707 this->add_must_have(tcolor,
1708 this->game().cards().count(tcolor)
1709 - forgotten_cards
1710 - this->cards_information().played(tcolor)
1711 - sum_can_have);
1712 }
1713 } // minimum must have
1714 // set the can have and must have according to the information of the cards
1715 this->add_can_have(tcolor, this->can_have_(tcolor, this->game()));
1716 this->add_must_have(tcolor, this->must_have_(tcolor, this->game()));
1717 this->check_can_is_must(tcolor);
1718 return ;
1719 } // void CardsInformation::OfPlayer::update_information(Card::TColor tcolor)
1720
1721 /** updates the information of the tcolors
1722 **/
1723 void
update_tcolor_information()1724 CardsInformation::OfPlayer::update_tcolor_information()
1725 {
1726 #ifdef CONDITION_INFORMATION_FLOW
1727 if (CONDITION_INFORMATION_FLOW)
1728 cout << "CardsInformation(" << this->cards_information().player().no() << ")::OfPlayer(" << this->playerno() << ")::"
1729 << "update_tcolor_information()\n";
1730 #endif
1731
1732 for (unsigned c = 0; c < Card::number_of_tcolors; ++c)
1733 this->update_information(static_cast<Card::TColor>(c));
1734
1735 if (!this->all_known()) {
1736 { // check can is must
1737 if (this->tcolor_can_have_.cards_no()
1738 == this->player().cards_to_play()) {
1739 for (unsigned c = 0; c < Card::number_of_tcolors; ++c)
1740 this->add_must_have(static_cast<Card::TColor>(c),
1741 this->can_have(static_cast<Card::TColor>(c)));
1742 }
1743 } // check can is must
1744
1745 { // check must is can
1746 if (this->tcolor_must_have_.cards_no()
1747 == this->player().cards_to_play()) {
1748 for (unsigned c = 0; c < Card::number_of_tcolors; ++c)
1749 this->add_can_have(static_cast<Card::TColor>(c),
1750 this->must_have(static_cast<Card::TColor>(c)));
1751 }
1752 } // check must is can
1753 } // if (!this->all_known())
1754
1755 // ToDo: if the player has only one free of a color, then he cannot have two of a card (p.e. three trumps, two swines so he cannot have two club kings)
1756
1757 return ;
1758 } // void CardsInformation::OfPlayer::update_tcolor_information()
1759
1760 /** updates 'can have' according to 'remaining cards'
1761 **/
1762 void
update_remaining_cards()1763 CardsInformation::OfPlayer::update_remaining_cards()
1764 {
1765 #ifdef CONDITION_INFORMATION_FLOW
1766 if (CONDITION_INFORMATION_FLOW)
1767 cout << "CardsInformation(" << this->cards_information().player().no() << ")::OfPlayer(" << this->playerno() << ")::"
1768 << "update_remaining_cards()\n";
1769 #endif
1770 unsigned const remaining_cards_no
1771 = (this->player().cards_to_play() - this->must_have_.cards_no());
1772
1773 if ( !(remaining_cards_no
1774 < this->game().rule()(Rule::Type::number_of_same_cards)) )
1775 return ;
1776 if ( !(this->must_have_.cards_no() != this->can_have_.cards_no()) )
1777 return ;
1778
1779 vector<Card> cards;
1780 for (const auto & c : this->can_have_) {
1781 if (this->can_have(c.first)
1782 > remaining_cards_no - this->must_have(c.first))
1783 cards.push_back(c.first);
1784 } // for (c \in this->can_have_)
1785 for (vector<Card>::const_iterator c = cards.begin();
1786 c != cards.end();
1787 ++c)
1788 this->add_can_have(*c, remaining_cards_no + this->must_have(*c));
1789
1790 return ;
1791 } // void CardsInformation::OfPlayern::update_remaining_cards()
1792
1793 /** checks whether the cards which the player can have are the ones
1794 ** he has to have
1795 **/
1796 void
check_can_is_must()1797 CardsInformation::OfPlayer::check_can_is_must()
1798 {
1799 #ifdef CONDITION_INFORMATION_FLOW
1800 if (CONDITION_INFORMATION_FLOW)
1801 cout << "CardsInformation(" << this->cards_information().player().no() << ")::OfPlayer(" << this->playerno() << ")::"
1802 << "check_can_is_must()\n";
1803 #endif
1804 if (this->can_have_.cards_no() == this->must_have_.cards_no())
1805 return ;
1806 if (this->must_have_.cards_no() == this->player().cards_to_play())
1807 return ;
1808
1809 // update the tcolor information
1810 for (unsigned c = 0; c < Card::number_of_tcolors; ++c)
1811 this->check_can_is_must(static_cast<Card::TColor>(c));
1812
1813 if (this->can_have_.cards_no() != this->player().cards_to_play()) {
1814 if (this->can_have_.cards_no() <
1815 (this->player().cards_to_play()
1816 + this->game().rule()(Rule::Type::number_of_same_cards)) ) {
1817 unsigned const cards_surplus
1818 = this->can_have_.cards_no() - this->player().cards_to_play();
1819 for (const auto & c : this->can_have_) {
1820 if (c.second > cards_surplus)
1821 if (this->must_have_.min_set(c.first, c.second - cards_surplus))
1822 this->cards_information().queue_update(c.first);
1823 } // for (c \in this->can_have)
1824 } // if (surplus less than number of cards)
1825 { // only one card unknown
1826
1827 // Check whether there is only one card in 'can have' unknown.
1828 // Then the remaining number must be the difference between
1829 // 'cards to play' and 'must have'.
1830
1831 if (this->can_have_.cards_no()
1832 >= (this->must_have_.cards_no()
1833 + this->game().rule()(Rule::Type::number_of_same_cards)))
1834 return ;
1835
1836 Card unknown_card;
1837 for (const auto & c : this->can_have_) {
1838 if (this->must_have_[c.first] != c.second) {
1839 // found a second unknown card
1840 if (!unknown_card.is_empty())
1841 return ;
1842
1843 unknown_card = c.first;
1844 } // if (must_have != can_have)
1845 } // for (c \in this->can_have_)
1846
1847 this->can_have_.max_set(unknown_card,
1848 this->player().cards_to_play()
1849 - this->must_have_.cards_no()
1850 + this->must_have_[unknown_card]);
1851 } // only one card unknown
1852 } // if (can_have != cards_to_play)
1853
1854 // so all 'can_have' are 'must_have'
1855
1856 for (const auto & c : this->can_have_) {
1857 if (this->must_have_[c.first] != c.second) {
1858 if (this->must_have_.min_set(c.first, c.second))
1859 this->cards_information().queue_update(c.first);
1860 }
1861 } // for (c \in this->can_have_)
1862
1863 return ;
1864 } // void CardsInformation::OfPlayer::check_can_is_must()
1865
1866 /** checks whether the cards which the player can have are the ones
1867 ** he has to have
1868 **
1869 ** @param tcolor tcolor to check
1870 **
1871 ** @todo information of only one remaining unknown card (see below)
1872 **/
1873 void
check_can_is_must(Card::TColor const tcolor)1874 CardsInformation::OfPlayer::check_can_is_must(Card::TColor const tcolor)
1875 {
1876 #ifdef CONDITION_INFORMATION_FLOW
1877 if (CONDITION_INFORMATION_FLOW)
1878 cout << "CardsInformation(" << this->cards_information().player().no() << ")::OfPlayer(" << this->playerno() << ")::"
1879 << "check_can_is_must(" << tcolor << ")\n";
1880 #endif
1881 if (this->can_have(tcolor) > this->must_have(tcolor))
1882 return ;
1883 unsigned const can_have_tcolor = this->can_have_(tcolor, this->game());
1884 unsigned const must_have_tcolor = this->must_have_(tcolor, this->game());
1885 if (can_have_tcolor == must_have_tcolor)
1886 return ;
1887 #ifdef POSTPONED
1888 // ToDo: check, whether only one card is unknown:
1889 // either set 'can have' or 'must have' according to the free
1890 // can_have(tcolor) - must_have_(tcolor, game()) or
1891 // can_have_(tcolor, game()) - must_have(tcolor)
1892 if (can_have_tcolor > this->must_have(tcolor)) {
1893 if (can_have_tcolor - this->must_have(tcolor) <
1894 this->game().rule()(Rule::Type::number_of_same_cards)) {
1895 // check whether there is only one unknown card
1896 for (CardCounter::const_iterator c = this->can_have_.begin();
1897 c != this->can_have_.end();
1898 ++c) {
1899 if (c->first.tcolor(this->game()) == tcolor) {
1900 if (this->must_have_[c->first] != c->second) {
1901 this->must_have_[c->first].min_set(c->first,
1902 c->second
1903 - (can_have_tcolor
1904 - this->must_have(tcolor)));
1905 } // if (must_have != can_have)
1906 }
1907 } // for (c \in this->can_have_)
1908
1909 }
1910 } // if (can_have_tcolor > this->must_have(tcolor))
1911 #endif
1912
1913 if (can_have_tcolor == this->must_have(tcolor)) {
1914 // all cards of tcolor are must have
1915 for (const auto & c : this->can_have_) {
1916 if (c.first.tcolor(this->game()) == tcolor) {
1917 if (this->must_have_.min_set(c.first, c.second))
1918 this->cards_information().queue_update(c.first);
1919 } // if (c->tcolor(this->game()) == tcolor)
1920 } // for (c \in this->can_have_)
1921 } // if (this->can_have_(tcolor, this->game()) == this->must_have(tcolor))
1922
1923 if (must_have_tcolor == this->can_have(tcolor)) {
1924 // all cards of tcolor are must have
1925 // this->can_have_ is changed in the loop!
1926 CardCounter const can_have = this->can_have_;
1927 for (const auto & c : can_have) {
1928 if (c.first.tcolor(this->game()) == tcolor) {
1929 if (this->can_have_.max_set(c.first, this->must_have(c.first))) {
1930 this->cards_information().queue_update(c.first);
1931 }
1932 } // if (c->tcolor(this->game()) == tcolor)
1933 } // for (c \in this->can_have_)
1934 } // if (this->can_have_(tcolor, this->game()) == this->must_have(tcolor))
1935
1936 return ;
1937 } // void CardsInformation::OfPlayer::check_can_is_must(Card::TColor tcolor)
1938
1939 /** check whether the cards the player has to have are the only ones
1940 ** he can have
1941 **/
1942 void
check_must_is_can()1943 CardsInformation::OfPlayer::check_must_is_can()
1944 {
1945 #ifdef CONDITION_INFORMATION_FLOW
1946 if (CONDITION_INFORMATION_FLOW)
1947 cout << "CardsInformation(" << this->cards_information().player().no() << ")::OfPlayer(" << this->playerno() << ")::"
1948 << "check_must_is_can()\n";
1949 #endif
1950
1951 // the number of unknown cards of the player
1952 unsigned const unknown_cards_no
1953 = (this->player().cards_to_play() - this->must_have_.cards_no());
1954
1955 if (unknown_cards_no >= this->game().rule()(Rule::Type::number_of_same_cards))
1956 return ;
1957
1958 // Example:
1959 // We know now that there is only one unknown card.
1960 // So the player can only have one 'can have' more than 'must have'.
1961
1962 vector<Card> update_cards;
1963 for (const auto & c : this->can_have_) {
1964 unsigned const must_have = this->must_have(c.first);
1965 if (c.second > must_have + unknown_cards_no) {
1966 //if (this->can_have_.max_set(c->first, must_have))
1967 update_cards.push_back(c.first);
1968 }
1969 }
1970
1971 // limit the can have
1972 for (vector<Card>::const_iterator c = update_cards.begin();
1973 c != update_cards.end();
1974 ++c) {
1975 if (this->can_have_.max_set(*c, this->must_have(*c) + unknown_cards_no))
1976 this->cards_information().queue_update(*c);
1977 } // for (c \in update_cards)
1978
1979 // special case: poverty
1980 if ( (this->game().type() == GameType::poverty)
1981 && (this->playerno() == this->game().players().soloplayer().no()) ) {
1982 // check whether all trumps of the player are known
1983 if ( !this->does_not_have(Card::trump)
1984 && (this->can_have(Card::trump) > this->must_have(Card::trump))
1985 && (this->played(Card::trump) + this->must_have(Card::trump)
1986 == this->game().poverty().returned_trumpno())) {
1987 // search the trumps
1988 vector<Card> update_cards;
1989 for (const auto & c : this->can_have_) {
1990 if ( (c.first.istrump(this->game()))
1991 && (c.second > this->must_have(c.first)) )
1992 update_cards.push_back(c.first);
1993 } // for (c \in this->can_have_)
1994 // limit the can have
1995 for (vector<Card>::const_iterator c = update_cards.begin();
1996 c != update_cards.end();
1997 ++c) {
1998 if (this->can_have_.max_set(*c, this->must_have(*c)))
1999 this->cards_information().queue_update(*c);
2000 } // for (c \in update_cards)
2001 } // if (all trumps known)
2002
2003 } // if (poverty player)
2004 } // void CardsInformation::OfPlayer::check_must_is_can()
2005
2006 /** -> result
2007 **
2008 ** @param lhs first object
2009 ** @param rhs second object
2010 **
2011 ** @return whether the two objects are equal
2012 ** (the correspondign cards information may differ)
2013 **/
2014 bool
operator ==(CardsInformation::OfPlayer const & lhs,CardsInformation::OfPlayer const & rhs)2015 operator==(CardsInformation::OfPlayer const& lhs,
2016 CardsInformation::OfPlayer const& rhs)
2017 {
2018 return ( (lhs.playerno_
2019 == rhs.playerno_)
2020 && (lhs.played_
2021 == rhs.played_)
2022 && (lhs.must_have_
2023 == rhs.must_have_)
2024 && (lhs.can_have_
2025 == rhs.can_have_)
2026 && (lhs.tcolor_played_
2027 == rhs.tcolor_played_)
2028 && (lhs.tcolor_must_have_
2029 == rhs.tcolor_must_have_)
2030 && (lhs.tcolor_can_have_
2031 == rhs.tcolor_can_have_)
2032 );
2033 }
2034
2035 /** -> result
2036 **
2037 ** @param lhs first object
2038 ** @param rhs second object
2039 **
2040 ** @return whether the two objects are different
2041 **/
2042 bool
operator !=(CardsInformation::OfPlayer const & lhs,CardsInformation::OfPlayer const & rhs)2043 operator!=(CardsInformation::OfPlayer const& lhs,
2044 CardsInformation::OfPlayer const& rhs)
2045 {
2046 return !(lhs == rhs);
2047 }
2048
2049 /** self check
2050 ** when an error is found, an ASSERTION is created
2051 **
2052 ** @return whether the self-check was successful (no error)
2053 **/
2054 bool
self_check() const2055 CardsInformation::OfPlayer::self_check() const
2056 {
2057 if (this->player().cards_to_play() == UINT_MAX)
2058 return true;
2059
2060 { // cards
2061 // the player has to have at least as many cards as he has to play
2062 if ( !(this->can_have_.cards_no() >= this->player().cards_to_play())) {
2063 DEBUG_ASSERTION(false,
2064 "CardsInformation"
2065 << "(" << this->cards_information().player().no() << ")"
2066 << "::OfPlayer(" << this->playerno() << ")"
2067 << "::self_check()\n"
2068 " playerno = " << this->playerno() << "\n"
2069 " can_have < cards to play:\n"
2070 << " " << this->can_have_.cards_no()
2071 << " < " << this->player().cards_to_play());
2072 return false;
2073 }
2074
2075 if ( !this->cards_information().is_virtual()
2076 && !this->game().isvirtual()) {
2077 { // the player has all cards of his hand in 'can_have'
2078 if (!this->can_have_.contains(this->player().hand().counted_cards())) {
2079 DEBUG_ASSERTION(false,
2080 "CardsInformation"
2081 << "(" << this->cards_information().player().no() << ")"
2082 << "::OfPlayer(" << this->playerno() << ")"
2083 << "::self_check()\n"
2084 " the cards of the hand are not contained in the can have cards.\n");
2085 return false;
2086 }
2087 } // the player has all cards of his hand in 'can_have'
2088 { // the player has all 'must_have' cards in his hand
2089 if (!this->must_have_.is_contained(this->player().hand().counted_cards())) {
2090 DEBUG_ASSERTION(false,
2091 "CardsInformation"
2092 << "(" << this->cards_information().player().no() << ")"
2093 << "::OfPlayer(" << this->playerno() << ")"
2094 << "::self_check()\n"
2095 " the must have cards are not contained in the cards of the hand.\n");
2096 return false;
2097 }
2098 } // the player has all 'must_have' cards in his hand
2099 } // if (!this->cards_information().is_virtual() && !this->game().isvirtual())
2100
2101
2102 // the player has to be able to play all 'must' cards
2103 if ( !(this->must_have_.cards_no() <= this->player().cards_to_play())) {
2104 DEBUG_ASSERTION(false,
2105 "CardsInformation"
2106 << "(" << this->cards_information().player().no() << ")"
2107 << "::OfPlayer(" << this->playerno() << ")"
2108 << "::self_check()\n"
2109 " playerno = " << this->playerno() << "\n"
2110 " must_have > cards to play:\n"
2111 << " " << this->must_have_.cards_no()
2112 << " > " << this->player().cards_to_play());
2113 return false;
2114 }
2115
2116 // check 'can have == cards to play' ==> 'can have == must have'
2117 if ( !( (this->can_have_.cards_no() != this->player().cards_to_play())
2118 || (this->can_have_.cards_no() == this->must_have_.cards_no()) ) ) {
2119 DEBUG_ASSERTION(false,
2120 "CardsInformation"
2121 << "(" << this->cards_information().player().no() << ")"
2122 << "::OfPlayer(" << this->playerno() << ")"
2123 << "::self_check()\n"
2124 " playerno = " << this->playerno() << "\n"
2125 " cards_to_play == can_have != must_have:\n"
2126 << " " << this->player().cards_to_play()
2127 << " == " << this->can_have_.cards_no()
2128 << " != " << this->must_have_.cards_no()
2129 );
2130 return false;
2131 }
2132
2133 // for each card check:
2134 for (auto
2135 c = this->game().rule().cards().begin();
2136 c != this->game().rule().cards().end();
2137 ++c) {
2138 unsigned played = this->cards_information().played(*c);
2139 { // played(player) <= played(all)
2140 if (played < this->played(*c)) {
2141 DEBUG_ASSERTION(false,
2142 "CardsInformation"
2143 << "(" << this->cards_information().player().no() << ")"
2144 << "::OfPlayer(" << this->playerno() << ")"
2145 << "::self_check()\n"
2146 " playerno = " << this->playerno() << "\n"
2147 " card '" << *c << "' has been played "
2148 << played << " times, but by the player "
2149 << this->playerno() << " '" << this->played(*c)
2150 << "' times");
2151 return false;
2152 }
2153 } // played(player) <= played(all)
2154
2155 unsigned const can_have = this->can_have(*c);
2156 { // check 'can have < must have'
2157 if ( !(can_have >= this->must_have(*c))) {
2158 DEBUG_ASSERTION(false,
2159 "CardsInformation"
2160 << "(" << this->cards_information().player().no() << ")"
2161 << "::OfPlayer(" << this->playerno() << ")"
2162 << "::self_check()\n"
2163 " playerno = " << this->playerno() << "\n"
2164 " card '" << *c << "': "
2165 "can_have = " << can_have << " < "
2166 "must_have = " << this->must_have_[*c]
2167 );
2168 return false;
2169 }
2170 } // check 'can have < must have'
2171
2172 { // check 'can have < cards to play'
2173 if ( !(can_have <= this->player().cards_to_play())) {
2174 DEBUG_ASSERTION(false,
2175 "CardsInformation"
2176 << "(" << this->cards_information().player().no() << ")"
2177 << "::OfPlayer(" << this->playerno() << ")"
2178 << "::self_check()\n"
2179 " playerno = " << this->playerno() << "\n"
2180 " card '" << *c << "': "
2181 "can_have = " << can_have << " > "
2182 "cards to play = " << this->player().cards_to_play()
2183 );
2184 return false;
2185 }
2186 } // check 'can have < cards to play'
2187
2188 { // check 'can have + played + sum must have <= #Cards'
2189 unsigned sum = 0;
2190 for (unsigned p = 0; p < this->game().playerno(); ++p)
2191 if (p != this->playerno())
2192 sum += this->cards_information().of_player(p).must_have(*c);
2193
2194 if (can_have + played + sum
2195 > this->game().rule()(Rule::Type::number_of_same_cards) ) {
2196 #ifdef DEBUG_ASSERT
2197 for (unsigned p = 0; p < this->game().playerno(); ++p) {
2198 if (p != this->playerno())
2199 if (this->cards_information().of_player(p).must_have(*c) > 0)
2200 cerr << p << ": must have = " << this->cards_information().of_player(p).must_have(*c) << endl;
2201 }
2202 #endif
2203 DEBUG_ASSERTION(false,
2204 "CardsInformation"
2205 << "(" << this->cards_information().player().no() << ")"
2206 << "::OfPlayer(" << this->playerno() << ")"
2207 << "::self_check()\n"
2208 " playerno = " << this->playerno() << "\n"
2209 " card '" << *c << "':\n"
2210 " can_have + played + Sum must_have > number_of_cards:\n"
2211 " "
2212 << can_have
2213 << " + " << played << " + " << sum << " > "
2214 << this->game().rule()(Rule::Type::number_of_same_cards)
2215 //<< "\ngame:\n{\n" << this->game() << "}\n"
2216 //<< "\n" << this->cards_information()
2217 );
2218
2219 return false;
2220 }
2221 } // check 'can have + played + sum must have <= #Cards'
2222 { // check 'can have(tcolor) >= can have'
2223 if (can_have > this->can_have(c->tcolor(this->game()))) {
2224 DEBUG_ASSERTION(false,
2225 "CardsInformation"
2226 << "(" << this->cards_information().player().no() << ")"
2227 << "::OfPlayer(" << this->playerno() << ")"
2228 << "::self_check()\n"
2229 " playerno = " << this->playerno() << "\n"
2230 " card '" << *c << "':\n"
2231 " can_have > can_have(tcolor):\n"
2232 " "
2233 << can_have << " > "
2234 << this->can_have(c->tcolor(this->game()))
2235 //<< "\ngame:\n{\n" << this->game() << "}\n"
2236 //<< "\n" << this->cards_information()
2237 );
2238
2239 return false;
2240 } // if (can_have < this->can_have(c->tcolor(this->game())))
2241 } // check 'can have(tcolor) >= can have'
2242 } // for (c \in cards)
2243
2244 { // checked '#played intern <= #played by player'
2245 unsigned played_cardno = 0;
2246 for (const auto & p : this->played_)
2247 played_cardno += p.second;
2248 unsigned const played_cardno_by_player
2249 = (this->game().tricks().max_size() - this->player().cards_to_play());
2250 if (played_cardno > played_cardno_by_player) {
2251 DEBUG_ASSERTION(false,
2252 "CardsInformation"
2253 << "(" << this->cards_information().player().no() << ")"
2254 << "::OfPlayer(" << this->playerno() << ")"
2255 << "::self_check()\n"
2256 " " << played_cardno << " cards are marked as played, "
2257 "but the player has played "
2258 << played_cardno_by_player
2259 << "\n" << this->game());
2260 return false;
2261 }
2262 } // checked '#played intern <= #played by player'
2263
2264 if ( !this->cards_information().is_virtual()
2265 && (&this->cards_information()
2266 == &this->cards_information().player().cards_information())
2267 ) {
2268 // check that all cards on the hand of the player are 'can_be'
2269 for (const auto & card : this->player().hand().cards()) {
2270 if (card != Card::unknown)
2271 DEBUG_ASSERTION((this->can_have(card)
2272 >= this->player().hand().count(card)),
2273 "CardsInformation"
2274 << "(" << this->cards_information().player().no() << ")"
2275 << "::OfPlayer(" << this->playerno() << ")"
2276 << "::self_check()\n"
2277 " card '" << card << "' is "
2278 << this->player().hand().count(card)
2279 << " times on the hand, but 'can have' = "
2280 << this->can_have(card));
2281 } // for (card \in this->player().hand().cards())
2282 } // if (!is_virtual_game)
2283
2284 } // cards
2285
2286 { // tcolor
2287
2288 // played in tcolor is as in cards
2289 if (!(this->tcolor_played_.cards_no() == this->played_.cards_no())) {
2290 DEBUG_ASSERTION(false,
2291 "CardsInformation"
2292 << "(" << this->cards_information().player().no() << ")"
2293 << "::OfPlayer(" << this->playerno() << ")"
2294 << "::self_check()\n"
2295 " playerno = " << this->playerno() << "\n"
2296 " tcolor played != played (cards):\n"
2297 << " " << this->tcolor_played_.cards_no()
2298 << " != " << this->played_.cards_no());
2299 return false;
2300 }
2301
2302 // the player has to be able to play all 'must' cards
2303 if (!(this->tcolor_must_have_.cards_no()
2304 <= this->player().cards_to_play())) {
2305 DEBUG_ASSERTION(false,
2306 "CardsInformation"
2307 << "(" << this->cards_information().player().no() << ")"
2308 << "::OfPlayer(" << this->playerno() << ")"
2309 << "::self_check()\n"
2310 " playerno = " << this->playerno() << "\n"
2311 " tcolor must_have > cards to play:\n"
2312 << " " << this->tcolor_must_have_.cards_no()
2313 << " > " << this->player().cards_to_play());
2314 return false;
2315 }
2316
2317 // the player has to have at least as many cards as he has to play
2318 if (!(this->tcolor_can_have_.cards_no()
2319 >= this->player().cards_to_play())) {
2320 DEBUG_ASSERTION(false,
2321 "CardsInformation"
2322 << "(" << this->cards_information().player().no() << ")"
2323 << "::OfPlayer(" << this->playerno() << ")"
2324 << "::self_check()\n"
2325 " playerno = " << this->playerno() << "\n"
2326 " tcolor can_have < cards to play:\n"
2327 << " " << this->tcolor_can_have_.cards_no()
2328 << " < " << this->player().cards_to_play());
2329 return false;
2330 }
2331 // the player has to be able to play all 'must' cards
2332 if (!(this->tcolor_must_have_.cards_no()
2333 <= this->player().cards_to_play())) {
2334 DEBUG_ASSERTION(false,
2335 "CardsInformation"
2336 << "(" << this->cards_information().player().no() << ")"
2337 << "::OfPlayer(" << this->playerno() << ")"
2338 << "::self_check()\n"
2339 " playerno = " << this->playerno() << "\n"
2340 " tcolor must_have > cards to play:\n"
2341 << " " << this->tcolor_must_have_.cards_no()
2342 << " > " << this->player().cards_to_play());
2343 return false;
2344 }
2345
2346 // check 'can have == cards to play' ==> 'can have == must have'
2347 if ( !( (this->tcolor_can_have_.cards_no()
2348 != this->player().cards_to_play())
2349 || (this->tcolor_can_have_.cards_no()
2350 == this->tcolor_must_have_.cards_no()) ) ) {
2351 DEBUG_ASSERTION(false,
2352 "CardsInformation"
2353 << "(" << this->cards_information().player().no() << ")"
2354 << "::OfPlayer(" << this->playerno() << ")"
2355 << "::self_check()\n"
2356 " playerno = " << this->playerno() << "\n"
2357 " cards_to_play == tcolor can_have != tcolor must_have:\n"
2358 << " " << this->player().cards_to_play()
2359 << " == " << this->tcolor_can_have_.cards_no()
2360 << " != " << this->tcolor_must_have_.cards_no()
2361 );
2362 return false;
2363 }
2364
2365 // for each tcolor check:
2366 for (unsigned c = 0; c < Card::number_of_tcolors; ++c) {
2367 Card::TColor const tcolor = static_cast<Card::TColor>(c);
2368 unsigned const played = this->cards_information().played(tcolor);
2369 { // played(player) <= played(all)
2370 if (played < this->played(tcolor)) {
2371 DEBUG_ASSERTION(false,
2372 "CardsInformation"
2373 << "(" << this->cards_information().player().no() << ")"
2374 << "::OfPlayer(" << this->playerno() << ")"
2375 << "::self_check()\n"
2376 " playerno = " << this->playerno() << "\n"
2377 " tcolor '" << tcolor << "' has been played "
2378 << played << " times, but by the player "
2379 << this->playerno() << " '" << this->played(tcolor)
2380 << "' times");
2381 return false;
2382 }
2383 } // played(player) <= played(all)
2384 unsigned const can_have = this->can_have(tcolor);
2385 { // check 'can have < must have'
2386 if ( !(can_have >= this->must_have(tcolor))) {
2387 DEBUG_ASSERTION(false,
2388 "CardsInformation"
2389 << "(" << this->cards_information().player().no() << ")"
2390 << "::OfPlayer(" << this->playerno() << ")"
2391 << "::self_check()\n"
2392 " playerno = " << this->playerno() << "\n"
2393 " tcolor '" << tcolor << "': "
2394 "can_have = " << can_have << " < "
2395 "must_have = " << this->must_have(tcolor)
2396 );
2397 return false;
2398 }
2399 } // check 'can have < must have'
2400
2401 { // check 'can have < cards to play'
2402 if ( !(can_have <= this->player().cards_to_play())) {
2403 DEBUG_ASSERTION(false,
2404 "CardsInformation"
2405 << "(" << this->cards_information().player().no() << ")"
2406 << "::OfPlayer(" << this->playerno() << ")"
2407 << "::self_check()\n"
2408 " playerno = " << this->playerno() << "\n"
2409 " tcolor '" << tcolor << "': "
2410 "can_have = " << can_have << " > "
2411 "cards to play = " << this->player().cards_to_play()
2412 );
2413 return false;
2414 }
2415 } // check 'can have < cards to play'
2416
2417 { // check 'can have + played + sum must have <= #Cards'
2418 unsigned sum = 0;
2419 for (unsigned p = 0; p < this->game().playerno(); ++p)
2420 if (p != this->playerno())
2421 sum += this->cards_information().of_player(p).must_have(tcolor);
2422
2423 if (can_have + played + sum > this->game().cards().count(tcolor) ) {
2424 #ifdef DEBUG_ASSERT
2425 for (unsigned p = 0; p < this->game().playerno(); ++p) {
2426 if (p != this->playerno())
2427 if (this->cards_information().of_player(p).must_have(tcolor) > 0)
2428 cerr << p << ": tcolor must have = " << this->cards_information().of_player(p).must_have(tcolor) << endl;
2429 }
2430 #endif
2431 DEBUG_ASSERTION(false,
2432 "CardsInformation"
2433 << "(" << this->cards_information().player().no() << ")"
2434 << "::OfPlayer(" << this->playerno() << ")"
2435 << "::self_check()\n"
2436 " playerno = " << this->playerno() << "\n"
2437 " tcolor '" << tcolor << "':\n"
2438 " can_have + played + sum must_have > possible number:\n"
2439 " "
2440 << can_have
2441 << " + " << played << " + " << sum << " > "
2442 << this->game().cards().count(tcolor)
2443 //<< "\ngame:\n{\n" << this->game() << "}\n"
2444 << "\n" << *this
2445 //<< "\n" << this->cards_information()
2446 );
2447
2448 return false;
2449 }
2450 } // check 'can have + played + sum must have <= #Cards'
2451 } // for (c \in tcolors)
2452
2453 } // tcolor
2454
2455 return true;
2456 } // bool CardsInformation::OfPlayer::self_check() const
2457