Ejemplo n.º 1
0
    void MakeMove(Piece targetSquare)
    {
        //	Move proposedMove = new Move(, targetSquare);
        if (board.MakeMove(selectedSquare.coordinates, targetSquare.coordinates))
        {
            AudioManager.PlaySoundEffect(move);
            colourToMove = GameBoard.Colour.Black;
            if (legal.Mated(board.analysisBoard, GameBoard.Colour.Black))
            {
                if (inGameMode)
                {
                    freezeTimer = true;
                }
                Invoke("PuzzleCompleted", .4f);
            }
            else
            {
                Invoke("Lose", .5f);
                Invoke("AIResponse", .5f);
            }

            //NextMove();
        }
        pieceSelected = false;
        selectedPiece.localPosition = Vector3.zero;
        isDragging = false;
    }
Ejemplo n.º 2
0
 public Square(Coord coords, GameBoard.Pieces pieceP, GameBoard.Colour pieceColourP)
 {
     coordinates       = coords;
     piece             = pieceP;
     pieceColour       = pieceColourP;
     underAttack       = false;
     isEnPassantSquare = false;
     //destroyEP = false;
 }
Ejemplo n.º 3
0
    public List <Move> GetAllLegalMoves(Square[,] board, GameBoard.Colour myColour)
    {
        List <Move> allMoves = new List <Move>();

        foreach (Square s in board)
        {
            if (s.piece != GameBoard.Pieces.Empty && s.pieceColour == myColour)
            {
                BitBoard[,] myBitboard = new BitBoard[8, 8];
                switch (s.piece)
                {
                case GameBoard.Pieces.Pawn:
                    myBitboard = (myColour == GameBoard.Colour.White)?pawnBoardWhite:pawnBoardBlack;
                    break;

                case GameBoard.Pieces.Rook:
                    myBitboard = rookBoard;
                    break;

                case GameBoard.Pieces.Knight:
                    myBitboard = knightBoard;
                    break;

                case GameBoard.Pieces.Bishop:
                    myBitboard = bishopBoard;
                    break;

                case GameBoard.Pieces.Queen:
                    myBitboard = queenBoard;
                    break;

                case GameBoard.Pieces.King:
                    myBitboard = kingBoard;
                    break;
                }


                for (int ranks = 0; ranks < 8; ranks++)
                {
                    for (int files = 0; files < 8; files++)
                    {
                        if (myBitboard[s.coordinates.x, s.coordinates.y].Get(new Coord(files, ranks)))
                        {
                            Move m = new Move(s, board[files, ranks]);

                            if (IsLegalMove(m, board))
                            {
                                allMoves.Add(m);
                            }
                        }
                    }
                }
            }
        }

        return(allMoves);
    }
Ejemplo n.º 4
0
    public bool Mated(Square[,] board, GameBoard.Colour matedColour)
    {
        Move[] allMoves = GetAllLegalMoves(board, matedColour).ToArray();
        if (allMoves.Length == 0)
        {
            foreach (Square s in board)
            {
                if (s.piece == GameBoard.Pieces.King && s.pieceColour == matedColour)
                {
                    return(SquareUnderAttack(s.coordinates, board, matedColour));
                }
            }
        }

        return(false);
    }
Ejemplo n.º 5
0
    public Move GetMove(Square[,] analysisBoard, GameBoard.Colour myColour)
    {
        List <Move> allMoves = legalMoves.GetAllLegalMoves(analysisBoard, myColour);

        if (allMoves.Count > 0)
        {
            Move m = allMoves[Random.Range(0, allMoves.Count)];
            return(m);
            //board.MakeComputerMove(move);
        }
        else
        {
            print("AI MATED");
        }
        return(null);
    }
Ejemplo n.º 6
0
    static string PieceToNotation(GameBoard.Pieces piece, GameBoard.Colour colour)
    {
        string notation = "";

        switch (piece)
        {
        case GameBoard.Pieces.Pawn:
            notation = "P";
            break;

        case GameBoard.Pieces.Rook:
            notation = "R";
            break;

        case GameBoard.Pieces.Knight:
            notation = "N";
            break;

        case GameBoard.Pieces.Bishop:
            notation = "B";
            break;

        case GameBoard.Pieces.Queen:
            notation = "Q";
            break;

        case GameBoard.Pieces.King:
            notation = "K";
            break;
        }

        if (colour == GameBoard.Colour.Black)
        {
            notation = notation.ToLower();
        }
        return(notation);
    }
Ejemplo n.º 7
0
 void LoadNextPuzzle(int level = 1)
 {
     board.LoadPuzzle(puzzles.GetNextPuzzle());
     colourToMove = GameBoard.Colour.White;
     Invoke("MakeBlacksMove", .5f);
 }
Ejemplo n.º 8
0
    public void SetupFromFEN(string fen)
    {
        //fen = "r2q3r/ppp2Bpp/8/2B1k2n/4P3/3P4/PPP3PP/R2b1RK1 w - - [5544]";
        for (int ranks = 0; ranks < 8; ranks++)
        {
            for (int files = 0; files < 8; files++)
            {
                board[files, ranks]             = drawBoard.GetSquare(files, ranks);
                board[files, ranks].piece       = Pieces.Empty;
                board[files, ranks].coordinates = new Coord(files, ranks);
            }
        }

        string numbers  = "12345678";
        int    fenIndex = 0;

        for (int ranks = 7; ranks >= 0; ranks--)
        {
            for (int files = 0; files < 8; files++)
            {
                char fenChar = fen[fenIndex];
                fenIndex++;
                if (fenChar == '/')
                {
                    fenChar = fen[fenIndex];
                    fenIndex++;
                }

                if (numbers.Contains(fenChar.ToString()))
                {
                    files += int.Parse(fenChar.ToString()) - 1;
                }
                else
                {
                    board[files, ranks].piece       = NotationToPiece(fenChar);
                    board[files, ranks].pieceColour = (IsUpper(fenChar + ""))?Colour.White:Colour.Black;
                }
            }
        }


        for (int ranks = 0; ranks < 8; ranks++)
        {
            for (int files = 0; files < 8; files++)
            {
                analysisBoard[files, ranks] = new Square(board[files, ranks].coordinates, board[files, ranks].piece, board[files, ranks].pieceColour);
            }
        }

        string remainingFen = fen.Substring(fen.IndexOf(" "));

        GameBoard.Colour colToMove = GameBoard.Colour.White;
        int   fenSection           = 0;
        bool  sectionActive        = false;
        bool  isEnPassant          = false;
        Coord enPassantSquare      = new Coord();

        bool  hasBlacksLastMove = false;
        Coord blackLastMoveFrom = new Coord();
        Coord blackLastMoveTo   = new Coord();

        int[] blacksLastMoveCoord = new int[4];
        int   blacksLastMoveIndex = 0;

        legalMoves.NoCastling();
        foreach (char c in remainingFen)
        {
            if (fenSection == 0)
            {
                if (c == 'w' || c == 'b')                  // colour to move
                {
                    fenSection++;
                }
                if (c == 'b')
                {
                    colToMove = Colour.Black;
                }
            }
            else if (fenSection == 1)               // castling rights
            {
                if (c == '-')
                {
                    fenSection++;
                }
                else
                {
                    if ("kKqQ".Contains(c + ""))
                    {
                        sectionActive = true;
                    }
                    if (c == 'K')
                    {
                        legalMoves.whiteCanCastleKingside = true;
                    }
                    if (c == 'k')
                    {
                        legalMoves.blackCanCastleKingside = true;
                    }
                    if (c == 'Q')
                    {
                        legalMoves.whiteCanCastleQueenside = true;
                    }
                    if (c == 'q')
                    {
                        legalMoves.blackCanCastleQueenside = true;
                    }
                    if (c == ' ' && sectionActive)
                    {
                        sectionActive = false;
                        fenSection++;
                    }
                }
            }
            else if (fenSection == 2)               // en passant square
            {
                if (c == '-')
                {
                    fenSection++;
                }
                else
                {
                    if ("abcdefgh".Contains(c + ""))
                    {
                        sectionActive   = true;
                        isEnPassant     = true;
                        enPassantSquare = new Coord("abcdefgh"[c], 0);
                    }
                    if ("12345678".Contains(c + ""))
                    {
                        enPassantSquare = new Coord(enPassantSquare.x, "12345678".IndexOf(c));
                    }
                    if (c == ' ' && sectionActive)
                    {
                        sectionActive = false;
                        fenSection++;
                    }
                }
            }
            else if (fenSection == 3)               // puzzle 'black's last move' coords
            {
                if (c == '[')
                {
                    sectionActive = true;
                }
                if (c == ']')
                {
                    sectionActive = false;
                }
                if (sectionActive)
                {
                    if ("01234567".Contains(c + ""))
                    {
                        hasBlacksLastMove = true;

                        blacksLastMoveCoord[blacksLastMoveIndex] = int.Parse(c + "");

                        blacksLastMoveIndex++;
                    }
                }
            }
        }

        if (isEnPassant)
        {
            analysisBoard[enPassantSquare.x, enPassantSquare.y].isEnPassantSquare = true;
        }
        manager.colourToMove = colToMove;

        isPuzzle = hasBlacksLastMove;

        if (hasBlacksLastMove)
        {
            blacksPuzzleMoveFrom = new Coord(blacksLastMoveCoord[0], blacksLastMoveCoord[1]);
            blacksPuzzleMoveTo   = new Coord(blacksLastMoveCoord[2], blacksLastMoveCoord[3]);

            //Invoke("MakeBlacksMove", .5f);
            //MakeBlacksMove();
        }


        drawBoard.RedrawBoard(board);
    }
Ejemplo n.º 9
0
    public void ReadPGN(string pgn)
    {
        bool   readingExtraInfo  = false;
        bool   readingGame       = false;
        bool   readingMove       = false;
        bool   readingWhiteMove  = false;
        string currentMoveString = "";
        string moveLetters       = "abcdefghRNBQKO";

        List <string> currentGameMoveNotations = new List <string>();

        // Separate moves into strings
        for (int i = 0; i < pgn.Length; i++)
        {
            char c = pgn[i];
            if (c == '[')
            {
                readingGame      = false;
                readingExtraInfo = true;
            }
            if (c == ']')
            {
                readingExtraInfo = false;
            }

            if (readingGame)
            {
                if (!readingMove && c == '-')                   // Game over (result token, e.g. 0-1)
                {
                    moveNotation.Add(currentGameMoveNotations);
                    currentGameMoveNotations = new List <string>();
                    readingGame = false;
                    readingMove = false;
                }
                if (moveLetters.Contains(c.ToString()))
                {
                    readingMove = true;
                }
                if (c == ' ' || c == '.' || c == '\n' || c == '+' || c == '#')
                {
                    if (currentMoveString.Length >= 2)
                    {
                        currentGameMoveNotations.Add(currentMoveString);
                    }

                    readingMove = false;

                    currentMoveString = "";
                }
                if (readingMove)
                {
                    currentMoveString += c.ToString();
                }
            }
            else if (c == '1' && !readingExtraInfo)
            {
                readingGame      = true;
                readingWhiteMove = true;
            }
        }

        for (int gameIndex = 0; gameIndex < moveNotation.Count; gameIndex++)
        {
            // Convert move notation to moves
            GameBoard.Colour colourToMove     = GameBoard.Colour.White;
            List <Move>      currentGameMoves = new List <Move>();
            //print (moveNotation[gameIndex].Count);
            foreach (string m in moveNotation[gameIndex])
            {
                //print ( "   ASDAS " + m);
                string pieceType      = "";            // e.g RNBQK
                string disambiguation = "";            // (e.g. Rfd1 (f is disambiguation between two possible rooks)
                string targetSquare   = "";            // e.g e4
                bool   promoting      = false;
                string promotionPiece = "";

                string pieceSymbols      = "RNBQK";
                string coordinateSymbols = "abcdefgh";
                string coordinateNumbers = "12345678";

                if (m == "O-O" || m == "O-O-O")                   // Castling
                //print ("CASS");
                {
                    pieceType     = "K";
                    targetSquare  = (m == "O-O")?"g":"c";
                    targetSquare += (colourToMove == GameBoard.Colour.White)?"1":"8";
                }
                else
                {
                    for (int i = 0; i < m.Length; i++)                       // Iterate through each char in move string
                    {
                        char c = m[i];

                        if (c == '=')
                        {
                            promoting = true;
                        }

                        if (GameBoard.IsUpper(c.ToString()) && pieceSymbols.Contains(c.ToString()))
                        {
                            if (promoting)
                            {
                                promotionPiece = c.ToString();
                            }
                            else
                            {
                                pieceType = c.ToString();
                            }
                        }
                        else
                        {
                            if (coordinateSymbols.Contains(c.ToString()))
                            {
                                if (targetSquare != "")
                                {
                                    disambiguation = targetSquare;
                                }
                                targetSquare = c.ToString();
                            }
                            else if (coordinateNumbers.Contains(c.ToString()))
                            {
                                targetSquare += c.ToString();
                            }
                        }
                    }
                }
                if (pieceType == "")
                {
                    pieceType = "P";
                }
                //	print (m);

                Move newMove = legalMoves.GetMoveFromNotation(pieceType, targetSquare, disambiguation, promotionPiece, board.analysisBoard, colourToMove, m);

                currentGameMoves.Add(newMove);
                if (newMove != null)
                {
                    board.UpdateAnalysisBoard(newMove);
                }
                colourToMove = (colourToMove == GameBoard.Colour.White)?GameBoard.Colour.Black:GameBoard.Colour.White;
            }
            allMoves.Add(currentGameMoves);
            board.ResetBoardToStarting();
            legalMoves.NewGame();
        }
        devMode.SetMoves(allMoves);
    }
