Exemplo n.º 1
0
    /// <summary>
    /// The user has released a dragged piece. Verify that its a legal move, if so perform the move and perform the next move if appropriate mode.
    /// </summary>
    /// <param name="piece"></param>
    private void _pieceUp(cgChessPieceScript piece)
    {
        if (_downPiece != null)
        {
            if (playerCanMove || Mode == BoardMode.PlayerVsPlayer)
            {
                cgSimpleMove        legalMove     = null;
                cgSquareScript      closestSquare = _findSquareAt(_downPiece.transform.position);
                List <cgSimpleMove> legalMoves    = _abstractBoard.findLegalMoves(whiteTurnToMove);
                foreach (cgSimpleMove move in legalMoves)
                {
                    if (cgGlobal.SquareNames[move.from] == _downPiece.square.uniqueName && cgGlobal.SquareNames[move.to] == closestSquare.uniqueName)
                    {
                        legalMove = move;
                    }
                }
                //test legality of move here.

                if (legalMove != null && _abstractBoard.verifyLegality(legalMove))
                {
                    //piece.moveToSquare(closestSquare);
                    _makeMove(legalMove);
                    if (Mode == BoardMode.PlayerVsEngine)
                    {
                        _engine.MakeMove(_abstractBoard, false, _engineCallback);
                    }
                    else if (Mode == BoardMode.EngineVsPlayer)
                    {
                        _engine.MakeMove(_abstractBoard, true, _engineCallback);
                    }
                }
                else
                {
                    piece.moveToSquare(piece.square);
                }
            }
            else
            {
                piece.moveToSquare(piece.square);
            }
            _downPiece = null;
        }
        else
        {
            piece.moveToSquare(piece.square);
            _downPiece = null;
        }
        if (highlightLastMove)
        {//revert colors if highlighting is active
            foreach (cgSquareScript square in _squares)
            {
                square.changeColor(square.startColor);
            }
        }
    }
    /// <summary>
    /// Utilizing an AlphaBeta searching algorithm, we generate moves evaluate them, prune and decide which is best.
    /// https://en.wikipedia.org/wiki/Alpha%E2%80%93beta_pruning
    /// </summary>
    /// <param name="node">the move to analyze</param>
    /// <param name="depth">The max depth to search to, execution time increases exponentially the higher the depth</param>
    /// <param name="alpha"></param>
    /// <param name="beta"></param>
    /// <param name="maximizing"></param>
    /// <returns>The value of the provided node</returns>


    private int _alfaBeta(cgSimpleMove node, int depth, int alpha = int.MinValue, int beta = int.MaxValue, bool maximizing = true)
    {
        _board.move(node);

        if (depth == 0)
        {
            int val = _board.Evaluate();
            _board.revert();
            return(val);
        }

        if (maximizing)
        {
            int v = int.MinValue;
            List <cgSimpleMove> replies = _board.findLegalMoves(true);
            foreach (cgSimpleMove reply in replies)
            {
                int candidate = _alfaBeta(reply, depth - 1, alpha, beta, false);
                v = candidate > v ? candidate : v;

                alpha = alpha > v ? alpha : v;
                if (beta < alpha)
                {
                    break;
                }
            }
            _board.revert();
            return(v);
        }
        else
        {
            int v = int.MaxValue;
            List <cgSimpleMove> replies = _board.findLegalMoves(false);
            foreach (cgSimpleMove reply in replies)
            {
                int candidate = _alfaBeta(reply, depth - 1, alpha, beta, true);
                v = candidate < v ? candidate : v;
                if (beta > v)
                {
                    beta = v;
                    //node.bestResponse = reply;
                }
                if (beta < alpha)
                {
                    break;
                }
            }
            _board.revert();
            return(v);
        }
    }
