Split The code is public; the app answers only to the crew.

A bot with an empty primary slot walks over the rifle on the floor, when it is on its way #216

shipped merged opened this has it
opened this

Make a bot on an eco round divert to a dropped primary that is near its path, so a lost pistol round stops looking like five people walking past free guns.

This is the second half of #169, which was parked twice on the timeout: the arithmetic is split out into the issue this waits on, and what is left here is the wiring, one headless test and a measured table small enough to run inside one run.

What is there today: bots.ts never reads world.pickups - grep it and the only thing on the floor a bot ever walks to is the dropped bomb (bots.ts:308). updatePickups (src/client/world.ts:1010) already gives any player a gun they come within PICKUP_RANGE = 48 of with a free slot, so this is not a take action, it is one goal: put the bot's feet near the gun and the rules do the rest. chooseGoal (bots.ts:294) is the one place a goal is decided, and repath (bots.ts:503) only re-runs A* when the objective string changes or the path goes stale, a few times a round.

Done looks like

  • [ ] A bot in a live round with primary === null whose path passes near a dropped primary goes to it, takes it (via the existing pickup rule, no new take path), and carries on with the goal it was on. The detour bound is the predicate from the issue this waits on - no second opinion about distances in bots.ts.
  • [ ] A bot that already holds a primary does not divert. The bomb carrier does not drop the bomb plan for a gun, and a planted bomb outranks any gun for either side, exactly as chooseGoal already orders things.
  • [ ] The gun is part of the objective string in repath, so a rifle appearing mid-round turns a bot round and a rifle someone else took stops being a goal. A* does not start running every tick: say in the pull how many paths a measured match asks for, before and after.
  • [ ] Costs nothing when the floor is empty: world.pickups.length === 0 is the first thing checked, before any distance is computed. src/rl/arena.ts steps this millions of times a second with an empty floor.
  • [ ] Tests in src/client/bots.test.ts, headless: a bot with no primary and a rifle a few steps off its path is holding that rifle within a few seconds of stepped world time; the same bot already holding a rifle never touches it; a rifle across the map is not crossed for; an empty pickups list leaves every goal byte-for-byte what it was.
  • [ ] bun run scripts/measure.ts --matches 8 --seed 41 on de_forge only, before and after, both tables quoted in the pull: plant rate, side split and how rounds end. That is about two minutes a side - do not run 30 matches or both maps, which is what timed this out twice. A detour that costs the five-stack its arrival together is not worth the rifle; if the plant rate moves more than a few points, tighten the bound rather than keep the behaviour.
  • [ ] One sentence in README's The bots saying a bot now picks a gun up off the floor, and what it will not cross the map for.
  • [ ] bun run check green. No new dependency.

Files I expect to change

  • src/client/bots.ts, src/client/bots.test.ts, README.md.

Risks

  • Rolling one site a side is what took the plant rate from 38% to 65%; a bot that wanders off for a gun is how that gets undone, which is why the short measured table is an acceptance criterion and not a nicety.
  • bots.ts has #46, #58, #187 and #194 queued against it. Keep this narrow: one goal branch and one objective-string term, nothing about what the bot does with the gun once it has it.
  • Time budget is part of the task: if the headless test needs a whole match to show the pickup, the test is too big - seed a world, put a rifle down, step seconds, assert.

Crew

vesper - bot behaviour and the measured table behind it.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs