Skip to content

Re-path when a bot lands below its path - #2185

Merged
sunzenshen merged 2 commits into
NeotokyoRebuild:masterfrom
sunzenshen:bot-repath-after-fall
Oct 3, 2026
Merged

sunzenshen merged 2 commits into
NeotokyoRebuild:masterfrom
sunzenshen:bot-repath-after-fall

Conversation

@sunzenshen

@sunzenshen sunzenshen commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Description

Re-path when a bot lands below its path

When a bot walks or is pushed off a ledge its path does not drop from, it lands below the path and keeps following it. The stock fell-off check in PathFollower::Update only fires when the goal is more than a maximum jump height above the bot's feet, and only once the bot is stuck or within 25 u of that goal. Below a lower ledge the bot therefore walks towards a goal on the floor above it, pressing into whatever is in the way, until the stuck monitor fires several seconds later.

ntre_transit_ctg shows this every round. The walkway beside the west track is 41 u wide with a 40 u drop to the track bed. Bots step off it three to four times a match, keep the path along the walkway, and some walk along the track bed into the V between the walkway and the parked pilot car's nose, where they stand until OnStuck.

The path follower now remembers whether the bot was on the ground. On the tick the bot lands, if

  • its current goal is an ordinary ground segment (not a planned drop, gap jump, climb or ladder),
  • it is not standing on an area of its path,
  • the closest point of the path is more than a step height above its feet, and
  • a nav area lies within 50 u of its feet,

the follower reports FAIL_FELL_OFF and invalidates the path, as the stock fell-off check does. The behaviors already re-path on that failure, now from where the bot actually is.

The last condition is the second commit. A bot that falls where the nav mesh does not reach keeps the area it fell from as its last known area, because UpdateLastKnownArea() finds no area within 50 u of its feet. A re-path from there rebuilds the path it just fell off, so without the condition the check fired again on every landing: on ntre_vtol_ctg a bot in the unmeshed trench under the walkways fired it up to 180 times a match. Off the mesh the bot now keeps its path and the stuck monitor handles it, as before this change.

Evidence

