OSDN Git Service

Merge pull request #2335 from sikabane-works/release/3.0.0Alpha54
[hengbandforosx/hengbandosx.git] / src / market / poker.cpp
1 #include "market/poker.h"
2 #include "io/input-key-acceptor.h"
3 #include "system/angband.h"
4 #include "term/screen-processor.h"
5 #include "term/term-color-types.h"
6 #include "util/int-char-converter.h"
7
8 /*!
9  * ポーカーの現在の手札ID
10  */
11 static int cards[5];
12
13 #define ODDS_5A 3000 /*!< ファイブエースの役倍率 */
14 #define ODDS_5C 400 /*!< ファイブカードの役倍率 */
15 #define ODDS_RF 200 /*!< ロイヤルストレートフラッシュの役倍率 */
16 #define ODDS_SF 80 /*!< ストレートフラッシュの役倍率 */
17 #define ODDS_4C 16 /*!< フォアカードの役倍率 */
18 #define ODDS_FH 12 /*!< フルハウスの役倍率 */
19 #define ODDS_FL 8 /*!< フラッシュの役倍率 */
20 #define ODDS_ST 4 /*!< ストレートの役倍率 */
21 #define ODDS_3C 1 /*!< スリーカードの役倍率 */
22 #define ODDS_2P 1 /*!< ツーペアの役倍率 */
23
24 /*! @note
25  * kpoker no (tyuto-hannpa na)pakuri desu...
26  * joker ha shineru node haitte masen.
27  *
28  * TODO: donataka! tsukutte!
29  *  - agatta yaku no kiroku (like DQ).
30  *  - kakkoii card no e.
31  *  - sousa-sei no koujyo.
32  *  - code wo wakariyasuku.
33  *  - double up.
34  *  - Joker... -- done.
35  *
36  * 9/13/2000 --Koka
37  * 9/15/2000 joker wo jissou. soreto, code wo sukosi kakikae. --Habu
38  */
39
40 #define SUIT_OF(card) ((card) / 13) /*!< トランプカードのスートを返す */
41 #define NUM_OF(card) ((card) % 13) /*!< トランプカードの番号を返す */
42 #define IS_JOKER(card) ((card) == 52) /*!< トランプカードがジョーカーかどうかを返す */
43
44 /*!
45  * @brief ポーカーの山札を切る
46  * @param deck デッキの配列
47  */
48 static void reset_deck(int deck[])
49 {
50     for (int i = 0; i < 53; i++) {
51         deck[i] = i;
52     }
53
54     for (int i = 0; i < 53; i++) {
55         int tmp1 = randint0(53 - i) + i;
56         int tmp2 = deck[i];
57         deck[i] = deck[tmp1];
58         deck[tmp1] = tmp2;
59     }
60 }
61
62 /*!
63  * @brief ポーカープレイ中にジョーカーを持っているかの判定を返す
64  * @param なし
65  * @return ジョーカーを持っているか
66  */
67 static bool has_joker(void)
68 {
69     for (int i = 0; i < 5; i++) {
70         if (IS_JOKER(cards[i])) {
71             return true;
72         }
73     }
74     return false;
75 }
76
77 /*!
78  * @brief ポーカーの手札に該当の番号の札があるかを返す
79  * @param num 探したいカードの番号
80  * @return 該当の番号が手札にあるか。
81  */
82 static bool find_card_num(int num)
83 {
84     for (int i = 0; i < 5; i++) {
85         if (NUM_OF(cards[i]) == num && !IS_JOKER(cards[i])) {
86             return true;
87         }
88     }
89
90     return false;
91 }
92
93 /*!
94  * @brief ポーカーの手札がフラッシュ役を得ているかを帰す
95  * @param なし
96  * @return 役の判定結果
97  */
98 static bool poker_hand_check_flush(void)
99 {
100     bool joker_is_used = false;
101
102     int suit = IS_JOKER(cards[0]) ? SUIT_OF(cards[1]) : SUIT_OF(cards[0]);
103     for (int i = 0; i < 5; i++) {
104         if (SUIT_OF(cards[i]) == suit) {
105             continue;
106         }
107
108         if (has_joker() && !joker_is_used) {
109             joker_is_used = true;
110         } else {
111             return false;
112         }
113     }
114
115     return true;
116 }
117
118 /*!
119  * @brief ポーカーの手札がストレートを含んだ高位の役を得ているかを帰す
120  * @param なし
121  * @return 役の判定結果 0…ストレート、フラッシュいずれもなし/1…ストレートのみ/2…ストレートフラッシュ/3…ロイヤルストレートフラッシュ
122  */
123 static int poker_hand_check_straight(void)
124 {
125     int lowest = 99;
126     bool joker_is_used = false;
127     bool straight = false;
128
129     for (int i = 0; i < 5; i++) {
130         if (NUM_OF(cards[i]) < lowest && !IS_JOKER(cards[i])) {
131             lowest = NUM_OF(cards[i]);
132         }
133     }
134
135     if (poker_hand_check_flush()) {
136         int i;
137         if (lowest == 0) {
138             for (i = 0; i < 4; i++) {
139                 if (!find_card_num(9 + i)) {
140                     if (has_joker() && !joker_is_used) {
141                         joker_is_used = true;
142                     } else {
143                         break;
144                     }
145                 }
146             }
147
148             if (i == 4) {
149                 return 3;
150             }
151         }
152
153         if (lowest == 9) {
154             for (i = 0; i < 3; i++) {
155                 if (!find_card_num(10 + i)) {
156                     break;
157                 }
158             }
159
160             if (i == 3 && has_joker()) {
161                 return 3;
162             }
163         }
164     }
165
166     joker_is_used = false;
167
168     if (lowest == 0) {
169         int i;
170         for (i = 0; i < 4; i++) {
171             if (!find_card_num(9 + i)) {
172                 if (has_joker() && !joker_is_used) {
173                     joker_is_used = true;
174                 } else {
175                     break;
176                 }
177             }
178         }
179
180         if (i == 4) {
181             straight = true;
182         }
183     }
184
185     joker_is_used = false;
186
187     int i;
188     for (i = 0; i < 5; i++) {
189         if (!find_card_num(lowest + i)) {
190             if (has_joker() && !joker_is_used) {
191                 joker_is_used = true;
192             } else {
193                 break;
194             } /* None */
195         }
196     }
197
198     if (i == 5) {
199         straight = true;
200     }
201
202     if (straight && poker_hand_check_flush()) {
203         return 2;
204     } /* Straight Flush */
205     else if (straight) {
206         return 1;
207     } /* Only Straight */
208     else {
209         return 0;
210     }
211 }
212
213 /*!
214  * @brief ポーカーのペア役の状態を返す。
215  * @param なし
216  * @return 0:nopair 1:1 pair 2:2 pair 3:3 cards 4:full house 6:4cards
217  */
218 static int poker_hand_check_pair(void)
219 {
220     int matching = 0;
221     for (int i = 0; i < 5; i++) {
222         for (int j = i + 1; j < 5; j++) {
223             if (IS_JOKER(cards[i]) || IS_JOKER(cards[j])) {
224                 continue;
225             }
226             if (NUM_OF(cards[i]) == NUM_OF(cards[j])) {
227                 matching++;
228             }
229         }
230     }
231
232     if (has_joker()) {
233         switch (matching) {
234         case 0:
235             matching = 1;
236             break;
237         case 1:
238             matching = 3;
239             break;
240         case 2:
241             matching = 4;
242             break;
243         case 3:
244             matching = 6;
245             break;
246         case 6:
247             matching = 7;
248             break;
249         default:
250             /* don't reach */
251             break;
252         }
253     }
254
255     return matching;
256 }
257
258 /*!
259  * @brief ポーカーの役をチェックし、その結果を画面に表示しつつ結果を返す。
260  * @return 役のID
261  */
262 static int poker_hand_check(void)
263 {
264     prt("                            ", 4, 3);
265
266     switch (poker_hand_check_straight()) {
267     case 3: /* RF! */
268         c_put_str(TERM_YELLOW, _("ロイヤルストレートフラッシュ", "Royal Flush"), 4, 3);
269         return ODDS_RF;
270     case 2: /* SF! */
271         c_put_str(TERM_YELLOW, _("ストレートフラッシュ", "Straight Flush"), 4, 3);
272         return ODDS_SF;
273     case 1:
274         c_put_str(TERM_YELLOW, _("ストレート", "Straight"), 4, 3);
275         return ODDS_ST;
276     default:
277         /* Not straight -- fall through */
278         break;
279     }
280
281     if (poker_hand_check_flush()) {
282         c_put_str(TERM_YELLOW, _("フラッシュ", "Flush"), 4, 3);
283         return ODDS_FL;
284     }
285
286     switch (poker_hand_check_pair()) {
287     case 1:
288         c_put_str(TERM_YELLOW, _("ワンペア", "One pair"), 4, 3);
289         return 0;
290     case 2:
291         c_put_str(TERM_YELLOW, _("ツーペア", "Two pair"), 4, 3);
292         return ODDS_2P;
293     case 3:
294         c_put_str(TERM_YELLOW, _("スリーカード", "Three of a kind"), 4, 3);
295         return ODDS_3C;
296     case 4:
297         c_put_str(TERM_YELLOW, _("フルハウス", "Full house"), 4, 3);
298         return ODDS_FH;
299     case 6:
300         c_put_str(TERM_YELLOW, _("フォーカード", "Four of a kind"), 4, 3);
301         return ODDS_4C;
302     case 7:
303         if (!NUM_OF(cards[0]) && !NUM_OF(cards[1])) {
304             c_put_str(TERM_YELLOW, _("ファイブエース", "Five ace"), 4, 3);
305             return ODDS_5A;
306         } else {
307             c_put_str(TERM_YELLOW, _("ファイブカード", "Five of a kind"), 4, 3);
308             return ODDS_5C;
309         }
310     default:
311         break;
312     }
313
314     return 0;
315 }
316
317 /*!
318  * @brief ポーカーの捨てる/残すインターフェイスの表示を更新する。
319  * @param hoge カーソルの現在位置
320  * @param kaeruka カードの捨てる/残すフラグ配列
321  */
322 static void display_kaeruka(int hoge, int kaeruka[])
323 {
324     char col = TERM_WHITE;
325     for (int i = 0; i < 5; i++) {
326         if (i == hoge) {
327             col = TERM_YELLOW;
328         } else if (kaeruka[i]) {
329             col = TERM_WHITE;
330         } else {
331             col = TERM_L_BLUE;
332         }
333
334         if (kaeruka[i]) {
335             c_put_str(col, _("かえる", "Change"), 14, 5 + i * 16);
336         } else {
337             c_put_str(col, _("のこす", " Stay "), 14, 5 + i * 16);
338         }
339     }
340
341     if (hoge > 4) {
342         col = TERM_YELLOW;
343     } else {
344         col = TERM_WHITE;
345     }
346     c_put_str(col, _("決定", "Sure"), 16, 38);
347
348     if (hoge < 5) {
349         move_cursor(14, 5 + hoge * 16);
350     } else {
351         move_cursor(16, 38);
352     }
353 }
354
355 /*!
356  * @brief ポーカーの手札を表示する
357  * @param なし
358  * @todo _() でまとめる
359  */
360 static void display_cards(void)
361 {
362     char suitcolor[4] = { TERM_YELLOW, TERM_L_RED, TERM_L_BLUE, TERM_L_GREEN };
363 #ifdef JP
364     concptr suit[4] = { "★", "●", "¶", "†" };
365     concptr card_grph[13][7] = { { "A   %s     ",
366                                      "     変     ",
367                                      "     愚     ",
368                                      "     蛮     ",
369                                      "     怒     ",
370                                      "     %s     ",
371                                      "          A" },
372         { "2          ",
373             "     %s     ",
374             "            ",
375             "            ",
376             "            ",
377             "     %s     ",
378             "          2" },
379         { "3          ",
380             "     %s     ",
381             "            ",
382             "     %s     ",
383             "            ",
384             "     %s     ",
385             "          3" },
386         { "4          ",
387             "   %s  %s   ",
388             "            ",
389             "            ",
390             "            ",
391             "   %s  %s   ",
392             "          4" },
393         { "5          ",
394             "   %s  %s   ",
395             "            ",
396             "     %s     ",
397             "            ",
398             "   %s  %s   ",
399             "          5" },
400         { "6          ",
401             "   %s  %s   ",
402             "            ",
403             "   %s  %s   ",
404             "            ",
405             "   %s  %s   ",
406             "          6" },
407         { "7          ",
408             "   %s  %s   ",
409             "     %s     ",
410             "   %s  %s   ",
411             "            ",
412             "   %s  %s   ",
413             "          7" },
414         { "8          ",
415             "   %s  %s   ",
416             "     %s     ",
417             "   %s  %s   ",
418             "     %s     ",
419             "   %s  %s   ",
420             "          8" },
421         { "9 %s  %s   ",
422             "            ",
423             "   %s  %s   ",
424             "     %s     ",
425             "   %s  %s   ",
426             "            ",
427             "   %s  %s 9" },
428         { "10 %s  %s   ",
429             "     %s     ",
430             "   %s  %s   ",
431             "            ",
432             "   %s  %s   ",
433             "     %s     ",
434             "   %s  %s 10" },
435         { "J   Λ     ",
436             "%s   ||     ",
437             "     ||     ",
438             "     ||     ",
439             "     ||     ",
440             "   |=亜=| %s",
441             "     目   J" },
442         { "Q ######   ",
443             "%s#      #  ",
444             "  # ++++ #  ",
445             "  # +==+ #  ",
446             "   # ++ #   ",
447             "    #  #  %s",
448             "     ##   Q" },
449         { "K          ",
450             "%s `⌒´   ",
451             "  γγγλ  ",
452             "  ο ο ι  ",
453             "   υ    ∂ ",
454             "    σ ノ %s",
455             "          K" } };
456     concptr joker_grph[7] = { "            ",
457         "     J     ",
458         "     O     ",
459         "     K     ",
460         "     E     ",
461         "     R     ",
462         "            " };
463
464 #else
465
466     concptr suit[4] = { "[]", "qp", "<>", "db" };
467     concptr card_grph[13][7] = { { "A    %s     ",
468                                      "     He     ",
469                                      "     ng     ",
470                                      "     ba     ",
471                                      "     nd     ",
472                                      "     %s     ",
473                                      "           A" },
474         { "2           ",
475             "     %s     ",
476             "            ",
477             "            ",
478             "            ",
479             "     %s     ",
480             "           2" },
481         { "3           ",
482             "     %s     ",
483             "            ",
484             "     %s     ",
485             "            ",
486             "     %s     ",
487             "           3" },
488         { "4           ",
489             "   %s  %s   ",
490             "            ",
491             "            ",
492             "            ",
493             "   %s  %s   ",
494             "           4" },
495         { "5           ",
496             "   %s  %s   ",
497             "            ",
498             "     %s     ",
499             "            ",
500             "   %s  %s   ",
501             "           5" },
502         { "6           ",
503             "   %s  %s   ",
504             "            ",
505             "   %s  %s   ",
506             "            ",
507             "   %s  %s   ",
508             "           6" },
509         { "7           ",
510             "   %s  %s   ",
511             "     %s     ",
512             "   %s  %s   ",
513             "            ",
514             "   %s  %s   ",
515             "           7" },
516         { "8           ",
517             "   %s  %s   ",
518             "     %s     ",
519             "   %s  %s   ",
520             "     %s     ",
521             "   %s  %s   ",
522             "           8" },
523         { "9  %s  %s   ",
524             "            ",
525             "   %s  %s   ",
526             "     %s     ",
527             "   %s  %s   ",
528             "            ",
529             "   %s  %s  9" },
530         { "10 %s  %s   ",
531             "     %s     ",
532             "   %s  %s   ",
533             "            ",
534             "   %s  %s   ",
535             "     %s     ",
536             "   %s  %s 10" },
537         { "J    /\\     ",
538             "%s   ||     ",
539             "     ||     ",
540             "     ||     ",
541             "     ||     ",
542             "   |=HH=| %s",
543             "     ][    J" },
544         { "Q  ######   ",
545             "%s#      #  ",
546             "  # ++++ #  ",
547             "  # +==+ #  ",
548             "   # ++ #   ",
549             "    #  #  %s",
550             "     ##    Q" },
551         { "K           ",
552             "%s _'~~`_   ",
553             "   jjjjj$&  ",
554             "   q q uu   ",
555             "   c    &   ",
556             "    v__/  %s",
557             "           K" } };
558     concptr joker_grph[7] = { "            ",
559         "     J      ",
560         "     O      ",
561         "     K      ",
562         "     E      ",
563         "     R      ",
564         "            " };
565 #endif
566
567     for (int i = 0; i < 5; i++) {
568         prt(_("┏━━━━━━┓", " +------------+ "), 5, i * 16);
569     }
570
571     for (int i = 0; i < 5; i++) {
572         for (int j = 0; j < 7; j++) {
573             prt(_("┃", " |"), j + 6, i * 16);
574             if (IS_JOKER(cards[i])) {
575                 c_put_str(TERM_VIOLET, joker_grph[j], j + 6, 2 + i * 16);
576             } else {
577                 c_put_str(suitcolor[SUIT_OF(cards[i])], format(card_grph[NUM_OF(cards[i])][j], suit[SUIT_OF(cards[i])], suit[SUIT_OF(cards[i])]), j + 6, 2 + i * 16);
578             }
579             prt(_("┃", "| "), j + 6, i * 16 + 14);
580         }
581     }
582
583     for (int i = 0; i < 5; i++) {
584         prt(_("┗━━━━━━┛", " +------------+ "), 13, i * 16);
585     }
586 }
587
588 /*!
589  * @brief ポーカーの1プレイルーチン。
590  * @return 1プレイの役の結果
591  */
592 int do_poker(void)
593 {
594     int is_put[5];
595
596     bool done = false;
597     bool decision = true;
598     bool draw = true;
599
600     int deck[53];
601     reset_deck(deck);
602
603     int deck_ptr = 0;
604     for (int i = 0; i < 5; i++) {
605         cards[i] = deck[deck_ptr++];
606         is_put[i] = 0;
607     }
608
609     prt(_("残すカードを決めて下さい(方向で移動, スペースで選択)。", "Keep which cards (direction keys move; space selects)? "), 0, 0);
610
611     display_cards();
612     poker_hand_check();
613
614     int k = 2;
615     char cmd;
616     while (!done) {
617         if (draw) {
618             display_kaeruka(k + decision * 5, is_put);
619         }
620
621         draw = false;
622         cmd = inkey();
623         switch (cmd) {
624         case '6':
625         case 'l':
626         case 'L':
627         case KTRL('F'):
628             if (!decision) {
629                 k = (k + 1) % 5;
630             } else {
631                 k = 0;
632                 decision = false;
633             }
634
635             draw = true;
636             break;
637         case '4':
638         case 'h':
639         case 'H':
640         case KTRL('B'):
641             if (!decision) {
642                 k = (k + 4) % 5;
643             } else {
644                 k = 4;
645                 decision = false;
646             }
647
648             draw = true;
649             break;
650         case '2':
651         case 'j':
652         case 'J':
653         case KTRL('N'):
654             if (!decision) {
655                 decision = true;
656                 draw = true;
657             }
658
659             break;
660         case '8':
661         case 'k':
662         case 'K':
663         case KTRL('P'):
664             if (decision) {
665                 decision = false;
666                 draw = true;
667             }
668
669             break;
670         case ' ':
671         case '\r':
672             if (decision) {
673                 done = true;
674             } else {
675                 is_put[k] = !is_put[k];
676                 draw = true;
677             }
678
679             break;
680         default:
681             break;
682         }
683     }
684
685     prt("", 0, 0);
686
687     for (int i = 0; i < 5; i++) {
688         if (is_put[i] == 1) {
689             cards[i] = deck[deck_ptr++];
690         }
691     }
692
693     display_cards();
694
695     return poker_hand_check();
696 }