Esempio n. 1
0
        public static Graph2d CreateRoutingCostMap(List <Room> _exclude, IVector2 _size, int _roomBuffer,
                                                   int _tunnelMagBuffer, double _tunnelRoutingStrength)
        {
            var defCost = _tunnelRoutingStrength * 2d + 1;

            var routingGraph = new Graph2d(_size, defCost, false);


            foreach (var room in m_Tilemap.m_Rooms)
            {
                if (_exclude.Contains(room))
                {
                    //Add special case routing per room shape
                    switch (room.Shape)
                    {
                    //Rect rooms add corners as impassable
                    case Room.ShapeType.Rectangle:
                        foreach (var corner in room.Corners)
                        {
                            routingGraph.SetNodeWeight(corner, double.MaxValue);
                        }
                        break;

                    default:
                        break;
                    }
                    continue;
                }

                //Add room walls as impassable with specified buffer
                List <IVector2> bufferPoly;

                //Pre-calculate costs for room buffer
                var cost = new double[_roomBuffer + 1];
                for (var buffer = _roomBuffer; buffer > 0; --buffer)
                {
                    cost[buffer] = defCost + defCost * (_roomBuffer - buffer);
                }
                cost[0] = double.MaxValue;

                //Add room buffer costs
                for (var buffer = _roomBuffer; buffer >= 0; --buffer)
                {
                    if (buffer != 0)
                    {
                        var co         = new ClipperOffset();
                        var wallCoords = room.GetWallCoords(true);
                        co.AddPath(Support2D.ToIntPoint(wallCoords), JoinType.jtMiter,
                                   EndType.etClosedPolygon);
                        var pt = new PolyTree();
                        co.Execute(ref pt, buffer);

                        bufferPoly = Support2D.ToIVector2(pt.Childs[0].Contour);

                        var path = Support2D.CreatePath(bufferPoly, true);

                        foreach (var coord in path)
                        {
                            routingGraph.SetNodeWeight(coord, cost[buffer] + routingGraph.GetNodeWeight(coord));
                        }
                    }
                    else
                    {
                        foreach (var coord in room.GetWallCoords(true))
                        {
                            routingGraph.SetNodeWeight(coord, cost[0]);
                        }
                    }
                }
            }


            if (_tunnelMagBuffer >= 0 && Settings.CalcRoutingStrength != 0)
            {
                //Pre-calcluate costs for tunnel magnetism
                var tunnelCost = new double[_tunnelMagBuffer + 1];
                tunnelCost[0] = 1d;
                for (var tScaleIdx = 1; tScaleIdx <= _tunnelMagBuffer; ++tScaleIdx)
                {
                    tunnelCost[tScaleIdx] = tunnelCost[0] + _tunnelRoutingStrength +
                                            (tScaleIdx - 1) * (defCost - 1 - _tunnelRoutingStrength) / _tunnelMagBuffer;
                }
                foreach (var tunnel in m_Tilemap.m_Tunnels)
                {
                    for (var tOffset = _tunnelMagBuffer; tOffset >= 0; --tOffset)
                    {
                        //double cost = _defaultCost - _defaultCost/(tOffset + 1);
                        foreach (var path in tunnel.Paths)
                        {
                            if (tOffset > 0)
                            {
                                var solution = new PolyTree();
                                var co       = new ClipperOffset();
                                co.AddPath(Support2D.ToIntPoint(path.Points), JoinType.jtMiter,
                                           EndType.etOpenButt);
                                //co.AddPath(Support2D.ToIntPoint(path.PointsReverse), JoinType.jtSquare,
                                //    EndType.etOpenButt);
                                co.Execute(ref solution, tOffset);


                                foreach (var child in solution.Childs)
                                {
                                    var tunnelPath = Support2D.CreatePath(Support2D.ToIVector2(child.Contour), true);


                                    foreach (var coord in tunnelPath)
                                    {
                                        if (!routingGraph.IsImpassable(coord))
                                        {
                                            var curCost = routingGraph.GetNodeWeight(coord);
                                            if (curCost <= defCost && curCost > tunnelCost[tOffset])
                                            {
                                                routingGraph.SetNodeWeight(coord, tunnelCost[tOffset]);
                                            }
                                        }
                                    }
                                }
                            }
                            else
                            {
                                foreach (var coord in path.Points)
                                {
                                    if (!routingGraph.IsImpassable(coord))
                                    {
                                        routingGraph.SetNodeWeight(coord, tunnelCost[0]);
                                    }
                                }
                                //routingGraph.ScaleNodeWeight(coord, 0.1f * (float)_defaultCost);
                            }
                        }
                    }
                }
            }
            return(routingGraph);
        }
