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"
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 /*!< ツーペアの役倍率 */
25 * kpoker no (tyuto-hannpa na)pakuri desu...
26 * joker ha shineru node haitte masen.
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.
37 * 9/15/2000 joker wo jissou. soreto, code wo sukosi kakikae. --Habu
40 #define SUIT_OF(card) ((card) / 13) /*!< トランプカードのスートを返す */
41 #define NUM_OF(card) ((card) % 13) /*!< トランプカードの番号を返す */
42 #define IS_JOKER(card) ((card) == 52) /*!< トランプカードがジョーカーかどうかを返す */
49 static void reset_deck(int deck[])
51 for (int i = 0; i < 53; i++)
56 for (int i = 0; i < 53; i++) {
57 int tmp1 = randint0(53 - i) + i;
66 * @brief ポーカープレイ中にジョーカーを持っているかの判定を返す
68 * @return ジョーカーを持っているか
70 static bool has_joker(void)
72 for (int i = 0; i < 5; i++)
74 if (IS_JOKER(cards[i])) return TRUE;
81 * @brief ポーカーの手札に該当の番号の札があるかを返す
82 * @param num 探したいカードの番号
83 * @return 該当の番号が手札にあるか。
85 static bool find_card_num(int num)
87 for (int i = 0; i < 5; i++)
89 if (NUM_OF(cards[i]) == num && !IS_JOKER(cards[i])) return TRUE;
97 * @brief ポーカーの手札がフラッシュ役を得ているかを帰す
101 static bool poker_hand_check_flush(void)
103 bool joker_is_used = FALSE;
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;
109 if (has_joker() && !joker_is_used)
110 joker_is_used = TRUE;
120 * @brief ポーカーの手札がストレートを含んだ高位の役を得ているかを帰す
122 * @return 役の判定結果 0…ストレート、フラッシュいずれもなし/1…ストレートのみ/2…ストレートフラッシュ/3…ロイヤルストレートフラッシュ
124 static int poker_hand_check_straight(void)
127 bool joker_is_used = FALSE;
128 bool straight = FALSE;
130 for (int i = 0; i < 5; i++)
132 if (NUM_OF(cards[i]) < lowest && !IS_JOKER(cards[i]))
133 lowest = NUM_OF(cards[i]);
136 if (poker_hand_check_flush())
141 for (i = 0; i < 4; i++)
143 if (!find_card_num(9 + i)) {
144 if (has_joker() && !joker_is_used)
145 joker_is_used = TRUE;
151 if (i == 4) return 3;
156 for (i = 0; i < 3; i++)
158 if (!find_card_num(10 + i))
162 if (i == 3 && has_joker()) return 3;
166 joker_is_used = FALSE;
171 for (i = 0; i < 4; i++)
173 if (!find_card_num(9 + i)) {
174 if (has_joker() && !joker_is_used)
175 joker_is_used = TRUE;
181 if (i == 4) straight = TRUE;
184 joker_is_used = FALSE;
187 for (i = 0; i < 5; i++)
189 if (!find_card_num(lowest + i))
191 if (has_joker() && !joker_is_used)
192 joker_is_used = TRUE;
198 if (i == 5) straight = TRUE;
200 if (straight && poker_hand_check_flush()) return 2; /* Straight Flush */
201 else if (straight) return 1; /* Only Straight */
207 * @brief ポーカーのペア役の状態を返す。
209 * @return 0:nopair 1:1 pair 2:2 pair 3:3 cards 4:full house 6:4cards
211 static int poker_hand_check_pair(void)
214 for (int i = 0; i < 5; i++)
216 for (int j = i + 1; j < 5; j++)
218 if (IS_JOKER(cards[i]) || IS_JOKER(cards[j])) continue;
219 if (NUM_OF(cards[i]) == NUM_OF(cards[j]))
253 * @brief ポーカーの役をチェックし、その結果を画面に表示しつつ結果を返す。
256 static int poker_hand_check(void)
260 switch (poker_hand_check_straight())
263 c_put_str(TERM_YELLOW, _("ロイヤルストレートフラッシュ", "Royal Flush"), 4, 3);
266 c_put_str(TERM_YELLOW, _("ストレートフラッシュ", "Straight Flush"), 4, 3);
269 c_put_str(TERM_YELLOW, _("ストレート", "Straight"), 4, 3);
272 /* Not straight -- fall through */
276 if (poker_hand_check_flush())
278 c_put_str(TERM_YELLOW, _("フラッシュ", "Flush"), 4, 3);
282 switch (poker_hand_check_pair())
285 c_put_str(TERM_YELLOW, _("ワンペア", "One pair"), 4, 3);
288 c_put_str(TERM_YELLOW, _("ツーペア", "Two pair"), 4, 3);
291 c_put_str(TERM_YELLOW, _("スリーカード", "Three of a kind"), 4, 3);
294 c_put_str(TERM_YELLOW, _("フルハウス", "Full house"), 4, 3);
297 c_put_str(TERM_YELLOW, _("フォーカード", "Four of a kind"), 4, 3);
300 if (!NUM_OF(cards[0]) && !NUM_OF(cards[1]))
302 c_put_str(TERM_YELLOW, _("ファイブエース", "Five ace"), 4, 3);
307 c_put_str(TERM_YELLOW, _("ファイブカード", "Five of a kind"), 4, 3);
319 * @brief ポーカーの捨てる/残すインターフェイスの表示を更新する。
320 * @param hoge カーソルの現在位置
321 * @param kaeruka カードの捨てる/残すフラグ配列
324 static void display_kaeruka(int hoge, int kaeruka[])
326 char col = TERM_WHITE;
327 for (int i = 0; i < 5; i++)
329 if (i == hoge) col = TERM_YELLOW;
330 else if (kaeruka[i]) col = TERM_WHITE;
331 else col = TERM_L_BLUE;
334 c_put_str(col, _("かえる", "Change"), 14, 5 + i * 16);
336 c_put_str(col, _("のこす", " Stay "), 14, 5 + i * 16);
339 if (hoge > 4) col = TERM_YELLOW;
340 else col = TERM_WHITE;
341 c_put_str(col, _("決定", "Sure"), 16, 38);
343 if (hoge < 5) move_cursor(14, 5 + hoge * 16);
344 else move_cursor(16, 38);
350 * @brief ポーカーの手札を表示する
354 static void display_cards(void)
356 char suitcolor[4] = { TERM_YELLOW, TERM_L_RED, TERM_L_BLUE, TERM_L_GREEN };
358 concptr suit[4] = { "★", "●", "¶", "†" };
359 concptr card_grph[13][7] = { {"A %s ",
450 concptr joker_grph[7] = { " ",
460 concptr suit[4] = { "[]", "qp", "<>", "db" };
461 concptr card_grph[13][7] = { {"A %s ",
552 concptr joker_grph[7] = { " ",
561 for (int i = 0; i < 5; i++)
563 prt(_("┏━━━━━━┓", " +------------+ "), 5, i * 16);
566 for (int i = 0; i < 5; i++)
568 for (int j = 0; j < 7; j++)
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);
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);
579 for (int i = 0; i < 5; i++)
581 prt(_("┗━━━━━━┛", " +------------+ "), 13, i * 16);
587 * @brief ポーカーの1プレイルーチン。
595 bool decision = TRUE;
602 for (int i = 0; i < 5; i++)
604 cards[i] = deck[deck_ptr++];
608 prt(_("残すカードを決めて下さい(方向で移動, スペースで選択)。", "Keep which cards (direction keys move; space selects)? "), 0, 0);
619 display_kaeruka(k + decision * 5, is_put);
626 case '6': case 'l': case 'L': case KTRL('F'):
639 case '4': case 'h': case 'H': case KTRL('B'):
652 case '2': case 'j': case 'J': case KTRL('N'):
655 decision = TRUE; draw = TRUE;
659 case '8': case 'k': case 'K': case KTRL('P'):
662 decision = FALSE; draw = TRUE;
673 is_put[k] = !is_put[k]; draw = TRUE;
684 for (int i = 0; i < 5; i++)
686 if (is_put[i] == 1) cards[i] = deck[deck_ptr++];
691 return poker_hand_check();