Upstream master (at #2168) with this change, neo#2176 (draft) and harness logging (a line each time the new check fires), and a test-only switch that turns the check off. 30 bots, default weapon damage. CTG: 2 rounds of 3 minutes with the ghost pinned at each ghost spawn in turn. Both arms of each pair run in the same 8-wide batch. Every match reached match end with 0 asserts. "Stuck" is OnStuck plus FAIL_STUCK move failures, without the round-start spawn crowd and the weapon-scavenging behavior.

ntre_transit_ctg, master navmesh, 55 pairs (three batches):

a match stock with this change
stuck 54.6 46.8 (x0.86 [0.75, 0.98], 32 pairs down / 23 up)
stuck at the pilot car 3.6 0.1
re-paths on landing - 4.5
FAIL_NO_PATH_EXISTS 5.8 6.3
kills 49.8 50.0
fall deaths 0 0.02 (1 in 55 matches)

FAIL_FELL_OFF failures go from 0.5 to 4.9 a match: the new check reports each re-path that way. Besides the pilot car, the side landings of the east ladder's top and the passage by the south glass pane lose stuck events too.

With #2176's behavior switched off (stock ladder code), 15 pairs: x0.73 [0.57, 0.92], 9 down / 5 up; pilot car 3.6 -> 0.1 a match.

On transit with its reworked navmesh (the companion NeotokyoRebuild/neoAssets#145), 20 pairs: x0.96 [0.61, 1.54], pilot car 4.5 -> 0.25 a match; the rework already removes most of the other stuck spots. Over every transit batch (master and five candidate meshes, 195 pairs): x0.83 [0.75, 0.91], 118 down / 69 up.

Other maps, master navmeshes (bullet: the navmesh of its open PR), 77 pairs: stuck x0.89 [0.76, 1.07], 48 down / 25 up; kills 57.9 -> 56.8 a match; fall deaths 0.23 -> 0.16.

map pairs stuck, with / stock re-paths a match
ntre_rogue_ctg 26 x0.80 [0.57, 1.13] 7.2
ntre_tarmac_ctg 6 x0.86 [0.60, 1.15] 2.8
ntre_terminal_jgr 6 x0.92 [0.63, 1.45] 3.0
ntre_saitama_ctg 23 x0.93 [0.71, 1.24] 3.4
ntre_oilstain_ctg 6 x0.96 [0.55, 1.72] 0.8
ntre_subsurface_ctg 6 x1.00 [0.68, 1.52] 2.0
ntre_bullet_tdm 4 x1.02 [0.76, 1.44] 3.8

On ntre_rogue_ctg player kills went from 43.8 to 40.6 a match (26 pairs, difference -3.2 [-5.9, -0.5]); round outcomes did not move (40 rounds an arm: 7 against 8 ghost captures, no timeouts), and kills by its turret stayed at 6.7-6.8 a match. The other maps show no kill change.

Off the nav mesh (second commit)

Upstream master (at #2181) with neo#2176, neo#2186, this PR and harness logging (a line each time the second commit turns a landing away), and a test-only switch for each commit. 30 bots, default weapon damage, 16 wide; for each pin the three arms run back to back. 102 triples on seven maps, 306 matches, every one to match end with 0 asserts.

a match stock first commit both commits
ntre_vtol_ctg FAIL_FELL_OFF (16 matches an arm) 1.8 28.7 5.1
ntre_vtol_ctg landings turned away - - 15.8 (246 of 252 in the trench, z below -500)
ntre_transit_ctg stuck at the pilot car (15 matches an arm) 4.2 0.73 0.20
ntre_transit_ctg landings turned away - - 0.07 (1 in 15 matches, not at the car)
all seven maps, stuck 22.2 18.4 18.4
all seven maps, FAIL_FELL_OFF 3.2 12.5 5.3
all seven maps, kills / fall deaths 61.4 / 0.09 60.7 / 0.16 60.9 / 0.13

Against the first commit alone, stuck is x0.90 [0.74, 1.09] (56 pairs down / 43 up); against stock, x0.78 [0.64, 0.96] (first commit alone x0.87 [0.71, 1.08]). On the other five maps (ntre_saitama_ctg, ntre_rogue_ctg, ntre_ghost_ctg, ntre_sentinel_ctg, ntre_bullet_tdm) the second commit turned away 0 to 0.4 landings a match. In a cross-map check of 29 maps (446 pairs; this PR, neo#2176 and neo#2186 together against stock), no map's stuck rose in a repeat batch.

Cost

One IsOnGround() call and a comparison per path update, to track the ground state. The path-area scan, the closest-point search and the nearby-area search run only on the tick a bot lands below its path.

Toolchain

  • Linux GCC Distro Native (Linux Mint 22.3, GCC 13.3.0)

Linked Issues

@sunzenshen
sunzenshen force-pushed the bot-repath-after-fall branch from a0f9ef7 to 6f0a02d Compare October 1, 2026 05:34
@sunzenshen
sunzenshen marked this pull request as ready for review October 1, 2026 05:34
@sunzenshen
sunzenshen requested a review from sunmachine October 1, 2026 05:35
@sunzenshen sunzenshen added the Bots Related to bot players label Oct 1, 2026
sunzenshen added a commit to sunzenshen/neo that referenced this pull request Oct 1, 2026
A bot that falls where the nav mesh does not reach, such as the
trench under ntre_vtol_ctg's walkways, keeps the area it fell from as
its last known area: UpdateLastKnownArea() finds no area within 50 u
of its feet. A re-path then starts from that area and rebuilds the
path the bot just fell off, so the landing check fired again on every
landing, up to 180 times a match for one bot.

The landing re-path now needs a nav area within the same 50 u of the
bot's feet. Off the mesh the bot keeps its path and the stuck monitor
handles it, as it did before the landing check.

@sunmachine sunmachine left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Good catch!

@sunmachine
sunmachine requested a review from a team October 3, 2026 17:48
@sunzenshen
sunzenshen merged commit a5e1eb0 into NeotokyoRebuild:master Oct 3, 2026
9 checks passed
@sunzenshen
sunzenshen removed the request for review from a team October 3, 2026 17:49
sunzenshen added a commit to sunzenshen/neo that referenced this pull request Oct 7, 2026
Upstream's re-path on landing (NeotokyoRebuild#2185) defines LANDING_NAV_AREA_RANGE
near the top of NextBotPathFollow.cpp with the same value, so the
research block's own definition no longer compiles.
sunzenshen added a commit to sunzenshen/neo that referenced this pull request Oct 8, 2026
Upstream's re-path on landing (NeotokyoRebuild#2185) defines LANDING_NAV_AREA_RANGE
near the top of NextBotPathFollow.cpp with the same value, so the
research block's own definition no longer compiles.
sunzenshen added a commit to sunzenshen/neo that referenced this pull request Oct 8, 2026
Upstream's re-path on landing (NeotokyoRebuild#2185) defines LANDING_NAV_AREA_RANGE
near the top of NextBotPathFollow.cpp with the same value, so the
research block's own definition no longer compiles.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bots Related to bot players

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants