features_private_impl.h 35.5 KB
Newer Older
1
/* tarot implements the rules of the tarot game
2
 * Copyright (C) 2019, 2020  Vivien Kraus
3
 *
4
5
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation, version 3 of the License.
7
8
9
10
11
12
13
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
14
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16
17
18
19
20
21
22
 */

#ifndef H_TAROT_FEATURES_PRIVATE_IMPL_INCLUDED
#define H_TAROT_FEATURES_PRIVATE_IMPL_INCLUDED

#include <tarot/game_private.h>
#include <tarot/game_event_private.h>
#include <tarot/cards_private.h>
23
#include <tarot/counter_private.h>
24
25
26
27
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
28
#include <float.h>
29
#include <errno.h>
30
#include "xalloc.h"
31

32
static inline void
33
34
35
36
37
38
features_variant (const TarotGame * game, size_t *n_players, int *with_call)
{
  *n_players = game_n_players (game);
  *with_call = game_with_call (game);
}

39
static inline void
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
features_position (const TarotGame * game, size_t *i_trick, size_t *position)
{
  TarotPlayer myself, leader;
  *i_trick = 0;
  if (game_get_main_player (game, &myself) != TAROT_GAME_OK)
    {
      *position = 0;
    }
  else
    {
      *position = (size_t) myself;
    }
  if (game_get_current_trick (game, i_trick) != TAROT_GAME_OK)
    {
      *i_trick = 0;
    }
  if (game_get_trick_leader (game, *i_trick, &leader) == TAROT_GAME_OK)
    {
Vivien Kraus's avatar
Vivien Kraus committed
58
      if (leader > *position)
59
60
61
        {
          *position += game_n_players (game);
        }
Vivien Kraus's avatar
Vivien Kraus committed
62
      assert (leader <= *position);
63
64
65
66
      *position -= leader;
    }
}

67
static inline void
68
69
70
71
72
73
74
75
76
77
78
features_partner_known (const TarotGame * game, int *known)
{
  TarotPlayer partner;
  *known = 0;
  if (!game_with_call (game)
      || game_get_partner (game, &partner) == TAROT_GAME_OK)
    {
      *known = 1;
    }
}

79
static inline void
80
81
82
83
84
85
86
87
features_bid_minimum (const TarotGame * game, TarotBid * minimum)
{
  TarotPlayer taker;
  size_t n_bids;
  game_get_taker (game, &taker);
  if (taker < game_n_players (game)
      && game_get_bids (game, &n_bids, taker, 1, minimum) == TAROT_GAME_OK)
    {
88
89
90
91
92
93
94
95
      if (n_bids == 0)
        {
          *minimum = TAROT_PASS;
        }
      else
        {
          /* minimum is set */
        }
96
97
98
99
100
101
102
    }
  else
    {
      *minimum = TAROT_PASS;
    }
}

103
static inline size_t
104
105
106
features_get_my_cards (const TarotGame * game, size_t max, TarotCard * cards)
{
  TarotPlayer myself;
107
  if (game_get_next (game, &myself) == TAROT_GAME_OK)
108
109
110
111
112
    {
      size_t n_cards;
      if (game_get_cards (game, myself, &n_cards, 0, max, cards) ==
          TAROT_GAME_OK)
        {
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
          size_t n_dog;
          TarotCard dog[6];
          TarotPlayer taker;
          game_get_taker (game, &taker);
          if (game_step (game) == TAROT_DOG
              && taker == myself
              && game_get_dog (game, &n_dog, 0, 6, dog) == TAROT_GAME_OK)
            {
              size_t i = 0;
              assert (n_dog <= 6);
              for (i = 0; i < n_dog; i++)
                {
                  if (n_cards < max)
                    {
                      cards[n_cards] = dog[i];
                    }
                  n_cards++;
                }
            }
132
133
134
135
136
137
          return n_cards;
        }
    }
  return 0;
}

138
static inline void
139
features_count_faces (const TarotGame * game,
140
141
142
143
                      size_t *n_kings,
                      size_t *n_marriages,
                      size_t *n_extended_marriages,
                      size_t *n_queens, size_t *n_knights)
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
{
  TarotCard my_cards[78];
  size_t n_cards = features_get_my_cards (game, 78, my_cards);
  size_t i;
  int has_knight[4] = { 0, 0, 0, 0 };
  int has_queen[4] = { 0, 0, 0, 0 };
  int has_king[4] = { 0, 0, 0, 0 };
  *n_kings = 0;
  *n_marriages = 0;
  *n_extended_marriages = 0;
  *n_queens = 0;
  *n_knights = 0;
  assert (n_cards <= 78);
  for (i = 0; i < n_cards; i++)
    {
      TarotNumber number;
      TarotSuit suit;
      if (decompose (my_cards[i], &number, &suit) == 0
          && suit != TAROT_TRUMPS && number >= TAROT_KNIGHT)
        {
          size_t suit_index = (size_t) suit;
          assert (suit_index < 4);
          switch (number)
            {
            case TAROT_KNIGHT:
              assert (!has_knight[suit_index]);
              has_knight[suit_index] = 1;
              break;
            case TAROT_QUEEN:
              assert (!has_queen[suit_index]);
              has_queen[suit_index] = 1;
              break;
            case TAROT_KING:
              assert (!has_king[suit_index]);
              has_king[suit_index] = 1;
              break;
            default:
              assert (0);
            }
        }
    }
  for (i = 0; i < 4; i++)
    {
      *n_kings += has_king[i];
      *n_marriages += has_king[i] && has_queen[i];
      *n_extended_marriages += has_king[i] && has_queen[i] && has_knight[i];
      *n_queens += has_queen[i];
      *n_knights += has_knight[i];
    }
}

