Beispiel #1
0
    void moveNextMove(bool _moveOneSide = false)
    {
        m_Missed = false;

        m_WhiteTurn = !m_WhiteTurn;
        m_Board.move(m_CurLine.moveList[m_CurMoveIdx++]);

        UpdateInfos();

        if (m_Board.isChecked(m_Board.whiteTurnToMove))
        {
            AudioSource.PlayClipAtPoint(Check_Sound, Vector3.zero, 1.0f);
        }
        else
        {
            AudioSource.PlayClipAtPoint(MovePiece_Sound, Vector3.zero, 1.0f);
        }

        if (checkEndLine())
        {
            return;
        }

        Invoke("moveComputerMove", 1.5f);
    }
Beispiel #2
0
    public void OnNextMove()
    {
        if (curMove >= moveList.Count)
        {
            return;
        }

        board.move(moveList[curMove]);
        UpdateInfos();
        Wnd_Board.UpdateBoard();
        curMove++;
        AudioSource.PlayClipAtPoint(MovePiece_Sound, Vector3.zero, 1.0f);
    }
Beispiel #3
0
    /// <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);
        }
    }
    /// <summary>
    /// Peform the provided move on the visual board and the abstract board, with no legality checks - thus should be performed prior to calling this.
    /// </summary>
    /// <param name="move"></param>
    private void _makeMove(cgSimpleMove move)
    {
        UnityEngine.Debug.Log("White: " + _abstractBoard.whiteTurnToMove);
        movesMade++;
        playSound(moveSound);
        _abstractBoard.move(move);
        _writeLog(move);
        //_abstractBoard.debugReadBoard();
        if (_getPieceOn(_abstractBoard.SquareNames[move.to]) != null && !(move is cgCastlingMove))
        {
            _setDeadPiece(_getPieceOn(_abstractBoard.SquareNames[move.to]));
        }
        cgChessPieceScript piece = _getPieceOn(_abstractBoard.SquareNames[move.from]);

        if (move.queened)
        {
            piece.SetType(_abstractBoard.squares[move.to] > 0 ? cgChessPieceScript.Type.WhiteQueen : cgChessPieceScript.Type.BlackQueen);
        }
        if (move is cgCastlingMove)
        {
            cgChessPieceScript piece2 = _getPieceOn(_abstractBoard.SquareNames[(move as cgCastlingMove).secondFrom]);
            if (piece2)
            {
                piece2.moveToSquare(_getSquare(_abstractBoard.SquareNames[(move as cgCastlingMove).secondTo]));
            }
        }
        else if (move is cgEnPassantMove)
        {
            cgChessPieceScript piece2 = _getPieceOn(_abstractBoard.SquareNames[(move as cgEnPassantMove).attackingSquare]);
            piece2.dead = true;
        }
        piece.moveToSquare(_getSquare(_abstractBoard.SquareNames[move.to]));

        whiteTurnToMove = _abstractBoard.whiteTurnToMove;
        _checkGameOver();
        if (highlightLastMove)
        {
            //Color copyFrom = _getSquare(cgGlobal.SquareNames[move.to]).startColor;
            Color color = _getSquare(_abstractBoard.SquareNames[move.to]).recentMoveColor;

            _getSquare(_abstractBoard.SquareNames[move.to]).highlightTemporarily(color);
        }

        //Debug.Log("making move. " + _abstractBoard.whiteTurnToMove+" moves "+_abstractBoard.moves.Count);
        //UnityEngine.Debug.Log("Time elapsed: " + stopwatch.Elapsed);

        if (Mode == BoardMode.EngineVsEngine)
        {
            MakeEngineMove(_abstractBoard.duplicate(), _abstractBoard.whiteTurnToMove, _engineCallback);
        }
    }
Beispiel #5
0
    /// <summary>
    /// Peform the provided move on the visual board and the abstract board, with no legality checks - thus should be performed prior to calling this.
    /// </summary>
    /// <param name="move"></param>
    private void _makeMove(cgSimpleMove move)
    {
        //Debug.Log("making move:" + cgGlobal.MoveToString(move));

        movesMade++;
        playSound(moveSound);
        _abstractBoard.move(move);
        _writeLog(move);
        //_abstractBoard.debugReadBoard();
        if (_getPieceOn(cgGlobal.SquareNames[move.to]) != null)
        {
            _setDeadPiece(_getPieceOn(cgGlobal.SquareNames[move.to]));
        }
        cgChessPieceScript piece = _getPieceOn(cgGlobal.SquareNames[move.from]);

        piece.moveToSquare(_getSquare(cgGlobal.SquareNames[move.to]));
        if (move.promoted)
        {
            piece.SetType(_abstractBoard.squares[move.to] > 0 ? cgChessPieceScript.Type.WhiteQueen : cgChessPieceScript.Type.BlackQueen);
        }
        if (move is cgCastlingMove)
        {
            cgChessPieceScript piece2 = _getPieceOn(cgGlobal.SquareNames[(move as cgCastlingMove).secondFrom]);
            if (piece2)
            {
                piece2.moveToSquare(_getSquare(cgGlobal.SquareNames[(move as cgCastlingMove).secondTo]));
            }
        }
        else if (move is cgEnPassantMove)
        {
            cgChessPieceScript piece2 = _getPieceOn(cgGlobal.SquareNames[(move as cgEnPassantMove).attackingSquare]);
            piece2.dead = true;
        }

        whiteTurnToMove = _abstractBoard.whiteTurnToMove;
        _checkGameOver();
        if (highlightLastMove)
        {
            //Color copyFrom = _getSquare(cgGlobal.SquareNames[move.to]).startColor;
            Color color = _getSquare(cgGlobal.SquareNames[move.to]).recentMoveColor;

            _getSquare(cgGlobal.SquareNames[move.to]).highlightTemporarily(color);
        }
    }
Beispiel #6
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);
    }
Beispiel #7
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;
            }
        }
    }