ch.sahits.game.openpatrician.engine.player.strategy.SupplyHometownAIStrategy 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.SupplyCityMissionData;
import ch.sahits.game.openpatrician.engine.player.tradesteps.AggregatedCheckedBuyTradeStep;
import ch.sahits.game.openpatrician.engine.player.tradesteps.AggregatesDumpTradeStep;
import ch.sahits.game.openpatrician.engine.player.tradesteps.AggregatesSellTradeStep;
import ch.sahits.game.openpatrician.engine.player.tradesteps.BuyWeaponTradeStep;
import ch.sahits.game.openpatrician.engine.player.tradesteps.CheckForRepairTradeStep;
import ch.sahits.game.openpatrician.engine.player.tradesteps.CheckHireCaptainTradeStep;
import ch.sahits.game.openpatrician.engine.player.tradesteps.GuildJoinTradeStep;
import ch.sahits.game.openpatrician.engine.player.tradesteps.HireDismissTradeManagerTradeStep;
import ch.sahits.game.openpatrician.engine.player.tradesteps.HireSailorsStep;
import ch.sahits.game.openpatrician.engine.player.tradesteps.PayBackLoanTradeStep;
import ch.sahits.game.openpatrician.engine.player.tradesteps.TakeLoanTradeStep;
import ch.sahits.game.openpatrician.engine.player.tradesteps.TransferToOfficeTradeStep;
import ch.sahits.game.openpatrician.engine.player.tradesteps.TravelToTradeStep;
import ch.sahits.game.openpatrician.engine.player.tradesteps.UpgradeShipTradeStep;
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.ICityProductionConsumptionKnowledge;
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 com.google.common.base.Preconditions;
import com.google.common.eventbus.AsyncEventBus;
import javafx.util.Pair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
* AI strategy for trading with the aim to supply the players home town.
*/
@LazySingleton
@ClassCategory(EClassCategory.SINGLETON_BEAN)
public class SupplyHometownAIStrategy extends BasePlayerTradeStrategy {
private final Logger logger = LogManager.getLogger(getClass());
@Autowired
@Qualifier("serverClientEventBus")
private AsyncEventBus clientServerEventBus;
@Autowired
private ShipService shipService;
@Value("${aiplayer.money.low}")
private int lowMoney = 2000;
@Autowired
private ApplicationContext context;
public SupplyHometownAIStrategy() {
this.tradeStrategyType = EAITradeStrategyType.SUPPLY_HOMETOWN;
}
@PostConstruct
private void init() {
clientServerEventBus.register(this);
}
@PreDestroy
private void destroy() {
clientServerEventBus.unregister(this);
}
@Override
public void initializeTradeCycle(IAIPlayer player, INavigableVessel vessel) {
ICity hometown = player.getHometown();
IProductionConsumptionKnowledge knowledge = player.getProductionAndConsumptionKnowledge();
ICityProductionConsumptionKnowledge knowledgeHomeTown = knowledge.getKnowlege(hometown);
List> sortedNeeds = getMostNeededWares(knowledgeHomeTown, vessel);
ArrayList waresOfInterest = findWaresOfInterest(sortedNeeds);
SupplyCityMissionData missionData = new SupplyCityMissionData();
missionData.setRequiredWares(waresOfInterest);
missionData.setTargetCity(hometown);
player.setTradeMission(vessel, missionData);
addTradeStepsInHometownToTravelToNextCity(player, vessel);
}
@Override
public void handleShipArrivesInPort(IShipEntersPortEvent event) {
// no move steps defined
INavigableVessel vessel = event.getShip();
if (isMatchingTradeStrategy(vessel)) {
ICity city = event.getCity();
Preconditions.checkArgument(city.getCoordinates().equals(vessel.getLocation()), "The vessel " + vessel.getName() + " actually is not in city " + city.getName());
IAIPlayer player = (IAIPlayer) vessel.getOwner();
if (city.equals(player.getHometown())) {
addTradeStepsSellingInHomeTown(player, vessel);
} else {
addTradeStepTradingNextTown(player, vessel);
}
executeTradeSteps(player, vessel);
}
}
/**
* Add the tradesteps to buy wares in the hometown and travel to the first stop.
* @param player for whom to add the trade steps
* @param vessel for which to add the trade steps
*/
private void addTradeStepsInHometownToTravelToNextCity(IAIPlayer player, INavigableVessel vessel) {
ICity hometown = player.getHometown();
IProductionConsumptionKnowledge knowledge = player.getProductionAndConsumptionKnowledge();
ICityProductionConsumptionKnowledge knowledgeHomeTown = knowledge.getKnowlege(hometown);
List> sortedNeeds = getMostNeededWares(knowledgeHomeTown, vessel);
ArrayList waresOfInterest = findWaresOfInterest(sortedNeeds);
ICity firstStop = findNextStopForBuying(hometown, knowledge, waresOfInterest, vessel, hometown);
List deliverWare = getWaresNeedIn(knowledge, knowledgeHomeTown, firstStop);
PayBackLoanTradeStep payBackLoan = createPaybackLoanStep(player, hometown);
append(player, vessel, payBackLoan);
CheckHireCaptainTradeStep hireCaptain = createHireCaptain(vessel, hometown, player);
append(player, vessel, hireCaptain);
GuildJoinTradeStep joinTradeStep = createJoinGuildTradeStep(vessel, hometown, player);
append(player, vessel, joinTradeStep);
HireDismissTradeManagerTradeStep hireTradeManager = createHireDismissTradeManagerTradeStep(hometown, player);
append(player, vessel, hireTradeManager);
TakeLoanTradeStep takeLoanStep = createCheckAndTakeLoanStep(player, hometown);
append(player, vessel, takeLoanStep);
BuyWeaponTradeStep buyWeaponsStep = createWeaponBuyTradeStep(vessel, player, hometown);
append(player, vessel, buyWeaponsStep);
// define trade steps for the first city, consider what ware can be transported to that city.
// Buy step in home town for deliverWare
AggregatedCheckedBuyTradeStep buyStepHometown = createAggregatedCheckedBuyTradeStep(vessel, hometown, deliverWare);
append(player, vessel, buyStepHometown);
HireSailorsStep hireSailors = createHireSailorStep(vessel, hometown);
append(player, vessel, hireSailors);
// Travel step to next town
TravelToTradeStep travelTo = createTravelToStep(vessel, firstStop);
logger.debug("Add travel to step from hometown {}: {}", hometown.getName(), travelTo);
append(player, vessel, travelTo);
}
/**
* Add the tradesteps in the hometown to sell the wares and check for repairs
* @param player for whom to add the trade steps
* @param vessel for which to add the trade steps
*/
@VisibleForTesting
void addTradeStepsSellingInHomeTown(IAIPlayer player, INavigableVessel vessel){
ICity hometown = player.getHometown();
// Sell wares
logger.trace("Add sell steps of wares in hometown: {} for {}", hometown.getName(), vessel.getName());
TransferToOfficeTradeStep transferStep = createTransferToOfficeTradeStep(vessel, hometown);
append(player, vessel, transferStep);
List loadedWares = new ArrayList<>(vessel.getLoadedWares());
AggregatesDumpTradeStep sellStep1 = createAggregatedDumpStep(vessel, hometown, loadedWares);
append(player, vessel, sellStep1);
// Check for repair
UpgradeShipTradeStep upgradeShipStep = createUpgradeShipTradeStep(vessel, player);
append(player, vessel, upgradeShipStep);
CheckForRepairTradeStep repairStep = createCheckRepairStep(vessel, hometown);
append(player, vessel, repairStep);
AggregatesSellTradeStep sellStep2 = createAggregatedSellStep(vessel, hometown, loadedWares);
append(player, vessel, sellStep2);
addTradeStepsInHometownToTravelToNextCity(player, vessel);
}
/**
* Define the trade steps in another town.
* @param player for whom to add the trade steps
* @param vessel for which to add the trade steps
*/
@VisibleForTesting
void addTradeStepTradingNextTown(IAIPlayer player, INavigableVessel vessel) {
Optional optCity = shipService.findCity(vessel);
if (!optCity.isPresent()) {
logger.debug("The vessel {} is not in any city but {}", vessel.getName(), vessel.getLocation());
}
Preconditions.checkArgument(!optCity.get().equals(player.getHometown()), "The city must not be the players hometown");
ICity city = optCity.get();
ICity hometown = player.getHometown();
List waresOfInterest = ((SupplyCityMissionData) player.getTradeMission(vessel)).getRequiredWares();
IProductionConsumptionKnowledge knowledge = player.getProductionAndConsumptionKnowledge();
ICityProductionConsumptionKnowledge knowledgeCurrentTown = knowledge.getKnowlege(city);
List> sortedNeedsHometown = getMostNeededWares(knowledge.getKnowlege(hometown), vessel);
List deliveringWares = getLoadedWaresToSell(vessel, waresOfInterest);
logger.trace("Add sell steps of wares in other town: {} for {}", city.getName(), vessel.getName());
AggregatesSellTradeStep sellStep = createAggregatedSellStep(vessel, city, deliveringWares);
append(player, vessel, sellStep);
PayBackLoanTradeStep payBackLoan = createPaybackLoanStep(player, city);
append(player, vessel, payBackLoan);
CheckHireCaptainTradeStep hireCaptain = createHireCaptain(vessel, city, player);
append(player, vessel, hireCaptain);
GuildJoinTradeStep joinTradeStep = createJoinGuildTradeStep(vessel, city, player);
append(player, vessel, joinTradeStep);
HireDismissTradeManagerTradeStep hireTradeManager = createHireDismissTradeManagerTradeStep(city, player);
append(player, vessel, hireTradeManager);
TakeLoanTradeStep takeLoanStep = createCheckAndTakeLoanStep(player, city);
append(player, vessel, takeLoanStep);
BuyWeaponTradeStep buyWeaponsStep = createWeaponBuyTradeStep(vessel, player, city);
append(player, vessel, buyWeaponsStep);
logger.trace("Add buy steps of wares in other town ({}) needed in hometown ({}) for {}", city.getName(), hometown.getName(), vessel.getName());
AggregatedCheckedBuyTradeStep buyStep = createAggregatedCheckedBuyTradeStep(vessel, city, waresOfInterest);
append(player, vessel, buyStep);
if (shouldReturnToHometown(player, vessel)) {
HireSailorsStep hireSailors = createHireSailorStep(vessel, city);
append(player, vessel, hireSailors);
TravelToTradeStep travelTo = createTravelToStep(vessel, hometown);
logger.debug("Add travel to step from {} back: {}", city.getName(), travelTo);
append(player, vessel, travelTo);
} else {
ArrayList waresOfInterestHometown = findWaresOfInterest(sortedNeedsHometown);
ICity nextStop = findNextStopForBuying(city, knowledge, waresOfInterestHometown, vessel, hometown); // Find the next city that can provide more goods for the hometown
List deliverWare = getWaresNeedIn(knowledge, knowledgeCurrentTown, nextStop);
logger.trace("Add buy steps of wares in other town ({}) needed in next town ({}) for {}", city.getName(), nextStop.getName(), vessel.getName());
AggregatedCheckedBuyTradeStep buyStepNextStop = createAggregatedCheckedBuyTradeStep(vessel, city, deliverWare);
append(player, vessel, buyStepNextStop);
HireSailorsStep hireSailors = createHireSailorStep(vessel, city);
append(player, vessel, hireSailors);
TravelToTradeStep travelTo = createTravelToStep(vessel, nextStop);
StringBuilder neededInHomeTown = new StringBuilder();
for (IWare ware : waresOfInterest) {
neededInHomeTown.append(ware.name()).append(" ");
}
StringBuilder sellWares = new StringBuilder();
for (IWare ware : deliverWare) {
sellWares.append(ware.name()).append(" ");
}
logger.debug("Add travel to step from {}: {}, needed in hometown: {}, deliver wares {}", city.getName(), travelTo, neededInHomeTown.toString(), sellWares.toString());
append(player, vessel, travelTo);
}
}
/**
* Check weather the vessel should return to the hometown
* @param player for whom to check the returnal to the hometown
* @param vessel which should return to the hometown
* @return true if the vessle should return to the hometown
*/
@VisibleForTesting
boolean shouldReturnToHometown(IAIPlayer player, INavigableVessel vessel) {
if (player.getCompany().getCash() < lowMoney) {
return true;
} else {
List waresOfInterest = ((SupplyCityMissionData) player.getTradeMission(vessel)).getRequiredWares();
if (vessel.getCapacity() == 0) {
for (EWare ware : EWare.values()) {
if (vessel.getWare(ware).getAmount() > 0 && !waresOfInterest.contains(ware)) {
return false;
}
}
return true;
} else {
return false;
}
}
}
/**
* Retrieve the wares that can be soled in another city than the hometown.
* @param vessel from which to retrieve the loaded wares
* @param waresOfInterest list of wares that should be sold in the hometown and nowhere else.
* @return List of wares on the vessel
*/
@VisibleForTesting
List getLoadedWaresToSell(INavigableVessel vessel, List waresOfInterest) {
List wares = new ArrayList<>();
for (IWare ware : vessel.getLoadedWares()) {
if (!waresOfInterest.contains(ware)) {
wares.add(ware);
}
}
return wares;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy