public Square(Coord coords, GameBoard.Pieces pieceP, GameBoard.Colour pieceColourP)
 {
     coordinates       = coords;
     piece             = pieceP;
     pieceColour       = pieceColourP;
     underAttack       = false;
     isEnPassantSquare = false;
     //destroyEP = false;
 }
Exemple #2
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);
    }
Exemple #3
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);
    }
    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);
        }
    }
Exemple #5
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);
    }