Class BasicPathRanker
- All Implemented Interfaces:
IPathRanker
- Direct Known Subclasses:
AerospacePathRanker,InfantryPathRanker,MutualSupportPathRanker,NewtonianAerospacePathRanker,UtilityPathRanker
This class evaluates potential movement paths for units controlled by Princess and assigns utility scores based on tactical considerations. It ranks paths according to their overall desirability, considering multiple weighted factors including:
- Fall risk - Probability of failing piloting skill rolls and falling
- Combat effectiveness - Potential damage output vs. damage taken
- Strategic positioning - Maintaining appropriate distance to enemies
- Tactical advantage - Facing, movement modifiers, and clustering
- Self-preservation - Avoiding hazardous terrain and managing retreat
- Unit cohesion - Maintaining proximity to friendly units
The ranker implements Princess's core movement decision-making logic for most ground units, calculating a final utility score where higher values represent more desirable paths. The relative importance of different factors is determined by the bot's behavior settings (aggression, bravery, mutual support, etc.).
Path evaluation also considers terrain hazards like building collapses, water, magma, ice, swamp, and other that could damage or immobilize the unit.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic classSimple data structure that holds a separate firing and physical damage number.Nested classes/interfaces inherited from class megamek.client.bot.princess.PathRanker
PathRanker.PathRankerType -
Field Summary
FieldsModifier and TypeFieldDescriptionprotected intprotected static final doubleThe indifference band: how much better a destination must score before leaving a held firing position is worth it.static final intprotected static final doubleHow much of a turn of advance the hold credit may reach under each posture: an attacking force keeps the credit modest so a good hex never outbids the advance, while a defending force holds harder.protected static final doubleprotected final DecimalFormatprotected final NumberFormatprotected static final intThe to-hit number the hit-chance-ratio discounts are priced at: gunnery 4 plus a typical spread of range and target modifiers.protected static final doubleReference movement rate that prices "one turn of advance" (TEMPO_REFERENCE_MP * aggression), the yardstick every position-discipline bound is measured against.protected static final intPosition discipline is dormant beyond this range: out of contact there is no exchange to hold and the force should move loose and fast. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprotected doubleHow much of its raw damage-at-range a unit keeps after its own movement makes it a worse shot.protected BasicPathRanker.FiringPhysicalDamagecalcDamageToStrategicTargets(MovePath path, Game game, FireControlState fireControlState, BasicPathRanker.FiringPhysicalDamage damageStructure) protected doublecalculateAerospaceMod(MovePath path, Game game, List<Entity> enemies) Doctrine seam for atmospheric aerospace movement, overridden by CASPAR's aerospace ranker.protected doublecalculateAggressionMod(Entity movingUnit, MovePath path, Game game) Calculates an aggression modifier that penalizes paths keeping the unit far from enemies.protected doublecalculateCloseRangeIncentive(Entity movingUnit, double distToEnemy) A reward for advancing toward point-blank range, for units that do more damage up close than they do at their current range - short-range gunners and, most importantly, melee brawlers.protected doublecalculateCrowdingTolerance(MovePath movePath, List<Entity> enemies, double maxRange, StringBuilder formula) Calculates a crowding tolerance modifier that penalizes paths ending in densely populated areas.protected doublecalculateFacingMod(Entity movingUnit, Game game, MovePath path, Coords enemyMedianPosition, Coords closestEnemyPosition, boolean squareUpOnClosestEnemy) Calculates a facing modifier that penalizes paths where the unit is not facing threats.protected doublecalculateMovementMod(MovePath pathCopy, Game game, List<Entity> enemies, StringBuilder formula) Calculates a movement modifier that rewards paths making units harder to hit.protected doublecalculateMutualSupportMod(Coords friendsCoords, MovePath path) Calculates a mutual support modifier that penalizes paths taking the unit away from friendly forces.protected doublecalculateOffBoardMod(MovePath path) Calculates a modifier that penalizes paths risking an aerospace unit flying off the board.protected doublecalculatePositionHoldMod(MovePath path, Game game, BasicPathRanker.FiringPhysicalDamage damageEstimate, double expectedDamageTaken, double successProbability) Position persistence: a unit already standing on ground that gives a positive exchange earns credit for keeping it, so it stops shuffling between equivalent hexes for a movement modifier it does not need - the two-step that walks a firing line out of its positions.protected doublecalculateSelfPreservationMod(Entity movingUnit, MovePath path, Game game) Calculates a self-preservation modifier that encourages units to retreat when appropriate.protected voidcheckBlackIce(Game game) doublecheckPathForHazards(MovePath path, Entity movingUnit, Game game) doubledistanceToClosestEnemy(Entity me, Coords position, Game game) Gives the distance to the closest enemy unit, or -1 if none exist.The reasoning behind a subclass's own modifiers, which becomes extra columns in theBotLoggerTSV.protected booleanevaluateAsMoved(Entity enemy) Worker function that determines if a given enemy entity should be evaluated as if it has moved.protected doublegetBraveryMod(double successProbability, BasicPathRanker.FiringPhysicalDamage damageEstimate, double expectedDamageTaken) Calculates a bravery modifier for path evaluation based on potential damage and risk.protected List<TargetRoll> getPSRList(MovePath path) protected megamek.client.bot.princess.HexPropertiesMaphexProperties(Game game, int boardId) The per-hex terrain labels for a board, computed once per round and shared by every path of every mover on it.protected doubleHow much of an unmoved enemy's raw damage the terrain at this path's destination lets through.voidinitUnitTurn(Entity unit, Game game) Calculate who all other units would shoot at if I weren't aroundprotected booleanisExtremeRange(Game game) protected booleanisLosRange(Game game) protected booleanisWithdrawing(Entity unit) Whether a unit has left the fighting line - pulling back under forced withdrawal, or ordered somewhere else entirely (a destination edge or a player waypoint).protected RankedPathrankPath(MovePath path, Game game, int maxRange, double fallTolerance, List<Entity> enemies, Coords friendsCoords) Evaluates and ranks movement paths for MegaMek units based on multiple strategic factors.rankPaths(List<MovePath> movePaths, Game game, int maxRange, double fallTolerance, List<Entity> enemies, List<Entity> friends) protected CombatPostureresolvedPostureFor(Game game, int boardId) The posture already resolved for this board this round, without resolving one if none has been.protected CombatPostureresolvePosture(Game game, int boardId) The posture the force fights under this round on the given board, resolved once per round per board and shared by every unit there.Methods inherited from class megamek.client.bot.princess.PathRanker
calcAllyCenter, calculateAlliesCenter, calculateMovePathPSRDamage, distanceToHomeEdge, findClosestEnemy, findClosestEnemy, getBestPath, getMovePathSuccessProbability, getOwner, getPathRankerStateMethods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface megamek.client.bot.princess.IPathRanker
findClosestEnemy
-
Field Details
-
FACING_MOD_MULTIPLIER
public static final int FACING_MOD_MULTIPLIER- See Also:
-
LOG_DECIMAL
-
LOG_PERCENT
-
bestDamageByEnemies
-
blackIce
protected int blackIce -
THREAT_CONTACT_RANGE
protected static final int THREAT_CONTACT_RANGEPosition discipline is dormant beyond this range: out of contact there is no exchange to hold and the force should move loose and fast.- See Also:
-
TEMPO_REFERENCE_MP
protected static final double TEMPO_REFERENCE_MPReference movement rate that prices "one turn of advance" (TEMPO_REFERENCE_MP * aggression), the yardstick every position-discipline bound is measured against. At default aggression (2.5) a turn of advance is worth 37.5 - the same scale as the stock per-hex aggression gradient over a full move.- See Also:
-
REPRESENTATIVE_TO_HIT
protected static final int REPRESENTATIVE_TO_HITThe to-hit number the hit-chance-ratio discounts are priced at: gunnery 4 plus a typical spread of range and target modifiers. Only the RATIO of hit chances at this number matters - walking turns 8s into 9s whoever you are - so the midpoint stands in for every shooter without pretending the estimate knows its real to-hit.- See Also:
-
ESTIMATE_NOISE_MARGIN
protected static final double ESTIMATE_NOISE_MARGINThe indifference band: how much better a destination must score before leaving a held firing position is worth it. The ranker re-estimates every hex every round, and the estimate of the SAME hex moves round to round as enemies shift - measured on 30-game mirror runs, a unit standing still sees its own hex's score change by a median of about five points per round. A destination that beats the current hex by less than that is indistinguishable from the noise, and chasing it pays the attacker movement modifier for nothing. The margin is the measured median (estimate_wobble.py, re-measured whenever the estimators change), added to the stationary path's hold credit: real improvements - fresh cover against a new threat, a range advantage - typically score well past it and still win.- See Also:
-
HOLD_CREDIT_ATTACK_CAP_FACTOR
protected static final double HOLD_CREDIT_ATTACK_CAP_FACTORHow much of a turn of advance the hold credit may reach under each posture: an attacking force keeps the credit modest so a good hex never outbids the advance, while a defending force holds harder. Both keep the credit below one turn of advance at default aggression; a final clamp incalculatePositionHoldMod(megamek.common.moves.MovePath, megamek.common.game.Game, megamek.client.bot.princess.BasicPathRanker.FiringPhysicalDamage, double, double)holds that bound across the whole aggression slider, where the fixedESTIMATE_NOISE_MARGINwould otherwise overtake the shrinking yardstick.- See Also:
-
HOLD_CREDIT_DEFEND_CAP_FACTOR
protected static final double HOLD_CREDIT_DEFEND_CAP_FACTOR- See Also:
-
-
Constructor Details
-
BasicPathRanker
-
-
Method Details
-
calculateAerospaceMod
Doctrine seam for atmospheric aerospace movement, overridden by CASPAR's aerospace ranker.Returns 0 here, so the stock utility total is exactly what it was before this seam existed. It is a seam rather than a term because none of the modifiers above has any concept of altitude: they price distance, facing and cover on a flat board, while what decides an air-to-air engagement is whether the two units are close enough in altitude to shoot at all (TW p.241).
- Parameters:
path- the path being rankedgame- the current gameenemies- the enemies being weighed against this path- Returns:
- the doctrine adjustment to this path's utility, 0 in the stock ranker
-
attackerMovementDamageDiscount
How much of its raw damage-at-range a unit keeps after its own movement makes it a worse shot.The unmoved-enemy estimate above is a range-table lookup with no to-hit roll in it, so the one certain cost of moving - the attacker movement modifier, +1 walked, +2 ran, +3 jumped - did not exist in it, and a short step read as free. This prices it back in as a hit-chance ratio at the
REPRESENTATIVE_TO_HITmidpoint: standing keeps everything, walking keeps about two-thirds, running two-fifths, a standard jump one-fifth. The modifier comes from the same engine call the server fires with (Compute.getAttackerMovementModifier(megamek.common.game.Game, int)), so infantry's exemption, the dual-cockpit dedicated gunner, and the jumping-jack abilities are all priced without naming them.- Parameters:
path- the path being evaluated- Returns:
- the fraction of the raw damage estimate the path's movement mode leaves the unit
-
incomingFireTerrainDiscount
How much of an unmoved enemy's raw damage the terrain at this path's destination lets through.The twin of
attackerMovementDamageDiscount(megamek.common.moves.MovePath): the raw damage-at-range estimate above has no to-hit roll, so the cover the destination hex gives - the woods and partial-cover modifiers the full fire-control guess prices against already-moved enemies - did not exist in it, and a covered hex and an open one read the same. This discounts that raw estimate by the hit-chance ratio the destination's cover implies, from the per-roundHexPropertiesMaplabels. Only cover a unit can FIGHT from is credited: woodline edges and partial cover count; deep woods - concealing but blind - deliberately do not, so the discount never coaxes a unit into ground it cannot shoot from.- Parameters:
path- the path being evaluated- Returns:
- the fraction of the raw enemy damage estimate the destination's cover lets through
-
hexProperties
The per-hex terrain labels for a board, computed once per round and shared by every path of every mover on it. -
resolvePosture
The posture the force fights under this round on the given board, resolved once per round per board and shared by every unit there. Only units on that board have a say: entity lists are game-wide, and in a multi-board game mixing boards would make the closing rate meaningless. When the answer changes, the bot says so in the chat with its reason, so an observer can follow the force's intent without reading logs. -
resolvedPostureFor
The posture already resolved for this board this round, without resolving one if none has been.Deliberately does not call
resolvePosture(megamek.common.game.Game, int): that announces the force's intent in the chat when it changes, so resolving merely to write a log line would make the bot say things it had not otherwise decided.- Overrides:
resolvedPostureForin classPathRanker- Parameters:
game- the current gameboardId- the board to report on- Returns:
- the resolved posture, or
null
-
isWithdrawing
Whether a unit has left the fighting line - pulling back under forced withdrawal, or ordered somewhere else entirely (a destination edge or a player waypoint). Such a unit earns no hold credit (it has somewhere to be, however good its current hex), and its say in where the formation's centre lies is sharply reduced - not removed, so the centre moves continuously as units leave the line (seeMutualSupportPathRanker's withdrawing centre weight). -
getPSRList
- Overrides:
getPSRListin classPathRanker
-
calculateAggressionMod
Calculates an aggression modifier that penalizes paths keeping the unit far from enemies.This method implements the tactical preference for closing with the enemy based on:
- The distance to the closest enemy from the path's final position
- The AI's configured hyper-aggression value
The aggression modifier follows this formula:
aggressionMod = distanceToClosestEnemy * hyperAggressionValue
Since this value is subtracted in the final utility calculation, higher values represent stronger penalties for staying distant from enemies. A high hyperAggressionValue will strongly push units toward closing with enemies regardless of other tactical considerations.
- Parameters:
movingUnit- The entity being movedpath- The movement path being evaluatedgame- The current game state- Returns:
- An aggression modifier value (higher is worse) to be used in path ranking
-
calculateCloseRangeIncentive
A reward for advancing toward point-blank range, for units that do more damage up close than they do at their current range - short-range gunners and, most importantly, melee brawlers. The ranged damage estimate credits a unit's hatchet, sword or kick only on the turn it ends adjacent to an enemy, so a brawler otherwise sees no reason to close and will pace at range (issue #7627: an Axman would not wade a river to reach hatchet range). This incentive is the unit's point-blank damage premium scaled by how far it has closed toward contact, so it grows smoothly as the unit advances and is zero for units that already deliver their best damage at range.- Parameters:
movingUnit- the unit being moveddistToEnemy- the path's ending distance to the closest enemy- Returns:
- the closing incentive to add to the path's utility (never negative)
-
rankPaths
public TreeSet<RankedPath> rankPaths(List<MovePath> movePaths, Game game, int maxRange, double fallTolerance, List<Entity> enemies, List<Entity> friends) - Specified by:
rankPathsin interfaceIPathRanker- Overrides:
rankPathsin classPathRanker
-
calculateMutualSupportMod
Calculates a mutual support modifier that penalizes paths taking the unit away from friendly forces.This method implements the tactical preference for maintaining formation with friendly units based on:
- The distance from the path's final position to the center of friendly forces
- The AI's configured mutual support value
The mutual support modifier follows this formula:
mutualSupportMod = distanceToFriends * mutualSupportValue
Since this value is subtracted in the final utility calculation, higher values represent stronger penalties for straying from the friendly force. If no friendly forces are present (friendsCoords is null), the method returns 0, applying no penalty.
- Parameters:
friendsCoords- The coordinate representing the center of friendly forces, or null if no friendspath- The movement path being evaluated- Returns:
- A mutual support modifier value (higher is worse) to be used in path ranking
-
calculateFacingMod
protected double calculateFacingMod(Entity movingUnit, Game game, MovePath path, @Nullable Coords enemyMedianPosition, @Nullable Coords closestEnemyPosition, boolean squareUpOnClosestEnemy) Calculates a facing modifier that penalizes paths where the unit is not facing threats.This method evaluates how well the unit's final facing aligns with the direction it should optimally face to confront enemies. The method:
- Determines the ideal facing based on the position of the closest enemies
- Calculates how far off the unit's final facing is from this ideal
- Applies a penalty proportional to how far off the facing is
- Considers armor distribution to bias facing toward better-protected sides
Facing differences are measured in hexside rotations (0-3), where:
- 0 = Perfect facing toward threat
- 1 = Off by one hexside (60°)
- 2 = Off by two hexsides (120°)
- 3 = Facing directly away (180°)
The facing penalty is calculated as: 50 * (facingDiff - 1), with a minimum of 0. This means perfect facing has no penalty, while the worst facing incurs a -100 penalty.
- Parameters:
movingUnit- The entity being movedgame- The current game statepath- The movement path being evaluatedenemyMedianPosition- The coordinates of the median position of enemies, or null to use the board centerclosestEnemyPosition- The coordinates of the closest enemy, or null to use the board center- Returns:
- A facing modifier value (higher is worse) to be used in path ranking
-
calculateSelfPreservationMod
Calculates a self-preservation modifier that encourages units to retreat when appropriate.This method applies penalties or bonuses based on the unit's movement toward safety:
- For units in forced withdrawal or moving to a destination, encourages movement toward home edge
- Applies a significant bonus (
ARRIVED_AT_DESTINATION_FACTOR) if the path reaches the home edge - Applies a penalty proportional to distance from home edge otherwise
The method only applies these modifiers when the unit is in forced withdrawal or deliberately moving to a designated location. For normal combat operations, it returns 0 to indicate self-preservation is not a priority factor.
- Parameters:
movingUnit- The entity being movedpath- The movement path being evaluatedgame- The current game state- Returns:
- A self-preservation modifier value (negative values are better) to be used in path ranking
-
calculateOffBoardMod
Calculates a modifier that penalizes paths risking an aerospace unit flying off the board.This method evaluates the risk of aerospace units inadvertently leaving the game board on subsequent turns due to their movement characteristics. The method:
- Analyzes the path's final position, velocity, and facing
- Calculates whether the unit might be forced off-board on the following turns
- Returns a multiplier that severely penalizes paths with high off-board risk
For non-aerospace units, this method always returns 0 as they don't face this particular risk. For aerospace units, a non-zero return value serves as a multiplier to other penalties, effectively eliminating dangerous paths from consideration.
- Parameters:
path- The movement path being evaluated- Returns:
- A multiplier value (0 for no risk, positive for risk of flying off-board)
-
checkBlackIce
-
rankPath
protected RankedPath rankPath(MovePath path, Game game, int maxRange, double fallTolerance, List<Entity> enemies, Coords friendsCoords) Evaluates and ranks movement paths for MegaMek units based on multiple strategic factors. Returns a utility score where higher values represent more desirable paths.The utility score calculation combines several weighted factors:
utility = -fallMod + braveryMod - aggressionMod - mutualSupportMod + movementMod - crowdingTolerance - facingMod - selfPreservationMod - (utility * offBoardMod)Key Components:
- fallMod: Penalty for paths with risk of failing piloting rolls
- Calculated as
pilotingFailure * fallShame - Higher values = worse paths (more likely to fall)
- Calculated as
- braveryMod: Reward for paths balancing damage output vs. incoming damage
- Based on potential damage to enemies vs. expected damage received
- Higher values = better paths (can do more damage than take)
- aggressionMod: Penalty for staying far from enemies
- Calculated as
distanceToEnemy * aggressionValue - Higher values = worse paths (too far from enemies when aggression is high)
- Calculated as
- mutualSupportMod: Penalty for moving away from friendly units
- Calculated as
distanceToFriends * mutualSupportValue - Higher values = worse paths (isolated from allies)
- Calculated as
- facingMod: Penalty for not facing toward enemies
- Based on facing direction relative to enemies
- Higher values = worse paths (facing away from threats)
- selfPreservationMod: Penalty for not moving toward retreat edge when needed
- Special case: if reaching the home edge, gives a large bonus of
ARRIVED_AT_DESTINATION_FACTOR - Higher values = worse paths (not retreating when damaged)
- Special case: if reaching the home edge, gives a large bonus of
- movementMod: Reward for using movement effectively
- Based on multiple strategic factors
- Higher values = better paths (using speed effectively)
- crowdingTolerance: Penalty for ending in crowded areas
- Based on nearby threats relative to maximum weapon range
- Higher values = worse paths (too many enemies nearby)
- offBoardMod: Penalty for aerospace units at risk of flying off the board
- Applies as a multiplier to existing penalties
- Higher values = worse paths (likely to fly off the board)
The function uses behavior settings like bravery, aggression, and mutual support to adjust the relative importance of these factors based on the AI's configured personality.
- Specified by:
rankPathin classPathRanker- Parameters:
path- The movement path to be evaluatedgame- The current game statemaxRange- Entity max weapon rangefallTolerance- a maximum PSR failure chance to be acceptableenemies- List of enemy units visiblefriendsCoords- Center of Gravity of friendly units (average coordinate position)- Returns:
- A double representing the utility/desirability of the path (higher is better)
- fallMod: Penalty for paths with risk of failing piloting rolls
-
doctrineScores
The reasoning behind a subclass's own modifiers, which becomes extra columns in theBotLoggerTSV.The modifier values themselves are already recorded, but a number on its own only says how much a term weighed, not why. Answering "why did the bot do this" after the fact needs the inputs that produced it, and a subclass that replaces a modifier is the only thing that knows what those are. Anything left only in trace logging is effectively unavailable: it is off by default and rotates away within a minute of a company-scale game.
- Returns:
- named values to record alongside the path's modifiers
-
calculatePositionHoldMod
protected double calculatePositionHoldMod(MovePath path, Game game, BasicPathRanker.FiringPhysicalDamage damageEstimate, double expectedDamageTaken, double successProbability) Position persistence: a unit already standing on ground that gives a positive exchange earns credit for keeping it, so it stops shuffling between equivalent hexes for a movement modifier it does not need - the two-step that walks a firing line out of its positions.Quality is the exchange the stationary path itself was just evaluated at - expected damage dealt, weighted by the chance of standing to deliver it, minus expected damage taken - raised by
heatSinkSustainBoost(megamek.common.units.Entity, megamek.common.game.Game, megamek.common.moves.MovePath)when the hex lets a hot unit sustain more. The exchange already appears once in the bravery term for every path equally; counting it again here, only for standing still, is the deliberate asymmetry that makes a good position sticky. Ground that gives nothing (or worse) holds nothing: the credit never anchors a unit in a losing exchange.Dormant outside
THREAT_CONTACT_RANGE: on the approach there is no exchange to hold and the force should move loose and fast. Withdrawing units are leaving, not holding. The credit is capped so it never exceeds one turn of advance, harder under DEFEND than ATTACK (HOLD_CREDIT_DEFEND_CAP_FACTOR,HOLD_CREDIT_ATTACK_CAP_FACTOR).- Parameters:
path- the path being ranked (a copy, safe to inspect)game- the current gamedamageEstimate- the damage this unit is estimated to deal from the path's destinationexpectedDamageTaken- the damage it is estimated to take there, path hazards includedsuccessProbability- the chance the path completes without a failed piloting roll- Returns:
- the utility credit, added to the path's utility
-
isLosRange
-
isExtremeRange
-
getBraveryMod
protected double getBraveryMod(double successProbability, BasicPathRanker.FiringPhysicalDamage damageEstimate, double expectedDamageTaken) Calculates a bravery modifier for path evaluation based on potential damage and risk.This method determines how "brave" the AI should be when considering a path by weighing:
- The probability of successfully completing the move (avoiding falls)
- The maximum potential damage the unit can inflict from the final position
- The expected damage the unit might receive
The bravery modifier follows this formula:
braveryMod = (successProbability * maximumDamageDone * braveryValue) - expectedDamageTaken
Higher bravery values make the AI more willing to accept risks if it can deal significant damage. A positive bravery modifier indicates the path is tactically advantageous despite potential risks.
- Parameters:
successProbability- The probability (0.0 to 1.0) of making all required piloting rollsdamageEstimate- Container with estimates of damage that can be doneexpectedDamageTaken- Expected damage to be received in this position- Returns:
- A bravery modifier value (higher is better) to be used in path ranking
-
calculateMovementMod
protected double calculateMovementMod(MovePath pathCopy, Game game, List<Entity> enemies, StringBuilder formula) Calculates a movement modifier that rewards paths making units harder to hit. This serves as a key positive modifier in the overall utility calculation.The function encourages units to:
- Keep moving when tactically beneficial
- Choose paths with optimal movement types
- Use movement as a defensive strategy
The modifier is calculated as:
movementFactor = TMM × (selfPreservation + favorHigherTMM)
Where:
- TMM: Target Movement Modifier - higher values make units harder to hit
- selfPreservation: AI setting for valuing survival
- favorHigherTMM: AI setting specifically for valuing movement as defense
The modifier is applied when either:
- No enemies are visible (encouraging exploration/positioning)
- OR
favorHigherTMMsetting is enabled (encouraging defensive movement)
- Parameters:
pathCopy- The movement path to evaluategame- The current game stateenemies- List of enemy units visibleformula- StringBuilder to append the formula for logging- Returns:
- A positive double value representing the movement modifier
-
calculateCrowdingTolerance
protected double calculateCrowdingTolerance(MovePath movePath, List<Entity> enemies, double maxRange, StringBuilder formula) Calculates a crowding tolerance modifier that penalizes paths ending in densely populated areas.This method evaluates the tactical risks of positioning in areas with many units nearby:
- Counts friendly units within a short radius (depends on antiCrowding setting)
- Counts enemy units within a medium radius (typically 60% of max weapon range)
- Applies penalties based on these counts and the AI's antiCrowding preference
The crowding penalty increases as more units (friendly or enemy) are present near the final position. This encourages units to maintain tactical spacing rather than clumping together, which helps avoid:
- Becoming easy targets for area effect weapons
- Blocking each other's line of fire
- Creating movement bottlenecks
The crowding penalty is only applied to Meks and Tanks, as other unit types have different tactical positioning requirements.
- Parameters:
movePath- The movement path being evaluatedenemies- List of enemy units visiblemaxRange- Entity's maximum weapon rangeformula- StringBuilder to append the formula explanation for logging- Returns:
- A crowding tolerance value (higher is worse) to be used in path ranking
-
evaluateAsMoved
Worker function that determines if a given enemy entity should be evaluated as if it has moved. -
initUnitTurn
Calculate who all other units would shoot at if I weren't around- Specified by:
initUnitTurnin interfaceIPathRanker- Overrides:
initUnitTurnin classPathRanker
-
calcDamageToStrategicTargets
protected BasicPathRanker.FiringPhysicalDamage calcDamageToStrategicTargets(MovePath path, Game game, FireControlState fireControlState, BasicPathRanker.FiringPhysicalDamage damageStructure) -
distanceToClosestEnemy
Gives the distance to the closest enemy unit, or -1 if none exist. The reason being that the closest enemy unit may be 0 away. -
checkPathForHazards
-