Exemplo n.º 3
0
    /// <summary>
    /// Writes the full game notation from the current moves stored in Moves list.
    /// </summary>
    /// <param name="type">What notationtype should it be?</param>
    /// <param name="formatType">Should it be PGN format or not?</param>
    /// <returns>A string with full game notation.</returns>
    public string writeFullNotation(NotationType type, FormatType formatType = FormatType.None)
    {
        string  str = "";
        cgBoard disambiguationBoard = board.duplicate().revertToStart();

        if (type == NotationType.Coordinate)
        {
            foreach (cgSimpleMove pcem in moves)
            {
                str += (disambiguationBoard.SquareNames[pcem.from] + "-" + disambiguationBoard.SquareNames[pcem.to]) + " ";
            }
        }
        if (formatType == FormatType.PGN)
        {
            string q = "\"";
            str  = " [Event " + q + "Pro Chess" + q + "]\n";
            str += " [Site " + q + "Undefined site" + q + "]\n";
            str += " [Date " + q + DateTime.Now + q + "]\n";
            str += " [White " + q + "Chessplayer1" + q + "]\n";
            str += " [Black " + q + "Chessplayer2" + q + "]\n";
            str += " [Result " + q + "1/2-1/2" + q + "]\n";
        }
        if (type == NotationType.Algebraic)
        {
            foreach (cgSimpleMove pcem in moves)
            {
                if (disambiguationBoard.moves.Count % 2 == 0)
                {
                    str += (Math.Floor(disambiguationBoard.moves.Count / 2f) + 1).ToString() + ". ";
                }

                int typ = Math.Abs(disambiguationBoard.squares[pcem.from]);
                List <cgSimpleMove> othermoves     = disambiguationBoard.findLegalMoves(disambiguationBoard.whiteTurnToMove);
                List <cgSimpleMove> ambiguousMoves = new List <cgSimpleMove>();
                foreach (cgSimpleMove othermove in othermoves)
                {
                    if (othermove.to == pcem.to && othermove.from != pcem.from && Math.Abs(disambiguationBoard.squares[othermove.from]) == typ)
                    {
                        ambiguousMoves.Add(othermove);
                    }
                }
                if (typ == 1 && pcem.capturedType != 0)
                {
                    str += disambiguationBoard.SquareNames[pcem.from].Substring(0, 1);
                }
                if (typ == 2)
                {
                    str += "R";
                }
                if (typ == 3)
                {
                    str += "N";
                }
                if (typ == 4)
                {
                    str += "B";
                }
                if (typ == 5)
                {
                    str += "Q";
                }
                if (typ == 6 && !(pcem is cgCastlingMove))
                {
                    str += "K";
                }
                //if (typ == 6) str += "K";

                if (ambiguousMoves.Count > 0 && typ != 1)
                {
                    bool fileMatch = false;
                    bool rankMatch = false;
                    foreach (cgSimpleMove ambiguousMove in ambiguousMoves)
                    {
                        if (disambiguationBoard.SquareNames[ambiguousMove.from].Substring(0, 1) == disambiguationBoard.SquareNames[pcem.from].Substring(0, 1))
                        {
                            fileMatch = true;
                        }
                        if (disambiguationBoard.SquareNames[ambiguousMove.from].Substring(1, 1) == disambiguationBoard.SquareNames[pcem.from].Substring(1, 1))
                        {
                            rankMatch = true;
                        }
                    }
                    if (!fileMatch)
                    {
                        str += disambiguationBoard.SquareNames[pcem.from].Substring(0, 1);
                    }
                    else if (fileMatch && !rankMatch)
                    {
                        str += disambiguationBoard.SquareNames[pcem.from].Substring(1, 1);
                    }
                    else if (fileMatch && rankMatch)
                    {
                        str += disambiguationBoard.SquareNames[pcem.from];
                    }
                }
                if (pcem.capturedType != 0)
                {
                    str += "x";
                }
                if (pcem is cgCastlingMove)
                {
                    if (pcem.to == 2 || pcem.to == 58)
                    {
                        str += "O-O-O";
                    }
                    else
                    {
                        str += "O-O";
                    }
                }
                else
                {
                    str += disambiguationBoard.SquareNames[pcem.to];
                }
                if (pcem.queened)
                {
                    str += "=Q";
                }
                str += " ";
                disambiguationBoard.move(pcem);
            }
        }

        return(str);
    }
