Ejemplo n.º 1
0
 /**
  * Let all players involved in this action know the action has failed.
  *
  * @param paa the political action attachment that just failed.
  */
 private void notifyFailure(final PoliticalActionAttachment paa) {
   getSoundChannel().playSoundForAll(SoundPath.CLIP_POLITICAL_ACTION_FAILURE, m_player);
   final String transcriptText =
       m_bridge.getPlayerID().getName()
           + " fails on action: "
           + MyFormatter.attachmentNameToText(paa.getName());
   m_bridge.getHistoryWriter().addChildToEvent(transcriptText);
   sendNotification(PoliticsText.getInstance().getNotificationFailure(paa.getText()));
   notifyOtherPlayers(paa, PoliticsText.getInstance().getNotificationFailureOthers(paa.getText()));
 }
Ejemplo n.º 2
0
 /**
  * @param paa the action to check if it succeeds
  * @return true if the action succeeds, usually because the die-roll succeeded.
  */
 private boolean actionRollSucceeds(final PoliticalActionAttachment paa) {
   final int hitTarget = paa.getChanceToHit();
   final int diceSides = paa.getChanceDiceSides();
   if (diceSides <= 0 || hitTarget >= diceSides) {
     paa.changeChanceDecrementOrIncrementOnSuccessOrFailure(m_bridge, true, true);
     return true;
   } else if (hitTarget <= 0) {
     paa.changeChanceDecrementOrIncrementOnSuccessOrFailure(m_bridge, false, true);
     return false;
   }
   final int rollResult =
       m_bridge.getRandom(
               diceSides,
               m_player,
               DiceType.NONCOMBAT,
               "Attempting the Political Action: "
                   + MyFormatter.attachmentNameToText(paa.getName()))
           + 1;
   final boolean success = rollResult <= hitTarget;
   final String notificationMessage =
       "rolling ("
           + hitTarget
           + " out of "
           + diceSides
           + ") result: "
           + rollResult
           + " = "
           + (success ? "Success!" : "Failure!");
   m_bridge
       .getHistoryWriter()
       .addChildToEvent(
           MyFormatter.attachmentNameToText(paa.getName()) + " : " + notificationMessage);
   paa.changeChanceDecrementOrIncrementOnSuccessOrFailure(m_bridge, success, true);
   sendNotification(notificationMessage);
   return success;
 }
Ejemplo n.º 3
0
 /**
  * Subtract money from the players wallet
  *
  * @param paa the politicalactionattachment this the money is charged for.
  */
 private void chargeForAction(final PoliticalActionAttachment paa) {
   final Resource PUs = getData().getResourceList().getResource(Constants.PUS);
   final int cost = paa.getCostPU();
   if (cost > 0) {
     // don't notify user of spending money anymore
     // notifyMoney(paa, true);
     final String transcriptText =
         m_bridge.getPlayerID().getName()
             + " spend "
             + cost
             + " PU on Political Action: "
             + MyFormatter.attachmentNameToText(paa.getName());
     m_bridge.getHistoryWriter().startEvent(transcriptText);
     final Change charge = ChangeFactory.changeResourcesChange(m_bridge.getPlayerID(), PUs, -cost);
     m_bridge.addChange(charge);
   } else {
     final String transcriptText =
         m_bridge.getPlayerID().getName()
             + " takes Political Action: "
             + MyFormatter.attachmentNameToText(paa.getName());
     // we must start an event anyway
     m_bridge.getHistoryWriter().startEvent(transcriptText);
   }
 }
Ejemplo n.º 4
0
 /**
  * Changes all relationships
  *
  * @param paa the political action to change the relationships for
  */
 private void changeRelationships(final PoliticalActionAttachment paa) {
   getMyselfOutOfAlliance(paa, m_player, m_bridge);
   getNeutralOutOfWarWithAllies(paa, m_player, m_bridge);
   final CompositeChange change = new CompositeChange();
   for (final String relationshipChange : paa.getRelationshipChange()) {
     final String[] s = relationshipChange.split(":");
     final PlayerID player1 = getData().getPlayerList().getPlayerID(s[0]);
     final PlayerID player2 = getData().getPlayerList().getPlayerID(s[1]);
     final RelationshipType oldRelation =
         getData().getRelationshipTracker().getRelationshipType(player1, player2);
     final RelationshipType newRelation =
         getData().getRelationshipTypeList().getRelationshipType(s[2]);
     if (oldRelation.equals(newRelation)) {
       continue;
     }
     change.add(ChangeFactory.relationshipChange(player1, player2, oldRelation, newRelation));
     m_bridge
         .getHistoryWriter()
         .addChildToEvent(
             m_bridge.getPlayerID().getName()
                 + " succeeds on action: "
                 + MyFormatter.attachmentNameToText(paa.getName())
                 + ": Changing Relationship for "
                 + player1.getName()
                 + " and "
                 + player2.getName()
                 + " from "
                 + oldRelation.getName()
                 + " to "
                 + newRelation.getName());
     MoveDelegate.getBattleTracker(getData())
         .addRelationshipChangesThisTurn(player1, player2, oldRelation, newRelation);
     /*
      * creation of new battles is handled at the beginning of the battle delegate, in
      * "setupUnitsInSameTerritoryBattles", not here.
      * if (Matches.RelationshipTypeIsAtWar.match(newRelation))
      * TriggerAttachment.triggerMustFightBattle(player1, player2, m_bridge);
      */
   }
   if (!change.isEmpty()) {
     m_bridge.addChange(change);
   }
   chainAlliancesTogether(m_bridge);
 }
