Hi, so I have made a version of 2D Chess that uses raycasting for detection of pieces and checking the legality of moves. The error I’m having is to do with the CheckForCheckedKing() method which is meant to check whether moving your piece would put yourself in check. However, it is being very inconsistent and often allows for moves that would put the king in check. This is the relevant code below (Note: Items 1 and 2 are static variables used in GetObject()) :
public void GetObject(GameObject SelectedSquare)
{
if (Click1 == true) // When a square is selected it activates this method which sets the game object as items 1 or 2
{
Click1 = false;
Item1 = SelectedSquare;
Debug.Log("Selected First Item");
FindObjectOfType<AudioManager>().Play("Input");
}
else
{
Click1 = true;
Item2 = SelectedSquare;
Debug.Log("Selected Second Item");
bool Legal = CheckLegalityMove(Item1, Item2); // Goes to check if the move is legal once 2 objects are selected
bool EndangeredKing = CheckForCheckedKing(Item1, Item2); // Checks if the move will put the king of the player's turn in check or not
if (Legal == true && EndangeredKing == false && ((Item1.tag == "White" && Player1Turn == true && (Item2.tag == "Black" || Item2.tag == "EmptySquare")) || (Item1.tag == "Black" && Player1Turn == false && (Item2.tag == "White" || Item2.tag == "EmptySquare"))))
{
FindObjectOfType<AudioManager>().Play("Input");
MovePiece(Item1, Item2);
EnforceConditions();
Player1Turn = !Player1Turn; // If Legal is called back as true and the player isn't moving an enemy piece or killing their own, the pieces are swapped and the timer switches
}
else
FindObjectOfType<AudioManager>().Play("InvalidInput");
Item1 = null;
Item2 = null; // Resets the variables selected
}
}
private bool CheckForCheckedKing(GameObject Item1, GameObject Item2)
{
// Method for seeing if the user will put themselves in check or not BEFORE the move is performed
Player1Turn = !Player1Turn; // Turn order needs to be switched temporarily for the correct set of pieces to be compared when Check() is called
bool KingInDanger = false;
Vector2 Item1Position = Item1.transform.position;
Vector2 Item2Position = Item2.transform.position;
Item1.transform.position = Item2Position; // Temporarily swaps the pieces
Item2.transform.position = Item1Position;
Item2.SetActive(false); // if item2 was an enemy piece, needs to disable it as if the piece was taken
if (Player1Turn == false) //As the turn order is flipped in this function, false means that player 1 is trying to move so needs to check their king
{
GameObject TargetKing = GameObject.Find("WhiteKing(Clone)");
KingInDanger = Check(TargetKing);
}
else
{
GameObject TargetKing = GameObject.Find("BlackKing(Clone)");
KingInDanger = Check(TargetKing);
}
Item2.SetActive(true);
Item1.transform.position = Item1Position;
Item2.transform.position = Item2Position; // Restores the original positions and state of the pieces
Player1Turn = !Player1Turn;
return KingInDanger;
private bool Check(GameObject Target)
{
if (Player1Turn == true)
{
// White is the piece that has just been moved so checks to see if the target is now marked by any of the white pieces
GameObject[] WhitePieces = GameObject.FindGameObjectsWithTag("White");
bool Check = false;
foreach (GameObject piece in WhitePieces)
{
if (piece != Target)
{
bool Marked = CheckLegalityMove(piece, Target);
if (Marked == true) // If a piece marks the target parameter then Check is returned as true
Check = true;
}
}
return Check;
}
else
{
// Black is the piece that has just been moved so checks to see if the target is now marked by any of the black pieces
GameObject[] BlackPieces = GameObject.FindGameObjectsWithTag("Black");
bool Check = false;
foreach (GameObject piece in BlackPieces)
{
if (piece != Target)
{
bool Marked = CheckLegalityMove(piece, Target);
if (Marked == true) // If a piece marks the target parameter then Check is returned as true
Check = true;
}
}
return Check;
}
}
private bool CheckLegalityMove(GameObject Item1, GameObject Item2)
{
// Code to filter which legality is needed here
bool Legal = false;
if (Item1.name == "WhitePawn(Clone)" || Item1.name == "BlackPawn(Clone)")
Legal = MovePawn(Item1, Item2);
else if (Item1.name == "WhiteCastle(Clone)" || Item1.name == "BlackCastle(Clone)")
Legal = MoveCastle(Item1, Item2);
else if (Item1.name == "WhiteKnight(Clone)" || Item1.name == "BlackKnight(Clone)")
Legal = MoveKnight(Item1, Item2);
else if (Item1.name == "WhiteBishop(Clone)" || Item1.name == "BlackBishop(Clone)") // Calls the respective function for each piece
Legal = MoveBishop(Item1, Item2);
else if (Item1.name == "WhiteQueen(Clone)" || Item1.name == "BlackQueen(Clone)")
Legal = MoveQueen(Item1, Item2);
else if (Item1.name == "WhiteKing(Clone)" || Item1.name == "BlackKing(Clone)")
Legal = MoveKing(Item1, Item2);
else
Legal = false;
return Legal;
}
The Move____() methods are similar. They each work by raycasting in certain directions and seeing if they come into contact with Item2 (the target) or not. Some of these (i.e. Queen, Bishop, Castle) disable any EmptySquares in order to prevent them from obstructing white/black pieces. For example:
private bool MoveCastle(GameObject Item1, GameObject Item2)
{
// Code for castle here
bool Legal = false;
Item1.SetActive(false); // The raycast hits on the object it casts from unless disabled
ChangeEmptySquares(false);
Item2.SetActive(true); // Ensures Item2 is active incase it was an emptysquare (it would've been disabled in ChangeEmptySquares()
RaycastHit2D hit = Physics2D.Raycast(Item1.transform.position, new Vector2(1, 0), 400.0f);
if (hit.collider != null && hit.collider.gameObject == Item2)
Legal = true;
hit = Physics2D.Raycast(Item1.transform.position, new Vector2(0, 1), 400.0f);
if (hit.collider != null && hit.collider.gameObject == Item2)
Legal = true;
hit = Physics2D.Raycast(Item1.transform.position, new Vector2(0, -1), 400.0f);
if (hit.collider != null && hit.collider.gameObject == Item2)
Legal = true;
hit = Physics2D.Raycast(Item1.transform.position, new Vector2(-1, 0), 400.0f);
if (hit.collider != null && hit.collider.gameObject == Item2)
Legal = true;
ChangeEmptySquares(true);
Item1.SetActive(true); // Enables item1 after raycasting from it
return Legal;
// Castle, Queen and Bishop all do sequential raycasts after disabling emptysquares except item2 in order to check if it can move over multiple squares
}
Does anyone know why it isn’t working?