Ejemplo n.º 10
0
    void NextPuzzle()
    {
        board.ResetBoardToStarting();
        legal.NewGame();

        //print (puzzleIndex);

        //print ("Move Count: " +allMoves[puzzleIndex].Count);
        foreach (Move m in allMoves[puzzleIndex])
        {
            board.MakeMove(m.moveFrom.coordinates, m.moveTo.coordinates);
        }
        bool mated = false;
        bool flip  = false;

        if (legal.Mated(board.analysisBoard, GameBoard.Colour.Black))
        {
            mated = true;
        }
        else if (legal.Mated(board.analysisBoard, GameBoard.Colour.White))
        {
            mated = true;
            flip  = true;
        }


        if (mated)
        {
            blacksLastMove = allMoves[puzzleIndex][allMoves[puzzleIndex].Count - 2];

            board.ResetBoardToStarting();
            for (int i = 0; i < allMoves[puzzleIndex].Count - 2; i++)
            {
                Move m = allMoves[puzzleIndex][i];
                board.MakeMove(m.moveFrom.coordinates, m.moveTo.coordinates);
            }

            if (flip)
            {
                for (int ranks = 0; ranks < 4; ranks++)
                {
                    for (int files = 0; files < 8; files++)
                    {
                        GameBoard.Pieces tempPiece  = board.analysisBoard[files, ranks].piece;
                        GameBoard.Colour tempColour = board.analysisBoard[files, ranks].pieceColour;
                        bool             tempEp     = board.analysisBoard[files, ranks].isEnPassantSquare;

                        board.analysisBoard[files, ranks].piece                     = board.analysisBoard[7 - files, 7 - ranks].piece;
                        board.analysisBoard[files, ranks].pieceColour               = (board.analysisBoard[7 - files, 7 - ranks].pieceColour == GameBoard.Colour.White)?GameBoard.Colour.Black:GameBoard.Colour.White;
                        board.analysisBoard[files, ranks].isEnPassantSquare         = board.analysisBoard[7 - files, 7 - ranks].isEnPassantSquare;
                        board.analysisBoard[7 - files, 7 - ranks].piece             = tempPiece;
                        board.analysisBoard[7 - files, 7 - ranks].pieceColour       = (tempColour == GameBoard.Colour.White)?GameBoard.Colour.Black:GameBoard.Colour.White;
                        board.analysisBoard[7 - files, 7 - ranks].isEnPassantSquare = tempEp;
                    }
                }
                blacksLastMove.moveFrom.coordinates = new Coord(7 - blacksLastMove.moveFrom.coordinates.x, 7 - blacksLastMove.moveFrom.coordinates.y);
                blacksLastMove.moveTo.coordinates   = new Coord(7 - blacksLastMove.moveTo.coordinates.x, 7 - blacksLastMove.moveTo.coordinates.y);
            }

            puzzleFen = DatabaseManager.GetPuzzleFEN(board.analysisBoard, blacksLastMove.moveFrom.coordinates, blacksLastMove.moveTo.coordinates, legal);
            board.SetToAnalysisBoard();
            board.MakeMove(blacksLastMove.moveFrom.coordinates, blacksLastMove.moveTo.coordinates);
            board.SetToAnalysisBoard();
        }
        else
        {
            SetPuzzle(false);
        }
    }
Ejemplo n.º 11
0
    public Move GetMoveFromNotation(string pieceType, string targetSquare, string disambiguation, string promotionPieceString, Square[,] analysisBoard, GameBoard.Colour colourToMove, string originalNotation = "")
    {
        bool  debugMode = (originalNotation == "xxx");
        Coord toCoord   = new Coord("abcdefgh".IndexOf(targetSquare[0]), int.Parse(targetSquare[1].ToString()) - 1);

        GameBoard.Pieces movePiece    = GameBoard.Pieces.Empty;
        GameBoard.Pieces promotePiece = GameBoard.Pieces.Empty;
        moveIndex++;

        #region piece type
        switch (pieceType)
        {
        case "P":
            movePiece = GameBoard.Pieces.Pawn;
            break;

        case "R":
            movePiece = GameBoard.Pieces.Rook;
            break;

        case "N":
            movePiece = GameBoard.Pieces.Knight;
            break;

        case "B":
            movePiece = GameBoard.Pieces.Bishop;
            break;

        case "Q":
            movePiece = GameBoard.Pieces.Queen;
            break;

        case "K":
            movePiece = GameBoard.Pieces.King;
            break;
        }
        #endregion

        if (promotionPieceString != "")
        {
            switch (promotionPieceString)
            {
            case "R":
                promotePiece = GameBoard.Pieces.Rook;
                break;

            case "N":
                promotePiece = GameBoard.Pieces.Knight;
                break;

            case "B":
                promotePiece = GameBoard.Pieces.Bishop;
                break;

            case "Q":
                promotePiece = GameBoard.Pieces.Queen;
                break;
            }
        }


        // if more than one piece is able to reach the target square, e.g. Rfd1 (where f is the disambiguation)
        if (disambiguation != "")
        {
            bool findRank   = false;                 // true if given file
            int  givenValue = 0;
            if ("abcdefgh".Contains(disambiguation)) // given file
            {
                givenValue = "abcdefgh".IndexOf(disambiguation);
                findRank   = true;
            }
            if ("12345678".Contains(disambiguation))               // given rank
            {
                int givenRank = "12345678".IndexOf(disambiguation);
                if (findRank)
                {
                    Move m = new Move(analysisBoard[givenValue, givenRank], analysisBoard[toCoord.x, toCoord.y]);
                    m.promotionPiece = promotePiece;
                    return(m);
                }
                givenValue = givenRank;
            }

            for (int i = 0; i < 8; i++)
            {
                Coord checkCoord = new Coord((findRank)?givenValue:i, (findRank)?i:givenValue);

                if (analysisBoard[checkCoord.x, checkCoord.y].piece == movePiece && analysisBoard[checkCoord.x, checkCoord.y].pieceColour == colourToMove)
                {
                    Move proposedMove = new Move(analysisBoard[checkCoord.x, checkCoord.y], analysisBoard[toCoord.x, toCoord.y]);
                    proposedMove.promotionPiece = promotePiece;
                    if (IsLegalMove(proposedMove, analysisBoard, debugMode))
                    {
                        return(proposedMove);
                    }
                }
            }
        }
        else           // Only one piece can reach this square
        {
            Coord moveFromCoords;


            foreach (Square s in analysisBoard)
            {
                if (s.piece == movePiece && s.pieceColour == colourToMove)
                {
                    Move proposedMove = new Move(s, analysisBoard[toCoord.x, toCoord.y]);
                    proposedMove.promotionPiece = promotePiece;
                    if (IsLegalMove(proposedMove, analysisBoard, debugMode))
                    {
                        return(proposedMove);
                    }
                }
            }
        }
        print("Move illegal " + originalNotation + "  " + gameIndex + "  " + Mathf.CeilToInt(moveIndex / 2f));
        return(null);
    }
