Пример #1
0
    /// <summary>
    /// Acts similarly to normal alpha beta search but instead of generating new board nodes, traverses existing board node list.
    /// </summary>
    /// <param name="_node"></param>
    /// <param name="_depth"></param>
    /// <param name="_alpha"></param>
    /// <param name="_beta"></param>
    /// <param name="_searchingPlayer"></param>
    /// <param name="_maximizingPlayer"></param>
    /// <param name="_player"></param>
    /// <param name="_accuracyMod"></param>
    /// <returns></returns>
    static public float TraverseNodeList(BoardNode _node, int _depth, float _alpha, float _beta, int _searchingPlayer, bool _maximizingPlayer, AI _player, float _accuracyMod)
    {
        float v;

        if (_depth == 0 || _node.MoveCount() == 0)
        {
            if (_maximizingPlayer)
            {
                v = (float)_node.GetValue(_player);
                if (_accuracyMod != 0)
                {
                    System.Random random = new MathNet.Numerics.Random.SystemRandomSource();
                    v = v + (float)random.NextDouble() * (2 * _accuracyMod) - _accuracyMod;
                }
                return(v);
            }
            else
            {
                return(AlphaBeta(_node, _depth, _alpha, _beta, _searchingPlayer, _maximizingPlayer, _player, _accuracyMod));
            }
        }

        if (!_node.IsEndNode())
        {
            if (_maximizingPlayer)
            {
                v = -Mathf.Infinity;
                foreach (BoardNode b in _node.GetChildren())
                {
                    v      = Mathf.Max(v, TraverseNodeList(b, _depth - 1, _alpha, _beta, _searchingPlayer, false, _player, _accuracyMod));
                    _alpha = Mathf.Max(_alpha, v);
                    if (_beta <= _alpha)
                    {
                        break;
                    }
                }
                return(v);
            }
            else
            {
                v = 1;
                foreach (BoardNode b in _node.GetChildren())
                {
                    v     = Mathf.Min(v, TraverseNodeList(b, _depth - 1, _alpha, _beta, _searchingPlayer, true, _player, _accuracyMod));
                    _beta = Mathf.Min(_beta, v);
                    if (_beta <= _alpha)
                    {
                        break;
                    }
                }
                return(v);
            }
        }
        else
        {
            return(AlphaBeta(_node, _depth, _alpha, _beta, _searchingPlayer, _maximizingPlayer, _player, _accuracyMod));
        }
    }
Пример #2
0
    public override bool PerformTurn(Board _currentBoard, int _aiPlayer, PlayerType otherPlayer, bool _firstTurn, out StoneMove _move, int presetFirstMove)
    {
        ADRASMoveList.Clear();

        if (boardNodes == null)
        {
            boardNodes = new List <BoardNode>();
        }

        _move = new StoneMove();

        List <StoneMove> possibleMoves = FindAllValidMoves(_currentBoard, _aiPlayer, true);

        System.Random    rnd          = new System.Random();
        List <StoneMove> shuffledList = possibleMoves.OrderBy(item => rnd.Next()).ToList();

        if (shuffledList.Count > 0)
        {
            StoneMove selectedMove      = possibleMoves[0];
            float     selectedMoveValue = -Mathf.Infinity;

            if (_firstTurn)
            {
                FFData temp;
                float  boardVal = GetBoardRating(_currentBoard, _aiPlayer, out temp);
                InitBoardVal[_aiPlayer - 1] = boardVal;
                if (_aiPlayer == 1)
                {
                    if (presetFirstMove >= 0 && presetFirstMove < possibleMoves.Count && !GameManager.DEMO)
                    {
                        _move = possibleMoves[presetFirstMove];
                    }
                    else
                    {
                        _move = shuffledList.First();
                    }
                    return(true);
                }
            }
            else
            {
                bool      existingNodeFound = false;
                BoardNode baseNode          = new BoardNode(_currentBoard, _aiPlayer);

                if (boardNodes.Count > 0)
                {
                    for (int i = 0; i < boardNodes.Count; i++)
                    {
                        if (boardNodes[i].boardState == _currentBoard)
                        {
                            existingNodeFound = true;
                            baseNode          = boardNodes[i];
                            break;
                        }
                    }
                }

                boardNodes = new List <BoardNode>();

                if (existingNodeFound && !baseNode.IsEndNode())
                {
                    boardNodes.AddRange(baseNode.GetChildren());
                }
                else
                {
                    foreach (StoneMove m in shuffledList)
                    {
                        Board testBoard = _currentBoard.Clone();
                        testBoard.ResolveMove(m);
                        BoardNode bn = new BoardNode(testBoard, 3 - _aiPlayer, m);
                        boardNodes.Add(bn);
                    }
                }

                foreach (BoardNode bn in boardNodes)
                {
                    bool prevStateFound = false;
                    foreach (Board b in CheckersMain.prevStates)
                    {
                        if (b == bn.boardState)
                        {
                            prevStateFound = true;
                        }
                    }

                    float moveValue = Mathf.NegativeInfinity;
                    if (!prevStateFound)
                    {
                        moveValue = Search.TraverseNodeList(bn, searchDepth - 1, Mathf.NegativeInfinity, Mathf.Infinity, _aiPlayer, false, this, 0);
                    }

                    if (moveValue >= 1 - accuracyMod)
                    {
                        ADRASMoveList.Add(bn);
                    }

                    if (moveValue > selectedMoveValue)
                    {
                        selectedMove      = bn.GetMoveMade();
                        selectedMoveValue = moveValue;
                    }
                }

                if (otherPlayer == PlayerType.Human)
                {
                    List <BoardNode> newNodeList = new List <BoardNode>(0);
                    foreach (BoardNode bn in boardNodes)
                    {
                        if (!bn.IsEndNode())
                        {
                            newNodeList.AddRange(bn.GetChildren());
                        }
                    }
                    boardNodes = newNodeList;
                }
            }

            if (selectedMoveValue > 1 - accuracyMod)
            {
                selectedMove = ADRASMoveList.OrderBy(item => rnd.Next()).First().GetMoveMade();
            }

            _move = selectedMove;
            return(true);
        }
        else
        {
            FFData data;
            GetBoardRating(_currentBoard, _aiPlayer, out data);
            return(false);
        }
    }
Пример #3
0
    public virtual bool PerformTurn(Board _currentBoard, int _aiPlayer, PlayerType otherPlayer, bool _firstTurn, out StoneMove _move, int _presetFirstMove)
    {
        //initialize board node list if it isn't already
        if (boardNodes == null)
        {
            boardNodes = new List <BoardNode>();
        }

        //Placeholder move in case no valid moves are found
        _move = new StoneMove();

        //Generate list of possible moves for board state
        List <StoneMove> possibleMoves = FindAllValidMoves(_currentBoard, _aiPlayer, true);

        //Shuffle the list
        System.Random    rnd          = new System.Random();
        List <StoneMove> shuffledList = possibleMoves.OrderBy(item => rnd.Next()).ToList();

        if (shuffledList.Count > 0)
        {
            //set selected move to first move in the list & the value to infinity, this will likely be overwritten immediately.
            StoneMove selectedMove      = possibleMoves[0];
            float     selectedMoveValue = -Mathf.Infinity;

            //If its the first turn, run some extra processing
            if (_firstTurn)
            {
                FFData temp;
                //Find the initial board value for the player. This is used for dynamic difficulty AI's
                float boardVal = GetBoardRating(_currentBoard, _aiPlayer, out temp);
                InitBoardVal[_aiPlayer - 1] = boardVal;
                //If player is black, select the preset first move from the list and exit.
                if (_aiPlayer == 1)
                {
                    if (_presetFirstMove >= 0 && _presetFirstMove < possibleMoves.Count && !GameManager.DEMO)
                    {
                        _move = possibleMoves[_presetFirstMove];
                    }
                    else
                    {
                        _move = shuffledList.First();
                    }
                    return(true);
                }
            }
            //Main body
            else
            {
                bool      existingNodeFound = false;
                BoardNode baseNode          = new BoardNode(_currentBoard, _aiPlayer);
                //If we already have a list of board nodes to use the attempt to locate the current board in the list.
                if (boardNodes.Count > 0)
                {
                    for (int i = 0; i < boardNodes.Count; i++)
                    {
                        if (boardNodes[i].boardState == _currentBoard)
                        {
                            existingNodeFound = true;
                            baseNode          = boardNodes[i];
                            break;
                        }
                    }
                }
                //Refresh board node list
                boardNodes = new List <BoardNode>();
                //If we found a node, add the nodes children to the board node list
                if (existingNodeFound && !baseNode.IsEndNode())
                {
                    boardNodes.AddRange(baseNode.GetChildren());
                }
                //otherwise, generate a new node from this board and add that nodes children to the list
                else
                {
                    foreach (StoneMove m in shuffledList)
                    {
                        Board testBoard = _currentBoard.Clone();
                        testBoard.ResolveMove(m);
                        BoardNode bn = new BoardNode(testBoard, 3 - _aiPlayer, m);
                        boardNodes.Add(bn);
                    }
                }

                //Go through the board nodes and begin search
                foreach (BoardNode bn in boardNodes)
                {
                    bool prevStateFound = false;
                    foreach (Board b in CheckersMain.prevStates)
                    {
                        if (b == bn.boardState)
                        {
                            prevStateFound = true;
                        }
                    }

                    float moveValue = Mathf.NegativeInfinity;
                    if (!prevStateFound)
                    {
                        moveValue = Search.TraverseNodeList(bn, searchDepth - 1, Mathf.NegativeInfinity, Mathf.Infinity, _aiPlayer, false, this, 0);
                    }


                    if (moveValue > selectedMoveValue)
                    {
                        selectedMove      = bn.GetMoveMade();
                        selectedMoveValue = moveValue;
                    }
                }
                //If the other player is human. Then the next board state will be skipped, so next board node list has to be 2 ply away.
                if (otherPlayer == PlayerType.Human)
                {
                    List <BoardNode> newNodeList = new List <BoardNode>(0);
                    foreach (BoardNode bn in boardNodes)
                    {
                        if (!bn.IsEndNode())
                        {
                            newNodeList.AddRange(bn.GetChildren());
                        }
                    }
                    boardNodes = newNodeList;
                }
            }

            _move = selectedMove;
            return(true);
        }
        else
        {
            FFData data;
            GetBoardRating(_currentBoard, _aiPlayer, out data);
            return(false);
        }
    }
