이 글은 Claude Fable 5.1 을 이용해 초안이 작성되었으며, 이후 퇴고를 거쳤습니다.


지난 두 편에서#

Part 6 에서 문제를 확인했습니다. hard 봇 세 명을 상대로 사람이 판의 59.8% 를 1등으로 끝냈고, 원인은 봇이 리드할 때 easy 와 똑같이 두는 데 있었습니다.

Part 7 에서는 봇을 이긴 사람의 결정 6,746개를 봇과 비교해 세 가지 습관을 찾았습니다.

잘 두는 사람의 습관
하나강한 한두 장으로 리드를 지키고, 약한 큰 뭉치는 마지막에 낸다
둘초반에 최상위 카드를 아낀다
셋받을 때 딱 이길 만큼만 쓴다

이번 편은 이것을 봇에 넣은 이야기입니다. 고친 곳은 두 군데입니다. 리드 에는 습관 하나를, 받기 에는 습관 둘과 셋을 넣었습니다.

아래 그림들은 색을 이렇게 통일했습니다.

색뜻
붉은색구버전에서 문제였던 자리
초록색새로 넣은 판단
회색바뀌지 않은 부분

1. 리드: 바꾸기 전과 후#

1.1 나란히 놓고 보기#

flowchart TD
    subgraph TOBE["바꾼 뒤"]
        direction TB
        b1["내가 리드할 차례"] --> b2["<b>기본 수</b>를 정한다<br/>가장 약한 숫자를 통째로"]
        b2 --> b3["낼 수 있는 수마다<br/><b>리드 지키기 계획</b>을 세운다<br/>이 수로 시작하면<br/>마지막 뭉치 전까지<br/>리드를 안 빼앗길 확률은?"]
        b3 --> b4["뭉치를 쪼개는 수는<br/>내는 횟수가 늘지 않을 때만<br/>후보로 남긴다"]
        b4 --> b5{"기본 수보다<br/><b>확실히</b> 나은<br/>후보가 있나?"}
        b5 -- "없다" --> b6["기본 수를<br/>그대로 낸다"]
        b5 -- "있다" --> b7["그 후보로<br/>바꾼다"]
    end
    subgraph ASIS["바꾸기 전"]
        direction TB
        a1["내가 리드할 차례"] --> a2["낼 수 있는 수마다<br/>점수를 매긴다"]
        a2 --> a3["<b>그 점수를 버린다</b>"]
        a3 --> a4["가장 약한 숫자를<br/>통째로 낸다"]
    end
    style a1 fill:#FFD700,color:#000000
    style a2 fill:#D3D3D3,color:#000000
    style a3 fill:#FF9999,color:#000000
    style a4 fill:#FF9999,color:#000000
    style b1 fill:#FFD700,color:#000000
    style b2 fill:#D3D3D3,color:#000000
    style b3 fill:#90EE90,color:#000000
    style b4 fill:#90EE90,color:#000000
    style b5 fill:#90EE90,color:#000000
    style b6 fill:#D3D3D3,color:#000000
    style b7 fill:#90EE90,color:#000000

왼쪽과 오른쪽의 차이를 한 문장으로 줄이면 이렇습니다.

구버전은 무조건 가장 약한 뭉치를 냈습니다. 새 버전은 기본으로는 가장 약한 뭉치를 내되, 리드를 지키는 데 확실히 더 나은 수가 있으면 그것으로 바꿉니다.

“가장 약한 숫자를 통째로” 를 버리지 않았다는 점이 중요합니다. 이유는 1.4 에서 설명합니다.

1.2 리드 지키기 계획이란#

Part 7 의 예시를 다시 가져옵니다. 4인 방이고, 1과 광대, 3부터 6, 8이 모두 나온 상황입니다.

내 손패: 2 한 장 · 7 두 장 · 10 네 장

봇은 뭉치마다 “이것을 내면 아무도 못 받을 확률” 을 계산합니다. 안 나온 카드를 세면 알 수 있습니다.

뭉치아무도 못 받을 확률이유
2 한 장100%2를 이기는 것은 1뿐인데 이미 나왔다
7 두 장100%두 장짜리로 7을 이길 숫자가 남아 있지 않다
10 네 장예를 들어 60%9 네 장이나 7 네 장을 든 사람이 있을 수 있다

