Exemple #1
0
        static void Main(string[] args)
        {
            var input = File.ReadAllLines("../../../input.txt");

            var sw = new Stopwatch();

            sw.Start();

            var wires     = input.Select(WireToPoints).ToList();
            var crossings = new HashSet <Point>(wires[0].Keys.Intersect(wires[1].Keys));

            var closest = crossings.MinBy(DistanceFromOrigin).First();

            Console.WriteLine($"Part 1: point {closest} is in both wires and close to the origin.");

            var shortest = crossings.MinBy(x => wires[0][x] + wires[1][x]).First();
            var delay    = wires[0][shortest] + wires[1][shortest];

            Console.WriteLine($"Part 2: point {shortest} has signal delay {delay}");

            var search1 = new BreadthFirstSearch <Point>(EqualityComparer <Point> .Default, p =>
                                                         _mapDirectionToSize.Values.Select(s => p + s).Where(wires[0].Keys.Contains)
                                                         )
            {
                PerformParallelSearch = false
            };

            var wire1 = search1.FindAll(Point.Empty, p => crossings.Contains(p))
                        .ToDictionary(x => x.Target, x => x.Length);


            var search2 = new BreadthFirstSearch <Point>(EqualityComparer <Point> .Default, p =>
                                                         _mapDirectionToSize.Values.Select(s => p + s).Where(wires[1].Keys.Contains)
                                                         )
            {
                PerformParallelSearch = false
            };

            var wire2 = search2.FindAll(Point.Empty, p => crossings.Contains(p))
                        .ToDictionary(x => x.Target, x => x.Length);

            var shortedCrossings = crossings.MinBy(x => wire1[x] + wire2[x]).First();

            delay = wire1[shortedCrossings] + wire2[shortedCrossings];
            Console.WriteLine($"Part 3: point {shortedCrossings} has signal delay {delay}");


            sw.Stop();
            Console.WriteLine($"Solving took {sw.ElapsedMilliseconds}ms.");
            _ = Console.ReadLine();
        }
Exemple #2
0
        /// <summary>
        /// Computes the result of the operation.
        /// </summary>
        protected override void ComputeResult()
        {
            _edgeSet = new HashSet <IGraphEdge>();
            _forest  = new DisjointSetForest <IGraphVertex>(Source.Vertices);

            while (_forest.SetCount > 1)
            {
                IGraphVertex currentRep = null;

                foreach (IGraphVertex vertex in _forest.OrderedEnumerator)
                {
                    if (currentRep != _forest.Find(vertex))
                    {
                        //new component
                        currentRep = _forest.Find(vertex);
                        if (_edgeSet.Count > 0)
                        {
                            _spanningEdges.Add(_edgeSet.MinBy(x => _weightMetric(x)).First());
                        }
                        _edgeSet.Clear();
                    }

                    if (Source.OutEdges(vertex).Any(x => _forest.Find(x.Target) != currentRep))
                    {
                        _edgeSet.Add(
                            Source.OutEdges(vertex)
                            .Where(x => _forest.Find(x.Target) != currentRep)
                            .MinBy(y => _weightMetric(y))
                            .First());
                    }
                }

                if (_edgeSet.Count > 0)
                {
                    //on the last element there is no component change
                    _spanningEdges.Add(_edgeSet.MinBy(x => _weightMetric(x)).First());
                }

                _edgeSet.Clear();

                foreach (IGraphEdge spanningEdge in _spanningEdges)
                {
                    _forest.Union(spanningEdge.Source, spanningEdge.Target);
                }
            }
        }
