Skip to content

Route marching armies around lakes; show thieves on the map - #94

Merged
daedeloth merged 3 commits into
developfrom
claude/project-thread-0yjogm
Nov 5, 2026
Merged

daedeloth merged 3 commits into
developfrom
claude/project-thread-0yjogm

Conversation

@daedeloth

Copy link
Copy Markdown
Member

Requested by Thijs · project thread

What

Armies, regiments, market transfers and thieves now walk around lakes instead of straight through them. Travel time uses the longer route, and the map flags and dashed lines follow the shore. Moving thieves now also show on the map, with their own flag.

How

  • Dolumar_Map_LandRoute (new): walks the straight line and only searches where that line is under water. The search is a grid A* inside a box around that one crossing, and the box grows if no way is found. The result is smoothed back to straight legs. Over open land the distance is still exactly the straight line. If there is no way around, it falls back to the straight line, so no village becomes unreachable. Results are cached in memcache with no expiry, because water never changes.
  • Dolumar_Map_Distance: every walking edge, to the destination and to portals, gets its cost from LandRoute. Routes are now stored as legs (a list of point lists, with a portal jump between legs). The new $overLand parameter (default true) is passed as false by Ranking and PlayerProfile, so their long distance lists stay a cheap straight-line estimate.
  • Map: ArmyFactory::routeSegments() reads both the new leg format and the old flat format, so armies already on the move keep their stored route. MovingRows::pointsOfRow() reads both formats too.
  • Thieves: SpecialUnits::moveUnit() now stores vsu_from and vsu_route (new idempotent upgrade dump/upgrades/20261105-thief-routes.sql, mirrored in dump.sql). MovingRows::thieves() and ArmyFactory::fromThiefRow() build a thief map object with a new sprite (a dark pennant with a silver crescent). Thieves are secret: only the owner and their clan receive them. The target and strangers get nothing, not even a neutral sprite. Thieves sent before deploy have no vsu_from and are not drawn. The kind text is added in en/fr/de.

Numbers (real map generator, default seed)

  • About 2% of tiles are water. 15 to 23% of straight lines between land tiles cross water.
  • The detour is +0.3 to 0.4% at the median, the largest seen was about +13%, and the mean over all routes is about +0.3%. Routes come within about 2% of a full-grid optimum.
  • Search time without the cache: about 3 to 9 ms median for routes up to 200 tiles. For 200 to 1000 tiles it is about 80 ms median and 230 ms at most. The cache makes repeats free.

Testing

  • vendor/bin/phpunit --testsuite unit: 170 tests pass. New tests cover synthetic lakes (going around, two lakes, no way around, the cache), portal legs, the leg and flat route formats, thief rows, and keeping thieves secret. Two real-map routes are tested to stay on land, with a 2 s time guard.
  • phpcs: no new findings.
  • Not run against the Docker stack or a database in this session (no Docker here). Please check on the PR preview: send an attack across a lake, and send a thief.

Balance note

This is a small rules change: about 1 route in 5 gets a little longer. Thijs approved it in the project thread.


Generated by Claude Code

Dolumar_Map_LandRoute walks the straight line and, only where it crosses
water, searches a way around that lake (grid A* in a box around the
crossing), then smooths the result to straight legs. Open land stays the
exact straight line; no way around falls back to the straight line.
Results are cached in memcache without expiry (water never changes).

Dolumar_Map_Distance uses it for every walking edge (to the destination
and to portals), so travel time, the Battle window, market transfers and
thieves all follow the land route. Routes are now stored as legs (a list
of point lists, a portal jump between legs); the map still reads the old
flat routes of armies already on the move. Ranking and profile distance
lists keep the cheap straight line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WpWbf9LAeFevtaMRw9drZH
A thief sent to another village now stores where it left from and its
route around lakes (villages_specialunits.vsu_from / vsu_route, new
upgrade file). The map draws it with a dark pennant with a silver
crescent. Thieves are secret: only the owner and their clan get them,
not the target and not unrelated viewers. Thieves sent before this
change have no vsu_from and are not drawn.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WpWbf9LAeFevtaMRw9drZH
@daedeloth daedeloth self-assigned this Nov 5, 2026
@github-actions

github-actions Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Preview: removed, this pull request is closed.

From review: walk (b, a) could pick a different equal-cost detour than
walk (a, b), so a regiment's or thief's trip home took a few seconds
longer or shorter than the trip out. Search one canonical direction and
reverse it. Also make sure the map seed is loaded before building the
cache key.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WpWbf9LAeFevtaMRw9drZH
@daedeloth
daedeloth merged commit 382d57e into develop Nov 5, 2026
5 checks passed
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.

2 participants