ch.sahits.game.openpatrician.engine.player.strategy.DynamicTradeRouteStrategy Maven / Gradle / Ivy
package ch.sahits.game.openpatrician.engine.player.strategy;
import ch.sahits.game.openpatrician.clientserverinterface.service.ShipService;
import ch.sahits.game.openpatrician.engine.player.DynamicTradeRouteMissionData;
import ch.sahits.game.openpatrician.engine.player.tradesteps.TravelToTradeStep;
import ch.sahits.game.openpatrician.model.IAIPlayer;
import ch.sahits.game.openpatrician.model.city.ICity;
import ch.sahits.game.openpatrician.model.event.IShipEntersPortEvent;
import ch.sahits.game.openpatrician.model.player.IProductionConsumptionKnowledge;
import ch.sahits.game.openpatrician.model.product.EWare;
import ch.sahits.game.openpatrician.model.product.IWare;
import ch.sahits.game.openpatrician.model.ship.INavigableVessel;
import ch.sahits.game.openpatrician.utilities.annotation.ClassCategory;
import ch.sahits.game.openpatrician.utilities.annotation.EClassCategory;
import ch.sahits.game.openpatrician.utilities.annotation.LazySingleton;
import com.google.common.annotations.VisibleForTesting;
import javafx.geometry.Point2D;
import javafx.util.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.TreeMap;
/**
* Trade strategy to buy certain wares (wine, spices, fur or fish oil) and then sell them until none is left.
* @author Andi Hotz, (c) Sahits GmbH, 2017
* Created on Oct 27, 2017
*/
@LazySingleton
@ClassCategory(EClassCategory.SINGLETON_BEAN)
public class DynamicTradeRouteStrategy extends BasePlayerTradeStrategy {
private final static IWare[] tradableWares = new IWare[]{EWare.WINE, EWare.SPICE, EWare.FUR, EWare.FISH_OIL};
@Autowired
private ShipService shipService;
@Override
public void initializeTradeCycle(IAIPlayer player, INavigableVessel vessel) {
// find closest city having producing one of the tradable wares.
Pair pair = findClosestCityProducingTradableWare(player, vessel);
Optional optCity = shipService.findCity(vessel);
if (optCity.isPresent()) {
if (optCity.get().equals(pair.getKey())) { // in start city
handleBuyWaresInStartCity(player, vessel, optCity.get());
} else { // in different city
handleBuyWaresReturnToStartCity(player, vessel, optCity.get(), pair.getKey());
}
} else {
TravelToTradeStep travelTo = createTravelToStep(vessel, pair.getKey());
append(player, vessel, travelTo);
}
DynamicTradeRouteMissionData missionData = new DynamicTradeRouteMissionData();
missionData.setWare(pair.getValue());
player.setTradeMission(vessel, missionData);
}
@VisibleForTesting
void handleBuyWaresInStartCity(IAIPlayer player, INavigableVessel vessel, ICity city) {
IProductionConsumptionKnowledge globalKnowledge = player.getProductionAndConsumptionKnowledge();
DynamicTradeRouteMissionData missionData = (DynamicTradeRouteMissionData) player.getTradeMission(vessel);
ICity nextStop = findNextStopForBuying(city, globalKnowledge, Collections.singletonList(missionData.getWare()), vessel, city);
HashSet buyWares = new HashSet<>();
buyWares.add(missionData.getWare());
addDefaultTradeSteps(vessel, player, city, nextStop, new HashSet<>(), buyWares, false);
}
@VisibleForTesting
void handleBuyWaresReturnToStartCity(IAIPlayer player, INavigableVessel vessel, ICity city, ICity startCity) {
addDefaultTradeSteps(vessel, player, city, startCity, new HashSet<>(), new HashSet<>(), false);
}
@VisibleForTesting
Pair findClosestCityProducingTradableWare(IAIPlayer player, INavigableVessel vessel) {
TreeMap> distances = new TreeMap<>();
Point2D location = vessel.getLocation();
for (IWare ware : tradableWares) {
ICity city = findCitySupplyingWare(player, ware, vessel, new HashSet<>());
double distance = location.distance(city.getCoordinates());
Pair pair = new Pair<>(city, ware);
distances.put(distance, pair);
}
return distances.pollFirstEntry().getValue();
}
@Override
public void handleShipArrivesInPort(IShipEntersPortEvent event) {
INavigableVessel vessel = event.getShip();
if (isMatchingTradeStrategy(vessel)) {
IAIPlayer player = (IAIPlayer) vessel.getOwner();
ICity city = event.getCity();
IProductionConsumptionKnowledge globalKnowledge = player.getProductionAndConsumptionKnowledge();
DynamicTradeRouteMissionData missionData = (DynamicTradeRouteMissionData) player.getTradeMission(vessel);
int wareAmount = vessel.getWare(missionData.getWare()).getAmount();
if (wareAmount > 0) { // TODO: andi 10/27/17 when selling all wares in this city we still travel one further: #631
List wareOfInterest = Collections.singletonList(missionData.getWare());
ICity nextStop = findNextStopForSelling(city, globalKnowledge, wareOfInterest, vessel, city);
addDefaultTradeSteps(vessel, player, city, nextStop, new HashSet<>(), new HashSet<>(), false);
} else {
Pair pair = findClosestCityProducingTradableWare(player, vessel);
missionData.setWare(pair.getValue());
handleBuyWaresReturnToStartCity(player, vessel, city, pair.getKey());
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy