Example #1
0
        public string AB(int depth, float time)
        {
            List <IMove> moves       = moveOptions(root.state);
            List <float> evaluations = new List <float>();
            var          ai          = new TakAI_V4(root.state.Size, maxDepth: 0);
            var          evaluator   = ai.Evaluator;
            bool         gameOver;
            int          eval;

            Console.WriteLine(moves.Count);
            foreach (IMove m in moves)
            {
                GameState tempState = root.state.DeepCopy();
                ABNode    n         = new ABNode(!root.player, tempState);
                TakEngine.Notation.MoveNotation notated;
                TakEngine.Notation.MoveNotation.TryParse(m.Notate(), out notated);
                var match = notated.MatchLegalMove(moves);
                match.MakeMove(n.state);
                tempState.Ply++;

                evaluator.Evaluate(root.state, out eval, out gameOver);
                if (gameOver)
                {
                    return(m.Notate());
                }
                evaluations.Add(ABSearch((new ABNode(!root.player, tempState)), 0, depth, time));
            }


            //get argMax of list
            int   i   = 0;
            int   arg = 0;
            float max = 0;

            foreach (float f in evaluations)
            {
                if (f > max)
                {
                    max = f;
                    arg = i;
                }
                i++;
            }
            return(moves[arg].Notate());
        }
Example #2
0
        //uses same methodology and code as MCTree varient
        public float evaluate(ABNode node)
        {
            float positionValue = 0;
            int   flatCount = 0;
            int   highestCap = 0;
            int   maxCap = 0, maxCapEnemy = 0;
            int   losingState = 0;

            //Set coefficient values here for ease of parameter tuning
            float flatCo = 1F;
            float capCo  = 5F;
            float lossCo = 1000F;

            //check if position is one move away from an enemy win state
            List <IMove> moves     = moveOptions(node.state);
            var          ai        = new TakAI_V4(root.state.Size, maxDepth: 0);
            var          evaluator = ai.Evaluator;
            bool         gameOver;
            int          eval;

            TakEngine.Notation.MoveNotation notated;
            GameState state = node.state.DeepCopy();

            foreach (var m in moves)
            {
                TakEngine.Notation.MoveNotation.TryParse(m.Notate(), out notated);
                var match = notated.MatchLegalMove(moves);
                match.MakeMove(state);
                state.Ply++;
                evaluator.Evaluate(state, out eval, out gameOver);
                if (gameOver)
                {
                    losingState = 1;
                }
                m.TakeBackMove(state);
            }

            //count the number of flat stones
            for (int i = 0; i < node.state.Size; i++)
            {
                for (int j = 0; j < node.state.Size; j++)
                {
                    if (node.state.Board[i, j].Count > 0)
                    {
                        var piece = node.state.Board[i, j][node.state.Board[i, j].Count - 1];
                        if (Piece.GetStone(piece) == Piece.Stone_Flat)
                        {
                            if ((Piece.GetPlayerID(piece) == 1 && !node.player) || (Piece.GetPlayerID(piece) == 0 && node.player))
                            {
                                flatCount++;
                            }
                            else
                            {
                                //Account for enemy flat stones, making the heuristic a differential rather than a simple count
                                flatCount--;
                            }
                        }

                        //check for highest capstone
                        if (Piece.GetStone(piece) == Piece.Stone_Cap)
                        {
                            if (Piece.GetPlayerID(piece) == 1 && !node.player)
                            {
                                maxCapEnemy = node.state.Board[i, j].Count;
                            }
                            else if (Piece.GetPlayerID(piece) == 0 && node.player)
                            {
                                maxCap = node.state.Board[i, j].Count;
                            }
                        }
                    }
                }
            }

            //check which (if either) player has the highest capstone
            if (maxCap > maxCapEnemy)
            {
                highestCap = 1;
            }
            else if (maxCap < maxCapEnemy)
            {
                highestCap = -1;
            }

            positionValue = flatCount * flatCo + highestCap * capCo + losingState * lossCo;
            return(positionValue);
        }
Example #3
0
 public ABTree(GameState game)
 {
     root = new ABNode(true, game);
 }
Example #4
0
        public float ABSearch(ABNode node, int ply, int depth, float time, float alpha = float.MinValue, float beta = float.MinValue)
        {
            if (ply > depth)
            {
                return(evaluate(node));
            }
            List <IMove> moves       = moveOptions(root.state);
            List <float> evaluations = new List <float>();
            var          ai          = new TakAI_V4(root.state.Size, maxDepth: 0);
            var          evaluator   = ai.Evaluator;
            bool         gameOver;
            int          eval;
            int          i = 0;

            time /= moves.Count;
            while (i < moves.Count)
            {
                IMove  m = moves[i];
                ABNode n = new ABNode(!node.player, node.state);
                TakEngine.Notation.MoveNotation notated;
                TakEngine.Notation.MoveNotation.TryParse(m.Notate(), out notated);
                var match = notated.MatchLegalMove(moves);

                /* match.MakeMove(n.state);
                 * node.state.Ply++;
                 *
                 * evaluator.Evaluate(n.state, out eval, out gameOver);
                 * if (gameOver)
                 * {
                 *   if (node.player)
                 *       return 1000F;
                 *   else
                 *       return -1000F;
                 * }*/
                var task = Task.Run(() =>
                {
                    return(ABSearch(n, ply + 1, depth, (float)(time)));
                });

                bool completedOnTime = task.Wait(TimeSpan.FromMilliseconds(time));

                //float e = ABSearch(n, ply + 1, depth);
                float e = 0;
                if (completedOnTime)
                {
                    e = task.Result;

                    evaluations.Add(e);

                    //alpha-beta pruning
                    if (node.player)    //max
                    {
                        if (e > alpha)
                        {
                            alpha = e;
                        }
                        if (e > beta)
                        {
                            return(e);
                        }
                    }
                    if (!node.player)   //min
                    {
                        if (e < beta)
                        {
                            beta = e;
                        }
                        if (e <= alpha)
                        {
                            return(e);
                        }
                    }
                }
                else
                {
                    evaluations.Add(0);
                }
                i++;
            }

            if (node.player)
            {
                return(evaluations.Max());
            }
            else
            {
                return(evaluations.Min());
            }
        }