Exemplo n.º 4
0
    /// <summary>
    /// Read the notations in the provided string.
    /// </summary>
    /// <param name="curgame">the string to decipher.</param>
    public void Read(string curgame)
    {
        int          lastIndex = 0;
        int          nextIndex = 0;
        string       move      = curgame.Substring(lastIndex, nextIndex);
        NotationType ntype     = NotationType.Algebraic; //= NotationType.Coordinate;

        //Debug.Log("first move:" + move);
        //if (move.Contains("-")) ntype = NotationType.Coordinate;
        moves = new List <cgSimpleMove>();
        if (ntype == NotationType.Coordinate)
        {
            while (lastIndex != -1)
            {
                byte fromp = board.IndexFromCellName(move.Substring(0, 2));
                byte top   = board.IndexFromCellName(move.Substring(3, 2));
                moves.Add(new cgSimpleMove(fromp, top));
                nextIndex = curgame.IndexOf(" ", lastIndex + 1);
                if (nextIndex == -1)
                {
                    break;
                }
                move      = curgame.Substring(lastIndex + 1, nextIndex - lastIndex);
                lastIndex = nextIndex;
                //Debug.Log("current move being analyzed="+move);
            }
        }
        else if (ntype == NotationType.Algebraic)
        {
            cgBoard      disambBoard = new cgBoard();
            cgSimpleMove chosenMove;
            while (lastIndex != -1)
            {
                chosenMove = null;

                nextIndex = curgame.IndexOf(" ", nextIndex + 1);
                if (nextIndex == -1 || lastIndex == -1)
                {
                    break;
                }
                move = curgame.Substring(lastIndex + 1, nextIndex - lastIndex);
                bool legitMove = (!move.Contains(".") && move.Length > 1 && !move.Contains("\n")) ? true : false;

                move = move.Trim(' ');
                //move = move.Trim('\n');
                //Debug.Log("trimmed:" + move+" contains .:"+move.Contains(".")+" contains newline:"+move.Contains("\n")+" legit move:"+legitMove);
                if (move.Contains("{"))
                {
                    nextIndex = curgame.IndexOf("}", lastIndex + 1);
                }
                else if (move.Contains("["))
                {
                    nextIndex = curgame.IndexOf("]", lastIndex + 1);
                }
                else if (legitMove)
                {
                    //Debug.Log("found to be legit move.");
                    byte tosquare;
                    byte pushback = 2;
                    byte type     = 1;
                    //bool promotion = false;
                    bool shortCastling = (move == "O-O");
                    bool longCastling  = (move == "O-O-O");
                    if (move.Contains("="))
                    {
                        //promotion = true;
                        move.Remove(move.IndexOf("="), 2);
                    }
                    else if (move.Contains("+"))
                    {
                        move.Remove(move.IndexOf("+"), 1);
                    }
                    else if (move.Contains("!"))
                    {
                        move.Remove(move.IndexOf("!"), 1);
                    }
                    else if (move.Contains("?"))
                    {
                        move.Remove(move.IndexOf("?"), 1);
                    }
                    tosquare = board.IndexFromCellName(move.Substring(move.Length - pushback, 2));
                    if (move[0] == 'R')
                    {
                        type = 2;
                    }
                    if (move[0] == 'N')
                    {
                        type = 3;
                    }
                    if (move[0] == 'B')
                    {
                        type = 4;
                    }
                    if (move[0] == 'Q')
                    {
                        type = 5;
                    }
                    if (move[0] == 'K')
                    {
                        type = 6;
                    }

                    List <cgSimpleMove> ambiguousMoves = new List <cgSimpleMove>();
                    foreach (cgSimpleMove legalMove in disambBoard.findLegalMoves(disambBoard.whiteTurnToMove))
                    {
                        if (shortCastling && legalMove is cgCastlingMove)
                        {
                            if (legalMove.to == 6 || legalMove.to == 62)
                            {
                                chosenMove = legalMove;
                                break;
                            }
                        }
                        else if (longCastling && legalMove is cgCastlingMove)
                        {
                            if (legalMove.to == 2 || legalMove.to == 58)
                            {
                                chosenMove = legalMove;
                                break;
                            }
                        }
                        if (Math.Abs(disambBoard.squares[legalMove.from]) == type && legalMove.to == tosquare)
                        {
                            ambiguousMoves.Add(legalMove);
                        }
                    }
                    if (ambiguousMoves.Count == 0 && chosenMove == null)
                    {
                        //Debug.WriteLine("found no matching move for the string: " + move+" type:"+type+" tosquare:"+tosquare+" chosenMove:"+chosenMove+" castling:"+shortCastling);
                        break;
                    }
                    else if (ambiguousMoves.Count == 1)
                    {
                        chosenMove = ambiguousMoves[0];
                    }
                    else if (ambiguousMoves.Count > 1)
                    {
                        //UnityEngine.Debug.Log("2 or mroe ambiguousmoves");
                        //2 or more ambiguous moves in which the piece type matches and the destination square matches. Further disambiguation needed.
                        List <cgSimpleMove> matching = new List <cgSimpleMove>();
                        foreach (cgSimpleMove mov in ambiguousMoves)
                        {
                            if (board.SquareNames[mov.from].Contains(move.Substring(1 + (type == 1?-1:0), 1)))
                            {
                                matching.Add(mov);
                            }
                        }

                        if (matching.Count == 1)
                        {
                            chosenMove = matching[0];                     //only 1 of the ambiguous moves have the correct rank and/or file.
                        }
                        else
                        {
                            foreach (cgSimpleMove mov in ambiguousMoves)
                            {
                                if (board.SquareNames[mov.from].Contains(move.Substring(1, 2)))
                                {
                                    chosenMove = ambiguousMoves[0];
                                    break;
                                }
                            }
                        }
                    }
                    if (chosenMove != null)
                    {
                        disambBoard.move(chosenMove);
                        moves.Add(chosenMove);
                    }
                }
                Debug.WriteLine("legitmove:" + legitMove);
                lastIndex = nextIndex;
            }
        }
    }
Exemplo n.º 5
0
    public static string NotationFromMove(cgBoard _board, cgSimpleMove _move)
    {
        string str = "";

        if (_board.moves.Count % 2 == 0)
        {
            str += (Math.Floor(_board.moves.Count / 2f) + 1).ToString() + ". ";
        }

        int typ = Mathf.Abs(_board.squares[_move.from]);
        List <cgSimpleMove> othermoves     = _board.findLegalMoves(_board.whiteTurnToMove);
        List <cgSimpleMove> ambiguousMoves = new List <cgSimpleMove>();

        foreach (cgSimpleMove othermove in othermoves)
        {
            if (othermove.to == _move.to && othermove.from != _move.from && Mathf.Abs(_board.squares[othermove.from]) == typ)
            {
                ambiguousMoves.Add(othermove);
            }
        }
        if (typ == 1 && _move.capturedType != 0)
        {
            str += cgGlobal.SquareNames[_move.from].Substring(0, 1);
        }
        if (typ == 2)
        {
            str += "R";
        }
        if (typ == 3)
        {
            str += "N";
        }
        if (typ == 4)
        {
            str += "B";
        }
        if (typ == 5)
        {
            str += "Q";
        }
        if (typ == 6 && !(_move is cgCastlingMove))
        {
            str += "K";
        }
        //if (typ == 6) str += "K";

        if (ambiguousMoves.Count > 0 && typ != 1)
        {
            bool fileMatch = false;
            bool rankMatch = false;
            foreach (cgSimpleMove ambiguousMove in ambiguousMoves)
            {
                if (cgGlobal.SquareNames[ambiguousMove.from].Substring(0, 1) == cgGlobal.SquareNames[_move.from].Substring(0, 1))
                {
                    fileMatch = true;
                }
                if (cgGlobal.SquareNames[ambiguousMove.from].Substring(1, 1) == cgGlobal.SquareNames[_move.from].Substring(1, 1))
                {
                    rankMatch = true;
                }
            }
            if (!fileMatch)
            {
                str += cgGlobal.SquareNames[_move.from].Substring(0, 1);
            }
            else if (fileMatch && !rankMatch)
            {
                str += cgGlobal.SquareNames[_move.from].Substring(1, 1);
            }
            else if (fileMatch && rankMatch)
            {
                str += cgGlobal.SquareNames[_move.from];
            }
        }
        if (_move.capturedType != 0)
        {
            str += "x";
        }
        if (_move is cgCastlingMove)
        {
            if (_move.to == 2 || _move.to == 58)
            {
                str += "O-O-O";
            }
            else
            {
                str += "O-O";
            }
        }
        else
        {
            str += cgGlobal.SquareNames[_move.to];
        }
        if (_move.promoted)
        {
            switch (_move.promotionType)
            {
            case 2:
                str += "=R";
                break;

            case 3:
                str += "=N";
                break;

            case 4:
                str += "=B";
                break;

            case 5:
                str += "=Q";
                break;

            default:
                break;
            }
        }

        return(str);
    }