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 "game.h"
31
32 #include "gameplay.h"
33 #include "gameplay_actions/marriage.h"
34 #include "gameplay_actions/genscher.h"
35
36 #include "../party/rule.h"
37 #include "../player/player.h"
38 #include "../card/trick.h"
39 #include "../ui/ui.h"
40
41 /** constructor
42 **
43 ** @param game corresponding game
44 **/
GameMarriage(Game & game)45 GameMarriage::GameMarriage(Game& game) noexcept :
46 game_(&game)
47 { }
48
49 /** constructor
50 **
51 ** @param marriage marriage to copy
52 ** @param game corresponding game
53 **/
GameMarriage(GameMarriage const & marriage,Game & game)54 GameMarriage::GameMarriage(GameMarriage const& marriage, Game& game) noexcept :
55 game_(&game),
56 selector_(marriage.selector_),
57 determination_trickno_(marriage.determination_trickno_)
58 { }
59
60 /** @return the marriage selector
61 **/
62 MarriageSelector
selector() const63 GameMarriage::selector() const noexcept
64 { return this->selector_; }
65
66 /** @return the tricknumber, the marriage was determined
67 **/
68 unsigned
determination_trickno() const69 GameMarriage::determination_trickno() const noexcept
70 { return this->determination_trickno_; }
71
72 /** test, whether a genscher is played
73 **
74 ** @param played_card the played card
75 **/
76 void
check_for_genscher(HandCard const & played_card)77 GameMarriage::check_for_genscher(HandCard const& played_card)
78 {
79 auto& game = *this->game_;
80 auto const& rule = game.rule();
81
82 if (!rule(Rule::Type::genscher))
83 return ;
84
85 if ( ::is_solo(game.type())
86 || (game.type() == GameType::poverty))
87 return ;
88
89 if (!played_card.istrumpking())
90 return ;
91
92 if (game.players().current_player().hand().count_trump_kings()
93 != rule(Rule::Type::number_of_same_cards))
94 return ;
95
96 Player const* const genscher_partner
97 = game.players().current_player().genscher_partner();
98
99 if (!genscher_partner)
100 return ;
101
102 game.players().set_soloplayer(game.players().current_player());
103 auto const& soloplayer = game.players().soloplayer();
104 // set the teams: 're' for the genscher players, 'contra' for the others
105 for (auto& p : game.players()) {
106 auto const team = ( ( (p == game.players().current_player())
107 || (p == *genscher_partner))
108 ? Team::re
109 : Team::contra);
110 game.teaminfo_.set(p, team);
111 p.set_team(team);
112 } // for (p : this->player)
113 game.set_type(GameType::genscher);
114
115 game.announcements().remove_all_but_re_contra();
116
117 // tell all players about the genscher
118 for (auto& p : game.players())
119 p.genscher(game.players().current_player(), *genscher_partner);
120
121 game.gameplay_->gameplay_action(GameplayActions::Genscher(soloplayer.no(),
122 genscher_partner->no()));
123 if (!game.isvirtual()) {
124 ::ui->genscher(soloplayer, *genscher_partner);
125 this->signal_genscher_(soloplayer, *genscher_partner);
126 ::ui->gameplay_action(GameplayActions::Genscher(soloplayer.no(),
127 genscher_partner->no()));
128 game.signal_gameplay_action_(GameplayActions::Genscher(soloplayer.no(),
129 genscher_partner->no()));
130 }
131 } // void GameMarriage::check_for_genscher(HandCard played_card)
132
133
134 /** test, whether a silent marriage is played
135 **
136 ** @return
137 **/
138 void
check_for_silent_marriage()139 GameMarriage::check_for_silent_marriage()
140 {
141 if (::game_status == GameStatus::game_redistribute)
142 return ;
143
144 DEBUG_ASSERTION((::game_status == GameStatus::game_reservation),
145 "GameMarriage::check_for_silent_marriage()\n"
146 " game status is not 'reservation' "
147 "but '" << ::game_status << "'");
148
149 auto& game = *this->game_;
150 auto const& rule = game.rule();
151
152 if (game.type() != GameType::normal)
153 return ;
154
155 for (auto& p : game.players()) {
156 if (p.hand().count_club_queens()
157 == rule(Rule::Type::number_of_same_cards)) {
158 game.players().set_soloplayer(p);
159 game.set_type(GameType::marriage_silent);
160 this->selector_ = MarriageSelector::silent;
161 this->determination_trickno_ = UINT_MAX;
162 break;
163 } // if (silent marriage)
164 } // for (p : game.players())
165 } // void GameMarriage::check_for_silent_marriage()
166
167 /** test, if the silent marriage is solved
168 **/
169 void
determine_silent_marriage()170 GameMarriage::determine_silent_marriage()
171 {
172 auto& game = *this->game_;
173 auto const& rule = game.rule();
174
175 if ( (game.type_ != GameType::marriage_silent)
176 || (this->selector() != MarriageSelector::silent))
177 return ;
178
179 // whether the silent marriage is known to all
180 bool solved = false;
181
182 { // check whether both club queens have been played
183 if (game.cards().count_played(Card::club_queen)
184 == rule(Rule::Type::number_of_same_cards) )
185 solved = true;
186 } // check whether both club queens have been played
187
188 { // check whether all other players are known to be contra
189 unsigned contra_no = 0;
190 for (auto& p : game.players())
191 if (game.teaminfo().get(p) == Team::contra)
192 contra_no += 1;
193
194 if (contra_no == game.playerno() - 1)
195 solved = true;
196 } // check whether all other players are known to be contra
197
198 if (solved) {
199 this->selector_ = MarriageSelector::team_set;
200 this->determination_trickno_ = game.tricks().current_no();
201 } // if (solved)
202 } // void GameMarriage::determine_silent_marriage()
203
204 /** test, if the marriage is solved
205 **
206 ** @return
207 **/
208 void
determine_marriage()209 GameMarriage::determine_marriage()
210 {
211 if (!this->is_undetermined())
212 return ;
213
214 auto& game = *this->game_;
215 auto const& rule = game.rule();
216 auto const& tricks = game.tricks();
217 auto const& current_trick = tricks.current();
218 auto const& soloplayer = game.players().soloplayer();
219
220 // whether the player has to play alone
221 // note that 'tricks().current_no()' begins at '0'
222 // but 'determination' at '1'
223 bool alone = (tricks.current_no() >= rule(Rule::Type::marriage_determination));
224 auto const& winnerplayer = current_trick.winnerplayer();
225
226 if ( rule(Rule::Type::marriage_first_one_decides)
227 && is_selector(current_trick.startcard().tcolor(),
228 this->selector())
229 && (winnerplayer == soloplayer) )
230 alone = true;
231
232
233 if ( is_selector(current_trick.startcard().tcolor(),
234 this->selector())
235 && (winnerplayer != soloplayer) ) {
236 // set the teams
237 for (auto& p : game.players()) {
238 auto const team = (( (p == soloplayer)
239 || (p == winnerplayer))
240 ? Team::re
241 : Team::contra);
242 game.teaminfo_.set(p, team);
243 p.set_team(team);
244 }
245 this->selector_ = MarriageSelector::team_set;
246 this->determination_trickno_ = tricks.current_no();
247 // update the teaminfo of the players
248 for (auto& p : game.players()) {
249 p.marriage(soloplayer, winnerplayer);
250 }
251
252 game.gameplay_->gameplay_action(GameplayActions::Marriage(soloplayer.no(),
253 winnerplayer.no()));
254 if (!game.isvirtual()) {
255 ::ui->marriage(soloplayer, winnerplayer);
256 this->signal_marriage_(soloplayer, winnerplayer);
257 ::ui->gameplay_action(GameplayActions::Marriage(soloplayer.no(),
258 winnerplayer.no()));
259 game.signal_gameplay_action_(GameplayActions::Marriage(soloplayer.no(),
260 winnerplayer.no()));
261 }
262
263 alone = false;
264 } // if selected trick is caught
265
266
267 if ( (this->selector() != MarriageSelector::team_set)
268 && !alone) {
269 // test, whether there is a remaining card of the color
270 bool has_card = false; // whether a player has a card of the color
271 for (auto& p : game.players()) {
272 switch(this->selector()) {
273 case MarriageSelector::silent:
274 case MarriageSelector::team_set:
275 case MarriageSelector::first_foreign:
276 has_card = true;
277 break;
278 case MarriageSelector::first_trump:
279 if (p.hand().contains(Card::trump))
280 has_card = true;
281 break;
282 case MarriageSelector::first_color:
283 if ( p.hand().contains(Card::club)
284 || p.hand().contains(Card::spade)
285 || p.hand().contains(Card::heart))
286 has_card = true;
287 break;
288 case MarriageSelector::first_club:
289 if (p.hand().contains(Card::club))
290 has_card = true;
291 break;
292 case MarriageSelector::first_spade:
293 if (p.hand().contains(Card::spade))
294 has_card = true;
295 break;
296 case MarriageSelector::first_heart:
297 if (p.hand().contains(Card::heart))
298 has_card = true;
299 break;
300 } // switch (this->selector())
301 } // for (p : this->players())
302
303 if (!has_card)
304 alone = true;
305 } // if (!alone)
306
307 if (alone) {
308 this->determination_trickno_ = tricks.current_no();
309 game.set_type(GameType::marriage_solo);
310 for (auto& p : game.players()) {
311 auto const team = ( (p == soloplayer)
312 ? Team::re
313 : Team::contra);
314 game.teaminfo_.set(p, team);
315 p.set_team(team);
316 } // for (p : this->players())
317 this->selector_ = MarriageSelector::team_set;
318
319 for (auto& p : game.players())
320 p.marriage(soloplayer, soloplayer);
321
322 game.gameplay_->gameplay_action(GameplayActions::Marriage(soloplayer.no(),
323 soloplayer.no())
324 );
325 if (!game.isvirtual()) {
326 ::ui->marriage(soloplayer, soloplayer);
327 this->signal_marriage_(soloplayer, soloplayer);
328 ::ui->gameplay_action(GameplayActions::Marriage(soloplayer.no(),
329 soloplayer.no())
330 );
331 game.signal_gameplay_action_(GameplayActions::Marriage(soloplayer.no(),
332 soloplayer.no())
333 );
334 }
335 } // if (this->acttrick() >= rule(Rule::Type::determination))
336
337 // it can be, that the team of the swines owner or the first fox catcher
338 // has changed
339 if (rule(Rule::Type::swine_only_second)
340 && game.swines().swines_announced()
341 && game.swines().first_fox_caught()
342 && (this->selector() == MarriageSelector::team_set)){
343 if (!game.isvirtual())
344 ::ui->redraw_all();
345 } // if (first fox of swines in trick)
346 } // void GameMarriage::determine_marriage()
347
348 /** reset the values
349 **/
350 void
reset()351 GameMarriage::reset() noexcept
352 {
353 this->selector_ = MarriageSelector::team_set;
354 this->determination_trickno_ = 0;
355 }
356
357 /** @return whether the game is a marriage and undetermined
358 **/
359 bool
is_undetermined() const360 GameMarriage::is_undetermined() const noexcept
361 {
362 return ( (this->game_->type() == GameType::marriage)
363 && (this->selector() != MarriageSelector::team_set));
364 } // bool GameMarriage::marriage().is_undetermined() const
365
366 /** @return signal for a marriage
367 **/
368 Signal<void(Player const&, Player const&)>&
signal_marriage()369 GameMarriage::signal_marriage() noexcept
370 { return this->signal_marriage_; }
371
372 /** @return signal, when the partner for a genscher shall be selected
373 **/
374 Signal<void()>&
signal_get_genscher_partner()375 GameMarriage::signal_get_genscher_partner() noexcept
376 { return this->signal_get_genscher_partner_; }
377
378 /** @return signal, when a genscher is made
379 **/
380 Signal<void(Player const&, Player const&)>&
signal_genscher()381 GameMarriage::signal_genscher() noexcept
382 { return this->signal_genscher_; }
383
384