GTO 기초

포커에서 GTO란? 실전적인 설명

GTO의 개념과 레인지, 혼합 전략을 살펴보고 조건이 명확한 솔버 예시로 결과의 의미와 한계를 설명합니다.

목차

GTO는 game theory optimal의 약자입니다. 포커에서는 특정 게임 모델에서 상대가 전략을 공략해도 큰 이익을 얻기 어렵도록 설계한 전략을 뜻합니다. 어떤 차트, 한 핸드, 솔버 화면 하나가 모든 상황에서 최선이라는 약속은 아닙니다.

포지션, 유효 스택, 레인지, 레이크, 보드, 베팅 크기와 계산 중단 조건에 따라 답이 달라집니다. 불완전 정보 게임에서는 반사실적 후회 최소화(CFR) 같은 방법으로 주어진 게임 모델의 근사 균형을 찾습니다. 그렇다고 실제 노리밋 홀덤의 모든 상황이 “해결”되는 것은 아닙니다. Zinkevich et al. (2007)와 Bowling et al. (2015)는 관련 배경 연구입니다. 이 중 Bowling 등의 “해결” 주장은 특정 헤즈업 리밋 홀덤 모델에만 해당합니다.

한 핸드가 아니라 레인지로 생각하기

레인지는 가능한 핸드와 가중치의 집합입니다. 혼합 전략은 각 액션을 적절히 구성된 레인지로 뒷받침하기 위한 것이며 감으로 번갈아 행동하라는 뜻이 아닙니다. 먼저 가정을 읽고 각 빈도를 이름 붙은 모델과 노드의 값으로 해석하십시오.

제품에서 프리플롭 레인지를 살펴보려면 레인지를 참고하세요. 호스팅 제품의 API 인터페이스는 GTO 솔버 API 가이드에서 설명합니다. 용어집은 EV, 레인지, 동형성 등의 용어를 정의하므로 이 글에서 API 문서까지 다룰 필요는 없습니다.

조건을 명시한 루트 노드 예시

이 예시는 GG200NL 100 bb 레인지로 만든 실제 Direct CPU 기록입니다. 6인 테이블 캐시 게임에서 CO가 2.5 bb로 오픈하고 BB가 콜했으며 플롭은 Qs Th 2d입니다. 루트 노드의 팟은 5.5 bb, 남은 스택은 97.5 bb이고 BB는 아웃 오브 포지션(OOP), CO는 인 포지션(IP)입니다. 원본 레인지의 혼합 핸드 클래스 가중치를 보존한 예시 입력일 뿐, 유일하게 올바른 프리플롭 레인지나 GG 레이크를 반영한 완전한 균형을 주장하지 않습니다.

BB 루트의 KQs 핸드 클래스 비교는 네이티브 CSV의 클래스별 평균을 사용합니다. 빈도는 남은 KQs 조합의 산술 평균이고, 액션별 기대값(EV)은 액션별 클래스 평균(bb)입니다. 이 수치들은 레인지 전체의 가중 결과나 조합별 EV, 원래 KQs 프리플롭 가중치가 아니며, 에퀴티를 뜻하는 것도 아닙니다. 입력 KQs 가중치는 0.913이며 CSV의 InRange 0.7500은 남은 조합의 커버리지 비율입니다.

기록한 BB 루트 CSV의 KQs 클래스 빈도
기록한 BB 루트 CSV의 KQs 클래스 빈도
루트 액션KQs 빈도
체크0.3978
3 bb 베팅0.6022
97 bb 베팅0

아래 전략 이미지는 앱이 해당 BB 루트 노드에 대해 직접 내보낸 결과입니다. 바탕화면 스크린샷이 아니며, 위 수치의 출처도 아닙니다.

앱이 내보낸 BB 루트 노드의 전략 이미지
앱이 내보낸 BB 루트 노드의 전략 이미지

Direct의 전체 영어 화면은 같은 CSV에 연결된 계산 기록을 보여 주는 별도의 시각 자료입니다. 결과 화면을 설명하기 위한 것으로, 이미지의 픽셀에서 수치를 옮겨 적은 자료는 아닙니다.

같은 BB 루트 노드를 표시하는 Direct의 전체 영어 화면
같은 BB 루트 노드를 표시하는 Direct의 전체 영어 화면

이 예시가 말하는 것과 말하지 않는 것

설정한 베팅 크기는 팟의 50%로, 이 루트 노드에서는 2.75 bb입니다. 솔버가 1 bb 단위로 반올림하므로 실제 액션은 BET 3.000000이 됩니다. 루트 노드에는 CHECK와 BET 97.000000도 있으므로 두 액션만 있는 트리가 아닙니다. 세 번째 액션의 CSV 빈도가 반올림되어 표시된다고 해서 “절대 베팅하지 않는다”는 뜻으로 바꾸면 안 됩니다.

이번 계산은 CPU, customExact, FP32, maxIteration 100, 팟의 0.5%라는 설정상 정밀도 목표와 동형성 기능을 사용했습니다. 플롭 이후의 게임 트리는 레이크를 차감하지 않는 로컬 모델로, 원래 GG 레이크 모델을 재현한 것은 아닙니다. 기록에는 최종 반복 횟수나 실측 익스플로잇 가능성이 없습니다. 관측한 완료 시간 98.509초는 상한일 뿐 정확한 계산 시간이 아닙니다. 따라서 정밀도 목표 달성이나 완전한 균형을 주장하지 않으며, 이 액션 라인을 다른 게임에 그대로 적용하라는 조언도 아닙니다.

학습 절차

  1. 권장 액션을 읽기 전에 포지션, 스택, 레인지, 보드, 레이크 처리 방식과 가능한 액션을 확인합니다.
  2. 노드와 통계의 종류를 구분합니다. 빈도, 액션별 EV, 에퀴티와 레인지 전체의 가중 EV는 서로 다른 질문에 답합니다.
  3. 반올림한 표시가 0이더라도 아주 낮은 빈도의 액션을 삭제하지 않습니다.
  4. 비교할 때는 한 번에 한 조건만 바꿉니다. 보드나 레인지가 바뀌면 다른 게임 모델입니다.
  5. 솔버 결과는 학습과 연습에 사용하고, 실제 플레이 중 실시간 보조 수단으로 사용하지 않습니다.

입력과 결과

이 연구 예시는 그대로 따라야 할 전략을 제시하는 것이 아닙니다. 조건은 6인 테이블 노리밋 홀덤이며 BB는 OOP, CO는 IP, 시작 스택은 양쪽 모두 100 bb입니다. CO가 2.5 bb로 오픈하고 BB가 콜한 뒤 플롭이 Qs Th 2d가 된 상황으로, 루트 노드의 팟은 5.5 bb이고 남은 스택은 97.5 bb입니다.

다운로드

설정 사용 값
솔버 CPU, FP32, customExact
베팅 크기 플롭, 턴, 리버에서 양쪽 모두 팟의 50%. 1 bb 단위 반올림으로 플롭의 하프팟 베팅은 3 bb가 됩니다
게임 트리 raiseLimit 1; allinThreshold 0.67; 동형성 사용
중단 조건 maxIteration 100; 팟의 0.5%라는 정밀도 목표; 스레드 수 자동(-1)

정밀도 목표는 설정값이며, 실제로 그 수준까지 수렴했다는 증거는 아닙니다. 기록에는 최종 반복 횟수나 실측 익스플로잇 가능성이 없습니다. 루트 노드에는 CHECK, BET 3.000000, BET 97.000000이 남아 있습니다. CSV에서 세 번째 액션의 빈도가 0.0000으로 반올림되어 표시되더라도 그 액션이 불가능하다는 뜻은 아닙니다.

사용한 레인지

다음은 저장된 입력의 완전한 혼합 가중치 레인지이며 Direct의 Bulk edit 필드 형식으로 작성했습니다. 핸드 클래스와 가중치는 소수 셋째 자리까지 유지했고, 나열되지 않은 클래스의 가중치는 0입니다.

BB OOP(98개 클래스)

22:1.000, 33:1.000, 44:1.000, 55:1.000, 66:0.900, 77:0.965, 88:0.956, 99:0.920, 32s:0.431, 42s:1.000, 43s:0.804, 52s:1.000, 53s:0.873, 54s:0.727, 63s:1.000, 64s:0.711, 65o:0.060, 65s:0.706, 74s:1.000, 75s:0.871, 76o:0.176, 76s:0.665, 84s:0.309, 85s:0.949, 86s:0.916, 87o:0.163, 87s:0.746, 95s:0.387, 96s:0.927, 97s:0.928, 98o:0.271, 98s:0.823, A2s:0.711, A3s:0.735, A4o:0.289, A4s:0.754, A5o:0.815, A5s:0.540, A6s:1.000, A7o:0.849, A7s:1.000, A8o:0.928, A8s:1.000, A9o:0.996, A9s:0.998, AJo:0.937, AJs:0.785, AQo:0.912, ATo:0.951, ATs:0.883, J3s:0.828, J4s:0.885, J5s:0.936, J6s:0.875, J7s:0.731, J8s:0.747, J9o:0.482, J9s:0.334, JJ:0.224, JTo:1.000, JTs:0.384, K2s:0.912, K3s:0.652, K4s:0.747, K5s:0.882, K6o:0.083, K6s:0.921, K7s:0.856, K8o:0.101, K8s:0.995, K9o:0.980, K9s:0.814, KJo:0.779, KJs:0.527, KQo:0.700, KQs:0.913, KTo:0.856, KTs:0.772, Q2s:0.815, Q3s:0.818, Q4s:0.805, Q5s:0.701, Q6s:0.622, Q7s:0.997, Q8s:0.611, Q9o:0.452, Q9s:0.499, QJo:0.906, QJs:0.145, QTo:0.926, QTs:0.577, T6s:0.829, T7s:0.915, T8o:0.057, T8s:0.910, T9o:0.839, T9s:0.265, TT:0.808

CO IP(73개 클래스)

22:0.417, 33:0.407, 44:1.000, 55:1.000, 66:1.000, 77:1.000, 88:1.000, 99:1.000, 54s:0.302, 65s:0.401, 76s:0.357, 87s:0.566, 97s:0.623, 98s:1.000, A2s:1.000, A3s:1.000, A4s:1.000, A5o:0.926, A5s:1.000, A6s:1.000, A7o:0.464, A7s:1.000, A8o:1.000, A8s:1.000, A9o:1.000, A9s:1.000, AA:1.000, AJo:1.000, AJs:1.000, AKo:1.000, AKs:1.000, AQo:1.000, AQs:1.000, ATo:1.000, ATs:1.000, J7s:1.000, J8s:1.000, J9o:0.305, J9s:1.000, JJ:1.000, JTo:1.000, JTs:1.000, K3s:1.000, K4s:1.000, K5s:1.000, K6s:1.000, K7s:1.000, K8s:1.000, K9o:0.677, K9s:1.000, KJo:1.000, KJs:1.000, KK:1.000, KQo:1.000, KQs:1.000, KTo:1.000, KTs:1.000, Q5s:1.000, Q6s:1.000, Q7s:1.000, Q8s:1.000, Q9o:0.213, Q9s:1.000, QJo:1.000, QJs:1.000, QQ:1.000, QTo:1.000, QTs:1.000, T7s:0.670, T8s:1.000, T9o:0.160, T9s:1.000, TT:1.000

JSON을 전체 파라미터 참조로 사용하세요. Direct에서 위 값으로 Custom spot을 만들고 Bulk edit로 전체 레인지를 붙여 넣은 뒤 CPU 계산을 선택하고, 루트 노드 출력을 다운로드한 CSV와 비교합니다. 버전, 하드웨어, 중단 조건은 정확한 재실행에 영향을 줄 수 있습니다.

프리플랍 레인지 보기