feat: playable arcade — rooms, identity, client, deployment
Round length is now bounded: the multiplier follows a hyperbolic curve diverging at 60s, replacing an exponential one where a 275x crash point produced a two-and-a-half minute round. Fixes seed reveal, which silently failed every round because pgx cannot encode a fixed-size byte array as bytea. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -95,3 +95,33 @@ func TestTicksToMultiplierRoundTrips(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No round may outlast the ceiling, however extreme the crash point.
|
||||
func TestRoundLengthIsBounded(t *testing.T) {
|
||||
if got := MultiplierAt(RoundTicks); got != MaxMultiplier() {
|
||||
t.Fatalf("curve past the ceiling = %v, want %v", got, MaxMultiplier())
|
||||
}
|
||||
// Even the most extreme crash point settles within the ceiling.
|
||||
worst := fixed.FromInt(4_000_000_000)
|
||||
if tick := TicksToMultiplier(worst); tick > RoundTicks {
|
||||
t.Fatalf("extreme crash point needs %d ticks, ceiling is %d", tick, RoundTicks)
|
||||
}
|
||||
}
|
||||
|
||||
// Timings that matter for how the game feels.
|
||||
func TestCurveTimings(t *testing.T) {
|
||||
for _, c := range []struct {
|
||||
multiplier int64
|
||||
maxSeconds float64
|
||||
}{
|
||||
{2, 20}, // the common case should arrive quickly
|
||||
{10, 45},
|
||||
{100, 56},
|
||||
} {
|
||||
tick := TicksToMultiplier(fixed.FromInt(c.multiplier))
|
||||
secs := float64(tick) / TickHz
|
||||
if secs > c.maxSeconds {
|
||||
t.Errorf("%dx takes %.1fs, want under %.0fs", c.multiplier, secs, c.maxSeconds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user