Bracket cut table
How many fighters get eliminated each round depends on the bracket size M at the start of that round — and M shrinks after each cut. The battle hits _finalize the moment M ≤ 1 or round 4 completes, whichever comes first — so smaller brackets finish in fewer than 4 rounds.
Defined in BattleOrchestrator._cutSizeForRound(round, M) and finalize gate runRound line if (round == TOTAL_ROUNDS || b.active.length <= 1) _finalize(...).
Progression per starting bracket
Each cell is the cut applied during that round. 🏆 marks the round in which the battle finalizes (only one fighter left). Dashes (—) are rounds that never run.
| Starting M | R1 | R2 | R3 | R4 | Total rounds |
|---|---|---|---|---|---|
| 2 | 0 (skip) | 1 → 🏆 | — | — | 2 |
| 3 | 1 | 1 → 🏆 | — | — | 2 |
| 4 | 1 | 1 | 1 → 🏆 | — | 3 |
| 5 | 1 | 1 | 1 | 1 → 🏆 | 4 |
| 6 | 1 | 2 | 1 | 1 → 🏆 | 4 |
| 7 | 2 | 2 | 1 | 1 → 🏆 | 4 |
| 8 | 1 | 2 | 3 | 1 → 🏆 | 4 |
| 9 | 2 | 2 | 3 | 1 → 🏆 | 4 |
| 10 | 2 | 3 | 3 | 1 → 🏆 | 4 |
Notes
- M=2 special: round 1’s cut is 0 — the round still has a trade phase, but no eliminations happen. The
afterSwaphook auto-advances past zero-cut rounds vianextRoundIsSafeToAutoAdvance, so trades inside R1 keep flowing; the keeper bot only needs to fire at the actual cut. R2 then cuts the loser → finalize. - Brackets of 2 and 3 finish in 2 rounds; bracket of 4 in 3 rounds; everything ≥5 plays the full 4 rounds.
- R4 always cuts
M − 1(whatever’s left → 1 winner). That’s why all paths converge toM=2going into R4. - For M=7 and ≥9, R1 cuts 2 — lookup checks
M >= 9first thenM == 7, so M=10 (≥9) and M=7 both yield 2; M=8 falls through to the genericM >= 3→ 1. - After each cut, M decreases — subsequent rounds re-evaluate against the new bracket. The table above already does that walk for you.
Example: 6-fighter bracket
Start: [A B C D E F] M=6
After R1: [B C D E F] M=5 (cut 1)
After R2: [C D E] M=3 (cut 2)
After R3: [D E] M=2 (cut 1)
After R4: [E] M=1 (cut M−1 = 1 → winner)Example: 2-fighter bracket
Start: [A B] M=2
After R1: [A B] M=2 (cut 0 → no elimination, trade phase only)
After R2: [B] M=1 (cut 1 → winner, FINALIZE)No R3 or R4 runs — runRound finalizes the battle the instant b.active.length <= 1.
Lookup function reference
For contract devs: the raw _cutSizeForRound(round, M) lookup (without progression context):
| round \ M | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | 0 | 1 | 1 | 1 | 1 | 2 | 1 | 2 | 2 |
| 2 | 1 | 1 | 1 | 2 | 2 | 2 | 3 | 3 | 3 |
| 3 | 1 | 1 | 1 | 3 | 3 | 3 | 3 | 3 | 3 |
| 4 | M − 1 for all M ≥ 2 |
This is what the function returns for arbitrary (round, M) inputs — but most of these cells are unreachable during a real battle, because the bracket already collapsed to 1 before that (round, M) pair occurs. The progression table above shows only the cells actually visited.