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


지난 편에서#

Part 6 에서 확인한 것은 이렇습니다. hard 봇 세 명과 앉은 4인 방에서 사람이 판의 59.8% 를 1등으로 끝냈습니다. 공정하다면 25% 여야 합니다. 가장 많이 플레이한 사용자에게는 hard 와 easy 가 구별되지 않았습니다.

이번 편은 그 사용자가 어떻게 이겼는지를 봅니다. 봇을 고치기 전에 이것부터 한 이유는 단순합니다. 봇을 이기는 방법을 가장 잘 아는 것은 봇을 이긴 사람입니다.

이 글에서 쓰는 말 두 가지만 다시 적습니다.

  • 리드: 테이블이 비었을 때 먼저 내는 것. 몇 장짜리로 할지 정합니다
  • 받기: 깔린 카드보다 강한 숫자를 같은 장수로 내는 것

그리고 덱에 관한 것 하나입니다. 달무티 공식 룰북의 인원별 덱 규칙대로, 인원이 적으면 약한 숫자를 덜어 내고 합니다. 4인이면 1~10, 5인이면 1~11, 6인 이상이면 1~12 를 씁니다. 분석한 판의 대부분이 4인 방이어서, 아래에 나오는 예시에서는 10이 가장 약한 카드 입니다.


1. 어떻게 비교했는가#

게임 서버에는 판마다 누가 어떤 카드를 받았고, 누가 언제 무엇을 냈고, 누가 패스했는지가 순서대로 남아 있습니다. 이 기록을 처음부터 다시 돌리면 사람이 결정을 내리던 바로 그 순간의 테이블 을 복원할 수 있습니다.

flowchart TD
    A["기록에서 한 판을 꺼낸다"] --> B["처음부터 한 수씩 다시 돌린다"]
    B --> C["사람 차례가 오면 멈춘다"]
    C --> D["그 순간 사람이 볼 수 있던 것을 복원<br/>· 자기 손패<br/>· 테이블에 깔린 카드<br/>· 지금까지 나온 카드<br/>· 상대가 각각 몇 장 남았나"]
    D --> E["같은 것을 봇에게 보여 주고<br/><b>너라면 무엇을 내겠느냐</b> 묻는다"]
    E --> F{"사람이 낸 것과<br/>봇의 답이 같은가?"}
    F -- "같다" --> G["일치로 센다"]
    F -- "다르다" --> H["어떻게 다른지<br/>유형을 붙여 센다"]
    G --> I["다음 수로"]
    H --> I
    I --> C
    style A fill:#FFD700,color:#000000
    style E fill:#87CEEB,color:#000000
    style G fill:#90EE90,color:#000000
    style H fill:#FFA07A,color:#000000

중요한 조건이 하나 있습니다. 봇에게는 사람이 볼 수 있던 것만 보여 줍니다. 상대 손패는 보여 주지 않습니다. 같은 정보를 놓고 판단이 어떻게 갈리는지를 보려는 것이기 때문입니다.

시간이 다 되어 자동으로 넘어간 수는 사람의 판단이 아니므로 세지 않았습니다.

봇에게 사람을 따라 하게 하지는 않았다#

이 기록으로 “사람처럼 두도록 봇을 학습시키면 되지 않느냐” 는 생각이 들 수 있습니다. 그렇게 하지 않았습니다. 이유는 셋입니다.

  • 한 사람의 기록입니다. 그대로 배우면 그 사람의 버릇까지 배웁니다
  • 봇은 같은 상황에서 늘 같은 수를 내도록 만들어져 있습니다. 그래야 문제가 생겼을 때 다시 돌려 보며 원인을 찾을 수 있습니다. 흉내 학습은 이 성질과 맞지 않습니다
  • 알고 싶은 것은 “무엇을 냈는가” 가 아니라 “왜 그것이 좋은 수인가” 입니다. 이유를 알아야 봇의 판단 기준에 넣을 수 있습니다

그래서 이 기록은 어디를 고쳐야 하는지 가리키는 지도 로만 썼습니다.


2. 대부분은 같았다#

분석한 것은 hard 봇을 상대한 474판, 결정 6,746개 입니다.

국면사람과 봇이 같은 수를 고른 비율
리드71.8%
받기89.5%

받을 때는 열 번 중 아홉 번이 같았습니다. 리드는 열 번 중 일곱 번이 같았습니다.

이것만 보면 “봇이 사람과 꽤 비슷하게 두네” 싶습니다. 그런데 승부는 나머지 에서 갈렸습니다. 전체 결정을 유형별로 나누면 이렇습니다.

유형건수비율그 판에서 사람의 평균 등수
둘 다 패스2,84742.2%2.82
같은 카드로 받음1,61323.9%2.18
같은 리드1,26618.8%2.00
사람이 더 강한 숫자로 리드4717.0%1.44
사람은 패스, 봇은 냄3144.7%1.91
둘 다 내지만 다른 카드2013.0%1.61
같은 숫자인데 사람이 더 많이 냄220.3%1.41
사람은 냄, 봇은 패스80.1%2.12
같은 숫자인데 사람이 쪼개서 냄40.1%1.25

마지막 열을 보시기 바랍니다. 등수는 작을수록 좋습니다. 사람과 봇이 같은 수를 고른 판에서 사람의 평균 등수는 2.0~2.8 이었습니다. 굵게 표시한 세 유형, 즉 사람이 봇과 다르게 둔 판에서는 1.4~1.9 였습니다.

세 유형을 합쳐도 전체의 15% 가 안 됩니다. 그러나 이 15% 가 이기는 판과 지는 판을 가르고 있었습니다. 하나씩 봅니다.


3. 습관 하나: 강한 한두 장으로 리드를 지킨다#

가장 많이 갈라진 유형입니다. 471건. 이 유형이 나온 판에서 사람의 평균 등수는 1.44 로, 거의 1등 아니면 2등이었습니다.

같은 순간에 봇과 사람이 낸 카드를 많이 나온 순서로 적으면 이렇습니다.

많이 나온 리드
봇10 네 장, 8 두 장, 8 세 장, 9 한 장, 9 세 장, 10 두 장
사람2 한 장, 6 한 장, 5 한 장, 4 한 장, 7 두 장, 5 두 장, 3 한 장

봇은 약한 숫자를 뭉치로 냅니다. 사람은 강한 숫자를 한두 장 냅니다.

왜 이것이 좋은 수인지는 예를 들면 분명합니다. 4인 방에서 판이 중반을 넘어 1과 광대, 3부터 6, 그리고 8이 모두 나온 상황이라고 하겠습니다. 내 손에는 이렇게 남았습니다.

2 한 장 · 7 두 장 · 10 네 장

flowchart TD
    S["내 손패<br/>2 한 장 · 7 두 장 · 10 네 장<br/>지금 내가 리드"]

    S --> B1["<b>봇</b><br/>가장 약한 10 네 장을 낸다"]
    B1 --> B2{"누가 네 장짜리로<br/>받을 수 있나?"}
    B2 -- "9 네 장을 든 사람이 받는다" --> B3["리드를 빼앗긴다"]
    B3 --> B4["2 와 7 두 장을 든 채<br/>남의 리드를 기다린다"]
    B2 -- "아무도 못 받는다" --> B5["다시 내 리드"]

    S --> H1["<b>사람</b><br/>2 한 장을 낸다"]
    H1 --> H2["1 과 광대가 다 나왔으므로<br/>아무도 못 받는다"]
    H2 --> H3["다시 내 리드<br/>7 두 장을 낸다"]
    H3 --> H4["3 부터 6 이 다 나왔으므로<br/>두 장짜리로 받을 사람이 없다"]
    H4 --> H5["다시 내 리드<br/>10 네 장을 내고 끝"]

    style S fill:#FFD700,color:#000000
    style B1 fill:#FF9999,color:#000000
    style B3 fill:#FF9999,color:#000000
    style B4 fill:#FF9999,color:#000000
    style H1 fill:#90EE90,color:#000000
    style H3 fill:#90EE90,color:#000000
    style H5 fill:#90EE90,color:#000000

사람의 순서에서 눈여겨볼 것은 마지막 10 네 장 입니다. 이 뭉치는 누가 받든 상관없습니다. 내는 순간 내 손패가 비기 때문입니다. 그러니 받힐 위험이 가장 큰 뭉치를 맨 뒤로 보내는 것 이 정답입니다. 그 앞의 수들은 전부 “리드를 잃지 않는 수” 여야 합니다.

