Skip to content

Refactor Grid Logic and Optimize Pathfinding/Movement#125

Merged
candour merged 4 commits into
mainfrom
refactor-grid-logic-774816735204400749
May 6, 2026
Merged

Refactor Grid Logic and Optimize Pathfinding/Movement#125
candour merged 4 commits into
mainfrom
refactor-grid-logic-774816735204400749

Conversation

@candour
Copy link
Copy Markdown
Owner

@candour candour commented May 5, 2026

I have picked the grid-related logic across several files for refactoring. The primary goal was to centralize redundant math and improve the efficiency of the core game loop.

Key changes include:

  1. Centralized Grid Math: All axial distance calculations and neighbor finding logic have been moved to a new GridUtils.kt file. This eliminates duplication in MainViewModel, MapGenerator, and Pathfinding.
  2. Optimized Pathfinding: The A* algorithm in Pathfinding.kt was rewritten from scratch to be more idiomatic and efficient, utilizing the new centralized utility methods.
  3. Improved Game Loop Efficiency: In MainViewModel.kt, the handleEnemyMovement function was refactored to consolidate multiple iterations over puddles into a single pass per enemy, significantly reducing the number of distance calculations performed every tick.
  4. Documentation: Updated fixes.md to track these improvements as requested.

All unit tests (including Pathfinding and MainViewModel tests) pass successfully.


PR created automatically by Jules for task 774816735204400749 started by @candour

Summary by CodeRabbit

  • New Features

    • Bak Kut Teh (BKT) stat-boost system and Tiger Mom buff improvements affecting stall buffs, providers, and ATM income.
  • Improvements

    • Enemies now slow when crossing puddles; enhanced stall targeting, projectile interactions, and stall-related effects.
    • More accurate, grid-aware distance and neighbor handling for visuals, buffs, and budget/ATM actions.
  • Refactor

    • Centralized grid utilities and a rewritten pathfinding implementation for more reliable, neighbor-aware movement.

- Created GridUtils.kt to consolidate axial coordinate math and neighbor offsets.
- Rewrote Pathfinding.kt with an idiomatic and efficient A* implementation.
- Optimized handleEnemyMovement in MainViewModel to reduce redundant puddle iterations and distance calculations.
- Updated MapGenerator and other call sites to use the new GridUtils.
- Added record of changes to fixes.md.

Co-authored-by: candour <4670475+candour@users.noreply.github.com>
@google-labs-jules
Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 5, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e8b1b7cd-b80d-48e8-b87f-2ed6adab8bdc

📥 Commits

Reviewing files that changed from the base of the PR and between 944db85 and eaf7c64.

📒 Files selected for processing (3)
  • app/src/main/java/com/messark/hawker/MainViewModel.kt
  • app/src/main/java/com/messark/hawker/utils/GridUtils.kt
  • fixes.md

📝 Walkthrough

Walkthrough

Centralizes axial/grid math in GridUtils, rewrites A* Pathfinding to use the utilities, and updates MainViewModel to use GridUtils while adding Bak Kut Teh stat-boost aggregation, puddle slowdowns, and related enemy/stall/projectile logic changes.

Changes

Grid Logic Centralization & Gameplay Update

Layer / File(s) Summary
Utility Foundation
app/src/main/java/com/messark/hawker/utils/GridUtils.kt
Adds NEIGHBOR_OFFSETS, getNeighbors(coord: AxialCoordinate), and two axialDistance overloads (AxialCoordinate and PreciseAxialCoordinate).
Pathfinding Core
app/src/main/java/com/messark/hawker/utils/Pathfinding.kt
Rewrites A* with explicit gScores, parents, openSet/closedSet; uses GridUtils.getNeighbors and GridUtils.axialDistance; adds reconstructPath; updates Node signature.
Map Generator Cleanup
app/src/main/java/com/messark/hawker/utils/MapGenerator.kt
Removes local getNeighbors helper (delegated to GridUtils).
Game Logic Integration (movement & status)
app/src/main/java/com/messark/hawker/MainViewModel.kt
Replaces ad-hoc distance/neighbor logic with GridUtils across enemy movement, path handling, facing, puddle slowdowns, status duration decay, and removes the old axialDistance wrapper.
Combat / Projectiles / Stall Rules
app/src/main/java/com/messark/hawker/MainViewModel.kt
Updates stall target selection, projectile/AoE hit checks, Tray Return Uncle neighbor rules, and release-tile computation to use GridUtils.getNeighbors/axialDistance.
Stat Boosts (BKT)
app/src/main/java/com/messark/hawker/MainViewModel.kt
Adds data class BoostResult(val multiplier: Float, val providerCoords: List<AxialCoordinate>) and private fun calculateStatBoost(coord: AxialCoordinate, state: GameState): BoostResult to aggregate adjacent BKT boosts and return multiplier + providers.
Docs / Notes
fixes.md
Documents grid utility centralization, Pathfinding A* rewrite, and handleEnemyMovement refactor (puddles/stat updates).

