Example #1
0
 //node constructors
 public Node(Node p, Move m, int a, int b)
 {
     //create a new board with the move provided
     CBoard = Move.CopyAndMove(p.CBoard, m);
     Alpha = a;
     Beta = b;
 }
Example #2
0
 //construct node from just a board state
 public Node(Piece[,] b)
 {
     Parent = null;
     CBoard = b;
     Alpha = int.MinValue;
     Beta = int.MaxValue;
 }
Example #3
0
 static bool Terminal(Node p, bool turn)
 {
     return (Move.GenerateAllMoves(p.CBoard, turn).Count == 0);
 }
Example #4
0
 public bool Equals(Node other)
 {
     if (ReferenceEquals(null, other)) return false;
     if (ReferenceEquals(this, other)) return true;
     return Game1.Check(this.CBoard, other.CBoard);
 }
Example #5
0
        public static Piece[,] AlphaBetaSearch(Piece[,] cboard)
        {
            Console.WriteLine("Starting");
            int depth = 0;
            int v = int.MinValue;
            counter c;
            c.nodes = 1;
            c.minprune = 0;
            c.maxprune = 0;
            var startTime = DateTime.Now;

            Node p = new Node(cboard);
            List<Move> moves = Move.GenerateAllMoves(p.CBoard, false);
            if (moves.Count() > 0)
                if (moves[0].Jump)
                {
                    var pairs = new List<Tuple<Piece[,], int>>();
                    foreach (Piece[,] b in GenerateJumps(moves, p.CBoard, false))
                    {
                        Node tNode = new Node(b);
                        tNode.Alpha = p.Alpha;
                        tNode.Beta = p.Beta;
                        tNode.Parent = p;
                        v = Math.Max(v, MinValue(ref tNode, ref c, depth));
                        if (v >= p.Beta)
                        {
                            Console.WriteLine("Time Elapsed: " + (DateTime.Now - startTime));
                            return b;
                        }
                        p.Alpha = Math.Max(p.Alpha, v);
                        pairs.Add(new Tuple<Piece[,], int>(b, v));
                    }
                    foreach (var d in pairs)
                    {
                        if (d.Item2 == v)
                        {
                            Console.WriteLine("Time Elapsed: " + (DateTime.Now - startTime));
                            return d.Item1;
                        }
                    }
                }
                else
                {
                    var pairs = new List<Tuple<Move, int>>();
                    foreach (Move m in moves)
                    {
                        Node tNode = new Node(p, m, p.Alpha, p.Beta);
                        v = Math.Max(v,MinValue(ref tNode, ref c, depth));
                        if (v >= p.Beta)
                        {
                            Console.WriteLine("Time Elapsed: " + (DateTime.Now - startTime));
                            return Move.CopyAndMove(cboard, m);
                        }
                        p.Alpha = Math.Max(p.Alpha, v);
                        pairs.Add(new Tuple<Move, int>(m, v));
                    }
                    foreach (var d in pairs)
                    {
                        if (d.Item2 == v)
                        {
                            Console.WriteLine("Time Elapsed: "+ (DateTime.Now - startTime));
                            return Move.CopyAndMove(cboard, d.Item1);
                        }
                    }
                }
            return Move.CopyAndMove(cboard,new Move(new Vector2(1), new Vector2(1)) );
        }
Example #6
0
        static int MinValue(ref Node p, ref counter c, int depth)
        {
            c.nodes++;
            depth++;
            if (c.nodes % 10000 == 0) Console.WriteLine("Nodes: " + c.nodes + "\n" + "Min Prune: " + c.minprune + "\n" + "Max Prune: " + c.maxprune);
            //if(count%10== 0) Console.WriteLine(count);
            if (Terminal(p, true))
            {
                return 20;
            }
            if (depth == MAX_DEPTH)
            {
                return Node.UtilityFunc(p.CBoard);
            }
            int v = int.MaxValue;
            List<Move> moves = Move.GenerateAllMoves(p.CBoard, true);
            if (moves.Count() > 0) if (moves[0].Jump)
                {
                    foreach (Piece[,] b in GenerateJumps(moves, p.CBoard, false))
                    {
                        Node tNode = new Node(b);
                        tNode.Alpha = p.Alpha;
                        tNode.Beta = p.Beta;
                        tNode.Parent = p;
                        v = Math.Min(v, MaxValue(ref tNode, ref c, depth));
                        if (v <= p.Alpha)
                        {
                            c.minprune++;
                            return v;
                        }
                        p.Beta = Math.Min(p.Beta, v);

                    }
                }
                else
            {
                foreach (Move m in moves)
                {
                    Node tNode = new Node(p, m, p.Alpha, p.Beta);
                    v = Math.Min(v, MaxValue(ref tNode, ref c, depth));
                    if (v <= p.Alpha)
                    {
                        c.minprune++;
                        return v;
                    }
                    p.Beta = Math.Min(p.Beta, v);
                }
            }
            return v;
        }
