fix(moonbreak): estimate losses from the real waves, not a pooled average - #58
Merged
Merged
Conversation
…rage The loss estimate pooled the whole attack into one average wave size (`totalRip / waves`) while the probability was built from each attacker's own six-wave split. The two halves of the same calculation therefore modelled different attacks, and the losses came out blind to how the fleet was divided: 101 Deathstars sent as 1 + 100 gave the same 22.04 mean losses as 50 + 50, where the chance of breaking the moon was 79 % against 87 %. It now walks the same wave sequence the probability is built from — each attacker's six waves, at their own size, in firing order — so a lopsided attack and an even one no longer look alike. Attackers with fewer than six Deathstars pad with empty waves, which neither threaten the moon nor lose a ship. Even fleets, which is what the numbers were checked against when this was ported from the Discord bot, barely move: 6 RIP stays at 2.48, 4x25 goes from 16.72 to 16.85. Lopsided ones move a lot, which was the point. One consequence worth stating: losses now depend on the order the attackers are listed, because the fleet that opens faces a moon still standing. The probability does not. The help text says so. Also bumps ogamejs to 4.0.2, which refuses rate terms that cannot describe a trade (rolljee/ogamejs#40). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The inconsistency flagged at the end of #56.
The bug
computeMoonbreakbuilds its probability from each attacker's own six-wave split —remainderwaves ofbase + 1, the rest ofbase. Its loss estimate did something else: it pooled the whole attack into one average wave size,totalRip / min(totalRip, attackers × 6).The two halves of the same calculation therefore modelled different attacks, and the losses came out blind to how the fleet was divided:
[1, 100][50, 50]Same answer for two attacks that are nothing alike. Spread evenly, the waves are smaller, the moon falls sooner and fewer waves ever fire — so it should cost less, not the same.
The fix
Walk the same wave sequence the probability is built from: each attacker's six waves, at their own size, in firing order. An attacker with fewer than six Deathstars pads with empty waves, which neither threaten the moon nor lose a ship, so they cost nothing to carry.
Impact on the numbers people already trust
Even fleets — what the module was checked against when it was ported from
og-bot-discord— barely move:[6]on 8944 km[25, 25][25, 25, 25, 25][100]Lopsided ones move a lot, which was the point.
One consequence worth stating
Losses now depend on the order the attackers are listed, because the fleet that opens faces a moon still standing:
[100, 1]loses 27.88 where[1, 100]loses 26.74. The probability is unchanged either way. That is real — attackers fly one after the other — and the help text now says so in both languages, rather than leaving it to be discovered.Not changed
The variance still sums the per-wave variances, treating waves as independent although they share the survival chain, and the spread is still summarised as a gaussian. Both are approximations kept from the model this was ported from; they are now documented as such in the code. Changing them is a separate decision about the statistics, not about which attack is being modelled.
Also here
ogamejsbumped to 4.0.2, which refuses rate terms that cannot describe a trade (rolljee/ogamejs#40) — the follow-up noted in #56.Tests
New coverage for the wave decomposition (
attackerWaves,attackWaves: extras first, empty padding, firing order, every Deathstar accounted for) and for the two behaviours that motivated the change — a lopsided attack costing more than an even one, and the leading fleet costing more than the trailing one. Existing expectations updated where the numbers moved. 415 pass, build OK.🤖 Generated with Claude Code