Search in sources :

Example 31 with Unit

use of games.strategy.engine.data.Unit in project triplea by triplea-game.

the class AbstractPlaceDelegate method getCanAllUnitsWithRequiresUnitsBePlacedCorrectly.

private boolean getCanAllUnitsWithRequiresUnitsBePlacedCorrectly(final Collection<Unit> units, final Territory to) {
    if (!isUnitPlacementRestrictions() || units.stream().noneMatch(Matches.unitRequiresUnitsOnCreation())) {
        return true;
    }
    final IntegerMap<Territory> producersMap = getMaxUnitsToBePlacedMap(units, to, player, true);
    final List<Territory> producers = getAllProducers(to, player, units);
    if (producers.isEmpty()) {
        return false;
    }
    producers.sort(getBestProducerComparator(to, units, player));
    final Collection<Unit> unitsLeftToPlace = new ArrayList<>(units);
    for (final Territory t : producers) {
        if (unitsLeftToPlace.isEmpty()) {
            return true;
        }
        final int productionHere = producersMap.getInt(t);
        final List<Unit> canBePlacedHere = CollectionUtils.getMatches(unitsLeftToPlace, unitWhichRequiresUnitsHasRequiredUnits(t, true));
        if (productionHere == -1 || productionHere >= canBePlacedHere.size()) {
            unitsLeftToPlace.removeAll(canBePlacedHere);
            continue;
        }
        canBePlacedHere.sort(getHardestToPlaceWithRequiresUnitsRestrictions(true));
        final Collection<Unit> placedHere = CollectionUtils.getNMatches(canBePlacedHere, productionHere, Matches.always());
        unitsLeftToPlace.removeAll(placedHere);
    }
    return unitsLeftToPlace.isEmpty();
}
Also used : Territory(games.strategy.engine.data.Territory) ArrayList(java.util.ArrayList) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit)

Example 32 with Unit

use of games.strategy.engine.data.Unit in project triplea by triplea-game.

the class AirBattle method queryRetreat.

private void queryRetreat(final boolean defender, final IDelegateBridge bridge, final Collection<Territory> availableTerritories) {
    if (availableTerritories.isEmpty()) {
        return;
    }
    final Collection<Unit> units = defender ? new ArrayList<>(m_defendingUnits) : new ArrayList<>(m_attackingUnits);
    if (units.isEmpty()) {
        return;
    }
    final PlayerID retreatingPlayer = defender ? m_defender : m_attacker;
    final String text = retreatingPlayer.getName() + " retreat?";
    final String step = defender ? DEFENDERS_WITHDRAW : ATTACKERS_WITHDRAW;
    getDisplay(bridge).gotoBattleStep(m_battleID, step);
    final Territory retreatTo = getRemote(retreatingPlayer, bridge).retreatQuery(m_battleID, false, m_battleSite, availableTerritories, text);
    if (retreatTo != null && !availableTerritories.contains(retreatTo)) {
        System.err.println("Invalid retreat selection :" + retreatTo + " not in " + MyFormatter.defaultNamedToTextList(availableTerritories));
        Thread.dumpStack();
        return;
    }
    if (retreatTo != null) {
        if (!m_headless) {
            bridge.getSoundChannelBroadcaster().playSoundForAll(SoundPath.CLIP_BATTLE_RETREAT_AIR, m_attacker);
        }
        retreat(units, defender, bridge);
        final String messageShort = retreatingPlayer.getName() + " retreats";
        final String messageLong = retreatingPlayer.getName() + " retreats all units to " + retreatTo.getName();
        getDisplay(bridge).notifyRetreat(messageShort, messageLong, step, retreatingPlayer);
    }
}
Also used : PlayerID(games.strategy.engine.data.PlayerID) Territory(games.strategy.engine.data.Territory) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit)

Example 33 with Unit

use of games.strategy.engine.data.Unit in project triplea by triplea-game.

the class AirBattle method remove.

private void remove(final Collection<Unit> killed, final IDelegateBridge bridge, final Territory battleSite) {
    if (killed.size() == 0) {
        return;
    }
    final Collection<Unit> dependent = getDependentUnits(killed);
    killed.addAll(dependent);
    final Change killedChange = ChangeFactory.removeUnits(battleSite, killed);
    // m_killed.addAll(killed);
    final String transcriptText = MyFormatter.unitsToText(killed) + " lost in " + battleSite.getName();
    bridge.getHistoryWriter().addChildToEvent(transcriptText, new ArrayList<>(killed));
    bridge.addChange(killedChange);
    final Collection<IBattle> dependentBattles = m_battleTracker.getBlocked(AirBattle.this);
    removeFromDependents(killed, bridge, dependentBattles, false);
}
Also used : CompositeChange(games.strategy.engine.data.CompositeChange) Change(games.strategy.engine.data.Change) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit)

Example 34 with Unit

use of games.strategy.engine.data.Unit in project triplea by triplea-game.

the class AirMovementValidator method getMovementLeftForValidatingAir.

private static LinkedHashMap<Unit, Integer> getMovementLeftForValidatingAir(final Collection<Unit> airBeingValidated, final PlayerID player, final Route route) {
    final LinkedHashMap<Unit, Integer> map = new LinkedHashMap<>();
    for (final Unit unit : airBeingValidated) {
        // unit must be in either start or end.
        final int movementLeft;
        if (Matches.unitIsOwnedBy(player).test(unit)) {
            movementLeft = getMovementLeftForAirUnitNotMovedYet(unit, route);
        } else {
            movementLeft = 0;
        }
        map.put(unit, movementLeft);
    }
    return map;
}
Also used : TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) LinkedHashMap(java.util.LinkedHashMap)

Example 35 with Unit

use of games.strategy.engine.data.Unit in project triplea by triplea-game.

the class AirMovementValidator method validateAirCaughtByMovingCarriersAndOwnedAndAlliedAir.