마지막 줄의 60% 는 설명을 위해 지어낸 숫자입니다. 실제 값은 그때까지 나온 카드와 상대의 남은 장수에 따라 달라집니다.

이제 계획 을 세웁니다. 규칙은 하나입니다.

마지막에 내는 뭉치는 받혀도 상관없다. 내는 순간 손패가 비기 때문이다. 그러니 가장 위험한 뭉치를 맨 뒤로 보내고, 그 앞의 뭉치들이 전부 통과할 확률을 본다.

시작하는 수그 뒤의 순서마지막 뭉치 전까지 리드를 지킬 확률
10 네 장부터10 네 장 → 2 한 장 → 7 두 장60%
2 한 장부터2 한 장 → 7 두 장 → 10 네 장100%

10 네 장부터 내면 그 뭉치가 통과해야 다음으로 넘어갈 수 있으니 60% 입니다. 2 한 장부터 내면 위험한 10 네 장이 맨 뒤로 가서 계산에서 빠지고, 앞의 두 뭉치는 둘 다 100% 이니 전체가 100% 입니다.

기본 수(10 네 장)가 60%, 다른 후보(2 한 장)가 100% 입니다. 차이가 40%p 입니다. 새 봇은 이 차이가 35%p 이상 일 때 기본 수를 버립니다. 그래서 이 상황에서 새 봇은 2 한 장을 냅니다. Part 7 에서 사람이 하던 바로 그 수입니다.

1.3 공짜 쪼개기#

후보 가운데에는 뭉치를 쪼개서 내는 수도 있습니다. 7 두 장을 한 장씩 따로 내는 식입니다. 새 봇은 이것을 내는 횟수가 늘어나지 않을 때만 허용합니다.

달무티는 손패를 먼저 비우는 게임이므로 내는 횟수가 한 번 늘면 그만큼 늦게 끝납니다. 쪼개서 얻는 것이 있어도 횟수가 늘어난다면 손해일 때가 많습니다. 이전에 뭉치를 자유롭게 쪼개게 했던 시도가 크게 졌던 것이 이 때문이었습니다.

Part 7 의 기록에서도 사람이 뭉치를 쪼개 낸 경우는 네 건뿐이었습니다. 이 규칙의 효과는 작을 것으로 예상했고, 실제로도 그랬습니다.

1.4 왜 기본 수를 남겨 두었나#

Part 6 에서 적었듯, 리드를 고치려는 시도는 이전에 세 번 있었고 세 번 다 크게 졌습니다. 평균 0.78등에서 0.96등까지 나빠졌습니다.

진 이유는 같았습니다. 리드를 전부 점수에 맡기면, 점수가 높은 강한 카드부터 나가고 약한 큰 뭉치가 계속 뒤로 밀렸습니다. 그러다 끝내 털지 못하고 꼴찌를 했습니다.

이번에는 다르게 접근했습니다.

flowchart LR
    subgraph LATE["중반과 종반"]
        direction TB
        L1["나온 카드가 많다"] --> L2["아무도 못 받는 뭉치가<br/>생기기 시작한다"]
        L2 --> L3["계획들 사이에<br/>차이가 크게 난다"]
        L3 --> L4["<b>더 나은 계획으로 바꾼다</b>"]
    end
    subgraph EARLY["초반"]
        direction TB
        E1["나온 카드가 거의 없다"] --> E2["어떤 뭉치든<br/>받힐 수 있다"]
        E2 --> E3["어느 계획이든<br/>성공 확률이 0 에 가깝다"]
        E3 --> E4["<b>기본 수 유지</b><br/>약한 뭉치를 통째로"]
    end
    style E4 fill:#D3D3D3,color:#000000
    style L4 fill:#90EE90,color:#000000

초반에는 어떤 계획이든 성공 확률이 비슷하게 낮습니다. “확실히 나은” 후보가 없으므로 봇은 기본 수를 냅니다. 그래서 약한 뭉치가 초반부터 꾸준히 빠져나갑니다. 이전 시도들이 실패한 바로 그 자리를 이렇게 피했습니다.

판이 진행되어 나온 카드가 쌓이면 “아무도 못 받는 뭉치” 가 생기기 시작하고, 계획들 사이에 차이가 벌어집니다. 새 판단은 그때부터 끼어듭니다. Part 7 에서 리드가 가장 많이 갈린 구간이 손패 네 장에서 여섯 장이었는데, 새 판단이 힘을 쓰는 구간이 정확히 거기입니다.


2. 받기: 바꾸기 전과 후#

2.1 나란히 놓고 보기#

flowchart TD
    subgraph TOBE2["바꾼 뒤"]
        direction TB
        d1["카드가 깔려 있고 내 차례"] --> d2["받을 수 있는 수를<br/>전부 나열한다"]
        d2 --> d3["<b>점수에 더하는 것</b><br/>· 손패 비우는 계획이 좋아진다<br/>· 이 수로 리드를 가져올 것 같다<br/><b>(비중을 3분의 1 아래로)</b>"]
        d3 --> d4["<b>점수에서 빼는 것</b><br/>· 이 수가 받힐 위험<br/>· <b>아껴 두기 비용</b><br/>쓴 카드가 얼마나 귀한가"]
        d4 --> d5["패스에도 점수를 매겨<br/>같이 비교한다"]
        d5 --> d6["가장 점수가 높은 것을<br/>고른다"]
    end
    subgraph ASIS2["바꾸기 전"]
        direction TB
        c1["카드가 깔려 있고 내 차례"] --> c2["받을 수 있는 수를<br/>전부 나열한다"]
        c2 --> c3["<b>점수에 더하는 것</b><br/>· 손패 비우는 계획이 좋아진다<br/>· 이 수로 리드를 가져올 것 같다"]
        c3 --> c4["<b>점수에서 빼는 것</b><br/>· 이 수가 받힐 위험"]
        c4 --> c5["패스에도 점수를 매겨<br/>같이 비교한다"]
        c5 --> c6["가장 점수가 높은 것을<br/>고른다"]
    end
    style c1 fill:#FFD700,color:#000000
    style c2 fill:#D3D3D3,color:#000000
    style c3 fill:#FF9999,color:#000000
    style c4 fill:#FF9999,color:#000000
    style c5 fill:#D3D3D3,color:#000000
    style c6 fill:#D3D3D3,color:#000000
    style d1 fill:#FFD700,color:#000000
    style d2 fill:#D3D3D3,color:#000000
    style d3 fill:#90EE90,color:#000000
    style d4 fill:#90EE90,color:#000000
    style d5 fill:#D3D3D3,color:#000000
    style d6 fill:#D3D3D3,color:#000000

흐름의 모양은 같습니다. 점수표의 항목 이 달라졌습니다. 빼는 쪽에 한 줄이 새로 생겼고, 더하는 쪽의 한 줄은 비중이 줄었습니다.

그림에서는 생략했지만, 상대가 이번에 손패를 다 털 수 있을 때 점수와 상관없이 막는 규칙은 그대로 있습니다.

2.2 아껴 두기 비용#

구버전 봇은 “이 카드가 지금 받힐 확률” 은 계산했지만 “이 카드 자체가 얼마나 귀한가” 는 매기지 않았습니다. 그래서 초반에 1을 쓰는 것과 5를 쓰는 것의 아까움이 점수에 드러나지 않았습니다.

새 봇은 받는 수마다 쓴 카드의 값 을 비용으로 뺍니다. 비용은 세 가지를 곱한 것입니다.

곱하는 것뜻
카드의 강함가장 강한 1이 1.0, 가장 약한 카드가 가장 작은 값. 광대는 1.0
장수두 장을 쓰면 두 배
남은 손패12장일 때 1.0 에서 점점 줄어 3장 이하면 0

4인 방을 기준으로 몇 가지 예를 들면 이렇습니다.

상황비용
손패 12장일 때 1 한 장으로 받기1.0
손패 12장일 때 2 두 장으로 받기1.8
손패 12장일 때 10 한 장으로 받기0.1
손패 7장일 때 1 한 장으로 받기약 0.44
손패 3장일 때 1 한 장으로 받기0

표의 위에서 아래로 읽으면 습관 둘과 셋이 그대로 들어 있습니다.

  • 초반일수록 비쌉니다. 손패가 많을 때 강한 카드를 쓰면 비용이 큽니다. 그래서 초반에는 최상위 카드를 아끼게 됩니다 (습관 둘)
  • 강할수록 비쌉니다. 같은 상황에서 2로 받는 것보다 3으로 받는 것이 쌉니다. 그래서 이길 수 있는 가장 약한 카드를 고르게 됩니다 (습관 셋)
  • 종반에는 공짜입니다. 손패가 세 장 이하면 비용이 0 입니다. 끝낼 수 있을 때는 아끼지 말고 써야 하기 때문입니다

2.3 “리드를 가져올 것 같다” 의 비중을 줄였다#

봇이 필요 이상으로 강한 카드를 꺼내던 직접적인 이유는, 확실하게 리드를 가져오는 것 에 점수를 많이 주고 있었기 때문입니다. 강한 카드일수록 확실하니 강한 카드가 뽑혔습니다.

이 항목의 비중을 얼마로 할지는 사람이 정하지 않고 시뮬레이션에 맡겼습니다 (4절에서 설명합니다). 결과는 원래의 3분의 1 아래 였습니다. 봇이 그동안 “리드를 확실히 가져오기” 를 세 배쯤 비싸게 사고 있었다는 뜻입니다.


3. 두 가지를 따로 넣어 보고, 같이 넣어 보았다#

고친 곳이 둘이니, 어느 쪽이 얼마나 기여하는지 따로 재었습니다. 방법은 Part 6 에서 만든 장치 그대로입니다. 새 봇 한 명을 구버전 봇들 사이에 앉히고 평균 몇 등을 하는지 봅니다.

새 봇에 넣은 것구버전 대비 평균 등수 변화4인 방에서 1등한 판의 비율
아무것도 안 넣음 (구버전 그대로)025.0%
리드 지키기 계획만−0.16130.9%
아껴 두기만−0.23933.7%
둘 다−0.36837.2%

등수는 작을수록 좋으므로 음수가 개선 입니다. −0.368 은 평균 등수가 0.37등 앞당겨졌다는 뜻입니다. 이 표는 다음 절에서 설명할 “손잡이 맞추기” 를 하기 전 의 값으로 잰 것입니다.

눈여겨볼 것이 둘 있습니다.

첫째, 두 효과가 거의 그대로 더해집니다. 0.161 과 0.239 를 더하면 0.400 이고, 둘 다 넣은 결과가 0.368 입니다. 두 수정이 서로 다른 자리 에서 이득을 낸다는 뜻입니다. 하나는 중반 이후의 리드에서, 다른 하나는 초반의 받기에서 일합니다.

둘째, 아껴 두기가 더 컸습니다. 처음 계획에는 리드 수정만 있었습니다. 아껴 두기는 Part 7 의 기록 분석을 하고 나서야 추가한 것입니다. 기록을 보지 않았다면 절반 넘는 개선을 놓쳤을 것입니다.

첫 줄의 25.0% 도 의미가 있습니다. 구버전 봇을 구버전 봇들 사이에 앉히면 정확히 넷 중 하나를 이깁니다. 재는 장치가 어느 자리에도 유리하지 않다는 확인입니다.


4. 손잡이를 돌려 맞추기#

봇의 점수표에는 항목마다 비중 이 있습니다. 라디오의 손잡이 여러 개라고 생각하시면 됩니다. 이번에 새로 생긴 손잡이가 둘(리드를 바꾸는 문턱, 아껴 두기의 비중)이고 원래 있던 것이 여섯입니다.

맞추는 방법은 단순합니다. 손잡이 하나를 조금 돌려 보고, 같은 패로 많은 판을 돌려서 나아졌으면 그 자리에 두고, 아니면 되돌립니다. 다음 손잡이로 넘어갑니다. 여덟 개를 다 돌고 나면 처음부터 다시 돕니다. 세 바퀴를 돌렸습니다.

움직인 손잡이는 셋이었습니다.

손잡이바뀐 값풀어 쓰면
리드를 가져오는 것의 비중0.5 → 0.14확실하게 리드를 가져오려고 강한 카드를 쓰는 일을 줄였다
상대의 패스를 믿는 정도0.35 → 0.55“저 사람은 아까 패스했으니 이걸 못 받는다” 는 추론을 더 믿는다
리드를 바꾸는 문턱15%p → 35%p기본 수를 버리려면 계획이 훨씬 더 좋아야 한다

세 번째 줄이 재미있습니다. 처음에는 계획이 15%p 만 나아도 리드를 바꾸게 했는데, 맞추고 나니 35%p 가 되었습니다. “가장 약한 뭉치를 통째로” 는 웬만해서는 버리지 않는 편이 낫다 는 것을 시뮬레이션이 다시 한번 확인해 준 셈입니다. Part 5 에서 “달무티에서는 단순한 규칙이 이미 상당히 좋은 답” 이라고 썼는데, 그 결론은 여전히 유효합니다.


5. 검증: 시험 문제는 따로 떼어 두었다#

손잡이를 맞출 때 쓴 판으로 다시 채점하면 점수가 잘 나오는 것이 당연합니다. 기출문제로 공부하고 같은 기출문제로 시험을 본 것과 같습니다. 그래서 두 가지를 미리 해 두었습니다.

하나, 시험 문제를 따로 떼어 두었습니다. 손잡이를 맞출 때 한 번도 쓰지 않은 패로만 채점했습니다.

둘, 합격선을 시험 전에 적어 두었습니다. 결과를 본 뒤에 기준을 정하면 어떤 결과든 합격으로 만들 수 있습니다. 그래서 채점하기 전에 합격선을 문서에 적고, 채점한 뒤에는 고치지 않기로 했습니다.

적어 둔 합격선은 이랬습니다.

시험합격선
구버전 봇들 사이에 새 봇 한 명4인·5인·6인 방 모두에서 오차를 감안해도 개선일 것. 4인 방은 0.15등 이상 앞당길 것
easy 봇과의 비교기존에 쓰던 합격선을 그대로 통과할 것

결과입니다.

시험결과오차 범위판정
구버전 대비, 전체−0.440−0.478 ~ −0.402통과
구버전 대비, 4인−0.414−0.468 ~ −0.360통과
구버전 대비, 5인−0.446−0.512 ~ −0.379통과
구버전 대비, 6인−0.460−0.533 ~ −0.387통과
easy 대비, 전체−0.484−0.507 ~ −0.461통과

오차 범위의 나쁜 쪽 끝도 전부 음수입니다. 운이 나빴다고 가정해도 개선이라는 뜻입니다.

1등 비율로 옮기면 이렇습니다.

4인 방에서구버전 봇새 봇
판 하나를 1등으로 끝낸 비율25.0%39.1%
게임 전체를 1등으로 끝낸 비율28.4%49.1%

구버전 봇 세 명 사이에 앉은 새 봇은 열 판 중 네 판 을 1등으로 끝냈습니다.

게임 전체 1등은 동점인 경우도 함께 세기 때문에 구버전의 기준이 25% 보다 조금 높게 나옵니다.

easy 와의 격차도 달라졌습니다. Part 5 내내 붙들고 있던 숫자 0.07등 이 이번에 0.48등 이 되었습니다. 일곱 배입니다. Part 5 에서 “격차를 먼저 벌린 다음에야 중간 난이도가 의미를 갖습니다” 라고 썼는데, 이제 그 조건이 갖춰졌습니다.

한 가지 더 확인한 것이 있습니다. 따로 떼어 둔 시험의 결과(−0.440)가 손잡이를 맞출 때의 결과(−0.374)보다 오히려 좋았습니다. 맞출 때 쓴 패에만 통하는 꼼수를 배운 것이 아니라는 신호입니다.

봇이 수 하나를 고르는 데 걸리는 시간도 상한을 정해 두었습니다. 100번 중 가장 느린 경우에도 0.05초를 넘지 않아야 합니다. 봇이 세져도 사람이 기다리게 되면 안 되기 때문입니다.


6. 말할 수 있는 것과 아직 말할 수 없는 것#

여기까지 읽으시면 “그래서 이제 사람이 몇 판이나 이기느냐” 가 궁금하실 것입니다. 솔직하게 적겠습니다. 아직 모릅니다.

말할 수 있는 것

  • 새 봇은 구버전 봇보다 셉니다. 구버전 봇들 사이에서 평균 0.44등 앞섭니다
  • 새 봇은 easy 보다 뚜렷하게 셉니다. 격차가 0.07등에서 0.48등이 되었습니다
  • 이 개선은 손잡이를 맞출 때 쓰지 않은 패에서도 재현되었습니다
  • 개선의 절반 이상은 사람의 기록을 보고서야 찾은 수정에서 나왔습니다

아직 말할 수 없는 것

  • 사람을 상대로 얼마나 세졌는지. 위 숫자는 전부 봇끼리 겨룬 결과입니다. 봇에게 센 것과 사람에게 센 것은 다른 이야기입니다. 바로 그 차이 때문에 이 세 편이 시작되었습니다
  • Part 7 의 그 사용자에게 통하는지. 이 분은 구버전 봇을 읽는 데 한 달이 걸렸습니다. 새 봇을 읽는 데는 얼마가 걸릴지 모릅니다. 새 봇도 같은 상황에서는 늘 같은 수를 내므로, 읽힐 수 있다는 점은 같습니다
  • 다른 고수에게도 통하는지. 세 가지 습관은 한 사람의 기록에서 나왔습니다