Example #7
0
        //the main alpha-beta search function
        //takes in a board state, the current turn, and the maximum depth that the function should go to
        //returns a board state
        public static Piece[,] AlphaBetaSearch(Piece[,] cboard, int turn, int maxDepth)
        {
            //write some info to the console
            Console.WriteLine("Starting Alpha-Beta Search");
            Console.WriteLine("Turn: " + turn);

            //depth counter
            int depth = 0;

            //value of best node
            Value v;

            //counter class holding statistics
            Counter c;

            //set values
            c.Nodes = 1;
            c.Minprune = 0;
            c.Maxprune = 0;
            c.Maxdepth = 0;

            //start counting time
            var startTime = DateTime.Now;

            //if the difficulty is set to very hard, increase depth as the
            //number of turns increases
            if(maxDepth == 18)
            {
                switch (turn)
                {

                    case 0:
                        _currentdepth = maxDepth;
                        break;
                    case 1:
                        _currentdepth = maxDepth;
                        break;
                    case 2:
                        _currentdepth = maxDepth + 2;
                        break;
                    case 3:
                        _currentdepth = maxDepth + 3;
                        break;
                    case 4:
                        _currentdepth = maxDepth + 5;
                        break;
                    case 5:
                        _currentdepth = maxDepth + 7;
                        break;
                    default:
                        _currentdepth = maxDepth + 100;
                        break;
                }
            }
            else _currentdepth = maxDepth;

            //create root node
            Node p = new Node(cboard);

            //start the search
            v = MaxValue(ref p, ref c, depth);

            //go up the chain of parents until reaching the proper move to choose
            p = v.Nod;
            while(p.Parent.Parent != null)
            {
                p = p.Parent;
            }

            //write out the statistics
            Console.WriteLine( "Nodes: " + c.Nodes + "\n" + "Min Prune: " + c.Minprune + "\n" + "Max Prune: " + c.Maxprune + "\n" + "Maximum Depth: " + c.Maxdepth);
            Console.WriteLine("Time Elapsed: " + (DateTime.Now - startTime) + "\n");

            return p.CBoard;
        }
Example #8
0
        //essentially the same as MaxValue, but with
        //alpha and beta flipped around
        static Value MinValue(ref Node p, ref Counter c, int depth)
        {
            c.Nodes++;

            if (depth == _currentdepth)
            {
                return new Value { Nod = p, Val = Node.UtilityFunc(p.CBoard, true) };
            }

            List<Move> moves = Move.GenerateAllMoves(p.CBoard, true);
            if (!moves.Any())
            {
                return new Value { Nod = p, Val = 40 };
            }

            Value v = new Value { Nod = p, Val = int.MaxValue };

            depth++;
            if (depth > c.Maxdepth) c.Maxdepth = depth;

            if (moves.Count() > 0)
            {
                List<Piece[,]> boards;
                if (moves[0].Jump) boards = Move.GenerateJumps(moves, p.CBoard, true);
                else boards = GenerateBoards(moves, p.CBoard);
                foreach(var b in boards)
                {
                    Node tNode = new Node(b);
                    tNode.Alpha = p.Alpha;
                    tNode.Beta = p.Beta;
                    tNode.Parent = p;
                    v = Min(v, MaxValue(ref tNode, ref c, depth));
                    if (v.Val <= p.Alpha)
                    {
                        c.Minprune++;
                        return v;
                    }
                    p.Beta = Math.Min(p.Beta, v.Val);
                }

            }
            return v;
        }
Example #9
0
        //max value function, part of the alpha-beta search
        static Value MaxValue(ref Node p, ref Counter c, int depth)
        {
            //increase node counter
            c.Nodes++;

            //if the depth is the maximum allowed,
            if (depth == _currentdepth)
            {
                return new Value{Nod = p, Val = Node.UtilityFunc(p.CBoard, false)};
            }

            //generate all possible moves
            List<Move> moves = Move.GenerateAllMoves(p.CBoard, false);

            //if there anre't any moves, this is a terminating state
            if (!moves.Any())
            {
                return new Value { Nod = p, Val = -40 };
            }

            //create new value holder
            Value v = new Value { Nod = p, Val = int.MinValue };

            //increase depth
            depth++;

            //if the depth is greater than the one currently in the counter
            //replace it
            if (depth > c.Maxdepth) c.Maxdepth = depth;

            //if moves exist
            if (moves.Count() > 0)
            {
                List<Piece[,]> boards;

                //if the first child is a jump, generate all jump outcomes
                if (moves[0].Jump) boards = Move.GenerateJumps(moves, p.CBoard, false);
                //otherwise generate regular board moves
                else boards = GenerateBoards(moves, p.CBoard);

                //for each child
                foreach (var b in boards)
                {
                    //create a new node and set values
                    Node tNode = new Node(b);
                    tNode.Alpha = p.Alpha;
                    tNode.Beta = p.Beta;
                    tNode.Parent = p;

                    //run minvalue on the new node
                    v = Max(v, MinValue(ref tNode, ref c, depth));

                    //handle pruning
                    if (v.Val >= p.Beta)
                    {
                        c.Maxprune++;
                        return v;
                    }
                    p.Alpha = Math.Max(p.Alpha, v.Val);
                }

            }
            return v;
        }