Esempio n. 2
0
        //public static IEnumerator AStar(Graph2d _graph, IVector2 _start, IVector2 _end, double _turnCostAdder, double _defVaul, Func<IVector2, IVector2, double, double> _heuristic)
        public static void AStar(Graph2d _graph, IVector2 _start, IVector2 _end, double _turnCostAdder, double _defVaul, Func <IVector2, IVector2, double, double> _heuristic)
        {
            var openList = new ioMinPriQ <AStarOpenNode>();

            openList.Enqueue(new AStarOpenNode(_start, null, 0, _heuristic(_start, _end, _defVaul)));
            var closedList = new Dictionary <IVector2, AStarClosedNode>();

            /* //UNITY
             * bool debugMe = true;
             * var texture = (Texture2D)TileMap2D.meshRenderer.material.mainTexture;
             * int frameUpdateRate = 30;
             * if (debugMe)
             * {
             *
             *  texture.SetPixel(_start.x, _start.y, new Color(0.6f, 1f, 0.6f, 1));
             *  texture.SetPixel(_end.x, _end.y, new Color(0.6f, 1f, 0.6f, 1));
             *  texture.Apply();
             * }
             * */

            AStarOpenNode curNode = null;
            var           prevDir = -1;

            while (!openList.IsEmpty)
            {
                //Find smallest element in open list (est total cost)
                curNode = openList.Dequeue();

                //Get direction of step from current node
                if (curNode.Parent != null)
                {
                    prevDir = (int)curNode.StepDirection;
                }

                //Exit if goal found
                if (curNode.Coord.Equals(_end))
                {
                    closedList[_end] = new AStarClosedNode(curNode);
                    break;
                }

                for (int i = 1; i < 8; i = i + 2)
                //foreach (var neighbor in curNode.Coord.Neighbors())
                {
                    IVector2 neighbor = curNode.Coord + DirMap.Get(i);
                    if (!_graph.InBounds(neighbor) || (_graph.IsImpassable(neighbor)))
                    {
                        continue;
                    }
                    //Set end node and add cost
                    //var endNode = neighbor;
                    //var endNodeCost = curNode.CostSoFar + _graph.GetEdgeWeight(curNode.Coord, (G2Dir) i);//_graph[neighbor].GetEdge((G2Dir)i);
                    var endNodeCost = curNode.CostSoFar + _graph.GetNodeWeight(neighbor);
                    if (i != prevDir && prevDir != -1)
                    {
                        endNodeCost += _turnCostAdder;
                    }

                    //Skip if not walkable
                    if (endNodeCost == Graph2d.IMPASSABLE)
                    {
                        continue;
                    }

                    //Skip if better path already exists
                    var skipNode = false;
                    for (int j = 0; j < openList.DataList.Count; ++j)
                    {
                        if (openList.DataList[j].Coord.Equals(neighbor))
                        {
                            if (openList.DataList[j].CostSoFar <= endNodeCost)
                            {
                                skipNode = true;
                                break;
                            }
                            openList.Remove(openList.DataList[j]);
                        }
                    }
                    if (skipNode)
                    {
                        continue;
                    }

                    //Skip or update if current path is worse/better
                    if (closedList.ContainsKey(neighbor))
                    {
                        if (closedList[neighbor].CostSoFar <= endNodeCost)
                        {
                            continue;
                        }
                        closedList[neighbor] = new AStarClosedNode(curNode.Coord, endNodeCost);

                        /* //UNITY
                         * if (debugMe)
                         *  texture.SetPixel(neighbor.x, neighbor.y, new Color(0.0f, 1f, 1f, 1f));
                         */
                    }


                    var endNode = new AStarOpenNode(neighbor, curNode.Coord, endNodeCost, endNodeCost + _heuristic(neighbor, _end, _defVaul));

                    openList.Enqueue(endNode);
                }

                closedList[curNode.Coord] = new AStarClosedNode(curNode);

                /* //UNITY
                 * if (debugMe)
                 * {
                 *
                 *  var pixel = texture.GetPixel(curNode.Coord.x, curNode.Coord.y);
                 *  pixel = new Color(pixel.r + 0.3f, pixel.g, pixel.b, pixel.a);
                 *  texture.SetPixel(curNode.Coord.x, curNode.Coord.y, pixel);
                 *  texture.Apply();
                 *  if (++debugFrameCount == frameUpdateRate)
                 *  {
                 *      debugFrameCount = 0;
                 *      yield return null;
                 *  }
                 *
                 * }
                 */
            }
            if (curNode.Coord != _end)
            {
                String dbgMsg = "End Node Null -- No path found?";
                Msg.LogDebug(TAG_DEBUG, dbgMsg, MsgPriLvl.HIGH);
                AStarPath = null;
                //return null; new List<IVector2>();
            }
            else
            {
                var path = new List <IVector2>()
                {
                    curNode.Coord
                };
                var closedNode = new AStarClosedNode(curNode);
                ;
                while (closedNode.Parent != null)
                {
                    path.Insert(0, closedNode.Parent.Value);
                    Msg.LogDebug(TAG_DEBUG, "Added to path: " + closedNode.Parent, MsgPriLvl.LOW);
                    closedNode = closedList[closedNode.Parent.Value];  //TODO Seed 705 crashes here with invalid key
                }
                AStarPath = path;

                closedList[curNode.Coord] = new AStarClosedNode(curNode);

                /* //UNITY
                 * if (debugMe)
                 * {
                 *  foreach (var coord in path)
                 *      texture.SetPixel(coord.x, coord.y, new Color(0.8f, 0.8f, 1f, 1));
                 *  texture.Apply();
                 *  yield return null;
                 * }
                 */
            }
            //yield return null; //UNITY
        }