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) /*!< トランプカードがジョーカーかどうかを返す */
48 static void reset_deck(int deck[])
50 for (int i = 0; i < 53; i++)
55 for (int i = 0; i < 53; i++) {
56 int tmp1 = randint0(53 - i) + i;
65 * @brief ポーカープレイ中にジョーカーを持っているかの判定を返す
67 * @return ジョーカーを持っているか
69 static bool has_joker(void)
71 for (int i = 0; i < 5; i++)
73 if (IS_JOKER(cards[i])) return TRUE;
80 * @brief ポーカーの手札に該当の番号の札があるかを返す
81 * @param num 探したいカードの番号
82 * @return 該当の番号が手札にあるか。
84 static bool find_card_num(int num)
86 for (int i = 0; i < 5; i++)
88 if (NUM_OF(cards[i]) == num && !IS_JOKER(cards[i])) return TRUE;
96 * @brief ポーカーの手札がフラッシュ役を得ているかを帰す
100 static bool poker_hand_check_flush(void)
102 bool joker_is_used = FALSE;
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;
108 if (has_joker() && !joker_is_used)
109 joker_is_used = TRUE;
119 * @brief ポーカーの手札がストレートを含んだ高位の役を得ているかを帰す
121 * @return 役の判定結果 0…ストレート、フラッシュいずれもなし/1…ストレートのみ/2…ストレートフラッシュ/3…ロイヤルストレートフラッシュ
123 static int poker_hand_check_straight(void)
126 bool joker_is_used = FALSE;
127 bool straight = FALSE;
129 for (int i = 0; i < 5; i++)
131 if (NUM_OF(cards[i]) < lowest && !IS_JOKER(cards[i]))
132 lowest = NUM_OF(cards[i]);
135 if (poker_hand_check_flush())
140 for (i = 0; i < 4; i++)
142 if (!find_card_num(9 + i)) {
143 if (has_joker() && !joker_is_used)
144 joker_is_used = TRUE;
150 if (i == 4) return 3;
155 for (i = 0; i < 3; i++)
157 if (!find_card_num(10 + i))
161 if (i == 3 && has_joker()) return 3;
165 joker_is_used = FALSE;
170 for (i = 0; i < 4; i++)
172 if (!find_card_num(9 + i)) {
173 if (has_joker() && !joker_is_used)
174 joker_is_used = TRUE;
180 if (i == 4) straight = TRUE;
183 joker_is_used = FALSE;
186 for (i = 0; i < 5; i++)
188 if (!find_card_num(lowest + i))
190 if (has_joker() && !joker_is_used)
191 joker_is_used = TRUE;
197 if (i == 5) straight = TRUE;
199 if (straight && poker_hand_check_flush()) return 2; /* Straight Flush */
200 else if (straight) return 1; /* Only Straight */
206 * @brief ポーカーのペア役の状態を返す。
208 * @return 0:nopair 1:1 pair 2:2 pair 3:3 cards 4:full house 6:4cards
210 static int poker_hand_check_pair(void)
213 for (int i = 0; i < 5; i++)
215 for (int j = i + 1; j < 5; j++)
217 if (IS_JOKER(cards[i]) || IS_JOKER(cards[j])) continue;
218 if (NUM_OF(cards[i]) == NUM_OF(cards[j]))
252 * @brief ポーカーの役をチェックし、その結果を画面に表示しつつ結果を返す。
255 static int poker_hand_check(void)
259 switch (poker_hand_check_straight())
262 c_put_str(TERM_YELLOW, _("ロイヤルストレートフラッシュ", "Royal Flush"), 4, 3);
265 c_put_str(TERM_YELLOW, _("ストレートフラッシュ", "Straight Flush"), 4, 3);
268 c_put_str(TERM_YELLOW, _("ストレート", "Straight"), 4, 3);
271 /* Not straight -- fall through */
275 if (poker_hand_check_flush())
277 c_put_str(TERM_YELLOW, _("フラッシュ", "Flush"), 4, 3);
281 switch (poker_hand_check_pair())
284 c_put_str(TERM_YELLOW, _("ワンペア", "One pair"), 4, 3);
287 c_put_str(TERM_YELLOW, _("ツーペア", "Two pair"), 4, 3);
290 c_put_str(TERM_YELLOW, _("スリーカード", "Three of a kind"), 4, 3);
293 c_put_str(TERM_YELLOW, _("フルハウス", "Full house"), 4, 3);
296 c_put_str(TERM_YELLOW, _("フォーカード", "Four of a kind"), 4, 3);
299 if (!NUM_OF(cards[0]) && !NUM_OF(cards[1]))
301 c_put_str(TERM_YELLOW, _("ファイブエース", "Five ace"), 4, 3);
306 c_put_str(TERM_YELLOW, _("ファイブカード", "Five of a kind"), 4, 3);
318 * @brief ポーカーの捨てる/残すインターフェイスの表示を更新する。
319 * @param hoge カーソルの現在位置
320 * @param kaeruka カードの捨てる/残すフラグ配列
322 static void display_kaeruka(int hoge, int kaeruka[])
324 char col = TERM_WHITE;
325 for (int i = 0; i < 5; i++)
327 if (i == hoge) col = TERM_YELLOW;
328 else if (kaeruka[i]) col = TERM_WHITE;
329 else col = TERM_L_BLUE;
332 c_put_str(col, _("かえる", "Change"), 14, 5 + i * 16);
334 c_put_str(col, _("のこす", " Stay "), 14, 5 + i * 16);
337 if (hoge > 4) col = TERM_YELLOW;
338 else col = TERM_WHITE;
339 c_put_str(col, _("決定", "Sure"), 16, 38);
341 if (hoge < 5) move_cursor(14, 5 + hoge * 16);
342 else move_cursor(16, 38);
347 * @brief ポーカーの手札を表示する
351 static void display_cards(void)
353 char suitcolor[4] = { TERM_YELLOW, TERM_L_RED, TERM_L_BLUE, TERM_L_GREEN };
355 concptr suit[4] = { "★", "●", "¶", "†" };
356 concptr card_grph[13][7] = { {"A %s ",
447 concptr joker_grph[7] = { " ",
457 concptr suit[4] = { "[]", "qp", "<>", "db" };
458 concptr card_grph[13][7] = { {"A %s ",
549 concptr joker_grph[7] = { " ",
558 for (int i = 0; i < 5; i++)
560 prt(_("┏━━━━━━┓", " +------------+ "), 5, i * 16);
563 for (int i = 0; i < 5; i++)
565 for (int j = 0; j < 7; j++)
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);
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);
576 for (int i = 0; i < 5; i++)
578 prt(_("┗━━━━━━┛", " +------------+ "), 13, i * 16);
584 * @brief ポーカーの1プレイルーチン。
592 bool decision = TRUE;
599 for (int i = 0; i < 5; i++)
601 cards[i] = deck[deck_ptr++];
605 prt(_("残すカードを決めて下さい(方向で移動, スペースで選択)。", "Keep which cards (direction keys move; space selects)? "), 0, 0);
616 display_kaeruka(k + decision * 5, is_put);
623 case '6': case 'l': case 'L': case KTRL('F'):
636 case '4': case 'h': case 'H': case KTRL('B'):
649 case '2': case 'j': case 'J': case KTRL('N'):
652 decision = TRUE; draw = TRUE;
656 case '8': case 'k': case 'K': case KTRL('P'):
659 decision = FALSE; draw = TRUE;
670 is_put[k] = !is_put[k]; draw = TRUE;
681 for (int i = 0; i < 5; i++)
683 if (is_put[i] == 1) cards[i] = deck[deck_ptr++];
688 return poker_hand_check();