장기로 돌아가기

놀이터 › 장기 › 장기 컴퓨터는 어떻게 생각하나, 네 단계를 숫자로 나눈 과정

장기 컴퓨터는 어떻게 생각하나, 네 단계를 숫자로 나눈 과정

난이도를 네 단계로 나누는 것은 쉽습니다. 그 네 단계가 진짜로 다른지 확인하는 것이 어렵습니다. 화면으로는 네 단계 모두 멀쩡하게 잘 둡니다. 단계끼리 맞붙여 승률을 재고 나서야 최고수가 어려움에게 열두 판을 내리 지고 있다는 것을 알았습니다. 아래는 그 과정을 숫자와 함께 적은 것입니다.

기본 방식

상대는 알파베타 탐색을 씁니다. 내가 둘 수 있는 수를 하나씩 둬 보고, 그 뒤에 상대가 둘 수를 둬 보고, 다시 내가 둘 수를 둬 보는 식으로 앞을 읽습니다. 끝까지 가서 점수를 매긴 뒤 가장 좋은 쪽을 고릅니다.

점수는 남은 기물의 가치 합에 자리 점수를 조금 더한 값입니다. 알파베타는 이미 진 가지를 중간에 잘라내는 방법이라, 좋은 수를 먼저 볼수록 더 많이 잘라냅니다. 그래서 잡는 수를 먼저 봅니다. 비싼 기물을 잡는 수가 가장 앞입니다.

깊이를 하나 올릴 때마다 얼마나 늘어나나

몇 수 앞본 판의 개수걸린 시간
1수37개0.001초
2수1,117개0.001초
3수2,825개0.007초
4수47,789개0.048초
5수173,668개0.376초

한 수 더 보려면 대략 그 전의 몇십 배를 봐야 합니다. 장기는 한 자리에서 둘 수 있는 수가 평균 37개쯤 되기 때문입니다. 자가 대국 첫 60수 동안 재 보니 평균 37.3개였습니다.

처음에는 한 수에 1.5초를 쓰고도 두 수 앞밖에 못 봤습니다. 수를 하나 만들 때마다 판 전체를 훑어 궁이 잡히는지 검사했기 때문입니다. 탐색 중에는 그 검사를 빼고, 궁이 잡히는 가지는 점수로 걸러내게 바꿨습니다. 실제로 둘 수를 고를 때만 한 번 제대로 검사합니다.

네 단계

단계읽는 깊이실수한 수에 보는 판걸린 시간
쉬움1수35% 확률로 2~4등 수34개0.001초
보통2수15% 확률로 2~3등 수1,240개0.001초
어려움4수없음69,883개0.097초
최고수4수 + 주고받기 끝까지없음547,021개1.511초

깊이 하나로만 가르면 아래 두 단계가 똑같이 바보 같고 위 두 단계는 구분이 안 됩니다. 그래서 깊이와 실수 확률을 같이 움직였습니다. 실수는 아무 수나 두는 것이 아니라 2등이나 3등 수를 두는 것으로 제한했습니다.

최고수가 어려움에게 열두 판을 내리 졌습니다

단계를 다 만들고 인접한 두 단계를 자동으로 맞붙였습니다. 선후공을 번갈아 가며 열두 판씩 두게 했습니다.

대결처음 결과
보통 vs 쉬움12승 0패 (100%)
어려움 vs 보통12승 0패 (100%)
최고수 vs 어려움0승 12패 (0%)

최고수가 전패했습니다. 난이도가 거꾸로였습니다. 화면으로는 네 단계 모두 멀쩡히 두는 것처럼 보였습니다.

원인 두 가지

첫째, 최고수는 시간 안에서 깊이를 1, 2, 3으로 올려 가며 읽습니다. 시간이 다 되면 중간에 멈추는데, 그때 얕게 때운 값으로 채워진 결과가 그 전까지 제대로 읽어 둔 결과를 덮어썼습니다. 깊이를 올리려는 시도가 오히려 수를 나쁘게 만들었습니다. 끝까지 못 읽은 깊이는 통째로 버리게 고쳤습니다. 승률이 0%에서 50%가 됐습니다.

둘째, 홀수 깊이에서 읽기를 끊는 것이 문제였습니다. 다섯 수를 읽으면 마지막이 내가 두는 차례라, 내가 기물을 잡는 장면까지만 보고 되잡히는 장면은 못 봅니다. 그래서 거저 던지는 수를 좋다고 봅니다. 읽는 깊이를 짝수로 맞추니 양쪽 수를 같은 만큼 읽게 됐습니다.

짝수로 맞추고 나니 최고수가 어려움과 5대 5가 됐습니다. 같은 1.5초 안에 깊이 6을 못 끝내서 결국 둘 다 깊이 4로 끝나기 때문이었습니다. 그래서 마지막 깊이에서 잡는 수만 더 따라가, 주고받기가 끝난 자리에서 점수를 매기게 했습니다.

고친 단계최고수 vs 어려움 승률
처음0%
끝까지 못 읽은 깊이 버림50%
읽는 깊이를 짝수로 맞춤100%
자리 점수를 모든 단계에 적용80%

마지막에 80%로 내려온 것은 어려움도 같이 세졌기 때문입니다. 단계를 나눌 때 위가 아래를 70~80% 이기면 적당하다고 보고 있어서, 이 상태를 그대로 두었습니다.

명단에 올린 기보를 서버가 다시 둬 봅니다

전체 명단을 두면서 같이 풀어야 했던 문제가 있습니다. 화면에서 보낸 결과를 그대로 믿으면, 보내는 내용만 바꿔서 아무나 1등이 될 수 있습니다. 그러면 명단이 의미를 잃습니다.

그래서 이름을 올릴 때 결과만 보내지 않고 기보 전체를 보냅니다. 서버는 같은 규칙 엔진으로 빈 판에서 시작해 그 기보를 한 수씩 다시 둬 봅니다. 중간에 규칙에 안 맞는 수가 하나라도 있으면 거기서 멈추고 받지 않습니다.

보낸 것서버가 하는 말
마지막 한 수를 뺀 기보아직 안 끝난 판이에요
진 편으로 신고이긴 판만 올릴 수 있어요
수를 아무렇게나 바꾼 기보기보가 규칙에 안 맞아요
무르기를 쓴 판무르기를 쓴 판은 올릴 수 없어요
진짜 이긴 판올라갑니다

규칙 엔진이 화면과 완전히 분리되어 있어서 가능한 방법입니다. 같은 파일을 화면에서도 쓰고 서버에서도 씁니다. 규칙이 두 벌로 갈라져 서로 다르게 판단하는 일이 생기지 않습니다.

지금 상태

대결10판 결과
보통 vs 쉬움10승 0패 (100%)
어려움 vs 보통10승 0패 (100%)
최고수 vs 어려움8승 2패 (80%)

아래 두 쌍은 아직 100%라 간격이 넓습니다. 쉬움과 보통 사이를 더 촘촘하게 만드는 것은 남은 숙제입니다.

상대의 생각은 화면과 분리된 별도 작업으로 돌립니다. 그래서 최고수가 1.5초를 쓰는 동안에도 화면이 멈추지 않습니다. 그 작업이 안 뜨는 환경에서는 화면 쪽에서 대신 계산하는데, 그때는 잠깐 멈춥니다.

장기 바로 하기 장기 규칙 한 번에 정리, 기물 움직임부터 승부 가리는 법까지 장기 차림 4종 비교: 마상상마, 상마마상, 마상마상, 상마상마 다른 게임 보기