fix(bots): roll between the nearest spots so a fleet stops sharing one #246

Merged
sickday merged 2 commits from fix/fisher-spot-spread into main 2026-08-19 11:20:54 +00:00
Owner

The spot scan ended in Enum.min_by/3 on distance, which is a clone factory:
every fisher at the same water has the same scan, the same candidates and the
same answer, and min_by is first-wins on ties against a stable
MovementAuthority.nearby/3 order, so a tie cannot break the symmetry either.

Measured before touching it. Three fishers at Barbarian Village, sampled every
six seconds over twenty minutes: 47% of the ticks on which all three were
fishing had all three on one tile, 51% on two, and one tick in 161 on
three. Two of them held identical target indices for hundreds of ticks at a
stretch -- 132 both on 17905, 110 both on 17785, 107 both on 18180.

So take the nearest three workable spots and roll, which is the roll
Bot.Sites.choose/2 already makes between grounds and the spread
Bot.Sites.spot/2 already gives a fleet around a booth. The spreading was
written twice; this was the third place that needed it. Re-rolled on every
acquire rather than fixed per body, so a fleet keeps redistributing as spots
relocate under it.

Re-measured the same way: 22% of ticks on one tile, 75% on two. That is
the ceiling rather than a half-fix -- the water there carries exactly two
live spots inside the scan radius, on adjacent tiles, and three bots rolling
uniformly over two spots land on the same one 25% of the time by construction.
The observed 22% is that number. A cluster with one spot in it still shares,
which is what the game looks like anyway.

The test asserts the distribution rather than reading variety off the dice: it
seeds four spots, rolls sixty acquires, and requires both that more than one
index comes back and that the fourth -- the one outside the pool -- never
does. Checked against the old behaviour before keeping it, where it fails with
"every scan chose [32701], which is the argmin this roll replaced".

The spot scan ended in `Enum.min_by/3` on distance, which is a clone factory: every fisher at the same water has the same scan, the same candidates and the same answer, and `min_by` is first-wins on ties against a stable `MovementAuthority.nearby/3` order, so a tie cannot break the symmetry either. Measured before touching it. Three fishers at Barbarian Village, sampled every six seconds over twenty minutes: **47%** of the ticks on which all three were fishing had all three on **one tile**, 51% on two, and one tick in 161 on three. Two of them held identical target indices for hundreds of ticks at a stretch -- 132 both on 17905, 110 both on 17785, 107 both on 18180. So take the nearest three workable spots and roll, which is the roll `Bot.Sites.choose/2` already makes between grounds and the spread `Bot.Sites.spot/2` already gives a fleet around a booth. The spreading was written twice; this was the third place that needed it. Re-rolled on every acquire rather than fixed per body, so a fleet keeps redistributing as spots relocate under it. Re-measured the same way: **22%** of ticks on one tile, 75% on two. That is the ceiling rather than a half-fix -- the water there carries exactly **two** live spots inside the scan radius, on adjacent tiles, and three bots rolling uniformly over two spots land on the same one 25% of the time by construction. The observed 22% is that number. A cluster with one spot in it still shares, which is what the game looks like anyway. The test asserts the distribution rather than reading variety off the dice: it seeds four spots, rolls sixty acquires, and requires both that more than one index comes back and that the fourth -- the one outside the pool -- never does. Checked against the old behaviour before keeping it, where it fails with "every scan chose [32701], which is the argmin this roll replaced".
fix(bots): roll between the nearest spots so a fleet stops sharing one
All checks were successful
ci / gates (pull_request) Successful in 3m26s
73aa6cdbd9
The spot scan ended in `Enum.min_by/3` on distance, which is a clone factory:
every fisher at the same water has the same scan, the same candidates and the
same answer, and `min_by` is first-wins on ties against a stable
`MovementAuthority.nearby/3` order, so a tie cannot break the symmetry either.

Measured before touching it. Three fishers at Barbarian Village, sampled every
six seconds over twenty minutes: **47%** of the ticks on which all three were
fishing had all three on **one tile**, 51% on two, and one tick in 161 on
three. Two of them held identical target indices for hundreds of ticks at a
stretch -- 132 both on 17905, 110 both on 17785, 107 both on 18180.

So take the nearest three workable spots and roll, which is the roll
`Bot.Sites.choose/2` already makes between grounds and the spread
`Bot.Sites.spot/2` already gives a fleet around a booth. The spreading was
written twice; this was the third place that needed it. Re-rolled on every
acquire rather than fixed per body, so a fleet keeps redistributing as spots
relocate under it.

Re-measured the same way: **22%** of ticks on one tile, 75% on two. That is
the ceiling rather than a half-fix -- the water there carries exactly **two**
live spots inside the scan radius, on adjacent tiles, and three bots rolling
uniformly over two spots land on the same one 25% of the time by construction.
The observed 22% is that number. A cluster with one spot in it still shares,
which is what the game looks like anyway.

The test asserts the distribution rather than reading variety off the dice: it
seeds four spots, rolls sixty acquires, and requires both that more than one
index comes back and that the fourth -- the one outside the pool -- never
does. Checked against the old behaviour before keeping it, where it fails with
"every scan chose [32701], which is the argmin this roll replaced".
Merge branch 'main' into fix/fisher-spot-spread
All checks were successful
build / image (push) Successful in 38s
ci / gates (pull_request) Successful in 3m53s
ci / gates (push) Successful in 3m42s
240105fe6a
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Revenant/Server!246
No description provided.