본문으로 건너뛰기

이번에는 체스 — 말마다 다른 움직임을 코드로 옮기기

이번에는 체스 — 말마다 다른 움직임을 코드로
이번에는 체스 — 말마다 다른 움직임을 코드로

오목과 오델로를 만들고 나니 다음 판에는 다른 모양의 말들을 올려 보고 싶었다. 같은 8×8 판을 쓰더라도 체스에서는 폰, 나이트, 비숍이 제각각 움직인다. 이번에는 그 차이를 화면에서 알아볼 수 있게 만드는 데서 시작했다.

이번에도 Sonnet을 썼다. 두 사람이 한 컴퓨터에서 번갈아 두는 HTML5 게임으로 정하고, 컴퓨터 상대와 제한 시간은 뺐다. 우선 내 말을 고르고 다음 칸을 누르는 일이 편해야 했다.

백 차례인데, 아래쪽 말이 검게 보였다

첫 화면을 열자 체스판과 말들은 모두 나왔다. 그런데 잠깐 멈칫했다. 오른쪽에는 ‘백 차례’라고 쓰여 있는데 아래쪽 말은 검게 보이고, 위쪽 말은 밝은 윤곽선으로 보였다.

첫 구현 화면. 백 차례 표시와 달리 아래쪽 말이 어둡게 보여 흑백 구분이 헷갈렸다.
첫 구현 화면. 백 차례 표시와 달리 아래쪽 말이 어둡게 보여 흑백 구분이 헷갈렸다.

말의 위치가 뒤바뀐 것은 아니었다. 흰색과 검은색에 같은 윤곽형 문자를 쓰고 테두리 색을 입힌 탓이었다. 코드에 흰색이라고 써 놓았다고 해서 눈에도 흰 말로 보이는 건 아니었다.

속이 채워진 모양으로 바꾸고 흰 말에는 밝은 면과 얇은 어두운 테두리를, 검은 말에는 어두운 면을 줬다. 크기도 키웠다. 수정한 뒤에는 어느 쪽 말을 움직여야 하는지 바로 구분됐다.

그 상태에서 g1의 나이트를 눌렀다. 앞에는 폰들이 있지만 f3과 h3 두 칸에 이동 표시가 떴다. 폰처럼 앞으로 가는 말이 아니라는 것을 긴 설명 없이 보여 줄 수 있었다.

말의 모양과 대비를 수정한 화면. g1 나이트를 선택하면 f3·h3에 이동 가능한 칸이 표시된다.
말의 모양과 대비를 수정한 화면. g1 나이트를 선택하면 f3·h3에 이동 가능한 칸이 표시된다.

옆에는 말 이름도 붙였다. 모양과 이름이 익숙하지 않을 때 킹인지 퀸인지 확인할 수 있도록 했다. 이동을 마치면 기보에 출발 칸과 도착 칸이 쌓인다. 정식 기보 표기를 전부 구현하기보다는, 방금 무엇을 움직였는지 읽을 수 있는 정도로 잡았다.

왕을 옮겼는데 룩도 따라와야 한다

캐슬링은 화면에서 꼭 확인하고 싶었다. 왕만 두 칸 옮겨 놓고 끝나면 체스 규칙을 제대로 구현한 것이 아니기 때문이다.

e2의 폰을 e4로, g1의 나이트를 f3으로, f1의 비숍을 c4로 옮겨 길을 열었다. 흑도 번갈아 수를 둔 뒤, 백 킹을 e1에서 g1로 이동했다. 오른쪽 구석 h1에 있던 룩이 f1로 함께 옮겨졌다.

캐슬링 직후. 백 킹은 g1, 룩은 f1에 놓였고 차례는 흑으로 넘어갔다.
캐슬링 직후. 백 킹은 g1, 룩은 f1에 놓였고 차례는 흑으로 넘어갔다.

그런데 두 말이 함께 움직이는 것만 확인해서는 부족했다. 왕이나 해당 룩이 이미 움직였는지, 왕이 지나가는 칸이 공격받는지도 따져야 했다. 길이 비어 있다는 이유만으로 항상 허용되는 수는 아니다.

폰이 마지막 줄에 닿는 상황도 따로 진행했다. 퀸으로 바로 바뀌게 두지 않고 퀸·룩·비숍·나이트를 고르게 했다. 실제로 나이트를 선택하자 a8의 폰이 흰 나이트로 바뀌었다. 자주 보게 될 장면은 아니어도, 선택은 두는 사람에게 남겨 두고 싶었다.

왕이 잡히기 전에 끝나야 했다

종료를 확인할 때는 양쪽 말을 직접 움직여 짧은 체크메이트 상황을 만들었다. 백 f2-f3, 흑 e7-e5, 백 g2-g4, 흑 d8-h4 순서다. 잘 두려고 진행한 대국이 아니라, 끝나는 조건을 확인하기 위한 수순이었다.

짧은 검증 수순으로 만든 체크메이트. 백 킹은 판에 남아 있고 ‘체크메이트 — 흑 승리’가 표시된다.
짧은 검증 수순으로 만든 체크메이트. 백 킹은 판에 남아 있고 ‘체크메이트 — 흑 승리’가 표시된다.

흑 퀸이 h4에 도착하자 종료 안내가 떴다. 백 킹은 여전히 e1에 남아 있다. 왕을 잡아 없애는 것으로 끝내는 게임이 아니라는 점이 화면에도 드러났다. ‘한 수 무르기’를 누르자 퀸이 돌아가고 흑 차례로 다시 이어졌다.

눈으로 보이지 않는 판정도 있었다. 같은 배치가 반복되면 무승부를 선언할 수 있게 했는데, 처음 코드에서는 앙파상 대상 칸이 기록돼 있다는 이유만으로 서로 다른 배치라고 세고 있었다. 실제로 그 폰을 잡을 수 없는 경우에도 그랬다. 반복 판정에서는 합법적인 앙파상이 가능한 때만 차이를 두도록 고쳤다.

이 부분을 포함해 규칙 테스트 13개를 통과했고, 별도의 체스 라이브러리와 1,080개 배치에서 가능한 수를 비교했다. 비교한 범위에서는 차이가 없었다. 이것이 모든 상황을 검증했다는 뜻은 아니지만, 시작 화면에서 몇 번 눌러 본 것보다는 확인 범위를 넓힐 수 있었다.

이번 작업에서 가장 먼저 고친 것은 흑백 말의 색이었고, 그다음에는 화면에 드러나지 않는 반복 판정을 손봤다. 둘 다 코드를 읽기만 하거나 화면만 보기만 했다면 지나치기 쉬운 부분이었다. 체스판 하나를 띄운 뒤에도 할 일이 꽤 남아 있었다.

지금 버전은 이동 안내를 보며 두 사람이 천천히 둘 수 있는 로컬 체스다. 보드 방향을 뒤집을 수 있고, 잘못 둔 수는 되돌릴 수 있다. 컴퓨터와 겨루는 기능은 없다. 먼저 이 판으로 직접 말을 옮기며 한 게임을 이어 가는 데 집중했다.


실행 방법
저장소의 chess.html 파일을 내려받아 브라우저로 연다. 외부 라이브러리를 불러오지 않는 단일 HTML 파일이다. 말을 클릭한 다음 표시된 칸을 누르면 된다.

체스 게임 소스와 실행 안내

캐슬링·승격·반복 판정은 FIDE 체스 규칙을 참고했다. 이 버전은 대회용 프로그램이 아니며, 모든 교착 배치 판정과 예정 수를 제출하는 사전 무승부 선언은 지원하지 않는다.

다음 이전