Sequence Diagram(s)

sequenceDiagram
    participant VM as MainViewModel
    participant Grid as GridUtils
    participant Path as Pathfinding
    participant GS as GameState

    VM->>Grid: getNeighbors(coord)
    Grid-->>VM: adjacent coords
    VM->>Path: findPath(start, end)
    Path->>Grid: getNeighbors / axialDistance
    Grid-->>Path: neighbors / distances
    Path-->>VM: reconstructed path
    VM->>GS: apply movement updates (position, facing, status)
    VM->>Grid: getNeighbors(coord) for boosts
    Grid-->>VM: adjacent coords
    VM->>GS: apply boosts/slowdowns to stalls/enemies/projectiles
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly Related PRs

  • candour/towerpower#125: Centralizes axial distance and neighbor logic into GridUtils and updates Pathfinding/MainViewModel accordingly.
  • candour/towerpower#126: Modifies Bak Kut Teh boost logic and neighbor usage in MainViewModel, overlapping with added BoostResult/calculateStatBoost.
  • candour/towerpower#120: Similar A* Pathfinding changes (Node, parents/gScores, path reconstruction) and heuristic updates.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Refactor Grid Logic and Optimize Pathfinding/Movement' accurately describes the main changes: centralizing grid utilities and optimizing pathfinding/movement logic across the codebase.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor-grid-logic-774816735204400749

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 5, 2026

Build Successful! 🚀

Download APK

Note: This link will be removed when the PR is closed.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
app/src/main/java/com/messark/hawker/utils/GridUtils.kt (1)

9-12: 💤 Low value

Consider exposing NEIGHBOR_OFFSETS as an immutable List.

Array is mutable and reference-shared, so callers could in principle reassign elements (e.g., GridUtils.NEIGHBOR_OFFSETS[0] = ...) and silently corrupt neighbor generation everywhere. A List (or private array exposed via List) gives you immutability for free.

♻️ Suggested change
-    val NEIGHBOR_OFFSETS = arrayOf(
-        AxialCoordinate(1, 0), AxialCoordinate(1, -1), AxialCoordinate(0, -1),
-        AxialCoordinate(-1, 0), AxialCoordinate(-1, 1), AxialCoordinate(0, 1)
-    )
+    val NEIGHBOR_OFFSETS: List<AxialCoordinate> = listOf(
+        AxialCoordinate(1, 0), AxialCoordinate(1, -1), AxialCoordinate(0, -1),
+        AxialCoordinate(-1, 0), AxialCoordinate(-1, 1), AxialCoordinate(0, 1)
+    )
app/src/main/java/com/messark/hawker/utils/Pathfinding.kt (1)

62-73: 💤 Low value

Minor: reconstructPath won't include start if start == end path-relaxation never sets parents[start].

Not a bug here because the start == end case is short-circuited on line 18, and any successful search to a different end guarantees a chain of parents entries terminating at start (whose parents[start] is absent — so the loop correctly stops after adding start). Just calling out that this invariant is what makes the helper correct; a small comment would help future readers.

📝 Optional doc
+    /**
+     * Walks the parents map from `end` back to the start node (which is the only node
+     * without an entry in `parents`). Caller must guarantee `end` was reached.
+     */
     private fun reconstructPath(
app/src/main/java/com/messark/hawker/MainViewModel.kt (1)

468-469: 💤 Low value

Prefer Kotlin's maxOf / kotlin.math.max over java.lang.Math.max.

Idiomatic Kotlin and avoids the implicit java.lang.Math dependency. Applies to several other call sites in this file (e.g., 514, 804, 805) but only the changed lines are flagged here.

♻️ Suggested change
-            var freezeDuration = Math.max(0, enemy.freezeDurationMs - 32)
-            var speedBoostDuration = Math.max(0, enemy.speedBoostDurationMs - 32)
+            var freezeDuration = maxOf(0, enemy.freezeDurationMs - 32)
+            var speedBoostDuration = maxOf(0, enemy.speedBoostDurationMs - 32)

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3dba75ce-74bb-4227-8b08-d83a4b12af5a

📥 Commits

Reviewing files that changed from the base of the PR and between 7e3712e and fe437f5.

📒 Files selected for processing (5)
  • app/src/main/java/com/messark/hawker/MainViewModel.kt
  • app/src/main/java/com/messark/hawker/utils/GridUtils.kt
  • app/src/main/java/com/messark/hawker/utils/MapGenerator.kt
  • app/src/main/java/com/messark/hawker/utils/Pathfinding.kt
  • fixes.md
💤 Files with no reviewable changes (1)
  • app/src/main/java/com/messark/hawker/utils/MapGenerator.kt

Comment thread app/src/main/java/com/messark/hawker/MainViewModel.kt
@candour candour enabled auto-merge (squash) May 6, 2026 01:30
@candour
Copy link
Copy Markdown
Owner Author

candour commented May 6, 2026

@jules I think Neighbor_offsets should be an immutable List.

Also Prefer Kotlin's maxOf / kotlin.math.max over java.lang.Math.max.

@candour
Copy link
Copy Markdown
Owner Author

candour commented May 6, 2026

The comparison for puddles being < 0.8 should use a float for consistency

@google-labs-jules
Copy link
Copy Markdown
Contributor

@jules I think Neighbor_offsets should be an immutable List.

Also Prefer Kotlin's maxOf / kotlin.math.max over java.lang.Math.max.

Thank you for the feedback, @jules! I've made the following changes:

  1. Changed NEIGHBOR_OFFSETS in GridUtils.kt to an immutable List.
  2. Replaced Math.max with Kotlin's maxOf in MainViewModel.kt for better idiomaticity.

- Changed NEIGHBOR_OFFSETS to a List in GridUtils.kt.
- Replaced Math.max with Kotlin's maxOf in MainViewModel.kt.

Co-authored-by: candour <4670475+candour@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 6, 2026

Build Successful! 🚀

Download APK

Note: This link will be removed when the PR is closed.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/src/main/java/com/messark/hawker/MainViewModel.kt (1)

583-618: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Return finalEnemies from handleEnemyMovement.

Lines 584-602 apply Tiger Mom buff additions/removals to finalEnemies, but Line 618 returns updatedEnemies. That drops those mutations every tick, so the armor buff state never actually sticks.

Suggested fix
-        return Pair(mutableState, updatedEnemies)
+        return Pair(mutableState, finalEnemies)

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6e4f0f60-9acf-4685-b661-341a75e6b6ed

📥 Commits

Reviewing files that changed from the base of the PR and between fe437f5 and 84fbbad.

📒 Files selected for processing (2)
  • app/src/main/java/com/messark/hawker/MainViewModel.kt
  • app/src/main/java/com/messark/hawker/utils/GridUtils.kt

@candour
Copy link
Copy Markdown
Owner Author

candour commented May 6, 2026

In MainViewModel.kt Return finalEnemies from handleEnemyMovement.

Lines 584-602 apply Tiger Mom buff additions/removals to finalEnemies, but Line 618 returns updatedEnemies. That drops those mutations every tick, so the armor buff state never actually sticks.

@google-labs-jules
Copy link
Copy Markdown
Contributor

In MainViewModel.kt Return finalEnemies from handleEnemyMovement.

Lines 584-602 apply Tiger Mom buff additions/removals to finalEnemies, but Line 618 returns updatedEnemies. That drops those mutations every tick, so the armor buff state never actually sticks.

Sharp catch! I've updated handleEnemyMovement to return finalEnemies instead of updatedEnemies, ensuring that the Tiger Mom buff mutations are correctly preserved.

Corrected a bug where Tiger Mom buff mutations were dropped by returning the intermediate updatedEnemies list instead of the final finalEnemies list in handleEnemyMovement.

Co-authored-by: candour <4670475+candour@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 6, 2026

Build Successful! 🚀

Download APK

Note: This link will be removed when the PR is closed.

@candour
Copy link
Copy Markdown
Owner Author

candour commented May 6, 2026

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
app/src/main/java/com/messark/hawker/MainViewModel.kt (1)

477-486: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use a Float literal for puddle proximity comparison.

GridUtils.axialDistance(PreciseAxialCoordinate, PreciseAxialCoordinate) returns Float, so < 0.8 performs a FloatDouble widening on every enemy/puddle pair each tick. Use 0.8f to keep the comparison purely in Float and consistent with the rest of the precise-coord math.

Proposed fix
-                if (GridUtils.axialDistance(enemy.position, puddle.position) < 0.8) {
+                if (GridUtils.axialDistance(enemy.position, puddle.position) < 0.8f) {
🧹 Nitpick comments (1)
app/src/main/java/com/messark/hawker/MainViewModel.kt (1)

524-528: 💤 Low value

Optional: extract the screen-x facing comparison.

The same q + r / 2f screen-x comparison is repeated at lines 431, 524–528, and 1096–1100 — three slightly different copies of the same axial→screen-x facing rule. A small helper (e.g., GridUtils.screenX(q, r) or isFacingLeft(from, to, fallback)) would DRY these and keep the canonical transformation in one place alongside toScreenPrecise. Not blocking.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9c914104-b06f-4946-812b-a70524262c69

📥 Commits

Reviewing files that changed from the base of the PR and between 7e3712e and 944db85.

📒 Files selected for processing (5)
  • app/src/main/java/com/messark/hawker/MainViewModel.kt
  • app/src/main/java/com/messark/hawker/utils/GridUtils.kt
  • app/src/main/java/com/messark/hawker/utils/MapGenerator.kt
  • app/src/main/java/com/messark/hawker/utils/Pathfinding.kt
  • fixes.md
💤 Files with no reviewable changes (1)
  • app/src/main/java/com/messark/hawker/utils/MapGenerator.kt

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.

1 participant