Skip to content

Add no-retreat-path Forced Withdrawal evaluation scenario - #501

Merged
HammerGS merged 1 commit into
mainfrom
Fix-Princess-forced-withdrawal-loiter
Aug 2, 2026
Merged

Add no-retreat-path Forced Withdrawal evaluation scenario#501
HammerGS merged 1 commit into
mainfrom
Fix-Princess-forced-withdrawal-loiter

Conversation

@HammerGS

@HammerGS HammerGS commented Aug 1, 2026

Copy link
Copy Markdown
Member

Summary

Adds a variant of the Forced Withdrawal benchmark scenario (from #500) with the withdrawal edge set to NONE on both sides, so crippled units are trapped with no path to a retreat edge. Companion to the megamek Forced Withdrawal loiter fix, which it was built to measure.

Changes Made

  • Trapped case coverage: same mirror lances and map as PrincessEval_ForcedWithdrawal.mms, but withdrawto: NONE for both bot factions. Pre-fix, trapped crippled units passively loitered with their fire suppressed; the scenario measures that they now keep fighting and back away instead.

Files Changed

  • data/scenarios/Evaluation/PrincessEval_ForcedWithdrawal_NoPath.mms - NEW

Testing

  • 100-game headless AIMatchRunner batches ran on this scenario both before and after the megamek fix (decision-log counts: passive holds-fire 49 to 0, fight-on 0 to 49).

🤖 Generated with Claude Code

Variant of PrincessEval_ForcedWithdrawal with the withdrawal edge set
to NONE on both sides, so crippled units are trapped with no path to
a retreat edge. Companion to the megamek Forced Withdrawal loiter fix:
measures that trapped crippled units keep fighting and back away
instead of passively loitering with their fire suppressed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
IllianiBird added a commit to MegaMek/megamek that referenced this pull request Aug 2, 2026
…8630)

## Summary

QA reported units under Forced Withdrawal hanging in the engagement
zone: not shooting, not retreating, often not moving at all. Three
compounding defects in Princess caused it. Validated with ~500 headless
Princess-vs-Princess games (100-game before/after arms on two scenarios)
using the #8629 harness.

## Bug Fixed

- **Return-fire deadlock**: permission to return fire was granted from
the start-of-turn crippled set, so a unit crippled and attacked in the
same turn needed a *later* attack to unlock - which bot opponents never
deliver, because their honor rules stop them shooting crippled units.
Permanently disarmed. A new end-of-turn pass grants permission from the
freshly refreshed set; the dishonor check keeps its deliberate
start-of-turn view (an attacker is only dishonored for shooting a unit
that was already visibly crippled).
- **No-path loiter**: with no route to the retreat edge (blocked,
surrounded, or withdraw edge None), the unit was classified
`NoPathToDestination`: zero retreat pull, fire still suppressed. Now a
trapped withdrawer may fire and make physical attacks, and its path
ranking rewards opening the range to the closest enemy.
- **Combat pulls on withdrawers**: aggression, the melee closing
incentive, and herding no longer apply to withdrawing units, so
self-preservation actually decides their path.
- **Predicate drift**: `wantsToFallBack`, `mustFleeBoard`, and
`UnitBehavior` now agree with `refreshCrippledUnits` on
`isCrippled(true)`, so crew-crippled Meks withdraw consistently.

## Files Changed

- `megamek/src/megamek/client/bot/princess/Princess.java` - return-fire
pass, trapped-unit fire permission, predicate unification
- `megamek/src/megamek/client/bot/princess/UnitBehavior.java` -
isCrippled(true)
- `megamek/src/megamek/client/bot/princess/BasicPathRanker.java` -
no-path retreat pull, withdrawal damping in rankPath
- `megamek/unittests/.../PrincessTest.java` - new return-fire test,
updated stubs
- `megamek/unittests/.../BasicPathRankerTest.java` - new
self-preservation test

## Testing

- Unit tests: 2 new, both fail with the fix reverted; 2 updated for the
unified arity. All 216 `megamek.client.bot.princess` tests pass.
checkstyle and javadoc clean.
- Headless benchmark, 100-game mirror-match arms (scenarios: mm-data
#500 and MegaMek/mm-data#501), Princess decision logs mined from
complete (incl. rotated) files:
- **Trapped case** (no retreat path): passive holds-fire 49 -> 0, "no
path - fight on" 0 -> 49, return-fire 0 -> 37. The passive loiter is
eliminated. Crippled units still loitering at game end 0.62 -> 0.41 per
game and game length 11.8 -> 10.9 rounds (both beyond 2 standard
errors).
- **Normal case** (edge reachable): return-fire permission grants 0 ->
4-11 per run, return-fire decisions 3 -> up to 31 (two independent
after-runs; honor-cascade dynamics make these counts high-variance
between runs). Movement metrics unchanged - movement-to-edge already
worked when a path exists.

## Rules clarification

| Behavior | Status |
| --- | --- |
| A crippled unit that returns fire loses honor protection (enemy bots
mark its player dishonored and resume shooting its cripples) | **Working
as designed.** Bot-vs-bot, fled dropped 0.70 -> ~0.56 per game with
destroyed up ~0.2: some cripples now trade escape for self-defense.
Against human opponents - the QA report - there is no honor protection
to lose, so returning fire is strictly better. |

## Out of scope

- Restricting a withdrawing unit's return fire to units that actually
attacked it (would soften the bot-vs-bot dishonor cascade above).
Deliberately not included - minimal in-scope fix first; happy to file it
as a follow-up if wanted.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@HammerGS
HammerGS merged commit c3cf80d into main Aug 2, 2026
6 checks passed
@HammerGS
HammerGS deleted the Fix-Princess-forced-withdrawal-loiter branch August 2, 2026 01:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant