private void updatePirateAttackStatistic(List<IShip> defendingShips, List<IShip> sunkenDefendingShips, List<IShip> capturedDefendingShips, IShipOwner attacker) { boolean won = defendingShips.size() - capturedDefendingShips.size() - sunkenDefendingShips.size() <= 0; PirateActivityEntry entry = PirateActivityEntry.builder() .pirate((ISeaPirate) attacker) .enteredShips(capturedDefendingShips.size()) .sukenShips(sunkenDefendingShips.size()) .lootedShips(0) // TODO: andi 10/17/17 implement looting. .fightWon(won) .build(); pirateActivity.add(entry); }
/** * Retrieve the number of pirate attacks where the victim suffered. * @return number of successful pirate attacks */ public int getNumberOfSuccessfulPirateAttacks(List<PirateActivityEntry> activities) { return (int) activities.stream() .filter(PirateActivityEntry::isFightWon) .filter(attack -> attack.getEnteredShips() > 0 || attack.getLootedShips() > 0 || attack.getSukenShips() > 0) .count(); } }
NodeData<Point2D> sourceNodeData = graph.getNodeData(source); sourceNodeData.setG(source, 0); sourceNodeData.calcF(destination, source); openQueue.add(sourceNodeData); logger.trace("Inspect node: {}", nodeData.getNodeId()); if (nodeData.getNodeId().equals(destination)) { // termination pathList = path(path, destination); Map<Point2D, List<Point2D>> sourceMap = pathCache.get(destination); ObjectDoubleMap<NodeData<Point2D>> map = graph.edgesFrom(nodeData.getNodeId()); for (ObjectDoubleCursor<NodeData<Point2D>> neighborEntry : map) { NodeData<Point2D> neighbor = neighborEntry.key; double tentativeG = distanceBetweenTwoNodes + nodeData.getG(source); // guess distance to source if (tentativeG <= neighbor.getG(source)) { // distance to the source is smaller than to for the previous node neighbor.setG(source, tentativeG); neighbor.calcF(destination, source); path.put(neighbor.getNodeId(), nodeData.getNodeId()); if (!openQueue.contains(neighbor)) { openQueue.add(neighbor); logger.trace("Add neighbor {}", neighbor.getNodeId()); sb.append("Partial path: "); for (NodeData<Point2D> nodeData : closedList) { sb.append(nodeData.getNodeId()).append(" ");
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); } } }
@Override public int calculateRequiredSailorAmount(IShip ship, IAIPlayer player) { int min = ship.getMinNumberOfSailors(); int max = ship.getMaxNumberOfSailors(); int range = max - min; List<PirateActivityEntry> activity = pirateActivity.getPirateActivity(); int observationDuration = pirateActivity.getObservationPeriodInDays(); int nbAttacks = dangerService.getNumberOfPirateAttacks(activity); double twoWeeks = observationDuration / 14.0; double attacksInTwoWeeks = twoWeeks / nbAttacks; if (attacksInTwoWeeks > 1) { // There should be one attack in two weeks return min; } if (attacksInTwoWeeks > 0.5) { // there should be one attack in four weeks / or half an attack in two return rnd.nextInt(range) + min; } return max; } }
@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
/** * Retrieve the most recent pirate activities. * @return list of {@link PirateActivityEntry} */ public List<PirateActivityEntry> getPirateActivity() { clearCache(); return new ArrayList<>(map.values()); }
/** * Count the number of distinct pirates. * @return number of free sea pirates. */ public int getNumberOfPirates(List<PirateActivityEntry> activities) { Map<ISeaPirate, Integer> counter = new HashMap<>(); for (PirateActivityEntry activity : activities) { ISeaPirate pirate = activity.getPirate(); if (counter.containsKey(pirate)) { counter.put(pirate, counter.get(pirate) + 1); } else { counter.put(pirate, 1); } } return counter.size(); }
/** * Adds a new node to the graph. This is used internally in the initial creation where all nodes * are added but only the target nodes have heuristic. * Internally it creates the nodeData and populates the heuristic map concerning input node into node data. * * @param nodeId the node to be added */ public void addNodeInternal(T nodeId) { Preconditions.checkNotNull(nodeId, "The node id cannot be null"); graph.put(nodeId, new ObjectDoubleScatterMap<>()); nodeIdNodeData.put(nodeId, new NodeData<>(nodeId, heuristicMap.get(nodeId))); }
/** * Adds a new node to the graph. * Internally it creates the nodeData and populates the heuristic map concerning input node into node data. * * @param nodeId the node to be added * @param isTargetNode flag indicatin the the node is a target node. Only target nodes are contained in the heuristic. */ public void addNode(T nodeId, boolean isTargetNode) { Preconditions.checkNotNull(nodeId, "The node id cannot be null"); if (!isTargetNode) { if (!heuristicMap.containsKey(nodeId)) throw new NoSuchElementException("This node (" + nodeId + ") is not a part of hueristic map"); } addNodeInternal(nodeId); // graph.put(nodeId, new HashMap<>()); // nodeIdNodeData.put(nodeId, new NodeData<>(nodeId, heuristicMap.get(nodeId))); } /**
public void calcF(T destination, T source) { if (heuristic == null) { LOGGER.warn("Heuristic is null"); } if (!heuristic.containsKey(destination)) { LOGGER.warn("Destination ({}) for source {} not available", destination, source); } this.h = heuristic.get(destination); this.f = getG(source) + h; }
/** * Handle the update of damage to the ship. * @param value vessel data that needs to be updated with the distance that is not yet considered in the damage * @param vessel that should be damaged * @param travelPerTick number of pixels that were traveled. */ @VisibleForTesting void updateShipDamage(VesselPositionUpdateData value, INavigableVessel vessel, double travelPerTick) { double distanceInKm = mapService.convertToDistenceInKm(travelPerTick); double distanceSinceLastDamageUpdate = value.getTraveledDistanceSinceLastDamageUpdate() + distanceInKm; if (vessel instanceof IShip) { IShip ship = (IShip) vessel; damageShip(value, distanceSinceLastDamageUpdate, ship); } else if (vessel instanceof IGroupableVessel){ for (IShip ship : ((IGroupableVessel) vessel).getShips()) { // The traveled distance since the last update is determined by the last ship damageShip(value, distanceSinceLastDamageUpdate, ship); } } }
@PostConstruct protected void register() { clientServerEventBus.register(this); super.register(); pause(new PauseGame()); } @PreDestroy
/** * Update the damage of the ship that is taken by traveling. * @param value vessel data that needs to be updated with the distance that is not yet considered in the damage * @param distanceSinceLastDamageUpdate traveled distance in km since the last update of the damage * @param ship instance of the ship that is to be damaged. */ private void damageShip(VesselPositionUpdateData value, double distanceSinceLastDamageUpdate, IShip ship) { int kmPerDamage = ship.getDistanceInKmForOneHealthPointReduction(); if (distanceSinceLastDamageUpdate > kmPerDamage) { int damagePoint = calculateDamagePoints(kmPerDamage, distanceSinceLastDamageUpdate); ship.damage(damagePoint, false); double remainingDistance = distanceSinceLastDamageUpdate - (damagePoint * kmPerDamage); value.setTraveledDistanceSinceLastDamageUpdate(remainingDistance); } else { value.setTraveledDistanceSinceLastDamageUpdate(distanceSinceLastDamageUpdate); } }
private void ensureSetup(Point2D source, Point2D destination) { if (!graph.containsNode(source)) { boolean isCity = false; for (ICity city : map.getCities()) { if (source.equals(city.getCoordinates())) { isCity = true; break; } } // graphProvider.addSourcePoint(source, isCity); graphProvider.addDestinationPoint(source, isCity); } if (!graph.containsNode(destination)) { boolean isCity = false; for (ICity city : map.getCities()) { if (destination.equals(city.getCoordinates())) { isCity = true; break; } } graphProvider.addDestinationPoint(destination, isCity); } graphProvider.getGraph(); }
@Override public boolean shouldUpgrade(IShip ship) { if (ship.getShipUpgradeLevel() == EShipUpgrade.LEVEL2) { return false; } int weaponsStrength = shipService.calculateShipsWeaponsStrength(ship); List<PirateActivityEntry> attacks = pirateActivity.getPirateActivity(); int observationDuration = pirateActivity.getObservationPeriodInDays(); int nbAttacks = dangerService.getNumberOfPirateAttacks(attacks); double twoWeeks = observationDuration / 14.0; double attacksInTwoWeeks = twoWeeks / nbAttacks; if (attacksInTwoWeeks > 1) { // There should be one attack in two weeks if (weaponsStrength < 4) { return true; } } if (attacksInTwoWeeks > 0) { // there should be one attack in four weeks / or half an attack in two return weaponsStrength < 6; } return false; }
@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
int numberOfFreeSlots = getNumberOfEmptyWeaponSlots(ship); // also number of free small slots int numberOfFreeLargeSlots = getNumberOfEmptyLargeWeaponSlots(ship); List<PirateActivityEntry> attacks = pirateActivity.getPirateActivity(); int numberOfAttacks = dangerService.getNumberOfSuccessfulPirateAttacks(attacks); int limitNumberOfFewAttacks = pirateActivity.getObservationPeriodInDays() / 14; // one attack every 2 weeks if (numberOfAttacks > limitNumberOfFewAttacks && numberOfFreeSlots > 0 && cash > CASH_LIMIT && ship.getCapacity() > 0) { int nbHandWeapons = Math.max(0, ship.getNumberOfSailors() - ship.getWeaponAmount(EWeapon.HAND_WEAPON));
int numberOfFreeSlots = getNumberOfEmptyWeaponSlots(ship); // also number of free small slots int numberOfFreeLargeSlots = getNumberOfEmptyLargeWeaponSlots(ship); List<PirateActivityEntry> attacks = pirateActivity.getPirateActivity(); int numberOfAttacks = dangerService.getNumberOfPirateAttacks(attacks); int limitNumberOfFewAttacks = pirateActivity.getObservationPeriodInDays() / 14; // one attack every 2 weeks if (numberOfAttacks > limitNumberOfFewAttacks && numberOfFreeSlots > 0 && cash > CASH_LIMIT && ship.getCapacity() > 0) { int nbHandWeapons = Math.max(0, ship.getNumberOfSailors() - ship.getWeaponAmount(EWeapon.HAND_WEAPON));