195
static inline void
196
features_count_minor (const TarotGame * game,
197
198
199
200
                      size_t *n_shortest,
                      size_t *n_second_shortest,
                      size_t *n_second_longest, size_t *n_longest,
                      TarotSuit * suit_order)
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
{
  TarotCard my_cards[78];
  size_t n_cards = features_get_my_cards (game, 78, my_cards);
  size_t i;
  size_t n_by_suit[4] = { 0, 0, 0, 0 };
  size_t size_sorted;
  *n_shortest = 0;
  *n_second_shortest = 0;
  *n_second_longest = 0;
  *n_longest = 0;
  suit_order[0] = TAROT_HEARTS;
  suit_order[1] = TAROT_CLUBS;
  suit_order[2] = TAROT_DIAMONDS;
  suit_order[3] = TAROT_SPADES;
  assert (n_cards <= 78);
  for (i = 0; i < n_cards; i++)
    {
      TarotNumber number;
      TarotSuit suit;
      if (decompose (my_cards[i], &number, &suit) == 0
          && suit != TAROT_TRUMPS)
        {
          size_t suit_index = (size_t) suit;
          assert (suit_index < 4);
          n_by_suit[suit_index]++;
        }
    }
  for (size_sorted = 1; size_sorted < 4; size_sorted++)
    {
      size_t inserted = size_sorted;
      while (inserted > 0 && n_by_suit[inserted - 1] > n_by_suit[inserted])
        {
          size_t n_inserted = n_by_suit[inserted];
234
          TarotSuit suit_inserted = suit_order[inserted];
235
236
          n_by_suit[inserted] = n_by_suit[inserted - 1];
          n_by_suit[inserted - 1] = n_inserted;
237
238
          suit_order[inserted] = suit_order[inserted - 1];
          suit_order[inserted - 1] = suit_inserted;
239
240
241
242
243
244
245
246
247
248
249
250
251
          inserted--;
        }
    }
  for (i = 0; i + 1 < 4; i++)
    {
      assert (n_by_suit[i] <= n_by_suit[i + 1]);
    }
  *n_shortest = n_by_suit[0];
  *n_second_shortest = n_by_suit[1];
  *n_second_longest = n_by_suit[2];
  *n_longest = n_by_suit[3];
}

252
static inline void
253
254
features_count_oudlers (const TarotGame * game,
                        int *has_petit, int *has_excuse, int *has_twentyone)
255
256
257
258
259
260
261
262
263
264
{
  TarotCard my_cards[78];
  size_t n_cards = features_get_my_cards (game, 78, my_cards);
  size_t i;
  *has_petit = 0;
  *has_excuse = 0;
  *has_twentyone = 0;
  for (i = 0; i < n_cards; i++)
    {
      if (my_cards[i] == TAROT_PETIT)
265
266
267
        {
          *has_petit = 1;
        }
268
      else if (my_cards[i] == TAROT_EXCUSE)
269
270
271
        {
          *has_excuse = 1;
        }
272
      else if (my_cards[i] == TAROT_TWENTYONE)
273
274
275
        {
          *has_twentyone = 1;
        }
276
277
278
    }
}

279
static inline void
280
features_count_trumps (const TarotGame * game,
281
282
283
284
285
                       size_t *n_trumps,
                       TarotNumber * max_trump,
                       TarotNumber * min_trump,
                       TarotNumber * q1_trumps,
                       TarotNumber * q3_trumps, TarotNumber * median_trump)
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
{
  TarotCard my_cards[78];
  size_t n_cards = features_get_my_cards (game, 78, my_cards);
  size_t i;
  TarotNumber my_trumps[21];
  size_t my_n_trumps = 0;
  *max_trump = 0;
  *min_trump = 0;
  *q1_trumps = 0;
  *q3_trumps = 0;
  *median_trump = 0;
  for (i = 0; i < n_cards; i++)
    {
      TarotNumber number;
      TarotSuit suit;
      if (decompose (my_cards[i], &number, &suit) == 0
          && suit == TAROT_TRUMPS)
        {
          assert (my_n_trumps < 21);
          if (my_n_trumps > 0)
            {
              assert (my_trumps[my_n_trumps - 1] < number);
            }
          my_trumps[my_n_trumps++] = number;
        }
    }
  *n_trumps = my_n_trumps;
  if (my_n_trumps != 0)
    {
      double size_d = (double) my_n_trumps;
      double size_q1 = size_d / 4;
      double size_med = size_d / 2;
      double size_q3 = 3 * size_d / 4;
      *max_trump = my_trumps[my_n_trumps - 1];
      *min_trump = my_trumps[0];
      *q1_trumps = my_trumps[(size_t) size_q1];
      *q3_trumps = my_trumps[(size_t) size_q3];
      *median_trump = my_trumps[(size_t) size_med];
    }
}

327
static inline void
328
329
strategy_bid (const TarotGame * game,
              const TarotGameEvent * event, TarotBid * bid)
330
331
{
  (void) game;
332
333
334
  if (event_get_bid (event, bid) != TAROT_EVENT_OK)
    {
      *bid = TAROT_PASS;
335
336
337
    }
}

338
static inline void
339
340
strategy_outbid (const TarotGame * game,
                 const TarotGameEvent * event, int *outbid)
