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

A bot with an AWP fires it from the hip: no bot ever scopes, so the most accurate gun in the game sprays a 7.7° cone #194

shipped merged opened this has it
opened this

input.scope is never set anywhere in bots.ts, so a bot holding the AWP never zooms it and shoots the one gun that needs stillness while strafing at full carry speed.

botBuy (bots.ts:135) hands an AWP to any rich bot on a 15% roll, and #169 will let a bot pick a dropped one off the floor as well. scriptedFight (bots.ts:440-444) then holds input.side = ±1 for the whole duel and only sets input.walk past 1200 units, so the shot goes out at 200 u/s unscoped. Through inaccuracy, measured against the shipped numbers:

how it shootsinaccuracycone at 1000 units
hip, strafing at 200 u/s (today)7.73°136 u
scoped, walking at 130 u/s (p.scoped already forces walk)0.49°9 u
scoped, standing still0.007°0 u

A player hitbox is 32 units wide. So an AWP bot today is firing a cone four bodies wide and its $4750 is a handicap, while the same bot scoped is the thing an AWP is supposed to be. The world side already works for anyone: applyInput (world.ts:1234) honours input.scope for any player holding a weapon with zoom, gates it on nextShotAt, and shoot reads p.scoped through inaccuracy.

Done looks like

  • [ ] A bot holding a weapon with a zoom scopes to fight: input.scope true when it has a target it can see beyond a stated range, false when the target is close enough that zoom is a liability, with the range written down as a named constant and not a literal.
  • [ ] A scoped bot stops dancing: input.side is not held at full strafe while p.scoped, so the shot is taken from something near a stop rather than from a full-speed slide.
  • [ ] Unscoping is not free of the rule that already exists — the bot does not fight the nextShotAt - 0.05 gate in applyInput by toggling scope every tick; whatever it asks for is stable for at least one shot.
  • [ ] The difficulty ladder still means something: an easy bot is not handed sniper discipline a hard bot has. Tie it to brain.skill the way input.duck at bots.ts:444 already is.
  • [ ] Tests in bots.test.ts: a bot given an AWP and a visible enemy at long range asks for scope; the same bot with the enemy at knife range does not; a scoped bot's input.side is bounded; and the inaccuracy of the shot it actually takes is below a stated ceiling (the test that fails today).
  • [ ] bun run scripts/duel.ts and/or scripts/measure.ts run before and after, both numbers in the pull: teaching the snipers to scope should move the round split, and if it moves it past the ±2 points #154 cares about, say so there.
  • [ ] README's bot section says a sniper bot scopes, and at what range.

Files

src/client/bots.ts, src/client/bots.test.ts, README.md. No change to world.ts should be needed; if one is, say why in the pull.

Risks

  • bots.ts is #169's file and #187's, so this waits on #169 to keep the diffs apart.
  • The policy path (think/observe.ts) has no scope action in its action space; this is scriptedFight's business and must not change what the learned policy sees, or the shipped weights stop meaning what they were trained on.
  • Scoping forces walk speed, so a bot that scopes too eagerly becomes a slow target — the range constant is the whole design, and the arena is how you defend the number you pick.

Suggested: vesper.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs