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"
15 #define ODDS_5A 3000 /*!< ファイブエースの役倍率 */
16 #define ODDS_5C 400 /*!< ファイブカードの役倍率 */
17 #define ODDS_RF 200 /*!< ロイヤルストレートフラッシュの役倍率 */
18 #define ODDS_SF 80 /*!< ストレートフラッシュの役倍率 */
19 #define ODDS_4C 16 /*!< フォアカードの役倍率 */
20 #define ODDS_FH 12 /*!< フルハウスの役倍率 */
21 #define ODDS_FL 8 /*!< フラッシュの役倍率 */
22 #define ODDS_ST 4 /*!< ストレートの役倍率 */
23 #define ODDS_3C 1 /*!< スリーカードの役倍率 */
24 #define ODDS_2P 1 /*!< ツーペアの役倍率 */
27 * kpoker no (tyuto-hannpa na)pakuri desu...
28 * joker ha shineru node haitte masen.
30 * TODO: donataka! tsukutte!
31 * - agatta yaku no kiroku (like DQ).
32 * - kakkoii card no e.
33 * - sousa-sei no koujyo.
34 * - code wo wakariyasuku.
39 * 9/15/2000 joker wo jissou. soreto, code wo sukosi kakikae. --Habu
42 #define SUIT_OF(card) ((card) / 13) /*!< トランプカードのスートを返す */
43 #define NUM_OF(card) ((card) % 13) /*!< トランプカードの番号を返す */
44 #define IS_JOKER(card) ((card) == 52) /*!< トランプカードがジョーカーかどうかを返す */
50 static void reset_deck(int (&deck)[53])
52 std::iota(std::begin(deck), std::end(deck), 0);
53 rand_shuffle(std::begin(deck), std::end(deck));
57 * @brief ポーカープレイ中にジョーカーを持っているかの判定を返す
59 * @return ジョーカーを持っているか
61 static bool has_joker(void)
63 for (int i = 0; i < 5; i++) {
64 if (IS_JOKER(cards[i])) {
72 * @brief ポーカーの手札に該当の番号の札があるかを返す
73 * @param num 探したいカードの番号
74 * @return 該当の番号が手札にあるか。
76 static bool find_card_num(int num)
78 for (int i = 0; i < 5; i++) {
79 if (NUM_OF(cards[i]) == num && !IS_JOKER(cards[i])) {
88 * @brief ポーカーの手札がフラッシュ役を得ているかを帰す
92 static bool poker_hand_check_flush(void)
94 bool joker_is_used = false;
96 int suit = IS_JOKER(cards[0]) ? SUIT_OF(cards[1]) : SUIT_OF(cards[0]);
97 for (int i = 0; i < 5; i++) {
98 if (SUIT_OF(cards[i]) == suit) {
102 if (has_joker() && !joker_is_used) {
103 joker_is_used = true;
113 * @brief ポーカーの手札がストレートを含んだ高位の役を得ているかを帰す
115 * @return 役の判定結果 0…ストレート、フラッシュいずれもなし/1…ストレートのみ/2…ストレートフラッシュ/3…ロイヤルストレートフラッシュ
117 static int poker_hand_check_straight(void)
120 bool joker_is_used = false;
121 bool straight = false;
123 for (int i = 0; i < 5; i++) {
124 if (NUM_OF(cards[i]) < lowest && !IS_JOKER(cards[i])) {
125 lowest = NUM_OF(cards[i]);
129 if (poker_hand_check_flush()) {
132 for (i = 0; i < 4; i++) {
133 if (!find_card_num(9 + i)) {
134 if (has_joker() && !joker_is_used) {
135 joker_is_used = true;
148 for (i = 0; i < 3; i++) {
149 if (!find_card_num(10 + i)) {
154 if (i == 3 && has_joker()) {
160 joker_is_used = false;
164 for (i = 0; i < 4; i++) {
165 if (!find_card_num(9 + i)) {
166 if (has_joker() && !joker_is_used) {
167 joker_is_used = true;
179 joker_is_used = false;
182 for (i = 0; i < 5; i++) {
183 if (!find_card_num(lowest + i)) {
184 if (has_joker() && !joker_is_used) {
185 joker_is_used = true;
196 if (straight && poker_hand_check_flush()) {
198 } /* Straight Flush */
201 } /* Only Straight */
208 * @brief ポーカーのペア役の状態を返す。
210 * @return 0:nopair 1:1 pair 2:2 pair 3:3 cards 4:full house 6:4cards
212 static int poker_hand_check_pair(void)
215 for (int i = 0; i < 5; i++) {
216 for (int j = i + 1; j < 5; j++) {
217 if (IS_JOKER(cards[i]) || IS_JOKER(cards[j])) {
220 if (NUM_OF(cards[i]) == NUM_OF(cards[j])) {
253 * @brief ポーカーの役をチェックし、その結果を画面に表示しつつ結果を返す。
256 static int poker_hand_check(void)
260 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()) {
276 c_put_str(TERM_YELLOW, _("フラッシュ", "Flush"), 4, 3);
280 switch (poker_hand_check_pair()) {
282 c_put_str(TERM_YELLOW, _("ワンペア", "One pair"), 4, 3);
285 c_put_str(TERM_YELLOW, _("ツーペア", "Two pair"), 4, 3);
288 c_put_str(TERM_YELLOW, _("スリーカード", "Three of a kind"), 4, 3);
291 c_put_str(TERM_YELLOW, _("フルハウス", "Full house"), 4, 3);
294 c_put_str(TERM_YELLOW, _("フォーカード", "Four of a kind"), 4, 3);
297 if (!NUM_OF(cards[0]) && !NUM_OF(cards[1])) {
298 c_put_str(TERM_YELLOW, _("ファイブエース", "Five ace"), 4, 3);
301 c_put_str(TERM_YELLOW, _("ファイブカード", "Five of a kind"), 4, 3);
312 * @brief ポーカーの捨てる/残すインターフェイスの表示を更新する。
313 * @param hoge カーソルの現在位置
314 * @param kaeruka カードの捨てる/残すフラグ配列
316 static void display_kaeruka(int hoge, int kaeruka[])
318 char col = TERM_WHITE;
319 for (int i = 0; i < 5; i++) {
322 } else if (kaeruka[i]) {
329 c_put_str(col, _("かえる", "Change"), 14, 5 + i * 16);
331 c_put_str(col, _("のこす", " Stay "), 14, 5 + i * 16);
340 c_put_str(col, _("決定", "Sure"), 16, 38);
343 move_cursor(14, 5 + hoge * 16);
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++) {
562 prt(_("┏━━━━━━┓", " +------------+ "), 5, i * 16);
565 for (int i = 0; i < 5; i++) {
566 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);
573 prt(_("┃", "| "), j + 6, i * 16 + 14);
577 for (int i = 0; i < 5; i++) {
578 prt(_("┗━━━━━━┛", " +------------+ "), 13, i * 16);
583 * @brief ポーカーの1プレイルーチン。
591 bool decision = true;
598 for (int i = 0; i < 5; i++) {
599 cards[i] = deck[deck_ptr++];
603 prt(_("残すカードを決めて下さい(方向で移動, スペースで選択)。", "Keep which cards (direction keys move; space selects)? "), 0, 0);
612 display_kaeruka(k + decision * 5, is_put);
669 is_put[k] = !is_put[k];
681 for (int i = 0; i < 5; i++) {
682 if (is_put[i] == 1) {
683 cards[i] = deck[deck_ptr++];
689 return poker_hand_check();