341
342
343
344
345
346
347
348
349
350
351
352
{
  TarotBid minimum;
  TarotBid actual;
  TarotPlayer next;
  *outbid = 0;
  if (game_get_hint_bid (game, &next, &minimum) == TAROT_GAME_OK
      && event_get_bid (event, &actual) == TAROT_EVENT_OK)
    {
      *outbid = ((int) actual) - ((int) minimum);
    }
}

353
static inline void
354
355
356
357
358
strategy_call_by_length (const TarotGame * game,
                         const TarotGameEvent * event,
                         int *shortest,
                         int *second_shortest,
                         int *second_longest, int *longest)
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
{
  TarotCard my_cards[78];
  size_t n_cards = features_get_my_cards (game, 78, my_cards);
  size_t i;
  size_t n_by_suit[4] = { 0, 0, 0, 0 };
  size_t n_fewer = 0;
  size_t n_more = 0;
  TarotSuit call_suit;
  TarotNumber call_number;
  TarotCard call;
  *shortest = 0;
  *second_shortest = 0;
  *second_longest = 0;
  *longest = 0;
  assert (n_cards <= 78);
  if (event_get_call (event, &call) != TAROT_EVENT_OK)
    {
      return;
    }
  if (decompose (call, &call_number, &call_suit) != 0)
    {
      return;
    }
382
383
384
385
  if (call_suit == TAROT_TRUMPS)
    {
      return;
    }
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
  for (i = 0; i < n_cards; i++)
    {
      TarotNumber number;
      TarotSuit suit;
      if (decompose (my_cards[i], &number, &suit) == 0
          && suit != TAROT_TRUMPS)
        {
          size_t suit_index = (size_t) suit;
          assert (suit_index < 4);
          n_by_suit[suit_index]++;
        }
    }
  n_fewer = n_more = 0;
  for (i = 0; i < 4; i++)
    {
      if (n_by_suit[i] < n_by_suit[(size_t) call_suit])
402
403
404
        {
          n_fewer++;
        }
405
      if (n_by_suit[i] > n_by_suit[(size_t) call_suit])
406
407
408
        {
          n_more++;
        }
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
    }
  switch (n_fewer)
    {
    case 0:
      *shortest = 1;
      break;
    case 1:
      *second_shortest = 1;
      break;
    case 2:
      *second_longest = 1;
      break;
    case 3:
      *longest = 1;
      break;
    default:
      assert (0);
    }
  switch (n_more)
    {
    case 0:
      *longest = 1;
      break;
    case 1:
      *second_longest = 1;
      break;
    case 2:
      *second_shortest = 1;
      break;
    case 3:
      *shortest = 1;
      break;
    default:
      assert (0);
    }
}

446
static inline void
447
448
strategy_call_myself (const TarotGame * game,
                      const TarotGameEvent * event, int *myself)
449
450
451
452
453
454
455
456
457
458
459
460
461
462
{
  TarotCard my_cards[78];
  size_t n_cards = features_get_my_cards (game, 78, my_cards);
  size_t i;
  TarotCard call;
  *myself = 0;
  assert (n_cards <= 78);
  if (event_get_call (event, &call) != TAROT_EVENT_OK)
    {
      return;
    }
  for (i = 0; i < n_cards; i++)
    {
      if (my_cards[i] == call)
463
464
465
        {
          *myself = 1;
        }
466
467
468
    }
}

469
static inline void
470
471
strategy_call_marriage (const TarotGame * game,
                        const TarotGameEvent * event, int *will_own_marriage)
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
{
  TarotCard my_cards[78];
  size_t n_cards = features_get_my_cards (game, 78, my_cards);
  size_t i;
  TarotCard call;
  TarotNumber call_number;
  TarotSuit call_suit;
  TarotNumber spouse_number;
  TarotCard spouse;
  *will_own_marriage = 0;
  assert (n_cards <= 78);
  if (event_get_call (event, &call) != TAROT_EVENT_OK)
    {
      return;
    }
  if (decompose (call, &call_number, &call_suit) != 0)
    {
      return;
    }
  switch (call_number)
    {
    case TAROT_KING:
      spouse_number = TAROT_QUEEN;
      break;
    case TAROT_QUEEN:
      spouse_number = TAROT_KING;
      break;
    default:
      return;
    }
  if (of (spouse_number, call_suit, &spouse) != 0)
    {
      assert (0);
    }
  assert (spouse == call + 1 || spouse + 1 == call);
  for (i = 0; i < n_cards; i++)
    {
      if (my_cards[i] == spouse)
510
511
512
        {
          *will_own_marriage = 1;
        }
513
514
515
516
517
518
    }
}

/* For each of the 78 cards, set its status to 0 by default, or +1 if
   we own that card, or +2 if we do not own it, do not discard it and
   call it, or -1 if we own it and discard it. */
519
static inline void
520
521
features_get_status (const TarotGame * game,
                     const TarotGameEvent * event, int *status)
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
{
  size_t i = 0;
  TarotCard my_cards[78];
  TarotCard discard[6];
  size_t n_cards = features_get_my_cards (game, 78, my_cards);
  size_t n_discard;
  TarotCard call;
  for (i = 0; i < 78; i++)
    {
      status[i] = 0;
    }
  assert (n_cards <= 78);
  if (event_get_discard (event, &n_discard, 0, 6, discard) != TAROT_EVENT_OK)
    {
      return;
    }
  assert (n_discard <= 6);
  for (i = 0; i < n_cards; i++)
    {
      status[my_cards[i]] = +1;
    }
  if (game_get_call (game, &call) == TAROT_GAME_OK)
    {
      status[call] = +2;
    }
  for (i = 0; i < n_discard; i++)
    {
      status[discard[i]] = -1;
    }
}

