용코바코 게임즈 노트

개발 노트용코바코 장기

6만 자리를 심판과 맞춰 봤다 — 용코바코 장기 규칙과 AI를 직접 짠 이야기

용코바코 장기는 규칙도 AI도 직접 짰습니다. 서버에서 돌릴 장기 규칙 라이브러리가 없어서였고, 대신 Fairy-Stockfish를 심판으로 세워 6만 자리를 맞춰 봤습니다. 그 과정에서 알게 된 빅장 · 쉬기 · 포의 세부 규칙, 200수 제한과 되풀이처럼 우리가 따로 정한 것, AI 다섯 단계의 숫자를 적었습니다.

용코바코 장기는 「용코바코 전통 전략 시리즈」의 셋째 게임입니다. 체스 · 바둑과 같은 짜임으로 연습 · AI 대결 · 1:1 대결을 두지만, 장기는 시작부터 길이 달랐습니다. 가져다 쓸 수 있는 장기 규칙 코드가 서버에서 돌지 않았기 때문입니다. 이 글은 그래서 규칙을 직접 짜고, 남이 만든 엔진을 «심판»으로 세워 맞춰 본 이야기입니다. 기물마다 가는 길과 기본 규칙은 용코바코 장기 게임 소개에 있습니다.

규칙은 한 벌, 화면과 서버가 같이 씁니다

1:1 대결에서는 둔 수를 서버의 대국방이 한 번 더 확인합니다. 그러려면 서버에도 장기 규칙이 있어야 합니다. 장기를 아는 공개 라이브러리로는 체스 엔진 Stockfish를 여러 변형 게임으로 넓힌 Fairy-Stockfish를 웹용으로 옮긴 것(ffish)이 있는데, 우리가 쓰는 Cloudflare Worker 안에서는 뜨지 않았습니다. 그 라이브러리가 실행 중에 함수를 새로 만들어 쓰는데, Worker가 보안 때문에 그것을 막습니다. 순수 자바스크립트로 된 장기 규칙 라이브러리는 찾지 못했습니다.

그래서 9×10 판 · 궁성과 궁성 대각선 · 기물 여섯 가지 · 장군 · 외통 · 빅장 · 쉬기 · 점수 계산을 파일 하나에 직접 짰습니다. 화면과 서버가 이 파일 한 벌을 같이 읽으니, 두 쪽의 규칙이 어긋날 자리가 처음부터 없습니다.

심판과 6만 자리를 맞춰 봤습니다

직접 짠 규칙이 맞는지는 어떻게 아는가. ffish를 버리지 않고 심판으로 썼습니다. 서버에서는 못 돌려도 개발하는 컴퓨터에서는 돌기 때문입니다. 시험 코드가 무작위로 수백 판을 두면서 자리마다 「둘 수 있는 수의 목록」과 「장군인가」를 우리 규칙과 ffish에 똑같이 묻고, 글자 하나까지 같은지 견줍니다. 마지막으로 돌린 시험은 400판 · 61,086자리에서 어긋난 곳이 0곳이었습니다.

0곳이 되기까지 알게 된 것이 몇 있습니다.

  • 빅장은 마주 본 쪽이 풉니다. 내 수로 두 궁 사이를 텅 비워 서로 마주 보게 «만드는» 것은 허용됩니다. 하지만 내 차례를 받았는데 판에 이미 빅장이 서 있다면, 고를 수 있는 수는 빅장을 푸는 것뿐입니다. 궁이 줄을 옮기거나 둘 사이를 기물로 막는 수가 그렇습니다. 풀지 못하는 수는 목록에서 아예 빠집니다.
  • 장군과 빅장이 겹치면 장군을 맞고도 쉴 수 있습니다. 보통은 장군을 맞은 채로 한 수를 쉬지 못합니다. 그런데 빅장이 걸린 자리라면 쉬어서 판을 끝내는 길이 열려 있습니다. 이 한 가지를 못 맞춰서 무작위 6만 자리 중 7곳이 어긋났었습니다.
  • 포는 포를 넘지도 잡지도 못합니다. 상대 포든 내 포든 발판이 될 수 없고, 포로 포를 잡을 수도 없습니다. 다른 기물은 넘을 수도 잡을 수도 있습니다. 발판 하나를 넘은 뒤로는 거리 제한이 없습니다.
  • 덤은 뒤에 두는 한(漢)이 받습니다. 양쪽에 궁만 남겨 두고 점수 판정을 받아 보면 뒤에 두는 쪽이 이깁니다. 먼저 두는 초(楚)가 유리하니 한이 1.5점을 받는 것이고, 실제 장기 규칙과도 같습니다. 개발 메모 하나가 이것을 거꾸로 적어 두었다가 여기서 바로잡혔습니다.

심판에게 없어서 우리가 정한 것

ffish의 장기에는 판을 끝내는 장치가 몇 개 빠져 있었습니다. 쉬기만 2,000수를 둬도 판이 끝나지 않았고, 같은 자리를 세 번 만들어도 그대로였습니다. 점수 판정도 한쪽에 궁만 남았을 때만 나왔습니다. 그대로 두면 1:1에서 두 사람이 서로 쉬기만 하며 판이 영영 안 끝날 수 있어서 둘을 정했습니다.

  • 수 제한 — 두 쪽이 둔 수를 합쳐 200수에 닿으면 점수로 가립니다.
  • 되풀이 — 같은 자리가 세 번 나오면 점수로 가립니다.

