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