553
static inline void
554
555
556
strategy_discard_save (const TarotGame * game,
                       const TarotGameEvent * event,
                       size_t *queens, size_t *knights, size_t *jacks)
557
558
{
  int status[78] = { 0 };
559
560
  static const TarotSuit minor_suits[4] =
    { TAROT_HEARTS, TAROT_CLUBS, TAROT_DIAMONDS, TAROT_SPADES };
561
562
563
564
565
566
567
568
569
570
  size_t i;
  *queens = 0;
  *knights = 0;
  *jacks = 0;
  features_get_status (game, event, status);
  for (i = 0; i < 4; i++)
    {
      TarotSuit suit = minor_suits[i];
      TarotCard king, queen, knight, jack;
      if (of (TAROT_KING, suit, &king) != 0
571
572
573
574
575
576
          || of (TAROT_QUEEN, suit, &queen) != 0
          || of (TAROT_KNIGHT, suit, &knight) != 0
          || of (TAROT_JACK, suit, &jack) != 0)
        {
          assert (0);
        }
577
      if (status[king] == 0 && status[queen] < 0)
578
579
580
581
582
583
584
        {
          *queens += 1;
        }
      if ((status[king] == 0 || status[queen] == 0) && status[knight] < 0)
        {
          *knights += 1;
        }
585
      if ((status[king] == 0 || status[queen] == 0 || status[knight] == 0)
586
587
588
589
          && status[jack] < 0)
        {
          *jacks += 1;
        }
590
591
592
    }
}

593
static inline void
594
595
strategy_discard_junk (const TarotGame * game,
                       const TarotGameEvent * event, size_t *lesser)
596
597
{
  int status[78] = { 0 };
598
599
  static const TarotSuit minor_suits[4] =
    { TAROT_HEARTS, TAROT_CLUBS, TAROT_DIAMONDS, TAROT_SPADES };
600
601
602
603
604
605
606
  size_t i;
  *lesser = 0;
  features_get_status (game, event, status);
  for (i = 0; i < 4; i++)
    {
      TarotSuit suit = minor_suits[i];
      TarotCard ace, ten, c;
607
608
609
610
      if (of (TAROT_ACE, suit, &ace) != 0 || of (10, suit, &ten) != 0)
        {
          assert (0);
        }
611
      /* Check if we discarded any minor card of that suit */
612
      for (c = ace; c <= ten && status[c] >= 0; c++);
613
      if (c <= ten)
614
615
616
617
618
619
620
621
622
        {
          for (c = ace; c <= ten && status[c] >= 0; c++)
            {
              if (status[c] > 0)
                {
                  *lesser += 1;
                }
            }
        }
623
624
625
    }
}

626
static inline void
627
628
629
630
631
strategy_discard_by_length (const TarotGame * game,
                            const TarotGameEvent * event,
                            size_t *shortest,
                            size_t *second_shortest,
                            size_t *second_longest, size_t *longest)
632
633
634
635
636
637
638
639
640
641
642
643
644
645
{
  TarotSuit suit_order[4];
  size_t i = 0;
  TarotCard discard[6];
  size_t n_discard;
  size_t n_shortest;
  size_t n_second_shortest;
  size_t n_second_longest;
  size_t n_longest;
  *shortest = 0;
  *second_shortest = 0;
  *second_longest = 0;
  *longest = 0;
  features_count_minor (game, &n_shortest, &n_second_shortest,
646
                        &n_second_longest, &n_longest, suit_order);
647
648
649
650
651
652
653
654
655
656
  if (event_get_discard (event, &n_discard, 0, 6, discard) != TAROT_EVENT_OK)
    {
      return;
    }
  assert (n_discard <= 6);
  for (i = 0; i < n_discard; i++)
    {
      TarotNumber n;
      TarotSuit s;
      if (decompose (discard[i], &n, &s) != 0)
657
658
659
        {
          assert (0);
        }
660
      if (s == suit_order[0])
661
662
663
        {
          *shortest += 1;
        }
664
      else if (s == suit_order[1])
665
666
667
        {
          *second_shortest += 1;
        }
668
      else if (s == suit_order[2])
669
670
671
        {
          *second_longest += 1;
        }
672
      else
673
674
675
676
        {
          assert (s == suit_order[3]);
          *longest += 1;
        }
677
678
679
    }
}

680
static inline void
681
get_teams (const TarotGame * game, int *attack)
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
{
  size_t n_players = game_n_players (game), i;
  TarotPlayer taker, partner;
  assert (n_players <= 5);
  game_get_taker (game, &taker);
  if (game_get_partner (game, &partner) != TAROT_GAME_OK)
    {
      partner = taker;
    }
  for (i = 0; i < n_players; i++)
    {
      attack[i] = 0;
    }
  attack[taker] = 1;
  attack[partner] = 1;
}

699
static inline void
700
features_team (const TarotGame * game, int *attack, int *defence)
701
702
703
704
705
706
707
708
709
710
711
712
713
{
  TarotPlayer myself;
  int teams[5];
  *attack = 0;
  *defence = 0;
  get_teams (game, teams);
  if (tarot_game_get_main_player (game, &myself) == TAROT_GAME_OK)
    {
      *attack = teams[myself];
      *defence = 1 - teams[myself];
    }
}

