@VisibleForTesting void addDestinationPointInternal(Point2D newPoint, boolean isCity) { synchronized (lock) { if (!heuristic.containsKey(newPoint)) { heuristicProvider.addSourceNodeToHeuristic(newPoint); // once reached there we must leave again. heuristicProvider.addTargetNodeToHeuristic(newPoint); heuristicProvider.getHeuristic(); } Preconditions.checkArgument(heuristic.containsKey(newPoint), "Destination not part of the heuristic: "+newPoint); if (graph.containsNode(newPoint)) { return; } List<Point2D> nearest = new ArrayList<>(); for (Point2D node : graph) { double distance = node.distance(newPoint); if (distance <= DIAG_CHECK_DISTANCE) { nearest.add(node); } } graph.addNode(newPoint, true); for (Point2D point : nearest) { addEdges(newPoint, point, isCity, false); } } } @VisibleForTesting
/** * Add a new target node to the heuristic. * @param source location to be added. */ public void addSourceNodeToHeuristic(Point2D source) { Preconditions.checkNotNull(source, "The source node may not be null"); if (!heuristicForSourceAvailable(source)) { synchronized (lock) { ObjectDoubleMap<Point2D> hueristicForTarget = calculateHeuristicForSource(source, map.getCities()); heuristicMap.put(source, hueristicForTarget); } } else { logger.debug("Heuristic for source point {} is available (point is contained as key)", source); } } /**
/** * Add a new target node to the heuristic. * @param target location to be added. */ public void addTargetNodeToHeuristic(Point2D target) { Preconditions.checkNotNull(target, "The target node may not be null"); synchronized (lock) { for (Entry<Point2D, ObjectDoubleMap<Point2D>> entry : heuristicMap.entrySet()) { if (!entry.getValue().containsKey(target)) { Point2D source = entry.getKey(); double dist = calculateWeight(source, target); entry.getValue().put(target, dist); } } } }
@VisibleForTesting void createGraph() { long timestamp = System.currentTimeMillis(); synchronized (lock) { List<ICity> cities = map.getCities(); for (ICity city : cities) { ObjectDoubleMap<Point2D> hueristicForTarget = calculateHeuristicForSource(city.getCoordinates(), cities); heuristicMap.put(city.getCoordinates(), hueristicForTarget); } for (int x = 0; x < width; x += CHECK_DISTANCE) { // TODO: andi 1/3/16 split to different threads for (int y = 0; y < height; y += CHECK_DISTANCE) { Point2D source = getPoint(x, y); ObjectDoubleMap<Point2D> hueristicForTarget = calculateHeuristicForSource(source, cities); heuristicMap.put(source, hueristicForTarget); } } } long took = System.currentTimeMillis() - timestamp; logger.debug("Created heuristic for "+heuristicMap.size()+" sources connecting to "+heuristicMap.values().iterator().next().size()+" nodes taking "+took+"ms"); clientServerEventBus.post(new HeuristicGraphInitialisationComplete()); initializing = false; }
} /** * Select a new destination for the pirate. * @param pirate free sea pirate */ private void selectDestination(ISeaPirate pirate) { Point2D destination; if (pirate instanceof INonFreeSeaPirate && ((INonFreeSeaPirate) pirate).roamingNearCity().isPresent()) { ICity city = ((INonFreeSeaPirate) pirate).roamingNearCity().get(); destination = mapService.getRandomPointAtSeaNear(city.getCoordinates()); } else { destination = mapService.getLocationAtOtherEndOfMap(pirate.getShip().getLocation()); } // make sure that the source of the pirate location is in the graph Point2D adjustedDestination = aStarHeuristicProvider.findClosest(destination); aStarHeuristicProvider.addTargetNodeToHeuristic(adjustedDestination); logger.debug("Source point of pirate is {}", pirate.getShip().getLocation()); seafaringService.travelNotBetweenCities(pirate.getShip(), adjustedDestination); }
/** * Find the closest point in the graph for a defined point. * @param point for which the closest defined point should be looked up. * @return closest point to <code>point</code> */ public Point2D findClosest(Point2D point) { double distance = Double.MAX_VALUE; Point2D p = null; for (Point2D tempPoint : getHeuristic().keySet()) { if (point.distance(tempPoint) < distance) { distance = point.distance(tempPoint); p = tempPoint; } } return p; }
@Subscribe public void registerGameLoad(GameStateChange gameStateChange) { if (!initializing && gameStateChange.getStatusChange() == EGameStatusChange.GAME_LOADED) { logger.info("Initialize heuristic after game load."); initialize(); } } @VisibleForTesting
@PostConstruct private void initialize() { initializing = true; try { // as well, which means it needs to be reset first initImage(); serverThreadPool.execute(this::createGraph); } catch (IOException e) { logger.error("Failed to create black and white image from the map", e); initializing = false; } clientServerEventBus.register(this); } @Subscribe
@VisibleForTesting void addSourcePointInternal(Point2D source, boolean isCity) { synchronized (lock) { if (!heuristic.containsKey(source)) { heuristicProvider.addSourceNodeToHeuristic(source); } if (graph.containsNode(source)) { return; } List<Point2D> nearest = new ArrayList<>(); for (Point2D node : graph) { double distance = node.distance(source); if (distance <= DIAG_CHECK_DISTANCE) { nearest.add(node); } } graph.addNode(source, false); for (Point2D point : nearest) { addEdges(source, point, isCity, false); } } } @Override
/** * Handle the even when a new pirate becomes available. * @param pirateEvent new pirate emerged */ @Subscribe public void handleNewPirate(NewPirateEvent pirateEvent) { IShip ship = (IShip) pirateEvent.getPirate().getShip(); Point2D adjustedSource = aStarHeuristicProvider.findClosest(ship.getLocation()); ship.setLocation(adjustedSource); selectDestination(pirateEvent.getPirate()); }
long timestamp = System.currentTimeMillis(); synchronized (lock) { heuristic = heuristicProvider.getHeuristic(); while(heuristic.size() == 0) { Thread.yield(); heuristic = heuristicProvider.getHeuristic();
private void addEdges(Point2D from, Point2D to, boolean isCity, boolean initial) { if (isCity || isOnSea(to)) { if (!graph.containsNode(to)) { if (initial) { graph.addNodeInternal(to); } else { graph.addNode(to, true); } } heuristicProvider.getHeuristic(); double weight = calculateWeight(from, to); if (initial) { graph.addEdgeInternal(from, to, weight); } else { graph.addEdge(from, to, weight); } weight = calculateWeight(to, from); if (initial) { graph.addEdgeInternal(to, from, weight); } else { graph.addEdge(to, from, weight); } } }
private ObjectDoubleMap<Point2D> calculateHeuristicForSource(Point2D source, List<ICity> cities) { ObjectDoubleMap<Point2D> distance = new ObjectDoubleScatterMap<>(); for (ICity city : cities) { final Point2D coordinates = city.getCoordinates(); double dist = calculateWeight(source, coordinates); distance.put(coordinates, dist); } return distance; } @VisibleForTesting