Example #1
0
 /// <summary>
 /// 插入一个新的值。
 /// </summary>
 /// <param name="v">待插入的新值。</param>
 public void Insert(Key v)
 {
     this.n++;
     MinMaxNode.GetNodes(v, this.n, out MinMaxNode minNode, out MinMaxNode maxNode);
     this.maxPQ.Insert(maxNode);
     this.minPQ.Insert(minNode);
 }
Example #2
0
 /// <summary>
 /// 插入一个新的值。
 /// </summary>
 /// <param name="v">待插入的新值。</param>
 public void Insert(TKey v)
 {
     _n++;
     MinMaxNode.GetNodes(v, _n, out var minNode, out var maxNode);
     _maxPq.Insert(maxNode);
     _minPq.Insert(minNode);
 }
Example #3
0
    public override void PlayChess()
    {
        if (CheckBoard.Instance.chessStack.Count == 0)
        {
            CheckBoard.Instance.chessDown(new int[2] {
                7, 7
            });
            return;
        }

        float alpha = int.MinValue;
        float beta  = int.MaxValue;

        int[,] g = (int[, ])CheckBoard.Instance.grid.Clone();
        List <MinMaxNode> node = findNextLevel(g, (int)playChess);
        MinMaxNode        res  = new MinMaxNode();

        res.value = float.MinValue;
        foreach (var n in node)
        {
            float t = findMNode(g, 6, n, true, ref alpha, ref beta);
            if (t > res.value)
            {
                res = n;
            }
        }

        CheckBoard.Instance.chessDown(res.pos);
    }
Example #4
0
 /// <summary>
 /// 插入一个新的值。
 /// </summary>
 /// <param name="v">待插入的新值。</param>
 public void Insert(Key v)
 {
     n++;
     MinMaxNode.GetNodes(v, n, out var minNode, out var maxNode);
     maxPQ.Insert(maxNode);
     minPQ.Insert(minNode);
 }
Example #5
0
    MinMaxTree()
    {
        Root = new MinMaxNode <int>(0, 0);
        System.Diagnostics.Stopwatch timer = System.Diagnostics.Stopwatch.StartNew();
        this.AddChildren(Root, new BoardState(), 0);
        timer.Stop();
#if DEBUG
        Debug.LogFormat("MinMaxTree nodes count: {0}. Construction time: {1}. Check tree: {2}", this.GetNodesCountByDepth(), timer.Elapsed.TotalSeconds, this.CheckTree(Root, 9));
#endif
    }
Example #6
0
    public PlayersMove?ApplyRandomMove(ref MinMaxNode <int> node)
    {
        if (node.Children == null || node.Children.Length == 0)
        {
            return(null);
        }

        node = node.RandomChild;
        return(new PlayersMove(node.Data));
    }
    static public MinMaxNode CalculateBestMove(GameManager.CELL_DATA[,] currentTable)
    {
        // Treating the special situations
        MinMaxNode aiFirstMoveNode = new MinMaxNode();

        aiFirstMoveNode.StartMinMaxNode(currentTable);

        MinMaxNode bestMove = aiFirstMoveNode.CalculateInternalBestMove();

        return(bestMove);
    }
Example #8
0
 /// <summary>
 /// 根据已有元素建立一个最大-最小堆。(O(n))
 /// </summary>
 /// <param name="keys">需要建堆的元素。</param>
 public MinMaxPQ(Key[] keys)
 {
     this.n = keys.Length;
     MinMaxNode[] minNodes = new MinMaxNode[keys.Length];
     MinMaxNode[] maxNodes = new MinMaxNode[keys.Length];
     for (int i = 0; i < this.n; i++)
     {
         MinMaxNode.GetNodes(keys[i], i + 1, out minNodes[i], out maxNodes[i]);
     }
     this.minPQ = new MinPQ(minNodes);
     this.maxPQ = new MaxPQ(maxNodes);
 }
Example #9
0
    public bool TryApplyMove(ref MinMaxNode <int> node, PlayersMove move)
    {
        MinMaxNode <int> nextNode = node.Children.FirstOrDefault(n => n.Data == move.Hash);

        if (nextNode != null)
        {
            node = nextNode;
            return(true);
        }

        return(false);
    }
Example #10
0
    public PlayersMove?ApplyBestMove(ref MinMaxNode <int> node, bool maximize)
    {
        if (node.Children == null || node.Children.Length == 0)
        {
            return(null);
        }

        MinMaxNode <int> nextNode = maximize ? node.MaxChild : node.MinChild;

        node = nextNode;
        return(new PlayersMove(nextNode.Data));
    }
Example #11
0
        /// <summary>
        /// 根据已有元素建立一个最大-最小堆。(O(n))
        /// </summary>
        /// <param name="keys">需要建堆的元素。</param>
        public MinMaxPQ(Key[] keys)
        {
            n = keys.Length;
            var minNodes = new MinMaxNode[keys.Length];
            var maxNodes = new MinMaxNode[keys.Length];

            for (var i = 0; i < n; i++)
            {
                MinMaxNode.GetNodes(keys[i], i + 1, out minNodes[i], out maxNodes[i]);
            }
            minPQ = new MinPQ(minNodes);
            maxPQ = new MaxPQ(maxNodes);
        }
Example #12
0
    /// <summary>
    /// 根据已有元素建立一个最大-最小堆。(O(n))
    /// </summary>
    /// <param name="keys">需要建堆的元素。</param>
    public MinMaxPq(TKey[] keys)
    {
        _n = keys.Length;
        var minNodes = new MinMaxNode[keys.Length];
        var maxNodes = new MinMaxNode[keys.Length];

        for (var i = 0; i < _n; i++)
        {
            MinMaxNode.GetNodes(keys[i], i + 1, out minNodes[i], out maxNodes[i]);
        }
        _minPq = new MinPq(minNodes);
        _maxPq = new MaxPq(maxNodes);
    }
Example #13
0
    MinMaxNode CalculateInternalBestMove()
    {
        if (GetTreeChildrenCount() == 0)
        {
            return(this);
        }

        int   ChoosedChild = 0;
        float resultValue  = (MoveType == TYPE.MAX) ? -20.0f : 20.0f;
        int   resultIIndex = 0;

        for (int i = 0; i < GetTreeChildrenCount(); i++)
        {
            MinMaxNode node = (MinMaxNode)GetTreeChild(i);

            if (node.MoveResult == 0.0f)
            {
                node.CalculateInternalBestMove();
            }

            if (MoveType == TYPE.MAX && node.MoveResult > resultValue)
            {
                ChoosedChild = i;
                resultValue  = node.MoveResult;
                resultIIndex = node.IndexI;
            }
            else if (MoveType == TYPE.MIN && node.MoveResult < resultValue)
            {
                ChoosedChild = i;
                resultValue  = node.MoveResult;
                resultIIndex = node.IndexI;
            }
            else if (node.MoveResult == resultValue && node.IndexI > resultIIndex)
            {
                ChoosedChild = i;
                resultValue  = node.MoveResult;
                resultIIndex = node.IndexI;
            }
            else if (node.MoveResult == resultValue && Random.value > 0.5f)
            {
                ChoosedChild = i;
                resultValue  = node.MoveResult;
                resultIIndex = node.IndexI;
            }
        }

        MoveResult = resultValue;
        return((MinMaxNode)GetTreeChild(ChoosedChild));
    }
Example #14
0
    private float findMNode(int[,] grid, int level, MinMaxNode node, bool myself, ref float alpha, ref float beta)
    {
        if (level == 0 || node.value >= int.MaxValue)
        {
            return(findNextLevel(grid, node.chess == 1 ? 2 : 1)[0].value);
        }

        if (myself)
        {
            //遍历所有可能走法
            grid[node.pos[0], node.pos[1]] = node.chess;
            node.children = findNextLevel(grid, node.chess == 1 ? 2 : 1);//下一步对方的走法
            foreach (MinMaxNode child in node.children)
            {
                //grid[child.pos[0], child.pos[1]] = child.chess;
                float newNode = findMNode((int[, ])grid.Clone(), level - 1, child, !myself, ref alpha, ref beta);
                if (newNode > alpha)
                {
                    alpha = newNode;
                }
                if (alpha > beta)
                {
                    return(alpha);
                }
            }
            return(alpha);
        }
        else
        {
            grid[node.pos[0], node.pos[1]] = node.chess;
            node.children = findNextLevel(grid, node.chess == 1 ? 2 : 1);//下一步对方的走法
            foreach (MinMaxNode child in node.children)
            {
                //grid[child.pos[0], child.pos[1]] = child.chess;
                float newNode = findMNode((int[, ])grid.Clone(), level - 1, child, !myself, ref alpha, ref beta);
                if (newNode < beta)
                {
                    beta = newNode;
                }
                if (alpha > beta)
                {
                    return(beta);
                }
            }
            return(beta);
        }
    }
Example #15
0
    public void GetTree(MinMaxNode node, int[,] grid, int depth, bool isSelf)
    {
        //if game is over, no need to go forward
        if (depth == 0 || node.value == float.MaxValue)
        {
            return;
        }

        grid[node.pos[0], node.pos[1]] = node.chessColor;

        node.childNode = GetList(grid, node.chessColor, !isSelf);

        foreach (MinMaxNode item in node.childNode)
        {
            GetTree(item, (int[, ])grid.Clone(), depth - 1, !isSelf);
        }
    }
Example #16
0
    bool CheckTree(MinMaxNode <int> node, int maxChildren)
    {
        if (node.Children == null)
        {
            return(true);
        }

        if (node.Children.Length > maxChildren)
        {
            return(false);
        }

        for (int i = 0; i < node.Children.Length; ++i)
        {
            if (!CheckTree(node.Children[i], maxChildren - 1))
            {
                return(false);
            }
        }

        return(true);
    }
Example #17
0
    public float AlphaBeta(MinMaxNode node, int depth, bool isSelf, float alpha, float beta)
    {
        if (depth == 0 || node.value == float.MaxValue || node.value == float.MinValue)
        {
            return(node.value);
        }
        //if is player, find the max value
        if (isSelf)
        {
            foreach (MinMaxNode child in node.childNode)
            {
                //compare to self and childnodes
                alpha = Mathf.Max(alpha, AlphaBeta(child, depth - 1, !isSelf, alpha, beta));

                //cut alpha branch
                if (alpha >= beta)
                {
                    return(alpha);
                }
            }
            return(alpha);
        }
        //if is enemy, find the min value
        else
        {
            foreach (MinMaxNode child in node.childNode)
            {
                //compare to self and childnodes
                beta = Mathf.Min(beta, AlphaBeta(child, depth - 1, !isSelf, alpha, beta));

                //cut beta branch
                if (alpha >= beta)
                {
                    return(beta);
                }
            }
            return(beta);
        }
    }
Example #18
0
    int AddChildren(MinMaxNode <int> node, BoardState state, int depth)
    {
        MinMaxNode <int>[] children = new MinMaxNode <int> [9 - depth];
        int playerType = depth % 2;
        int childIdx   = -1;

        for (int i = 0; i < 9; ++i)
        {
            if (state[i] == 0)
            {
                PlayersMove      move  = new PlayersMove(i / 3, i % 3);
                MinMaxNode <int> child = new MinMaxNode <int>(move.Hash, 0);

                state.SetTile(i, playerType + 1);
                int winner = state.GetWinner();

                if (winner != -1)
                {
                    child.Score = winner == 1 ? int.MaxValue : (winner == 2 ? int.MinValue : 0);
                }
                else
                {
                    child.Score = this.AddChildren(child, state, depth + 1);
                }

                // Restore board state as it was before this move
                state.SetTile(i, 0);

                // Add child to current node
                children[++childIdx] = child;
                ++this.nodesCountByDepth[depth];
            }
        }

        System.Array.Sort <MinMaxNode <int> >(children);
        node.Children = children;
        return((playerType == 0 ? node.MaxChild : node.MinChild).Score);
    }
Example #19
0
    public override void StartPlay()
    {
        //if AI is black, let it occupy the center
        if (Board.Instance.chessPos.Count == 0)
        {
            Board.Instance.StarterPlay(new int[2] {
                halfBoard, halfBoard
            });
            return;
        }
        MinMaxNode node = null;

        foreach (var item in GetList(Board.Instance.grid, (int)chessColor, true))
        {
            //create tree for each node
            GetTree(item, (int[, ])Board.Instance.grid.Clone(), 3, false);
            //find the alpha, beta value
            float a = float.MinValue;
            float b = float.MaxValue;

            item.value += AlphaBeta(item, 3, false, a, b);

            if (node != null)
            {
                if (node.value < item.value)
                {
                    node = item;
                }
            }
            else
            {
                node = item;
            }
        }
        Board.Instance.StarterPlay(node.pos);
    }
Example #20
0
    List <MinMaxNode> GetList(int[,] grid, int chess, bool isSelf)
    {
        List <MinMaxNode> nodes = new List <MinMaxNode>();
        MinMaxNode        node;

        for (int i = 0; i < boardLength; i++)
        {
            for (int j = 0; j < boardLength; j++)
            {
                int[] pos = new int[2] {
                    i, j
                };
                //if the current position is not empty
                if (grid[pos[0], pos[1]] != 0)
                {
                    continue;
                }

                //initialize a new node and set up information
                node            = new MinMaxNode();
                node.pos        = pos;
                node.chessColor = chess;

                //if the chess belongs to player
                if (isSelf)
                {
                    node.value = GetScore(grid, pos);
                }
                //if the chess belongs to enmey[
                else
                {
                    node.value = -GetScore(grid, pos);
                }
                //one chess have four options to go(right,up,right up, right bottom)
                if (nodes.Count < 4)
                {
                    nodes.Add(node);
                }

                else//if count >=4 , compare node value
                {
                    foreach (MinMaxNode item in nodes)
                    {
                        if (isSelf)//belongs to player, find max value
                        {
                            if (node.value > item.value)
                            {
                                nodes.Remove(item);
                                nodes.Add(node);
                                break;
                            }
                        }
                        else//belongs to enemy, find min value
                        {
                            if (node.value < item.value)
                            {
                                nodes.Remove(item);
                                nodes.Add(node);
                                break;
                            }
                        }
                    }
                }
            }
        }
        return(nodes);
    }
Example #21
0
        internal void     MinMax(decimal min, decimal max) {
            ContentNode n;

            if (stack.Count > 0) {
                InternalNode n1;
                n = (ContentNode)stack.Pop();
                if (isPartial &&
                    n.NodeType != ContentNode.Type.Terminal &&
                    n.NodeType != ContentNode.Type.Any) {
                    // need to reach in and wrap _pRight hand side of element.
                    // and n remains the same.
                    InternalNode inNode = (InternalNode)n;
                    n1 = new MinMaxNode(inNode.RightNode, min, max);
                    n1.ParentNode = n;
                    if (inNode.RightNode != null)
                        inNode.RightNode.ParentNode = n1;
                    inNode.RightNode = n1;
                }
                else {
                    // wrap terminal or any node
                    n1 = new MinMaxNode(n, min, max);
                    n.ParentNode = n1;
                    n = n1;
                }
                stack.Push(n);
            }
            else {
                // wrap whole content
                n = new MinMaxNode(contentNode, min, max);
                contentNode.ParentNode = n;
                contentNode = n;
            }

            abnormalContent = true;
        }
Example #22
0
 /// <summary>
 /// Class constructor
 /// </summary>
 /// <param name="depth">Maximum depth when running the algorithm</param>
 /// <param name="maxProcessingTime">Maximum thread job time</param>
 public MinMaxJob(int depth, float maxProcessingTime)
     : base(maxProcessingTime)
 {
     m_origin = new ChessNode(BoardManager.Singleton.CurrentStatus, depth, null, NodeType.MAX);
     m_processedNodes = 0;
 }
Example #23
0
    void DoMainMaxMove()
    {
        MinMaxNode bestMoveNode = MinMaxNode.CalculateBestMove(Cells);

        DoAiMove(bestMoveNode.GetSelectedColumn());
    }
Example #24
0
 public int CompareTo(MinMaxNode <T> other)
 {
     return(this.Score.CompareTo(other.Score));
 }
Example #25
0
 /// <summary>
 /// Class constructor
 /// </summary>
 /// <param name="depth">Depth from the origin node</param>
 /// <param name="parentNode">Parent node</param>
 /// <param name="nodeType">Node type</param>
 public MinMaxNode(int depth, ChessNode parentNode, NodeType nodeType)
 {
     m_Depth = depth;
     m_parent = parentNode;
     m_NodeType = nodeType;
 }
Example #26
0
 public override void PrepareForGame(TileMark playerType)
 {
     base.PrepareForGame(playerType);
     this.currentNode = MinMaxTree.Instance.Root;
 }
Example #27
0
    /// <summary>
    /// Recursive function of MinMax Algorithm.
    /// 
    /// This version of the algorithm uses Apha-Beta bound optimization.
    /// </summary>
    /// <param name="node">Reference node to start the algorithm</param>
    /// <param name="alpha">Current alpha value</param>
    /// <param name="beta">Current beta value</param>
    /// <param name="nodeType">NodeType: MIN or MAX node</param>
    /// <returns>Optimal value for the Current Node</returns>
    private float MinMax(MinMaxNode node, float alpha, float beta, NodeType nodeType)
    {
        //Debug.Log("recursivo - depth: "+depth+" alpha: "+alpha+" beta: "+beta+" NodeType: "+nodeType);

        m_processedNodes++;

        if (node.IsEndNode())
        {
            //Debug.Log("retorno valor de funcion estatica");
            return node.StaticValueFunction();
        }
        else if (nodeType == NodeType.MAX)
        {
            foreach (MinMaxNode child in node.getChildren())
            {
                float newAlpha = MinMax(child, alpha, beta, NodeType.MIN);
                //Debug.Log("Alpha score: " + newAlpha);
                if (newAlpha > alpha)
                {
                    node.BestChildren.Clear();
                    node.BestChildren.Add(child);
                    alpha = newAlpha;

                    //Debug.LogWarning("New best Alpha score: " + newAlpha);
                }
                else if (newAlpha == alpha)
                {
                    node.BestChildren.Add(child);
                }

                if (beta <= alpha)
                {
                    //Debug.LogWarning("Poda alpha!!");
                    break;
                }
            }
            //Debug.Log("retorno alpha");
            return alpha;
        }
        else
        {
            foreach (MinMaxNode child in node.getChildren())
            {
                float newBeta = MinMax(child, alpha, beta, NodeType.MAX);
                //Debug.Log("Beta score: " + newBeta);
                if (newBeta < beta)
                {
                    node.BestChildren.Clear();
                    node.BestChildren.Add(child);
                    beta = newBeta;

                    //Debug.LogWarning("new Best Beta Score: " + newBeta);
                }
                else if (newBeta == beta)
                {
                    node.BestChildren.Add(child);
                }

                if (beta <= alpha)
                {
                    //Debug.LogWarning("Poda Beta!!!");
                    break;
                }
            }
            //Debug.Log("retorno beta");
            return beta;
        }
    }
