static void ExpandNode(this IBoard <IHex> board, StepCost directedStepCost,
                               BoardStorage <int> costs, Queue queue, IHex here, int key, Hexside hexside
                               )
        {
            var neighbourCoords = here.Coords.GetNeighbour(hexside);

            board[neighbourCoords].IfHasValueDo(neighbour => {
                var cost = directedStepCost(here, hexside);
                if (cost > 0 && costs[neighbourCoords] < 0)
                {
                    Trace($"   Enqueue {neighbourCoords}: {cost,4}");

                    queue.Enqueue(key + cost, neighbour);
                }
            });
            //if (neighbourHex != null) {
            //    var cost = directedStepCost(here, hexside);
            //    if (cost > 0  &&  costs[neighbourCoords] < 0) {

            //        Trace($"   Enqueue {neighbourCoords}: {cost,4}");

            //        queue.Enqueue(key + cost,neighbourHex);
            //    }
            //}
        }
 // returns a Path if there is one or null if not
 // default to allow diagonal steps
 public static Path BFSPath(int xStart, int yStart, int xEnd, int yEnd,
    CanStep stepFrom, CanStep stepTo, StepCost costFrom, DirectedStepCost costTo,
    MapRectangle limits)
 {
     return BFSPath(xStart, yStart, xEnd, yEnd, stepFrom, stepTo,
        costFrom, costTo, limits, true);
 }
        static IBoardStorage <int> PopulateLandmark(this IBoard <IHex> board,
                                                    StepCost directedStepCost, Func <Queue> queueGenerator, IHex landmark
                                                    )
        {
            TraceNewLine($"Find distances from {landmark.Coords}");

            var costs = new BlockedBoardStorage32x32 <int>(board.MapSizeHexes, c => - 1);
            var queue = queueGenerator();

            queue.Enqueue(0, landmark);

            while (queue.TryDequeue(out var item))
            {
                var here = item.Value;
                var key  = item.Key;
                if (costs[here.Coords] > 0)
                {
                    continue;
                }

                Trace($"Dequeue Path at {here} w/ cost={key,4}.");

                costs.SetItem(here.Coords, key);

                void SetHexside(Hexside hexside)
                => board.ExpandNode(directedStepCost, costs, queue, here, key, hexside);

                Hexside.ForEach(SetHexside);
            }

            return(costs);
        }
 // returns a Path if there is one or null if not
 // default to allow diagonal steps
 public static Path BFSPath(int xStart, int yStart, int xEnd, int yEnd,
                            CanStep stepFrom, CanStep stepTo, StepCost costFrom, DirectedStepCost costTo,
                            MapRectangle limits)
 {
     return(BFSPath(xStart, yStart, xEnd, yEnd, stepFrom, stepTo,
                    costFrom, costTo, limits, true));
 }
Example #5
0
 public Problem(
     TState initalState,
     ActionFunction <TState, TAction> actionFunction,
     ResultFunction <TState, TAction> resultFunction,
     GoalTest <TState> goalTest, StepCost <TState, TAction> stepCost)
 {
     InitalState    = initalState;
     ActionFunction = actionFunction;
     ResultFunction = resultFunction;
     GoalTest       = goalTest;
     StepCost       = stepCost;
 }
Example #6
0
        private static void SolveProblem <TState, TAction>(
            ActionFunction <TState, TAction> actionFunction,
            ResultFunction <TState, TAction> resultFunction,
            GoalTest <TState> goalTest,
            StepCost <TState, TAction> stepCost,
            TState initialState,
            IGraphSearch <TState, TAction> searchAlgorithm)
        {
            var problem = new Problem <TState, TAction>(
                initialState, actionFunction, resultFunction, goalTest, stepCost);

            var solution = searchAlgorithm.Search(problem);

            Console.WriteLine("Solution:");
            Console.WriteLine("=========");
            foreach (var node in solution)
            {
                Console.WriteLine(node.State);
            }

            Console.ReadKey();
        }
        // returns a Path if there is one or null if not
        public static Path BFSPath(int xStart, int yStart, int xEnd, int yEnd,
           CanStep stepFrom, CanStep stepTo, StepCost costFrom, DirectedStepCost costTo,
           MapRectangle limits, bool allowDiagonalSteps)
        {
            bool debug = false;
            if (debug)
            {
                Console.WriteLine("BFS start");
            }

            // update bestCost to hold the Dijkstra map
            if (bestCost == null || bestCost.Length < limits.w)
            {
                bestCost = new int[limits.w][];
                visitedFrom = new eStep[limits.w][];
            }
            if (bestCost[0] == null || bestCost[0].Length < limits.h)
            {
                for (int x = 0; x < limits.w; x++)
                {
                    bestCost[x] = new int[limits.h];
                    visitedFrom[x] = new eStep[limits.h];
                }
            }

            // clear bestCost to -1 = unvisited
            for (int x = 0; x < limits.w; x++)
            {
                for (int y = 0; y < limits.h; y++)
                {
                    bestCost[x][y] = -1;
                }
            }

            // forward pass
            List<int> frontX = new List<int>();
            List<int> frontY = new List<int>();
            List<int> newFrontX = new List<int>();
            List<int> newFrontY = new List<int>();
            frontX.Add(xStart);
            frontY.Add(yStart);
            bestCost[xStart - limits.x][yStart - limits.y] = 0;
            bool done = false;
            while (!done)
            {
                if (debug)
                {
                    Console.WriteLine("BFS new iteration, front size = " +
                       frontX.Count);
                }
                newFrontX.Clear();
                newFrontY.Clear();
                done = true;
                for (int i = 0; i < frontX.Count; i++)
                {
                    int baseCost = bestCost[frontX[i] - limits.x][
                       frontY[i] - limits.y];
                    if (costFrom != null)
                    {
                        baseCost += costFrom(frontX[i], frontY[i]);
                    }
                    if (stepFrom == null || stepFrom(frontX[i], frontY[i]))
                    {
                        for (int j = 0; j < 8; j += (allowDiagonalSteps ? 1 : 2))
                        {
                            int xNew = frontX[i] + StepDX[j];
                            int yNew = frontY[i] + StepDY[j];
                            if (debug) 
                            {
                                Console.WriteLine("   attempt step from " + frontX[i] +
                                   ", " + frontY[i] + " dir " + j + " delta = " + 
                                   StepDX[j] + ", " + StepDY[j] + " to " + xNew + ", " + 
                                   yNew);
                            }
                            if (xNew >= limits.x && yNew >= limits.y &&
                               xNew <= limits.x2 && yNew <= limits.y2 &&
                               (stepTo == null || stepTo(xNew, yNew)))
                            {
                                int newCost = baseCost;
                                if (costTo != null)
                                {
                                    newCost += costTo(xNew, yNew, (eStep)j);
                                }
                                int dx = xNew - limits.x;
                                int dy = yNew - limits.y;
                                int currentCost = bestCost[dx][dy];
                                if (currentCost == -1 ||
                                   currentCost > newCost)
                                {
                                    bestCost[dx][dy] = newCost;
                                    visitedFrom[dx][dy] = ReverseStep[
                                       (int)j];
                                    newFrontX.Add(xNew);
                                    newFrontY.Add(yNew);
                                    if (debug)
                                    {
                                        Console.WriteLine("  step to " + xNew +
                                           ", " + yNew + " new cost = " +
                                           newCost);
                                    }
                                    done = false;
                                }
                            }
                        }
                    }
                }
                if (!done)
                {
                    List<int> swap = newFrontX; newFrontX = frontX; frontX = swap;
                    swap = newFrontY; newFrontY = frontY; frontY = swap;
                }
            }


            if (bestCost[xEnd - limits.x][yEnd - limits.y] != -1)
            {
                // reverse pass and path gen
                int x = xEnd, y = yEnd;
                List<eStep> steps = new List<eStep>();
                while (x != xStart || y != yStart)
                {
                    eStep backStep = visitedFrom[x - limits.x][y - limits.y];
                    steps.Add(backStep);
                    int dx = StepDX[(int)backStep];
                    int dy = StepDY[(int)backStep];
                    x += dx;
                    y += dy;
                }
                Path solution = new Path(new eStep[steps.Count]);
                for (int i = 0; i < steps.Count; i++)
                {
                    solution.Steps[i] = ReverseStep[(int)steps[steps.Count - i - 1]];
                }
                return solution;
            }
            else
            {
                return null; // there is no path
            }
        }
        // returns a Path if there is one or null if not
        public static Path BFSPath(int xStart, int yStart, int xEnd, int yEnd,
                                   CanStep stepFrom, CanStep stepTo, StepCost costFrom, DirectedStepCost costTo,
                                   MapRectangle limits, bool allowDiagonalSteps)
        {
            bool debug = false;

            if (debug)
            {
                Console.WriteLine("BFS start");
            }

            // update bestCost to hold the Dijkstra map
            if (bestCost == null || bestCost.Length < limits.w)
            {
                bestCost    = new int[limits.w][];
                visitedFrom = new eStep[limits.w][];
            }
            if (bestCost[0] == null || bestCost[0].Length < limits.h)
            {
                for (int x = 0; x < limits.w; x++)
                {
                    bestCost[x]    = new int[limits.h];
                    visitedFrom[x] = new eStep[limits.h];
                }
            }

            // clear bestCost to -1 = unvisited
            for (int x = 0; x < limits.w; x++)
            {
                for (int y = 0; y < limits.h; y++)
                {
                    bestCost[x][y] = -1;
                }
            }

            // forward pass
            List <int> frontX    = new List <int>();
            List <int> frontY    = new List <int>();
            List <int> newFrontX = new List <int>();
            List <int> newFrontY = new List <int>();

            frontX.Add(xStart);
            frontY.Add(yStart);
            bestCost[xStart - limits.x][yStart - limits.y] = 0;
            bool done = false;

            while (!done)
            {
                if (debug)
                {
                    Console.WriteLine("BFS new iteration, front size = " +
                                      frontX.Count);
                }
                newFrontX.Clear();
                newFrontY.Clear();
                done = true;
                for (int i = 0; i < frontX.Count; i++)
                {
                    int baseCost = bestCost[frontX[i] - limits.x][
                        frontY[i] - limits.y];
                    if (costFrom != null)
                    {
                        baseCost += costFrom(frontX[i], frontY[i]);
                    }
                    if (stepFrom == null || stepFrom(frontX[i], frontY[i]))
                    {
                        for (int j = 0; j < 8; j += (allowDiagonalSteps ? 1 : 2))
                        {
                            int xNew = frontX[i] + StepDX[j];
                            int yNew = frontY[i] + StepDY[j];
                            if (debug)
                            {
                                Console.WriteLine("   attempt step from " + frontX[i] +
                                                  ", " + frontY[i] + " dir " + j + " delta = " +
                                                  StepDX[j] + ", " + StepDY[j] + " to " + xNew + ", " +
                                                  yNew);
                            }
                            if (xNew >= limits.x && yNew >= limits.y &&
                                xNew <= limits.x2 && yNew <= limits.y2 &&
                                (stepTo == null || stepTo(xNew, yNew)))
                            {
                                int newCost = baseCost;
                                if (costTo != null)
                                {
                                    newCost += costTo(xNew, yNew, (eStep)j);
                                }
                                int dx          = xNew - limits.x;
                                int dy          = yNew - limits.y;
                                int currentCost = bestCost[dx][dy];
                                if (currentCost == -1 ||
                                    currentCost > newCost)
                                {
                                    bestCost[dx][dy]    = newCost;
                                    visitedFrom[dx][dy] = ReverseStep[
                                        (int)j];
                                    newFrontX.Add(xNew);
                                    newFrontY.Add(yNew);
                                    if (debug)
                                    {
                                        Console.WriteLine("  step to " + xNew +
                                                          ", " + yNew + " new cost = " +
                                                          newCost);
                                    }
                                    done = false;
                                }
                            }
                        }
                    }
                }
                if (!done)
                {
                    List <int> swap = newFrontX; newFrontX = frontX; frontX = swap;
                    swap = newFrontY; newFrontY = frontY; frontY = swap;
                }
            }


            if (bestCost[xEnd - limits.x][yEnd - limits.y] != -1)
            {
                // reverse pass and path gen
                int          x = xEnd, y = yEnd;
                List <eStep> steps = new List <eStep>();
                while (x != xStart || y != yStart)
                {
                    eStep backStep = visitedFrom[x - limits.x][y - limits.y];
                    steps.Add(backStep);
                    int dx = StepDX[(int)backStep];
                    int dy = StepDY[(int)backStep];
                    x += dx;
                    y += dy;
                }
                Path solution = new Path(new eStep[steps.Count]);
                for (int i = 0; i < steps.Count; i++)
                {
                    solution.Steps[i] = ReverseStep[(int)steps[steps.Count - i - 1]];
                }
                return(solution);
            }
            else
            {
                return(null); // there is no path
            }
        }