Skip to content

fix(balance-analyser): emit real patrol radius, not spawn rate (closes #124)#128

Merged
hyperpolymath merged 1 commit into
mainfrom
fix/124-balance-analyser-patrol-radius
Jun 1, 2026
Merged

fix(balance-analyser): emit real patrol radius, not spawn rate (closes #124)#128
hyperpolymath merged 1 commit into
mainfrom
fix/124-balance-analyser-patrol-radius

Conversation

@hyperpolymath
Copy link
Copy Markdown
Owner

Summary

Closes #124.

tools/balance-analyser.jl:761 was emitting stats.guard_spawn_rate as the value of the guard_patrol_radius recommendation. Three of seven recommendations in balance-report.json (city, security, backbone) were corrupted by this — wrong units, wrong magnitudes, gameplay-meaningless.

Option A fix (per #124):

  • Add mean_patrol_radius::Float64 to LevelStats (in pixels, matching LevelConfig.res)
  • Compute it as the mean of all guardPlacements[].patrolRadius in level_dict_to_stats
  • Reference it correctly at the recommendation call site
  • Emit mean_patrol_radius in the JSON output
  • Mirror as meanPatrolRadius: float in BalanceAnalyserModel.levelSummary + parser

Test plan

  • julia tools/balance-analyser.jl regenerates balance-report.json with patrol_radius recommendations in pixels (e.g. ~210→179 for backbone) rather than spawn-rate units
  • npx rescript succeeds — meanPatrolRadius field add is purely additive
  • Four pre-existing valid recommendations (alert_threshold, defence_density, guard_spawn_rate ×2) unaffected

Follow-up

`balance-report.json` regeneration + applying the four valid recommendations to per-level configs lands in idaptik#19 once this merges.

Closes #124
Refs #19

🤖 Generated with Claude Code

…#124)

The `guard_patrol_radius` recommendation at `tools/balance-analyser.jl:761`
was reporting `stats.guard_spawn_rate` (guards-per-1000-pixels) in place
of an actual patrol radius. Levels like backbone (3 guards / 1650px =
1.818) got recommendations of "guard_patrol_radius 1.818 → 1.545" — a
unit-mismatched, gameplay-meaningless number.

Fix (Option A from #124):

- Add `mean_patrol_radius::Float64` to `LevelStats` (in pixels — matches
  the `patrolRadius` field already carried by every guard in
  `LevelConfig.res`)
- Compute it in `level_dict_to_stats` as the mean of all
  `guardPlacements[].patrolRadius`
- Reference it correctly at the `guard_patrol_radius` recommendation
  call site
- Emit `mean_patrol_radius` in the JSON output (`generate_report`) so
  the ReScript reader can consume it
- Mirror the field as `meanPatrolRadius: float` in
  `BalanceAnalyserModel.levelSummary` + `parseLevelSummary`

The four valid recommendations in `balance-report.json` (alert_threshold,
defence_density, guard_spawn_rate ×2) are unaffected — only the three
that hit the `guard_patrol_radius` branch were corrupted.

`balance-report.json` itself needs regeneration to consume the fix;
that is a separate data update that lands alongside applying the
recommendations to `LevelConfig.res` (idaptik#19 follow-up).

Closes #124

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: hyperpolymath <6759885+hyperpolymath@users.noreply.github.com>
@hyperpolymath hyperpolymath enabled auto-merge (squash) June 1, 2026 19:16
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 1, 2026

🔍 Hypatia Security Scan

Findings: 71 issues detected

Severity Count
🔴 Critical 11
🟠 High 18
🟡 Medium 42

⚠️ Action Required: Critical security issues found!

View findings
[
  {
    "reason": "Issue in boj-build.yml",
    "type": "missing_timeout_minutes",
    "file": "boj-build.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in build-validation.yml",
    "type": "missing_timeout_minutes",
    "file": "build-validation.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in cflite-pr.yml",
    "type": "missing_timeout_minutes",
    "file": "cflite-pr.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in codeql.yml",
    "type": "missing_timeout_minutes",
    "file": "codeql.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in containers.yml",
    "type": "missing_timeout_minutes",
    "file": "containers.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in containers.yml",
    "type": "missing_timeout_minutes",
    "file": "containers.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in dco.yml",
    "type": "missing_timeout_minutes",
    "file": "dco.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in dogfood-gate.yml",
    "type": "missing_timeout_minutes",
    "file": "dogfood-gate.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in dogfood-gate.yml",
    "type": "missing_timeout_minutes",
    "file": "dogfood-gate.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in dogfood-gate.yml",
    "type": "missing_timeout_minutes",
    "file": "dogfood-gate.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

@hyperpolymath hyperpolymath merged commit 8a48a88 into main Jun 1, 2026
28 of 31 checks passed
@hyperpolymath hyperpolymath deleted the fix/124-balance-analyser-patrol-radius branch June 1, 2026 20:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

balance-analyser: guard_patrol_radius recommendations report guard_spawn_rate values (bug at tools/balance-analyser.jl:762)

1 participant