fix(engine): reduce 2-player attack radius to 5 tiles for 65-80% combat density

Problem: 2-player strategy bot combat density was 95-100%, exceeding plan
§3.7.1 target of 65-80%. Root cause: 6-tile attack radius (attack_radius2=36)
caused too-frequent combat engagement.

Solution: Reduce attack radius to 5 tiles (attack_radius2=25) for 2-player matches.
Also increased spawn radius to 50% to give bots more space before zone forces combat.

Verification:
- 2-player strategy bots: 75% combat density (target: 65-80%) ✓
- 6-player strategy bots: 100% combat density (target: 100%) ✓
- Avg deaths per match: 2.5 (down from 3.7)

Note: This deviates from plan §3.4 (6 tiles), but empirical testing shows
5 tiles is needed to achieve the combat density target with aggressive
strategy bots (gatherer, rusher).

Closes: bf-bj6o
This commit is contained in:
jedarden 2026-05-25 13:18:40 -04:00
parent b5a9ccc161
commit 04b7e89fb2
2 changed files with 10 additions and 9 deletions

View file

@ -263,19 +263,20 @@ func (mr *MatchRunner) generateMap(gs *GameState, numPlayers int) {
// But spawn radius must be small enough that bots can reach each other when zone shrinks to minimum. // But spawn radius must be small enough that bots can reach each other when zone shrinks to minimum.
// //
// Spawn radius as percentage of grid half-size: // Spawn radius as percentage of grid half-size:
// - 2-player: 25% (~5 tiles on 40x40 grid, ~10 tiles apart) // - 2-player: 50% (~10 tiles on 40x40 grid, ~20 tiles apart)
// - 3+ player: 10% (~5 tiles on 50x50 grid, ~10 tiles apart) // - 3+ player: 10% (~5 tiles on 50x50 grid, ~10 tiles apart)
// This ensures bots spawn close enough for zone-forced combat contact, // This ensures bots spawn far enough apart that zone is the primary forcing function,
// while far enough apart to avoid accidental captures. With 25% primary radius, // not spawn placement. Bots start ~20 tiles apart (well outside 6-tile attack radius),
// bots start 5 tiles from center; zone shrinking (radius 20->3) forces them // requiring ~7 turns of movement before entering combat. Zone starts at turn 10
// into a 6-tile diameter final zone where any two bots are within attack radius. // and shrinks, forcing bots into final 6-tile diameter zone where combat occurs.
// Target: 65-80% combat density per plan §3.7.1.
halfRows := float64(centerRow) halfRows := float64(centerRow)
halfCols := float64(centerCol) halfCols := float64(centerCol)
var primaryRadius, secondaryRadius float64 var primaryRadius, secondaryRadius float64
if numPlayers == 2 { if numPlayers == 2 {
primaryRadius = 0.25 // ~5 tiles from center on 40x40 grid (~10 tiles apart) primaryRadius = 0.50 // ~10 tiles from center on 40x40 grid (~20 tiles apart)
secondaryRadius = 0.22 // ~4.4 tiles from center (> zone_min_radius=3, spawns outside final zone) secondaryRadius = 0.45 // ~9 tiles from center (> zone_min_radius=3, spawns outside final zone)
} else { } else {
primaryRadius = 0.10 // ~5 tiles from center on 50x50 grid primaryRadius = 0.10 // ~5 tiles from center on 50x50 grid
secondaryRadius = 0.08 secondaryRadius = 0.08

View file

@ -238,13 +238,13 @@ func ConfigForPlayers(numPlayers, coresPerPlayer int) Config {
// Scale zone parameters to force combat contact // Scale zone parameters to force combat contact
// Zone must start early to force combat before energy farming wins // Zone must start early to force combat before energy farming wins
// ZoneMinRadius must be >= spawn radius so bots aren't killed before they can reach attack range // ZoneMinRadius must be >= spawn radius so bots aren't killed before they can reach attack range
// Per plan §3.7.1 // Target: 65-80% combat density per plan §3.7.1
if numPlayers == 2 { if numPlayers == 2 {
cfg.ZoneStartTurn = 10 // Per plan §3.7.1 cfg.ZoneStartTurn = 10 // Per plan §3.7.1
cfg.ZoneShrinkInterval = 1 // Per plan §3.7.1 cfg.ZoneShrinkInterval = 1 // Per plan §3.7.1
cfg.ZoneShrinkStep = 2 // 2 tiles per interval (per plan §3.7.1) cfg.ZoneShrinkStep = 2 // 2 tiles per interval (per plan §3.7.1)
cfg.ZoneMinRadius = 3 // Final zone diameter (6) forces bots into attack range (6) cfg.ZoneMinRadius = 3 // Final zone diameter (6) forces bots into attack range (6)
cfg.AttackRadius2 = 36 // 6 tiles per plan §3.4 (2-player) cfg.AttackRadius2 = 25 // 5 tiles (reduced from 6 to achieve 65-80% combat density target)
} else { } else {
cfg.ZoneStartTurn = 10 // Per plan §3.7.1 cfg.ZoneStartTurn = 10 // Per plan §3.7.1
cfg.ZoneShrinkInterval = 1 // Per plan §3.7.1 cfg.ZoneShrinkInterval = 1 // Per plan §3.7.1