Ejemplo n.º 12
0
    bool SquareUnderAttack(Coord coord, Square[,] analysisBoard, GameBoard.Colour friendlyColour)
    {
        // work outwards from friendly king to find attacking pieces
        foreach (Coord dir in rookDirections)           // check horizontal/vertical
        {
            for (int i = 1; i < 8; i++)
            {
                Coord c = coord + dir * i;
                if (CoordInRange(c))
                {
                    Square checkSquare = GetSquare(analysisBoard, c);
                    if (checkSquare.piece != GameBoard.Pieces.Empty)
                    {
                        if (checkSquare.pieceColour == friendlyColour)                         // Direction blocked by a friendly piece
                        {
                            break;
                        }
                        else                                                                                                                                                         // enemy piece in this direction
                        {
                            if (checkSquare.piece == GameBoard.Pieces.Rook || checkSquare.piece == GameBoard.Pieces.Queen || (i == 1 && checkSquare.piece == GameBoard.Pieces.King)) // Is a piece that attacks horizontally/vertically
                            {
                                return(true);                                                                                                                                        // King is still in check, thus move is not legal
                            }
                            else                                                                                                                                                     // enemy piece in this direction, but not one that attacks in this direction, thus blocking any further attacks in this direction
                            {
                                break;
                            }
                        }
                    }
                }
                else                   // end of board, check next direction
                {
                    break;
                }
            }
        }

        foreach (Coord dir in bishopDirections)           // check diagonals
        {
            for (int i = 1; i < 8; i++)
            {
                Coord c = coord + dir * i;
                if (CoordInRange(c))
                {
                    Square checkSquare = GetSquare(analysisBoard, c);
                    if (checkSquare.piece != GameBoard.Pieces.Empty)
                    {
                        if (checkSquare.pieceColour == friendlyColour)                         // Direction blocked by a friendly piece
                        {
                            break;
                        }
                        else                                                                                                                                                           // enemy piece in this direction
                        {
                            if (checkSquare.piece == GameBoard.Pieces.Bishop || checkSquare.piece == GameBoard.Pieces.Queen || (i == 1 && checkSquare.piece == GameBoard.Pieces.King)) // Is a piece that attacks diagonally
                            {
                                return(true);                                                                                                                                          // King is still in check, thus move is not legal
                            }
                            else                                                                                                                                                       // enemy piece in this direction, but not one that attacks in this direction, thus blocking any further attacks in this direction
                            {
                                break;
                            }
                        }
                    }
                }
                else                   // end of board, check next direction
                {
                    break;
                }
            }
        }

        // Check knight attacks
        foreach (Coord knightOffset in knightDirections)
        {
            Coord c = coord + knightOffset;
            if (CoordInRange(c))
            {
                Square s = GetSquare(analysisBoard, c);
                if (s.piece == GameBoard.Pieces.Knight && s.pieceColour != friendlyColour)                   // square is attacked by enemy knight
                {
                    return(true);
                }
            }
        }


        // Check pawn attacks
        int pawnAttackDir = (friendlyColour == GameBoard.Colour.White)?-1:1;

        for (int i = -1; i <= 1; i += 2)
        {
            Coord pawnAttackCoord = coord + new Coord(i, -pawnAttackDir);
            if (CoordInRange(pawnAttackCoord))
            {
                Square s = GetSquare(analysisBoard, pawnAttackCoord);
                if (s.piece == GameBoard.Pieces.Pawn && s.pieceColour != friendlyColour)                   // square attacked by enemy pawn
                {
                    return(true);
                }
            }
        }

        return(false);
    }
Ejemplo n.º 13
0
    public bool IsLegalMove(Move move, Square[,] board, bool debugMode = false)
    {
        Square[,] analysisBoard = new Square[8, 8];

        for (int ranks = 0; ranks < 8; ranks++)
        {
            for (int files = 0; files < 8; files++)
            {
                analysisBoard[files, ranks] = new Square(board[files, ranks].coordinates, board[files, ranks].piece, board[files, ranks].pieceColour);
                analysisBoard[files, ranks].isEnPassantSquare = board[files, ranks].isEnPassantSquare;
            }
        }


        GameBoard.Pieces pieceType      = move.moveFrom.piece;
        GameBoard.Colour friendlyColour = move.moveFrom.pieceColour;

        Coord  toCoord      = move.moveTo.coordinates;
        Coord  fromCoord    = move.moveFrom.coordinates;
        Square targetSquare = analysisBoard[toCoord.x, toCoord.y];

        GameBoard.Pieces capturePiece = targetSquare.piece;

        if (debugMode)
        {
//			print (pieceType + " from " + fromCoord.x +";"+fromCoord.y + " to " + toCoord.x + ";" + toCoord.y + "  " );
        }

        // Do not allow capture of friendly pieces OR of kings
        if (targetSquare.pieceColour == friendlyColour && targetSquare.piece != GameBoard.Pieces.Empty || targetSquare.piece == GameBoard.Pieces.King)
        {
            if (debugMode)
            {
                print("Trying to capture friendly piece / king");
            }
            return(false);
        }


        // apply suggested move to analysis board (whether legal or not)
        analysisBoard[toCoord.x, toCoord.y].piece       = analysisBoard[fromCoord.x, fromCoord.y].piece;
        analysisBoard[toCoord.x, toCoord.y].pieceColour = friendlyColour;

        analysisBoard[fromCoord.x, fromCoord.y].piece = GameBoard.Pieces.Empty;
        Coord epCoord = new Coord();

        GameBoard.Pieces epRemovedPiece = GameBoard.Pieces.Empty;
        bool             isEP           = false;

        if (analysisBoard[toCoord.x, toCoord.y].isEnPassantSquare && toCoord.x != fromCoord.x && pieceType == GameBoard.Pieces.Pawn)
        {
            isEP = true;
            int epDir = (toCoord.y == 5)?-1:1;
            epCoord        = new Coord(toCoord.x, toCoord.y + epDir);
            epRemovedPiece = analysisBoard[epCoord.x, epCoord.y].piece;
            analysisBoard[epCoord.x, epCoord.y].piece = GameBoard.Pieces.Empty;
        }


        Coord deltaMove = toCoord - fromCoord;

        // Check if resulting position is legal (is king in check)
        Coord friendlyKingCoord = new Coord();

        foreach (Square s in analysisBoard)
        {
            if (s.pieceColour == friendlyColour && s.piece == GameBoard.Pieces.King)
            {
                friendlyKingCoord = s.coordinates;
                break;
            }
        }

        Coord offsetFromMyKing = fromCoord - friendlyKingCoord;
        bool  pinned           = false;

        if (SquareUnderAttack(friendlyKingCoord, analysisBoard, friendlyColour))
        {
            if (debugMode)
            {
                print("Piece is pinned");
            }
            pinned = true;
        }
        if (isEP)
        {
            analysisBoard[epCoord.x, epCoord.y].piece = epRemovedPiece;
        }

        if (pinned)
        {
            return(false);
        }


        // check if move direction is allowed by this piece
        // reset analysis board
        analysisBoard[fromCoord.x, fromCoord.y].piece       = analysisBoard[toCoord.x, toCoord.y].piece;
        analysisBoard[fromCoord.x, fromCoord.y].pieceColour = friendlyColour;
        analysisBoard[toCoord.x, toCoord.y].piece           = capturePiece;
        analysisBoard[toCoord.x, toCoord.y].pieceColour     = (friendlyColour == GameBoard.Colour.White)?GameBoard.Colour.Black:GameBoard.Colour.White;



        if (pieceType == GameBoard.Pieces.Knight)           // Check if knight move is legal
        {
            foreach (Coord c in knightDirections)
            {
                if (fromCoord + c == toCoord)
                {
                    return(true);
                }
            }
            return(false);
        }
        else if (pieceType == GameBoard.Pieces.Pawn)
        {
            if (toCoord.y == 0 || toCoord.y == 7)               // is promoting if reached first/eigth rank
            {
                move.isPromotion = true;


                if (move.promotionPiece == GameBoard.Pieces.Empty)
                {
                    move.promotionPiece = GameBoard.Pieces.Queen;
                    foreach (Coord c in knightDirections)
                    {
                        Coord knightAttackRange = toCoord + c;
                        if (CoordInRange(knightAttackRange))
                        {
                            if (analysisBoard[knightAttackRange.x, knightAttackRange.y].piece == GameBoard.Pieces.King && analysisBoard[knightAttackRange.x, knightAttackRange.y].pieceColour != friendlyColour)
                            {
                                move.promotionPiece = GameBoard.Pieces.Knight;
                            }
                        }
                    }
                }
            }
            int pawnMoveDir = (friendlyColour == GameBoard.Colour.White)?1:-1;
            if (deltaMove.x == 0 && Mathf.Sign(deltaMove.y) == pawnMoveDir && analysisBoard[toCoord.x, toCoord.y].piece == GameBoard.Pieces.Empty) // pawn is advancing in correct direction and landing on empty square
            {
                if (Mathf.Abs(deltaMove.y) == 1)                                                                                                   // single step forward
                {
                    return(true);
                }
                else if (Mathf.Abs(deltaMove.y) == 2)                                                              // two steps forward
                {
                    if ((fromCoord.y == 1 && pawnMoveDir == 1) || (fromCoord.y == 6 && pawnMoveDir == -1))         // is on starting square
                    {
                        if (analysisBoard[fromCoord.x, fromCoord.y + pawnMoveDir].piece == GameBoard.Pieces.Empty) // not jumping over any pieces
                        {
                            move.createEnPassant = true;
                            move.enPassantSquare = new Coord(fromCoord.x, fromCoord.y + pawnMoveDir);                            // set en passant square

                            return(true);
                        }
                    }
                }
            }
            if (Mathf.Sign(deltaMove.y) == pawnMoveDir && Mathf.Abs(deltaMove.y) == 1 && Mathf.Abs(deltaMove.x) == 1) // capturing in correct direction
            {
                if (analysisBoard[toCoord.x, toCoord.y].isEnPassantSquare)                                            // capturing ep
                {
                    move.isEnPassantCapture     = true;
                    move.enPassantSquare        = analysisBoard[toCoord.x, toCoord.y].coordinates;
                    move.enPassantCaptureSquare = analysisBoard[fromCoord.x + deltaMove.x, fromCoord.y].coordinates;
                    return(true);
                }
                if (capturePiece != GameBoard.Pieces.Empty)                   // is capturing enemy piece
                {
                    return(true);
                }
            }
            return(false);
        }
        else if (pieceType == GameBoard.Pieces.King)
        {
            if (Mathf.Abs(deltaMove.x) <= 1 && Mathf.Abs(deltaMove.y) <= 1)
            {
                // Castling is henceforth illegal as king has moved
                if (friendlyColour == GameBoard.Colour.White)
                {
                    whiteCanCastleKingside  = false;
                    whiteCanCastleQueenside = false;
                }
                else
                {
                    blackCanCastleKingside  = false;
                    blackCanCastleQueenside = false;
                }
                return(true);
            }

            if (deltaMove.y == 0 && Mathf.Abs(deltaMove.x) == 2)               // castling
            {
                int castleDir = (int)Mathf.Sign(deltaMove.x);

                bool canCastle = false;
                if (castleDir == -1)
                {
                    canCastle = (friendlyColour == GameBoard.Colour.White)?whiteCanCastleQueenside:blackCanCastleQueenside;
                }
                else if (castleDir == 1)
                {
                    canCastle = (friendlyColour == GameBoard.Colour.White)?whiteCanCastleKingside:blackCanCastleKingside;
                }

                if (!canCastle)
                {
                    print(analysisBoard[fromCoord.x, fromCoord.y].pieceColour + "  " + blackCanCastleQueenside);
                    return(false);
                }

                Coord passingSquare = new Coord(fromCoord.x + castleDir, fromCoord.y);
                int   min           = (castleDir == 1)?5:1;
                int   max           = (castleDir == 1)?7:4;
                for (int i = min; i < max; i++)
                {
                    if (analysisBoard[i, toCoord.y].piece != GameBoard.Pieces.Empty)                      // cant castle through occupied squares
                    {
                        return(false);
                    }
                }
                if (!SquareUnderAttack(passingSquare, analysisBoard, friendlyColour))                 //cant castle through check
                {
                    move.isCastling       = true;
                    move.rookStartSquare  = new Coord((castleDir == -1)?0:7, fromCoord.y);
                    move.rookTargetSquare = new Coord(fromCoord.x + castleDir, fromCoord.y);
                    if (friendlyColour == GameBoard.Colour.White)
                    {
                        whiteCanCastleKingside  = false;
                        whiteCanCastleQueenside = false;
                    }
                    else
                    {
                        blackCanCastleKingside  = false;
                        blackCanCastleQueenside = false;
                    }
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
        }


        Coord moveDir    = ClampCoordToDir(deltaMove);
        int   moveLength = Mathf.Max(Mathf.Abs(deltaMove.x), Mathf.Abs(deltaMove.y));

        if ((deltaMove.x == 0 || deltaMove.y == 0) && (pieceType == GameBoard.Pieces.Rook || pieceType == GameBoard.Pieces.Queen))           // horizontal/vertical for Rook or Queen
        {
            for (int i = 1; i < moveLength; i++)
            {
                Coord c = fromCoord + moveDir * i;
                if (analysisBoard[c.x, c.y].piece != GameBoard.Pieces.Empty)                  // moving through a piece
                {
                    return(false);
                }
            }

            if (pieceType == GameBoard.Pieces.Rook)
            {
                if (move.moveFrom.coordinates == new Coord(0, 0))
                {
                    whiteCanCastleQueenside = false;
                }
                if (move.moveFrom.coordinates == new Coord(7, 0))
                {
                    whiteCanCastleKingside = false;
                }
                if (move.moveFrom.coordinates == new Coord(0, 7))
                {
                    blackCanCastleQueenside = false;
                }
                if (move.moveFrom.coordinates == new Coord(7, 7))
                {
                    blackCanCastleKingside = false;
                }
            }
            return(true);
        }


        if (Mathf.Abs(deltaMove.x) == Mathf.Abs(deltaMove.y) && (pieceType == GameBoard.Pieces.Bishop || pieceType == GameBoard.Pieces.Queen))           // diagonal for bishop or Queen

        {
            for (int i = 1; i < moveLength; i++)
            {
                Coord c = fromCoord + moveDir * i;
                if (analysisBoard[c.x, c.y].piece != GameBoard.Pieces.Empty)                  // moving through a piece
                {
                    if (debugMode)
                    {
                        print("Moving diagonally through a piece");
                    }
                    return(false);
                }
            }
            return(true);
        }



        if (debugMode)
        {
            print("Returned false by default");
        }
        return(false);
    }