'use strict'; // 役の判定は @pokertools/evaluator(@pokertools/engine のショーダウンと同じ判定器)を使う。 // ここでは表示用に、最強の5枚と日本語の役名を求める。 // カードは "As"(スペードのA), "Td"(ダイヤの10)のような2文字 const { evaluate, getCardCodes, rank, HandRank } = require('@pokertools/evaluator'); const HAND_NAMES = { [HandRank.HighCard]: 'ハイカード', [HandRank.OnePair]: 'ワンペア', [HandRank.TwoPair]: 'ツーペア', [HandRank.ThreeOfAKind]: 'スリーカード', [HandRank.Straight]: 'ストレート', [HandRank.Flush]: 'フラッシュ', [HandRank.FullHouse]: 'フルハウス', [HandRank.FourOfAKind]: 'フォーカード', [HandRank.StraightFlush]: 'ストレートフラッシュ', }; const ROYAL_FLUSH = 1; // 判定器のスコアは小さいほど強く、1 がロイヤルフラッシュ // 5〜7枚の中で最も強い役。score は小さいほど強い function bestHand(cards) { const codes = getCardCodes(cards); const score = evaluate(codes); const name = score === ROYAL_FLUSH ? 'ロイヤルフラッシュ' : HAND_NAMES[rank(codes)]; // 役を作っている5枚(7枚から5枚を選ぶ21通りで、全体と同じ強さになる組) let five = cards.slice(0, 5); if (cards.length > 5) { const n = cards.length; const pick = (start, chosen) => { if (chosen.length === 5) return evaluate(chosen.map((i) => codes[i])) === score ? chosen.slice() : null; for (let i = start; i <= n - (5 - chosen.length); i++) { chosen.push(i); const found = pick(i + 1, chosen); chosen.pop(); if (found) return found; } return null; }; five = pick(0, []).map((i) => cards[i]); } return { score, cards: five, name }; } // a が強ければ正、b が強ければ負、同じ強さなら 0 function compareScore(a, b) { return b - a; } module.exports = { bestHand, compareScore };