Exemple #3
0
    public static int Dijkstra(this Dictionary <Point, int> graph, Point source, Point target)
    {
        var Q    = new HashSet <Point>();
        var dist = new Dictionary <Point, int>();
        var prev = new Dictionary <Point, Point?>();

        foreach (var v in graph.Keys)
        {
            dist[v] = int.MaxValue;
            prev[v] = null;
            Q.Add(v);
        }
        dist[source] = 0;

        while (Q.Count > 0)
        {
            var u = Q.MinBy(p => dist[p]) !;

            Q.Remove(u);

            foreach (var v in u.Neighbors(target).Intersect(Q))
            {
                var alt = dist[u] + graph[v];
                if (alt < dist[v])
                {
                    dist[v] = alt;
                    prev[v] = u;
                }
            }
        }

        var seq = new List <(Point, int, int)>();
        var p   = target;

        while (p is not null)
        {
            seq.Add((p, graph[p], dist[p]));
Exemple #4
0
    // Split any edges that intersect with the given edge at their midpoint.
    private static void SplitEdgesWithEdge(List <Vector2> vertexes, List <IntTuple2> edges, IntTuple2 splitterEdge)
    {
        // Gather edge split data. These are tuples in the form (splitter vertex index, split edge index).
        List <IntTuple2> edgeSplitData     = new List <IntTuple2>();
        HashSet <int>    splitEdgeVertsSet = new HashSet <int>();

        splitEdgeVertsSet.Add(splitterEdge.e0);
        splitEdgeVertsSet.Add(splitterEdge.e1);
        for (int i = 0; i < edges.Count; ++i)
        {
            IntTuple2 curEdge           = edges[i];
            int       intersectionIndex = MakeIntersection(vertexes, splitterEdge, curEdge);

            // If the current edge had a vertex on the splitter edge, split the splitter edge but leave the current egde alone.
            if (curEdge.e0 == intersectionIndex || curEdge.e1 == intersectionIndex)
            {
                Debug.Log("Will split edge [" + vertexes[splitterEdge.e0] + ", " + vertexes[splitterEdge.e1] + "] at " + vertexes[intersectionIndex]);
                splitEdgeVertsSet.Add(intersectionIndex);
            }
            // If the splitter edge had a vertex on the current edge, split the current edge but leave the splitter edge alone.
            else if (splitterEdge.e0 == intersectionIndex || splitterEdge.e1 == intersectionIndex)
            {
                Debug.Log("Will split edge [" + vertexes[curEdge.e0] + ", " + vertexes[curEdge.e1] + "] at " + vertexes[intersectionIndex]);
                edgeSplitData.Add(new IntTuple2(intersectionIndex, i));
            }
            // If the edges met in the middle, split them both.
            else if (intersectionIndex != -1)
            {
                Debug.Log("Will split edge [" + vertexes[splitterEdge.e0] + ", " + vertexes[splitterEdge.e1] + "] at " + vertexes[intersectionIndex]);
                Debug.Log("Will split edge [" + vertexes[curEdge.e0] + ", " + vertexes[curEdge.e1] + "] at " + vertexes[intersectionIndex]);
                splitEdgeVertsSet.Add(intersectionIndex);
                edgeSplitData.Add(new IntTuple2(intersectionIndex, i));
            }
        }

        // DEBUG: Log stuff to figure out why splitting doesn't work as expected.

        /*if (edgeSplitData.Count > 0)
         * {
         *      string debugText = "Edge split data:\n";
         *      foreach (IntTuple2 splitData in edgeSplitData)
         *      {
         *              int vertexIndex = splitData.e0;
         *              int edgeIndex = splitData.e1;
         *
         *              Vector2 vertex = vertexes[vertexIndex];
         *              IntTuple2 edge = edges[edgeIndex];
         *
         *              debugText += ("[" + vertexes[edge.e0] + ", " + vertexes[edge.e1] + "] was split at " + vertex + "\n");
         *      }
         *      Debug.Log(debugText);
         * }
         *
         * if (splitEdgeVertsSet.Count > 0)
         * {
         *      string debugText = "Split edge verts set:\n";
         *      foreach (int vert in splitEdgeVertsSet)
         *      {
         *              debugText += vertexes[vert];
         *      }
         *      Debug.Log(debugText);
         * }*/

        // Split the edges.
        foreach (IntTuple2 splitData in edgeSplitData)
        {
            int intersectionIndex = splitData.e0;
            int edgeIndex         = splitData.e1;

            IntTuple2 edge = edges[edgeIndex];

            // Split the old edge in two.
            int oldEnd = edge.e1;
            edge.e1 = intersectionIndex;

            IntTuple2 newEdge = new IntTuple2(intersectionIndex, oldEnd);
            if (!edges.Contains(newEdge))
            {
                edges.Add(newEdge);
            }

            Debug.Log("Edge split into " + vertexes[edge.e0] + ", " + vertexes[intersectionIndex] + ", " + vertexes[newEdge.e1]);
        }

        // Make the new, split up edge to replace the old splitter edge from the vertexes.
        int[] splitEdgeVerts = new int[splitEdgeVertsSet.Count];
        splitEdgeVertsSet.CopyTo(splitEdgeVerts);
        Vector2 mostNegative = vertexes[splitEdgeVertsSet.MinBy(v => vertexes[v].x + vertexes[v].y)];

        System.Array.Sort <int>(splitEdgeVerts, (a, b) =>
        {
            Vector2 vA = vertexes[a] - mostNegative;
            Vector2 vB = vertexes[b] - mostNegative;
            return(vA.sqrMagnitude.CompareTo(vB.sqrMagnitude));
        }
                                );

        // DEBUG: Log the split edge verts.
        string debugText = "Split edge verts: ";

        foreach (int vertexIndex in splitEdgeVerts)
        {
            debugText += vertexes[vertexIndex] + ", ";
        }
        Debug.Log(debugText);

        // Create the new edges from the splitter edge data.
        for (int i = 1; i < splitEdgeVerts.Length; ++i)
        {
            int       vA      = splitEdgeVerts[i - 1];
            int       vB      = splitEdgeVerts[i];
            IntTuple2 newEdge = new IntTuple2(vA, vB);
            if (!edges.Contains(newEdge))
            {
                edges.Add(newEdge);
            }
        }
    }
Exemple #5
0
        protected Job ResourceDeliverJobFor(Pawn pawn, IConstructible c, bool canRemoveExistingFloorUnderNearbyNeeders = true)
        {
            Blueprint_Install blueprint_Install = c as Blueprint_Install;

            if (blueprint_Install != null)
            {
                return(this.InstallJob(pawn, blueprint_Install));
            }
            bool flag = false;
            ThingDefCountClass        thingDefCountClass = null;
            List <ThingDefCountClass> list = c.MaterialsNeeded();
            int count = list.Count;
            int i     = 0;

            while (i < count)
            {
                ThingDefCountClass need = list[i];
                if (!pawn.Map.itemAvailability.ThingsAvailableAnywhere(need, pawn))
                {
                    flag = true;
                    thingDefCountClass = need;
                    break;
                }
                Thing foundRes = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForDef(need.thingDef), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, (Thing r) => WorkGiver_ConstructDeliverResources.ResourceValidator(pawn, need, r), null, 0, -1, false, RegionType.Set_Passable, false);
                if (foundRes != null)
                {
                    int resTotalAvailable;
                    this.FindAvailableNearbyResources(foundRes, pawn, out resTotalAvailable);
                    int             num;
                    Job             job;
                    HashSet <Thing> hashSet = this.FindNearbyNeeders(pawn, need, c, resTotalAvailable, canRemoveExistingFloorUnderNearbyNeeders, out num, out job);
                    if (job != null)
                    {
                        return(job);
                    }
                    hashSet.Add((Thing)c);
                    Thing thing = hashSet.MinBy((Thing nee) => IntVec3Utility.ManhattanDistanceFlat(foundRes.Position, nee.Position));
                    hashSet.Remove(thing);
                    int num2 = 0;
                    int j    = 0;
                    do
                    {
                        num2 += WorkGiver_ConstructDeliverResources.resourcesAvailable[j].stackCount;
                        j++;
                    }while (num2 < num && j < WorkGiver_ConstructDeliverResources.resourcesAvailable.Count);
                    WorkGiver_ConstructDeliverResources.resourcesAvailable.RemoveRange(j, WorkGiver_ConstructDeliverResources.resourcesAvailable.Count - j);
                    WorkGiver_ConstructDeliverResources.resourcesAvailable.Remove(foundRes);
                    Job job2 = new Job(JobDefOf.HaulToContainer);
                    job2.targetA      = foundRes;
                    job2.targetQueueA = new List <LocalTargetInfo>();
                    for (j = 0; j < WorkGiver_ConstructDeliverResources.resourcesAvailable.Count; j++)
                    {
                        job2.targetQueueA.Add(WorkGiver_ConstructDeliverResources.resourcesAvailable[j]);
                    }
                    job2.targetB = thing;
                    if (hashSet.Count > 0)
                    {
                        job2.targetQueueB = new List <LocalTargetInfo>();
                        foreach (Thing current in hashSet)
                        {
                            job2.targetQueueB.Add(current);
                        }
                    }
                    job2.targetC  = (Thing)c;
                    job2.count    = num;
                    job2.haulMode = HaulMode.ToContainer;
                    return(job2);
                }
                else
                {
                    flag = true;
                    thingDefCountClass = need;
                    i++;
                }
            }
            if (flag)
            {
                JobFailReason.Is(string.Format("{0}: {1}", WorkGiver_ConstructDeliverResources.MissingMaterialsTranslated, thingDefCountClass.thingDef.label), null);
            }
            return(null);
        }
Exemple #6
0
            private List <Node> DijkstraConnect(Node source, Node sink, out float routeCost)
            {
                string lastKey = "nokey";

                routeCost = -1;
                StringBuilder sb = new StringBuilder();

                try
                {
                    List <Node> ret = null;
                    Dictionary <Node, float> distances     = new Dictionary <Node, float>(nodes.Count);
                    Dictionary <Node, Node>  previousNodes = new Dictionary <Node, Node>(nodes.Count);
                    HashSet <Node>           Q             = new HashSet <Node>(nodes);
                    Q.Add(sink);
                    foreach (Node nd in nodes)
                    {
                        distances.SetOrAdd(nd, Single.PositiveInfinity);
                        previousNodes.SetOrAdd(nd, null);
                    }

                    distances.SetOrAdd(sink, float.PositiveInfinity);
                    previousNodes.SetOrAdd(sink, null);
                    previousNodes.SetOrAdd(source, null);

                    ZLogger.Message("DijkstraConnect", debugLevel: DebugLevel.Pathfinding);
                    lastKey = "distances/source";
                    distances.SetOrAdd(source, 0);

                    foreach (Node neighbor in source.neighbors)
                    {
                        distances[neighbor] = source.neighborDistances[neighbor];
                    }

                    bool found = false;
                    Node u     = source;
                    while (Q.Count > 0)
                    {
                        sb.Clear();
                        u = Q.MinBy((x) => distances[x]);
                        //foreach (Node nd in u.neighbors)
                        //{
                        //    sb.Append($"nd = {nd}, distance = {distances[nd]}");
                        //}

                        sb.Append($"Chose {u} as shortest with {distances[u]}- looking for sink {sink}");
                        ZLogger.Message(sb.ToString(), debugLevel: DebugLevel.Pathfinding);
                        //Console.WriteLine(sb.ToString());
                        Q.Remove(u);
                        if (u == sink)
                        {
                            break;
                        }
                        foreach (Node v in u.neighbors)
                        {
                            float altDistance = distances[u] + u.neighborDistances[v];
                            if (altDistance < distances[v])
                            {
                                distances[v]     = altDistance;
                                previousNodes[v] = u;
                            }
                        }
                    }

                    sb.Clear();

                    foreach (Node node in previousNodes.Keys)
                    {
                        sb.Append($"Node:{node}, previous: {previousNodes[node]}, cumulative distance: {distances[node]}");
                    }
                    ret       = new List <Node>();
                    routeCost = distances[sink];
                    sb.Clear();
                    while (sink != null)
                    {
                        sb.AppendLine($"{sink}");
                        ret.Add(sink);
                        sink = previousNodes[sink];
                    }

                    ret.Add(source);
                    sb.AppendLine($"Source Key = {source}");
                    ZLogger.Message(sb.ToString(), debugLevel: DebugLevel.Pathfinding);
                    ret.Reverse();
                    return(ret);
                }
                catch (Exception e)
                {
                    sb = new StringBuilder();
                    foreach (object v in e.Data.Keys)
                    {
                        sb.Append($"{e.Data[v]}: {v}");
                    }
                    ZLogger.Message($"Couldn't find key!  Or key was null... {lastKey}  Exception data of type {e.GetType()} follows: {sb}", debugLevel: DebugLevel.Pathfinding);
                    return(new List <Node>());
                }
            }
        DijkstraShortestPaths <TVertex, TEdge>(
            this IWeightedDirectedGraph <TVertex, TEdge> graph,
            TVertex origin,
            IAdder <TEdge> adder,
            IComparer <TEdge> comparer
            )
        {
            if (graph == null)
            {
                throw new ArgumentNullException(nameof(graph));
            }
            if (origin == null)
            {
                throw new ArgumentNullException(nameof(origin));
            }
            if (adder == null)
            {
                throw new ArgumentNullException(nameof(adder));
            }
            if (comparer == null)
            {
                throw new ArgumentNullException(nameof(comparer));
            }

            if (!graph.Vertices.Contains(origin))
            {
                throw new ArgumentException();
            }

            // Constructs a dictionary which stores the graphs which contain the shortest path from the origin to
            // each of the vertices that is reachable from the origin by iteratively traversing successor endpoints.
            var graphs = new Dictionary <TVertex, IWeightedDirectedGraph <TVertex, TEdge> >();

            // Constructs a dictionary which stores the additions which represent the added edges which in turn
            // represent the shortest path from the origin to each of the vertices when added.
            var accumulations = new Dictionary <TVertex, TEdge>();

            var settledVertices   = new HashSet <TVertex>();
            var unsettledVertices = new HashSet <TVertex> {
                origin
            };

            while (unsettledVertices.Count > 0)
            {
                // Returns the unsettled vertex that is nearest to the origin by finding the shortest of all the
                // accumulated edges which form a path from the origin to each of the unsettled vertices. Calling
                // the `MinBy` method with only one unsettled vertex in the set of unsettled vertices will return
                // that unsettled vertex, hence it will always return the origin during the first iteration over
                // the unsettled vertices set, because the unsettled vertices set will only contain the origin.
                var nearestVertex = unsettledVertices.MinBy(vertex => accumulations[vertex], comparer);

                // Removes the nearest vertex from the set of unvisited vertices.
                unsettledVertices.Remove(nearestVertex);

                // Iterates over each of the successor endpoints of the nearest vertex.
                foreach (var endpoint in graph.SuccessorEndpoints(nearestVertex))
                {
                    // If the vertex of the endpoint is already settled, then continue to the next iteration.
                    if (settledVertices.Contains(endpoint.Vertex))
                    {
                        continue;
                    }

                    // If the dictionary of additions contains an addition for the nearest vertex, then add this
                    // addition and the endpoint edge together in order to calculate a single path from the origin
                    // to the endpoint vertex of the current iteration; otherwise, an addition for the nearest vertex
                    // does not exist so return the endpoint edge without adding.
                    var currentPath = accumulations.ContainsKey(nearestVertex)
                        ? adder.Add(accumulations[nearestVertex], endpoint.Edge)
                        : endpoint.Edge;

                    // Returns true if the dictionary of additions contains the endpoint vertex and the current path
                    // is less than the existing shortest path from the origin to the endpoint vertex; otherwise,
                    // false. The existing shortest path is taken from the addition of each of the endpoints from
                    // the origin to the endpoint vertex which represent the existing shortest path when added.
                    bool IsCurrentPathLessThanShortestPath()
                    {
                        return(accumulations.ContainsKey(endpoint.Vertex) &&
                               comparer.Compare(currentPath, accumulations[endpoint.Vertex]) < 0);
                    }

                    // If the dictionary of graphs does not contain a graph for the endpoint vertex or the current
                    // path is less than the existing shortest path, then update the graph of the endpoint vertex.
                    if (!graphs.ContainsKey(endpoint.Vertex) || IsCurrentPathLessThanShortestPath())
                    {
                        // If the dictionary of graphs contains a graph for the nearest vertex, then a shortest path
                        // from the origin to the nearest vertex already exists so return a copy of this graph;
                        // otherwise, such a shortest path does not exist so return a new empty graph.
                        var currentGraph = graphs.ContainsKey(nearestVertex)
                            ? graphs[nearestVertex].EndpointPairs.ToGraph()
                            : new WeightedDirectedGraph <TVertex, TEdge>();

                        // Adds an edge from the nearest vertex to the vertex of the endpoint. This means that the
                        // graph will now contain endpoint pairs from the origin to the endpoint vertex.
                        currentGraph.AddEdge(nearestVertex, endpoint.Vertex, endpoint.Edge);

                        // Updates the graph of the endpoint vertex with the current graph because the current graph
                        // contains a shorter path from the origin to the endpoint vertex than the existing graph.
                        graphs[endpoint.Vertex] = currentGraph;

                        // Updates the addition of the endpoint vertex with the current path for the same reason.
                        accumulations[endpoint.Vertex] = currentPath;
                    }

                    // Adds the endpoint vertex to the set of unsettled vertices.
                    unsettledVertices.Add(endpoint.Vertex);
                }

                // Adds the nearest vertex to the set of settled vertices.
                settledVertices.Add(nearestVertex);
            }

            return(graphs);
        }
        protected Job ResourceDeliverJobFor(Pawn pawn, IConstructible c, bool canRemoveExistingFloorUnderNearbyNeeders = true)
        {
            Blueprint_Install blueprint_Install = c as Blueprint_Install;

            if (blueprint_Install != null)
            {
                return(InstallJob(pawn, blueprint_Install));
            }
            bool flag = false;
            ThingDefCountClass        thingDefCountClass = null;
            List <ThingDefCountClass> list = c.MaterialsNeeded();
            int count = list.Count;

            for (int i = 0; i < count; i++)
            {
                ThingDefCountClass need = list[i];
                if (!pawn.Map.itemAvailability.ThingsAvailableAnywhere(need, pawn))
                {
                    flag = true;
                    thingDefCountClass = need;
                    break;
                }
                Thing foundRes = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForDef(need.thingDef), PathEndMode.ClosestTouch, TraverseParms.For(pawn), 9999f, (Thing r) => ResourceValidator(pawn, need, r));
                if (foundRes != null)
                {
                    FindAvailableNearbyResources(foundRes, pawn, out int resTotalAvailable);
                    int             neededTotal;
                    Job             jobToMakeNeederAvailable;
                    HashSet <Thing> hashSet = FindNearbyNeeders(pawn, need, c, resTotalAvailable, canRemoveExistingFloorUnderNearbyNeeders, out neededTotal, out jobToMakeNeederAvailable);
                    if (jobToMakeNeederAvailable != null)
                    {
                        return(jobToMakeNeederAvailable);
                    }
                    hashSet.Add((Thing)c);
                    Thing thing = hashSet.MinBy((Thing nee) => IntVec3Utility.ManhattanDistanceFlat(foundRes.Position, nee.Position));
                    hashSet.Remove(thing);
                    int num  = 0;
                    int num2 = 0;
                    do
                    {
                        num += resourcesAvailable[num2].stackCount;
                        num2++;
                    }while (num < neededTotal && num2 < resourcesAvailable.Count);
                    resourcesAvailable.RemoveRange(num2, resourcesAvailable.Count - num2);
                    resourcesAvailable.Remove(foundRes);
                    Job job = new Job(JobDefOf.HaulToContainer);
                    job.targetA      = foundRes;
                    job.targetQueueA = new List <LocalTargetInfo>();
                    for (num2 = 0; num2 < resourcesAvailable.Count; num2++)
                    {
                        job.targetQueueA.Add(resourcesAvailable[num2]);
                    }
                    job.targetB = thing;
                    if (hashSet.Count > 0)
                    {
                        job.targetQueueB = new List <LocalTargetInfo>();
                        foreach (Thing item in hashSet)
                        {
                            job.targetQueueB.Add(item);
                        }
                    }
                    job.targetC  = (Thing)c;
                    job.count    = neededTotal;
                    job.haulMode = HaulMode.ToContainer;
                    return(job);
                }
                flag = true;
                thingDefCountClass = need;
            }
            if (flag)
            {
                JobFailReason.Is($"{MissingMaterialsTranslated}: {thingDefCountClass.thingDef.label}");
            }
            return(null);
        }
Exemple #9
0
        private void DoSearch(IEnumerable<Point> starts, Func<Point, bool> isPassable, Func<Point, bool> isGoal, Func<Point, Point, int> getCost, Func<Point, int> getH, int maxCost)
        {
            ClosedSet = new HashSet<Point>();
            OpenSet = new HashSet<Point>(starts);
            CameFrom = new Dictionary<Point, Point>();

            GScore = starts.ToDictionary(s => s, s => 0);
            FScore = starts.ToDictionary(s => s, s => GScore[s] + getH(s));

            while (OpenSet.Any())
            {
                var current = OpenSet.MinBy(p => FScore[p]);

                if (GScore[current] > maxCost)
                {
                    return;
                }

                if (isGoal(current))
                {
                    Path = ConstructPath(CameFrom, current);
                    return;
                }

                OpenSet.Remove(current);
                ClosedSet.Add(current);
                foreach (var n in GetNeighbors(current, isPassable))
                {
                    if (ClosedSet.Contains(n))
                        continue;

                    var tentativeG = GScore[current] + getCost(current, n);

                    if (!OpenSet.Contains(n) || tentativeG < GScore[n])
                    {
                        CameFrom[n] = current;
                        GScore[n] = tentativeG;
                        FScore[n] = tentativeG + getH(n);
                        OpenSet.Add(n);
                    }
                }
            }
        }