봇은 거꾸로 했습니다. 받힐 위험이 가장 큰 뭉치를 맨 먼저 냈습니다.

이 갈림은 판의 어느 시점에서나 나왔습니다. 손패가 12장인 첫 리드에서도, 세 장 남은 마무리에서도 고르게 있었습니다.


4. 습관 둘: 초반에 최상위 카드를 아낀다#

두 번째 유형은 받을 수 있는데 사람은 패스하고 봇은 낸 경우입니다. 314건.

이때 봇이 내려던 카드를 많이 나온 순서로 적으면 이렇습니다.

1 한 장, 2 한 장, 2 두 장, 3 두 장, 4 두 장, 3 한 장

전부 최상위 카드 입니다. 그리고 이 일이 벌어진 시점은 한쪽에 몰려 있었습니다.

그때 사람의 손패건수
12장111
11장46
10장43
9장29

판 초반 입니다. 손패가 거의 그대로 남아 있을 때입니다.

봇은 “이 카드를 내면 리드를 가져올 수 있다” 는 계산이 서면 초반이라도 1이나 2를 씁니다. 사람은 넘깁니다. 초반에 리드를 한 번 가져오는 것보다, 그 카드를 종반까지 들고 있는 것 이 더 값지다고 보기 때문입니다.

앞의 습관과 이어 보면 이유가 보입니다. 종반에 “아무도 못 받는 한 장” 으로 리드를 지키려면 그 한 장이 손에 남아 있어야 합니다. 초반에 써 버리면 종반에 쓸 것이 없습니다.

봇이 이것을 놓친 데는 구조적인 이유가 있었습니다. 봇은 “이 카드가 지금 받힐 확률” 은 계산하지만, “이 카드 자체가 얼마나 귀한가” 는 따로 매기지 않았습니다. 초반에는 아직 나온 카드가 없어서 어떤 카드든 받힐 가능성이 있다고 계산됩니다. 그러니 1을 쓰는 것과 5를 쓰는 것의 아까움 이 점수에 드러나지 않았습니다.


5. 습관 셋: 받을 때 딱 이길 만큼만 쓴다#

세 번째 유형은 둘 다 받긴 받는데 다른 카드로 받은 경우입니다. 201건.

이 가운데 183건, 91% 에서 사람이 봇보다 약한 카드로 받았습니다.

사람이 낸 것같은 순간 봇이 내려던 것건수
3 한 장2 한 장11
5 한 장4 한 장10
4 두 장3 두 장8
3 한 장1 한 장8

깔린 카드를 이기기만 하면 되는데, 봇은 필요한 것보다 한 단계 강한 카드를 꺼냈습니다. 사람은 이길 수 있는 가장 약한 카드 로 받았습니다.

이 유형도 초반에 몰려 있었습니다. 평균 손패가 10.4장이었습니다.

습관 둘과 뿌리가 같습니다. 봇은 “확실하게 리드를 가져오는 것” 에 점수를 많이 주고 있었고, 더 강한 카드일수록 더 확실하므로 더 강한 카드를 골랐습니다. 그 확실함을 사느라 치른 값은 보지 않았습니다.


6. 승부처는 손패 네 장에서 여섯 장 사이#

손패가 몇 장 남았을 때 가장 많이 갈라지는지도 봤습니다.

남은 손패리드가 같았던 비율받기가 같았던 비율
1~3장85.4%97.6%
4~6장60.9%95.1%
7장 이상68.9%84.9%

세 장 이하로 남으면 선택지가 거의 없어서 사람이나 봇이나 비슷하게 둡니다. 일곱 장 이상일 때는 받기에서 좀 갈립니다(앞의 습관 둘과 셋입니다).

리드가 가장 많이 갈라지는 구간은 네 장에서 여섯 장 입니다. 열 번 중 네 번이 달랐습니다. 마지막 두세 수를 어떤 순서로 낼지를 정하는 구간입니다. 앞의 예시처럼 뭉치가 두세 개 남아서, 무엇을 먼저 내고 무엇을 마지막에 낼지가 곧 등수를 정하는 때입니다.


7. 이긴 판일수록 봇과 다르게 두었다#

