Search in sources :

Example 1 with RulesAttachment

use of games.strategy.triplea.attachments.RulesAttachment in project triplea by triplea-game.

the class AbstractPlaceDelegate method getMaxUnitsToBePlacedFrom.

/**
 * Returns -1 if can place unlimited units.
 */
protected int getMaxUnitsToBePlacedFrom(final Territory producer, final Collection<Unit> units, final Territory to, final PlayerID player, final boolean countSwitchedProductionToNeighbors, final Collection<Territory> notUsableAsOtherProducers, final Map<Territory, Integer> currentAvailablePlacementForOtherProducers) {
    // we may have special units with requiresUnits restrictions
    final Collection<Unit> unitsCanBePlacedByThisProducer = (isUnitPlacementRestrictions() ? CollectionUtils.getMatches(units, unitWhichRequiresUnitsHasRequiredUnits(producer, true)) : new ArrayList<>(units));
    if (unitsCanBePlacedByThisProducer.size() <= 0) {
        return 0;
    }
    // if its an original factory then unlimited production
    // Can be null!
    final TerritoryAttachment ta = TerritoryAttachment.get(producer);
    final Predicate<Unit> factoryMatch = Matches.unitIsOwnedAndIsFactoryOrCanProduceUnits(player).and(Matches.unitIsBeingTransported().negate()).and(producer.isWater() ? Matches.unitIsLand().negate() : Matches.unitIsSea().negate());
    final Collection<Unit> factoryUnits = producer.getUnits().getMatches(factoryMatch);
    // boolean placementRestrictedByFactory = isPlacementRestrictedByFactory();
    final boolean unitPlacementPerTerritoryRestricted = isUnitPlacementPerTerritoryRestricted();
    final boolean originalFactory = (ta != null && ta.getOriginalFactory());
    final boolean playerIsOriginalOwner = factoryUnits.size() > 0 && this.player.equals(getOriginalFactoryOwner(producer));
    final RulesAttachment ra = (RulesAttachment) player.getAttachment(Constants.RULES_ATTACHMENT_NAME);
    final Collection<Unit> alreadProducedUnits = getAlreadyProduced(producer);
    final int unitCountAlreadyProduced = alreadProducedUnits.size();
    if (originalFactory && playerIsOriginalOwner) {
        if (ra != null && ra.getMaxPlacePerTerritory() != -1) {
            return Math.max(0, ra.getMaxPlacePerTerritory() - unitCountAlreadyProduced);
        }
        return -1;
    }
    // Restricts based on the STARTING number of units in a territory (otherwise it is infinite placement)
    if (unitPlacementPerTerritoryRestricted) {
        if (ra != null && ra.getPlacementPerTerritory() > 0) {
            final int allowedPlacement = ra.getPlacementPerTerritory();
            final int ownedUnitsInTerritory = CollectionUtils.countMatches(to.getUnits().getUnits(), Matches.unitIsOwnedBy(player));
            if (ownedUnitsInTerritory >= allowedPlacement) {
                return 0;
            }
            if (ra.getMaxPlacePerTerritory() == -1) {
                return -1;
            }
            return Math.max(0, ra.getMaxPlacePerTerritory() - unitCountAlreadyProduced);
        }
    }
    // a factory can produce the same number of units as the number of PUs the territory generates each turn (or not, if
    // it has canProduceXUnits)
    final int maxConstructions = howManyOfEachConstructionCanPlace(to, producer, unitsCanBePlacedByThisProducer, player).totalValues();
    final boolean wasFactoryThereAtStart = wasOwnedUnitThatCanProduceUnitsOrIsFactoryInTerritoryAtStartOfStep(producer, player);
    // If there's NO factory, allow placement of the factory
    if (!wasFactoryThereAtStart) {
        if (ra != null && ra.getMaxPlacePerTerritory() > 0) {
            return Math.max(0, Math.min(maxConstructions, ra.getMaxPlacePerTerritory() - unitCountAlreadyProduced));
        }
        return Math.max(0, maxConstructions);
    }
    // getHowMuchCanUnitProduce accounts for IncreasedFactoryProduction, but does not account for maxConstructions
    int production = TripleAUnit.getProductionPotentialOfTerritory(unitsAtStartOfStepInTerritory(producer), producer, player, getData(), true, true);
    // increase the production by the number of constructions allowed
    if (maxConstructions > 0) {
        production += maxConstructions;
    }
    // return 0 if less than 0
    if (production < 0) {
        return 0;
    }
    production += CollectionUtils.countMatches(alreadProducedUnits, Matches.unitIsConstruction());
    // Now we check if units we have already produced here could be produced by a different producer
    int unitCountHaveToAndHaveBeenBeProducedHere = unitCountAlreadyProduced;
    if (countSwitchedProductionToNeighbors && unitCountAlreadyProduced > 0) {
        if (notUsableAsOtherProducers == null) {
            throw new IllegalStateException("notUsableAsOtherProducers cannot be null if countSwitchedProductionToNeighbors is true");
        }
        if (currentAvailablePlacementForOtherProducers == null) {
            throw new IllegalStateException("currentAvailablePlacementForOtherProducers cannot be null if countSwitchedProductionToNeighbors is true");
        }
        int productionCanNotBeMoved = 0;
        int productionThatCanBeTakenOver = 0;
        // try to find a placement move (to an adjacent sea zone) that can be taken over by some other territory factory
        for (final UndoablePlacement placementMove : placements) {
            if (placementMove.getProducerTerritory().equals(producer)) {
                final Territory placeTerritory = placementMove.getPlaceTerritory();
                final Collection<Unit> unitsPlacedByCurrentPlacementMove = placementMove.getUnits();
                // for our special 'move shit around' methods.
                if (!placeTerritory.isWater() || (isUnitPlacementRestrictions() && unitsPlacedByCurrentPlacementMove.stream().anyMatch(Matches.unitRequiresUnitsOnCreation()))) {
                    productionCanNotBeMoved += unitsPlacedByCurrentPlacementMove.size();
                } else {
                    final int maxProductionThatCanBeTakenOverFromThisPlacement = unitsPlacedByCurrentPlacementMove.size();
                    // find other producers for this placement move to the same water territory
                    final List<Territory> newPotentialOtherProducers = getAllProducers(placeTerritory, player, unitsCanBePlacedByThisProducer);
                    newPotentialOtherProducers.removeAll(notUsableAsOtherProducers);
                    newPotentialOtherProducers.sort(getBestProducerComparator(placeTerritory, unitsCanBePlacedByThisProducer, player));
                    int productionThatCanBeTakenOverFromThisPlacement = 0;
                    for (final Territory potentialOtherProducer : newPotentialOtherProducers) {
                        Integer potential = currentAvailablePlacementForOtherProducers.get(potentialOtherProducer);
                        if (potential == null) {
                            potential = getMaxUnitsToBePlacedFrom(potentialOtherProducer, unitsPlacedInTerritorySoFar(placeTerritory), placeTerritory, player);
                        }
                        if (potential == -1) {
                            currentAvailablePlacementForOtherProducers.put(potentialOtherProducer, -1);
                            productionThatCanBeTakenOverFromThisPlacement = maxProductionThatCanBeTakenOverFromThisPlacement;
                            break;
                        }
                        final int needed = maxProductionThatCanBeTakenOverFromThisPlacement - productionThatCanBeTakenOverFromThisPlacement;
                        final int surplus = potential - needed;
                        if (surplus > 0) {
                            currentAvailablePlacementForOtherProducers.put(potentialOtherProducer, surplus);
                            productionThatCanBeTakenOverFromThisPlacement += needed;
                        } else {
                            currentAvailablePlacementForOtherProducers.put(potentialOtherProducer, 0);
                            productionThatCanBeTakenOverFromThisPlacement += potential;
                            notUsableAsOtherProducers.add(potentialOtherProducer);
                        }
                        if (surplus >= 0) {
                            break;
                        }
                    }
                    if (productionThatCanBeTakenOverFromThisPlacement > maxProductionThatCanBeTakenOverFromThisPlacement) {
                        throw new IllegalStateException("productionThatCanBeTakenOverFromThisPlacement should never be larger " + "than maxProductionThatCanBeTakenOverFromThisPlacement");
                    }
                    productionThatCanBeTakenOver += productionThatCanBeTakenOverFromThisPlacement;
                }
                if (productionThatCanBeTakenOver >= unitCountAlreadyProduced - productionCanNotBeMoved) {
                    break;
                }
            }
        }
        unitCountHaveToAndHaveBeenBeProducedHere = Math.max(0, unitCountAlreadyProduced - productionThatCanBeTakenOver);
    }
    if (ra != null && ra.getMaxPlacePerTerritory() > 0) {
        return Math.max(0, Math.min(production - unitCountHaveToAndHaveBeenBeProducedHere, ra.getMaxPlacePerTerritory() - unitCountHaveToAndHaveBeenBeProducedHere));
    }
    return Math.max(0, production - unitCountHaveToAndHaveBeenBeProducedHere);
}
Also used : Territory(games.strategy.engine.data.Territory) TerritoryAttachment(games.strategy.triplea.attachments.TerritoryAttachment) ArrayList(java.util.ArrayList) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) RulesAttachment(games.strategy.triplea.attachments.RulesAttachment)