714
static inline void
715
716
717
features_trick_players (const TarotGame * game,
                        size_t *n_already_played,
                        size_t *n_allies_after_last_opponent)
718
719
720
721
722
{
  size_t i_trick;
  size_t n_players = game_n_players (game), i, n_cards;
  TarotPlayer leader, myself;
  int teams[5];
Vivien Kraus's avatar
Vivien Kraus committed
723
  TarotPlayer partner;
724
725
726
727
728
729
730
731
732
733
734
735
  *n_already_played = 0;
  *n_allies_after_last_opponent = 0;
  if (game_get_current_trick (game, &i_trick) != TAROT_GAME_OK
      || game_get_main_player (game, &myself) != TAROT_GAME_OK)
    {
      return;
    }
  if (game_get_trick_leader (game, i_trick, &leader) != TAROT_GAME_OK)
    {
      return;
    }
  assert (leader < n_players);
736
737
  if (game_get_trick_cards (game, i_trick, &n_cards, 0, 0, NULL) ==
      TAROT_GAME_OK)
738
739
740
741
    {
      *n_already_played = n_cards;
    }
  get_teams (game, teams);
742
  assert (n_players >= 3 && n_players <= 5);
Vivien Kraus's avatar
Vivien Kraus committed
743
744
  if (!game_with_call (game)
      || game_get_partner (game, &partner) == TAROT_GAME_OK)
745
    {
Vivien Kraus's avatar
Vivien Kraus committed
746
747
748
749
      size_t last_opponent;     /* Number of players that have played before
                                 * the last opponent */
      last_opponent = n_cards;
      for (i = n_cards + 1; i < n_players; i++)
750
        {
Vivien Kraus's avatar
Vivien Kraus committed
751
752
753
754
755
756
757
          TarotPlayer player = (leader + i) % n_players;
          int team = teams[player];
          int is_ally = (team == teams[myself]);
          if (!is_ally)
            {
              last_opponent = i;
            }
758
        }
Vivien Kraus's avatar
Vivien Kraus committed
759
      *n_allies_after_last_opponent = n_players - last_opponent - 1;
760
761
762
    }
}

763
static inline void
764
765
766
767
768
769
may_play_in_trick (const TarotCounter * counter,
                   size_t n_players,
                   TarotPlayer first_forced,
                   size_t n_forced,
                   const TarotCard * forced_cards,
                   TarotCard candidate, int *may_play)
770
771
772
773
774
{
  size_t i;
  assert (n_players <= 5);
  for (i = 0; i < n_players; i++)
    {
Vivien Kraus's avatar
Vivien Kraus committed
775
      TarotPlayer player = (i + first_forced) % n_players;
776
      if (i < n_forced)
777
        {
Vivien Kraus's avatar
Vivien Kraus committed
778
          may_play[player] = (candidate == forced_cards[i]);
779
        }
780
      else
781
        {
Vivien Kraus's avatar
Vivien Kraus committed
782
          may_play[player] = counter_may_own (counter, 1, &player, candidate);
783
        }
784
785
786
    }
}

787
static inline int
788
789
790
791
find_master (const TarotGame * game,
             const TarotCounter * counter,
             TarotCard least_candidate,
             TarotCard strongest_candidate, int *may_play)
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
{
  size_t n_players = game_n_players (game);
  size_t i_trick;
  size_t i_candidate;
  TarotGameCardAnalysis cards_full[5];
  TarotCard cards[5];
  size_t n_cards, i_card;
  TarotPlayer leader;
  if (game_get_current_trick (game, &i_trick) != TAROT_GAME_OK)
    {
      return 1;
    }
  if (game_get_trick_leader (game, i_trick, &leader) != TAROT_GAME_OK)
    {
      return 1;
    }
808
809
  if (game_get_trick_cards (game, i_trick, &n_cards, 0, 5, cards_full) !=
      TAROT_GAME_OK)
810
811
812
813
814
815
816
    {
      return 1;
    }
  for (i_card = 0; i_card < n_cards; i_card++)
    {
      cards[i_card] = cards_full[i_card].card;
    }
817
818
  for (i_candidate = 0;
       i_candidate < strongest_candidate - least_candidate + 1; i_candidate++)
819
820
821
    {
      TarotCard candidate = strongest_candidate - i_candidate;
      TarotPlayer i;
822
823
      may_play_in_trick (counter, n_players, leader, n_cards, cards,
                         candidate, may_play);
824
      for (i = 0; i < n_players; i++)
825
826
827
828
829
830
        {
          if (may_play[i])
            {
              return 0;
            }
        }
831
832
833
834
    }
  return 0;
}

835
static inline int
836
837
838
839
find_master_team (const TarotGame * game,
                  const TarotCounter * counter,
                  TarotCard least_candidate,
                  TarotCard strongest_candidate, int *ally, int *ennemy)
840
841
842
843
844
845
846
847
{
  int teams[5];
  int may_play[5] = { 0 };
  size_t i;
  TarotPlayer myself;
  get_teams (game, teams);
  *ally = 0;
  *ennemy = 0;
848
849
  if (find_master
      (game, counter, least_candidate, strongest_candidate, may_play) != 0)
850
851
852
853
854
855
856
857
858
859
860
861
    {
      return 1;
    }
  if (game_get_main_player (game, &myself) != 0)
    {
      return 1;
    }
  /* Since may_play has been initialized with extra zeros, this works
   * with 3 or 4 players too */
  for (i = 0; i < 5; i++)
    {
      if (may_play[i])
862
863
864
865
866
867
868
869
870
871
        {
          if (teams[i] == teams[myself])
            {
              *ally = 1;
            }
          else
            {
              *ennemy = 1;
            }
        }
872
873
874
875
    }
  return 0;
}

876
static inline int
877
get_called_suit (const TarotGame * game, TarotSuit * called)
878
879
880
881
882
883
{
  TarotCard call;
  if (game_get_call (game, &call) == TAROT_GAME_OK)
    {
      TarotNumber n;
      if (decompose (call, &n, called) != 0)
884
885
886
        {
          assert (0);
        }
887
888
889
890
891
      return 0;
    }
  return 1;
}

892
static inline size_t
893
count_times_lead (const TarotGame * game, TarotSuit suit)
894
895
896
897
898
899
900
901
902
903
904
905
906
{
  size_t current_trick;
  size_t trick;
  size_t ret = 0;
  if (game_get_current_trick (game, &current_trick) != TAROT_GAME_OK)
    {
      /* Fun fact: this is actually correct! */
      return 0;
    }
  for (trick = 0; trick <= current_trick; trick++)
    {
      TarotSuit lead_suit;
      if (game_get_lead_suit (game, trick, &lead_suit) == TAROT_GAME_OK)
907
908
909
        {
          ret += (suit == lead_suit);
        }
910
911
912
913
    }
  return ret;
}

914
static inline void
915
916
917
918
919
920
921
features_minor_suit (const TarotGame * game,
                     const TarotCounter * counter,
                     int *called_suit,
                     size_t *n_times_lead,
                     size_t *n_remaining_cards,
                     size_t *n_remaining_points,
                     int *ally_may_be_master, int *ennemy_may_be_master)
922
923
{
  TarotSuit the_called_suit, lead_suit;
924
  size_t i_trick;
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
  TarotCard first_of_lead_suit;
  TarotCard last_of_lead_suit;
  TarotCard card_of_lead_suit;
  size_t n_players = tarot_game_n_players (game);
  *called_suit = 0;
  *n_times_lead = 0;
  *n_remaining_cards = 0;
  *n_remaining_points = 0;
  *ally_may_be_master = 0;
  *ennemy_may_be_master = 0;
  assert (n_players <= 5);
  if (game_get_current_trick (game, &i_trick) != TAROT_GAME_OK)
    {
      return;
    }
  if (game_get_lead_suit (game, i_trick, &lead_suit) != TAROT_GAME_OK)
    {
      return;
    }
  if (get_called_suit (game, &the_called_suit) == 0)
    {
      *called_suit = (lead_suit == the_called_suit);
    }
  *n_times_lead = count_times_lead (game, lead_suit);
  if (of (1, lead_suit, &first_of_lead_suit) != 0)
    {
      assert (0);
    }
  if (lead_suit == TAROT_TRUMPS)
    {
      if (of (21, lead_suit, &last_of_lead_suit) != 0)
956
957
958
        {
          assert (0);
        }
959
960
961
962
    }
  else
    {
      if (of (TAROT_KING, lead_suit, &last_of_lead_suit) != 0)
963
964
965
        {
          assert (0);
        }
966
967
    }
  for (card_of_lead_suit = first_of_lead_suit;
968
969
970
971
972
973
974
975
976
977
978
979
       card_of_lead_suit <= last_of_lead_suit; card_of_lead_suit++)
    {
      TarotPlayer current_owner =
        counter->current_owner_of[card_of_lead_suit];
      static const size_t points[78] = {
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 5, 7, 9,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 5, 7, 9,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 5, 7, 9,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 5, 7, 9,
        9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9,
        1
      };
980
      if (current_owner == TAROT_COUNTER_CARD_OWNER_PLAYED
981
982
983
984
          || current_owner == TAROT_COUNTER_CARD_OWNER_DISCARDED)
        {
          /* This card is not available */
        }
985
      else
986
987
988
989
        {
          *n_remaining_cards += 1;
          *n_remaining_points += points[card_of_lead_suit];
        }
990
    }
991
992
993
994
  assert (*n_remaining_points <= 37);
  if (find_master_team
      (game, counter, first_of_lead_suit, last_of_lead_suit,
       ally_may_be_master, ennemy_may_be_master) != 0)
995
996
997
998
999
1000
    {
      *ally_may_be_master = 0;
      *ennemy_may_be_master = 0;
    }
}

1001
static inline void
1002
1003
1004
1005
features_trump (const TarotGame * game,
                const TarotCounter * counter,
                size_t *n_remaining,
                int *ally_may_be_master, int *ennemy_may_be_master)
1006
1007
1008
1009
1010
1011
1012
{
  TarotCard first = TAROT_PETIT;
  TarotCard last = TAROT_TWENTYONE;
  TarotCard card;
  size_t n_players = tarot_game_n_players (game);
  *n_remaining = 0;
  *ally_may_be_master = 0;
1013
  *ennemy_may_be_master = 0;
1014
1015
1016
1017
1018
  assert (n_players <= 5);
  for (card = first; card <= last; card++)
    {
      TarotPlayer current_owner = counter->current_owner_of[card];
      if (current_owner == TAROT_COUNTER_CARD_OWNER_PLAYED
1019
1020
1021
1022
          || current_owner == TAROT_COUNTER_CARD_OWNER_DISCARDED)
        {
          /* This card is not available */
        }
1023
      else
1024
1025
1026
        {
          *n_remaining += 1;
        }
1027
    }
1028
1029
1030
  if (find_master_team
      (game, counter, first, last, ally_may_be_master,
       ennemy_may_be_master) != 0)
1031
1032
1033
1034
1035
1036
    {
      *ally_may_be_master = 0;
      *ennemy_may_be_master = 0;
    }
}

