// 캐슬링 확인하기 위해 우선 킹이 움직인 적 없는지 확인하고, 다른 편에서 조회하는건지 확인한다
if (FirstMove && !gameManager.checkFromOther)
{
CheckCastling(moves, x, y);
}
king.cs의 PossibleMove()에서 firstMove랑 checkFromOther 확인 후 캐슬링 체크
private void CheckCastling(List<(int, int)> moves, int x, int y)
{
// 왼쪽에 룩이 있는지 확인한다
Rook leftRook = null;
Piece leftRookPositionPiece = gameManager.PieceAt(1, y);
if (leftRookPositionPiece != null) leftRook = leftRookPositionPiece.GetComponent<Rook>();
// 룩이 있고, 한 번도 이동하지 않았다면
if (leftRook != null && leftRook.FirstMove)
{
// 킹 자신이 이동한다면 체크메이트 될지 확인할 때 사용하는 플래그 설정 (폰만 사용함)
gameManager.checkFromOther = true;
bool canCastle = true;
// 룩과 킹 사이에 기물이 있는지 확인하고, 체크가 되는지 확인한다
for (int i = 2; i < x; i++)
{
if (gameManager.PieceAt(i, y) != null || gameManager.IsCheck(i, y))
{
canCastle = false;
break;
}
}
if (canCastle)
{
if (isWhite)
{
gameManager.white_queencastling = true;
moves.Add((x - 2, y));
}
else
{
gameManager.black_queencastling = true;
moves.Add((x - 2, y));
}
}
gameManager.checkFromOther = false;
}
gameManager.cs의 PieceAt(), IsCheck()로 조건을 체크하고, 캐슬링 변수 설정
public bool IsCheck(int x, int y)
{
for (int i = 1; i <= 8; i++)
{
for (int j = 1; j <= 8; j++)
{
GameObject piece = pieces[i, j];
if (piece != null && piece.GetComponent<Piece>().isWhite != whiteTurn)
{
List<(int, int)> moves = piece.GetComponent<Piece>().PossibleMove();
if (moves.Contains((x, y)))
{
return true;
}
}
}
}
return false;
}
IsCheck()에선 상대편 모든 기물 확인
void MoveTo(GameObject piece, Vector2 moveto_position)
{
int mx = (int)moveto_position.x;
int my = (int)moveto_position.y;
// 기물이 있다면 제거 (같은 편인지는 piece의 스크립트에서 검증되어 들어옴)
if (pieces[mx, my] != null)
{
Destroy(pieces[mx, my]);
print("Destroyed");
}
// 폰이라면 앙파상 설정 혹은 앙파상 행동 여부 검사
if (piece.GetComponent<Pawn>() != null)
{
HandleEnPassant(piece, mx, my);
}
// 킹이라면 캐슬링 여부 검사
if (piece.GetComponent<King>() != null)
{
HandleCastling(piece, mx, my);
}
클릭하여 해당 좌표로 이동할 때 킹인지 확인하고 캐슬링 검사
private void HandleCastling(GameObject piece, int mx, int my)
{
King king = piece.GetComponent<King>();
if (king.isWhite)
{
if (mx == 3 && my == 1 && white_queencastling)
{
pieces[1, 1].transform.position = new Vector2(4, 1);
pieces[4, 1] = pieces[1, 1];
pieces[1, 1] = null;
white_queencastling = false;
}
else if (mx == 7 && my == 1 && white_kingcastling)
{
pieces[8, 1].transform.position = new Vector2(6, 1);
pieces[6, 1] = pieces[8, 1];
pieces[8, 1] = null;
white_kingcastling = false;
}
}
이동하려는 좌표를 확인하고, 그에 맞는 캐슬링 변수를 확인.
턴이 시작될 때 게임 매니저의 캐슬링 변수들을 false로 초기화한다.
폰은 공격 가능 대상이 있으면 대각선 이동도 가능하므로,
대각선 이동 가능 여부 조건에 checkFromOther = true을 포함시켜야 한다.
향후 체크메이트 로직에서의 중복을 피하기 위해 게임매니저에 IsCheck() 구현
즉, IsCheck()는 두 가지 용도로 사용됨
pawn의 이동 로직을 gameManager.whiteTurn으로 구별하고 있었는데,
그게 아니라 Piece 자체의 isWhite로 구별하는게 맞다.
애초에 클릭 로직에서 걸러져서 지금껏 오류가 없었던 것.

