Repository navigation
ntre_dusk_ctg: navmesh rework - #150
Merged
sunzenshen merged 6 commits intoOct 14, 2026
Merged
Conversation
One file. Against master: 1358 -> 1123 areas, 1,168,376 -> 813,513 bytes; areas the engine blocks at every round start 28 -> 2; areas no spawn can reach 58 -> 19. - Sliver areas merged into their neighbors on the same floor, and areas the engine blocks at round start (a prop or brush over their center) cut away. - Walk links a player hull cannot cross are cut: the drop from the walkway to the garden through the garden wall's west end (603 -> 601 near (240,4640)) and the jumps from the walkway onto the wall's 8 u cap (master's largest stuck spot), past the feet of the rabbitfrog vehicle near (2050,3900), between bamboo stalks near (1935,3525) and (450,1540), and through the bamboo row near (1650,4160), which is now crossed at its east end with the areas beside it a half hull off the stalks. - Ladder 1, the ivy wall at (375,4617): its top lands on the wall cap, which drops to the walkway north of the wall; its bottom is on the garden floor between the two benches. A climb route; the cap cannot be reached from the walkway. - A 13 x 12 u sliver with a link in and none out gets a return link; a box top and an isolated area nothing reaches are removed. - Re-analyzed in game after the edits.
Renumbers area and ladder ids only, so an id-keyed diff against master reads sensibly: 1117 of the 1123 areas and all 4 ladders carry the id of the master area they match. Areas are matched only within 64 u of height. Geometry, connections, attributes and the analyzed visibility data are unchanged (verified topology-identical).
An outside review of this mesh found walk links that run one way only, and a wall-cap strip reached only by a 92 u climb no class makes, whose drop back had been cut. - One-way links, each swept with a player hull in both directions by the engine's hull audit: cut both ways the seven pairs blocked both ways (the rabbitfrog vehicle, bamboo stalks, a work light); restore the missing direction of the six pairs clear both ways. - Delete 694, the area under the rabbitfrog vehicle near (2050, 3900): the vehicle blocks 287 of its 325 hull stand samples, its only way out ran into the vehicle, and bots that walked in got stuck there. 698 <-> 4152 joins its neighbors round it. - Delete 4382, the wall cap at (30, 4562), and its 92 u climb from 3998: nothing else reaches it. - Remove 760 -> 1386 (70 u, over every class's limit) onto the APC at (-2320, 2860); 1386 stays as a drop-only pocket. Existing areas keep their ids. Re-analyzed in game (same graph, fresh visibility).
The engine's hull audit (a player hull stood on every area and swept across every link, in the server) of the previous revision, and navconnect's link check against master: - Restore the drop back of six climbs of 19-38 u whose drop had been cut: the climb reads clear on some or all lanes. - Delete areas no player hull stands in: squares inside bamboo clumps, a street lamp, a temple lantern, a wooden wall, a desk and wall corners, a work light, and 4143 beside the rabbitfrog vehicle near (1975, 3910), 224 of whose 247 stand samples the vehicle blocks: bots walked from it into the gap under the vehicle and wedged there. - Cut three pairs blocked both ways that bots never cross (bamboo). Kept: links bots cross though the audit reads them blocked (the work truck, a bamboo row, a displacement slope, the work light); the office chairs and the breakable glass, left as at map load. Existing areas keep their ids. Re-analyzed in game (same graph, fresh visibility).
The pocket under the ledge near (250, 1830) beside a bamboo clump (a static prop) had two drops into it from 156. Over the one into 2518 a stalk overhangs the space a player falls through, so the bots' path code found no clear column and put the landing 70 u past the ledge, beyond the clump: bots dropped, landed against the stalks and pushed on toward it. Nearly every stuck episode at the pocket started there. Cut that drop and its climb back; the engine's hull test reads both blocked on every lane, and no bot made either as planned. The pocket is still reached by the drop into 2506. Also move the pocket's way out (2506 -> 2518 -> 211) 9 u north, onto the lane a player hull fits between the ledge wall and the stalks: the path crossed from 2506 to 2518 at a point no hull can stand on. 2506 keeps its south part, where bots landing from the drop end up. 2518 now meets 211 on its south edge, so that link faces south. No area deleted, ids unchanged. Re-analyzed in game (same graph, fresh visibility).
This was referenced Oct 5, 2026
116 -> 1165 was a walk link down a ~27 u displacement step whose foot is a crease with the hillside; a bot spawned on 116 walked off at 1165's west edge and wedged there with no ground under it. Cut it one way: 116 still reaches 1165 through 4380 and 4159, and 1165 -> 116 stays. Pinned twin runs at that spawn, wedge escape off, 18 an arm: wedges 2 -> 0.
sunmachine
approved these changes
Oct 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ntre_dusk_ctg: navmesh rework
One file,
neo/maps/nav/ntre_dusk_ctg.nav. It was measured on upstream master plus the draft NeotokyoRebuild/neo#2176 (then only its unwanted-ladder release, now its changes 1 and 7) and NeotokyoRebuild/neo#2186 ("Bots skip weapons they cannot reach", merged since), with harness logging added; the final file was measured again on the harness's research build of the bot code (those PRs plus the other open bot code PRs, among them NeotokyoRebuild/neo#2197).ntre_dawn_ctghas the same layout and gets the same mesh in its own PR (#151).Dependencies and status
Needs (worse than master, or broken, without it):
Helped by (measured better with it; the mesh does not wait on it):
ntre_dawn_ctg, its dismount change cut ladder 4 climbs kicked backwards off the top from 71 of 627 to 4 of 604 (see "Known, not changed").Pending before review:
At a glance
Six commits:
1. What changed
2. Id alignment
1117 of the 1123 areas carry the id of the master area they match, including the wall cap at ladder 1's top (4424). All four ladders keep their ids. Areas are matched only within 64 u of height. Geometry, connections, attributes and the analysis data are unchanged by this step (verified topology-identical).
3. Review fixes
Ladder 1
Ladder 1 is the ivy wall on the garden's north side, (262..489, 4611..4623), from the garden floor (z -251) to the wall's 8 u wide cap (z -160); the walkway north of the wall is 45-50 u below the cap. On master the nav ladder covered only the top 42 % of the climb, and its top joined the cap both ways to the walkway. On the branch this mesh came from, the cap had no walk links at all, so the ladder led nowhere.
Bots climbed it 19 times in 20 matches (dawn: 16 in 20); of the 57 climbs on both maps and both versions, 52 reached the walkway within 8 s. No stuck event on any area around the wall or the ladder.
How it was tested
Reachability:
BLOCKED_LINKS map=ntre_dusk_ctg level_pairs=1843 oneway=0 keep=0 cut=1 area=2 check=2 entity=4)Falls. The map has no
trigger_hurtand no other hurt volume, and no drop that kills a bot at full health (the deepest drop link is 233 u, 2 damage). No fall marks were needed.Master against the final file, 1 round. The same twin setup and stuck count as below, on the harness's research build of the bot code: CTG, 1 round with the ghost pinned at each of the 5 ghost spawns, 4 runs each, 30 bots, default weapon damage, the game's default 15 s freeze time, 8 matches at a time, the arms interleaved. Rates a match are about half those of the 2-round runs below. All 40 matches reached match end with 0 asserts and no crash.
FAIL_NO_PATH_EXISTSmove failures 0.60 -> 0.80 a match (x1.07 [0.76, 1.56]); "fell off the path" failures 0.80 -> 1.10 (x1.20 [0.83, 1.68])FAIL_NO_PATH_EXISTSmove failures in 20 matches -> 0; at the 116 step no event of any kind on either mesh (bots stood on 1165 in 7 of 20 matches, master 12, and on 116 in all 20)Master against this mesh before the 116 step cut, 2 rounds, same bot code. Byte-identical copies of the map, one carrying each
.nav, run back to back. CTG, 2 rounds of 3 minutes with the ghost pinned at each of the 5 ghost spawns in turn, 4 runs each, 30 bots, default weapon damage, 8 matches at a time. Every match reached match end with 0 asserts and no crash (368 matches on dusk and dawn in all, probes and the other revisions included). The stuck count isOnStuckplusFAIL_STUCKmove failures, excluding the spawn crush at round start and the weapon-scavenging behavior.FAIL_NO_PATH_EXISTSmove failures 3.9 -> 5.2 a match, paired x1.26 [0.90, 1.78] (without #2176 7.9 -> 4.3); "fell off the path" failures 0.6 -> 0.5The review fixes (section 3) against the previous revision of this PR, one comparison. The same twin setup with the previous and the fixed
.nav, the ghost pinned at each of the 5 ghost spawns, 10 matches each, 30 bots, default weapon damage, 8 matches at a time, on the same bot code as above:ntre_dawn_ctg, 326 -> 4: bots trapped under the vehicle in 3 of 50 matches, up to 156 stuck events in one). Those traps came from the test harness's 2 s freeze time: the bots walked under the vehicle while it was still landing (see "Known, not changed")FAIL_NO_PATH_EXISTSmove failures 6.1 -> 6.2 a match; "fell off the path" 0.5 -> 0.6; kills 48.4 -> 48.7 a match; ghost captures 8 -> 8 of 100 rounds; 94 / 93 % of kills between different nav areas and 82 % between non-adjacent onesCommit 4 against commit 3, one comparison. The same twin setup, the ghost pinned at each of the 5 ghost spawns, 5 matches each, 30 bots, default weapon damage, 8 matches at a time, on the same bot code:
FAIL_NO_PATH_EXISTSmove failures 6.0 -> 4.3 a match; "fell off the path" 0.9 -> 0.5; kills 48.4 -> 48.7 a match; ghost captures 2 -> 5 of 50 rounds; 94 / 95 % of kills between different nav areas and 81 / 82 % between non-adjacent ones; deaths to the world 2 -> 1, all in the office chairs' corridor (no drop there)Commit 5 against commit 4, two comparisons pooled. The same twin setup, the ghost pinned at each of the 5 ghost spawns, 20 matches each, 30 bots, default weapon damage, the game's default 15 s freeze time, 8 matches at a time, on the harness's research build of the bot code (upstream master plus the bot code PRs, among them #2176, #2197 and #2186 (merged since)):
ntre_dawn_ctg8 -> 0 in 50)FAIL_NO_PATH_EXISTSmove failures 1.5 -> 1.2 a match; "fell off the path" 3.0 -> 2.9; kills 48.3 -> 49.3 a match; ghost captures 21 -> 19 of 200 rounds; no fall deaths, no asserts, no crashes in 200 matchesntre_dawn_ctg, at the old crossing into 2518The carve at the rabbitfrog vehicle, at the game's default freeze time (15 s), one comparison. Commit 4 against the same mesh with 694, 4143 and the three pairs through the vehicle put back (two-way), the same twin setup, the ghost pinned at each of the 5 ghost spawns, 5 matches each, 30 bots, default weapon damage, 8 matches at a time (beside another 8-wide batch on the same machine), on the same bot code. No bot was trapped under the vehicle on either mesh; the floor put back costs:
ntre_dawn_ctg0 -> 137), bots pressing its parked feet; the longest episode 12 eventsntre_dawn_ctgx1.29 [0.93, 1.83])FAIL_NO_PATH_EXISTSmove failures 4.8 -> 6.6 a match; kills 47.7 -> 49.0; ghost captures 4 -> 4 of 50 rounds; no asserts, no crashes in 50 matchesHow the pinned-ghost probes work
The offline checks show that the mesh links an area to a spawn. They do not show that a bot will walk there. To test one spot in game, the ghost is placed on it and bots are sent to get it.
sv_neo_ghost_spawn_pos "x y z", which replaces the position of the round's ghost spawn. The map file is not edited..bspunder a second name that loads its own.nav, so the same pin runs on both meshes in one batch.On this map
Both ends of all four ladders were probed (ladder 4's top at both landings), 3 matches each, 12 bots, at a tenth of weapon damage, on the same build. Every probe was reached in 3 of 3 matches on both meshes (first pickup at 10-41 s; ladder 3's top, which bots almost never use, at 101-176 s on both). A ghost pinned on ladder 1's 8 u cap rolls off into the garden, so ladder 1 was checked through the climbs in the comparison above instead.
Known, not changed
prop_dynamichelicopter (rabbitfrog_dynamic.mdl) whose collision moves with its animation. It is re-created at every round start, lands within 10 s, and stays parked until the ghost is captured, when it takes off. With the default 15 s freeze time it has landed before anyone moves, so during play it is a fixed obstacle, and the mesh is carved round its parked footprint (commits 1, 3 and 4; the comparison above). With a freeze time under 10 s, as in the test harness, bots can walk under it while it is landing and stay trapped there until the round ends. That landing phase is left to runtime prop avoidance in bot code.prop_physics_multiplayer) start in the 100 u corridor near (-725,1275), and bots climb onto them or push them along. Stuck events there 5.9 -> 3.4 a match, bot episodes a round 0.27 -> 0.40; without #2176 5.4 -> 3.1 and 0.17 -> 0.37. The chairs move, so the mesh is not cut around them; that is runtime prop avoidance in bot code. Stuck events on physics props across the whole map: 3.65 -> 1.15 a match.ntre_dawn_ctg, climbs kicked backwards off the top went 71 of 627 -> 4 of 604 and stuck events at ladder 4's top 94 -> 30.