예제 #1
0
        public float GoalDistanceEstimate(MapSearchNode nodeGoal)
        {
            if (nodeGoal.mapNode.floorNode != null)
            {
                if (mapNode.floorNode != null)
                {
                    h = (float)(Math.Abs(end_point.Y - mapNode.position.Y) * FLOOR_COST);
                }
                else
                {
                    h = (float)(Math.Abs(end_point.X - mapNode.position.X) * WALKING_COST + Math.Abs(end_point.Y - mapNode.position.Y) * FLOOR_COST);
                }
            }
            else
            {
                if (mapNode.floorNode != null)
                {
                    h = (float)(Math.Abs(nodeGoal.mapNode.position.X - start_point.X) * WALKING_COST + Math.Abs(nodeGoal.mapNode.position.Y - start_point.Y) * FLOOR_COST);
                }
                else
                {
                    h = (float)(Math.Abs(nodeGoal.mapNode.position.X - mapNode.position.X) * WALKING_COST + Math.Abs(nodeGoal.mapNode.position.Y - mapNode.position.Y) * FLOOR_COST);
                }
            }

            return(h);
        }
예제 #2
0
        public Route FindRoute(MapNode start_mapnode, MapNode end_mapnode, Item.Item start_item, Item.Item end_item, bool serviceRoute)
        {
            Slot start_point = new Slot(start_item.Position.X + ((IPrototype)start_item).Size.X, start_mapnode.position.Y);
            Slot end_point   = new Slot(end_item.Position.X + ((IPrototype)end_item).Size.X, end_mapnode.position.Y);

            MapSearchNode nodeStart = new MapSearchNode(start_mapnode);

            nodeStart.parent_item  = start_item;
            nodeStart.start_point  = start_point;
            nodeStart.end_point    = end_point;
            nodeStart.serviceRoute = serviceRoute;
            MapSearchNode nodeEnd = new MapSearchNode(end_mapnode);

            astarsearch.SetStartAndGoalStates(nodeStart, nodeEnd);

            int SearchSteps = 0;

            do
            {
                SearchState = astarsearch.SearchStep();
                SearchSteps++;
            } while (SearchState == AStarPathfinder.SearchState.Searching);

            Route r = new Route();

            buildRoute(r, start_item, end_item);
            clear();

            return(r);
        }
예제 #3
0
 public bool IsGoal(MapSearchNode nodeGoal)
 {
     if (mapNode == nodeGoal.mapNode)
     {
         nodeGoal.g = g;
         nodeGoal.h = h;
         return(true);
     }
     else
     {
         return(false);
     }
 }
예제 #4
0
        private Item.Item getItemOnRoute(MapSearchNode successor)
        {
            // NOTE: Calling this on the start and end nodes will not give correct results.
            // Always use known start and destination items instead.

            MapNode s_mapnode;

            if (successor != null || successor.mapNode != null)
            {
                return(null);
            }
            else
            {
                s_mapnode = successor.mapNode;
            }

            if (mapNode.neighbours[(int)Direction.UP] == s_mapnode)
            {
                return((Item.Item)mapNode.transportItems[(int)Direction.UP]);
            }
            else if (mapNode.neighbours[(int)Direction.DOWN] == s_mapnode)
            {
                return((Item.Item)mapNode.transportItems[(int)Direction.DOWN]);
            }
            else if (mapNode.transportItems[(int)Direction.UP] != null && mapNode.transportItems[(int)Direction.UP] == s_mapnode.transportItems[(int)Direction.DOWN])
            {
                return((Item.Item)mapNode.transportItems[(int)Direction.UP]);
            }
            else if (mapNode.transportItems[(int)Direction.DOWN] != null && mapNode.transportItems[(int)Direction.DOWN] == s_mapnode.transportItems[(int)Direction.UP])
            {
                return((Item.Item)mapNode.transportItems[(int)Direction.DOWN]);
            }
            else
            {
                return(null);
            }
        }
예제 #5
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);
        }
예제 #6
0
 void createNode(out MapSearchNode n, MapNode node)
 {
     n              = new MapSearchNode(node);
     n.end_point    = end_point;
     n.serviceRoute = serviceRoute;
 }
예제 #7
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);
        }
예제 #8
0
        public float GetCost(MapSearchNode successor)
        {
            Item.Item i = getItemOnRoute(successor); // Discover item that lies on this node, given the next step
            successor.parent_item   = i;
            successor.numStairs     = numStairs;
            successor.numEscalators = numEscalators;
            successor.numElevators  = numElevators;
            successor.g             = g;

            int traverse_cost = 0;

            if (i != null)
            {
                // NULL item. Next step is traversal on current floor.
                if (mapNode.position.Y == 0 && successor.mapNode.position.Y == 0)
                {
                    traverse_cost = 0;                                              // Movement in main lobby is free(?)
                }
                else if (mapNode.floorNode != null && start_point.X > int.MinValue) // This is a floor start node, use start_point to compute cost instead
                {
                    traverse_cost = Math.Abs(successor.mapNode.position.X - start_point.X) * WALKING_COST;
                }
                else if (successor.mapNode.floorNode != null && mapNode.position.Y == end_point.Y)
                {
                    // Successor is a floor end node, use end_point to compute cost instead
                    int end_walking_dist = Math.Abs(end_point.X - mapNode.position.X);

                    // Check if final transport node is too far away from destination, and adjust cost accordingly
                    if (end_walking_dist > MAX_WALKING_DIST)
                    {
                        traverse_cost = (int)(MAX_WALKING_DIST * WALKING_COST + (float)end_walking_dist / MAX_WALKING_DIST * INHIBITORY_COST);
                    }
                    else
                    {
                        traverse_cost = end_walking_dist * WALKING_COST;
                    }
                }
                else
                {
                    traverse_cost = Math.Abs(successor.mapNode.position.X - mapNode.position.X) * WALKING_COST;
                }
            }
            else if (i is IHaulsPeople && !(i is Elevator))
            {
                if (((IPrototype)i).Icon == 2)
                {
                    traverse_cost += STAIRS_COST;
                    successor.numStairs++;
                }
                else
                {
                    traverse_cost += ESCALATOR_COST;
                    successor.numEscalators++;
                }

                traverse_cost += FLOOR_COST;
            }
            else if (i is Elevator)
            {
                if (i != parent_item)
                {
                    // NOTE: In future when hotel rooms are implemented,
                    // there will need to be another check here to include Service elevator costs.
                    if (((IPrototype)i).Icon == 4)
                    {
                        traverse_cost += ELEVATOR_COST;
                    }
                    else
                    {
                        traverse_cost += EXPRESS_COST;
                    }
                    successor.numElevators++;
                }

                traverse_cost += Math.Abs(successor.mapNode.position.Y - mapNode.position.Y) * FLOOR_COST;
            }
            else
            {
                traverse_cost = INHIBITORY_COST; // ERROR: Should not end up here. INHIBITORY_COST should deter further expansion from this node.
            }
            successor.g += (float)traverse_cost;
            return((float)traverse_cost);
        }
예제 #9
0
 public bool IsSameState(MapSearchNode rhs)
 {
     return(mapNode == rhs.mapNode);
 }