Quick answer: Define ascending move thresholds for 3/2/1 stars and compare from best to worst with inclusive operators, awarding three stars when moves are at or below the three-star limit.
Star ratings reward efficiency, but boundary bugs are common: finishing in exactly the three-star limit should give three stars, not two. Use inclusive comparisons and evaluate the best tier first.
How to fix it
1. Define clear thresholds
Store the maximum moves for three stars and for two stars. Anything above the two-star limit but still a win earns one star.
2. Compare best-tier first, inclusively
Award three stars when moves <= threeStarMax, else two stars when moves <= twoStarMax, else one star. Inclusive <= avoids dropping players at the boundary.
3. Drive other modes from the same table
If a level rates by time instead of moves, reuse the same ascending-threshold structure so the comparison logic stays consistent across rating types.
Catching the ones you can't reproduce
The hardest version of this to fix is the one you can't reproduce — it only happens on a player's hardware, OS, driver, or save state, under conditions that simply aren't present on your machine. A report that says “it crashed” or “it froze” gives you nothing to act on, so the bug survives release after release while quietly costing you players.
Automatic error capture closes that gap. Each failure arrives with its full stack trace, the device and OS, the build number, and a breadcrumb trail of what the player did right before it broke, so even a failure you have never seen becomes a specific, reproducible issue. Fold identical failures into one signature ranked by how many players each hits, and your worklist sorts itself worst-first instead of arriving as a stream of vague complaints.
This is where a tool like Bugnet earns its place. Its SDK captures every GameMaker error automatically with the full stack trace plus device, OS, memory, build, and game-state context, folds duplicates into one grouped issue with an occurrence count, and ties each to the build it first appeared on — so you fix the problem that hurts the most players first and confirm it is gone when its signature disappears from the next release.
The errors you never hear about are the ones quietly costing you players. Visibility turns them into a worklist.