체스 봇 개발 일지 3일차
2023 09 08
저번 2일차까지 코드 분석을 했다. 이제부터는 더 많은 게임의 기능을 구현해볼 것이다. 캐슬링, 승진, 체크까지 구현해볼 생각이다. 오늘은 캐슬링을 구현할 것이다.
1. 캐슬링이란
일단 구현에 앞서 캐슬링이란 킹을 두 칸 옆으로 옮기고 룩을 킹의 반대편 옆으로 옮길 수 있는 규칙이다. 캐슬링에는 2가지 종류가 있다. 바로 킹사이드 캐슬링과 퀸 사이드 캐슬링이다. 말 그대로 킹쪽 룩과 자리를 바꾸면 킹 사이드, 퀸 쪽 룩과 바꾸면 퀸 사이드이다. 그리고 캐슬링을 하기 위해서는 3가지 조건을 충족해야 한다. 첫 번째는 킹과 캐슬링을 할 룩 사이의 공간을 완전히 비워야 한다는 것이고, 두 번째는 킹과 캐슬링을 할 룩이 게임을 시작하고 한 번도 이동한 적이 없어야 한다는 것이다. 세 번째는 체크 상태가 아니어야 한다는 것이다.
2. 구현
처음에 일단 킹과 룩의 움직임을 카운트 해줄 변수를 만든다. 그리고 킹 또는 룩이 움직였으면 그 변수를 증가시킨다. 이 변수를 이용해 두 번째 조건을 판단할 것이다. 그 다음 킹의 위치를 (ax,ay)로 받고 룩의 위치를 (bx,by)로 받는다. 그리고 룩의 bx,by (룩의 위치)로 퀸 사이드인지 킹 사이드인지 판별한다. 킹 사이드이면 옆으로 2칸이 다 비였는지 확인한다. 퀸 사이드면 3칸을 확인한다. 이 조건이 모두 충족이 된다면 킹과 룩을 정해진 자리로 이동시킨다.
int Ro(int team, int ax, int ay, int bx, int by, Piece _pBoard[][10]) {
if (ax != bx && ay != by) {
printf("impossible\n");
return 0;
}
if (ax == bx) {
for (int y = min(ay, by) + 1; y < max(ay, by); y++) {
if (_pBoard[y][ax].type > 0) {
printf("impossible\n");
return 0;
}
}
if (_pBoard[by][bx].team != team) {
if (ax == 1 && ay == 8) br1++;
else if (ax == 8 && ay == 8) br2++;
else if (ax == 1 && ay == 1) wr1++;
else if (ax == 8 && ay == 1) wr2++;
_move(ax, ay, bx, by, _pBoard);
printf("attack\n");
else return 2;
}
else if (_pBoard[by][bx].team == team) {
printf("same team impossible\n");
return 0;
}
else if (_pBoard[by][bx].team == -1) {
if (ax == 1 && ay == 8) br1++;
else if (ax == 8 && ay == 8) br2++;
else if (ax == 1 && ay == 1) wr1++;
else if (ax == 8 && ay == 1) wr2++;
_move(ax, ay, bx, by, _pBoard);
printf("move\n");
else return 1;
}
}
if (ay == by) {
for (int x = min(ax, bx) + 1; x < max(ax, bx); x++) {
if (_pBoard[ay][x].type > 0) {
printf("impossible\n");
return 0;
}
}
if (_pBoard[by][bx].team != -1 && _pBoard[by][bx].team != team) {
if (ax == 1 && ay == 8) br1++;
else if (ax == 8 && ay == 8) br2++;
else if (ax == 1 && ay == 1) wr1++;
else if (ax == 8 && ay == 1) wr2++;
_move(ax, ay, bx, by, _pBoard);
printf("attack\n");
else return 2;
}
else if (_pBoard[by][bx].team == team) {
printf("same team impossible\n");
return 0;
}
else if (_pBoard[by][bx].team == -1) {
if (ax == 1 && ay == 8) br1++;
else if (ax == 8 && ay == 8) br2++;
else if (ax == 1 && ay == 1) wr1++;
else if (ax == 8 && ay == 1) wr2++;
_move(ax, ay, bx, by, _pBoard);
printf("move\n");
else return 1;
}
}
return 0;
}
br1, br2, wr1, wr2 라는 변수들이 바로 룩의 이동을 카운트하는 변수들이다. 이동 할 룩의 좌표에 따라 그에 맞는 변수를 증가시킨다.
int Ki(int team, int ax, int ay, int bx, int by, Piece _pBoard[][10]) {
castling = 0;
if (_pBoard[by][bx].team == team) {
if (_pBoard[by][bx].type == 2) {
if (_pBoard[ay][ax].team == 1 && w_cnt == 0) {
if (bx == 1 && by == 1) {
if (wr1 == 0) {
if (_pBoard[1][2].type == 0 && _pBoard[1][3].type == 0) {
_move(ax, ay, 2, 1, _pBoard);
_move(bx, by, 3, 1, _pBoard);
castling = 1;
w_cnt++;
return 1;
}
}
}
if (bx == 8 && by == 1) {
if (wr2 == 0) {
if (_pBoard[1][5].type == 0 && _pBoard[1][6].type == 0 && _pBoard[1][7].type == 0) {
_move(ax, ay, 6, 1, _pBoard);
_move(bx, by, 5, 1, _pBoard);
castling = 1;
w_cnt++;
return 1;
}
}
}
}
else if (_pBoard[ay][ax].team == 0 && b_cnt == 0) {
if (bx == 1 && by == 8) {
if (br1 == 0) {
if (_pBoard[8][2].type == 0 && _pBoard[8][3].type == 0)
{
_move(ax, ay, 2, 8, _pBoard);
_move(bx, by, 3, 8, _pBoard);
castling = 1;
b_cnt++;
return 1;
}
}
}
else if (bx == 8 && by == 8) {
if (br2 == 0) {
if (_pBoard[8][5].type == 0 && _pBoard[8][6].type == 0 && _pBoard[8][7].type == 0)
{
_move(ax, ay, 6, 8, _pBoard);
_move(bx, by, 5, 8, _pBoard);
castling = 1;
b_cnt++;
return 1;
}
}
}
}
}
if (castling == 0) {
printf("same team impossible\n");
return 0;
}
}
if (abs(ay - by) > 1 || abs(ax - bx) > 1) {
printf("impossible\n");
return 0;
}
else if (_pBoard[by][bx].type < 1) {
if (_pBoard[ay][ax].team == 0) {
b_cnt++;
}
else if (_pBoard[ay][ax].team == 1) {
w_cnt++;
}
printf("move\n");
_move(ax, ay, bx, by, _pBoard);
else return 1;
}
else if (_pBoard[by][bx].team != team) {
if (_pBoard[ay][ax].team == 0) {
b_cnt++;
}
else if (_pBoard[ay][ax].team == 1) {
w_cnt++;
}
printf("attack\n");
_move(ax, ay, bx, by, _pBoard);
else return 2;
}
else
printf("error\n");
return 0;
}
맨 1,2번째 if문에서 선택한 기물이 룩이고 선택한 왕과 팀이 같은지 확인한다. 그 다음 룩의 팀과 어느 룩이냐에 따라 경우를 나눈다. 그리고 이에 맞게 위해서 만든 변수를 이용하여 이전에 이동을 했는지 확인한다. 만약 이동을 안했다면 킹과 룩을 알맞은 자리로 이동시킨다. 마지막으로 캐슬링이라는 변수에 1을 넣어 성공 여부를 판단하고 성공했다면 1을 리턴, 실패했다면 0을 리턴한다.
3. 마치며
첫 번째 추가 기능 구현을 마쳤다. 캐슬링은 이동되는 자리가 정해져 있어 약간의 노가다만 있었을 뿐 그렇게 어렵지는 않았다. 다음에는 폰이 끝까지 이동하면 다른 기물로 바꿀 수 있는 계승을 구현해볼 것이다.