그래서 판이 끝나는 길은 외통 · 빅장(마주 본 채로 쉬기) · 한쪽에 궁만 남음 · 200수 · 같은 자리 세 번 · 기권이고, 1:1에서는 여기에 시간패가 더해집니다. 외통 · 기권 · 시간패가 아니면 점수로 가립니다. 점수는 차가 13점, 포 7점, 마 5점, 상과 사가 각각 3점, 졸과 병이 2점이라 한쪽을 다 더하면 72점이고, 한이 1.5점을 더 받으니 반 점 차이로 늘 승부가 납니다. 심판이 봐 주지 않는 이 끝내기 판정들은 우리 규칙 시험이 따로 봅니다.

AI도 직접 짰습니다

AI 대결 설정 창. 난이도 다섯 단계 단추 아래에, 내 쪽을 초 · 한 · 무작위 가운데서 정하는 줄이 놓여 있다
AI 대결 — 난이도 다섯 단계를 고르고, 내 쪽은 초 · 한 · 무작위 가운데서 정합니다

AI도 처음에는 Fairy-Stockfish의 웹 빌드를 쓰려 했습니다. 그런데 찾은 빌드가 모두 여러 줄로 도는(멀티스레드) 빌드였고, 그것을 브라우저에서 돌리려면 사이트 전체에 보안 머리글 두 개를 켜야 합니다. 그러면 다른 곳에서 불러오는 스크립트가 막힐 수 있습니다. 한 줄로 도는 빌드는 찾지 못했고, 바둑처럼 직접 짜는 쪽을 골랐습니다. 덕분에 내려받을 엔진 파일이 없어 첫 화면이 뜨면 바로 둘 수 있습니다.

수를 고르는 방식은 체스 엔진들이 오래 써 온 것과 같습니다. 가능한 수를 몇 수 앞까지 따라가 보되 볼 필요가 없는 갈래는 잘라 내고(알파베타 탐색), 한 번 본 자리는 표에 적어 두고 다시 읽지 않으며, 잡는 수가 이어지는 동안에는 끝까지 따라가 봅니다. 장기에는 «쉬기»가 진짜로 있어서, 「한 수 쉬어도 버틸 수 있나」를 먼저 보는 기법이 규칙과 그대로 맞아떨어집니다. 판은 기물 점수와 자리(제 진영에서 얼마나 나왔나 · 가장자리에서 얼마나 들어왔나)로 매기고, 개발하는 컴퓨터에서 1초에 300만 자리쯤을 봅니다.

한 가지 일부러 넣은 버릇이 있습니다. AI는 점수로 끝나는 판(빅장 · 200수 · 되풀이)을 외통 바로 다음으로 무겁게 봅니다. 그래서 앞설 때는 빅장을 걸고 쉬어서 판을 끝내려 하고, 뒤질 때는 빅장을 풉니다. AI와 두다가 빅장이 걸리면 그때의 점수를 한번 보시면 왜 그랬는지 보입니다.

다섯 단계의 숫자

단계몇 수 앞가장 오래 생각아무 수
입문1수0.5초30%
초급2수0.8초8%
중급3수1.2초없음
상급5수1.8초없음
최상급시간이 되는 데까지3초없음

아래 세 단계는 여기에 점수 흔들기를 더합니다. 수마다 매긴 점수에 무작위 값을 더해 고르는데, 입문은 수마다 ±4.5점까지(마 한 마리 값에 가깝습니다), 초급은 ±1.8점, 중급은 ±0.4점쯤 흔듭니다. 다만 외통이나 점수로 끝나는 판이 걸린 수는 흔들지 않습니다. 생각이 너무 빨리 끝나는 아래 단계는 손을 떼자마자 두지 않게, 생각한 시간을 합쳐 입문 0.6초 · 초급 0.5초 · 중급 0.4초 · 상급 0.25초를 채운 뒤에 둡니다. 연습의 힌트는 최상급처럼 시간이 되는 데까지(최대 1.5초) 읽은 수를, 지금 차례인 쪽 기준으로 보여 줍니다.

단계 사이는 AI끼리 같은 무작위 첫 네 수에서 초 · 한을 바꿔 가며 여덟 판씩 둬서 확인했습니다.

맞붙은 단계위 단계가 이긴 판끝난 꼴
초급 vs 입문8판 중 7판외통 7 · 빅장 1
중급 vs 초급8판 중 8판외통 6 · 빅장 2
상급 vs 중급8판 중 8판외통 4 · 빅장 3 · 되풀이 1
최상급 vs 상급8판 중 7판외통 5 · 되풀이 2 · 궁만 남음 1

입문을 두 번 낮췄습니다

입문의 처음 숫자는 흔들기 ±3.3점 · 아무 수 20%였습니다. 이것을 「잡을 수 있으면 가장 비싼 것을 잡고, 아니면 아무 수」로 두는 단순한 손과 붙였더니 96판 중 92판을 이겼습니다. 처음 장기를 두는 사람이 대개 그렇게 둔다고 보면 너무 셉니다. 바둑의 입문은 같은 꼴의 손을 넷에 셋쯤(12판 중 9판) 이기게 맞춰 두었기에, 그 근처까지 내렸습니다.

입문 설정 (흔들기 · 아무 수)단순한 손을 이긴 판
±3.3점 · 20% (처음)96판 중 92판
±4.5점 · 25%96판 중 84판
±4.5점 · 30% (지금)96판 중 73판
±6점 · 30%96판 중 64판

초급도 입문을 낮춘 만큼 함께 조금 낮췄습니다(흔들기 ±1.35점 → ±1.8점, 아무 수 4% → 8%). 체스 초급 8% · 바둑 초급 10%와 비슷한 자리입니다. 이 숫자는 AI끼리 둬서 맞춘 것이라, 사람에게 꼭 맞는지는 실제로 두는 판이 쌓여야 알 수 있습니다.

같은 시리즈의 체스와 9줄 바둑은 용코바코 체스 게임 소개와 용코바코 바둑 게임 소개에 있습니다.

다른 노트

← 노트 목록