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 
32 #include "../../game/game.h"
33 #include "../../party/rule.h"
34 #include "../../card/trick.h"
35 
36 /** constructor
37  **/
AiRandom()38 AiRandom::AiRandom() :
39   Player(Player::Type::ai_random)
40 { }
41 
42 /** construktor
43  **
44  ** @param    istr   stream with the infos
45  **
46  ** @todo   all
47  **/
AiRandom(istream & istr)48 AiRandom::AiRandom(istream& istr) :
49   Player(Player::Type::ai_random)
50 {
51   (void)istr;
52   DEBUG_ASSERTION(false,
53 		  "AiRandom::AiRandom(istr):\n"
54 		  "  Contructor not implemented");
55 } // AiRandom::AiRandom(istream& istr)
56 
57 /** copy constructor
58  **
59  ** @param    player   player to copy
60  **/
AiRandom(Player const & player)61 AiRandom::AiRandom(Player const& player) :
62   Player(player),
63   Aiconfig()
64 {
65   this->set_type(Player::Type::ai_random);
66 } // AiRandom::AiRandom(Player player)
67 
68 /** copy constructor
69  **
70  ** @param    player   player to copy
71  ** @param    aiconfig   configuration to copy
72  **/
AiRandom(Player const & player,Aiconfig const & aiconfig)73 AiRandom::AiRandom(Player const& player, Aiconfig const& aiconfig) :
74   Player(player),
75   Aiconfig(aiconfig)
76 {
77   this->set_type(Player::Type::ai_random);
78 } // AiRandom::AiRandom(Player player, Aiconfig aiconfig)
79 
80 /** clone the player
81  **
82  ** @return   pointer of a clone
83  **/
84 unique_ptr<Player>
clone() const85 AiRandom::clone() const
86 {
87   return make_unique<AiRandom>(*this);
88 } // virtual unique_ptr<Player> AiRandom::clone() const
89 
90 /** -> result
91  ** (test of poverty, marriage, swines, hyperswines)
92  **
93  ** @param    duty_solo   whether the player has to play a solo
94  **    (default: false)
95  **
96  ** @return   simple Reservation
97  **/
98 Reservation const&
reservation_get(bool const duty_solo)99 AiRandom::reservation_get(bool const duty_solo)
100 {
101   this->reservation() = this->Player::reservation_get_default();
102 
103   if (   duty_solo
104       || (::random_value(this->game().playerno() * this->game().playerno()) == 0) ) {
105     vector<GameType> soli;
106     for (auto t : game_type_list) {
107       if (is_real_solo(t)
108           && this->game().rule()(t) ) {
109         soli.push_back(t);
110       }
111     } // for (t)
112     if (!soli.empty()) {
113       this->reservation().game_type = soli[::random_value(soli.size())];
114     }
115   } // if (duty_solo)
116 
117   return this->reservation();
118 } // Reservation const& AiRandom::reservation_get(bool duty_solo)
119 
120 /** -> result:
121  ** take a random card of all valid ones
122  **
123  ** @return   valid card
124  **/
125 HandCard
card_get()126 AiRandom::card_get()
127 {
128   HandCard card;
129   do {
130     card = this->hand().card(::random_value(this->hand().cardsnumber()));
131   } while (!this->game().tricks().current().isvalid(card));
132 
133   return card;
134 } // HandCard AiRandom::card_get()
135 
136 /** @return   announcement of the player
137  **/
138 Announcement
announcement_request() const139 AiRandom::announcement_request() const
140 {
141   // points of the own team
142   unsigned points = 0;
143 
144   // count the points, the own team has made
145   for(auto const& player : this->game().players()) {
146     if (this->game().teaminfo().get(player) == this->team())
147       points += this->game().points_of_player(player);
148   }
149 
150   if (points == 240)
151     return Announcement::no0;
152   if (points > 240 - 30)
153     return Announcement::no30;
154   if (points > 240 - 60)
155     return Announcement::no60;
156   if (points > 240 - 90)
157     return Announcement::no90;
158   if (points > 240 - 120)
159     return Announcement::no120;
160 
161   return Announcement::noannouncement;
162 } // Announcement AiRandom::announcement_request() const
163 
164 /** @return   NULL (no new partner)
165  **/
166 Player const*
genscher_partner()167 AiRandom::genscher_partner()
168 {
169   return {};
170 } // Player const* AiRandom::genscher_partner()
171 
172 /** @return   shifted cards
173  **/
174 HandCards
poverty_shift()175 AiRandom::poverty_shift()
176 {
177   HandCards hand_cards = this->hand().cards();
178   HandCards cards_to_shift;
179 
180   // first add all trump
181   for (auto c = hand_cards.begin(); c != hand_cards.end(); ) {
182     if (c->istrump()) {
183       cards_to_shift.push_back(*c);
184       c = hand_cards.erase(c);
185     } else {
186       ++c;
187     }
188   } // for (c : hand_cards)
189 
190   // then fill up with cards randomly chosen
191   while (cards_to_shift.size() < this->hand().count_poverty_cards()) {
192     auto const i = ::random_value(hand_cards.size());
193     cards_to_shift.push_back(hand_cards[i]);
194     hand_cards.erase(hand_cards.begin() + i);
195   }
196 
197   this->hand().remove(cards_to_shift);
198 
199   return cards_to_shift;
200 } // HandCards AiRandom::poverty_shift()
201 
202 /** -> result
203  **
204  ** @param    cardno   number of shifted cards (ignored)
205  **
206  ** @return   false (do not accept the poverty)
207  **/
208 bool
poverty_take_accept(unsigned const cardno)209 AiRandom::poverty_take_accept(unsigned const cardno)
210 {
211   return false;
212 } // bool AiRandom::poverty_take_accept(unsigned cardno)
213 
214 
215 // the player changes the cards of the poverty
216 /** should not be called
217  **
218  ** @param    cards   the cards the player takes
219  **
220  ** @return   empty cards
221  **/
222 HandCards
poverty_cards_change(HandCards const & cards)223 AiRandom::poverty_cards_change(HandCards const& cards)
224 {
225   DEBUG_ASSERTION(false,
226                   "AiRandom::poverty_cards_change(cards)\n"
227                   "  function should not be called!");
228   return HandCards();
229 } // HandCards AiRandom::poverty_cards_change(HandCards cards)
230 
231 /** the poverty player gets 'cards'
232  **
233  ** @param    cards   cards the player gets back
234  **/
235 void
poverty_cards_get_back(HandCards const & cards)236 AiRandom::poverty_cards_get_back(HandCards const& cards)
237 {
238   this->hand().add(cards);
239 } // void AiRandom::poverty_cards_get_back(HandCards cards)
240