OSDN Git Service

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