Skip to content

Commit

Permalink
Merge branch 'master' into feat/tinkering-princess-ai
Browse files Browse the repository at this point in the history
  • Loading branch information
Scoppio authored Jan 22, 2025
2 parents 0ada31b + a6522b4 commit c0f0ad7
Show file tree
Hide file tree
Showing 24 changed files with 156 additions and 178 deletions.
5 changes: 4 additions & 1 deletion megamek/docs/history.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ MEGAMEK VERSION HISTORY:
+ PR #6414: Warnings on Campaign Load - MegaMek Portion
+ Fix #6412: Fix TacOps "Standing Still" modifier description
+ Fix 6373: Fixed "unit that starts and ends a Movement Phase in liquid magma takes an additional damage" so it doesn't apply to units above the magma

+ PR #6427 & #6428: Fix for Princess not ignoring Hidden and Ignored units. - Scoppio
+ PR #6431: Fix Artemis derivatives getting bonus on indirect fire
+ PR #6430: Renamed Directory ProtomMek Pilots to ProtoMek Pilots in MegaMek to match MekHQ
+ Fix #6359: LAMs now properly consider if they're in fighter mode or not when deploying.

0.50.02 (2024-12-30 2130 UTC)
+ PR #6183: New GM Commands, princess commands on map menu, graphics for some explosions
Expand Down
6 changes: 3 additions & 3 deletions megamek/src/megamek/client/bot/BotClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -363,9 +363,9 @@ public List<Entity> getEnemyEntities() {
currentTurnEnemyEntities = new ArrayList<>();
for (Entity entity : game.getEntitiesVector()) {
if (entity.getOwner().isEnemyOf(getLocalPlayer())
&& (entity.getPosition() != null) && !entity.isOffBoard()
&& (entity.getCrew() != null) && !entity.getCrew().isDead()) {

&& (entity.getPosition() != null) && !entity.isOffBoard()
&& (entity.getCrew() != null) && !entity.getCrew().isDead()
&& !entity.isHidden()) {
currentTurnEnemyEntities.add(entity);
}
}
Expand Down
14 changes: 5 additions & 9 deletions megamek/src/megamek/client/bot/ChatProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,7 @@
*/
package megamek.client.bot;

import java.util.StringTokenizer;
import java.util.stream.Collectors;

import megamek.client.bot.princess.BehaviorSettings;
import megamek.client.bot.princess.BehaviorSettingsFactory;
import megamek.client.bot.princess.CardinalEdge;
import megamek.client.bot.princess.ChatCommands;
import megamek.client.bot.princess.Princess;
import megamek.client.bot.princess.*;
import megamek.codeUtilities.StringUtility;
import megamek.common.Coords;
import megamek.common.Game;
Expand All @@ -39,6 +32,9 @@
import megamek.server.commands.GameMasterCommand;
import megamek.server.commands.JoinTeamCommand;

import java.util.StringTokenizer;
import java.util.stream.Collectors;

public class ChatProcessor {
private final static MMLogger logger = MMLogger.create(ChatProcessor.class);

Expand Down Expand Up @@ -451,7 +447,7 @@ void additionalPrincessCommands(GamePlayerChatEvent chatEvent, Princess princess
// Specify a priority unit target.
if (command.toLowerCase().startsWith(ChatCommands.SHOW_DISHONORED.getAbbreviation())) {
msg = "Dishonored Player ids: " + princess.getHonorUtil().getDishonoredEnemies().stream()
.map(Object::toString).collect(Collectors.joining(", "));
.map(Object::toString).collect(Collectors.joining(", "));
princess.sendChat(msg);
logger.info(msg);
}
Expand Down
42 changes: 8 additions & 34 deletions megamek/src/megamek/client/bot/princess/FireControl.java
Original file line number Diff line number Diff line change
Expand Up @@ -1374,7 +1374,7 @@ protected double calcPriorityUnitTargetUtility(final Targetable target) {
return 0;
}

final int id = ((Entity) target).getId();
final int id = target.getId();
if (owner.getPriorityUnitTargets().contains(id)) {
return PRIORITY_TARGET_UTILITY;
}
Expand Down Expand Up @@ -1546,31 +1546,6 @@ protected double calcTargetPotentialDamageMultiplier(final Targetable target) {
// damage)).
}

/**
* calculates the 'utility' of a physical action.
*
* @param physicalInfo The {@link PhysicalInfo} to be calculated.
*/
void calculateUtility(final PhysicalInfo physicalInfo) {
// If we can't hit, there's no point.
if (0.0 >= physicalInfo.getProbabilityToHit()) {
physicalInfo.setUtility(-10000);
return;
}

double utility = DAMAGE_UTILITY * physicalInfo.getExpectedDamage();
utility += CRITICAL_UTILITY * physicalInfo.getExpectedCriticals();
utility += KILL_UTILITY * physicalInfo.getKillProbability();
utility *= calcTargetPotentialDamageMultiplier(physicalInfo.getTarget());
utility -= (physicalInfo.getTarget() instanceof MekWarrior) ? EJECTED_PILOT_DISUTILITY : 0;
utility += calcCommandUtility(physicalInfo.getTarget());
utility += calcStrategicBuildingTargetUtility(physicalInfo.getTarget());
utility += calcPriorityUnitTargetUtility(physicalInfo.getTarget());
utility -= calcCivilianTargetDisutility(physicalInfo.getTarget());

physicalInfo.setUtility(utility);
}

/**
* Creates a new {@link WeaponFireInfo} object containing data about firing
* the given weapon at the given target.
Expand Down Expand Up @@ -2705,19 +2680,17 @@ FiringPlan getBestFiringPlan(final Entity shooter,

// Loop through each enemy and find the best plan for attacking them.
for (final Targetable enemy : enemies) {

if (owner.getBehaviorSettings().getIgnoredUnitTargets().contains(enemy.getId())) {
logger.info(enemy.getDisplayName() + " is being explicitly ignored");
continue;
}

final int playerId = enemy.getOwnerId();
final boolean priorityTarget = owner.getPriorityUnitTargets().contains(enemy.getId());

// Skip retreating enemies so long as they haven't fired on me while retreating.
final int playerId = (enemy instanceof Entity) ? ((Entity) enemy).getOwnerId() : -1;
if (!priorityTarget && honorUtil.isEnemyBroken(enemy.getId(), playerId,
owner.getForcedWithdrawal())) {
logger.info(enemy.getDisplayName() + " is broken - ignoring");
final boolean isEnemyBroken = honorUtil.isEnemyBroken(enemy.getId(), playerId, owner.getForcedWithdrawal());
// Only skip retreating enemies that are not priority targets so long as they haven't fired on me while retreating.
if (!priorityTarget && isEnemyBroken) {
logger.info(enemy.getDisplayName() + " is broken and not priority - ignoring");
continue;
}

Expand All @@ -2727,7 +2700,8 @@ FiringPlan getBestFiringPlan(final Entity shooter,
ammoConservation);
final FiringPlan plan = determineBestFiringPlan(parameters);

if ((null == bestPlan) || (plan.getUtility() > bestPlan.getUtility())) {
if ((bestPlan == null)
|| (plan.getUtility() > bestPlan.getUtility())) {
bestPlan = plan;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,24 +39,29 @@ public NewtonianAerospacePathRanker(Princess owningPrincess) {
*/
@Override
public Entity findClosestEnemy(Entity me, Coords position, Game game) {
int range = 9999;
int range = Integer.MAX_VALUE;
Entity closest = null;
List<Entity> enemies = getOwner().getEnemyEntities();
for (Entity e : enemies) {
// Also, skip withdrawing enemy bot units, to avoid humping disabled tanks and ejected MekWarriors
if (getOwner().getHonorUtil().isEnemyBroken(e.getId(), e.getOwnerId(), getOwner().getForcedWithdrawal())) {
var ignoredTargets = getOwner().getBehaviorSettings().getIgnoredUnitTargets();
var priorityTargets = getOwner().getBehaviorSettings().getPriorityUnitTargets();
for (Entity enemy : enemies) {
// targets that are withdrawing and are not priorities are ignored
// targets in the ignore list are ignored
// therefore... a priority target in the ignore list is ignored
if ((!priorityTargets.contains(enemy.getId()) && getOwner().getHonorUtil().isEnemyBroken(enemy.getId(), enemy.getOwnerId(), getOwner().getForcedWithdrawal()))
|| ignoredTargets.contains(enemy.getId())) {
continue;
}

// If a unit has not moved, assume it will move away from me.
int unmovedDistMod = 0;
if (e.isSelectableThisTurn() && !e.isImmobile()) {
unmovedDistMod = e.getWalkMP();
if (enemy.isSelectableThisTurn() && !enemy.isImmobile()) {
unmovedDistMod = enemy.getWalkMP();
}

if ((position.distance(e.getPosition()) + unmovedDistMod) < range) {
range = position.distance(e.getPosition());
closest = e;
if ((position.distance(enemy.getPosition()) + unmovedDistMod) < range) {
range = position.distance(enemy.getPosition());
closest = enemy;
}
}
return closest;
Expand Down
52 changes: 26 additions & 26 deletions megamek/src/megamek/client/bot/princess/PathRanker.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@
*/
package megamek.client.bot.princess;

import megamek.client.bot.princess.UnitBehavior.BehaviorType;
import megamek.client.ui.Messages;
import megamek.client.ui.SharedUtility;
import megamek.codeUtilities.StringUtility;
import megamek.common.*;
import megamek.common.annotations.Nullable;
import megamek.common.options.OptionsConstants;
import megamek.logging.MMLogger;
import org.apache.logging.log4j.Level;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
Expand All @@ -28,17 +38,6 @@
import java.util.Enumeration;
import java.util.List;

import megamek.client.ui.Messages;
import org.apache.logging.log4j.Level;

import megamek.client.bot.princess.UnitBehavior.BehaviorType;
import megamek.client.ui.SharedUtility;
import megamek.codeUtilities.StringUtility;
import megamek.common.*;
import megamek.common.annotations.Nullable;
import megamek.common.options.OptionsConstants;
import megamek.logging.MMLogger;

import static megamek.client.ui.SharedUtility.predictLeapDamage;
import static megamek.client.ui.SharedUtility.predictLeapFallDamage;

Expand All @@ -63,7 +62,7 @@ public enum PathRankerType {
NewtonianAerospace
}

private Princess owner;
private final Princess owner;

public PathRanker(Princess princess) {
owner = princess;
Expand Down Expand Up @@ -275,31 +274,32 @@ public Targetable findClosestEnemy(Entity me, Coords position, Game game) {
@Override
public Targetable findClosestEnemy(Entity me, Coords position, Game game,
boolean includeStrategicTargets) {
int range = 9999;
int range = Integer.MAX_VALUE;
Targetable closest = null;
List<Entity> enemies = getOwner().getEnemyEntities();
for (Entity e : enemies) {
var ignoredTargets = owner.getBehaviorSettings().getIgnoredUnitTargets();
var priorityTargets = getOwner().getBehaviorSettings().getPriorityUnitTargets();
for (Entity enemy : enemies) {
// Skip airborne aero units as they're further away than they seem and hard to
// catch.
// Also, skip withdrawing enemy bot units, to avoid humping disabled tanks and
// ejected
// MekWarriors
if (e.isAirborneAeroOnGroundMap() ||
getOwner().getHonorUtil().isEnemyBroken(e.getId(), e.getOwnerId(),
getOwner().getForcedWithdrawal())) {
// Also, skip withdrawing enemy bot units that are not priority targets
// skip ignored units
if (enemy.isAirborneAeroOnGroundMap()
|| (!priorityTargets.contains(enemy.getId()) && getOwner().getHonorUtil().isEnemyBroken(enemy.getId(), enemy.getOwnerId(), getOwner().getForcedWithdrawal()))
|| ignoredTargets.contains(enemy.getId())) {
continue;
}

// If a unit has not moved, assume it will move away from me.
int unmovedDistMod = 0;
if (e.isSelectableThisTurn() && !e.isImmobile()) {
unmovedDistMod = e.getWalkMP();
if (enemy.isSelectableThisTurn() && !enemy.isImmobile()) {
unmovedDistMod = enemy.getWalkMP();
}

int distance = position.distance(e.getPosition());
int distance = position.distance(enemy.getPosition());
if ((distance + unmovedDistMod) < range) {
range = distance;
closest = e;
closest = enemy;
}
}

Expand Down Expand Up @@ -570,8 +570,8 @@ private boolean willBuildingCollapse(MovePath path, Game game) {
return null;
}

int xCenter = Math.round(xTotal / friendOnBoardCount);
int yCenter = Math.round(yTotal / friendOnBoardCount);
int xCenter = Math.round((float) xTotal / friendOnBoardCount);
int yCenter = Math.round((float) yTotal / friendOnBoardCount);
Coords center = new Coords(xCenter, yCenter);

if (!game.getBoard().contains(center)) {
Expand Down
2 changes: 1 addition & 1 deletion megamek/src/megamek/client/bot/princess/RankedPath.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
* @author Deric "Netzilla" Page (deric dot page at usa dot net)
* @since 12/5/13 10:19 AM
*/
class RankedPath implements Comparable<RankedPath> {
public class RankedPath implements Comparable<RankedPath> {
private MovePath path;
private double rank;
private String reason;
Expand Down
3 changes: 2 additions & 1 deletion megamek/src/megamek/client/ui/swing/DeploymentDisplay.java
Original file line number Diff line number Diff line change
Expand Up @@ -534,8 +534,9 @@ public void hexMoused(BoardViewEvent b) {
}
}

// entity.isAero will check if a unit is a LAM in Fighter mode
if ((entity instanceof IAero aero)
&& (!(entity instanceof LandAirMek lam) || (lam.getConversionMode() == LandAirMek.CONV_MODE_FIGHTER))) {
&& (entity.isAero())) {
entity.setAltitude(finalElevation);
if (finalElevation == 0) {
aero.land();
Expand Down
3 changes: 2 additions & 1 deletion megamek/src/megamek/common/actions/WeaponAttackAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -3352,14 +3352,15 @@ private static ToHitData compileAmmoToHitMods(Game game, Entity ae, Targetable t
}

// Missile Munitions
boolean isIndirect = weapon.hasModes() && (weapon.curMode().isIndirect());

// Apollo FCS for MRMs
if (bApollo) {
toHit.addModifier(-1, Messages.getString("WeaponAttackAction.ApolloFcs"));
}

// add Artemis V bonus
if (bArtemisV) {
if (bArtemisV && !isIndirect) {
toHit.addModifier(-1, Messages.getString("WeaponAttackAction.ArtemisV"));
}

Expand Down
Loading

0 comments on commit c0f0ad7

Please sign in to comment.