Example #28
0
    public void StartMinMaxNode(GameManager.CELL_DATA[,] currentTable, int level = 0,
                                TYPE type = TYPE.MAX, int indexI = 0, int indexJ = 0,
                                GameManager.CELL_MARKING marking = GameManager.CELL_MARKING.PLAYER)
    {
        CurrentLevel = level;
        MoveType     = type;

        // Copying table
        GameTable = new GameManager.CELL_DATA[6, 7];
        for (int i = 0; i < 6; i++)
        {
            for (int j = 0; j < 7; j++)
            {
                GameTable[i, j].Marking = currentTable[i, j].Marking;
            }
        }


        if (CurrentLevel > 0)
        {
            IndexI = indexI;
            IndexJ = indexJ;
            GameTable[IndexI, IndexJ].Marking = marking;

            // Check if there are more children (only if game is not finished)
            GameManager.CELL_MARKING victory = GameManager.Instance.CheckVictory(GameTable);
            if (victory == GameManager.CELL_MARKING.AI)
            {
                MoveResult = 10.0f - (float)CurrentLevel;
                return;
            }
            else if (victory == GameManager.CELL_MARKING.PLAYER)
            {
                MoveResult = -1.0f * (10.0f - (float)CurrentLevel);
                return;
            }
            else if (IsGameTableFull(GameTable))
            {
                return;
            }
        }

        // Checking if it's possible to go down on tree
        int maxTreeLevel = GameManager.Instance.GetMinMaxTreeLevel();

        if (CurrentLevel + 1 <= maxTreeLevel)
        {
            GameManager.CELL_MARKING newMarking = (marking == GameManager.CELL_MARKING.PLAYER) ?
                                                  GameManager.CELL_MARKING.AI : GameManager.CELL_MARKING.PLAYER;

            TYPE newType = (MoveType == TYPE.MAX) ? TYPE.MIN : TYPE.MAX;

            for (int j = 0; j < 7; j++)
            {
                if (GameTable[0, j].Marking != GameManager.CELL_MARKING.NONE)
                {
                    continue;
                }

                int i = 1;
                while (GameTable[i, j].Marking == GameManager.CELL_MARKING.NONE)
                {
                    i++;
                    if (i == 6)
                    {
                        break;
                    }
                }

                i--;

                // Creating new min max move
                MinMaxNode node = new MinMaxNode();

                AddTreeChild(node);

                node.StartMinMaxNode(GameTable, CurrentLevel + 1, newType, i, j, newMarking);
            }
        }
    }
Example #29
0
    private List <MinMaxNode> findNextLevel(int[,] grid, int chess)
    {
        List <MinMaxNode> poslist = new List <MinMaxNode>();

        for (int i = 0; i < 15; i++)
        {
            for (int j = 0; j < 15; j++)
            {
                if (grid[i, j] != 0)
                {
                    continue;
                }

                float      p = checkScore(grid, new int[] { i, j });
                MinMaxNode n = new MinMaxNode();
                n.pos = new int[2] {
                    i, j
                };
                n.chess = chess;

                if (chess == (int)playChess)
                {
                    n.value = p;
                    if (poslist.Count < depth)
                    {
                        poslist.Add(n);
                    }
                    else
                    {
                        for (int m = 0; m < depth; m++)
                        {
                            if (p > poslist[m].value)
                            {
                                poslist.Insert(m, n);
                                poslist.RemoveAt(depth);
                                break;
                            }
                        }
                    }
                }
                else
                {
                    n.value = -p;
                    if (poslist.Count < depth)
                    {
                        poslist.Add(n);
                    }
                    else
                    {
                        for (int m = 0; m < depth; m++)
                        {
                            if (n.value < poslist[m].value)
                            {
                                poslist.Insert(m, n);
                                poslist.RemoveAt(depth);
                                break;
                            }
                        }
                    }
                }
            }
        }
        return(poslist);
    }