private static void validateAirCaughtByMovingCarriersAndOwnedAndAlliedAir(final MoveValidationResult result, final List<Territory> landingSpots, final Collection<Territory> potentialCarrierOrigins, final Map<Unit, Collection<Unit>> movedCarriersAndTheirFighters, final Collection<Unit> airThatMustLandOnCarriers, final Collection<Unit> airNotToConsider, final PlayerID player, final Route route, final GameData data) {
    final Predicate<Unit> ownedCarrierMatch = Matches.unitIsOwnedBy(player).and(Matches.unitIsCarrier());
    final Predicate<Unit> ownedAirMatch = Matches.unitIsOwnedBy(player).and(Matches.unitIsAir()).and(Matches.unitCanLandOnCarrier());
    final Predicate<Unit> alliedNotOwnedAirMatch = Matches.unitIsOwnedBy(player).negate().and(Matches.isUnitAllied(player, data)).and(Matches.unitIsAir()).and(Matches.unitCanLandOnCarrier());
    final Predicate<Unit> alliedNotOwnedCarrierMatch = Matches.unitIsOwnedBy(player).negate().and(Matches.isUnitAllied(player, data)).and(Matches.unitIsCarrier());
    final Territory routeEnd = route.getEnd();
    final boolean areNeutralsPassableByAir = areNeutralsPassableByAir(data);
    final IntegerMap<Territory> landingSpotsWithCarrierCapacity = // fill our landing spot capacity with capacity from allied carriers and potential building of new carriers
    populateStaticAlliedAndBuildingCarrierCapacity(landingSpots, movedCarriersAndTheirFighters, player, data);
    final LinkedHashMap<Unit, Integer> movementLeftForAirToValidate = // calculate movement left only once
    getMovementLeftForValidatingAir(airThatMustLandOnCarriers, player, route);
    for (final Territory landingSpot : landingSpots) {
        // since we are here, no point looking at this place twice
        potentialCarrierOrigins.remove(landingSpot);
        final List<Unit> airCanReach = new ArrayList<>();
        for (final Unit air : airThatMustLandOnCarriers) {
            if (canAirReachThisSpot(data, player, air, routeEnd, movementLeftForAirToValidate.get(air), landingSpot, areNeutralsPassableByAir)) {
                // get all air that can reach this spot
                airCanReach.add(air);
            }
        }
        if (airCanReach.isEmpty()) {
            continue;
        }
        final Collection<Unit> unitsInLandingSpot = landingSpot.getUnits().getUnits();
        unitsInLandingSpot.removeAll(movedCarriersAndTheirFighters.keySet());
        // make sure to remove any units we have already moved, or units that are excluded
        unitsInLandingSpot.removeAll(airNotToConsider);
        // because they are in our mouse selection
        for (final Collection<Unit> ftrs : movedCarriersAndTheirFighters.values()) {
            // also remove any fighters that are being moved with carriers that we have already moved
            unitsInLandingSpot.removeAll(ftrs);
        }
        final Collection<Unit> ownedCarriersInLandingSpot = CollectionUtils.getMatches(unitsInLandingSpot, ownedCarrierMatch);
        // get air we own here, but exclude any air that can fly to allied land
        final Collection<Unit> airInLandingSpot = CollectionUtils.getMatches(CollectionUtils.getMatches(unitsInLandingSpot, ownedAirMatch), unitCanFindLand(data, landingSpot).negate());
        // add allied air (it can't fly away)
        airInLandingSpot.addAll(CollectionUtils.getMatches(unitsInLandingSpot, alliedNotOwnedAirMatch));
        // make sure we don't count this again
        // airNotToConsider.addAll(airInLandingSpot);
        // get the current capacity
        int landingSpotCapacity = landingSpotsWithCarrierCapacity.getInt(landingSpot);
        // add capacity of owned carriers
        landingSpotCapacity += carrierCapacity(ownedCarriersInLandingSpot, landingSpot);
        // minus capacity of air in the territory
        landingSpotCapacity -= carrierCost(airInLandingSpot);
        if (!airCanReach.isEmpty()) {
            final Iterator<Unit> airIter = airCanReach.iterator();
            while (airIter.hasNext()) {
                final Unit air = airIter.next();
                final int carrierCost = carrierCost(air);
                if (landingSpotCapacity >= carrierCost) {
                    landingSpotCapacity -= carrierCost;
                    // we can land this one here, yay
                    airThatMustLandOnCarriers.remove(air);
                    airIter.remove();
                }
            }
        }
        if (airThatMustLandOnCarriers.isEmpty()) {
            // all can land here, so return
            return;
        }
        // final int lowestCarrierCost = getLowestCarrierCost(airCanReach);
        // now bring carriers here...
        final Iterator<Territory> iter = potentialCarrierOrigins.iterator();
        while (iter.hasNext()) {
            final Territory carrierSpot = iter.next();
            final Collection<Unit> unitsInCarrierSpot = carrierSpot.getUnits().getUnits();
            // remove carriers we have already moved
            unitsInCarrierSpot.removeAll(movedCarriersAndTheirFighters.keySet());
            // remove units we do not want to consider because they are in our mouse selection
            unitsInCarrierSpot.removeAll(airNotToConsider);
            for (final Collection<Unit> ftrs : movedCarriersAndTheirFighters.values()) {
                // remove the fighters that are moving with the carriers we have already moved
                unitsInCarrierSpot.removeAll(ftrs);
            }
            final Collection<Unit> ownedCarriersInCarrierSpot = CollectionUtils.getMatches(unitsInCarrierSpot, ownedCarrierMatch);
            if (ownedCarriersInCarrierSpot.isEmpty()) {
                iter.remove();
                continue;
            }
            final Collection<Unit> ownedAirInCarrierSpot = CollectionUtils.getMatches(// exclude any owned air that can fly to land
            CollectionUtils.getMatches(unitsInCarrierSpot, ownedAirMatch), unitCanFindLand(data, carrierSpot).negate());
            final Collection<Unit> alliedNotOwnedAirInCarrierSpot = CollectionUtils.getMatches(unitsInCarrierSpot, alliedNotOwnedAirMatch);
            final Map<Unit, Collection<Unit>> mustMoveWithMap = // this only returns the allied cargo
            MoveValidator.carrierMustMoveWith(ownedCarriersInCarrierSpot, carrierSpot, data, player);
            // planes that MUST travel with the carrier
            // get the current capacity for the carrier spot
            int carrierSpotCapacity = landingSpotsWithCarrierCapacity.getInt(carrierSpot);
            // we don't have it because this spot is not in the landing zone area.
            if (!landingSpotsWithCarrierCapacity.containsKey(carrierSpot)) {
                // we still have a capacity for allied carriers, but only to carry other allied or local owned units, not to
                // carry our selected
                // units.
                carrierSpotCapacity = carrierCapacity(carrierSpot.getUnits().getMatches(alliedNotOwnedCarrierMatch), carrierSpot);
                landingSpotsWithCarrierCapacity.put(carrierSpot, carrierSpotCapacity);
            }
            // we have allied air here, so we need to account for them before moving any carriers
            if (!alliedNotOwnedAirInCarrierSpot.isEmpty() || !mustMoveWithMap.isEmpty()) {
                // them
                if (mustMoveWithMap.isEmpty()) {
                    // allied carriers can carry enough
                    carrierSpotCapacity -= carrierCost(alliedNotOwnedAirInCarrierSpot);
                    // we do not want to consider these units again
                    airNotToConsider.addAll(alliedNotOwnedAirInCarrierSpot);
                    if (carrierSpotCapacity > 0) {
                        // we can hold some of the owned air here too
                        final Iterator<Unit> ownedIter = ownedAirInCarrierSpot.iterator();
                        while (ownedIter.hasNext()) {
                            final Unit air = ownedIter.next();
                            final int carrierCost = carrierCost(air);
                            if (carrierSpotCapacity >= carrierCost) {
                                carrierSpotCapacity -= carrierCost;
                                // we do not want to consider this one again
                                airNotToConsider.add(air);
                                ownedIter.remove();
                            }
                        }
                    }
                    // put correct value for future reference now that we
                    // have considered the allied air
                    landingSpotsWithCarrierCapacity.put(carrierSpot, carrierSpotCapacity);
                } else {
                    // carrierMustMoveWith does not account for any allied cargo already moved out.
                    for (final Collection<Unit> airMovingWith : mustMoveWithMap.values()) {
                        for (final Collection<Unit> ftrs : movedCarriersAndTheirFighters.values()) {
                            // remove the fighters that are moving with the carriers we have already moved
                            airMovingWith.removeAll(ftrs);
                        }
                    }
                    for (final Collection<Unit> airMovingWith : mustMoveWithMap.values()) {
                        // we will consider these as part of their moving carrier
                        alliedNotOwnedAirInCarrierSpot.removeAll(airMovingWith);
                    }
                    carrierSpotCapacity -= carrierCost(alliedNotOwnedAirInCarrierSpot);
                    // we do not want to consider these units again
                    airNotToConsider.addAll(alliedNotOwnedAirInCarrierSpot);
                    // put correct value for future reference now that we
                    // have considered the allied air
                    landingSpotsWithCarrierCapacity.put(carrierSpot, carrierSpotCapacity);
                }
            }
            final Route toLandingSpot = data.getMap().getRoute(carrierSpot, landingSpot, Matches.seaCanMoveOver(player, data));
            if (toLandingSpot == null) {
                continue;
            }
            final List<Unit> carrierCanReach = CollectionUtils.getMatches(ownedCarriersInCarrierSpot, Matches.unitHasEnoughMovementForRoute(toLandingSpot));
            if (carrierCanReach.isEmpty()) {
                // none can reach
                continue;
            }
            final List<Unit> carrierNotReach = new ArrayList<>(ownedCarriersInCarrierSpot);
            // we want to see if the air units can be put on the carriers that cannot make it
            // first, before taking up room on the carriers that can make it
            carrierNotReach.removeAll(carrierCanReach);
            final List<Unit> allCarriers = new ArrayList<>(carrierNotReach);
            // so we remove them from the list then re-add them so that they will be at the end of the list
            allCarriers.addAll(carrierCanReach);
            // now we want to make a map of the carriers to the units they must carry with them (both allied and owned)
            final Map<Unit, Collection<Unit>> carriersToMove = new HashMap<>();
            final List<Unit> carrierFull = new ArrayList<>();
            for (final Unit carrier : allCarriers) {
                final Collection<Unit> airMovingWith = new ArrayList<>();
                // first add allied cargo
                final Collection<Unit> alliedMovingWith = mustMoveWithMap.get(carrier);
                if (alliedMovingWith != null) {
                    airMovingWith.addAll(alliedMovingWith);
                }
                // now test if our carrier has any room for owned fighters
                int carrierCapacity = carrierCapacity(carrier, carrierSpot);
                carrierCapacity -= carrierCost(airMovingWith);
                final Iterator<Unit> ownedIter = ownedAirInCarrierSpot.iterator();
                while (ownedIter.hasNext()) {
                    final Unit air = ownedIter.next();
                    final int carrierCost = carrierCost(air);
                    if (carrierCapacity >= carrierCost) {
                        carrierCapacity -= carrierCost;
                        airMovingWith.add(air);
                        ownedIter.remove();
                    }
                }
                carriersToMove.put(carrier, airMovingWith);
                if (carrierCapacity <= 0) {
                    carrierFull.add(carrier);
                }
            }
            // if all carriers full, remove this carrier spot from consideration
            if (carrierFull.containsAll(allCarriers)) {
                iter.remove();
                continue;
            }
            if (carrierFull.containsAll(carrierNotReach)) {
                iter.remove();
            }
            // ok, now lets move them.
            for (final Unit carrier : carrierCanReach) {
                movedCarriersAndTheirFighters.put(carrier, carriersToMove.get(carrier));
                landingSpotCapacity += carrierCapacity(carrier, carrierSpot);
                landingSpotCapacity -= carrierCost(carriersToMove.get(carrier));
            }
            // optional for debugging
            final Iterator<Unit> reachIter = airCanReach.iterator();
            while (reachIter.hasNext()) {
                final Unit air = reachIter.next();
                final int carrierCost = carrierCost(air);
                if (landingSpotCapacity >= carrierCost) {
                    landingSpotCapacity -= carrierCost;
                    // we can land this one here, yay
                    airThatMustLandOnCarriers.remove(air);
                    reachIter.remove();
                }
            }
            if (airThatMustLandOnCarriers.isEmpty()) {
                // all can land here, so return
                return;
            }
        }
    }
    // anyone left over cannot land
    for (final Unit air : airThatMustLandOnCarriers) {
        result.addDisallowedUnit(NOT_ALL_AIR_UNITS_CAN_LAND, air);
    }
}
Also used : Territory(games.strategy.engine.data.Territory) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ArrayList(java.util.ArrayList) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) Collection(java.util.Collection) Route(games.strategy.engine.data.Route)

Aggregations

Unit (games.strategy.engine.data.Unit)447 TripleAUnit (games.strategy.triplea.TripleAUnit)301 Territory (games.strategy.engine.data.Territory)255 ArrayList (java.util.ArrayList)204 PlayerID (games.strategy.engine.data.PlayerID)135 GameData (games.strategy.engine.data.GameData)103 HashSet (java.util.HashSet)92 Test (org.junit.jupiter.api.Test)91 Route (games.strategy.engine.data.Route)89 UnitType (games.strategy.engine.data.UnitType)85 CompositeChange (games.strategy.engine.data.CompositeChange)64 HashMap (java.util.HashMap)64 IntegerMap (games.strategy.util.IntegerMap)61 UnitAttachment (games.strategy.triplea.attachments.UnitAttachment)58 Collection (java.util.Collection)58 ITestDelegateBridge (games.strategy.engine.data.ITestDelegateBridge)56 List (java.util.List)48 ScriptedRandomSource (games.strategy.engine.random.ScriptedRandomSource)47 Change (games.strategy.engine.data.Change)44 Set (java.util.Set)43