use of games.strategy.engine.data.Unit in project triplea by triplea-game.
the class AirMovementValidator method populateStaticAlliedAndBuildingCarrierCapacity.
private static IntegerMap<Territory> populateStaticAlliedAndBuildingCarrierCapacity(final List<Territory> landingSpots, final Map<Unit, Collection<Unit>> movedCarriersAndTheirFighters, final PlayerID player, final GameData data) {
final IntegerMap<Territory> startingSpace = new IntegerMap<>();
final Predicate<Unit> carrierAlliedNotOwned = Matches.unitIsOwnedBy(player).negate().and(Matches.isUnitAllied(player, data)).and(Matches.unitIsCarrier());
// final Predicate<Unit> airAlliedNotOwned = new CompositeMatchAnd<Unit>(Matches.unitIsOwnedBy(player).negate(),
// Matches.isUnitAllied(player, data), Matches.unitIsAir(), Matches.unitCanLandOnCarrier());
final boolean landAirOnNewCarriers = AirThatCantLandUtil.isLhtrCarrierProduction(data) || AirThatCantLandUtil.isLandExistingFightersOnNewCarriers(data);
// final boolean areNeutralsPassableByAir = areNeutralsPassableByAir(data);
final List<Unit> carriersInProductionQueue = player.getUnits().getMatches(Matches.unitIsCarrier());
for (final Territory t : landingSpots) {
if (landAirOnNewCarriers && !carriersInProductionQueue.isEmpty()) {
if (Matches.territoryIsWater().test(t) && Matches.territoryHasOwnedAtBeginningOfTurnIsFactoryOrCanProduceUnitsNeighbor(data, player).test(t)) {
// TODO: Here we are assuming that this factory can produce all of the carriers. Actually it might not be able
// to produce any
// carriers (because of complex requires units coding) or because of unit damage or maximum production.
// TODO: Here we are also assuming that the first territory we find that has an adjacent factory is the
// closest one in terms of
// unit movement. We have sorted the list of territories so this IS the closest in terms of steps, but each
// unit may have specific
// movement allowances for different terrain or some bullshit like that.
final int producedCarrierCapacity = carrierCapacity(carriersInProductionQueue, t);
startingSpace.add(t, producedCarrierCapacity);
carriersInProductionQueue.clear();
}
}
final Collection<Unit> alliedCarriers = t.getUnits().getMatches(carrierAlliedNotOwned);
alliedCarriers.removeAll(movedCarriersAndTheirFighters.keySet());
// Collection<Unit> alliedAir = t.getUnits().getMatches(airAlliedNotOwned);
final int alliedCarrierCapacity = carrierCapacity(alliedCarriers, t);
startingSpace.add(t, alliedCarrierCapacity);
}
return startingSpace;
}
use of games.strategy.engine.data.Unit in project triplea by triplea-game.
the class AirMovementValidator method validateAirCanLand.
// TODO: this class does a pretty good job already, but could be improved by having the carriers that are potentially
// moved also look for
// any owned air units that are in sea zones without carriers. these would be air units that have already been moved
// this turn, and
// therefore would need pickup.
static MoveValidationResult validateAirCanLand(final GameData data, final Collection<Unit> units, final Route route, final PlayerID player, final MoveValidationResult result) {
// First check if we even need to check
if (// Edit Mode, no need to check
getEditMode(data) || // No Airunits, nothing to check
units.stream().noneMatch(Matches.unitIsAir()) || // if there are no steps, we didn't move, so it is always OK!
route.hasNoSteps() || // we can land at the end, nothing left to check
Matches.airCanLandOnThisAlliedNonConqueredLandTerritory(player, data).test(route.getEnd()) || // we do not do any validation at all, cus they can all die and we don't care
isKamikazeAircraft(data)) {
return result;
}
// Find which aircraft cannot find friendly land to land on
final Collection<Unit> ownedAirThatMustLandOnCarriers = getAirThatMustLandOnCarriers(data, getAirUnitsToValidate(units, route, player), route, result);
if (ownedAirThatMustLandOnCarriers.isEmpty()) {
// we are done, everything can find a place to land
return result;
}
final Territory routeEnd = route.getEnd();
final Territory routeStart = route.getStart();
// we cannot forget to account for allied air at our location already
final Predicate<Unit> airAlliedNotOwned = Matches.unitIsOwnedBy(player).negate().and(Matches.isUnitAllied(player, data)).and(Matches.unitIsAir()).and(Matches.unitCanLandOnCarrier());
final HashSet<Unit> airThatMustLandOnCarriersHash = new HashSet<>();
airThatMustLandOnCarriersHash.addAll(CollectionUtils.getMatches(routeEnd.getUnits().getUnits(), airAlliedNotOwned));
airThatMustLandOnCarriersHash.addAll(CollectionUtils.getMatches(units, airAlliedNotOwned));
// now we must see if we also need to account for units (allied cargo) that are moving with our carriers, if we have
// selected any carriers
final Collection<Unit> movingCarriersAtStartLocationBeingMoved = CollectionUtils.getMatches(units, Matches.unitIsCarrier());
if (!movingCarriersAtStartLocationBeingMoved.isEmpty()) {
final Map<Unit, Collection<Unit>> carrierToAlliedCargo = MoveValidator.carrierMustMoveWith(units, routeStart, data, player);
for (final Collection<Unit> alliedAirOnCarrier : carrierToAlliedCargo.values()) {
airThatMustLandOnCarriersHash.addAll(alliedAirOnCarrier);
}
}
// now we can add our owned air. we add our owned air last because it can be moved, while allied air cannot be. we
// want the lowest
// movement to be validated first.
airThatMustLandOnCarriersHash.addAll(ownedAirThatMustLandOnCarriers);
final List<Unit> airThatMustLandOnCarriers = new ArrayList<>(airThatMustLandOnCarriersHash);
// sort the list by shortest range first so those birds will get first pick of landingspots
airThatMustLandOnCarriers.sort(getLowestToHighestMovementComparatorIncludingUnitsNotYetMoved(route));
// now we should see if the carriers we are moving with, plus the carriers already there, can handle all our air
// units (we check ending
// territories first, separately, because it is special [it includes units in our selection])
final Collection<Unit> carriersAtEnd = CollectionUtils.getMatches(getFriendly(routeEnd, player, data), Matches.unitIsCarrier());
carriersAtEnd.addAll(movingCarriersAtStartLocationBeingMoved);
// to keep track of all carriers, and their fighters, that have moved, so that we do not move them again.
final Map<Unit, Collection<Unit>> movedCarriersAndTheirFighters = new HashMap<>();
for (final Unit carrier : carriersAtEnd) {
movedCarriersAndTheirFighters.put(carrier, new ArrayList<>());
}
final Collection<Unit> airNotToConsiderBecauseWeAreValidatingThem = new ArrayList<>(airThatMustLandOnCarriers);
airThatMustLandOnCarriers.removeAll(whatAirCanLandOnTheseCarriers(carriersAtEnd, airThatMustLandOnCarriers, routeEnd));
if (airThatMustLandOnCarriers.isEmpty()) {
return result;
}
// we still have air left, so begin calling carriers to come here to pick up the air
// figure out what is the max distance of
// our remaining air units
final int maxMovementLeftForTheseAirUnitsBeingValidated = maxMovementLeftForTheseAirUnitsBeingValidated(airThatMustLandOnCarriers, route, player);
// figure out what is the max distance
// of our remaining carrier units
final int maxMovementLeftForAllOwnedCarriers = maxMovementLeftForAllOwnedCarriers(player, data);
final List<Territory> landingSpots = new ArrayList<>(Collections.singleton(routeEnd));
landingSpots.addAll(data.getMap().getNeighbors(routeEnd, maxMovementLeftForTheseAirUnitsBeingValidated, // where can we fly to?
Matches.airCanFlyOver(player, data, areNeutralsPassableByAir(data))));
// we only want to consider
landingSpots.removeAll(CollectionUtils.getMatches(landingSpots, Matches.seaCanMoveOver(player, data).negate()));
// places we can move carriers to
landingSpots.sort(getLowestToHighestDistance(routeEnd, Matches.seaCanMoveOver(player, data)));
final Collection<Territory> potentialCarrierOrigins = new LinkedHashSet<>(landingSpots);
potentialCarrierOrigins.addAll(data.getMap().getNeighbors(new HashSet<>(landingSpots), maxMovementLeftForAllOwnedCarriers, Matches.seaCanMoveOver(player, data)));
potentialCarrierOrigins.remove(routeEnd);
potentialCarrierOrigins.removeAll(CollectionUtils.getMatches(potentialCarrierOrigins, Matches.territoryHasOwnedCarrier(player).negate()));
// now see if we can move carriers there to pick up
validateAirCaughtByMovingCarriersAndOwnedAndAlliedAir(result, landingSpots, potentialCarrierOrigins, movedCarriersAndTheirFighters, airThatMustLandOnCarriers, airNotToConsiderBecauseWeAreValidatingThem, player, route, data);
return result;
}
use of games.strategy.engine.data.Unit in project triplea by triplea-game.
the class AirMovementValidator method getAirThatMustLandOnCarriers.
private static Collection<Unit> getAirThatMustLandOnCarriers(final GameData data, final Collection<Unit> ownedAir, final Route route, final MoveValidationResult result) {
final Collection<Unit> airThatMustLandOnCarriers = new ArrayList<>();
final Predicate<Unit> canLandOnCarriers = Matches.unitCanLandOnCarrier();
for (final Unit unit : ownedAir) {
if (!canFindLand(data, unit, route)) {
if (canLandOnCarriers.test(unit)) {
airThatMustLandOnCarriers.add(unit);
} else {
// not everything can land on a carrier (i.e. bombers)
result.addDisallowedUnit(NOT_ALL_AIR_UNITS_CAN_LAND, unit);
}
}
}
return airThatMustLandOnCarriers;
}
use of games.strategy.engine.data.Unit in project triplea by triplea-game.
the class AirThatCantLandUtil method removeAirThatCantLand.
private void removeAirThatCantLand(final PlayerID player, final Territory territory, final Collection<Unit> airUnits) {
final Collection<Unit> toRemove = new ArrayList<>(airUnits.size());
// if we cant land on land then none can
if (!territory.isWater()) {
toRemove.addAll(airUnits);
} else {
// on water we may just no have enough carriers
// find the carrier capacity
final Collection<Unit> carriers = territory.getUnits().getMatches(Matches.alliedUnit(player, bridge.getData()));
int capacity = AirMovementValidator.carrierCapacity(carriers, territory);
for (final Unit unit : airUnits) {
final UnitAttachment ua = UnitAttachment.get(unit.getType());
final int cost = ua.getCarrierCost();
if (cost == -1 || cost > capacity) {
toRemove.add(unit);
} else {
capacity -= cost;
}
}
}
final Change remove = ChangeFactory.removeUnits(territory, toRemove);
final String transcriptText = MyFormatter.unitsToTextNoOwner(toRemove) + " could not land in " + territory.getName() + " and " + (toRemove.size() > 1 ? "were" : "was") + " removed";
bridge.getHistoryWriter().startEvent(transcriptText);
bridge.addChange(remove);
}
use of games.strategy.engine.data.Unit in project triplea by triplea-game.
the class AirThatCantLandUtil method removeAirThatCantLand.
void removeAirThatCantLand(final PlayerID player, final boolean spareAirInSeaZonesBesideFactories) {
final GameData data = bridge.getData();
final GameMap map = data.getMap();
for (final Territory current : getTerritoriesWhereAirCantLand(player)) {
final Predicate<Unit> ownedAir = Matches.unitIsAir().and(Matches.alliedUnit(player, data));
final Collection<Unit> air = current.getUnits().getMatches(ownedAir);
final boolean hasNeighboringFriendlyFactory = map.getNeighbors(current, Matches.territoryHasAlliedIsFactoryOrCanProduceUnits(data, player)).size() > 0;
final boolean skip = spareAirInSeaZonesBesideFactories && current.isWater() && hasNeighboringFriendlyFactory;
if (!skip) {
removeAirThatCantLand(player, current, air);
}
}
}
Aggregations