package ai import ( "testing" "github.com/greyson/super-auto-pets-board-game/internal/game" ) // TestWinScoreMarginBreaksTiesNotVerdicts pins down the margin tie-breaker: // within a single verdict it prefers the more decisive result (a win with pets // to spare, a loss that took most of the enemy down), but no margin, however // lopsided, may ever raise a loss above a draw or a draw above a win. func TestWinScoreMarginBreaksTiesNotVerdicts(t *testing.T) { mk := func(winner, mine, theirs int) *game.BattleResult { return &game.BattleResult{WinnerSeat: winner, Survivors: []int{mine, theirs}} } decisiveWin := winScore(mk(0, 5, 0), 0) narrowWin := winScore(mk(0, 1, 0), 0) drawAhead := winScore(mk(-1, 3, 1), 0) evenDraw := winScore(mk(-1, 0, 0), 0) drawBehind := winScore(mk(-1, 1, 3), 0) narrowLoss := winScore(mk(1, 0, 1), 0) blowoutLoss := winScore(mk(1, 0, 6), 0) // Ties within a verdict resolve toward the stronger finish. if !(decisiveWin > narrowWin) { t.Errorf("a win with survivors should beat a squeaker: %.4f !> %.4f", decisiveWin, narrowWin) } if !(drawAhead > evenDraw && evenDraw > drawBehind) { t.Errorf("draws should order by margin: ahead %.4f, even %.4f, behind %.4f", drawAhead, evenDraw, drawBehind) } if !(narrowLoss > blowoutLoss) { t.Errorf("a narrow loss should beat a blowout: %.4f !> %.4f", narrowLoss, blowoutLoss) } // Verdict ordering is inviolable: the best-possible loss still ranks below // the worst-possible draw, and the best draw below the worst win. if !(narrowWin > drawAhead) { t.Errorf("the worst win must outrank the best draw: %.4f !> %.4f", narrowWin, drawAhead) } if !(drawBehind > narrowLoss) { t.Errorf("the worst draw must outrank the best loss: %.4f !> %.4f", drawBehind, narrowLoss) } }