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 "ai.h"
31 #include "team_information.h"
32 #include "cards_information.h"
33 #include "heuristic_ai.h"
34 #include "virtual_games_ai.h"
35 #include "solo_decision.h"
36 
37 #include "heuristic.h"
38 #include "heuristics.h"
39 #include "weighting.h"
40 #include "aiDb.h"
41 #include "../../party/party.h"
42 #include "../../party/rule.h"
43 #include "../../card/trick.h"
44 #include "../../game/gameplay_actions.h"
45 #ifndef OUTDATED
46 // for 'nextcard()' errors
47 #include "../../misc/bug_report.h"
48 #include "../../os/bug_report.h"
49 #endif
50 #include "../../os/bug_report_replay.h"
51 #ifndef WORKAROUND
52 // for replaying old bug reports
53 #include "../../utils/version.h"
54 #endif
55 #ifdef CHECK_RUNTIME
56 #include "../../runtime.h"
57 #endif
58 
59 //#define DEBUG_PLAYER ((::party->game().tricks().current_no() == 8) ? 2 : 22)
60 #define DEBUG_PLAYER 33
61 
62 // whether to debug the game decision
63 #ifndef RELEASE
64 #define DEBUG_RESERVATION_PLAYER 9
65 #endif
66 #ifdef DEBUG_RESERVATION_PLAYER
67 #define DEBUG_RESERVATION(solo, value, max) \
68   if (this->no() == DEBUG_RESERVATION_PLAYER) { \
69     COUT << solo << ": " << value << (value == max ? " * " : "") << '\n'; \
70   } else (void)0
71 #else
72 #define DEBUG_RESERVATION(solo, value, max) (void)0
73 #endif
74 
75 /** construktor
76  **
77  ** @param    istr   stream with the infos
78  **
79  ** @todo      using constructor Aiconfig(istr)
80  ** @todo      update to the new format
81  **/
Ai(istream & istr)82 Ai::Ai(istream& istr) :
83   Player(Player::Type::ai),
84   trick_(::party->rule()(Rule::Type::number_of_tricks_in_game)),
85   colorjabbed_(::party->rule()(Rule::Type::number_of_card_colors),
86                 vector<bool>(::party->rule()(Rule::Type::number_of_players_in_game),
87                              false)),
88   vgi_(make_unique<VirtualGamesAi>(*this)),
89   hi_(make_unique<HeuristicAi>(*this))
90 {
91   this->db_ = make_unique<AiDb>();
92 
93   while (istr.good()) {
94     string line;
95     getline(istr, line);
96     if (istr.fail() || istr.eof())
97       break;
98 
99     if (*line.rbegin() == '\r')
100       line.erase(line.end() - 1);
101 
102     if ((line == "")
103         || (line[0] == '#')) {
104       continue;
105     }
106     if (   (line == "Aiconfig")
107         || (line == "aiconfig") ) {
108       // this is the last entry
109       this->Aiconfig::read(istr);
110       break;
111     } else if (line == "Database") {
112       this->db_->read(istr);
113     } else {
114       cerr << "Reading the ai:\n"
115         << "found following unknown line:\n"
116         << line << '\n'
117         << "ignoring it."
118         << endl;
119 #ifndef RELEASE
120       exit(EXIT_FAILURE);
121 #endif
122     }
123   }; // while (istr.good())
124 }
125 
126 /** standard constructor
127  **
128  ** @result    -
129  **/
Ai()130 Ai::Ai() :
131   Player(Player::Type::ai),
132   trick_(::party->rule()(Rule::Type::number_of_tricks_in_game)),
133   colorjabbed_(::party->rule()(Rule::Type::number_of_card_colors),
134                vector<bool>(::party->rule()(Rule::Type::number_of_players_in_game),
135                             false)),
136   vgi_(make_unique<VirtualGamesAi>(*this)),
137   hi_(make_unique<HeuristicAi>(*this))
138 {
139   this->db_ = make_unique<AiDb>();
140   for (auto const game_type : ::game_type_solo_list) {
141     this->solo_decisions_.emplace_back(SoloDecision::create(game_type, *this));
142   }
143 }
144 
145 /** constructor
146  **
147  ** @param    aiconfig   ai configuration
148  **
149  ** @result    -
150  **/
Ai(Aiconfig const & aiconfig)151 Ai::Ai(Aiconfig const& aiconfig) :
152   Player(Player::Type::ai),
153   Aiconfig(aiconfig),
154   trick_(::party->rule()(Rule::Type::number_of_tricks_in_game)),
155   colorjabbed_(::party->rule()(Rule::Type::number_of_card_colors),
156                vector<bool>(::party->rule()(Rule::Type::number_of_players_in_game),
157                             false)),
158   vgi_(make_unique<VirtualGamesAi>(*this)),
159   hi_(make_unique<HeuristicAi>(*this))
160 {
161   this->db_ = make_unique<AiDb>();
162   for (auto const game_type : ::game_type_solo_list) {
163     this->solo_decisions_.emplace_back(SoloDecision::create(game_type, *this));
164   }
165 }
166 
167 /** copy constructor
168  **
169  ** @param    player   player to copy
170  **/
Ai(Player const & player)171 Ai::Ai(Player const& player) :
172   Player(player),
173   trick_(::party->rule()(Rule::Type::number_of_tricks_in_game)),
174   colorjabbed_(::party->rule()(Rule::Type::number_of_card_colors),
175                vector<bool>(::party->rule()(Rule::Type::number_of_players_in_game),
176                             false)
177               ) ,
178   vgi_(make_unique<VirtualGamesAi>(*this)),
179   hi_(make_unique<HeuristicAi>(*this))
180 {
181   this->set_type(Player::Type::ai);
182   this->db_ = make_unique<AiDb>(player.db());
183   for (auto const game_type : ::game_type_solo_list) {
184     this->solo_decisions_.emplace_back(SoloDecision::create(game_type, *this));
185   }
186 }
187 
188 /** copy constructor
189  **
190  ** @param    player   player to copy
191  ** @param    aiconfig   configuration to copy
192  **/
Ai(Player const & player,Aiconfig const & aiconfig)193 Ai::Ai(Player const& player, Aiconfig const& aiconfig) :
194   Player(player),
195   Aiconfig(aiconfig),
196   trick_(::party->rule()(Rule::Type::number_of_tricks_in_game)),
197   colorjabbed_(::party->rule()(Rule::Type::number_of_card_colors),
198                vector<bool>(::party->rule()(Rule::Type::number_of_players_in_game),
199                             false)
200               ) ,
201   vgi_(make_unique<VirtualGamesAi>(*this)),
202   hi_(make_unique<HeuristicAi>(*this))
203 {
204   this->set_type(Player::Type::ai);
205 
206   if (::game_status & GameStatus::game)
207     DEBUG_ASSERTION(false,
208                     "Ai::Ai(player):\n"
209                     "  in game");
210 
211   this->db_ = make_unique<AiDb>(player.db());
212   for (auto const game_type : ::game_type_solo_list) {
213     this->solo_decisions_.emplace_back(SoloDecision::create(game_type, *this));
214   }
215 }
216 
217 /** copy constructor
218  **/
Ai(Ai const & ai)219 Ai::Ai(Ai const& ai) :
220   Player(ai),
221   Aiconfig(ai),
222 team_information_(ai.team_information_
223                   ? new TeamInformation(ai.team_information())
224                   : nullptr),
225 cards_information_(ai.cards_information_
226                    ? new CardsInformation(ai.cards_information())
227                    : nullptr),
228   teaminfo_(ai.teaminfo_),
229   trick_(ai.trick_),
230   trickno_(ai.trickno_),
231   colorjabbed_(ai.colorjabbed_),
232   low_(ai.low_),
233   meatlesscolor_(ai.meatlesscolor_),
234   trumpless_( ai.trumpless_ ),
235   last_trick_to_calculate_(ai.last_trick_to_calculate_),
236   last_heuristic_(ai.last_heuristic_),
237   last_heuristic_rationale_(ai.last_heuristic_rationale_),
238   vgi_(make_unique<VirtualGamesAi>(*this)),
239   hi_(make_unique<HeuristicAi>(*this)),
240   silent_marriage_(ai.silent_marriage_)
241 {
242   if (::game_status & GameStatus::game)
243     DEBUG_ASSERTION(!this->trumpless_.empty(),
244                     "Ai::Ai(ai):\n"
245                     "  'trumpless_.size() == 0");
246 
247   this->set_type(Player::Type::ai);
248   if (this->team_information_)
249     this->team_information_->set_player(*this);
250   if (this->cards_information_)
251     this->cards_information_->set_player(*this);
252 
253   if (ai.db())
254     this->db_ = make_unique<AiDb>(*ai.db());
255   else
256     this->db_ = make_unique<AiDb>();
257   for (auto const game_type : ::game_type_solo_list) {
258     this->solo_decisions_.emplace_back(SoloDecision::create(game_type, *this));
259   }
260 
261   if (::game_status & GameStatus::game) {
262     for (unsigned i = 0; i < this->colorjabbed_.size(); ++i) {
263       DEBUG_ASSERTION((ai.colorjabbed_[i].size() == this->game().playerno()),
264                       "Ai::Ai(ai)\n"
265                       "ai");
266       DEBUG_ASSERTION((this->colorjabbed_[i].size() == this->game().playerno()),
267                       "Ai::Ai(ai)\n"
268                       "this");
269     }
270   } // if (::game_status & GameStatus::game)
271 }
272 
273 /** destructor
274  **/
275 Ai::~Ai() = default;
276 
277 /** clone the player
278  **
279  ** @return   pointer of a clone
280  **/
281 unique_ptr<Player>
clone() const282 Ai::clone() const
283 {
284   return make_unique<Ai>(*this);
285 }
286 
287 /** cast to 'VirtualGamesInterface'
288  **/
operator VirtualGamesInterface const&() const289 Ai::operator VirtualGamesInterface const&() const
290 { return *this->vgi_; }
291 
292 /** cast to 'HeuristicInterface'
293  **/
operator HeuristicInterface const&() const294 Ai::operator HeuristicInterface const&() const
295 { return *this->hi_; }
296 
297 /** @return   the team information
298  **/
299 TeamInformation const&
team_information() const300 Ai::team_information() const
301 { return *this->team_information_; }
302 
303 /** @return   the team information
304  **/
305 TeamInformation&
team_information()306 Ai::team_information()
307 { return *this->team_information_; }
308 
309 /** @return   the cards information
310  **/
311 CardsInformation const&
cards_information() const312 Ai::cards_information() const
313 { return *this->cards_information_; }
314 
315 /** @return   the cards information
316  **/
317 CardsInformation&
cards_information()318 Ai::cards_information()
319 { return *this->cards_information_; }
320 
321 /** @return   the database
322  **/
323 AiDb const*
db() const324 Ai::db() const
325 { return dynamic_cast<AiDb const*>(this->db_.get()); }
326 
327 /** @return   the database
328  **/
329 AiDb*
db()330 Ai::db()
331 { return dynamic_cast<AiDb*>(db_.get()); }
332 
333 /** writes the ai into the stream
334  **
335  ** @param    ostr   stream the ai is to be written in
336  **
337  ** @return   the output stream
338  **/
339 ostream&
write(ostream & ostr) const340 Ai::write(ostream& ostr) const
341 {
342   // output of the name, type and database
343   this->Player::write(ostr);
344 
345   // output of the configuration
346   ostr << '\n'
347     << "Aiconfig\n"
348     << "{\n";
349   this->Aiconfig::write(ostr);
350   ostr << "}\n";
351 
352   return ostr;
353 }
354 
355 /** read the config of the player
356  **
357  ** @param    config   configuration to read
358  ** @param    istr   input stream
359  **
360  ** @return   whether the configuration was valid
361  **/
362 bool
read(Config const & config,istream & istr)363 Ai::read(Config const& config, istream& istr)
364 {
365   if (   !config.separator
366       && (   (config.name == "Aiconfig")
367           || (config.name == "aiconfig") ) ) {
368     return this->Aiconfig::read(istr);
369   }
370 
371   return this->Player::read(config, istr);
372 }
373 
374 /** compares the '*this' with 'ai'
375  **
376  ** @param    ai   ai to compare with
377  **
378  ** @return   whether 'ai' is equal to '*this'
379  **
380  ** @todo   test 'cards_information', 'team_information'
381  **/
382 bool
isequal(Ai const & ai) const383 Ai::isequal(Ai const& ai) const
384 {
385   // ToDo: test team_information
386   // ToDo: test cards_information
387 
388   if (this->colorjabbed_.size() != ai.colorjabbed_.size())
389     return false;
390 
391   for (unsigned i = 0; i < this->colorjabbed_.size(); i++) {
392     if (this->colorjabbed_[i].size() != ai.colorjabbed_[i].size())
393       return false;
394 
395     for (unsigned j = 0; j < this->colorjabbed_[i].size(); j++)
396       if (this->colorjabbed_[i][j] != ai.colorjabbed_[i][j])
397         return false;
398   } // for (i < this->colorjabbed_.size())
399 
400   if (this->trumpless_.size() != ai.trumpless_.size())
401     return false;
402 
403   for (unsigned i = 0; i < this->trumpless_.size(); i++)
404     if (this->trumpless_[i] != ai.trumpless_[i])
405       return false;
406 
407   if (this->trickno_ != ai.trickno_)
408     return false;
409 
410   if (this->low_ != ai.low_)
411     return false;
412 
413   if (this->meatlesscolor_ != ai.meatlesscolor_)
414     return false;
415 
416   if (this->last_trick_to_calculate_ != ai.last_trick_to_calculate_)
417     return false;
418 
419   if (this->last_heuristic_ != ai.last_heuristic_)
420     return false;
421 
422   if (this->last_heuristic_rationale_ != ai.last_heuristic_rationale_)
423     return false;
424 
425 #if 0
426   vector<Trick> trick_; // last played tricks
427 #endif
428 
429   return true;
430 }
431 
432 /** @return   the aitype for the current trick
433  **/
434 AiType
aitype() const435 Ai::aitype() const
436 {
437 #ifdef RELEASE
438   // Workaround
439   if( !( (::game_status >= GameStatus::game_play)
440         && (::game_status < GameStatus::game_finished) ))
441     return this->Aiconfig::aitype(0);
442 #else
443   DEBUG_ASSERTION( (::game_status >= GameStatus::game_play)
444                   && (::game_status < GameStatus::game_finished),
445                   "Ai::aitype():\n"
446                   "  game status not in game: " << ::game_status);
447 #endif
448 
449   return this->Aiconfig::aitype(this->game().tricks().current().no());
450 }
451 
452 /** @return   the rating type for the current trick
453  **/
454 Rating::Type
rating() const455 Ai::rating() const
456 {
457 #ifdef RELEASE
458   // Workaround
459   if( !( (::game_status >= GameStatus::game_play)
460         && (::game_status < GameStatus::game_finished) ))
461     return this->Aiconfig::rating(0);
462 #else
463   DEBUG_ASSERTION( (::game_status >= GameStatus::game_play)
464                   && (::game_status < GameStatus::game_finished),
465                   "Ai::rating():\n"
466                   "  game status not in game: " << ::game_status);
467 #endif
468 
469   return this->Aiconfig::rating(this->game().tricks().current().no());
470 }
471 
472 /** sets the cards information
473  **
474  ** @param    cards_information   new cards information
475  **/
476 void
set_cards_information(CardsInformation const & cards_information)477 Ai::set_cards_information(CardsInformation const& cards_information)
478 {
479   if (this->cards_information_.get() == &cards_information)
480     return ;
481 
482   this->cards_information_ = make_unique<CardsInformation>(cards_information);
483   this->cards_information_->set_player(*this);
484 }
485 
486 /** @return   the future limit for the current trick
487  **/
488 unsigned
future_limit() const489 Ai::future_limit() const
490 {
491   DEBUG_ASSERTION( (::game_status >= GameStatus::game_play)
492                   && (::game_status < GameStatus::game_finished),
493                   "Ai::future_limit():\n"
494                   "  game status not in game: " << ::game_status);
495 
496   return this->Aiconfig::future_limit(this->game().tricks().current().no());
497 }
498 
499 /** sets the game of the ai
500  **
501  ** @param    game   the new game for the ai
502  **/
503 void
set_game(Game & game)504 Ai::set_game(Game& game)
505 {
506   //bool const old_isvirtual = this->game().isvirtual();
507   this->Player::set_game(game);
508 }
509 
510 /** sets the hand of the ai
511  **
512  ** @param    hand   new hand
513  **
514  ** @return   the hand
515  **/
516 Hand const&
set_hand(const Hand & hand)517 Ai::set_hand(const Hand& hand)
518 {
519   this->Player::set_hand(hand);
520   if (::game_status <= GameStatus::game_init)
521     return this->hand();
522   this->cards_information().set_hand(*this, hand);
523   this->team_information().update_teams();
524 
525   // how to start in the heuristic 'play low high'
526   this->low_ = (this->hand().count(Card::jack) >= this->hand().count(Card::queen) +2);
527 
528   return this->hand();
529 }
530 
531 /** the rule has changed
532  **
533  ** @param    type        rule type to have changed
534  ** @param    old_value   old value of the rule
535  **/
536 void
rule_changed(int const type,void const * const old_value)537 Ai::rule_changed(int const type, void const* const old_value)
538 {
539   this->Aiconfig::rule_changed(type, old_value);
540 }
541 
542 /** the game 'game' is opened
543  **
544  ** @param    game    opened game
545  **/
546 void
game_open(Game & game)547 Ai::game_open(Game& game)
548 {
549   this->Player::game_open(game);
550   this->team_information().reset();
551   this->cards_information().reset();
552 }
553 
554 /** the game is started
555  **/
556 void
game_start()557 Ai::game_start()
558 {
559   if (::game_status == GameStatus::game_redistribute)
560     return ;
561 
562   this->Player::game_start();
563 
564   { // in a poverty the hand can have changed
565     this->cards_information().reset();
566     this->cards_information().set_hand(*this, this->hand());
567   }
568 
569   this->team_information().game_start();
570   this->cards_information().game_start();
571   this->team_information().update_teams();
572 }
573 
574 /** the game is closed
575  **
576  ** @param    game   game that is closed
577  **/
578 void
game_close(Game const & game)579 Ai::game_close(Game const& game)
580 {
581   this->Player::game_close(game);
582 
583   this->team_information_ = {};
584   this->cards_information_ = {};
585 }
586 
587 /** -> result
588  ** - if 'Aiconfig::hands_known' the real hand of the player is returned
589  **   (independent on 'Rule::Type::show_all_hands')
590  ** - if not 'Aiconfig::hands_known' the hand is calculated,
591  **   see 'CardsInformation'
592  **
593  ** @param    player   player whose hand is returned
594  **
595  ** @result   hand of 'player'
596  **/
597 Hand const&
handofplayer(Player const & player) const598 Ai::handofplayer(Player const& player) const
599 {
600   if (   !this->game().isvirtual()
601       && (player == *this))
602     return this->hand();
603 
604   if (this->Aiconfig::value(Aiconfig::Type::hands_known))
605     return player.hand();
606 
607   // If it is the last trick and the player has already played a card,
608   // his hand is empty.
609   if (   (::game_status == GameStatus::game_play)
610       && (this->game().tricks().real_remaining_no() == 1)
611       && (this->game().tricks().current().cardno_of_player(player)
612           < this->game().tricks().current().actcardno()))
613     return player.hand();
614 
615 #ifndef RELEASE
616   Hand const& hand = this->cards_information().estimated_hand(player);
617   hand.self_check();
618   return hand;
619 #else
620   return this->cards_information().estimated_hand(player);
621 #endif
622 }
623 
624 /** the known team of the player
625  **/
626 Team
teamofplayer(Player const & player) const627 Ai::teamofplayer(Player const& player) const
628 {
629   // In the marriage case, as long as the teams are not determined,
630   // the player shall think that every other player is against him.
631   if (this->game().type() == GameType::marriage)
632     return this->teaminfo(player);
633 
634   if (this->Aiconfig::value(Aiconfig::Type::teams_known))
635     return player.team();
636 
637   return this->teaminfo( player );
638 }
639 
640 /** set the teams
641  **
642  ** @param    teams   teams of the players
643  **/
644 void
set_teams(vector<Team> const & teams)645 Ai::set_teams(vector<Team> const& teams)
646 {
647   this->team_information().set_teams(teams);
648   this->set_team(teams[this->no()]);
649 }
650 
651 /** the trick is opened
652  **
653  ** @param    trick   opened trick
654  **/
655 void
trick_open(Trick const & trick)656 Ai::trick_open(Trick const& trick)
657 {
658   this->cards_information().trick_open(trick);
659   this->team_information().update_teams();
660 }
661 
662 /** the trick is full
663  **
664  ** @param    trick   full trick
665  **/
666 void
trick_full(Trick const & trick)667 Ai::trick_full(Trick const& trick)
668 {
669   DEBUG_ASSERT( trick.isfull() );
670 
671   this->team_information().trick_full(trick);
672   this->cards_information().trick_full(trick);
673   this->team_information().update_teams();
674 
675   if( trick.startcard().istrump() ) {
676     for ( unsigned i = 0; i < trick.actcardno(); i++) {
677       if (!trick.card(i).istrump()) {
678         DEBUG_ASSERTION((this->trumpless_.size()
679                          > trick.player_of_card(i).no()),
680                         "Ai::trick_full(trick):\n"
681                         "  'this->trumpless_' is too small: "
682                         << this->trumpless_.size() << " <= "
683                         << trick.player_of_card(i).no());
684         this->trumpless_[ trick.player_of_card(i).no() ] = true;
685       }
686     }
687   }
688 }
689 
690 /** @return   card played by the ai
691  **/
692 HandCard
card_get()693 Ai::card_get()
694 {
695   auto const& current_trick = this->game().tricks().current();
696   auto const card = this->nextcard(current_trick);
697   HandCard const handcard(this->hand(), card);
698 
699   auto& swines = this->game().swines();
700   if (   handcard.possible_swine()
701       && swines.swines_announcement_valid(*this))
702     swines.swines_announce(*this);
703   if (   handcard.possible_hyperswine()
704       && swines.hyperswines_announcement_valid(*this))
705     swines.hyperswines_announce(*this);
706   { // ToDo: check for last chance to announce
707     auto announcement = this->announcement_request();
708     while (!!announcement) {
709       this->game().announcements().make_announcement(announcement, *this);
710       if (this->announcement() != announcement)
711         break;
712       announcement = this->announcement_request();
713     }
714   }
715   this->check_and_make_first_announcement(handcard);
716 
717   return handcard;
718 }
719 
720 /** @return   suggested card
721  **/
722 HandCard
card_suggestion()723 Ai::card_suggestion()
724 {
725   if (::bug_report_replay) {
726     static bool bug_report_flip = false;
727     if (this->last_heuristic_ != Aiconfig::Heuristic::bug_report)
728       bug_report_flip = true;
729     else
730       bug_report_flip ^= true;
731     if (bug_report_flip) {
732       this->set_last_heuristic_to_bug_report();
733       auto const card = ::bug_report_replay->next_card(*this);
734       if (   !card.is_empty()
735           && this->hand().contains(card)) {
736         return HandCard(this->hand(), card);
737       }
738     }
739   }
740   auto const& current_trick = this->game().tricks().current();
741   auto const card = this->nextcard(current_trick);
742 #ifndef RELEASE
743 #ifdef DKNOF
744   cout << "card suggestion: " << card << '\n'
745     << this->last_heuristic() << '\n'
746     << this->last_heuristic_rationale() << '\n';
747 #endif
748 #endif
749   return HandCard(this->hand(), card);
750 }
751 
752 /** 'player' has played the card 'card'
753  **
754  ** @param    card    played card
755  **/
756 void
card_played(HandCard const & card)757 Ai::card_played(HandCard const& card)
758 {
759   this->cards_information().card_played(card);
760   this->team_information().card_played(card);
761   this->team_information().update_teams();
762 
763   if( this->no() == DEBUG_PLAYER ) {
764     COUT << "card played " << card << endl;
765     COUT << "virtual = " << this->game().isvirtual() << endl;
766   }
767 
768   Player const& player = card.player();
769   Card::Color jabbed = Card::nocardcolor;
770 
771 
772   Trick t = player.game().tricks().current();
773 
774   if (!t.startcard().istrump())
775   {
776     jabbed = t.startcard().color();
777   }
778 
779 
780   if (jabbed!=Card::nocardcolor && card.istrump())
781   {
782     colorjabbed_[jabbed][player.no()] = true;
783   }
784   if(   jabbed != Card::nocardcolor
785      && card.color() != jabbed
786      && (this->cards_information().remaining_trumps_others()
787          >=  game().tricks().remaining_no() ) )
788   {
789     colorjabbed_[jabbed][player.no()] = true;
790   }
791 
792 
793   if (player == *this) {
794     switch (this->last_heuristic_) {
795     case Aiconfig::Heuristic::low_high:
796     case Aiconfig::Heuristic::color_low_high:
797       if (! (   this->low_
798              && (this->game().tricks().current().winnerplayer() == *this)) )
799         this->check_low_high(card);
800       break;
801 
802     default:
803       break;
804     }
805     if(  this->hand().count(Card::jack) >= this->hand().count(Card::queen) +2 )
806       this->low_ = true;
807   } // if (player == *this)
808 
809   this->teaminfo_update();
810 }
811 
812 /** check a swines announcement at the game start
813  **/
814 void
check_swines_announcement_at_game_start()815 Ai::check_swines_announcement_at_game_start()
816 {
817   if (this->type() == Player::Type::ai) {
818     // announce swines
819     if (this->game().rule()(Rule::Type::swines_announcement_begin))
820       if (this->game().swines().swines_announcement_valid(*this))
821         this->game().swines().swines_announce(*this);
822 
823     // hyperswines are announced by 'Ai::swines_announced(player)'
824   } // if (this->type() == Player::Type::ai)
825 }
826 
827 /** 'player' has announce swines
828  ** if possible announce hyperswines
829  **
830  ** @param    player   player that has announced the swines
831  **/
832 void
swines_announced(Player const & player)833 Ai::swines_announced(Player const& player)
834 {
835   this->cards_information().swines_announced(player);
836   this->team_information().update_teams();
837 
838   if (this->type() == Player::Type::ai) {
839     if (   this->game().swines().hyperswines_announcement_valid(*this)
840         && this->game().rule()(Rule::Type::hyperswines_announcement_begin))
841       this->game().swines().hyperswines_announce(*this);
842   } // if (this->type() == Player::Type::ai)
843 }
844 
845 /** 'player' has announce hyperswines
846  **
847  ** @param    player   player that has announced the hyperswines
848  **/
849 void
hyperswines_announced(Player const & player)850 Ai::hyperswines_announced(Player const& player)
851 {
852   this->cards_information().hyperswines_announced(player);
853   this->team_information().update_teams();
854 }
855 
856 /** the marriage partner has found a bride
857  ** if the bride is the bridegroom, the bridegroom must play a solo
858  **
859  ** @param    bridegroom   the player with the marriage
860  ** @param    bride   the bride
861  **/
862 void
marriage(Player const & bridegroom,Player const & bride)863 Ai::marriage(Player const& bridegroom, Player const& bride)
864 {
865   this->team_information().marriage(bridegroom, bride);
866   this->teaminfo_update();
867 }
868 
869 /** a player has a genscher and selected a new partner
870  **
871  ** @param    genscher   genscher player
872  ** @param    partner   partner of the gensher player
873  **/
874 void
genscher(Player const & genscher,Player const & partner)875 Ai::genscher(Player const& genscher, Player const& partner)
876 {
877   this->team_information().genscher(genscher, partner);
878   this->cards_information().genscher(genscher, partner);
879   this->team_information().update_teams();
880 }
881 
882 /** selects a card to play
883  **
884  ** @param    trick   current trick
885  **
886  ** @return   card to play
887  **/
888 Card
nextcard(Trick const & trick)889 Ai::nextcard(Trick const& trick)
890 {
891   if (!this->game().isvirtual())
892     db()->increase( Aiconfig::Heuristic::no_heuristic );
893 
894 #ifdef CHECK_RUNTIME
895     auto const ssp = (  !this->game().isvirtual()
896                       ? ::runtime["ai heuristics"].start_stop_proxy()
897                       : nullptr);
898 #endif
899 
900     // special case: unset marriage and last chance
901     if (   (this->game().type() == GameType::marriage)
902         && (this->game().players().soloplayer() == *this)
903         && (this->game().marriage().selector() != MarriageSelector::silent)
904         && (this->game().marriage().selector() != MarriageSelector::team_set)
905         && (this->game().tricks().current().isempty())
906         && (this->game().tricks().current_no() + 1 == this->game().rule()(Rule::Type::marriage_determination)) ) {
907       Card const card = Heuristics::play_to_get_married(trick, *this);
908       if (card) {
909         this->last_heuristic_ = Aiconfig::Heuristic::play_to_get_married;
910         this->last_heuristic_rationale_.clear();
911         this->db()->increase(Aiconfig::Heuristic::play_to_get_married);
912         return card;
913       }
914     }
915 
916     auto
917       heuristics_vector = (  this->silent_marriage_
918                            ? (this->heuristic_states(HeuristicsMap::GameTypeGroup::marriage_silent,
919                                                      HeuristicsMap::PlayerTypeGroup::re))
920                            : this->heuristic_states(HeuristicsMap::Key(*this)));
921     heuristics_vector.insert(heuristics_vector.begin(),
922                              {Heuristic::only_one_valid_card, true});
923     heuristics_vector.insert(heuristics_vector.begin(),
924                              {Heuristic::bug_report, true});
925     for (auto const& heuristic_state : heuristics_vector) {
926       if (!heuristic_state.active)
927         continue;
928       auto const heuristic = heuristic_state.heuristic;
929       if (heuristic == Aiconfig::Heuristic::error) {
930         continue;
931       }
932 
933       auto heuristic_logic = ::Heuristic::create(heuristic, *this);
934       DEBUG_ASSERTION(heuristic_logic->heuristic() == heuristic,
935                       "Heuristic " << heuristic << " is of the wrong type");
936       heuristic_logic->set_player(*this);
937       auto const card = heuristic_logic->get_card(trick);
938       if (   !this->game().isvirtual()
939           && (   ::debug("heuristics")
940               || ::debug(to_string(heuristic)))) {
941         cout << this->no() << ' ' << this->name() << ": " << card << " (" << heuristic << ")\n";
942         cout << heuristic_logic->rationale();
943       }
944 
945       if (!card)
946         continue;
947       if (   HEURISTIC_OUTPUT
948           && !this->game().isvirtual()) {
949         cout <<  setw(2) << this->no() << " "
950           << setw(20) << card << " "
951           << heuristic
952           << endl;
953       }
954 
955       if (   (heuristic == Aiconfig::Heuristic::try_for_doppelkopf)
956           && (this->announcement() == Announcement::noannouncement)
957           && !trick.islastcard()
958           && (this->teaminfo(trick.player_of_card(this->game().playerno()))
959               != ::opposite(this->team()))) {
960         // make an announcement so that the player behind can give points
961         this->game().announcements().make_announcement(Announcement::no120, *this);
962       }
963 
964       this->last_heuristic_ = heuristic;
965       this->last_heuristic_rationale_ = heuristic_logic->rationale();
966       this->db()->increase(heuristic);
967 
968       return card;
969     } // for (heuristic_state : heuristics_vector)
970 
971   { // choosebestcard
972 
973     auto const heuristic = Aiconfig::Heuristic::choose_best_card;
974     auto const card = Weighting::best_card(this->aitype(), *this);
975 
976     if (HEURISTIC_OUTPUT
977         && !this->game().isvirtual())
978       cout <<  setw(2) << this->no() << " "
979         << setw(16) << card << " "
980         << setw(39) << heuristic << " (" << this->aitype() << ") "
981         << endl;
982 
983     this->last_heuristic_ = heuristic;
984     this->last_heuristic_rationale_.clear();
985     // only increment, if the ai could select a heuristic
986     if (static_cast<int>(this->game().tricks().remaining_no()) >
987         this->Aiconfig::value(Aiconfig::Type::last_tricks_without_heuristics ) ) {
988       this->db()->increase(heuristic);
989     }
990 
991     if (::game_status != GameStatus::game_play)
992       return Card();
993 
994     if (this->aitype() != AiType::no_choosebestcard)
995       DEBUG_ASSERT(!card.is_empty());
996 
997     return card;
998   } // choosebestcard
999 }
1000 
1001 /** @return   the last heuristic
1002  **/
1003 Aiconfig::Heuristic
last_heuristic() const1004 Ai::last_heuristic() const
1005 {
1006   return this->last_heuristic_;
1007 }
1008 
1009 /** @return   the rationale of the last heuristic
1010  **/
1011 Rationale const&
last_heuristic_rationale() const1012 Ai::last_heuristic_rationale() const
1013 {
1014   return this->last_heuristic_rationale_;
1015 }
1016 
1017 /** set the last heuristic to manual
1018  **/
1019 void
set_last_heuristic_to_manual()1020 Ai::set_last_heuristic_to_manual()
1021 {
1022   this->last_heuristic_ = Aiconfig::Heuristic::manual;
1023   this->last_heuristic_rationale_.clear();
1024 }
1025 
1026 /** set the last heuristic to bug report
1027  **/
1028 void
set_last_heuristic_to_bug_report()1029 Ai::set_last_heuristic_to_bug_report()
1030 {
1031   this->last_heuristic_ = Aiconfig::Heuristic::bug_report;
1032   this->last_heuristic_rationale_.clear();
1033 }
1034 
1035 /** @return   whether a player has jabbed the color
1036  **/
1037 bool
colorjabbed(Card::Color const color) const1038 Ai::colorjabbed(Card::Color const color) const
1039 {
1040   if (color == Card::nocardcolor)
1041     return false;
1042 
1043   for (unsigned i = 0; i < game().playerno(); ++i) {
1044     if (colorjabbed_[color][i])
1045       return true;
1046   }
1047 
1048   return false;
1049 }
1050 
1051 /** @return   whether the color has been jabbed by the own team
1052  **/
1053 bool
jabbedbyownteam(Card::Color const color) const1054 Ai::jabbedbyownteam(Card::Color const color) const
1055 {
1056   if (color == Card::nocardcolor)
1057     return false;
1058 
1059   auto const team = this->team();
1060   auto const& game = this->game();
1061   for (unsigned i = 0; i < game.playerno(); ++i) {
1062     if (   (i != this->no())
1063         && maybe_to_team(this->teaminfo(game.player(i))) == team) {
1064       if (colorjabbed_[color][i])
1065         return true;
1066     }
1067   }
1068 
1069   return false;
1070 }
1071 
1072 /** @return   whether the color was jabbed by the other team
1073  **/
1074 bool
jabbedbyotherteam(Card::Color const color) const1075 Ai::jabbedbyotherteam(Card::Color const color) const
1076 {
1077   if (color == Card::nocardcolor)
1078     return false;
1079 
1080   auto const team = this->team();
1081   auto const& game = this->game();
1082   for (unsigned i = 0; i < game.playerno(); ++i) {
1083     if (   (i != this->no())
1084         && (maybe_to_team(teaminfo(game.player(i))) != team)) {
1085       if (colorjabbed_[color][i])
1086         return true;
1087     }
1088   }
1089 
1090   return false;
1091 }
1092 
1093 /** -> result
1094  **
1095  ** @param    color   color
1096  **
1097  ** @return   how many times the color has run
1098  **/
1099 unsigned
color_runs(Card::Color const color) const1100 Ai::color_runs(Card::Color const color) const
1101 {
1102   return this->cards_information().color_runs(color);
1103 }
1104 
1105 /** -> result
1106  **
1107  ** @param    trick   current trick
1108  **
1109  ** @return   how many times the color of the trick has run
1110  **/
1111 unsigned
color_runs(Trick const & trick) const1112 Ai::color_runs(Trick const& trick) const
1113 {
1114   DEBUG_ASSERTION(!trick.isempty(),
1115                   "Ai::color_runs(trick)\n"
1116                   "  trick is empty");
1117   return this->cards_information().color_runs(trick.startcard().tcolor());
1118 }
1119 
1120 /** @return   whether the next card should be a low trump
1121  **/
1122 bool
next_low() const1123 Ai::next_low() const
1124 {
1125   return this->low_;
1126 }
1127 
1128 /** sets low_ to true if c>=diamond queen to false if card < diamond queen
1129  **/
1130 void
check_low_high(HandCard const & card)1131 Ai::check_low_high(HandCard const& card)
1132 {
1133   if (   card.istrump()
1134       && !(card.less(Card::diamond_queen)))
1135     this->low_ = true;
1136   else
1137     this->low_ = false;
1138 }
1139 
1140 /** initialize the ai for a new game
1141  **/
1142 void
new_game(Game & game)1143 Ai::new_game(Game& game)
1144 {
1145   this->Player::new_game(game);
1146 
1147   this->team_information_ = make_unique<TeamInformation>(*this);
1148   this->cards_information_ = make_unique<CardsInformation>(*this);
1149 
1150   this->teaminfo_ = vector<Team>(this->game().playerno(), Team::unknown);
1151 
1152   this->meatlesscolor_ = Card::nocardcolor;
1153 
1154   this->low_ = true;
1155 
1156   this->trick_ = vector<Trick>(this->game().rule()(Rule::Type::number_of_tricks_in_game));
1157 
1158   this->trumpless_ = vector<bool>(this->game().playerno(), false );
1159   this->trickno_ = 0;
1160   for ( unsigned x = 0;
1161        x < this->game().rule()(Rule::Type::number_of_card_colors); x++)
1162   {
1163     this->colorjabbed_[x] =  vector<bool>(this->game().playerno(), false );
1164     for(unsigned y = 0; y < this->game().playerno(); y++) {
1165       this->colorjabbed_[x][y] = false;
1166     } // for (y < this->game().playerno())
1167   } // for (x < this->game().playerno())
1168 
1169   this->silent_marriage_ = false;
1170 }
1171 
1172 /** @return   tricktype which determines teams for a marraige
1173  **/
1174 MarriageSelector
get_Marriage() const1175 Ai::get_Marriage() const
1176 {
1177   bool const isstartplayer = (this->game().startplayer() == *this);
1178   // ToDo: Test rules
1179   if (this->game().rule()(Rule::Type::marriage_first_foreign))
1180     return MarriageSelector::first_foreign;
1181 
1182   if (hand().count_trumps()<6
1183       && hand().count_trump_aces()==1
1184       && (   isstartplayer
1185           || this->game().rule()(Rule::Type::marriage_determination) >= 4)) {
1186     return MarriageSelector::first_trump;
1187   }
1188 
1189   if (Card::heart_ten.istrump(this->game())) {
1190     if (   hand().count(Card::heart) > 3
1191         && hand().count(Card::heart_ace) > 0) {
1192       return MarriageSelector::first_heart;
1193     }
1194   } else {
1195     if (   hand().count(Card::heart) > 4
1196         || (   hand().count(Card::heart) < 2
1197             && (  (   hand().count(Card::heart_ten) == 1
1198                    && isstartplayer)
1199                )
1200            )
1201        ) {
1202       return MarriageSelector::first_heart;
1203     }
1204   }
1205   if (  hand().count(Card::club) > 4
1206       || (   hand().count(Card::club) < 2
1207           && (   (   hand().count(Card::club_ten) == 1
1208                   && isstartplayer)
1209              )
1210          )
1211      ) {
1212     return MarriageSelector::first_club;
1213   }
1214   if (  hand().count(Card::spade) > 4
1215       || (   hand().count(Card::spade) < 2
1216           &&  (   hand().count(Card::spade_ten) == 1
1217                && isstartplayer)
1218          )
1219      ) {
1220     return MarriageSelector::first_spade;
1221   }
1222   if (   hand().count(Card::heart) == 1
1223       && hand().count(Card::heart_ace) != 1
1224       && isstartplayer) {
1225     return MarriageSelector::first_heart;
1226   }
1227   if (   hand().count(Card::club) == 1
1228       && hand().count(Card::club_ace) != 1
1229       && isstartplayer) {
1230     return MarriageSelector::first_club;
1231   }
1232   if (   hand().count(Card::spade) == 1
1233       && hand().count(Card::spade_ace) != 1
1234       && isstartplayer) {
1235     return MarriageSelector::first_spade;
1236   }
1237 
1238 
1239 
1240   if (   hand().count_trumps() >= 8
1241       && !isstartplayer) {
1242     return MarriageSelector::first_color;
1243   }
1244 
1245   return MarriageSelector::first_foreign;
1246 }
1247 
1248 /** -> result
1249  **
1250  ** @param    isDuty   whether the player must play a duty solo
1251  **                     (has no effect, yet)
1252  **
1253  ** @result    the reservation of the ai
1254  **/
1255 Reservation const&
reservation_get(bool const isDuty)1256 Ai::reservation_get( bool const isDuty )
1257 {
1258   this->team_information().reset();
1259   this->cards_information().reset();
1260   auto& reservation = this->reservation();
1261 
1262   { // bug report replay
1263     if (   ::bug_report_replay
1264         && ::bug_report_replay->auto_action()
1265         && (::bug_report_replay->current_action().type()
1266             == GameplayActions::Type::reservation)
1267         && (dynamic_cast<GameplayActions::Reservation const&>(::bug_report_replay->current_action()).player
1268             == this->no())
1269        ) {
1270       return (this->reservation() = dynamic_cast<GameplayActions::Reservation const&>(::bug_report_replay->current_action()).reservation);
1271     } // if (auto execute)
1272   } // bug report replay
1273 
1274   reservation = this->reservation_get_default();
1275 
1276   auto const& rule = this->game().rule();
1277 
1278   // check, whether to announce 'richness'
1279   if (reservation.game_type == GameType::thrown_richness) {
1280     if (Heuristics::make_announcement(*this))
1281       reservation.game_type = GameType::normal;
1282   }
1283 
1284   { // decide solo game
1285     SoloDecision::Points max_points = 120;
1286     if (   this->game().is_duty_solo()
1287         && *this == this->game().startplayer()) {
1288       max_points = INT_MIN;
1289     }
1290     GameType best_game_type = GameType::normal;
1291     // first all duty soli
1292     for (auto& decision : this->solo_decisions_) {
1293       auto const game_type = decision->game_type();
1294       if (!rule(game_type))
1295         continue;
1296       if (!this->is_remaining_duty_solo(game_type))
1297         continue;
1298       decision->set_player(*this);
1299       auto const points = decision->estimated_points();
1300       if (points > max_points) {
1301         best_game_type = game_type;
1302         max_points = points;
1303         DEBUG("solo decision rationale") << this->name() << ": " << decision->game_type() << ": " << points << " points\n"
1304           << decision->rationale() << '\n';
1305       }
1306     }
1307     max_points = 120;
1308     if (best_game_type == GameType::normal) {
1309       // lust solo games
1310       for (auto& decision : this->solo_decisions_) {
1311         auto const game_type = decision->game_type();
1312         if (!rule(game_type))
1313           continue;
1314         if (this->is_remaining_duty_solo(game_type))
1315           continue;
1316         decision->set_player(*this);
1317         auto const points = decision->estimated_points();
1318         if (points > max_points) {
1319           best_game_type = game_type;
1320           max_points = points;
1321           DEBUG("solo decision rationale") << this->name() << ": " << decision->game_type() << ": " << points << " points\n"
1322             << decision->rationale() << '\n';
1323         }
1324       }
1325     }
1326     if (best_game_type != GameType::normal) {
1327       reservation.game_type = best_game_type;
1328       if (is_color_solo(best_game_type)) {
1329         reservation.swines = true;
1330         reservation.hyperswines = true;
1331       }
1332     }
1333   }
1334 
1335 #ifndef OLD
1336   if (reservation.game_type == GameType::marriage) {
1337     reservation.marriage_selector=get_Marriage();
1338 #ifndef POSTPONED
1339     // ToDo: to be removed
1340     if (!rule(reservation.marriage_selector))
1341       reservation.marriage_selector = this->reservation_get_default().marriage_selector;
1342 #endif
1343   }
1344 #endif
1345 
1346   // special case: with swines announced the player does not have a poverty
1347   if (   reservation.game_type == GameType::poverty
1348       && (this->hand().count_poverty_cards()
1349           > rule(Rule::Type::max_number_of_poverty_trumps)) ) {
1350     reservation.swines = false;
1351   }
1352 
1353   return reservation;
1354 }
1355 
1356 /** -> result
1357  **
1358  ** @param    player whose teaminfo is returned
1359  **
1360  ** @return   the team of the given player, as far as this player knows it
1361  **/
1362 Team
teaminfo(Player const & player) const1363 Ai::teaminfo(Player const& player) const
1364 {
1365   return this->team_information().team(player);
1366 }
1367 
1368 /** updates the information of the teams (uses the current trick)
1369  **
1370  ** @return   the known teams
1371  **/
1372 void
teaminfo_update()1373 Ai::teaminfo_update()
1374 {
1375   this->team_information().update_teams();
1376 }
1377 
1378 /** @return   the partner of the player, nullptr, if not known for sure
1379  **/
1380 Player const*
partner(Player const & player) const1381 Ai::partner(Player const& player) const
1382 {
1383   if (::game_status < GameStatus::game_play)
1384     return nullptr;
1385 
1386   if (!this->team_information().all_known())
1387     return nullptr;
1388 
1389   Player const* partner = nullptr;
1390 
1391   for (unsigned p = 0; p < this->game().playerno(); ++p) {
1392     if (   (p != player.no())
1393         && (this->teaminfo(this->game().player(p))
1394             == this->teaminfo(player))) {
1395       if (partner != nullptr)
1396         return nullptr; // more than one partner
1397       partner = &this->game().player(p);
1398     }
1399   } // for (p)
1400 
1401   return partner;
1402 }
1403 
1404 /** @return   the points the team has made
1405  **/
1406 unsigned
points_of_team() const1407 Ai::points_of_team() const
1408 {
1409   unsigned points = this->game().points_of_player(*this);
1410 
1411 
1412   if (this->team_information().all_known()) {
1413     for (unsigned p = 0; p < this->game().playerno(); ++p)
1414       if (   (p != this->no())
1415           && (this->team_information().team(p) == this->team()))
1416         points += this->game().points_of_player(p);
1417   } else if (this->team_information().guessed_partner() != nullptr) {
1418     // normal game, partner guessed
1419     points += this->game().points_of_player(*this->team_information().guessed_partner());
1420   } else { // if (no partner known)
1421     // add the lowest points of the players
1422     unsigned lowest_points = 240;
1423     for (unsigned p = 0; p < this->game().playerno(); ++p)
1424       if (   (p != this->no())
1425           && (this->game().points_of_player(p) < lowest_points))
1426         lowest_points = this->game().points_of_player(p);
1427     points += lowest_points;
1428   } // if (no partner known)
1429 
1430   return points;
1431 }
1432 
1433 /** -> result
1434  ** (uses Heuristics)
1435  **
1436  ** @see        Heuristics::make_announcement()
1437  ** @see        Heuristics::say_no90
1438  ** @see        Heuristics::say_no60
1439  ** @see        Heuristics::say_no30
1440  ** @see        Heuristics::say_no0
1441  **
1442  ** @return   announcement of the player
1443  **/
1444 Announcement
announcement_request() const1445 Ai::announcement_request() const
1446 {
1447   if (   ::bug_report_replay
1448       && ::bug_report_replay->auto_action()) {
1449     if (   (::bug_report_replay->current_action().type()
1450             == GameplayActions::Type::announcement)
1451         && (dynamic_cast<GameplayActions::Announcement const&>(::bug_report_replay->current_action()).player
1452             == this->no())
1453        ) {
1454       return dynamic_cast<GameplayActions::Announcement const&>(::bug_report_replay->current_action()).announcement;
1455     } // if (current action = announcement)
1456     return Announcement::noannouncement;
1457   } // if (bug report auto execute)
1458 
1459 
1460   Announcement res = Announcement::noannouncement;
1461 
1462   for (auto a : real_announcements) {
1463     // make the announcement as late as possible
1464     if (!this->game().announcements().last_chance_to_announce(a, *this))
1465       continue;
1466     switch(a) {
1467     case Announcement::noannouncement:
1468     case Announcement::reply:
1469     case Announcement::no120_reply:
1470     case Announcement::no90_reply:
1471     case Announcement::no60_reply:
1472     case Announcement::no30_reply:
1473     case Announcement::no0_reply:
1474       DEBUG_ASSERTION(false,
1475                       "Ai::announcement_request():\n"
1476                       "  wrong announcement in 'switch': "
1477                       << a);
1478       break;
1479     case Announcement::no120:
1480       if (Heuristics::make_announcement(*this))
1481         res = a;
1482       break;
1483     case Announcement::no90:
1484       if (Heuristics::say_no90(*this))
1485         res = a;
1486       break;
1487     case Announcement::no60:
1488       if (Heuristics::say_no60(*this))
1489         res = a;
1490       break;
1491     case Announcement::no30:
1492       if (Heuristics::say_no30(*this))
1493         res = a;
1494       break;
1495     case Announcement::no0:
1496       if (Heuristics::say_no0(*this))
1497         res = a;
1498       break;
1499     } // switch(a)
1500   } // for (a \in announcements)
1501 
1502   if ( ( res == Announcement::noannouncement )
1503       && this->game().tricks().current().isfull()
1504       && this->game().announcements().is_valid(Announcement::reply, *this) )
1505     res = Heuristics::make_reply(*this);
1506 
1507   return res;
1508 }
1509 
1510 /** check whether re/contra shall be announced to announce the team
1511  **
1512  ** @param   handcard   card that is to be played
1513  **/
1514 void
check_and_make_first_announcement(HandCard const & handcard)1515 Ai::check_and_make_first_announcement(HandCard const& handcard)
1516 {
1517   if (   ::bug_report_replay
1518       && ::bug_report_replay->auto_action()) {
1519     return ;
1520   }
1521 
1522   if (is_real(this->game().teaminfo().get(*this)))
1523     return ;
1524 
1525   if (!Heuristics::make_announcement(*this))
1526     return ;
1527 
1528   auto const& trick = this->game().tricks().current();
1529   // Make an announcement earlier so that the partner can pfund
1530   if (!trick.isjabbed(handcard))
1531     return ;
1532 
1533   if (!handcard.istrump()) {
1534     if (handcard.value() != Card::ace)
1535       return ;
1536     // first color run
1537     auto const color = handcard.tcolor();
1538     if (this->cards_information().played(handcard.tcolor())
1539         > trick.cards().count(color))
1540       return ;
1541   } else {
1542     if (   trick.isempty()
1543         || trick.startcard().istrump()) {
1544       if (handcard.less(this->trump_card_limit()))
1545         return ;
1546     } else {
1547       auto const color = trick.startcard().tcolor();
1548       if (this->cards_information().played(handcard.tcolor())
1549           > trick.cards().count(color))
1550         return ;
1551     }
1552   }
1553   this->game().announcements().make_announcement(Announcement::no120, *this);
1554 }
1555 
1556 /** the announcement 'announcement' has been made by player 'player'
1557  **
1558  ** @param    announcement   the announcement
1559  ** @param    player   the player, who has made the announcement
1560  **/
1561 void
announcement_made(Announcement const announcement,Player const & player)1562 Ai::announcement_made(Announcement const announcement,
1563                       Player const& player)
1564 {
1565   this->team_information().announcement_made(announcement, player);
1566   this->cards_information().announcement_made(announcement, player);
1567   this->team_information().update_teams();
1568 
1569   this->teaminfo_update();
1570 } // void Ai::announcement_made(Announcement announcement, Player player)
1571 
1572 /** @return   modificator for the end depth for calculating tricks
1573  **             in WVirtualGames
1574  **/
1575 unsigned
last_trick_to_calculate() const1576 Ai::last_trick_to_calculate() const
1577 {
1578   return this->last_trick_to_calculate_;
1579 }
1580 
1581 /** sets the parameter to the last trick to calculate
1582  **
1583  ** @param    last_trick_to_calculate   new value
1584  **
1585  ** @return   modificator for the end depth for calculating tricks
1586  **             in WVirtualGames
1587  **/
1588 void
set_last_trick_to_calculate(unsigned const last_trick_to_calculate)1589 Ai::set_last_trick_to_calculate(unsigned const last_trick_to_calculate)
1590 {
1591   this->last_trick_to_calculate_ = last_trick_to_calculate;
1592 }
1593 
1594 /** returns which cards the player shifts
1595  **
1596  ** @return   the cards that are to be shifted
1597  **/
1598 HandCards
poverty_shift()1599 Ai::poverty_shift()
1600 {
1601   DEBUG_ASSERTION(this->hand().count_trumps() <= 5,
1602                   "Ai::poverty_shift()\n"
1603                   "  more then 5 trumps:\n" << this->hand());
1604 
1605   { // bug report replay
1606     if (   ::bug_report_replay
1607         && ::bug_report_replay->auto_action()
1608         && (::bug_report_replay->current_action().type()
1609             == GameplayActions::Type::poverty_shift)
1610         && (dynamic_cast<GameplayActions::PovertyShift const&>(::bug_report_replay->current_action()).player == this->no())
1611        ) {
1612       HandCards const cards(this->hand(),
1613                             dynamic_cast<GameplayActions::PovertyShift const&>(::bug_report_replay->current_action()).cards);
1614       this->hand().remove(cards);
1615       return cards;
1616     } // if (auto execute)
1617   } // bug report replay
1618 
1619   Hand& hand = this->hand();
1620 
1621   HandCards res;
1622 
1623   // number of remaining cards to shift
1624   unsigned rem = hand.count_poverty_cards();
1625 
1626   for (auto const card : hand)
1627     if (card.istrump())
1628       res.push_back(card);
1629 
1630   hand.remove(res);
1631 
1632   DEBUG_ASSERTION((res.size() <= rem),
1633                   "Ai::poverty_shift()\n"
1634                   "  too many trumps: " << res.size() << " > " << rem << '\n'
1635                   << "  trumps found:\n"
1636                   << res);
1637   rem -= res.size();
1638 
1639   if (   !this->game().rule()(Rule::Type::poverty_shift_only_trump)
1640       && rem > 0) {
1641     HandCards addon;
1642 
1643     auto color = Card::heart;
1644     auto size = hand.count(color);
1645 
1646     if (hand.count(Card::spade) < size) {
1647       color = Card::spade;
1648       size = hand.count(color);
1649     }
1650 
1651     if (hand.count(Card::club) < size) {
1652       color = Card::club;
1653       size = hand.count(color);
1654     }
1655 
1656     Hand::Position p = 0;
1657     while (rem > 0) {
1658       if (p >= hand.cardsnumber())
1659         p = 0;
1660       auto const card = hand.card(p);
1661       if (size > 0) {
1662         if (card.color() == color) {
1663           addon.push_back(card);
1664           hand.remove(p);
1665           size--;
1666           rem--;
1667         }
1668       } else {
1669         addon.push_back(card);
1670         hand.remove(p);
1671         rem--;
1672       }
1673       p += 1;
1674     }
1675 
1676     res.insert(res.end(), addon.begin(), addon.end());
1677   }// !this->game().rule()( Rule::Type::poverty_shift_only_trump ) && rem > 0
1678 
1679   return res;
1680 }
1681 
1682 /** returns whether 'player' accepts the shifted cards
1683  **
1684  ** @param    cardno  the number of shifted cards
1685  **
1686  ** @return   whether to accept the cards
1687  **/
1688 bool
poverty_take_accept(unsigned const cardno)1689 Ai::poverty_take_accept(unsigned const cardno)
1690 {
1691   { // bug report replay
1692     if (   ::bug_report_replay
1693         && ::bug_report_replay->auto_action()) {
1694       if (   (::bug_report_replay->current_action().type()
1695               == GameplayActions::Type::poverty_accepted)
1696           && (dynamic_cast<GameplayActions::PovertyAccepted const&>(::bug_report_replay->current_action()).player == this->no()) )
1697         return true;
1698       if (   (::bug_report_replay->current_action().type()
1699               == GameplayActions::Type::poverty_denied)
1700           && (dynamic_cast<GameplayActions::PovertyDenied const&>(::bug_report_replay->current_action()).player == this->no()) )
1701         return false;
1702     } // if (auto execute)
1703   } // bug report replay
1704 
1705   unsigned trumpno_possible = cardno;
1706   if (!this->game().rule()(Rule::Type::poverty_shift_only_trump)) {
1707     if (!this->game().rule()(Rule::Type::throw_with_one_trump))
1708       trumpno_possible = 2;
1709     else
1710       trumpno_possible = 1;
1711   }
1712 
1713   int value = Heuristics::CalcHandValue( *this );
1714 
1715   if( this->hand().count_trumps() >= 12 - cardno )
1716     value += this->hand().count( Card::queen );
1717 
1718   std::multimap<unsigned, Card::Color> color_nums;
1719   for (auto const c : this->game().rule().card_colors()) {
1720     color_nums.insert(std::make_pair(this->hand().count(c), c));
1721   }
1722 
1723   for (auto const& c : color_nums) {
1724     if (c.first > trumpno_possible)
1725       break;
1726 
1727     value += 2;
1728     trumpno_possible -= c.first;
1729   }
1730   if( this->hand().count_trumps() >= 12 - cardno - 1 )
1731     value += (this->hand().count( Card::queen )
1732               + this->hand().count_trump_aces());
1733 
1734 
1735   if ( this->game().rule()(Rule::Type::dullen))
1736     value -= 4 - 2 * this->hand().count(Card::heart, Card::ten);
1737 
1738   value -= 4 - 2 * this->hand().count_club_queens();
1739   value -= 2 - this->hand().count(Card::spade, Card::queen);
1740 
1741 
1742   //COUT << no() << "\t" << value << "\t" << static_cast<signed>(this->value(Aiconfig::takepoverty)) << std::endl;
1743 
1744   return (value >= 15);
1745 }
1746 
1747 /** changes the cards from the poverty-player
1748  **
1749  ** @param    cards   the cards that are given to the player
1750  **
1751  ** @return   the cards that are returned to the poverty-player
1752  **/
1753 HandCards
poverty_cards_change(HandCards const & cards)1754 Ai::poverty_cards_change(HandCards const& cards)
1755 {
1756   { // bug report replay
1757     if (   ::bug_report_replay
1758         && ::bug_report_replay->auto_action()) {
1759       if (::bug_report_replay->current_action().type()
1760           == GameplayActions::Type::poverty_returned) {
1761         HandCards const reshifted_cards(this->hand(),
1762                                         dynamic_cast<GameplayActions::PovertyReturned const&>(::bug_report_replay->current_action()).cards);
1763         this->hand().add(cards);
1764         this->hand().remove(reshifted_cards);
1765         return reshifted_cards;
1766       }
1767     } // if (auto execute)
1768   } // bug report replay
1769 
1770   auto& hand = this->hand();
1771   hand.add(cards);
1772 
1773   HandCards res;
1774   unsigned rem = cards.size();
1775 
1776   // create Fehl for Heart
1777   if (   hand.count(Card::heart) > 0
1778       && hand.count(Card::heart) <= rem
1779       && this->game().rule()(Rule::Type::dullen)) {
1780     HandCards addon;
1781 
1782     for (auto const c : hand) {
1783       if (   c.color() == Card::heart
1784           && !c.istrump()) {
1785         addon.push_back(c);
1786       }
1787     }
1788     hand.remove(addon);
1789     res.insert(res.end(), addon.begin(), addon.end());
1790     rem -= addon.size();
1791   }
1792 
1793   // create Fehl for Club
1794   if( hand.count( Card::club ) > 0 && hand.count( Card::club ) <= rem )
1795   {
1796     bool ace_removed = false;
1797     if( hand.count( Card::club_ace ) == 2 )
1798     {
1799       hand.remove (Card::club_ace); // keep second ace.
1800       ace_removed = true;
1801     }
1802 
1803     HandCards addon;
1804     for( unsigned int i = 0; i < hand.cardsnumber(); i++ )
1805       if ( ( hand.card( i ).color() == Card::club ) && !hand.card(i).istrump() )
1806         addon.push_back( hand.card( i ) );
1807     hand.remove( addon );
1808     res.insert(res.end(), addon.begin(), addon.end());
1809     rem-= addon.size();
1810 
1811     if (ace_removed)
1812       hand.add( Card::club_ace );
1813   }
1814 
1815 
1816   // create Fehl for Spade
1817   if( hand.count( Card::spade ) > 0 && hand.count( Card::spade ) <= rem )
1818   {
1819     bool ace_removed = false;
1820     if( hand.count( Card::spade_ace ) == 2 )
1821     {
1822       hand.remove (Card::spade_ace); // keep second ace.
1823       ace_removed = true;
1824     }
1825 
1826     HandCards addon;
1827     for( unsigned int i = 0; i < hand.cardsnumber(); i++ )
1828       if( ( hand.card( i ).color() == Card::spade ) && !hand.card(i).istrump() )
1829         addon.push_back( hand.card( i ) );
1830     hand.remove( addon );
1831     res.insert(res.end(), addon.begin(), addon.end());
1832     rem-= addon.size();
1833 
1834     if (ace_removed)
1835       hand.add( Card::spade_ace );
1836   }
1837 
1838   // create Fehl for Heart
1839   if( hand.count( Card::heart ) > 0 && hand.count( Card::heart ) <= rem )
1840   {
1841 
1842     bool ace_removed = false;
1843     if( hand.count( Card::heart_ace ) == 2 )
1844     {
1845       hand.remove (Card::heart_ace); // keep second ace.
1846       ace_removed = true;
1847     }
1848     HandCards addon;
1849     for( unsigned int i = 0; i < hand.cardsnumber(); i++ )
1850       if( ( hand.card( i ).color() == Card::heart ) && !hand.card(i).istrump() )
1851         addon.push_back( hand.card( i ) );
1852     hand.remove( addon );
1853     res.insert(res.end(), addon.begin(), addon.end());
1854     rem-= addon.size();
1855 
1856     if (ace_removed)
1857       hand.add( Card::heart_ace );
1858   }
1859 
1860 
1861   while ( rem > 0 ) {
1862     //adding highest color card not ace
1863     if ( hand.count_trumps() < hand.cardsnumber()) {
1864       HandCard c;
1865       for( unsigned int i = 0; i < hand.cardsnumber(); i++ )
1866         if ( !hand.card( i ).istrump() )
1867           c = hand.card( i );
1868 
1869       if( !c.is_empty() )
1870       {
1871         for( unsigned int i = 0; i < hand.cardsnumber(); i++ )
1872           if ( !hand.card( i ).istrump() && c.less(hand.card( i )) )
1873             c = hand.card( i );
1874 
1875         hand.remove( c );
1876         res.push_back( c );
1877         rem--;
1878         continue;
1879       }
1880     }
1881 
1882     { // adding color card
1883       if (hand.count_trumps() < hand.cardsnumber()) {
1884         HandCard c;
1885         for (unsigned int i = 0; i < hand.cardsnumber(); i++) {
1886           if (!hand.card(i).istrump()) {
1887             c = hand.card(i);
1888           }
1889         }
1890 
1891         hand.remove(c);
1892         res.push_back(c);
1893         rem--;
1894         continue;
1895       }
1896     } // adding color card
1897 
1898     if (rem > 0 ) {
1899       // add low trump cards
1900       static vector<Card> const cards_to_check = {
1901         Card::diamond_nine,
1902         Card::diamond_king,
1903         Card::diamond_jack,
1904         Card::diamond_queen,
1905         Card::diamond_ten,
1906         Card::heart_jack,
1907         Card::spade_jack,
1908         Card::club_jack,
1909         Card::diamond_ace,
1910         Card::heart_queen,
1911         Card::spade_queen,
1912         Card::club_queen,
1913       };
1914 
1915       for (auto card = cards_to_check.begin(); rem > 0; ++card) {
1916         while ((hand.count(*card) > 0) && (rem > 0)) {
1917           auto c = HandCard(hand, *card);
1918           if (c.possible_swine() || c.possible_hyperswine() )
1919             break;
1920           hand.remove(c);
1921           res.push_back(c);
1922           rem--;
1923         }
1924       } // for (card)
1925     } // add low trump cards
1926 
1927   } // if ( rem > 0 )
1928 
1929   this->cards_information().reset();
1930   this->set_hand(hand); // to update the cards information
1931 
1932   return res;
1933 }
1934 
1935 
1936 /** gets the cards from the partner and add them to the hand
1937  **
1938  ** @param    cards   the cards that are given to the player
1939  **/
1940 void
poverty_cards_get_back(HandCards const & cards)1941 Ai::poverty_cards_get_back(HandCards const& cards)
1942 {
1943   this->hand().add(cards);
1944   this->cards_information().reset();
1945   this->set_hand(this->hand()); // to update the cards information
1946 }
1947 
1948 
1949 /**  @return   limit card for some heuristic decisions
1950  **/
1951 Card
trump_card_limit() const1952 Ai::trump_card_limit() const
1953 {
1954   if (this->silent_marriage_)
1955     return this->Aiconfig::value(Aiconfig::Type::trumplimit_solocolor);
1956 
1957   switch (this->game().type()) {
1958   case GameType::solo_club:
1959   case GameType::solo_heart:
1960   case GameType::solo_spade:
1961   case GameType::solo_diamond:
1962     return this->Aiconfig::value(Aiconfig::Type::trumplimit_solocolor);
1963   case GameType::solo_jack:
1964     return this->Aiconfig::value(Aiconfig::Type::trumplimit_solojack);
1965   case GameType::solo_queen:
1966     return this->Aiconfig::value(Aiconfig::Type::trumplimit_soloqueen);
1967   case GameType::solo_king:
1968     return this->Aiconfig::value(Aiconfig::Type::trumplimit_soloking);
1969   case GameType::solo_queen_jack:
1970     return this->Aiconfig::value(Aiconfig::Type::trumplimit_solojackqueen);
1971   case GameType::solo_king_jack:
1972     return this->Aiconfig::value(Aiconfig::Type::trumplimit_solojackking);
1973   case GameType::solo_king_queen:
1974     return this->Aiconfig::value(Aiconfig::Type::trumplimit_soloqueenking);
1975   case GameType::solo_koehler:
1976     return this->Aiconfig::value(Aiconfig::Type::trumplimit_solokoehler);
1977   case GameType::solo_meatless:
1978     return this->Aiconfig::value(Aiconfig::Type::trumplimit_meatless);
1979   default:
1980     return this->Aiconfig::value(Aiconfig::Type::trumplimit_normal);
1981   }
1982 }
1983 
1984 /** @return   limit card for some heuristic decisions
1985  **/
1986 Card
lowest_trump_card_limit() const1987 Ai::lowest_trump_card_limit() const
1988 {
1989   if (this->silent_marriage_)
1990     return this->Aiconfig::value(Aiconfig::Type::lowest_trumplimit_solocolor);
1991 
1992   switch (this->game().type()) {
1993   case GameType::solo_club:
1994   case GameType::solo_heart:
1995   case GameType::solo_spade:
1996   case GameType::solo_diamond:
1997     return this->Aiconfig::value(Aiconfig::Type::lowest_trumplimit_solocolor);
1998   case GameType::solo_jack:
1999     return this->Aiconfig::value(Aiconfig::Type::lowest_trumplimit_solojack);
2000   case GameType::solo_queen:
2001     return this->Aiconfig::value(Aiconfig::Type::lowest_trumplimit_soloqueen);
2002   case GameType::solo_king:
2003     return this->Aiconfig::value(Aiconfig::Type::lowest_trumplimit_soloking);
2004   case GameType::solo_queen_jack:
2005     return this->Aiconfig::value(Aiconfig::Type::lowest_trumplimit_solojackqueen);
2006   case GameType::solo_king_jack:
2007     return this->Aiconfig::value(Aiconfig::Type::lowest_trumplimit_solojackking);
2008   case GameType::solo_king_queen:
2009     return this->Aiconfig::value(Aiconfig::Type::lowest_trumplimit_soloqueenking);
2010   case GameType::solo_koehler:
2011     return this->Aiconfig::value(Aiconfig::Type::lowest_trumplimit_solokoehler);
2012   case GameType::solo_meatless:
2013     return this->Aiconfig::value(Aiconfig::Type::lowest_trumplimit_meatless);
2014   default:
2015     return this->Aiconfig::value(Aiconfig::Type::lowest_trumplimit_normal);
2016   }
2017 }
2018 
2019 /** returns the selected partner for a genscher
2020  **
2021  ** @return   pointer to the partner
2022  **            nullptr if not to use the genscher
2023  **/
2024 Player const*
genscher_partner()2025 Ai::genscher_partner()
2026 {
2027   Player const* res = nullptr;
2028 
2029   // first find original teammate
2030   for ( unsigned i = 0; i < this->game().playerno(); i++ ) {
2031     if( this->teamofplayer( this->game().player(i) ) == this->team()
2032        && this->game().player(i) != *this)
2033     {
2034       res = &(this->game().player(i));
2035       break;
2036     }
2037   }
2038   /// @todo use teams after genscher...
2039 
2040   // check Specialpoints
2041   std::vector<int> bonusPoints( this->game().playerno(), 0 );
2042   for (auto const& t : this->trick_) {
2043     // DK: if hinzugefuegt
2044     if (!t.isempty())
2045       bonusPoints[t.winnerplayer().no()] += t.specialpoints().size() * 30;
2046   }
2047 
2048   // secure victory
2049   unsigned int points = 0;
2050   bool found = false;
2051   if ( this->game().points_of_team( this->team() ) < 120 )
2052     for ( unsigned i = 0; i < this->game().playerno(); i++ ) {
2053       if(   this->game().points_of_player( this->game().player(i) )
2054          + this->game().points_of_player( *this )
2055          > 120
2056          && (this->game().player(i) != *this )
2057          && this->game().points_of_player( this->game().player(i) )
2058          + bonusPoints[ i ] > points ) {
2059         res = &(this->game().player(i));
2060         points = this->game().points_of_player( this->game().player(i) )
2061           + bonusPoints[ i ] ;
2062         found = true;
2063       }
2064     }
2065 
2066   if (found)
2067     return res;
2068 
2069   for ( unsigned i = 0; i < this->game().playerno(); i++ ) {
2070     if (   (this->game().points_of_player(this->game().player(i))
2071             + bonusPoints[i]) > points
2072         && this->game().player(i) != *this) {
2073       points = (this->game().points_of_player(this->game().player(i))
2074                 + bonusPoints[i]);
2075       res = &(this->game().player(i));
2076     }
2077   }
2078 
2079   Announcement highest_announcement = Announcement::noannouncement;
2080   // calculate highest announcements of this team
2081   for (auto const& p : this->game().players()) {
2082     if (p.team() == this->team()) {
2083       if (p.announcement() > highest_announcement )
2084         highest_announcement = p.announcement();
2085     }
2086   }
2087 
2088   if (   highest_announcement >= Announcement::no0
2089       && this->game().tricks().has_trick(opposite(this->team())))
2090     return res;
2091 
2092   if (   highest_announcement >= Announcement::no30
2093       && this->game().points_of_team(opposite(this->team())) >= 30)
2094     return res;
2095 
2096   if (   highest_announcement >= Announcement::no60
2097       && this->game().points_of_team(opposite(this->team())) >= 60)
2098     return res;
2099 
2100   if (   highest_announcement >= Announcement::no90
2101       && this->game().points_of_team(opposite(this->team())) >= 90)
2102     return res;
2103 
2104   // don't use genscher
2105   return {};
2106 }
2107