All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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