Ejemplo n.º 5
0
 /**
  * Get a list of players that should accept this action and then ask each player if it accepts
  * this action.
  *
  * @param paa the politicalActionAttachment that should be accepted
  */
 private boolean actionIsAccepted(final PoliticalActionAttachment paa) {
   final GameData data = getData();
   final CompositeMatchOr<PoliticalActionAttachment> intoAlliedChainOrIntoOrOutOfWar =
       new CompositeMatchOr<>(
           Matches.politicalActionIsRelationshipChangeOf(
               null,
               Matches.RelationshipTypeIsAlliedAndAlliancesCanChainTogether.invert(),
               Matches.RelationshipTypeIsAlliedAndAlliancesCanChainTogether,
               data),
           Matches.politicalActionIsRelationshipChangeOf(
               null,
               Matches.RelationshipTypeIsAtWar.invert(),
               Matches.RelationshipTypeIsAtWar,
               data),
           Matches.politicalActionIsRelationshipChangeOf(
               null,
               Matches.RelationshipTypeIsAtWar,
               Matches.RelationshipTypeIsAtWar.invert(),
               data));
   if (!games.strategy.triplea.Properties.getAlliancesCanChainTogether(data)
       || !intoAlliedChainOrIntoOrOutOfWar.match(paa)) {
     for (final PlayerID player : paa.getActionAccept()) {
       if (!(getRemotePlayer(player))
           .acceptAction(
               m_player, PoliticsText.getInstance().getAcceptanceQuestion(paa.getText()), true)) {
         return false;
       }
     }
   } else {
     // if alliances chain together, then our allies must have a say in anyone becoming a new
     // ally/enemy
     final LinkedHashSet<PlayerID> playersWhoNeedToAccept = new LinkedHashSet<>();
     playersWhoNeedToAccept.addAll(paa.getActionAccept());
     playersWhoNeedToAccept.addAll(
         Match.getMatches(
             data.getPlayerList().getPlayers(),
             Matches.isAlliedAndAlliancesCanChainTogether(m_player, data)));
     for (final PlayerID player : paa.getActionAccept()) {
       playersWhoNeedToAccept.addAll(
           Match.getMatches(
               data.getPlayerList().getPlayers(),
               Matches.isAlliedAndAlliancesCanChainTogether(player, data)));
     }
     final HashSet<PlayerID> alliesWhoMustAccept = playersWhoNeedToAccept;
     alliesWhoMustAccept.removeAll(paa.getActionAccept());
     for (final PlayerID player : playersWhoNeedToAccept) {
       String actionText = PoliticsText.getInstance().getAcceptanceQuestion(paa.getText());
       if (actionText.equals("NONE")) {
         actionText =
             m_player.getName()
                 + " wants to take the following action: "
                 + MyFormatter.attachmentNameToText(paa.getName())
                 + " \r\n Do you approve?";
       } else {
         actionText =
             m_player.getName()
                 + " wants to take the following action: "
                 + MyFormatter.attachmentNameToText(paa.getName())
                 + ".  Do you approve? \r\n\r\n "
                 + m_player.getName()
                 + " will ask "
                 + MyFormatter.defaultNamedToTextList(paa.getActionAccept())
                 + ", the following question: \r\n "
                 + actionText;
       }
       if (!(getRemotePlayer(player)).acceptAction(m_player, actionText, true)) {
         return false;
       }
     }
     for (final PlayerID player : paa.getActionAccept()) {
       if (!(getRemotePlayer(player))
           .acceptAction(
               m_player, PoliticsText.getInstance().getAcceptanceQuestion(paa.getText()), true)) {
         return false;
       }
     }
   }
   return true;
 }
 private void fireRocket(
     final PlayerID player,
     final Territory attackedTerritory,
     final IDelegateBridge bridge,
     final Territory attackFrom) {
   final GameData data = bridge.getData();
   final PlayerID attacked = attackedTerritory.getOwner();
   final Resource PUs = data.getResourceList().getResource(Constants.PUS);
   final boolean DamageFromBombingDoneToUnits =
       isDamageFromBombingDoneToUnitsInsteadOfTerritories(data);
   // unit damage vs territory damage
   final Collection<Unit> enemyUnits =
       attackedTerritory
           .getUnits()
           .getMatches(
               new CompositeMatchAnd<Unit>(
                   Matches.enemyUnit(player, data), Matches.unitIsBeingTransported().invert()));
   final Collection<Unit> enemyTargetsTotal =
       Match.getMatches(
           enemyUnits, Matches.UnitIsAtMaxDamageOrNotCanBeDamaged(attackedTerritory).invert());
   final Collection<Unit> targets = new ArrayList<Unit>();
   final Collection<Unit> rockets;
   // attackFrom could be null if WW2V1
   if (attackFrom == null) rockets = null;
   else
     rockets =
         new ArrayList<Unit>(
             Match.getMatches(attackFrom.getUnits().getUnits(), rocketMatch(player, data)));
   final int numberOfAttacks =
       (rockets == null
           ? 1
           : Math.min(
               TechAbilityAttachment.getRocketNumberPerTerritory(player, data),
               TechAbilityAttachment.getRocketDiceNumber(rockets, data)));
   if (numberOfAttacks <= 0) return;
   final String transcript;
   if (DamageFromBombingDoneToUnits) {
     // TODO: rockets needs to be completely redone to allow for multiple rockets to fire at
     // different targets, etc etc.
     final HashSet<UnitType> legalTargetsForTheseRockets = new HashSet<UnitType>();
     if (rockets == null)
       legalTargetsForTheseRockets.addAll(data.getUnitTypeList().getAllUnitTypes());
     else {
       // a hack for now, we let the rockets fire at anyone who could be targetted by any rocket
       for (final Unit r : rockets) {
         legalTargetsForTheseRockets.addAll(
             UnitAttachment.get(r.getType()).getBombingTargets(data));
       }
     }
     final Collection<Unit> enemyTargets =
         Match.getMatches(enemyTargetsTotal, Matches.unitIsOfTypes(legalTargetsForTheseRockets));
     if (enemyTargets.isEmpty()) return; // TODO: this sucks
     Unit target = null;
     if (enemyTargets.size() == 1) target = enemyTargets.iterator().next();
     else {
       while (target == null) {
         final ITripleaPlayer iplayer = (ITripleaPlayer) bridge.getRemotePlayer(player);
         target = iplayer.whatShouldBomberBomb(attackedTerritory, enemyTargets, rockets);
       }
     }
     if (target == null)
       throw new IllegalStateException("No Targets in " + attackedTerritory.getName());
     targets.add(target);
   }
   final boolean doNotUseBombingBonus =
       !games.strategy.triplea.Properties.getUseBombingMaxDiceSidesAndBonus(data)
           || rockets == null;
   int cost = 0;
   if (!games.strategy.triplea.Properties.getLL_DAMAGE_ONLY(data)) {
     if (doNotUseBombingBonus || rockets == null) {
       // no low luck, and no bonus, so just roll based on the map's dice sides
       final int[] rolls =
           bridge.getRandom(
               data.getDiceSides(),
               numberOfAttacks,
               player,
               DiceType.BOMBING,
               "Rocket fired by " + player.getName() + " at " + attacked.getName());
       for (final int r : rolls) {
         cost += r + 1; // we are zero based
       }
       transcript =
           "Rockets "
               + (attackFrom == null ? "" : "in " + attackFrom.getName())
               + " roll: "
               + MyFormatter.asDice(rolls);
     } else {
       // we must use bombing bonus
       int highestMaxDice = 0;
       int highestBonus = 0;
       final int diceSides = data.getDiceSides();
       for (final Unit u : rockets) {
         final UnitAttachment ua = UnitAttachment.get(u.getType());
         int maxDice = ua.getBombingMaxDieSides();
         int bonus = ua.getBombingBonus();
         // both could be -1, meaning they were not set. if they were not set, then we use default
         // dice sides for the map, and zero for the bonus.
         if (maxDice < 0) maxDice = diceSides;
         if (bonus < 0) bonus = 0;
         // we only roll once for rockets, so if there are other rockets here we just roll for the
         // best rocket
         if ((bonus + ((maxDice + 1) / 2)) > (highestBonus + ((highestMaxDice + 1) / 2))) {
           highestMaxDice = maxDice;
           highestBonus = bonus;
         }
       }
       // now we roll, or don't if there is nothing to roll.
       if (highestMaxDice > 0) {
         final int[] rolls =
             bridge.getRandom(
                 highestMaxDice,
                 numberOfAttacks,
                 player,
                 DiceType.BOMBING,
                 "Rocket fired by " + player.getName() + " at " + attacked.getName());
         for (int i = 0; i < rolls.length; i++) {
           final int r = rolls[i] + highestBonus;
           rolls[i] = r;
           cost += r + 1; // we are zero based
         }
         transcript =
             "Rockets "
                 + (attackFrom == null ? "" : "in " + attackFrom.getName())
                 + " roll: "
                 + MyFormatter.asDice(rolls);
       } else {
         cost = highestBonus * numberOfAttacks;
         transcript =
             "Rockets "
                 + (attackFrom == null ? "" : "in " + attackFrom.getName())
                 + " do "
                 + highestBonus
                 + " damage for each rocket";
       }
     }
   } else {
     if (doNotUseBombingBonus || rockets == null) {
       // no bonus, so just roll based on the map's dice sides, but modify for LL
       final int maxDice = (data.getDiceSides() + 1) / 3;
       final int bonus = (data.getDiceSides() + 1) / 3;
       final int[] rolls =
           bridge.getRandom(
               maxDice,
               numberOfAttacks,
               player,
               DiceType.BOMBING,
               "Rocket fired by " + player.getName() + " at " + attacked.getName());
       for (int i = 0; i < rolls.length; i++) {
         final int r = rolls[i] + bonus;
         rolls[i] = r;
         cost += r + 1; // we are zero based
       }
       transcript =
           "Rockets "
               + (attackFrom == null ? "" : "in " + attackFrom.getName())
               + " roll: "
               + MyFormatter.asDice(rolls);
     } else {
       int highestMaxDice = 0;
       int highestBonus = 0;
       final int diceSides = data.getDiceSides();
       for (final Unit u : rockets) {
         final UnitAttachment ua = UnitAttachment.get(u.getType());
         int maxDice = ua.getBombingMaxDieSides();
         int bonus = ua.getBombingBonus();
         // both could be -1, meaning they were not set. if they were not set, then we use default
         // dice sides for the map, and zero for the bonus.
         if (maxDice < 0 || doNotUseBombingBonus) maxDice = diceSides;
         if (bonus < 0 || doNotUseBombingBonus) bonus = 0;
         // now, regardless of whether they were set or not, we have to apply "low luck" to them,
         // meaning in this case that we reduce the luck by 2/3.
         if (maxDice >= 5) {
           bonus += (maxDice + 1) / 3;
           maxDice = (maxDice + 1) / 3;
         }
         // we only roll once for rockets, so if there are other rockets here we just roll for the
         // best rocket
         if ((bonus + ((maxDice + 1) / 2)) > (highestBonus + ((highestMaxDice + 1) / 2))) {
           highestMaxDice = maxDice;
           highestBonus = bonus;
         }
       }
       // now we roll, or don't if there is nothing to roll.
       if (highestMaxDice > 0) {
         final int[] rolls =
             bridge.getRandom(
                 highestMaxDice,
                 numberOfAttacks,
                 player,
                 DiceType.BOMBING,
                 "Rocket fired by " + player.getName() + " at " + attacked.getName());
         for (int i = 0; i < rolls.length; i++) {
           final int r = rolls[i] + highestBonus;
           rolls[i] = r;
           cost += r + 1; // we are zero based
         }
         transcript =
             "Rockets "
                 + (attackFrom == null ? "" : "in " + attackFrom.getName())
                 + " roll: "
                 + MyFormatter.asDice(rolls);
       } else {
         cost = highestBonus * numberOfAttacks;
         transcript =
             "Rockets "
                 + (attackFrom == null ? "" : "in " + attackFrom.getName())
                 + " do "
                 + highestBonus
                 + " damage for each rocket";
       }
     }
   }
   int territoryProduction = TerritoryAttachment.getProduction(attackedTerritory);
   if (DamageFromBombingDoneToUnits && !targets.isEmpty()) {
     // we are doing damage to 'target', not to the territory
     final Unit target = targets.iterator().next();
     // UnitAttachment ua = UnitAttachment.get(target.getType());
     final TripleAUnit taUnit = (TripleAUnit) target;
     final int damageLimit = taUnit.getHowMuchMoreDamageCanThisUnitTake(target, attackedTerritory);
     cost = Math.max(0, Math.min(cost, damageLimit));
     final int totalDamage = taUnit.getUnitDamage() + cost;
     // Record production lost
     // DelegateFinder.moveDelegate(data).PUsLost(attackedTerritory, cost);
     // apply the hits to the targets
     final IntegerMap<Unit> damageMap = new IntegerMap<Unit>();
     damageMap.put(target, totalDamage);
     bridge.addChange(ChangeFactory.bombingUnitDamage(damageMap));
     // attackedTerritory.notifyChanged();
   }
   // in WW2V2, limit rocket attack cost to production value of factory.
   else if (isWW2V2(data) || isLimitRocketDamageToProduction(data)) {
     // If we are limiting total PUs lost then take that into account
     if (isPUCap(data) || isLimitRocketDamagePerTurn(data)) {
       final int alreadyLost = DelegateFinder.moveDelegate(data).PUsAlreadyLost(attackedTerritory);
       territoryProduction -= alreadyLost;
       territoryProduction = Math.max(0, territoryProduction);
     }
     if (cost > territoryProduction) {
       cost = territoryProduction;
     }
   }
   // Record the PUs lost
   DelegateFinder.moveDelegate(data).PUsLost(attackedTerritory, cost);
   if (DamageFromBombingDoneToUnits && !targets.isEmpty()) {
     getRemote(bridge)
         .reportMessage(
             "Rocket attack in "
                 + attackedTerritory.getName()
                 + " does "
                 + cost
                 + " damage to "
                 + targets.iterator().next(),
             "Rocket attack in "
                 + attackedTerritory.getName()
                 + " does "
                 + cost
                 + " damage to "
                 + targets.iterator().next());
     bridge
         .getHistoryWriter()
         .startEvent(
             "Rocket attack in "
                 + attackedTerritory.getName()
                 + " does "
                 + cost
                 + " damage to "
                 + targets.iterator().next());
   } else {
     cost *= Properties.getPU_Multiplier(data);
     getRemote(bridge)
         .reportMessage(
             "Rocket attack in " + attackedTerritory.getName() + " costs:" + cost,
             "Rocket attack in " + attackedTerritory.getName() + " costs:" + cost);
     // Trying to remove more PUs than the victim has is A Bad Thing[tm]
     final int availForRemoval = attacked.getResources().getQuantity(PUs);
     if (cost > availForRemoval) cost = availForRemoval;
     final String transcriptText =
         attacked.getName() + " lost " + cost + " PUs to rocket attack by " + player.getName();
     bridge.getHistoryWriter().startEvent(transcriptText);
     final Change rocketCharge = ChangeFactory.changeResourcesChange(attacked, PUs, -cost);
     bridge.addChange(rocketCharge);
   }
   bridge
       .getHistoryWriter()
       .addChildToEvent(transcript, rockets == null ? null : new ArrayList<Unit>(rockets));
   // this is null in WW2V1
   if (attackFrom != null) {
     if (rockets != null && !rockets.isEmpty()) {
       // TODO: only a certain number fired...
       final Change change =
           ChangeFactory.markNoMovementChange(Collections.singleton(rockets.iterator().next()));
       bridge.addChange(change);
     } else {
       throw new IllegalStateException("No rockets?" + attackFrom.getUnits().getUnits());
     }
   }
   // kill any units that can die if they have reached max damage (veqryn)
   if (Match.someMatch(targets, Matches.UnitCanDieFromReachingMaxDamage)) {
     final List<Unit> unitsCanDie =
         Match.getMatches(targets, Matches.UnitCanDieFromReachingMaxDamage);
     unitsCanDie.retainAll(
         Match.getMatches(
             unitsCanDie, Matches.UnitIsAtMaxDamageOrNotCanBeDamaged(attackedTerritory)));
     if (!unitsCanDie.isEmpty()) {
       // targets.removeAll(unitsCanDie);
       final Change removeDead = ChangeFactory.removeUnits(attackedTerritory, unitsCanDie);
       final String transcriptText =
           MyFormatter.unitsToText(unitsCanDie) + " lost in " + attackedTerritory.getName();
       bridge.getHistoryWriter().addChildToEvent(transcriptText, unitsCanDie);
       bridge.addChange(removeDead);
     }
   }
   // play a sound
   if (cost > 0)
     bridge
         .getSoundChannelBroadcaster()
         .playSoundForAll(SoundPath.CLIP_BOMBING_ROCKET, player.getName());
 }