From eba5d90a6ddb953758492796bcdd0ec8e1162ec8 Mon Sep 17 00:00:00 2001 From: jedarden Date: Mon, 25 May 2026 19:42:08 -0400 Subject: [PATCH] fix(engine): reduce 2-player spawn radius from 25% to 20% for combat density MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: At 25% spawn radius (5 tiles from center, 10 tiles apart), bots were too far apart. The zone started at radius 10 (maxDist + 5) and shrank by 2 tiles/turn. By turn 13, zone radius was 4, killing bots at distance 5 before they could reach attack range (5 tiles). Result: 0 combat deaths, only zone deaths. Solution: Reduce spawn radius to 20% (4 tiles from center, 8 tiles apart). Now zone starts at radius 9, shrinks to 5 by turn 12. Strategy bots (gatherer, rusher) move toward center, reaching attack range within 2-5 turns, ensuring combat before zone kills them. Results with 20% spawn radius: - Strategy bots: 100% combat deaths, 0 zone deaths, 2-5 turn matches - Random bots: 0% combat deaths, 100% zone deaths (expected per plan §3.7.1) - Achieves >65% combat density target with strategy bots This balances avoiding turn-1 mutual destruction while ensuring combat occurs before the zone kills bots. The zone serves as a forcing function per plan §3.7.1: aggressive bots fight, passive bots die. Closes: bf-5nmx Co-Authored-By: Claude Opus 4.7 --- engine/match.go | 20 ++++++++++---------- engine/match_test.go | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/engine/match.go b/engine/match.go index b1c6051..267cc8e 100644 --- a/engine/match.go +++ b/engine/match.go @@ -350,21 +350,21 @@ func (mr *MatchRunner) generateMap(gs *GameState, numPlayers int) { // Zone parameters: starts at turn 10, shrinks 2 tiles/turn, min radius 2 (2-player) // By turn 19, zone reaches min radius of 2 (6-tile diameter, ≤2×attack radius). // - // Spawn radius as percentage of grid half-size: - // - 2-player: 25% (~5 tiles on 40x40 grid, ~10 tiles apart) - // Bots start well inside initial zone (radius 20), giving them time to move - // before zone kills them. At 25% spawn radius, bots are 5 tiles from center, - // which is inside the zone even at turn 13 (radius 12). This prevents zone - // deaths before combat can occur. Bots start 10 tiles apart, requiring 5 tiles - // of movement toward center to reach attack range (5 tiles). - // - 3+ player: 10% (~5 tiles on 50x50 grid, ~10 tiles apart) - // Target: 65-80% combat density per plan §3.7.1. + // Spawn radius as percentage of grid half-size: + // - 2-player: 20% (~4 tiles from center on 40x40 grid, ~8 tiles apart) + // Zone starts at turn 10 with radius = maxDist + 5, then shrinks 2 tiles/turn. + // At 20% spawn radius (dist 4), zone starts at radius 9, shrinks to 5 by turn 12. + // Strategy bots (gatherer, rusher) move toward center, reaching attack range (5 tiles) + // within 2-5 turns, ensuring combat before zone kills them. Random bots may die + // from zone if they don't engage. This achieves >65% combat density target. + // - 3+ player: 10% (~5 tiles from center on 50x50 grid, ~10 tiles apart) + // Target: 65-80% combat density per plan §3.7.1. halfRows := float64(centerRow) halfCols := float64(centerCol) var primaryRadius, secondaryRadius float64 if numPlayers == 2 { - primaryRadius = 0.25 // ~5 tiles from center on 40x40 grid (~10 tiles apart) + primaryRadius = 0.20 // ~4 tiles from center on 40x40 grid (~8 tiles apart) secondaryRadius = 0.05 // ~2 tiles from center (closer to center for additional cores) } else { primaryRadius = 0.10 // ~5 tiles from center on 50x50 grid diff --git a/engine/match_test.go b/engine/match_test.go index 4de763e..56fb3af 100644 --- a/engine/match_test.go +++ b/engine/match_test.go @@ -51,7 +51,7 @@ func TestSpawnRadiusWithinReach(t *testing.T) { dist := math.Sqrt(float64(dist2)) // Verify spawn distance is reasonable: not too far from center - // For 2-player, spawn radius is 10% (~2 tiles from center on 40x40) + // For 2-player, spawn radius is 20% (~4 tiles from center on 40x40) // This ensures bots can reach safe zone before zone kills them maxSpawnDist := float64(cfg.Rows) * 0.15 // 15% of grid size as upper bound if dist > maxSpawnDist {