Example 2 with RulesAttachment

use of games.strategy.triplea.attachments.RulesAttachment in project triplea by triplea-game.

the class MoveValidator method validateMovementRestrictedByTerritory.

// Added to handle restriction of movement to listed territories
static MoveValidationResult validateMovementRestrictedByTerritory(final GameData data, final Route route, final PlayerID player, final MoveValidationResult result) {
    if (getEditMode(data)) {
        return result;
    }
    if (!isMovementByTerritoryRestricted(data)) {
        return result;
    }
    final RulesAttachment ra = (RulesAttachment) player.getAttachment(Constants.RULES_ATTACHMENT_NAME);
    if (ra == null || ra.getMovementRestrictionTerritories() == null) {
        return result;
    }
    final String movementRestrictionType = ra.getMovementRestrictionType();
    final Collection<Territory> listedTerritories = ra.getListedTerritories(ra.getMovementRestrictionTerritories(), true, true);
    if (movementRestrictionType.equals("allowed")) {
        for (final Territory current : route.getAllTerritories()) {
            if (!listedTerritories.contains(current)) {
                return result.setErrorReturnResult("Cannot move outside restricted territories");
            }
        }
    } else if (movementRestrictionType.equals("disallowed")) {
        for (final Territory current : route.getAllTerritories()) {
            if (listedTerritories.contains(current)) {
                return result.setErrorReturnResult("Cannot move to restricted territories");
            }
        }
    }
    return result;
}
Also used : Territory(games.strategy.engine.data.Territory) RulesAttachment(games.strategy.triplea.attachments.RulesAttachment)

Example 3 with RulesAttachment

use of games.strategy.triplea.attachments.RulesAttachment in project triplea by triplea-game.

the class NoPUPurchaseDelegate method getProductionUnits.

private Collection<Unit> getProductionUnits(final Collection<Territory> territories, final PlayerID player) {
    final Collection<Unit> productionUnits = new ArrayList<>();
    if (!(isProductionPerXTerritoriesRestricted() || isProductionPerValuedTerritoryRestricted())) {
        return productionUnits;
    }
    IntegerMap<UnitType> productionPerXTerritories = new IntegerMap<>();
    final RulesAttachment ra = (RulesAttachment) player.getAttachment(Constants.RULES_ATTACHMENT_NAME);
    // isProductionPerValuedTerritoryRestricted, then they want 1 infantry for each territory with PU value > 0
    if (isProductionPerValuedTerritoryRestricted() && (ra == null || ra.getProductionPerXTerritories() == null || ra.getProductionPerXTerritories().size() == 0)) {
        productionPerXTerritories.put(getData().getUnitTypeList().getUnitType(Constants.UNIT_TYPE_INFANTRY), 1);
    } else if (isProductionPerXTerritoriesRestricted()) {
        productionPerXTerritories = ra.getProductionPerXTerritories();
    } else {
        return productionUnits;
    }
    final Collection<UnitType> unitTypes = new ArrayList<>(productionPerXTerritories.keySet());
    for (final UnitType ut : unitTypes) {
        int unitCount = 0;
        final int prodPerXTerrs = productionPerXTerritories.getInt(ut);
        if (isPacific) {
            unitCount += getBurmaRoad(player);
        }
        int terrCount = 0;
        for (final Territory current : territories) {
            if (!isProductionPerValuedTerritoryRestricted()) {
                terrCount++;
            } else {
                if (TerritoryAttachment.getProduction(current) > 0) {
                    terrCount++;
                }
            }
        }
        unitCount += terrCount / prodPerXTerrs;
        productionUnits.addAll(getData().getUnitTypeList().getUnitType(ut.getName()).create(unitCount, player));
    }
    return productionUnits;
}
Also used : IntegerMap(games.strategy.util.IntegerMap) Territory(games.strategy.engine.data.Territory) UnitType(games.strategy.engine.data.UnitType) ArrayList(java.util.ArrayList) Unit(games.strategy.engine.data.Unit) RulesAttachment(games.strategy.triplea.attachments.RulesAttachment)

