From e61f7dcf1fc02b29907480550d05188a8b2f3da5 Mon Sep 17 00:00:00 2001 From: Scoppio Date: Mon, 2 Dec 2024 23:18:58 -0300 Subject: [PATCH] fix: fixing bug with Units matter force construction --- .../resources/AutoResolveMethod.properties | 6 ++ .../CampaignOptionsDialog.properties | 9 ++- MekHQ/src/mekhq/MekHQ.java | 72 +++++++++++++++++-- MekHQ/src/mekhq/campaign/CampaignOptions.java | 32 ++++++--- .../autoResolve/AutoResolveEngine.java | 9 ++- .../autoResolve/AutoResolveMethod.java | 55 ++++++++++++-- .../autoResolve/helper/SetupForces.java | 19 +++-- .../autoResolve/helper/SetupTeams.java | 52 +++++++++++--- .../scenarioResolver/ScenarioResolver.java | 3 +- MekHQ/src/mekhq/gui/BriefingTab.java | 8 +-- .../dialog/ResolveScenarioWizardDialog.java | 2 + .../mekhq/gui/panes/CampaignOptionsPane.java | 36 ++++++++-- 12 files changed, 251 insertions(+), 52 deletions(-) create mode 100644 MekHQ/resources/mekhq/resources/AutoResolveMethod.properties diff --git a/MekHQ/resources/mekhq/resources/AutoResolveMethod.properties b/MekHQ/resources/mekhq/resources/AutoResolveMethod.properties new file mode 100644 index 0000000000..68926b8819 --- /dev/null +++ b/MekHQ/resources/mekhq/resources/AutoResolveMethod.properties @@ -0,0 +1,6 @@ +AutoResolveMethod.PRINCESS.text=Princess +AutoResolveMethod.PRINCESS.toolTipText=Princess +AutoResolveMethod.UNITS_MATTER.text=Units Matter +AutoResolveMethod.UNITS_MATTER.toolTipText=Units Matter +AutoResolveMethod.ABSTRACT_COMBAT.text=Abstract Combat +AutoResolveMethod.ABSTRACT_COMBAT.toolTipText=Abstract Combat \ No newline at end of file diff --git a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties index 0d13950089..4b090f1a05 100644 --- a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties +++ b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties @@ -890,6 +890,8 @@ chkUseStratCon.text=Use StratCon campaign rules chkUseStratCon.toolTipText=An update of the AtB ruleset. lblSkillLevel.text=Skill Level lblSkillLevel.toolTipText=This is the difficulty level for generated scenarios.
Values above Elite are not recommended. +lblAutoResolveType.text=Auto Resolve method: +lblAutoResolveType.toolTipText=Auto resolve to use in campaign play.
Princess: The bot plays the MM game in your place.
Units Matter: A very fast simulation focused on speed.
Abstract Combat: Complex simulation well suited for very large confrontations. lblScenarioMod.text=Random Scenario Modifiers lblScenarioModMax.text=Maximum: lblScenarioModMax.toolTipText=This is the maximum number of random scenario mods that can spawn on for a single Scenario. Excludes StratCon facility modifiers. @@ -966,8 +968,11 @@ chkRegionalMekVariations.text=Varied weight distributions by faction chkRegionalMekVariations.toolTipText=Use alternate weight class distributions for some factions. chkAttachedPlayerCamouflage.text=Player-controlled allied units use player's camouflage chkPlayerControlsAttachedUnits.text=All attached allied units are player controlled -chkUseBotControlledAutoResolve.text=Bots play auto resolve -chkUseBotControlledAutoResolve.toolTipText=If checked, auto resolve will open a game and add all your units to a bot on your team, otherwise, auto resolve will use Abstract Combat System to resolve the scenarios. +chkUseBotControlledAutoResolveAARC.text=Auto Resolve using Abstract Auto Resolve Combat +chkUseBotControlledAutoResolve.text=Auto Resolve using Bots +chkUseBotControlledAutoResolve.toolTipText=If checked, auto resolve will open a game and add all your units to a bot on your team, otherwise, auto resolve will use Abstract Auto Resolve Combat to resolve the scenarios. +chkAutoResolveVictoryChanceEnabled.text=Show auto resolve victory chance +chkAutoResolveVictoryChanceEnabled.toolTipText=If checked, the pre-auto resolve dialog will show the chance of victory for the player. Only works when using Abstract Auto Resolve Combat. chkUseWeatherConditions.text=Use weather conditions chkUseWeatherConditions.toolTipText=Generate weather conditions when generating a scenario. chkUseLightConditions.text=Use light conditions diff --git a/MekHQ/src/mekhq/MekHQ.java b/MekHQ/src/mekhq/MekHQ.java index 4584159393..64fa7811da 100644 --- a/MekHQ/src/mekhq/MekHQ.java +++ b/MekHQ/src/mekhq/MekHQ.java @@ -48,7 +48,6 @@ import mekhq.campaign.ResolveScenarioTracker; import mekhq.campaign.ResolveScenarioTracker.PersonStatus; import mekhq.campaign.autoResolve.AutoResolveEngine; -import mekhq.campaign.autoResolve.AutoResolveGame; import mekhq.campaign.autoResolve.AutoResolveMethod; import mekhq.campaign.autoResolve.helper.AutoResolveClient; import mekhq.campaign.autoResolve.scenarioResolver.components.AutoResolveConcludedEvent; @@ -80,9 +79,10 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.ObjectInputFilter.Config; -import java.util.HashMap; +import java.util.*; import java.util.List; -import java.util.UUID; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Stream; /** @@ -527,6 +527,7 @@ public void gamePhaseChange(GamePhaseChangeEvent e) { // Why Empty? } + // TODO: LUANA public void autoResolveConcluded(AutoResolveConcludedEvent autoResolveConcludedEvent){ try { String message = autoResolveConcludedEvent.controlledScenario() ? @@ -693,11 +694,15 @@ public void gameVictory(PostGameResolution gve) { final File tempImageDirectory = new File("data/images/temp"); if (tempImageDirectory.isDirectory()) { // This can't be null because of the above - Stream.of(tempImageDirectory.listFiles()).filter(file -> file.getName().endsWith(".png")) - .forEach(File::delete); + var totalDeletedFiles = Stream.of(Objects.requireNonNull(tempImageDirectory.listFiles())) + .filter(file -> file.getName().endsWith(".png")) + .map(File::delete) + .mapToInt(result -> result ? 1 : 0) + .sum(); + logger.info("Deleted {} temporary image files", totalDeletedFiles); } } catch (Exception ex) { - logger.error(ex, "gameVictory()"); + logger.error("Exception during gameVictory() run", ex); } } @@ -802,7 +807,60 @@ public static void updateGuiScaling() { public void startAutoResolve(AtBScenario scenario, List units) { currentScenario = scenario; - new AutoResolveEngine(AutoResolveMethod.ABSTRACT_COMBAT_SYSTEM).resolveBattle(this, units, scenario); + String message = "This will auto resolve the battle. Do you want to proceed?"; + var autoResolveMethod = getCampaign().getCampaignOptions().getAutoResolveMethod(); + if (getCampaign().getCampaignOptions().isAutoResolveVictoryChanceEnabled() + // unfortunately UNITS MATTER force creating has a bug that makes it impossible to calculate victory chance without causing + // irreversible changes to the campaign + && autoResolveMethod.equals(AutoResolveMethod.ABSTRACT_COMBAT)) { + + var percent = calculateVictoryChance(scenario, units); + message = "Your chance of victory in this combat is " + percent + "%, do you want to proceed?"; + } + String title = "Auto Resolve Battle"; + boolean proceed = JOptionPane.showConfirmDialog(campaignGUI.getFrame(), message, title, JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION; + + if (proceed) { + new AutoResolveEngine(autoResolveMethod) + .resolveBattle(this, units, scenario, this::autoResolveConcluded); + } + } + + /** + * Calculates the victory chance for a given scenario and list of units by running multiple auto resolve scenarios in parallel. + * + * @param scenario the scenario to resolve + * @param units the list of units involved in the scenario + * @return the calculated victory chance as an integer percentage (0 to 100) + */ + private int calculateVictoryChance(AtBScenario scenario, List units) { + var atomicInt = new AtomicInteger(0); + int numTasks = 50; + ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); + List> futures = new ArrayList<>(); + + for (int i = 0; i < numTasks; i++) { + futures.add(executor.submit(() -> { + new AutoResolveEngine(AutoResolveMethod.ABSTRACT_COMBAT) + .resolveBattle(this, units, scenario, r -> { + if (r.controlledScenario()) { + atomicInt.incrementAndGet(); + } + }); + })); + } + + // Wait for all tasks to complete + for (Future future : futures) { + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + logger.error("Error in parallel execution", e); + } + } + + executor.shutdown(); + return atomicInt.get() * 2; } private static class MekHqPropertyChangedListener implements PropertyChangeListener { diff --git a/MekHQ/src/mekhq/campaign/CampaignOptions.java b/MekHQ/src/mekhq/campaign/CampaignOptions.java index bee8e940cf..4ec82a9c37 100644 --- a/MekHQ/src/mekhq/campaign/CampaignOptions.java +++ b/MekHQ/src/mekhq/campaign/CampaignOptions.java @@ -27,6 +27,7 @@ import megamek.logging.MMLogger; import mekhq.MekHQ; import mekhq.Utilities; +import mekhq.campaign.autoResolve.AutoResolveMethod; import mekhq.campaign.enums.PlanetaryAcquisitionFactionLimit; import mekhq.campaign.finances.Money; import mekhq.campaign.finances.enums.FinancialYearDuration; @@ -600,7 +601,8 @@ public static String getTransitUnitName(final int unit) { private int scenarioModChance; private int scenarioModBV; private boolean autoConfigMunitions; - private boolean princessBotAutoResolve; + private AutoResolveMethod autoResolveMethod; + private boolean autoResolveVictoryChanceEnabled; // endregion Against the Bot Tab // endregion Variable Declarations @@ -1191,7 +1193,8 @@ public CampaignOptions() { useAtB = false; useStratCon = false; setSkillLevel(SkillLevel.REGULAR); - princessBotAutoResolve = true; + autoResolveMethod = AutoResolveMethod.PRINCESS; + autoResolveVictoryChanceEnabled = false; // Unit Administration useAero = false; @@ -5163,7 +5166,8 @@ public void writeToXml(final PrintWriter pw, int indent) { // region AtB Tab MHQXMLUtility.writeSimpleXMLTag(pw, indent, "skillLevel", getSkillLevel().name()); - MHQXMLUtility.writeSimpleXMLTag(pw, indent, "princessBotAutoResolve", isPrincessBotAutoResolve()); + MHQXMLUtility.writeSimpleXMLTag(pw, indent, "autoResolveMethod", getAutoResolveMethod().name()); + MHQXMLUtility.writeSimpleXMLTag(pw, indent, "autoResolveVictoryChanceEnabled", isAutoResolveVictoryChanceEnabled()); // endregion AtB Tab MHQXMLUtility.writeSimpleXMLTag(pw, indent, "phenotypeProbabilities", phenotypeProbabilities); @@ -6148,8 +6152,10 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve // region AtB Tab } else if (wn2.getNodeName().equalsIgnoreCase("skillLevel")) { retVal.setSkillLevel(SkillLevel.valueOf(wn2.getTextContent().trim())); - } else if (wn2.getNodeName().equalsIgnoreCase("princessBotAutoResolve")) { - retVal.setPrincessBotAutoResolve(Boolean.parseBoolean(wn2.getTextContent().trim())); + } else if (wn2.getNodeName().equalsIgnoreCase("autoResolveMethod")) { + retVal.setAutoResolveMethod(AutoResolveMethod.valueOf(wn2.getTextContent().trim())); + } else if (wn2.getNodeName().equalsIgnoreCase("autoResolveVictoryChanceEnabled")) { + retVal.setAutoResolveVictoryChanceEnabled(Boolean.parseBoolean(wn2.getTextContent().trim())); // endregion AtB Tab } else if (wn2.getNodeName().equalsIgnoreCase("phenotypeProbabilities")) { @@ -6424,12 +6430,20 @@ public void migrateMarriageSurnameWeights47(final String... values) { } } - public boolean isPrincessBotAutoResolve() { - return princessBotAutoResolve; + public AutoResolveMethod getAutoResolveMethod() { + return autoResolveMethod; } - public void setPrincessBotAutoResolve(final boolean princessBotAutoResolve) { - this.princessBotAutoResolve = princessBotAutoResolve; + public void setAutoResolveMethod(final AutoResolveMethod autoResolveMethod) { + this.autoResolveMethod = autoResolveMethod; + } + + public boolean isAutoResolveVictoryChanceEnabled() { + return autoResolveVictoryChanceEnabled; + } + + public void setAutoResolveVictoryChanceEnabled(final boolean autoResolveVictoryChanceEnabled) { + this.autoResolveVictoryChanceEnabled = autoResolveVictoryChanceEnabled; } // endregion File IO diff --git a/MekHQ/src/mekhq/campaign/autoResolve/AutoResolveEngine.java b/MekHQ/src/mekhq/campaign/autoResolve/AutoResolveEngine.java index 7f444d57ee..7f45693f66 100644 --- a/MekHQ/src/mekhq/campaign/autoResolve/AutoResolveEngine.java +++ b/MekHQ/src/mekhq/campaign/autoResolve/AutoResolveEngine.java @@ -14,10 +14,15 @@ package mekhq.campaign.autoResolve; import mekhq.MekHQ; +import mekhq.campaign.autoResolve.scenarioResolver.components.AutoResolveConcludedEvent; import mekhq.campaign.mission.AtBScenario; import mekhq.campaign.unit.Unit; import java.util.List; +import java.util.concurrent.Callable; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; /** * @author Luana Coppio @@ -30,11 +35,11 @@ public AutoResolveEngine(AutoResolveMethod method) { this.autoResolveMethod = method; } - public void resolveBattle(MekHQ app, List units, AtBScenario scenario) { + public void resolveBattle(MekHQ app, List units, AtBScenario scenario, Consumer autoResolveConcludedEvent) { var scenarioSpecificResolutionResolver = autoResolveMethod.of(scenario); var game = new AutoResolveGame(app, units, scenario); var result = scenarioSpecificResolutionResolver.resolveScenario(game); - app.autoResolveConcluded(result); + autoResolveConcludedEvent.accept(result); } } diff --git a/MekHQ/src/mekhq/campaign/autoResolve/AutoResolveMethod.java b/MekHQ/src/mekhq/campaign/autoResolve/AutoResolveMethod.java index 3c29b96e1b..ba96b29060 100644 --- a/MekHQ/src/mekhq/campaign/autoResolve/AutoResolveMethod.java +++ b/MekHQ/src/mekhq/campaign/autoResolve/AutoResolveMethod.java @@ -13,35 +13,78 @@ */ package mekhq.campaign.autoResolve; +import megamek.MegaMek; +import mekhq.MekHQ; import mekhq.campaign.autoResolve.scenarioResolver.ScenarioResolver; import mekhq.campaign.autoResolve.scenarioResolver.abstractCombatSystem.AcsSimpleScenarioResolver; import mekhq.campaign.autoResolve.scenarioResolver.unitsMatter.UnitsMatterSimpleScenarioResolver; import mekhq.campaign.mission.AtBScenario; +import java.util.Optional; +import java.util.ResourceBundle; + /** * @author Luana Coppio */ public enum AutoResolveMethod { - UNITS_MATTER(){ + PRINCESS("AutoResolveMethod.PRINCESS.text", "AutoResolveMethod.PRINCESS.toolTipText") { + @Override + public ScenarioResolver of(AtBScenario scenario) { + throw new UnsupportedOperationException("Princess method not implemented"); + } + }, + UNITS_MATTER("AutoResolveMethod.UNITS_MATTER.text", "AutoResolveMethod.UNITS_MATTER.toolTipText") { @Override public ScenarioResolver of(AtBScenario scenario) { return new UnitsMatterSimpleScenarioResolver(scenario); } }, - ABSTRACT_COMBAT_SYSTEM() { + ABSTRACT_COMBAT("AutoResolveMethod.ABSTRACT_COMBAT.text", "AutoResolveMethod.ABSTRACT_COMBAT.toolTipText") { @Override public ScenarioResolver of(AtBScenario scenario) { return new AcsSimpleScenarioResolver(scenario); } }; - public static AutoResolveMethod fromString(String method) { + private final String name; + private final String toolTipText; + + AutoResolveMethod(final String name, final String toolTipText) { + final ResourceBundle resources = ResourceBundle.getBundle("mekhq.resources.AutoResolveMethod", + MekHQ.getMHQOptions().getLocale()); + this.name = resources.getString(name); + this.toolTipText = resources.getString(toolTipText); + } + + public String getToolTipText() { + return toolTipText; + } + + public String getName() { + return name; + } + + public static Optional fromInteger(int index) { + if (index < 0 || index >= values().length) { + return Optional.empty(); + } + return Optional.of(values()[index]); + } + + public static Optional fromString(String method) { return switch (method) { - case "UNITS_MATTER" -> UNITS_MATTER; - case "ABSTRACT_COMBAT_SYSTEM" -> ABSTRACT_COMBAT_SYSTEM; - default -> throw new IllegalArgumentException("Invalid method: " + method); + case "PRINCESS" -> Optional.of(PRINCESS); + case "UNITS_MATTER" -> Optional.of(UNITS_MATTER); + case "ABSTRACT_COMBAT_SYSTEM" -> Optional.of(ABSTRACT_COMBAT); + default -> Optional.empty(); }; } public abstract ScenarioResolver of(AtBScenario scenario); + + @Override + public String toString() { + return name; + } } + diff --git a/MekHQ/src/mekhq/campaign/autoResolve/helper/SetupForces.java b/MekHQ/src/mekhq/campaign/autoResolve/helper/SetupForces.java index 88663657eb..ec573ca0d6 100644 --- a/MekHQ/src/mekhq/campaign/autoResolve/helper/SetupForces.java +++ b/MekHQ/src/mekhq/campaign/autoResolve/helper/SetupForces.java @@ -166,8 +166,7 @@ private void setupPlayerForces(Campaign campaign, List units, AtBScenario if (force != null) { entity.setForceString(force.getFullMMName()); } - - var newCrewRef = getNewCrewRef(unit); + var newCrewRef = getNewCrewRef(unit.getEntity().getCrew()); entity.setCrew(newCrewRef); entities.add(entity); } @@ -202,8 +201,8 @@ private void setupPlayerForces(Campaign campaign, List units, AtBScenario sendEntities(entities); } - private static Crew getNewCrewRef(Unit unit) { - var originalCrew = unit.getEntity().getCrew(); + public static Crew getNewCrewRef(Crew originalCrew) { + var newCrewRef = new Crew(originalCrew.getCrewType(), originalCrew.getName(), originalCrew.getSize(), originalCrew.getGunnery(), originalCrew.getPiloting(), originalCrew.getGender(), originalCrew.isClanPilot(), originalCrew.getExtraData()); @@ -282,9 +281,19 @@ private void setupBotEntities(Player bot, BotForce botForce) { String forceName = bot.getName() + "|1"; var entities = new ArrayList(); botForce.generateRandomForces(units, campaign); - for (Entity entity : botForce.getFullEntityList(campaign)) { + for (Entity originalBotEntity : botForce.getFullEntityList(campaign)) { + var entity = ASConverter.getUndamagedEntity(originalBotEntity); + if (entity == null) { + logger.warn("Could not convert entity for bot {} - {}", bot.getName(), originalBotEntity); + continue; + } + entity.setOwner(bot); entity.setForceString(forceName); + entity.setCrew(getNewCrewRef(entity.getCrew())); + entity.setId(originalBotEntity.getId()); + entity.setExternalIdAsString(originalBotEntity.getExternalIdAsString()); + entity.setCommander(originalBotEntity.isCommander()); if (entity.getDeployRound() == 0) { entity.setDeployRound(botForce.getDeployRound()); diff --git a/MekHQ/src/mekhq/campaign/autoResolve/helper/SetupTeams.java b/MekHQ/src/mekhq/campaign/autoResolve/helper/SetupTeams.java index ca1352bc09..4ba498ef8d 100644 --- a/MekHQ/src/mekhq/campaign/autoResolve/helper/SetupTeams.java +++ b/MekHQ/src/mekhq/campaign/autoResolve/helper/SetupTeams.java @@ -2,19 +2,17 @@ import megamek.client.generator.RandomCallsignGenerator; import megamek.common.*; -import mekhq.MekHQ; +import megamek.common.alphaStrike.conversion.ASConverter; +import megamek.common.annotations.Nullable; import mekhq.campaign.Campaign; import mekhq.campaign.autoResolve.scenarioResolver.components.AutoResolveForce; - -import mekhq.campaign.mission.AtBContract; -import mekhq.campaign.mission.AtBScenario; -import mekhq.campaign.mission.BotForce; -import mekhq.campaign.mission.Scenario; +import mekhq.campaign.mission.*; import mekhq.campaign.unit.Unit; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; +import static mekhq.campaign.autoResolve.helper.SetupForces.getNewCrewRef; import static mekhq.campaign.force.StrategicFormation.getStandardForceSize; public class SetupTeams { @@ -44,7 +42,38 @@ static private List getBotForces(Campaign campaign, List } static private AutoResolveForce playerForce(int playerID, String forceName, List units) { - return new AutoResolveForce(1, forceName, playerID, units.stream().map(Unit::getEntity).toList()); + return new AutoResolveForce(1, forceName, playerID, units.stream().map(SetupTeams::breakEntityRef).filter(Objects::nonNull).toList()); + } + + @Nullable + public static Entity breakEntityRef(Unit unit) { + var entity = ASConverter.getUndamagedEntity(unit.getEntity()); + // Set the TempID for auto reporting + if (Objects.isNull(entity)) { + return null; + } + + entity.setExternalIdAsString(unit.getId().toString()); + // Set the owner + entity.setOwner(unit.getCampaign().getPlayer()); + + // If this unit is a spacecraft, set the crew size and marine size values + if (entity.isLargeCraft() || (entity.getUnitType() == UnitType.SMALL_CRAFT)) { + entity.setNCrew(unit.getActiveCrew().size()); + entity.setNMarines(unit.getMarineCount()); + } + // Calculate deployment round + int deploymentRound = entity.getDeployRound(); + + entity.setDeployRound(deploymentRound); + var force = unit.getCampaign().getForceFor(unit); + if (force != null) { + entity.setForceString(force.getFullMMName()); + } + var newCrewRef = getNewCrewRef(unit.getEntity().getCrew()); + entity.setCrew(newCrewRef); + + return entity; } static private List setupBotEntities(Campaign campaign, List units, BotForce botForce, Scenario scenario, int forceID) { @@ -74,12 +103,18 @@ static private List setupBotEntities(Campaign campaign, List units comp = comp.thenComparing(((Entity e) -> e.getRole().toString())); entitiesSorted.sort(comp); - for (Entity entity : entitiesSorted) { + for (Entity originalEntity : entitiesSorted) { + if (null == originalEntity) { + continue; + } + var entity = ASConverter.getUndamagedEntity(originalEntity); if (null == entity) { continue; } entity.setForceId(forceID); entity.setOwner(player); + entity.setCrew(getNewCrewRef(originalEntity.getCrew())); + entity.setDeployRound(originalEntity.getDeployRound()); if ((i != 0) && !lastType.equals(Entity.getEntityMajorTypeName(entity.getEntityType()))) { forceIdLance++; @@ -91,6 +126,7 @@ static private List setupBotEntities(Campaign campaign, List units String fName = String.format(forceName, lanceName, forceIdLance); entity.setForceString(fName); entity.setDestroyed(false); + entities.add(entity); i++; if (entity instanceof GunEmplacement gun) { diff --git a/MekHQ/src/mekhq/campaign/autoResolve/scenarioResolver/ScenarioResolver.java b/MekHQ/src/mekhq/campaign/autoResolve/scenarioResolver/ScenarioResolver.java index a4ce03ded4..d37f9af6aa 100644 --- a/MekHQ/src/mekhq/campaign/autoResolve/scenarioResolver/ScenarioResolver.java +++ b/MekHQ/src/mekhq/campaign/autoResolve/scenarioResolver/ScenarioResolver.java @@ -33,8 +33,9 @@ protected ScenarioResolver(AtBScenario scenario) { public static ScenarioResolver of(AutoResolveMethod method, AtBScenario scenario) { return switch (method) { + case PRINCESS -> throw new UnsupportedOperationException("Princess method is not run here!"); case UNITS_MATTER -> new UnitsMatterSimpleScenarioResolver(scenario); - case ABSTRACT_COMBAT_SYSTEM -> new AcsSimpleScenarioResolver(scenario); + case ABSTRACT_COMBAT -> new AcsSimpleScenarioResolver(scenario); }; } diff --git a/MekHQ/src/mekhq/gui/BriefingTab.java b/MekHQ/src/mekhq/gui/BriefingTab.java index eabe391d8c..a0bcd42608 100644 --- a/MekHQ/src/mekhq/gui/BriefingTab.java +++ b/MekHQ/src/mekhq/gui/BriefingTab.java @@ -36,7 +36,6 @@ import mekhq.campaign.Kill; import mekhq.campaign.ResolveScenarioTracker; import mekhq.campaign.ResolveScenarioTracker.PersonStatus; -import mekhq.campaign.autoResolve.AutoResolveEngine; import mekhq.campaign.event.*; import mekhq.campaign.finances.Money; import mekhq.campaign.finances.enums.TransactionType; @@ -871,11 +870,10 @@ private void autoResolveScenario() { if (scenario == null) { return; } - if (getCampaignOptions().isPrincessBotAutoResolve()) { - startScenario(getCampaign().getAutoResolveBehaviorSettings()); - } else { - getCampaignGui().getApplication() + switch(getCampaignOptions().getAutoResolveMethod()) { + case ABSTRACT_COMBAT, UNITS_MATTER-> getCampaignGui().getApplication() .startAutoResolve((AtBScenario) scenario, playerUnits(scenario, new StringBuilder())); + case PRINCESS -> startScenario(getCampaign().getAutoResolveBehaviorSettings()); } } diff --git a/MekHQ/src/mekhq/gui/dialog/ResolveScenarioWizardDialog.java b/MekHQ/src/mekhq/gui/dialog/ResolveScenarioWizardDialog.java index dfac268d74..72ddd79839 100644 --- a/MekHQ/src/mekhq/gui/dialog/ResolveScenarioWizardDialog.java +++ b/MekHQ/src/mekhq/gui/dialog/ResolveScenarioWizardDialog.java @@ -1642,10 +1642,12 @@ private void finish() { StratconRulesManager.processScenarioCompletion(tracker); aborted = false; this.setVisible(false); + dispose(); } private void cancel() { setVisible(false); + dispose(); } // region Misc II diff --git a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java index 264a380d5b..80a882f387 100644 --- a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java +++ b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java @@ -43,6 +43,7 @@ import mekhq.campaign.CampaignOptions; import mekhq.campaign.CampaignPreset; import mekhq.campaign.RandomSkillPreferences; +import mekhq.campaign.autoResolve.AutoResolveMethod; import mekhq.campaign.enums.PlanetaryAcquisitionFactionLimit; import mekhq.campaign.event.OptionsChangedEvent; import mekhq.campaign.finances.enums.FinancialYearDuration; @@ -647,6 +648,7 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { private JCheckBox chkUseAtB; private JCheckBox chkUseStratCon; private MMComboBox comboSkillLevel; + private MMComboBox comboAutoResolveType; // unit administration private JCheckBox chkUseAero; @@ -688,7 +690,8 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { private JCheckBox chkRegionalMekVariations; private JCheckBox chkAttachedPlayerCamouflage; private JCheckBox chkPlayerControlsAttachedUnits; - private JCheckBox chkUseBotControlledAutoResolve; + + private JCheckBox chkAutoResolveVictoryChanceEnabled; private JCheckBox chkUseDropShips; private JCheckBox chkUseWeatherConditions; private JCheckBox chkUseLightConditions; @@ -3364,14 +3367,31 @@ private JScrollPane createAgainstTheBotTab() { gridBagConstraints.gridy = yTablePosition++; panSubAtBScenario.add(chkPlayerControlsAttachedUnits, gridBagConstraints); - chkUseBotControlledAutoResolve = new JCheckBox( - resources.getString("chkUseBotControlledAutoResolve.text")); - chkUseBotControlledAutoResolve.setToolTipText(resources.getString("chkUseBotControlledAutoResolve.toolTipText")); + JLabel lblAutoResolveType = new JLabel(resources.getString("lblAutoResolveType.text")); + gridBagConstraints.gridx = 0; gridBagConstraints.gridy = yTablePosition++; - panSubAtBScenario.add(chkUseBotControlledAutoResolve, gridBagConstraints); + gridBagConstraints.gridwidth = 1; + panSubAtBScenario.add(lblAutoResolveType, gridBagConstraints); + + final DefaultComboBoxModel autoResolveTypeModel = new DefaultComboBoxModel<>( + AutoResolveMethod.values()); + comboAutoResolveType = new MMComboBox<>("comboAutoResolveType", autoResolveTypeModel); + comboAutoResolveType.setToolTipText(resources.getString("lblAutoResolveType.toolTipText")); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = yTablePosition; + panSubAtBScenario.add(comboAutoResolveType, gridBagConstraints); + + chkAutoResolveVictoryChanceEnabled = new JCheckBox( + resources.getString("chkAutoResolveVictoryChanceEnabled.text")); + chkAutoResolveVictoryChanceEnabled.setToolTipText( + resources.getString("chkAutoResolveVictoryChanceEnabled.toolTipText")); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = yTablePosition++; + panSubAtBScenario.add(chkAutoResolveVictoryChanceEnabled, gridBagConstraints); chkUseDropShips = new JCheckBox(resources.getString("chkUseDropShips.text")); chkUseDropShips.setToolTipText(resources.getString("chkUseDropShips.toolTipText")); + gridBagConstraints.gridx = 0; gridBagConstraints.gridy = yTablePosition++; panSubAtBScenario.add(chkUseDropShips, gridBagConstraints); @@ -8969,7 +8989,8 @@ public void setOptions(@Nullable CampaignOptions options, chkRegionalMekVariations.setSelected(options.isRegionalMekVariations()); chkAttachedPlayerCamouflage.setSelected(options.isAttachedPlayerCamouflage()); chkPlayerControlsAttachedUnits.setSelected(options.isPlayerControlsAttachedUnits()); - chkUseBotControlledAutoResolve.setSelected(options.isPrincessBotAutoResolve()); + comboAutoResolveType.setSelectedItem(options.getAutoResolveMethod()); + chkAutoResolveVictoryChanceEnabled.setSelected(options.isAutoResolveVictoryChanceEnabled()); chkUseDropShips.setSelected(options.isUseDropShips()); chkUseWeatherConditions.setSelected(options.isUseWeatherConditions()); chkUseLightConditions.setSelected(options.isUseLightConditions()); @@ -9572,7 +9593,8 @@ public void updateOptions() { options.setRegionalMekVariations(chkRegionalMekVariations.isSelected()); options.setAttachedPlayerCamouflage(chkAttachedPlayerCamouflage.isSelected()); options.setPlayerControlsAttachedUnits(chkPlayerControlsAttachedUnits.isSelected()); - options.setPrincessBotAutoResolve(chkUseBotControlledAutoResolve.isSelected()); + options.setAutoResolveMethod(comboAutoResolveType.getSelectedItem()); + options.setAutoResolveVictoryChanceEnabled(chkAutoResolveVictoryChanceEnabled.isSelected()); options.setUseWeatherConditions(chkUseWeatherConditions.isSelected()); options.setUseLightConditions(chkUseLightConditions.isSelected()); options.setUsePlanetaryConditions(chkUsePlanetaryConditions.isSelected());