Пример #1
0
 public MapSearchNode(MapNode mp)
 {
     mapNode = mp;
 }
Пример #2
0
        public bool GetSuccessors(AStarPathfinder astarsearch, MapSearchNode parent_node)
        {
            MapSearchNode n;
            MapNode       left  = null;
            MapNode       right = null;
            bool          ret;

            if (parent_node != null && mapNode.floorNode != null)
            {
                // Start node which is also a floor node.
                // Find and add nearest transport nodes to the left/right (based on start_point, which should be populated)
                List <MapNode> nodesOnFloor = mapNode.nodesOnFloor;
                //assert(nodesOnFloor != NULL);
                foreach (var nodex in nodesOnFloor)
                //for (List<MapNode> const_iterator i = nodesOnFloor->begin(); i != nodesOnFloor->end(); i++)
                {
                    //MapNode node = *i;
                    if (nodex.position.X <= start_point.X && canTransfer(this, nodex, Direction.LEFT))
                    {
                        left = nodex;
                    }
                    else if (canTransfer(this, nodex, Direction.RIGHT))
                    {
                        right = nodex;
                        break;
                    }
                }

                if (left != null)
                {
                    createNode(out n, left);
                    ret = astarsearch.AddSuccessor(n);
                    if (!ret)
                    {
                        return(false);
                    }
                }

                if (right != null)
                {
                    createNode(out n, right);
                    ret = astarsearch.AddSuccessor(n);
                    if (!ret)
                    {
                        return(false);
                    }
                }

                return(true);
            }

            //if (mapNode.position.Y == end_point.Y && astarsearch.GetSolutionEnd().mapNode.floorNode != null)
            //{
            //  // Reached the same floor as end node, and end node is a floor node.
            //  // Add destination floor node
            //  if (mapNode.floorNode != null) return false; // ERROR: All transport nodes must contain pointer to their respective floor node.

            //  createNode(out n, mapNode.floorNode);
            //  ret = astarsearch.AddSuccessor(n);
            //  if (!ret) return false;
            //  else return true;
            //}

            MapNode node = mapNode.neighbours[(int)Direction.LEFT];

            while (node != null && left == null)
            {
                if (!canTransfer(this, node, Direction.LEFT))
                {
                    node = node.neighbours[(int)Direction.LEFT];
                    continue;
                }

                left = node;
            }

            node = mapNode.neighbours[(int)Direction.RIGHT];
            while (node != null && right == null)
            {
                if (!canTransfer(this, node, Direction.RIGHT))
                {
                    node = node.neighbours[(int)Direction.RIGHT];
                    continue;
                }

                right = node;
            }

            if (left != null)
            {
                createNode(out n, left);
                ret = astarsearch.AddSuccessor(n);
                if (!ret)
                {
                    return(false);
                }
            }

            if (right != null)
            {
                createNode(out n, right);
                ret = astarsearch.AddSuccessor(n);
                if (!ret)
                {
                    return(false);
                }
            }

            if (mapNode.neighbours[(int)Direction.UP] != null)
            {
                node = mapNode.neighbours[(int)Direction.UP];
                if (mapNode.HasElevator)
                {
                    while (node != null)
                    {
                        createNode(out n, node);
                        ret = astarsearch.AddSuccessor(n);
                        if (!ret)
                        {
                            return(false);
                        }
                        node = node.neighbours[(int)Direction.UP];
                    }
                }
                else if (canTransfer(this, node, Direction.UP))
                {
                    createNode(out n, node);
                    ret = astarsearch.AddSuccessor(n);
                    if (!ret)
                    {
                        return(false);
                    }
                }
            }

            if (mapNode.neighbours[(int)Direction.DOWN] != null)
            {
                node = mapNode.neighbours[(int)Direction.DOWN];
                if (mapNode.HasElevator)
                {
                    while (node != null)
                    {
                        createNode(out n, node);
                        ret = astarsearch.AddSuccessor(n);
                        if (!ret)
                        {
                            return(false);
                        }
                        node = node.neighbours[(int)Direction.DOWN];
                    }
                }
                else if (canTransfer(this, node, Direction.DOWN))
                {
                    createNode(out n, node);
                    ret = astarsearch.AddSuccessor(n);
                    if (!ret)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
Пример #3
0
 void createNode(out MapSearchNode n, MapNode node)
 {
     n              = new MapSearchNode(node);
     n.end_point    = end_point;
     n.serviceRoute = serviceRoute;
 }
Пример #4
0
        bool canTransfer(MapSearchNode start, MapNode dest, Direction dir)
        {
            /*
             *      Returns true if transfer to destination transport has not exceed transfer limits.
             *      Returns false otherwise.
             *      Maximum transfer limits are:
             *              2 elevators (no more than 1 elevator if journey has already used stairs or escalators)
             *              3 stairs
             *              6 escalators
             *              1 stair, 2 escalators OR 2 stairs, 1 escalator
             */

            if ((dir == Direction.UP || dir == Direction.DOWN))
            {
                // Once in an elevator node, travel is allowed for as many floors available in the elevator shaft
                if (start.mapNode.HasElevator)
                {
                    return(true);
                }

                // Hence we only check limits for stairlike travel
                if (start.mapNode.transportItems[(int)dir].Icon == 2)
                {
                    if (start.numStairs > 2 - start.numEscalators)
                    {
                        return(false);
                    }
                }
                else
                {
                    if (start.numEscalators > 5)
                    {
                        return(false);
                    }
                    if (start.numStairs > 0 && start.numEscalators > 2 - start.numStairs)
                    {
                        return(false);
                    }
                }
            }
            else
            {
                if (dest.HasElevator)
                {
                    if ((!start.serviceRoute && dest.HasServiceElevator) || (start.serviceRoute && !dest.HasServiceElevator))
                    {
                        return(false);
                    }
                    if (start.numElevators > 1)
                    {
                        return(false);
                    }
                    if (start.numElevators == 1 && (start.mapNode.position.Y % 15 != 0 || start.numStairs > 0 || start.numEscalators > 0))
                    {
                        return(false);
                    }
                }
                // Transit to other stairlike nodes (moving left/right) has no limits.
                // Limit only applies when actually using (moving up/down) the stairlike.
            }

            return(true);
        }
Пример #5
0
        public void removeNode(Slot slot, IPrototype item)
        {
            return;

            if (item is null)
            {
                return;
            }
            if (!(item is IHaulsPeople))
            {
                return;
            }
            if (!peopleMovementMap.ContainsKey(slot.ToString()))
            {
                return;
            }

            MapNode n = peopleMovementMap[slot.ToString()];


            // Update all neighour links
            if (item is IHaulsPeople && slot.Y == item.Position.Y)
            {
                n.neighbours[(int)Direction.UP].neighbours[(int)Direction.DOWN]     = null;
                n.neighbours[(int)Direction.UP].transportItems[(int)Direction.DOWN] = null;
                n.neighbours[(int)Direction.UP]     = null;
                n.transportItems[(int)Direction.UP] = null;
            }
            else if (item is Elevator)
            {
                n.HasElevator = false;
                if (item.Icon == (int)IconNumbers.ICON_ELEVATOR_SERVICE)
                {
                    n.HasServiceElevator = false;
                }

                // Link upper & lower floor node to skip this node
                if (n.neighbours[(int)Direction.UP] != null)
                {
                    n.neighbours[(int)Direction.UP].neighbours[(int)Direction.DOWN] = n.neighbours[(int)Direction.DOWN];
                    if (n.neighbours[(int)Direction.DOWN] == null)
                    {
                        n.neighbours[(int)Direction.UP].transportItems[(int)Direction.DOWN] = null;
                    }
                }

                if (n.neighbours[(int)Direction.DOWN] != null)
                {
                    n.neighbours[(int)Direction.DOWN].neighbours[(int)Direction.UP] = n.neighbours[(int)Direction.UP];
                    if (n.neighbours[(int)Direction.UP] == null)
                    {
                        n.neighbours[(int)Direction.DOWN].transportItems[(int)Direction.UP] = null;
                    }
                }

                n.neighbours[(int)Direction.UP]       = null;
                n.transportItems[(int)Direction.UP]   = null;
                n.neighbours[(int)Direction.DOWN]     = null;
                n.transportItems[(int)Direction.DOWN] = null;
            }



            // Delete and erase only if no other overlapping item
            if (!n.HasElevator && !n.HasServiceElevator &&
                n.transportItems[(int)Direction.UP] == null &&
                n.transportItems[(int)Direction.DOWN] == null)
            {
                if (n.neighbours[(int)MapNode.Direction.LEFT] != null)
                {
                    n.neighbours[(int)MapNode.Direction.LEFT].neighbours[(int)MapNode.Direction.RIGHT] = n.neighbours[(int)MapNode.Direction.RIGHT];
                }

                if (n.neighbours[(int)MapNode.Direction.RIGHT] != null)
                {
                    n.neighbours[(int)MapNode.Direction.RIGHT].neighbours[(int)MapNode.Direction.LEFT] = n.neighbours[(int)MapNode.Direction.LEFT];
                }

                peopleMovementMap.Remove(slot.ToString());

                var mnl = mapNodesByFloor[slot.Y];
                //mnl.Clear();
                mnl.ForEach(x => {
                    if (x == n)
                    {
                        x.Status = 1; // mark for deletion
                    }
                });
                mnl.RemoveAll(x => x.Status == 1); // using status lets delete
            }
        }
Пример #6
0
        public MapNode extendNode(Slot slotBeforeExtending, Slot sizeBeforeExtending, IPrototype itemAfterExtending)
        {
            (FloorNode f, MapNode n)ret = createFloorAndNodeIfApplicable(slotBeforeExtending, itemAfterExtending);

            if (itemAfterExtending is Elevator)
            {
                // Link to upper/lower floor node
                var e = (Elevator)itemAfterExtending;

                var expandedUp = itemAfterExtending.Position.Y > slotBeforeExtending.Y;
                if (expandedUp)
                {
                    var topIndex = itemAfterExtending.Position.Y;

                    if (!e.ConnectsToFloor(topIndex, sizeBeforeExtending.Y))
                    {
                        var     ep    = new Slot(itemAfterExtending.Position.X, topIndex);
                        MapNode upper = peopleMovementMap.ContainsKey(ep.ToString()) ? peopleMovementMap[ep.ToString()] : addNode(ep, itemAfterExtending);

                        ret.n.neighbours[(int)MapNode.Direction.UP]     = upper;
                        ret.n.transportItems[(int)MapNode.Direction.UP] = itemAfterExtending;

                        //if (upper.neighbours[(int)MapNode.Direction.DOWN] != null)
                        //{
                        //  ret.n.neighbours[(int)MapNode.Direction.DOWN] = upper.neighbours[(int)MapNode.Direction.DOWN];
                        //  ret.n.transportItems[(int)MapNode.Direction.DOWN] = itemAfterExtending;
                        //}

                        upper.neighbours[(int)MapNode.Direction.DOWN]     = ret.n;
                        upper.transportItems[(int)MapNode.Direction.DOWN] = itemAfterExtending;
                    }
                }
                else
                { //expanded down
                    var bottomIndex = itemAfterExtending.Position.Y - itemAfterExtending.Size.Y + 1;
                    var topIndex    = bottomIndex + 1;
                    if (!e.ConnectsToFloor(bottomIndex, sizeBeforeExtending.Y))
                    {
                        var     epLower = new Slot(itemAfterExtending.Position.X, bottomIndex);
                        var     epUpper = new Slot(itemAfterExtending.Position.X, topIndex);
                        MapNode lower   = peopleMovementMap.ContainsKey(epLower.ToString()) ? peopleMovementMap[epLower.ToString()] : addNode(epLower, itemAfterExtending);
                        MapNode upper   = peopleMovementMap.ContainsKey(epUpper.ToString()) ? peopleMovementMap[epUpper.ToString()] : addNode(epUpper, itemAfterExtending);

                        upper.neighbours[(int)MapNode.Direction.DOWN]     = lower;
                        upper.transportItems[(int)MapNode.Direction.DOWN] = itemAfterExtending;
                        //ret.n.neighbours[(int)MapNode.Direction.DOWN] = lower;
                        //ret.n.transportItems[(int)MapNode.Direction.DOWN] = itemAfterExtending;

                        //if (lower.neighbours[(int)MapNode.Direction.UP] != null)
                        //{
                        //  ret.n.neighbours[(int)MapNode.Direction.UP] = lower.neighbours[(int)MapNode.Direction.UP];
                        //  ret.n.transportItems[(int)MapNode.Direction.UP] = itemAfterExtending;
                        //}

                        lower.neighbours[(int)MapNode.Direction.UP]     = upper;
                        lower.transportItems[(int)MapNode.Direction.UP] = itemAfterExtending;
                    }
                }
            }

            return(ret.n);
        }
Пример #7
0
        public (FloorNode, MapNode) createFloorAndNodeIfApplicable(Slot slot, IPrototype item)
        {
            // Create corresponding FloorNode if not available
            FloorNode f;

            if (!floorNodes.ContainsKey(slot.Y))
            {
                if (!mapNodesByFloor.ContainsKey(slot.Y))
                {
                    mapNodesByFloor[slot.Y] = new List <MapNode>();
                }
                f = new FloorNode(mapNodesByFloor[slot.Y]);
                floorNodes[slot.Y] = f;
                f.position         = new Slot(int.MinValue, slot.Y);
            }
            else
            {
                f = floorNodes[slot.Y];
            }

            if (!(item is IHaulsPeople))
            {
                return(f, null);                     // Building item, do not add into transport
            }
            // Create/Get MapNode for above created floor
            MapNode n;

            if (!peopleMovementMap.ContainsKey(slot.ToString()))
            {
                n = new MapNode(f);
                peopleMovementMap[slot.ToString()] = n;
                n.position = slot;

                // Just insert node if list is empty
                if (mapNodesByFloor[slot.Y].Count == 0)
                {
                    mapNodesByFloor[slot.Y].Add(n);
                }
                else
                {
                    // Look for nearby nodes on same floor to insert
                    MapNode left  = null;
                    MapNode right = null;
                    foreach (MapNode node in mapNodesByFloor[slot.Y])
                    {
                        if (node.position.X < slot.X)
                        {
                            left = node;
                        }
                        else
                        {
                            right = node;
                            var nodeIndex = mapNodesByFloor[slot.Y].IndexOf(node);
                            mapNodesByFloor[slot.Y].Insert(nodeIndex, n);
                            break;
                        }
                    }

                    if (left != null)
                    {
                        if (right == null)
                        {
                            mapNodesByFloor[slot.Y].Add(n);    // Insert node as last node in list
                        }
                        n.neighbours[(int)MapNode.Direction.LEFT]     = left;
                        left.neighbours[(int)MapNode.Direction.RIGHT] = n;
                    }

                    if (right != null)
                    {
                        n.neighbours[(int)MapNode.Direction.RIGHT]    = right;
                        right.neighbours[(int)MapNode.Direction.LEFT] = n;
                    }
                }
            }
            else
            {
                n = peopleMovementMap[slot.ToString()];
            }

            return(f, n);
        }