Skip to content

Commit a341db7

Browse files
authored
Merge pull request #8762 from capellancitizen/fix-botforce-generator
Fixed BotForceRandomizer throwing/generating nothing when weight class not set
2 parents ff6d6ea + 94339a0 commit a341db7

2 files changed

Lines changed: 127 additions & 1 deletion

File tree

MekHQ/src/mekhq/campaign/mission/BotForceRandomizer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ public List<Entity> generateForce(List<Unit> playerUnits, List<Entity> botFixedE
302302
// distribution is centered on the focal weight class and has some chance of
303303
// going higher
304304
// or lower. The scale parameter of 0.4 produces a reasonable variance.
305-
GammaDistribution gamma = new GammaDistribution(focalWeightClass / 0.4, 0.4);
305+
GammaDistribution gamma = new GammaDistribution(targetWeightClass / 0.4, 0.4);
306306

307307
// we use a double while loop here so that we start the whole thing over if we
308308
// overshoot force size
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/*
2+
* Copyright (C) 2026 The MegaMek Team. All Rights Reserved.
3+
*
4+
* This file is part of MekHQ.
5+
*
6+
* MekHQ is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License (GPL),
8+
* version 3 or (at your option) any later version,
9+
* as published by the Free Software Foundation.
10+
*
11+
* MekHQ is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty
13+
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14+
* See the GNU General Public License for more details.
15+
*
16+
* A copy of the GPL should have been included with this project;
17+
* if not, see <https://www.gnu.org/licenses/>.
18+
*
19+
* NOTICE: The MegaMek organization is a non-profit group of volunteers
20+
* creating free software for the BattleTech community.
21+
*
22+
* MechWarrior, BattleMech, `Mech and AeroTech are registered trademarks
23+
* of The Topps Company, Inc. All Rights Reserved.
24+
*
25+
* Catalyst Game Labs and the Catalyst Game Labs logo are trademarks of
26+
* InMediaRes Productions, LLC.
27+
*
28+
* MechWarrior Copyright Microsoft Corporation. MekHQ was created under
29+
* Microsoft's "Game Content Usage Rules"
30+
* <https://www.xbox.com/en-US/developers/rules> and it is not endorsed by or
31+
* affiliated with Microsoft.
32+
*/
33+
package mekhq.campaign.mission;
34+
35+
import megamek.common.Player;
36+
import megamek.common.equipment.EquipmentType;
37+
import megamek.common.loaders.MekSummary;
38+
import megamek.common.units.Entity;
39+
import megamek.common.units.UnitType;
40+
import mekhq.campaign.Campaign;
41+
import mekhq.campaign.campaignOptions.CampaignOptions;
42+
import mekhq.campaign.unit.Unit;
43+
import mekhq.campaign.universe.IUnitGenerator;
44+
import mekhq.campaign.universe.UnitGeneratorParameters;
45+
import static org.junit.jupiter.api.Assertions.assertEquals;
46+
import org.junit.jupiter.api.Test;
47+
import testUtilities.MHQTestUtilities;
48+
49+
import java.io.File;
50+
import java.util.List;
51+
52+
import static org.mockito.ArgumentMatchers.any;
53+
import static org.mockito.Mockito.mock;
54+
import static org.mockito.Mockito.when;
55+
56+
public class BotForceRandomizerTest {
57+
private Campaign mockCampaign;
58+
59+
private void initializeTest() {
60+
// Set up a test campaign with a unit generator that produces only Griffin Sparkys.
61+
// There's definitely room for these tests to cover more, but this at least checks that it
62+
// doesn't throw when used in the way that Story Arcs do.
63+
EquipmentType.initializeTypes();
64+
65+
MekSummary mockGeneratedMekSummary = mock(MekSummary.class);
66+
when(mockGeneratedMekSummary.getSourceFile()).thenReturn(new File(MHQTestUtilities.TEST_UNIT_DATA_DIR +
67+
"Griffin GRF-1E Sparky.mtf"));
68+
when(mockGeneratedMekSummary.getEntryName()).thenReturn(null);
69+
70+
IUnitGenerator mockUnitGenerator = mock(IUnitGenerator.class);
71+
when(mockUnitGenerator.generate(any(UnitGeneratorParameters.class))).thenReturn(mockGeneratedMekSummary);
72+
73+
mockCampaign = mock(Campaign.class);
74+
when(mockCampaign.getUnitGenerator()).thenReturn(mockUnitGenerator);
75+
when(mockCampaign.getPlayer()).thenReturn(new Player(1, "player"));
76+
when(mockCampaign.getCampaignOptions()).thenReturn(new CampaignOptions());
77+
}
78+
79+
@Test
80+
public void testBotForceRandomizerAdjustedWeight() {
81+
initializeTest();
82+
83+
Unit mockPlayerUnit = mock(Unit.class);
84+
Entity mockPlayerUnitEntity = mock(Entity.class);
85+
when(mockPlayerUnit.getEntity()).thenReturn(mockPlayerUnitEntity);
86+
87+
when(mockPlayerUnitEntity.getWeight()).thenReturn(55.0);
88+
when(mockPlayerUnitEntity.getUnitType()).thenReturn(UnitType.MEK);
89+
90+
List<Unit> playerUnits = List.of(mockPlayerUnit);
91+
List<Entity> fixedEntities = List.of();
92+
93+
BotForceRandomizer randomizer = new BotForceRandomizer();
94+
randomizer.setBalancingMethod(BotForceRandomizer.BalancingMethod.WEIGHT_ADJ);
95+
randomizer.setForceMultiplier(2.0);
96+
97+
List<Entity> generated = randomizer.generateForce(playerUnits, fixedEntities, mockCampaign);
98+
99+
// There should be two units generated, as the player units score 55 adjusted tons, and a Griffin scores 55
100+
// adjusted tons.
101+
assertEquals(2, generated.size());
102+
}
103+
104+
@Test
105+
public void testBotForceRandomizerBV() {
106+
initializeTest();
107+
108+
Unit mockPlayerUnit = mock(Unit.class);
109+
Entity mockPlayerUnitEntity = mock(Entity.class);
110+
when(mockPlayerUnit.getEntity()).thenReturn(mockPlayerUnitEntity);
111+
when(mockPlayerUnitEntity.calculateBattleValue()).thenReturn(1449);
112+
113+
List<Unit> playerUnits = List.of(mockPlayerUnit);
114+
List<Entity> fixedEntities = List.of();
115+
116+
BotForceRandomizer randomizer = new BotForceRandomizer();
117+
randomizer.setBalancingMethod(BotForceRandomizer.BalancingMethod.BV);
118+
randomizer.setForceMultiplier(2.0);
119+
120+
List<Entity> generated = randomizer.generateForce(playerUnits, fixedEntities, mockCampaign);
121+
122+
// There should be two units generated, as the player units score 1449BV, the same as the
123+
// Sparky.
124+
assertEquals(2, generated.size());
125+
}
126+
}

0 commit comments

Comments
 (0)