Exemple #10
0
 private static TPoint FindNodeWithLowestScore <TPoint>(HashSet <TPoint> list, IDictionary <TPoint, float> scoreTable)
 {
     //return list.OrderBy(x => scoreTable[x.Value]).First().Value;
     return(list.MinBy(x => scoreTable[x]));
 }
        public static bool ResourceDeliverJobFor(WorkGiver_ConstructDeliverResources __instance, ref Job __result, Pawn pawn, IConstructible c, bool canRemoveExistingFloorUnderNearbyNeeders = true)
        {
            Blueprint_Install blueprint_Install = c as Blueprint_Install;

            if (blueprint_Install != null)
            {
                __result = InstallJob(pawn, blueprint_Install);
                return(false);
            }
            List <Thing> resourcesAvailable = new List <Thing>();

            bool flag = false;
            ThingDefCountClass        thingDefCountClass = null;
            List <ThingDefCountClass> list = c.MaterialsNeeded();
            int count = list.Count;

            for (int i = 0; i < count; i++)
            {
                ThingDefCountClass need = list[i];
                if (!pawn.Map.itemAvailability.ThingsAvailableAnywhere(need, pawn))
                {
                    flag = true;
                    thingDefCountClass = need;
                    break;
                }

                Thing foundRes = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForDef(need.thingDef), PathEndMode.ClosestTouch, TraverseParms.For(pawn), 9999f, (Thing r) => ResourceValidator(pawn, need, r));
                if (foundRes != null)
                {
                    resourcesAvailable.Clear();
                    //FindAvailableNearbyResources2(foundRes, pawn, out int resTotalAvailable, resourcesAvailable);
                    int resTotalAvailable;
                    int num0 = Mathf.Min(foundRes.def.stackLimit, pawn.carryTracker.MaxStackSpaceEver(foundRes.def));
                    resTotalAvailable = 0;
                    resourcesAvailable.Add(foundRes);
                    resTotalAvailable += foundRes.stackCount;
                    if (resTotalAvailable < num0)
                    {
                        foreach (Thing item in GenRadial.RadialDistinctThingsAround(foundRes.Position, foundRes.Map, 5f, useCenter: false))
                        {
                            if (resTotalAvailable >= num0)
                            {
                                break;
                            }
                            if (item.def == foundRes.def && GenAI.CanUseItemForWork(pawn, item))
                            {
                                resourcesAvailable.Add(item);
                                resTotalAvailable += item.stackCount;
                            }
                        }
                    }
                    int             neededTotal;
                    Job             jobToMakeNeederAvailable;
                    HashSet <Thing> hashSet = FindNearbyNeeders(pawn, need, c, resTotalAvailable, canRemoveExistingFloorUnderNearbyNeeders, out neededTotal, out jobToMakeNeederAvailable);
                    if (jobToMakeNeederAvailable != null)
                    {
                        __result = jobToMakeNeederAvailable;
                        return(false);
                    }

                    hashSet.Add((Thing)c);
                    Thing thing = hashSet.MinBy((Thing nee) => IntVec3Utility.ManhattanDistanceFlat(foundRes.Position, nee.Position));
                    hashSet.Remove(thing);
                    int num  = 0;
                    int num2 = 0;
                    do
                    {
                        num += resourcesAvailable[num2].stackCount;
                        num2++;
                    }while (num < neededTotal && num2 < resourcesAvailable.Count);
                    resourcesAvailable.RemoveRange(num2, resourcesAvailable.Count - num2);
                    resourcesAvailable.Remove(foundRes);
                    Job job = JobMaker.MakeJob(JobDefOf.HaulToContainer);
                    job.targetA      = foundRes;
                    job.targetQueueA = new List <LocalTargetInfo>();
                    for (num2 = 0; num2 < resourcesAvailable.Count; num2++)
                    {
                        job.targetQueueA.Add(resourcesAvailable[num2]);
                    }

                    job.targetB = thing;
                    if (hashSet.Count > 0)
                    {
                        job.targetQueueB = new List <LocalTargetInfo>();
                        foreach (Thing item in hashSet)
                        {
                            job.targetQueueB.Add(item);
                        }
                    }

                    job.targetC  = (Thing)c;
                    job.count    = neededTotal;
                    job.haulMode = HaulMode.ToContainer;
                    __result     = job;
                    return(false);
                }

                flag = true;
                thingDefCountClass = need;
            }

            if (flag)
            {
                JobFailReason.Is($"{MissingMaterialsTranslated}: {thingDefCountClass.thingDef.label}");
            }

            __result = null;
            return(false);
        }