1037
static inline void
1038
1039
features_points (const TarotGame * game,
                 size_t *n_halfpoints, size_t *n_oudlers)
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
{
  size_t n_cards;
  TarotGameCardAnalysis cards[5];
  size_t i_trick;
  size_t i_card;
  *n_oudlers = 0;
  *n_halfpoints = 0;
  if (game_get_current_trick (game, &i_trick) != TAROT_GAME_OK)
    {
      return;
    }
1051
1052
  if (game_get_trick_cards (game, i_trick, &n_cards, 0, 5, cards) !=
      TAROT_GAME_OK)
1053
1054
1055
1056
1057
1058
    {
      return;
    }
  assert (n_cards <= 5);
  for (i_card = 0; i_card < n_cards; i_card++)
    {
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
      static const unsigned int halfpoints[78] = {
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 5, 7, 9,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 5, 7, 9,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 5, 7, 9,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 5, 7, 9,
        9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9,
        1
      };
      static const int is_oudler[78] = {
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
        0
      };
1075
1076
1077
1078
1079
      *n_oudlers += is_oudler[cards[i_card].card];
      *n_halfpoints += halfpoints[cards[i_card].card];
    }
}

1080
static inline void
1081
1082
1083
1084
1085
strategy_lead (const TarotGame * game,
               const TarotCounter * counter,
               const TarotGameEvent * event,
               int *called_suit,
               size_t *suit_length, size_t *n_times_lead, int *trumps)
1086
1087
1088
1089
1090
{
  TarotCard card;
  int is_decomposable;
  TarotSuit card_suit;
  TarotNumber card_number;
1091
  (void) counter;
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
  *called_suit = 0;
  *suit_length = 0;
  *n_times_lead = 0;
  *trumps = 0;
  if (event_get_card (event, &card) != TAROT_EVENT_OK)
    {
      return;
    }
  is_decomposable = (decompose (card, &card_number, &card_suit) == 0);
  if (is_decomposable)
    {
      TarotCard my_cards[78];
1104
1105
1106
      size_t n_my_cards =
        features_get_my_cards (game, sizeof (my_cards) / sizeof (*my_cards),
                               my_cards);
1107
1108
1109
1110
1111
1112
1113
1114
      size_t i_card;
      TarotCard first;
      TarotCard last;
      TarotNumber first_number = 1;
      TarotNumber last_number = TAROT_KING;
      size_t n_of_suit = 0;
      TarotSuit call_suit;
      if (card_suit == TAROT_TRUMPS)
1115
1116
1117
        {
          last_number = 21;
        }
1118
      if (of (first_number, card_suit, &first) != 0
1119
1120
1121
1122
          || of (last_number, card_suit, &last) != 0)
        {
          assert (0);
        }
1123
      for (i_card = 0; i_card < n_my_cards; i_card++)
1124
1125
1126
1127
1128
1129
        {
          if (my_cards[i_card] >= first && my_cards[i_card] <= last)
            {
              n_of_suit++;
            }
        }
1130
      if (get_called_suit (game, &call_suit) == 0)
1131
1132
1133
        {
          *called_suit = (call_suit == card_suit);
        }
1134
1135
1136
1137
1138
1139
      *suit_length = n_of_suit;
      *n_times_lead = count_times_lead (game, card_suit);
      *trumps = (card_suit == TAROT_TRUMPS);
    }
}

1140
static inline void
1141
1142
1143
1144
1145
strategy_purity (const TarotGame * game,
                 const TarotGameEvent * event,
                 size_t *n_smaller_kept,
                 size_t *n_greater_nonface_kept,
                 size_t *n_points_kept, size_t *n_greater_kept)
1146
1147
1148
1149
1150
1151
1152
1153
1154
{
  TarotCard card;
  int is_decomposable;
  TarotSuit card_suit;
  TarotNumber card_number;
  *n_smaller_kept = 0;
  *n_greater_nonface_kept = 0;
  *n_points_kept = 0;
  *n_greater_kept = 0;
1155
1156
1157
1158
  if (event_get_card (event, &card) != TAROT_EVENT_OK)
    {
      return;
    }
1159
1160
1161
1162
  is_decomposable = (decompose (card, &card_number, &card_suit) == 0);
  if (is_decomposable)
    {
      TarotCard my_cards[78];
1163
1164
1165
      size_t n_my_cards =
        features_get_my_cards (game, sizeof (my_cards) / sizeof (*my_cards),
                               my_cards);
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
      size_t i_card;
      TarotCard first;
      TarotCard last_nonface;
      TarotCard last;
      TarotNumber first_number = 1;
      TarotNumber last_nonface_number = 10;
      TarotNumber last_number = TAROT_KING;
      size_t n_lesser = 0;
      size_t n_greater_nonface = 0;
      size_t n_greater = 0;
      size_t n_points = 0;
      if (card_suit == TAROT_TRUMPS)
1178
1179
1180
1181
        {
          last_nonface_number = 21;
          last_number = 21;
        }
1182
      if (of (first_number, card_suit, &first) != 0
1183
1184
1185
1186
1187
          || of (last_nonface_number, card_suit, &last_nonface) != 0
          || of (last_number, card_suit, &last) != 0)
        {
          assert (0);
        }
1188
      for (i_card = 0; i_card < n_my_cards; i_card++)
1189
1190
1191
1192
1193
        {
          if (my_cards[i_card] >= first && my_cards[i_card] < card)
            {
              n_lesser++;
            }
Vivien Kraus's avatar
Vivien Kraus committed
1194
          if (my_cards[i_card] > card && my_cards[i_card] <= last_nonface)
1195
1196
1197
            {
              n_greater_nonface++;
            }
Vivien Kraus's avatar
Vivien Kraus committed
1198
          if (my_cards[i_card] > card && my_cards[i_card] <= last)
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
            {
              n_greater++;
            }
          if (my_cards[i_card] >= first && my_cards[i_card] <= last
              && my_cards[i_card] != card)
            {
              static const unsigned int halfpoints[78] = {
                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 5, 7, 9,
                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 5, 7, 9,
                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 5, 7, 9,
                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 5, 7, 9,
                9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9,
                1
              };
              n_points += halfpoints[my_cards[i_card]];
            }
        }
1216
1217
1218
1219
1220
1221
1222
      *n_smaller_kept = n_lesser;
      *n_greater_nonface_kept = n_greater_nonface;
      *n_greater_kept = n_greater;
      *n_points_kept = n_points;
    }
}

