- Replace the Yokosawa ranges with the 6-max opening ranges (UTG, HJ, CO, SB, BTN). Colors keep the old order: navy (strong UTG), red UTG, yellow HJ, green CO, blue SB, white BTN. SB is narrower than BTN, so blue sits one tier above white; the purple-frame category is gone. - Show the "BTN vs CO open" chart on the range page as frames: light blue for 3bet, yellow for call. - Grade BTN facing an unlimped CO open by those frames in reviews; other spots keep the color-tier rule (BB defends down to green). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
97 lines
5.6 KiB
JavaScript
97 lines
5.6 KiB
JavaScript
// 登録してあるハンドレンジ(ハンドレンジ学習ページとレビュー付きCPU戦で共用・管理者専用)
|
|
(function (root, factory) {
|
|
if (typeof module === 'object' && module.exports) module.exports = factory();
|
|
else root.HandRange = factory();
|
|
})(typeof self !== 'undefined' ? self : this, function () {
|
|
'use strict';
|
|
|
|
const RANKS = ['A', 'K', 'Q', 'J', 'T', '9', '8', '7', '6', '5', '4', '3', '2'];
|
|
|
|
// 6-max のオープンレンジ(Poker Skill のプリフロップレンジ表、スタック約100BB・全員が降りて回ってきた場面)。
|
|
// 強い順。tier が大きいほど強い(レビューでは「一つ上」「二つ上」をこの段階で数える)。
|
|
// 各ポジションのレンジは UTG ⊂ HJ ⊂ CO ⊂ SB ⊂ BTN と入れ子になっているので、手ごとに
|
|
// 「オープンできる一番狭いポジション」の色を付ける。SB は BTN より狭いので BTN の一つ上に置く。
|
|
// 紺は UTG のうち特に強い手
|
|
const CATEGORIES = [
|
|
{ id: 'navy', name: '紺', label: 'UTG(強)', tier: 6 },
|
|
{ id: 'red', name: '赤', label: 'UTG', tier: 5 },
|
|
{ id: 'yellow', name: '黄', label: 'HJ', tier: 4 },
|
|
{ id: 'green', name: '緑', label: 'CO', tier: 3 },
|
|
{ id: 'blue', name: '青', label: 'SB', tier: 2 },
|
|
{ id: 'white', name: '白', label: 'BTN', tier: 1 },
|
|
{ id: 'gray', name: 'グレー', label: 'フォールド', tier: 0 },
|
|
];
|
|
|
|
// 全169ハンドの分類(載っていないハンドはフォールド)
|
|
const RANGE = {
|
|
AA: 'navy', AKs: 'navy', AQs: 'red', AJs: 'red', ATs: 'red', A9s: 'yellow', A8s: 'yellow', A7s: 'yellow', A6s: 'yellow', A5s: 'red', A4s: 'red', A3s: 'red', A2s: 'red',
|
|
AKo: 'navy', KK: 'navy', KQs: 'red', KJs: 'red', KTs: 'red', K9s: 'yellow', K8s: 'green', K7s: 'green', K6s: 'green', K5s: 'green', K4s: 'blue', K3s: 'white', K2s: 'white',
|
|
AQo: 'red', KQo: 'red', QQ: 'navy', QJs: 'red', QTs: 'red', Q9s: 'yellow', Q8s: 'green', Q7s: 'blue', Q6s: 'blue', Q5s: 'white', Q4s: 'white',
|
|
AJo: 'red', KJo: 'yellow', QJo: 'green', JJ: 'red', JTs: 'red', J9s: 'yellow', J8s: 'green', J7s: 'blue', J6s: 'white',
|
|
ATo: 'yellow', KTo: 'green', QTo: 'blue', JTo: 'blue', TT: 'red', T9s: 'red', T8s: 'yellow', T7s: 'blue', T6s: 'white',
|
|
A9o: 'green', K9o: 'blue', Q9o: 'white', J9o: 'white', T9o: 'white', 99: 'red', '98s': 'red', '97s': 'green', '96s': 'blue', '95s': 'white',
|
|
A8o: 'green', K8o: 'white', '98o': 'white', 88: 'red', '87s': 'yellow', '86s': 'blue', '85s': 'white',
|
|
A7o: 'blue', 77: 'red', '76s': 'green', '75s': 'white',
|
|
A6o: 'blue', 66: 'red', '65s': 'green', '64s': 'white',
|
|
A5o: 'blue', 55: 'red', '54s': 'green',
|
|
A4o: 'white', 44: 'red',
|
|
A3o: 'white', 33: 'red',
|
|
A2o: 'white', 22: 'red',
|
|
};
|
|
|
|
// レイズを受けたときの対応(同じレンジ表の「CO のオープンに対する BTN の対応」)。レンジ表では枠で示す。
|
|
// 載っていないハンドはフォールド
|
|
const FACING_ACTIONS = [
|
|
{ id: '3bet', name: '水色枠', label: '3bet' },
|
|
{ id: 'call', name: '黄枠', label: 'コール' },
|
|
];
|
|
const FACING = {
|
|
AA: '3bet', KK: '3bet', QQ: '3bet', JJ: '3bet', AKs: '3bet', AKo: '3bet', A5s: '3bet', A4s: '3bet', A3s: '3bet', A2s: '3bet',
|
|
KQs: '3bet', KJs: '3bet', '76s': '3bet', '65s': '3bet', '54s': '3bet',
|
|
TT: 'call', 99: 'call', 88: 'call', 77: 'call', 66: 'call', 55: 'call', 44: 'call', 33: 'call', 22: 'call',
|
|
AQs: 'call', AJs: 'call', ATs: 'call', A9s: 'call', A8s: 'call', A7s: 'call', A6s: 'call', KTs: 'call', K9s: 'call',
|
|
QJs: 'call', QTs: 'call', Q9s: 'call', JTs: 'call', J9s: 'call', T9s: 'call', T8s: 'call', '98s': 'call', '87s': 'call',
|
|
AQo: 'call', AJo: 'call', KQo: 'call', KJo: 'call', QJo: 'call',
|
|
};
|
|
|
|
const BY_ID = new Map(CATEGORIES.map((c) => [c.id, c]));
|
|
|
|
// 13×13 の表の (行, 列) のハンド。右上がスーテッド、左下がオフスート
|
|
const handAt = (r, c) => (r === c ? RANKS[r] + RANKS[c] : r < c ? RANKS[r] + RANKS[c] + 's' : RANKS[c] + RANKS[r] + 'o');
|
|
const categoryOf = (hand) => RANGE[hand] || 'gray';
|
|
const category = (id) => BY_ID.get(id) || BY_ID.get('gray');
|
|
const labelOf = (id) => category(id).label;
|
|
const tierOf = (hand) => category(categoryOf(hand)).tier;
|
|
const categoryOfTier = (tier) => CATEGORIES.find((c) => c.tier === tier) || BY_ID.get('gray');
|
|
const facingOf = (hand) => FACING[hand] || null; // '3bet' / 'call' / null(フォールド)
|
|
const facingAction = (id) => FACING_ACTIONS.find((a) => a.id === id) || null;
|
|
|
|
// ["As", "Kd"] → "AKo"
|
|
function handKey(cards) {
|
|
const [a, b] = cards;
|
|
const ia = RANKS.indexOf(a[0]);
|
|
const ib = RANKS.indexOf(b[0]);
|
|
const hi = ia <= ib ? a : b;
|
|
const lo = ia <= ib ? b : a;
|
|
if (hi[0] === lo[0]) return hi[0] + lo[0];
|
|
return hi[0] + lo[0] + (hi[1] === lo[1] ? 's' : 'o');
|
|
}
|
|
|
|
// 自分より前に誰もコール・レイズしていないとき、後ろの人数(自分を含めず、まだ行動していない人)で
|
|
// 参加してよい一番弱い段階。6-max の席に当てはめて、5人以上は UTG の赤(紺は赤の一つ上)、4人は HJ の黄、
|
|
// 3人は CO の緑、2人は BTN の白、1人は SB の青。0人(全員降りてBBに回った)は無し
|
|
function requiredTier(behind) {
|
|
if (behind >= 5) return 5;
|
|
if (behind === 4) return 4;
|
|
if (behind === 3) return 3;
|
|
if (behind === 2) return 1;
|
|
if (behind === 1) return 2;
|
|
return 0;
|
|
}
|
|
|
|
return {
|
|
RANKS, CATEGORIES, RANGE, FACING_ACTIONS, FACING,
|
|
handAt, handKey, categoryOf, category, labelOf, tierOf, categoryOfTier, requiredTier, facingOf, facingAction,
|
|
};
|
|
});
|