Example 4 with RulesAttachment

use of games.strategy.triplea.attachments.RulesAttachment in project triplea by triplea-game.

the class EndTurnDelegate method findNationalObjectiveAndTriggerResources.

/**
 * Find the resources generated by national objectives and triggers that are currently met.
 */
public static IntegerMap<Resource> findNationalObjectiveAndTriggerResources(final PlayerID player, final GameData data) {
    final IDelegateBridge bridge = new ObjectiveDummyDelegateBridge(data);
    // Find and test all the conditions for triggers and national objectives
    final Set<TriggerAttachment> triggers = new HashSet<>();
    final List<RulesAttachment> objectives = new ArrayList<>();
    final HashMap<ICondition, Boolean> testedConditions = testNationalObjectivesAndTriggers(player, data, bridge, triggers, objectives);
    // Find triggers value
    final IntegerMap<Resource> resources;
    final boolean useTriggers = Properties.getTriggers(data);
    if (useTriggers && !triggers.isEmpty()) {
        final Set<TriggerAttachment> toFireTestedAndSatisfied = new HashSet<>(CollectionUtils.getMatches(triggers, AbstractTriggerAttachment.isSatisfiedMatch(testedConditions)));
        resources = TriggerAttachment.findResourceIncome(toFireTestedAndSatisfied, bridge);
    } else {
        resources = new IntegerMap<>();
    }
    // Find national objectives value
    int pus = 0;
    for (final RulesAttachment rule : objectives) {
        final int uses = rule.getUses();
        if (uses == 0 || !rule.isSatisfied(testedConditions)) {
            continue;
        }
        pus += (rule.getObjectiveValue() * rule.getEachMultiple() * Properties.getPuMultiplier(data));
    }
    resources.add(data.getResourceList().getResource(Constants.PUS), pus);
    return resources;
}
Also used : TriggerAttachment(games.strategy.triplea.attachments.TriggerAttachment) AbstractTriggerAttachment(games.strategy.triplea.attachments.AbstractTriggerAttachment) ArrayList(java.util.ArrayList) Resource(games.strategy.engine.data.Resource) ObjectiveDummyDelegateBridge(games.strategy.triplea.ui.ObjectiveDummyDelegateBridge) RulesAttachment(games.strategy.triplea.attachments.RulesAttachment) ICondition(games.strategy.triplea.attachments.ICondition) IDelegateBridge(games.strategy.engine.delegate.IDelegateBridge) HashSet(java.util.HashSet)

Example 5 with RulesAttachment

use of games.strategy.triplea.attachments.RulesAttachment in project triplea by triplea-game.

the class EndTurnDelegate method determineNationalObjectives.

/**
 * Determine if National Objectives have been met, and then do them.
 */
private String determineNationalObjectives(final IDelegateBridge bridge) {
    final GameData data = getData();
    final PlayerID player = data.getSequence().getStep().getPlayerId();
    // Find and test all the conditions for triggers and national objectives
    final Set<TriggerAttachment> triggers = new HashSet<>();
    final List<RulesAttachment> objectives = new ArrayList<>();
    final HashMap<ICondition, Boolean> testedConditions = testNationalObjectivesAndTriggers(player, data, bridge, triggers, objectives);
    // Execute triggers
    final StringBuilder endTurnReport = new StringBuilder();
    final boolean useTriggers = Properties.getTriggers(data);
    if (useTriggers && !triggers.isEmpty()) {
        final Set<TriggerAttachment> toFireTestedAndSatisfied = new HashSet<>(CollectionUtils.getMatches(triggers, AbstractTriggerAttachment.isSatisfiedMatch(testedConditions)));
        endTurnReport.append(TriggerAttachment.triggerResourceChange(toFireTestedAndSatisfied, bridge, null, null, true, true, true, true)).append("<br />");
    }
    // Execute national objectives
    for (final RulesAttachment rule : objectives) {
        int uses = rule.getUses();
        if (uses == 0 || !rule.isSatisfied(testedConditions)) {
            continue;
        }
        int toAdd = rule.getObjectiveValue();
        toAdd *= Properties.getPuMultiplier(data);
        toAdd *= rule.getEachMultiple();
        int total = player.getResources().getQuantity(Constants.PUS) + toAdd;
        if (total < 0) {
            toAdd -= total;
            total = 0;
        }
        final Change change = ChangeFactory.changeResourcesChange(player, data.getResourceList().getResource(Constants.PUS), toAdd);
        bridge.addChange(change);
        if (uses > 0) {
            uses--;
            final Change use = ChangeFactory.attachmentPropertyChange(rule, Integer.toString(uses), "uses");
            bridge.addChange(use);
        }
        final String puMessage = MyFormatter.attachmentNameToText(rule.getName()) + ": " + player.getName() + " met a national objective for an additional " + toAdd + MyFormatter.pluralize(" PU", toAdd) + "; end with " + total + MyFormatter.pluralize(" PU", total);
        bridge.getHistoryWriter().startEvent(puMessage);
        endTurnReport.append(puMessage).append("<br />");
    }
    return endTurnReport.toString();
}
Also used : TriggerAttachment(games.strategy.triplea.attachments.TriggerAttachment) AbstractTriggerAttachment(games.strategy.triplea.attachments.AbstractTriggerAttachment) PlayerID(games.strategy.engine.data.PlayerID) GameData(games.strategy.engine.data.GameData) ArrayList(java.util.ArrayList) CompositeChange(games.strategy.engine.data.CompositeChange) Change(games.strategy.engine.data.Change) RulesAttachment(games.strategy.triplea.attachments.RulesAttachment) ICondition(games.strategy.triplea.attachments.ICondition) HashSet(java.util.HashSet)

Aggregations

RulesAttachment (games.strategy.triplea.attachments.RulesAttachment)8 Territory (games.strategy.engine.data.Territory)5 ArrayList (java.util.ArrayList)5 Unit (games.strategy.engine.data.Unit)3 GameData (games.strategy.engine.data.GameData)2 PlayerID (games.strategy.engine.data.PlayerID)2 TripleAUnit (games.strategy.triplea.TripleAUnit)2 AbstractTriggerAttachment (games.strategy.triplea.attachments.AbstractTriggerAttachment)2 ICondition (games.strategy.triplea.attachments.ICondition)2 TerritoryAttachment (games.strategy.triplea.attachments.TerritoryAttachment)2 TriggerAttachment (games.strategy.triplea.attachments.TriggerAttachment)2 HashSet (java.util.HashSet)2 Change (games.strategy.engine.data.Change)1 CompositeChange (games.strategy.engine.data.CompositeChange)1 ITestDelegateBridge (games.strategy.engine.data.ITestDelegateBridge)1 Resource (games.strategy.engine.data.Resource)1 UnitType (games.strategy.engine.data.UnitType)1 IDelegateBridge (games.strategy.engine.delegate.IDelegateBridge)1 ProPlaceTerritory (games.strategy.triplea.ai.pro.data.ProPlaceTerritory)1 ProPurchaseTerritory (games.strategy.triplea.ai.pro.data.ProPurchaseTerritory)1