public int GetOpenDirections() { var openDirections = (int)DirectionFlags.East | (int)DirectionFlags.North | (int)DirectionFlags.South | (int)DirectionFlags.West; // If the route is empty then all directions are open! if (!Route.Any()) { return(openDirections); } var x = StartX; var y = StartY; foreach (var direction in _route.FastReverse()) { if (DirectionFlagsHelper.HasDirectionFlag(openDirections, DirectionFlags.North) && x == EndX && y == EndY + 1) { openDirections = DirectionFlagsHelper.UnsetDirectionFlag(openDirections, DirectionFlags.North); } if (DirectionFlagsHelper.HasDirectionFlag(openDirections, DirectionFlags.South) && x == EndX && y == EndY - 1) { openDirections = DirectionFlagsHelper.UnsetDirectionFlag(openDirections, DirectionFlags.South); } if (DirectionFlagsHelper.HasDirectionFlag(openDirections, DirectionFlags.East) && x == EndX + 1 && y == EndY) { openDirections = DirectionFlagsHelper.UnsetDirectionFlag(openDirections, DirectionFlags.East); } if (DirectionFlagsHelper.HasDirectionFlag(openDirections, DirectionFlags.West) && x == EndX - 1 && y == EndY) { openDirections = DirectionFlagsHelper.UnsetDirectionFlag(openDirections, DirectionFlags.West); } // If we're out of open directions we can go there's no need to continue checking and just return nothing if (openDirections == 0) { break; } } return(openDirections); }
public void ProcessBreadthSearchQueueItem(Queue <GetRouteSearchParams> searchQueue, GetRouteSearchParams searchParameters, Dictionary <int, IGameMapMovementRoute> routesFound, IGameUnit unit, int availableMovement) { // still wonderin' if (searchParameters.Direction == Direction.None) { return; } // We need to find what tiles we're going to check the movement cost for. Since units cover multiple tiles they have both an area we need to calculate and the edge of the unit we're looking for var targetX = searchParameters.BaseRoute.EndX; var targetY = searchParameters.BaseRoute.EndY; if (searchParameters.Direction == Direction.East) { targetX += unit.TileWidth; } else if (searchParameters.Direction == Direction.West) { targetX -= 1; } else if (searchParameters.Direction == Direction.North) { targetY += unit.TileHeight; } else if (searchParameters.Direction == Direction.South) { targetY -= 1; } // Grab the area that we're going to check var areaWidth = DirectionHelper.DirectionVertical(searchParameters.Direction) ? unit.TileWidth : 1; var areaHeight = DirectionHelper.DirectionHorizontal(searchParameters.Direction) ? unit.TileHeight : 1; // Get the movement cost for this unit to move this direction by one tile var movementCost = AreaMovementCostForUnit(unit, targetX, targetY, areaWidth, areaHeight); // If the movement cost is IMPASSIBLE or exceeds our available movement then this movement isn't possible var totalCost = Mathf.CeilToInt(searchParameters.BaseRoute.RouteCost.Cost + movementCost.Cost); // we do this just as a check here, movement cost can be fractional (TODO: there is a bug here, check half steps logic) if (!movementCost.IsPassable || totalCost > availableMovement) { return; } // If it is possible to make this movement then we can create a new route for it! var routeHere = searchParameters.BaseRoute.CreateExtendRoute(searchParameters.Direction, movementCost); // See if we have an existing route to this ending X,Y if (routesFound.ContainsKey(routeHere.EndSortKey)) { var compare = GameMapMovementRouteComparer.Instance.Compare(routeHere, routesFound[routeHere.EndSortKey]); if (compare < 0) { routesFound[routeHere.EndSortKey] = routeHere; } else if (compare > 0) { return; } else { return; // collision strat: drop latest } } else { routesFound.Add(routeHere.EndSortKey, routeHere); } // Find which directions don't overlap the current route var openDirections = routeHere.GetOpenDirections(); // Then add each non-overlapping direction to our queue of searches to perform with this current route if (searchParameters.Direction != Direction.North && DirectionFlagsHelper.HasDirectionFlag(openDirections, DirectionFlags.South)) { searchQueue.Enqueue(new GetRouteSearchParams(routeHere, Direction.South)); } if (searchParameters.Direction != Direction.South && DirectionFlagsHelper.HasDirectionFlag(openDirections, DirectionFlags.North)) { searchQueue.Enqueue(new GetRouteSearchParams(routeHere, Direction.North)); } if (searchParameters.Direction != Direction.East && DirectionFlagsHelper.HasDirectionFlag(openDirections, DirectionFlags.West)) { searchQueue.Enqueue(new GetRouteSearchParams(routeHere, Direction.West)); } if (searchParameters.Direction != Direction.West && DirectionFlagsHelper.HasDirectionFlag(openDirections, DirectionFlags.East)) { searchQueue.Enqueue(new GetRouteSearchParams(routeHere, Direction.East)); } }