use of games.strategy.util.IntegerMap in project triplea by triplea-game.
the class AbstractPlaceDelegate method getMaxUnitsToBePlacedMap.
/**
* Returns -1 somewhere in the map if can place unlimited units.
*/
protected IntegerMap<Territory> getMaxUnitsToBePlacedMap(final Collection<Unit> units, final Territory to, final PlayerID player, final boolean countSwitchedProductionToNeighbors) {
final IntegerMap<Territory> maxUnitsToBePlacedMap = new IntegerMap<>();
final List<Territory> producers = getAllProducers(to, player, units);
if (producers.isEmpty()) {
return maxUnitsToBePlacedMap;
}
producers.sort(getBestProducerComparator(to, units, player));
final Collection<Territory> notUsableAsOtherProducers = new ArrayList<>(producers);
final Map<Territory, Integer> currentAvailablePlacementForOtherProducers = new HashMap<>();
for (final Territory producerTerritory : producers) {
final Collection<Unit> unitsCanBePlacedByThisProducer = (isUnitPlacementRestrictions() ? CollectionUtils.getMatches(units, unitWhichRequiresUnitsHasRequiredUnits(producerTerritory, true)) : new ArrayList<>(units));
final int prodT = getMaxUnitsToBePlacedFrom(producerTerritory, unitsCanBePlacedByThisProducer, to, player, countSwitchedProductionToNeighbors, notUsableAsOtherProducers, currentAvailablePlacementForOtherProducers);
maxUnitsToBePlacedMap.put(producerTerritory, prodT);
}
return maxUnitsToBePlacedMap;
}
use of games.strategy.util.IntegerMap in project triplea by triplea-game.
the class AbstractPlaceDelegate method howManyOfEachConstructionCanPlace.
/**
* @param to
* referring territory.
* @param units
* units to place
* @param player
* PlayerID
* @return an empty IntegerMap if you can't produce any constructions (will never return null)
*/
public IntegerMap<String> howManyOfEachConstructionCanPlace(final Territory to, final Territory producer, final Collection<Unit> units, final PlayerID player) {
// constructions can ONLY be produced BY the same territory that they are going into!
if (!to.equals(producer) || units == null || units.isEmpty() || units.stream().noneMatch(Matches.unitIsConstruction())) {
return new IntegerMap<>();
}
final Collection<Unit> unitsAtStartOfTurnInTo = unitsAtStartOfStepInTerritory(to);
final Collection<Unit> unitsInTo = to.getUnits().getUnits();
final Collection<Unit> unitsPlacedAlready = getAlreadyProduced(to);
// build an integer map of each unit we have in our list of held units, as well as integer maps for maximum units
// and units per turn
final IntegerMap<String> unitMapHeld = new IntegerMap<>();
final IntegerMap<String> unitMapMaxType = new IntegerMap<>();
final IntegerMap<String> unitMapTypePerTurn = new IntegerMap<>();
final int maxFactory = Properties.getFactoriesPerCountry(getData());
// Can be null!
final TerritoryAttachment terrAttachment = TerritoryAttachment.get(to);
int toProduction = 0;
if (terrAttachment != null) {
toProduction = terrAttachment.getProduction();
}
for (final Unit currentUnit : CollectionUtils.getMatches(units, Matches.unitIsConstruction())) {
final UnitAttachment ua = UnitAttachment.get(currentUnit.getType());
// account for any unit placement restrictions by territory
if (isUnitPlacementRestrictions()) {
final String[] terrs = ua.getUnitPlacementRestrictions();
final Collection<Territory> listedTerrs = getListedTerritories(terrs);
if (listedTerrs.contains(to)) {
continue;
}
if (ua.getCanOnlyBePlacedInTerritoryValuedAtX() != -1 && ua.getCanOnlyBePlacedInTerritoryValuedAtX() > toProduction) {
continue;
}
if (unitWhichRequiresUnitsHasRequiredUnits(to, false).negate().test(currentUnit)) {
continue;
}
}
// remove any units that require other units to be consumed on creation (veqryn)
if (Matches.unitConsumesUnitsOnCreation().test(currentUnit) && Matches.unitWhichConsumesUnitsHasRequiredUnits(unitsAtStartOfTurnInTo).negate().test(currentUnit)) {
continue;
}
unitMapHeld.add(ua.getConstructionType(), 1);
unitMapTypePerTurn.put(ua.getConstructionType(), ua.getConstructionsPerTerrPerTypePerTurn());
if (ua.getConstructionType().equals(Constants.CONSTRUCTION_TYPE_FACTORY)) {
unitMapMaxType.put(ua.getConstructionType(), maxFactory);
} else {
unitMapMaxType.put(ua.getConstructionType(), ua.getMaxConstructionsPerTypePerTerr());
}
}
final boolean moreWithoutFactory = Properties.getMoreConstructionsWithoutFactory(getData());
final boolean moreWithFactory = Properties.getMoreConstructionsWithFactory(getData());
final boolean unlimitedConstructions = Properties.getUnlimitedConstructions(getData());
final boolean wasFactoryThereAtStart = wasOwnedUnitThatCanProduceUnitsOrIsFactoryInTerritoryAtStartOfStep(to, player);
// build an integer map of each construction unit in the territory
final IntegerMap<String> unitMapTo = new IntegerMap<>();
if (unitsInTo.stream().anyMatch(Matches.unitIsConstruction())) {
for (final Unit currentUnit : CollectionUtils.getMatches(unitsInTo, Matches.unitIsConstruction())) {
final UnitAttachment ua = UnitAttachment.get(currentUnit.getType());
/*
* if (Matches.UnitIsFactory.test(currentUnit) && !ua.getIsConstruction())
* unitMapTO.add("factory", 1);
* else
*/
unitMapTo.add(ua.getConstructionType(), 1);
}
// account for units already in the territory, based on max
for (final String constructionType : unitMapHeld.keySet()) {
int unitMax = unitMapMaxType.getInt(constructionType);
if (wasFactoryThereAtStart && !constructionType.equals(Constants.CONSTRUCTION_TYPE_FACTORY) && !constructionType.endsWith("structure")) {
unitMax = Math.max(Math.max(unitMax, (moreWithFactory ? toProduction : 0)), (unlimitedConstructions ? 10000 : 0));
}
if (!wasFactoryThereAtStart && !constructionType.equals(Constants.CONSTRUCTION_TYPE_FACTORY) && !constructionType.endsWith("structure")) {
unitMax = Math.max(Math.max(unitMax, (moreWithoutFactory ? toProduction : 0)), (unlimitedConstructions ? 10000 : 0));
}
unitMapHeld.put(constructionType, Math.max(0, Math.min(unitMax - unitMapTo.getInt(constructionType), unitMapHeld.getInt(constructionType))));
}
}
// deal with already placed units
for (final Unit currentUnit : CollectionUtils.getMatches(unitsPlacedAlready, Matches.unitIsConstruction())) {
final UnitAttachment ua = UnitAttachment.get(currentUnit.getType());
unitMapTypePerTurn.add(ua.getConstructionType(), -1);
}
// modify this list based on how many we can place per turn
final IntegerMap<String> unitsAllowed = new IntegerMap<>();
for (final String constructionType : unitMapHeld.keySet()) {
final int unitAllowed = Math.max(0, Math.min(unitMapTypePerTurn.getInt(constructionType), unitMapHeld.getInt(constructionType)));
if (unitAllowed > 0) {
unitsAllowed.put(constructionType, unitAllowed);
}
}
// return our integer map
return unitsAllowed;
}
use of games.strategy.util.IntegerMap 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.util.IntegerMap in project triplea by triplea-game.
the class TriggerAttachment method setRemoveUnits.
private void setRemoveUnits(final String value) throws GameParseException {
if (value == null) {
m_removeUnits = null;
return;
}
if (m_removeUnits == null) {
m_removeUnits = new HashMap<>();
}
final String[] s = value.split(":");
if (s.length < 1) {
throw new GameParseException("Empty removeUnits list" + thisErrorMsg());
}
int count;
int i = 0;
try {
count = getInt(s[0]);
i++;
} catch (final Exception e) {
count = 1;
}
if (s.length < 1 || (s.length == 1 && count != -1)) {
throw new GameParseException("Empty removeUnits list" + thisErrorMsg());
}
final Collection<Territory> territories = new ArrayList<>();
final Territory terr = getData().getMap().getTerritory(s[i]);
if (terr == null) {
if (s[i].equalsIgnoreCase("all")) {
territories.addAll(getData().getMap().getTerritories());
} else {
throw new GameParseException("Territory does not exist " + s[i] + thisErrorMsg());
}
} else {
territories.add(terr);
}
i++;
final IntegerMap<UnitType> map = new IntegerMap<>();
for (; i < s.length; i++) {
final Collection<UnitType> types = new ArrayList<>();
final UnitType tp = getData().getUnitTypeList().getUnitType(s[i]);
if (tp == null) {
if (s[i].equalsIgnoreCase("all")) {
types.addAll(getData().getUnitTypeList().getAllUnitTypes());
} else {
throw new GameParseException("UnitType does not exist " + s[i] + thisErrorMsg());
}
} else {
types.add(tp);
}
for (final UnitType type : types) {
map.add(type, count);
}
}
for (final Territory t : territories) {
if (m_removeUnits.containsKey(t)) {
map.add(m_removeUnits.get(t));
}
m_removeUnits.put(t, map);
}
}
use of games.strategy.util.IntegerMap in project triplea by triplea-game.
the class MoveDelegate method repairMultipleHitPointUnits.
static void repairMultipleHitPointUnits(final IDelegateBridge bridge, final PlayerID player) {
final GameData data = bridge.getData();
final boolean repairOnlyOwn = Properties.getBattleshipsRepairAtBeginningOfRound(bridge.getData());
final Predicate<Unit> damagedUnits = Matches.unitHasMoreThanOneHitPointTotal().and(Matches.unitHasTakenSomeDamage());
final Predicate<Unit> damagedUnitsOwned = damagedUnits.and(Matches.unitIsOwnedBy(player));
final Map<Territory, Set<Unit>> damagedMap = new HashMap<>();
for (final Territory current : data.getMap().getTerritories()) {
final Set<Unit> damaged;
if (!Properties.getTwoHitPointUnitsRequireRepairFacilities(data)) {
damaged = new HashSet<>(current.getUnits().getMatches(repairOnlyOwn ? damagedUnitsOwned : damagedUnits));
} else {
damaged = new HashSet<>(current.getUnits().getMatches(damagedUnitsOwned.and(Matches.unitCanBeRepairedByFacilitiesInItsTerritory(current, player, data))));
}
if (!damaged.isEmpty()) {
damagedMap.put(current, damaged);
}
}
if (damagedMap.isEmpty()) {
return;
}
final Map<Unit, Territory> fullyRepaired = new HashMap<>();
final IntegerMap<Unit> newHitsMap = new IntegerMap<>();
for (final Entry<Territory, Set<Unit>> entry : damagedMap.entrySet()) {
for (final Unit u : entry.getValue()) {
final int repairAmount = getLargestRepairRateForThisUnit(u, entry.getKey(), data);
final int currentHits = u.getHits();
final int newHits = Math.max(0, Math.min(currentHits, (currentHits - repairAmount)));
if (newHits != currentHits) {
newHitsMap.put(u, newHits);
}
if (newHits <= 0) {
fullyRepaired.put(u, entry.getKey());
}
}
}
bridge.getHistoryWriter().startEvent(newHitsMap.size() + " " + MyFormatter.pluralize("unit", newHitsMap.size()) + " repaired.", new HashSet<>(newHitsMap.keySet()));
bridge.addChange(ChangeFactory.unitsHit(newHitsMap));
// now if damaged includes any carriers that are repairing, and have damaged abilities set for not allowing air
// units to leave while damaged, we need to remove those air units now
final Collection<Unit> damagedCarriers = CollectionUtils.getMatches(fullyRepaired.keySet(), Matches.unitHasWhenCombatDamagedEffect(UnitAttachment.UNITSMAYNOTLEAVEALLIEDCARRIER));
// now cycle through those now-repaired carriers, and remove allied air from being dependent
final CompositeChange clearAlliedAir = new CompositeChange();
for (final Unit carrier : damagedCarriers) {
final CompositeChange change = MustFightBattle.clearTransportedByForAlliedAirOnCarrier(Collections.singleton(carrier), fullyRepaired.get(carrier), carrier.getOwner(), data);
if (!change.isEmpty()) {
clearAlliedAir.add(change);
}
}
if (!clearAlliedAir.isEmpty()) {
bridge.addChange(clearAlliedAir);
}
// Check if any repaired units change into different unit types
for (final Territory territory : damagedMap.keySet()) {
repairedChangeInto(damagedMap.get(territory), territory, bridge);
}
}
Aggregations