extras; samples: Fixed warnings
[sdk] / samples / games / cards / ruff / src / ai.ec
1 import "ruff.ec"
2
3 /*
4 int AI_ComputeBet(Player player)
5 {
6    int c, kind;
7    Kind trump = none;
8    int numberOfKind[4] = { 0 }, high[4] = { 0 };
9    int bet = 0;
10    RuffGame * game = player.game;
11    Round * round = &game->rounds[game->round];
12    static const int betTable[10][25]=
13    {
14       {40,40,40,40,40,40,40,40,40,40,40,40,40,40,40, 40,40,40,40,40,40,40,40,40,40},
15       {40,40,40,40,40,40,40,40,40,40,40,40,40,40,40, 40,40,40,40,40,40,40,40,40,40},
16       {40,40,40,40,40,40,40,40,40,40,40,40,40,40,40, 40,40,40,40,40,40,40,40,40,40},
17       {40,40,40,40,40,45,45,45,45,45,45,45,45,45,45, 45,45,45,45,45,45,45,45,45,45},
18       {40,40,40,40,40,45,50,50,50,50,50,50,50,50,50, 50,50,50,50,50,50,50,50,50,50},
19       {40,40,40,40,40,45,50,55,60,60,60,60,60,60,60, 60,60,60,60,60,60,60,60,60,60},
20       {40,40,40,40,40,45,50,55,60,65,70,70,70,70,70, 70,70,70,70,70,70,70,70,70,70},
21       {40,40,40,40,40,45,50,55,60,65,70,75,80,85,85, 85,85,85,85,85,85,85,85,85,85},
22       {40,40,40,40,40,45,50,55,60,65,70,75,80,85,90, 95,95,95,95,95,95,95,95,95,95},
23       {100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100}
24    };
25    int highTotal;
26
27    for(c=0; c<9; c++)
28    {
29       Card * card = &player.cards[c];
30
31       numberOfKind[card->kind] ++;
32       switch(card->number)
33       {
34          case Ace:   high[card->kind] += 3; break;
35          case King:  high[card->kind] += 2; break;
36          case Queen: high[card->kind] += 1; break;
37       }
38    }
39    highTotal = high[0] + high[1] + high[2] + high[3];
40
41    for(kind=0; kind<4; kind++)
42    {
43       if(betTable[numberOfKind[kind]][highTotal] > bet)
44       {
45          trump = kind;
46          bet = betTable[numberOfKind[kind]][highTotal];
47       }
48       else if(betTable[numberOfKind[kind]][highTotal] == bet && kind)
49       {
50                         if(trump == none || (numberOfKind[kind] > numberOfKind[trump] && high[kind] > high[trump]))
51                         {
52                                 trump = kind;
53             bet = betTable[numberOfKind[kind]][highTotal];
54               }
55       }
56    }
57
58    // Check if we're going to pass...
59    if(bet <= round->bet.howMuch && (player.id != round->shuffle || bet != round->bet.howMuch))
60       bet = 0;
61
62    player.trump = trump;
63
64    return bet;
65 }
66 */
67
68 int AI_ComputeBet(Player player)
69 {
70    int c;
71    Kind kind;
72    Kind trump = none;
73    int numberOfKind[4] = { 0 }, high[4] = { 0 };
74    int bet = 0;
75    RuffGame * game = player.game;
76    Round * round = &game->rounds[game->round];
77    static const int betTable[67] =
78    {
79         0,  0,  0,  0,  0,  0,  0,  0,
80         0,  0,  0,  0,  0,  0,  0,  0,
81         5,  5,  5, 10, 10, 15, 15, 15,
82        20, 20, 20, 25, 25, 25, 30, 30,
83        30, 35, 35, 35, 40, 40, 40, 45,
84        45, 45, 50, 50, 50, 55, 55, 55,
85        60, 60, 60, 65, 65, 65, 70, 70,
86        70, 75, 75, 75, 80, 80, 80, 85,
87        90, 95, 100
88    };
89    static const int kindTable[37] =
90    {
91       0,
92       5, 5, 10, 10, 10, 15,
93       15, 15, 20, 20, 20, 25,
94       25, 25, 30, 30, 30, 35,
95       35, 35, 40, 40, 40, 45,
96       50, 55, 60, 65, 70, 75,
97       80, 85, 90, 95, 100, 100
98    };
99
100    int highTotal;
101    int kindScore;
102
103    for(c=0; c<9; c++)
104    {
105       Card * card = &player.cards[c];
106
107       numberOfKind[card->kind] ++;
108       high[card->kind] += card->number;
109    }
110    highTotal = high[0] + high[1] + high[2] + high[3];
111
112    for(kind=0; kind<(Kind)4; kind++)
113    {
114       if(numberOfKind[kind] >= 3 &&
115          (trump == none || high[kind] > high[trump] || (high[kind] == high[trump] && numberOfKind[kind] > numberOfKind[trump])))
116          trump = kind;
117    }
118
119    kindScore = kindTable[high[trump]];
120    switch(numberOfKind[trump])
121    {
122       case 3: kindScore = Min(kindScore, 20); break;
123       case 4: kindScore = Min(kindScore, 40); break;
124       case 5: kindScore = Min(kindScore, 50); break;
125       case 6: kindScore = Min(kindScore, 60); break;
126       case 7: kindScore = Min(kindScore, 70); break;
127       case 8: kindScore = Min(kindScore, 80); break;
128    }
129
130    if(trump == none || betTable[highTotal] > betTable[highTotal - high[trump]] + kindScore)
131    {
132       trump = none;
133       bet = betTable[highTotal];
134    }
135    else
136       bet = betTable[highTotal - high[trump]] + kindTable[high[trump]];
137
138    bet = Min(bet, 100);
139    if(bet < 40) bet = 0;
140
141    // Check if we're going to pass...
142    if(bet <= round->bet.howMuch && (player.id != round->shuffle || bet != round->bet.howMuch))
143       bet = 0;
144    else if(player.id == round->shuffle)
145       bet = round->bet.howMuch ? round->bet.howMuch : 40;
146
147    player.trump = trump;
148
149    return bet;
150 }
151
152 void AI_RequestBet(Player player)
153 {
154    Player_PlaceBet(player, AI_ComputeBet(player));
155 }
156
157 void AI_RequestTrump(Player player)
158 {
159    Player_ChoseTrump(player, player.trump);
160 }
161
162 static bool CardMaster(Player player, Card card)
163 {
164    Number c;
165    for(c = ace; c > card.number; c--)
166       if(player.left[card.kind][c])
167          return false;
168    return true;
169 }
170
171 static bool DoesNotMakeNude(Player player, Card whichCard)
172 {
173    int c;
174
175    for(c=0; c<9; c++)
176    {
177       Card * card = &player.cards[c];
178       if(card->kind == whichCard.kind &&
179          card->number != whichCard.number &&
180          card->number != ace &&
181          card->number != _10 &&
182          card->number != _5)
183          return true;
184    }
185    return false;
186 }
187
188 static bool AloneInKind(Player player, Card whichCard)
189 {
190    int c;
191    for(c=0; c<9; c++)
192    {
193       Card * card = &player.cards[c];
194       if(card->kind == whichCard.kind && card->number != whichCard.number)
195           return false;
196    }
197    return true;
198 }
199
200 enum TrumpFlag { AnyCard, NoTrump, PutTrump, Alone, DontNudify };
201
202 static int Discard(Player player, const char * numbers, TrumpFlag trumpFlag)
203 {
204    RuffGame * game = player.game;
205    Round * round = &game->rounds[game->round];
206    Kind trump = round->bet.trump;
207    Kind kindRequested = game->played[game->start].kind;
208    int card;
209    for(card = 0; numbers[card]; card++)
210    {
211       Number number;
212       int c;
213
214       switch(numbers[card])
215       {
216          case '5': number = _5; break;    // AUTOCOMPLETE BUG ON number =
217          case '7': number = _7; break;
218          case '8': number = _8; break;
219          case '9': number = _9; break;
220          case 'T': number = _10; break;
221          case 'J': number = jack; break;
222          case 'Q': number = queen; break;
223          case 'K': number = king; break;
224          case 'A': number = ace; break;
225       }
226       for(c=0; c<9; c++)
227       {
228          Card * card = &player.cards[c];
229          if(card->number == number && RUFF_Legal(game, player, c))
230          {
231             switch(trumpFlag)
232             {
233                case AnyCard: return c;
234                case NoTrump:
235                   if(trump == kindRequested || card->kind != trump)
236                      return c;
237                   break;
238                case PutTrump:
239                   if(card->kind == trump)
240                      return c;
241                   break;
242                case Alone:
243                   if(AloneInKind(player,card))
244                      return c;
245                   break;
246                case DontNudify:
247                   if(DoesNotMakeNude(player,card))
248                      return c;
249                   break;
250             }
251          }
252       }
253    }
254    return None;
255 }
256
257 void AI_RequestCard(Player player)
258 {
259    RuffGame * game = player.game;
260    Round * round = &game->rounds[game->round];
261    int cardPlayed = None;
262    Kind trump = round->bet.trump;
263    Kind kindRequested = game->played[game->start].kind;
264    PlayerPosition partner = (player.id + 2) % 4;
265    bool trumpLeft = player.trumpLeft[(player.id+1) % 4] || player.trumpLeft[(player.id+3) % 4];
266    int maxScore, points;
267    PlayerPosition winner = RUFF_HandWinner(game, &points, &maxScore);
268    // Master if ignoring cards in my hands
269    bool master = (winner != none) ? CardMaster(player, &game->played[winner]) : false;
270    Kind winnerKind = game->played[winner].kind;
271    bool plus = false;
272    int turn = game->turn - game->start;
273    int c;
274
275    // Count the remaining trump
276    if(trump != none)
277    {
278       int count = 0;
279       for(c = 0; c<9; c++)
280          if(!player.left[trump][c])
281             count++;
282       if(count == 9) trumpLeft = false; // AUTOCOMPLETE BUG ON = IF ONLY } AFTER
283    }
284
285    if(turn < 0) turn += 4;
286
287    // Can I beat it?
288    {
289       int c;
290       for(c = 0; c<9; c++)
291       {
292          Card * card = &player.cards[c];
293                    int score = RUFF_CardScore(game, card->kind, card->number);
294          if(score > maxScore && RUFF_Legal(game, player, c) && card->kind == kindRequested)
295          {
296             plus = true;
297             break;
298          }
299       }
300    }
301
302    /*
303    Logf("Player %d thinking:\n", player.id);
304    Logf("   round = %d, turn = %d, partner = %d, winner = %d, trumpLeft = %d, maxScore = %d, master = %d, plus = %d\n",
305       game->round, turn, partner, winner, trumpLeft, maxScore, master, plus);
306    */
307
308    switch(turn)
309    {
310       case 0:
311          if(player.id == round->bet.player && trumpLeft)
312          {
313             // J'ai pris alors je fais tomber l'atout
314             // if((cardPlayed = Discard(player, "AKQJ9875T", PutTrump)) != None) break;
315             if((cardPlayed = Discard(player, "AKQJ987", PutTrump)) != None) break;
316          }
317          // Je mets ma plus grosse carte (pas des points)
318          if((cardPlayed = Discard(player, "AKQJ9875T", NoTrump)) != None) break;
319          // Je n'ai pas d'atout alors je mets ma plus grosse carte (pas des points)
320          if((cardPlayed = Discard(player, "AKQJ9875T", AnyCard)) != None) break;
321          break;
322       case 1:
323          // Je peux battre la carte sur la table alors je la bats
324          if(plus)
325          {
326             if((cardPlayed = Discard(player, "AKQJ9875T", NoTrump)) != None) break;
327          }
328          // Je ne peux pas battre la carte alors j'essaie de couper ou je mets ma plus petite carte
329          else
330          {
331             if(winnerKind != trump)
332             {
333                if((cardPlayed = Discard(player, "789JQKT5A", PutTrump)) != None) break;
334             }
335             if((cardPlayed = Discard(player, "789J", Alone)) != None) break;
336             if((cardPlayed = Discard(player, "789J", DontNudify)) != None) break;
337             if((cardPlayed = Discard(player, "789JQ5KTA", AnyCard)) != None) break;
338          }
339          break;
340       case 2:
341          // Mon partner est maitre alors je lui donne des points
342          if(winner == partner && master)
343          {
344             if((cardPlayed = Discard(player, "T5", NoTrump)) != None) break;
345             if((cardPlayed = Discard(player, "T5", AnyCard)) != None) break;
346
347             if((cardPlayed = Discard(player, "789JQ", NoTrump)) != None) break;
348
349             if((cardPlayed = Discard(player, "789JQ", AnyCard)) != None) break;
350
351             if((cardPlayed = Discard(player, "KA", NoTrump)) != None) break;
352             if((cardPlayed = Discard(player, "KA", AnyCard)) != None) break;
353          }
354          // Je peux battre la carte sur la table alors je la bats
355          else if(plus)
356          {
357             if((cardPlayed = Discard(player, "AKQJ9875T", NoTrump)) != None) break;
358          }
359          // Je ne peux pas battre la carte alors j'essaie de couper ou je mets ma plus petite carte
360          else
361          {
362             if(winnerKind != trump)
363             {
364                if((cardPlayed = Discard(player, "T5789JQKA", PutTrump)) != None) break;
365             }
366             if((cardPlayed = Discard(player, "789J", Alone)) != None) break;
367             if((cardPlayed = Discard(player, "789J", DontNudify)) != None) break;
368             if((cardPlayed = Discard(player, "789JQ5KTA", AnyCard)) != None) break;
369          }
370          break;
371       case 3:
372          // Mon partner remporte alors je lui donne des points
373          if(winner == partner)
374          {
375             if((cardPlayed = Discard(player, "T5", NoTrump)) != None) break;
376             if((cardPlayed = Discard(player, "T5", AnyCard)) != None) break;
377
378             if((cardPlayed = Discard(player, "789JQ", NoTrump)) != None) break;
379             if((cardPlayed = Discard(player, "789JQ", AnyCard)) != None) break;
380
381             if((cardPlayed = Discard(player, "KA", NoTrump)) != None) break;
382             if((cardPlayed = Discard(player, "KA", AnyCard)) != None) break;
383          }
384          // Je peux battre la carte sur la table alors je la bats
385          else if(plus)
386          {
387             if((cardPlayed = Discard(player, "AKQJ9875T", NoTrump)) != None) break;
388          }
389          // Je ne peux pas battre la carte alors j'essaie de couper ou je mets ma plus petite carte
390          else
391          {
392             if(winnerKind != trump)
393             {
394                if((cardPlayed = Discard(player, "T5789JQKA", PutTrump)) != None) break;
395             }
396             if((cardPlayed = Discard(player, "789J", Alone)) != None) break;
397             if((cardPlayed = Discard(player, "789J", DontNudify)) != None) break;
398
399             if((cardPlayed = Discard(player, "789JQ5KTA", AnyCard)) != None) break;
400          }
401          break;
402    }
403    Player_PlayCard(player, cardPlayed);
404 }
405
406 void AI_InformNewRound(Player player, int round, PlayerPosition shuffle, Card * cards)
407 {
408    // Reset the markers
409    int c, kind;
410    for(kind = 0; kind<4; kind++)
411       for(c = 0; c<9; c++)
412          player.left[kind][c] = true;
413    player.trumpLeft[0] = player.trumpLeft[1] =
414    player.trumpLeft[2] = player.trumpLeft[3] = true;
415
416    for(c = 0; c<9; c++)
417    {
418       if(player.cards[c].kind != none)
419          player.left[player.cards[c].kind][player.cards[c].number] = false;
420    }
421 }
422
423 void AI_InformBet(Player player, int who, int howMuch)
424 {
425
426 }
427
428 void AI_InformTrump(Player player, Kind trump)
429 {
430
431 }
432
433 void AI_InformCardPlayed(Player player, int who, Kind kind, Number number)
434 {
435    RuffGame * game = player.game;
436    Round * round = &game->rounds[game->round];
437
438    player.left[kind][number] = false;
439    // Mark this player as not having trump anymore
440    if(game->played[game->start].kind == round->bet.trump &&
441       kind != round->bet.trump)
442       player.trumpLeft[who] = false;
443    // Assume no more trump if a 10 is discarded
444    else if(game->played[game->start].kind == round->bet.trump && number == _10)
445       player.trumpLeft[who] = false;
446 }
447
448 void AI_InformEndOfRound(Player player, int score0, int score1)
449 {
450
451 }