OSDN Git Service

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