Exemple #12
0
        /// <summary>
        /// Calculates the shortest path to every other node in the network.
        /// The implementation uses Dijkstra's algorithm, for use in a link-state routing protocol.
        /// </summary>
        /// <returns>
        /// The tree, in the form of a dictionary (node => predecessor of node in shortest path to node), or (this => null).
        /// </returns>
        private IDictionary<Node, Node> CalculateShortestPaths()
        {
            var nodes = Simulator.Nodes.Values;
            /// Best known distance (sum of costs) from this to each node
            IDictionary<Node, double> dist = nodes.ToDictionary(node => node, _ => Double.PositiveInfinity);
            /// Predecessor of each node in shortest-paths tree
            IDictionary<Node, Node> previous = nodes.ToDictionary(node => node, _ => (Node)null);

            dist[this] = 0;
            /// Nodes that have yet to be processed
            ISet<Node> queue = new HashSet<Node>(nodes); // TODO Priority queue would be faster; replace if needed

            while(queue.Count > 0) {
            Node u = queue.MinBy(node => dist[node]);
            queue.Remove(u);
            if(dist[u] == Double.PositiveInfinity)
                break; // remaining nodes are inaccessible

            foreach(Node v in queue
                .Where(v => Simulator.LinksBySrcDest.ContainsKey(Tuple.Create(u, v))))
            {
                Link uv = Simulator.LinksBySrcDest[Tuple.Create(u, v)];
                // Look up link cost from our own local table, instead of statically
                double new_dist = dist[u] + this.known_link_costs[uv];
                if(new_dist < dist[v]) {
                    dist[v] = new_dist;
                    previous[v] = u;
                    // TODO for priority queue, run queue.DecreaseKey(new_dist, v)
                }
            }
            }

            return previous;
        }