Пример #4
0
    static public float AlphaBeta(BoardNode _node, int _depth, float _alpha, float _beta, int _searchingPlayer, bool _maximizingPlayer, AI _player, float _accuracyMod)
    {
        float v;

        //If we have reach the end of the search
        if (_depth == 0 || _node.MoveCount() == 0)
        {
            //If we are currently on the maximising player then find the board rating and return
            if (_maximizingPlayer)
            {
                v = (float)_node.GetValue(_player);
                if (_accuracyMod != 0)
                {
                    System.Random random = new MathNet.Numerics.Random.SystemRandomSource();
                    v = v + (float)random.NextDouble() * (2 * _accuracyMod) - _accuracyMod;
                }
                return(v);
            }
            //If we are not currently on the maximising player then jump one extra layer.
            else
            {
                v = 1;

                foreach (StoneMove m in _node.GetMoveList())
                {
                    Board testBoard = _node.boardState.Clone();
                    testBoard.ResolveMove(m);
                    _node.AddChild(new BoardNode(testBoard, _searchingPlayer, m));
                }

                foreach (BoardNode b in _node.GetChildren())
                {
                    v     = Mathf.Min(v, AlphaBeta(b, _depth - 1, _alpha, _beta, _searchingPlayer, true, _player, _accuracyMod));
                    _beta = Mathf.Min(_beta, v);
                    if (_beta <= _alpha)
                    {
                        break;
                    }
                }
                return(v);
            }
        }

        if (_maximizingPlayer)
        {
            v = -Mathf.Infinity;

            foreach (StoneMove m in _node.GetMoveList())
            {
                Board testBoard = _node.boardState.Clone();
                testBoard.ResolveMove(m);
                _node.AddChild(new BoardNode(testBoard, 3 - _searchingPlayer, m));
            }

            foreach (BoardNode b in _node.GetChildren())
            {
                v      = Mathf.Max(v, AlphaBeta(b, _depth - 1, _alpha, _beta, _searchingPlayer, false, _player, _accuracyMod));
                _alpha = Mathf.Max(_alpha, v);
                if (_beta <= _alpha)
                {
                    break;
                }
            }
            return(v);
        }
        else
        {
            v = +Mathf.Infinity;

            foreach (StoneMove m in _node.GetMoveList())
            {
                Board testBoard = _node.boardState.Clone();
                testBoard.ResolveMove(m);
                _node.AddChild(new BoardNode(testBoard, _searchingPlayer, m));
            }

            foreach (BoardNode b in _node.GetChildren())
            {
                v     = Mathf.Min(v, AlphaBeta(b, _depth - 1, _alpha, _beta, _searchingPlayer, true, _player, _accuracyMod));
                _beta = Mathf.Min(_beta, v);
                if (_beta <= _alpha)
                {
                    break;
                }
            }
            return(v);
        }
    }