목표는 정해 두었습니다. Part 7 의 사용자가 hard 를 상대로 판을 1등으로 끝내는 비율이 59.5% 에서 40% 아래로 내려가는 것입니다. 기준선 25% 에는 못 미치는 목표입니다. 한 번에 거기까지 가리라고는 기대하지 않습니다.

새 봇은 이제 기본 hard 봇이 되었습니다. 사람과 겨룬 기록이 충분히 쌓이면 이어서 쓰겠습니다.


7. 목표에 못 미치면#

다음 단계는 정해져 있습니다. 봇이 앞을 내다보게 하는 것입니다.

지금의 봇은 구버전이든 새 버전이든 규칙과 점수표 로 둡니다. 다음 단계의 봇은 수를 고르기 전에 머릿속으로 판을 끝까지 여러 번 둬 봅니다.

flowchart TD
    A["내 차례"] --> B["상대가 들고 있을 법한 패를<br/>여러 벌 가정한다"]
    B --> C["가정한 패마다, 후보 수마다<br/>판을 끝까지 빠르게 둬 본다"]
    C --> D["후보 수별로<br/>평균 몇 등으로 끝났는지 센다"]
    D --> E["평균 등수가 가장 좋은 수를 낸다"]
    style A fill:#FFD700,color:#000000
    style B fill:#87CEEB,color:#000000
    style C fill:#87CEEB,color:#000000
    style D fill:#87CEEB,color:#000000
    style E fill:#90EE90,color:#000000

카드 게임 봇에서 검증된 방식입니다. 리드, 종반 계획, 여러 수 앞 보기를 한 틀에서 풉니다. 대신 한 수를 고르는 데 드는 계산이 훨씬 많아지고, 만들기도 어렵습니다.

이번에 이 방식으로 바로 가지 않은 이유는 순서 때문입니다. 재는 장치가 없는 상태에서 큰 것을 만들면 그것이 나아졌는지 알 수 없습니다. 그래서 재는 장치를 먼저 만들고, 작은 수정으로 어디까지 가는지를 본 다음, 모자라면 큰 것으로 가기로 했습니다.


마치며#

세 편을 합쳐 세 줄로 줄이면 이렇습니다.

첫째, hard 봇은 처음 만나는 사람에게는 통했지만 패턴을 익힌 사람에게는 easy 와 같았습니다. 리드할 때 둘이 똑같이 두었기 때문입니다.

둘째, 봇을 이긴 사람의 기록을 봇과 나란히 놓으니 세 가지가 달랐습니다. 강한 카드로 리드를 지키고, 초반에 아끼고, 받을 때 최소한으로 씁니다.

셋째, 이것을 넣은 새 봇은 구버전 봇들 사이에서 평균 0.44등 앞섰습니다. 사람을 상대로 얼마나 세졌는지는 이제 재는 중입니다.

Part 5 는 “그것을 알아낸 유일한 방법은 만들어서 재보는 것이었습니다” 로 끝났습니다. 이번에 하나를 덧붙입니다. 잘 재려면, 이긴 사람에게 물어봐야 합니다. 봇끼리 아무리 겨뤄도 “0.07등 차이” 밖에 보이지 않던 문제가, 사람의 기록을 여니 “초반에 1을 쓰지 마라” 같은 구체적인 문장이 되어 나왔습니다.

달무티를 오래 하신 분들이 이 글의 세 가지 습관을 보고 “그걸 이제 알았느냐” 고 하신다면, 맞습니다. 봇은 이제 알았습니다.

편다루는 것
Part 1규칙 기반 easy 봇
Part 2hard 봇의 정보 모델과 확실승수 판정
Part 3수 평가와 전략적 패스
Part 4만들어 보니 hard 봇이 더 약했다
Part 5코드 없이 보는 easy 봇과 hard 봇의 차이
Part 6사람이 열 판 중 여섯 판을 이기는 hard 봇
Part 7잘 두는 사람은 봇과 어디서 다르게 두는가
Part 8 (이 글)봇을 고치다: 리드 지키기 계획과 아껴 두기