마지막으로, 그 판에서 사람이 몇 등을 했는지에 따라 나눠 봤습니다.

그 판 사람의 등수판마다 봇과 다르게 둔 횟수리드가 같았던 비율
1등2.8362.4%
2등2.0977.0%
3등1.0987.2%
4등1.1488.0%
5등1.4389.7%

1등한 판에서는 한 판에 평균 세 번 가까이 봇과 다르게 두었습니다. 3등 이하로 끝난 판에서는 한 번 남짓이었습니다.

이 표를 “봇과 다르게 두면 이긴다” 로 읽으면 안 됩니다. 좋은 패를 받으면 고를 수 있는 수가 많아집니다. 나쁜 패를 받으면 낼 수 있는 것이 뻔해서 누가 두어도 비슷합니다. 그러니 이긴 판에서 갈림이 많은 데에는 “패가 좋았다” 는 요인이 섞여 있습니다. 원인과 결과를 이 표만으로 가를 수는 없습니다.

그래도 방향은 분명합니다. 뒤집어 읽으면 이렇습니다.

구버전 봇처럼 둔 판은 사람도 이기지 못했다.


8. 상대가 easy 여도 습관은 같았다#

같은 사용자가 easy 봇을 상대한 기록도 같은 방법으로 봤습니다. 549판, 결정 8,584개 입니다.

유형hard 상대easy 상대
사람이 더 강한 숫자로 리드471건453건
사람은 패스, 봇은 냄314건442건
둘 다 내지만 다른 카드201건826건

같은 유형이 같은 모양으로 나왔습니다. 세 번째 유형은 easy 상대에서 훨씬 많았는데, 826건 가운데 790건이 “사람이 더 약한 카드로 받음” 이었습니다.

상대가 누구든 이 사용자의 두는 방식은 한결같았습니다. 즉 이 습관들은 특정 봇의 허점을 파고든 꼼수 가 아니라, 달무티를 잘 두는 일반적인 방법 에 가깝습니다. 봇에 넣을 가치가 있다는 뜻입니다.


9. 이 분석으로 말할 수 있는 것과 없는 것#

말할 수 있는 것

  • 구버전 hard 와 잘 두는 사람은 대부분의 수에서 같았고, 갈라진 자리는 세 가지 유형에 몰려 있었습니다
  • 세 유형 모두 방향이 뚜렷합니다. 리드는 강한 한두 장으로, 초반 받기는 아끼는 쪽으로, 받을 때는 최소한으로
  • 이 습관은 상대 봇이 달라져도 유지되었습니다

말할 수 없는 것

  • 한 사람의 기록입니다. 다른 고수는 다르게 둘 수 있습니다
  • “다르게 두어서 이겼다” 는 인과는 증명되지 않았습니다. 좋은 패의 효과가 섞여 있습니다
  • 이 습관을 봇에 넣으면 봇이 세진다는 것도 아직 가설 입니다. 사람에게 좋은 수가 봇에게도 좋으리라는 보장은 없습니다. Part 4 에서 리드를 고치려다 세 번 진 기억이 있습니다

마지막 줄이 중요합니다. 그래서 다음 단계는 “넣고, 재 보는 것” 이었습니다.


마치며#

세 줄로 줄이면 이렇습니다.

첫째, 사람의 결정 6,746개를 같은 순간 봇이 냈을 수와 비교했습니다. 리드는 71.8%, 받기는 89.5% 가 같았습니다.

둘째, 갈라진 자리는 셋이었습니다. 강한 한두 장으로 리드를 지킨다. 초반에 최상위 카드를 아낀다. 받을 때 딱 이길 만큼만 쓴다.

셋째, 리드가 가장 많이 갈린 것은 손패 네 장에서 여섯 장 구간이었고, 이긴 판일수록 사람은 봇과 다르게 두었습니다.

세 습관을 한 문장으로 묶으면 “강한 카드는 리드를 지키는 데 쓰려고 아껴 둔다” 입니다. 달무티를 오래 하신 분에게는 당연한 이야기일 것입니다. 그런데 그 당연한 것이 봇의 점수표에는 없었습니다.

다음 편 에서는 이것을 봇에 어떻게 넣었는지, 바꾸기 전과 후의 판단 흐름을 그림으로 나란히 놓고 봅니다.

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