1223
static inline void
1224
1225
strategy_excuse (const TarotGame * game,
                 const TarotGameEvent * event, int *excuse)
1226
1227
{
  TarotCard card;
1228
  (void) game;
1229
1230
1231
1232
1233
1234
1235
  *excuse = 0;
  if (event_get_card (event, &card) == TAROT_EVENT_OK)
    {
      *excuse = (card == TAROT_EXCUSE);
    }
}

1236
static inline size_t
1237
who_plays_after_me (const TarotGame * game, TarotPlayer * p)
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
{
  size_t i_trick, ret, i, n_cards, n_players = game_n_players (game);
  TarotPlayer leader;
  if (game_get_current_trick (game, &i_trick) != TAROT_GAME_OK)
    {
      return 0;
    }
  if (game_get_trick_leader (game, i_trick, &leader) != TAROT_GAME_OK)
    {
      return 0;
    }
1249
1250
  if (game_get_trick_cards (game, i_trick, &n_cards, 0, 0, NULL) !=
      TAROT_GAME_OK)
1251
1252
1253
1254
    {
      return 0;
    }
  ret = 0;
Vivien Kraus's avatar
Vivien Kraus committed
1255
  for (i = n_cards + 1; i < n_players; i++)
1256
1257
1258
1259
1260
1261
1262
    {
      assert (ret <= 5);
      p[ret++] = (leader + i) % n_players;
    }
  return ret;
}

1263
static inline void
1264
1265
1266
1267
strategy_trump_master (const TarotGame * game,
                       const TarotCounter * counter,
                       const TarotGameEvent * event,
                       int *actually_master, int *obvious_master)
1268
1269
{
  TarotCard card, c;
1270
  TarotNumber number, number_max_trump;
1271
1272
1273
1274
  TarotSuit suit;
  size_t n_players = game_n_players (game);
  TarotPlayer after_me[5];
  size_t n_after_me = who_plays_after_me (game, after_me);
1275
  size_t current_trick;
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
  *actually_master = 0;
  *obvious_master = 0;
  if (event_get_card (event, &card) != TAROT_EVENT_OK)
    {
      return;
    }
  if (decompose (card, &number, &suit) != 0)
    {
      return;
    }
  if (suit != TAROT_TRUMPS)
    {
      return;
    }
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
  if (game_get_current_trick (game, &current_trick) != TAROT_GAME_OK)
    {
      return;
    }
  if (game_get_max_trump (game, current_trick, &number_max_trump) ==
      TAROT_GAME_OK)
    {
      if (number_max_trump > number)
        {
          /* Someone has already played better than us in this
           * trick. */
          return;
        }
    }
1304
1305
  *obvious_master = 1;
  *actually_master = 1;
1306
1307
1308
  for (c = card + 1; c < TAROT_EXCUSE; c++)
    {
      if (counter->current_owner_of[c] < n_players)
1309
1310
1311
        {
          *obvious_master = 0;
        }
1312
      if (counter_may_own (counter, n_after_me, after_me, c))
1313
1314
        {
          *actually_master = 0;
Vivien Kraus's avatar
Vivien Kraus committed
1315
          *obvious_master = 0;
1316
        }
1317
1318
1319
    }
}

1320
static inline void
1321
1322
1323
strategy_play_points (const TarotGame * game,
                      const TarotGameEvent * event,
                      size_t *n_halfpoints, int *oudler)
1324
1325
{
  TarotCard card;
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
  static const unsigned int halfpoints[78] = {
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 5, 7, 9,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 5, 7, 9,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 5, 7, 9,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 5, 7, 9,
    9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9,
    1
  };
  static const int is_oudler[78] = {
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
    0
  };
  (void) game;
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
  *n_halfpoints = 0;
  *oudler = 0;
  if (event_get_card (event, &card) != TAROT_EVENT_OK)
    {
      return;
    }
  *n_halfpoints = halfpoints[card];
  *oudler = is_oudler[card];
}

#include <tarot/game_private_impl.h>
#include <tarot/game_event_private_impl.h>
#include <tarot/cards_private_impl.h>
1356
#include <tarot/counter_private_impl.h>
1357
1358

#endif /* H_TAROT_FEATURES_PRIVATE_IMPL_INCLUDED */