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 "weighted_card_list.h"
31
32 /** standard constructor
33 **
34 ** @param game corresponding game
35 **/
WeightedCardList(Game const & game)36 WeightedCardList::WeightedCardList(Game const& game) :
37 List(),
38 game_(&game),
39 tcolor_ptr(Card::number_of_tcolors, WeightedCardList::end()),
40 tcolor_pos(Card::number_of_tcolors, -1)
41 { }
42
43 /** copy constructor
44 **
45 ** @param card_list card list to copy
46 **/
WeightedCardList(WeightedCardList const & card_list)47 WeightedCardList::WeightedCardList(WeightedCardList const& card_list) :
48 List(card_list),
49 game_(card_list.game_),
50 tcolor_ptr(Card::number_of_tcolors, WeightedCardList::end()),
51 tcolor_pos(Card::number_of_tcolors, -1)
52 { this->recreate_tcolor_ptrs(); }
53
54 /** copy operator
55 **
56 ** @param card_list card list to copy
57 **
58 ** @return the card list
59 **/
60 WeightedCardList&
operator =(WeightedCardList const & card_list)61 WeightedCardList::operator=(WeightedCardList const& card_list)
62 {
63 static_cast<List&>(*this) = card_list;
64 this->recreate_tcolor_ptrs();
65
66 return *this;
67 } // WeightedCardList& WeightedCardList::operator=(WeightedCardList card_list)
68
69 /** @return the corresponding game
70 **/
71 Game const&
game() const72 WeightedCardList::game() const
73 { return *this->game_; }
74
75
76 /** clear the list
77 **/
78 void
clear()79 WeightedCardList::clear()
80 {
81 this->List::clear();
82 this->tcolor_ptr
83 = vector<WeightedCardList::iterator>(Card::number_of_tcolors,
84 this->end());
85 this->tcolor_pos = vector<int>(Card::number_of_tcolors, -1);
86 return ;
87 } // void WeightedCardList::clear()
88
89 /** write the list in the stream
90 **
91 ** @param ostr output stream
92 **/
93 void
write(ostream & ostr) const94 WeightedCardList::write(ostream& ostr) const
95 {
96 for (auto wc = this->begin(); wc != this->end(); ++wc) {
97 ostr << std::setw(5) << wc->first << ' ';
98 char c = ' ';
99 for (unsigned tcolor = 0; tcolor < Card::number_of_tcolors; ++tcolor) {
100 if (wc == this->tcolor_ptr[tcolor]) {
101 c = to_string(static_cast<Card::TColor>(tcolor))[0];
102 break;
103 }
104 }
105 ostr << c << ' ' << wc->second << '\n';
106 }
107 ostr << '\n';
108 for (unsigned tcolor = 0; tcolor < Card::number_of_tcolors; ++tcolor) {
109 ostr << setw(7) << static_cast<Card::TColor>(tcolor) << " "
110 << setw(2) << this->tcolor_pos[tcolor] << ' ';
111
112 auto const& highest = this->highest(static_cast<Card::TColor>(tcolor));
113 if (highest.is_empty())
114 ostr << "--\n";
115 else
116 ostr << highest << '\n';
117 }
118 } // void WeightedCardList::write(ostream& ostr) const
119
120 /** @return the number of cards
121 **/
122 unsigned
cards_no() const123 WeightedCardList::cards_no() const
124 {
125 return this->size();
126 } // unsigned WeightedCardList::cards_no() const
127
128 /** add the card
129 **
130 ** @param card card to add
131 ** @param weighting the weighting of the card
132 **/
133 void
add(Card const card,int const weighting)134 WeightedCardList::add(Card const card, int const weighting)
135 {
136 // pointer to the position to insert the card
137 auto wc = this->begin();
138 // position of the card
139 int pos = 0;
140 // search the position to insert the card
141 for (; wc != this->end(); ++wc, ++pos)
142 if (weighting >= wc->first)
143 break;
144 wc = this->insert(wc, pair<int, Card>(weighting, card));
145
146 { // update the pos of the highest tcolors
147 for (unsigned tcolor = 0; tcolor < Card::number_of_tcolors; ++tcolor)
148 if (this->tcolor_pos[tcolor] >= pos)
149 this->tcolor_pos[tcolor] += 1;
150 } // update the pos of the highest tcolors
151
152 { // update the highest pointer of the tcolor of the card
153 auto const tcolor = card.tcolor(this->game());
154 if ( (this->tcolor_pos[tcolor] == -1)
155 || (this->tcolor_pos[tcolor] >= pos) ) {
156 this->tcolor_pos[tcolor] = pos;
157 this->tcolor_ptr[tcolor] = wc;
158 } // if (this->tcolor_pos[tcolor] >= pos)
159 } // update the highest pointer of the tcolor of the card
160 } // void WeightedCardList::add(Card card, int weighting)
161
162 /** @return the card with the highest weighting
163 **/
164 Card
highest() const165 WeightedCardList::highest() const
166 {
167 if (this->empty())
168 return Card::empty;
169
170 return this->front().second;
171 } // Card WeightedCardList::highest() const
172
173 /** -> result
174 **
175 ** @param tcolor tcolor to check
176 **
177 ** @return the card with the highest weighting of 'tcolor'
178 **/
179 Card
highest(Card::TColor const tcolor) const180 WeightedCardList::highest(Card::TColor const tcolor) const
181 {
182 if (this->tcolor_ptr[tcolor] == this->end())
183 return Card::empty;
184
185 return this->tcolor_ptr[tcolor]->second;
186 } // Card WeightedCardList::highest(Card::TColor tcolor) const
187
188 /** -> result
189 **
190 ** @param tcolor tcolor not to check
191 **
192 ** @return the card with the highest weighting not of 'tcolor'
193 **/
194 Card
highest_not_of(Card::TColor const tcolor) const195 WeightedCardList::highest_not_of(Card::TColor const tcolor) const
196 {
197 auto const& ptr = this->highest_ptr_not_of(tcolor);
198 if (ptr == this->end())
199 return Card::empty;
200
201 return ptr->second;
202 } // Card WeightedCardList::highest_not_of(Card::TColor tcolor) const
203
204 /** -> result
205 **
206 ** @param tcolor_a first tcolor to check
207 ** @param tcolor_b second tcolor to check
208 **
209 ** @return the card with the highest weighting of 'tcolor_a' or 'tcolor_b'
210 **/
211 Card
highest(Card::TColor const tcolor_a,Card::TColor const tcolor_b) const212 WeightedCardList::highest(Card::TColor const tcolor_a,
213 Card::TColor const tcolor_b) const
214 {
215 auto const& ptr = this->highest_ptr(tcolor_a, tcolor_b);
216 if (ptr == this->end())
217 return Card::empty;
218
219 return ptr->second;
220 } // Card WeightedCardList::highest(Card::TColor tcolor_a, Card::TColor tcolor_b) const
221
222 /** -> result
223 **
224 ** @param tcolor_a first tcolor to check
225 ** @param tcolor_b second tcolor to check
226 ** @param tcolor_c third tcolor to check
227 **
228 ** @return the card with the highest weighting of 'tcolor_'.
229 **/
230 Card
highest(Card::TColor const tcolor_a,Card::TColor const tcolor_b,Card::TColor const tcolor_c) const231 WeightedCardList::highest(Card::TColor const tcolor_a,
232 Card::TColor const tcolor_b,
233 Card::TColor const tcolor_c) const
234 {
235 auto const& ptr = this->highest_ptr(tcolor_a, tcolor_b, tcolor_c);
236 if (ptr == this->end())
237 return Card::empty;
238
239 return ptr->second;
240 } // Card WeightedCardList::highest(Card::TColor tcolor_a, Card::TColor tcolor_b, Card::TColor tcolor_c) const
241
242 /** -> result
243 **
244 ** @param tcolor_a first tcolor to check
245 ** @param tcolor_b second tcolor to check
246 ** @param tcolor_c third tcolor to check
247 ** @param tcolor_d fourth tcolor to check
248 **
249 ** @return the card with the highest weighting of 'tcolor_'.
250 **/
251 Card
highest(Card::TColor const tcolor_a,Card::TColor const tcolor_b,Card::TColor const tcolor_c,Card::TColor const tcolor_d) const252 WeightedCardList::highest(Card::TColor const tcolor_a,
253 Card::TColor const tcolor_b,
254 Card::TColor const tcolor_c,
255 Card::TColor const tcolor_d) const
256 {
257 auto const& ptr = this->highest_ptr(tcolor_a, tcolor_b, tcolor_c, tcolor_d);
258 if (ptr == this->end())
259 return Card::empty;
260
261 return ptr->second;
262 } // Card WeightedCardList::highest(Card::TColor tcolor_a, Card::TColor tcolor_b, Card::TColor tcolor_c, Card::TColor tcolor_d) const
263
264 /** @return the highest weighting
265 ** INT_MIN, if none exists
266 **/
267 int
highest_weighting() const268 WeightedCardList::highest_weighting() const
269 {
270 if (this->empty())
271 return INT_MIN;
272
273 return this->front().first;
274 } // int WeightedCardList::highest_weighting() const
275
276 /** -> result
277 **
278 ** @param tcolor tcolor
279 **
280 ** @return the highest weighting of tcolor
281 ** INT_MIN, if none exists
282 **/
283 int
highest_weighting(Card::TColor const tcolor) const284 WeightedCardList::highest_weighting(Card::TColor const tcolor) const
285 {
286 if (this->tcolor_ptr[tcolor] == this->end())
287 return INT_MIN;
288
289 return this->tcolor_ptr[tcolor]->first;
290 } // int WeightedCardList::highest_weighting(Card::TColor tcolor) const
291
292 /** -> result
293 **
294 ** @param tcolor tcolor
295 **
296 ** @return the highest weighting not of tcolor
297 ** INT_MIN, if none exists
298 **/
299 int
highest_weighting_not_of(Card::TColor const tcolor) const300 WeightedCardList::highest_weighting_not_of(Card::TColor const tcolor) const
301 {
302 auto const& ptr = this->highest_ptr_not_of(tcolor);
303 if (ptr == this->end())
304 return INT_MIN;
305
306 return ptr->first;
307 } // int WeightedCardList::highest_weighting_not_of(Card::TColor tcolor) const
308
309 /** -> result
310 **
311 ** @param tcolor_a first tcolor to check
312 ** @param tcolor_b second tcolor to check
313 **
314 ** @return the highest weighting of 'tcolor_a' or 'tcolor_b'
315 **/
316 int
highest_weighting(Card::TColor const tcolor_a,Card::TColor const tcolor_b) const317 WeightedCardList::highest_weighting(Card::TColor const tcolor_a,
318 Card::TColor const tcolor_b) const
319 {
320 auto const& ptr = this->highest_ptr(tcolor_a, tcolor_b);
321 if (ptr == this->end())
322 return INT_MIN;
323
324 return ptr->first;
325 } // int WeightedCardList::highest_weighting(Card::TColor tcolor_a, Card::TColor tcolor_b) const
326
327 /** -> result
328 **
329 ** @param tcolor_a first tcolor to check
330 ** @param tcolor_b second tcolor to check
331 ** @param tcolor_c third tcolor to check
332 **
333 ** @return the highest weighting of 'tcolor_'.
334 **/
335 int
highest_weighting(Card::TColor const tcolor_a,Card::TColor const tcolor_b,Card::TColor const tcolor_c) const336 WeightedCardList::highest_weighting(Card::TColor const tcolor_a,
337 Card::TColor const tcolor_b,
338 Card::TColor const tcolor_c) const
339 {
340 auto const& ptr = this->highest_ptr(tcolor_a, tcolor_b, tcolor_c);
341 if (ptr == this->end())
342 return INT_MIN;
343
344 return ptr->first;
345 } // int WeightedCardList::highest_weighting(Card::TColor tcolor_a, Card::TColor tcolor_b, Card::TColor tcolor_c) const
346
347 /** -> result
348 **
349 ** @param tcolor_a first tcolor to check
350 ** @param tcolor_b second tcolor to check
351 ** @param tcolor_c third tcolor to check
352 ** @param tcolor_d fourth tcolor to check
353 **
354 ** @return the card with the highest weighting of 'tcolor_'.
355 **/
356 int
highest_weighting(Card::TColor const tcolor_a,Card::TColor const tcolor_b,Card::TColor const tcolor_c,Card::TColor const tcolor_d) const357 WeightedCardList::highest_weighting(Card::TColor const tcolor_a,
358 Card::TColor const tcolor_b,
359 Card::TColor const tcolor_c,
360 Card::TColor const tcolor_d) const
361 {
362 auto const& ptr = this->highest_ptr(tcolor_a, tcolor_b, tcolor_c, tcolor_d);
363 if (ptr == this->end()) {
364 return INT_MIN;
365 }
366
367 return ptr->first;
368 } // int WeightedCardList::highest_weighting(Card::TColor tcolor_a, Card::TColor tcolor_b, Card::TColor tcolor_c, Card::TColor tcolor_d) const
369
370 /** @return the pointer to the highest weighting
371 **/
372 WeightedCardList::const_iterator
highest_ptr() const373 WeightedCardList::highest_ptr() const
374 {
375 return this->begin();
376 } // WeightedCardList::const_iterator WeightedCardList::highest_ptr() const
377
378 /** -> result
379 **
380 ** @param tcolor tcolor to check
381 **
382 ** @return the pointer to the highest weighting of 'tcolor'
383 **/
384 WeightedCardList::iterator const&
highest_ptr(Card::TColor const tcolor) const385 WeightedCardList::highest_ptr(Card::TColor const tcolor) const
386 {
387 return this->tcolor_ptr[tcolor];
388 } // WeightedCardList::iterator WeightedCardList::highest_ptr(Card::TColor const tcolor) const
389
390 /** -> result
391 **
392 ** @param tcolor_a first tcolor to check
393 ** @param tcolor_b second tcolor to check
394 **
395 ** @return the ptr with the highest weighting of 'tcolor_a' or 'tcolor_b'
396 **/
397 WeightedCardList::iterator const&
highest_ptr(Card::TColor const tcolor_a,Card::TColor const tcolor_b) const398 WeightedCardList::highest_ptr(Card::TColor const tcolor_a,
399 Card::TColor const tcolor_b) const
400 {
401 if (this->tcolor_ptr[tcolor_a] == this->end())
402 return this->tcolor_ptr[tcolor_b];
403
404 if (this->tcolor_ptr[tcolor_b] == this->end())
405 return this->tcolor_ptr[tcolor_a];
406
407 if (this->tcolor_pos[tcolor_a] < this->tcolor_pos[tcolor_b])
408 return this->tcolor_ptr[tcolor_a];
409 else
410 return this->tcolor_ptr[tcolor_b];
411 } // WeightedCardList::iterator WeightedCardList::highest_ptr(Card::TColor tcolor_a, Card::TColor tcolor_b) const
412
413 /** -> result
414 **
415 ** @param tcolor_a first tcolor to check
416 ** @param tcolor_b second tcolor to check
417 ** @param tcolor_c third tcolor to check
418 **
419 ** @return the ptr with the highest weighting of 'tcolor_'.
420 **/
421 WeightedCardList::iterator const&
highest_ptr(Card::TColor const tcolor_a,Card::TColor const tcolor_b,Card::TColor const tcolor_c) const422 WeightedCardList::highest_ptr(Card::TColor const tcolor_a,
423 Card::TColor const tcolor_b,
424 Card::TColor const tcolor_c) const
425 {
426 if (this->tcolor_ptr[tcolor_a] == this->end())
427 return this->highest_ptr(tcolor_b, tcolor_c);
428
429 if (this->tcolor_ptr[tcolor_b] == this->end())
430 return this->highest_ptr(tcolor_a, tcolor_c);
431
432 if (this->tcolor_pos[tcolor_a] < this->tcolor_pos[tcolor_b])
433 return this->highest_ptr(tcolor_a, tcolor_c);
434 else
435 return this->highest_ptr(tcolor_b, tcolor_c);
436 } // WeightedCardList::iterator WeightedCardList::highest_ptr(Card::TColor tcolor_a, Card::TColor tcolor_b, Card::TColor tcolor_c) const
437
438 /** -> result
439 **
440 ** @param tcolor_a first tcolor to check
441 ** @param tcolor_b second tcolor to check
442 ** @param tcolor_c third tcolor to check
443 ** @param tcolor_d fourth tcolor to check
444 **
445 ** @return the ptr with the highest weighting of 'tcolor_'.
446 **/
447 WeightedCardList::iterator const&
highest_ptr(Card::TColor const tcolor_a,Card::TColor const tcolor_b,Card::TColor const tcolor_c,Card::TColor const tcolor_d) const448 WeightedCardList::highest_ptr(Card::TColor const tcolor_a,
449 Card::TColor const tcolor_b,
450 Card::TColor const tcolor_c,
451 Card::TColor const tcolor_d) const
452 {
453 if (this->tcolor_ptr[tcolor_a] == this->end())
454 return this->highest_ptr(tcolor_b, tcolor_c, tcolor_d);
455
456 if (this->tcolor_ptr[tcolor_b] == this->end())
457 return this->highest_ptr(tcolor_a, tcolor_c, tcolor_d);
458
459 if (this->tcolor_pos[tcolor_a] < this->tcolor_pos[tcolor_b])
460 return this->highest_ptr(tcolor_a, tcolor_c, tcolor_d);
461 else
462 return this->highest_ptr(tcolor_b, tcolor_c, tcolor_d);
463 } // WeightedCardList::iterator WeightedCardList::highest_ptr(Card::TColor tcolor_a, Card::TColor tcolor_b, Card::TColor tcolor_c, Card::TColor tcolor_d) const
464
465 /** -> result
466 **
467 ** @param tcolor tcolor not to check
468 **
469 ** @return the pointer to the highest weighting not of 'tcolor'
470 **/
471 WeightedCardList::iterator const&
highest_ptr_not_of(Card::TColor const tcolor) const472 WeightedCardList::highest_ptr_not_of(Card::TColor const tcolor) const
473 {
474 Card::TColor const tc = this->highest().tcolor(this->game());
475 if (tc != tcolor)
476 return this->highest_ptr(tc);
477
478 return this->highest_ptr(( (tcolor == Card::diamond)
479 ? Card::heart
480 : Card::diamond),
481 ( (tcolor <= Card::heart)
482 ? Card::spade
483 : Card::heart),
484 ( (tcolor <= Card::spade)
485 ? Card::club
486 : Card::spade),
487 ( (tcolor <= Card::club)
488 ? Card::trump
489 : Card::club)
490 );
491 } // WeightedCardList::iterator WeightedCardList::highest_ptr_not_of(Card::TColor const tcolor) const
492
493 /** -> result
494 **
495 ** @param card card to return the (heighest) weighting of
496 **
497 ** @return the (highest) weighting weighting of 'card'
498 ** INT_MIN, if none exists
499 **/
500 int
weighting(Card const card) const501 WeightedCardList::weighting(Card const card) const
502 {
503 // search the card in the pointers
504 for (auto ptr
505 = this->tcolor_ptr[card.tcolor(this->game())];
506 ptr != this->end();
507 ++ptr)
508 if (ptr->second == card)
509 return ptr->first;
510
511 return INT_MIN;
512 } // int WeightedCardList::weighting(Card card) const
513
514 /** remove the highest card
515 **/
516 void
pop_highest()517 WeightedCardList::pop_highest()
518 {
519 if (this->empty())
520 return ;
521
522 // the tcolor of the card to remove
523 auto const tcolor = this->front().second.tcolor(this->game());
524
525 // remove the card
526 this->pop_front();
527
528 // adjust the positions
529 for (unsigned tc = 0; tc < Card::number_of_tcolors; ++tc)
530 if (this->tcolor_pos[tc] >= 0)
531 this->tcolor_pos[tc] -= 1;
532
533 // search the first of 'tcolor' in the list
534 this->recreate_tcolor_ptr(tcolor);
535 } // void WeightedCardList::pop_highest()
536
537 /** remove the highest card of the tcolor
538 **
539 ** @param tcolor tcolor to remove the highest card from
540 **/
541 void
pop_highest(Card::TColor const tcolor)542 WeightedCardList::pop_highest(Card::TColor const tcolor)
543 {
544 // search the card in the pointers
545 auto& ptr = this->tcolor_ptr[tcolor];
546 if (ptr == this->end())
547 return ;
548
549 int& pos = this->tcolor_pos[tcolor];
550 // update the pos of the further tcolors
551 for (unsigned tc = 0; tc < Card::number_of_tcolors; ++tc)
552 if (this->tcolor_pos[tc] > pos)
553 this->tcolor_pos[tc] += 1;
554 // remove the pointer
555 ptr = this->erase(ptr);
556 for (; ptr != this->end(); ++ptr, ++pos)
557 if (ptr->second.tcolor(this->game()) == tcolor)
558 break;
559 if (ptr == this->end())
560 pos = -1;
561 } // void WeightedCardList::pop_highest(Card::TColor tcolor)
562
563 /** remove the highest card not of the tcolor
564 **
565 ** @param tcolor tcolor to remove the highest card from
566 **
567 ** @todo own code (for better performance)
568 **/
569 void
pop_highest_not_of(Card::TColor const tcolor)570 WeightedCardList::pop_highest_not_of(Card::TColor const tcolor)
571 {
572 this->pop(this->highest_not_of(tcolor));
573 } // void WeightedCardList::pop_highest_not_of(Card::TColor tcolor)
574
575 /** remove the given card
576 **
577 ** @param card card to remove
578 **/
579 void
pop(Card const card)580 WeightedCardList::pop(Card const card)
581 {
582 // search the card in the pointers
583 auto const tcolor = card.tcolor(this->game());
584 auto& ptr = this->tcolor_ptr[tcolor];
585 if ( (ptr != this->end())
586 && (ptr->second == card) ) {
587 int& pos = this->tcolor_pos[tcolor];
588 // update the pos of the further tcolors
589 for (unsigned tc = 0; tc < Card::number_of_tcolors; ++tc)
590 if (this->tcolor_pos[tc] > pos)
591 this->tcolor_pos[tc] += 1;
592 // remove the pointer
593 ptr = this->erase(ptr);
594 for (; ptr != this->end(); ++ptr, ++pos)
595 if (ptr->second.tcolor(this->game()) == tcolor)
596 break;
597 if (ptr == this->end())
598 pos = -1;
599 } else { // if !(this->tcolor_ptr[tcolor].second == card)
600 int pos = this->tcolor_pos[tcolor];
601 for (; ptr != this->end(); ++ptr, ++pos)
602 if (ptr->second == card)
603 break;
604 DEBUG_ASSERTION(ptr != this->end(),
605 "WeightedCardList::pop(card)\n"
606 " card '" << card << "' not found in the list:\n"
607 << *this);
608 ptr = this->erase(ptr);
609 // update the pos of the further tcolors
610 for (unsigned tc = 0; tc < Card::number_of_tcolors; ++tc)
611 if (this->tcolor_pos[tc] > pos)
612 this->tcolor_pos[tc] -= 1;
613 } // if !(this->tcolor_ptr[tcolor].second == card)
614 } // void WeightedCardList::pop(Card card)
615
616 /** recreate the pointers to the highest card of each tcolor
617 **/
618 void
recreate_tcolor_ptrs()619 WeightedCardList::recreate_tcolor_ptrs()
620 {
621 // search the first of 'tcolor' in the list
622 for (unsigned tcolor = 0; tcolor < Card::number_of_tcolors; ++tcolor)
623 this->recreate_tcolor_ptr(static_cast<Card::TColor>(tcolor));
624 } // void WeightedCardList::recreate_tcolor_ptrs()
625
626 /** recreate the pointer to the highest card of the tcolor
627 **
628 ** @param tcolor tcolor to recreate the pointer of
629 **/
630 void
recreate_tcolor_ptr(Card::TColor const tcolor)631 WeightedCardList::recreate_tcolor_ptr(Card::TColor const tcolor)
632 {
633 // search the first of 'tcolor' in the list
634 int& pos = this->tcolor_pos[tcolor];
635 auto& ptr = this->tcolor_ptr[tcolor];
636 for (pos = 0, ptr = this->begin(); ptr != this->end(); ++ptr, ++pos)
637 if (ptr->second.tcolor(this->game()) == tcolor)
638 break;
639 if (ptr == this->end())
640 pos = -1;
641 } // void WeightedCardList::recreate_tcolor_ptr(Card::TColor tcolor)
642
643 /** write 'card_list' in 'ostr'
644 **
645 ** @param ostr output stream
646 ** @param card_list card list to write
647 **/
648 ostream&
operator <<(ostream & ostr,WeightedCardList const & card_list)649 operator<<(ostream& ostr, WeightedCardList const& card_list)
650 {
651 card_list.write(ostr);
652 return ostr;
653 } // ostream& operator<<(ostream& ostr, WeightedCardList card_list)
654