I’ve had a lot more free time recently, so I started working on a passion project that’s been in the back of my head for a while now: solving draft in Brawl Stars.

Brawl Stars
Brawl Stars

Brawl Stars is a mobile game that I’ve been playing on and off since high school. I’m decent at it. Here are a few screenshots of me ranked 119th and 279th in the United States.

119th
119th
279th
279th

Draft in Brawl Stars is the character selection phase before a match where both teams will take turns picking brawlers in an attempt to get the upper hand over the other team. Ever since draft was added to the game in March 2021, draft has become increasingly important for winning in both pro and casual play.

It’s my dream to revolutionize the way top players draft in Brawl Stars by building a draft solver. The same way Stockfish revolutionized chess and PioSOLVER revolutionized poker.

Anatomy of a Brawl Stars draft

Draft in Brawl Stars happens in a few phases:

  1. coin flip
  2. bans
  3. picks

Coin Flip

Before the draft, a coin is flipped to decide which team has first pick and which team has last pick.

Bans

Then, both teams will simultaneously choose three brawlers to ban. The other team’s bans are not revealed to you until your team has finished banning, and vice versa. This is a bit like rock-paper-scissors (you don’t know if your opponent threw rock, paper, or scissors until you’ve thrown yourself).

Picks

Finally, teams will take turns picking brawlers in a snake order. That means:

  • team 1 picks a brawler (aka first pick)
  • team 2 picks two brawlers
  • team 1 picks two brawlers
  • team 2 picks a brawler (aka last pick)
Draft
Draft

What makes a solver good?

Solvers like Stockfish are extremely powerful and can crush humans players and other engines in a head to head game, but for it to be useful for a human to study with, it needs more than strength. From my experience using solvers to study both chess and poker, I’ve developed some opinions on what makes a solver useful.

  1. It needs to be correct (duh).
  2. It needs to be fast. No one likes using a slow tool.
  3. It needs to be accessible.
    • Why is GTOWizard so popular? One major reason is–unlike other poker solvers, it runs in the browser on all devices.
  4. It needs to be as complete as possible.
    • A solver that only solves part of the game tree is simply less useful.
    • In poker, an issue is that it’s infeasable to solve both preflop and postflop in a reasonable amount of time. Because of this, usually solvers only solve postflop, and preflop strategy is fixed to a precomputed optimal strategy. This makes it harder to study preflop exploit strategies with a solver.
  5. It needs to show how to punish bad moves.
    • It’s not enough for the solver to show optimal play. It’s also important that it shows how to punish weak play.
    • In chess, people often study by analyzing both their mistakes and their opponent’s mistakes and learning how to punish them. By doing this, they learn both how to capitalize on and to avoid previous mistakes.
  6. It needs to be able to tailor strategies for a specific opponent.
    • In chess, players often prepare by exploring databases of their opponents’ games and comparing them to solver outputs.
  7. It needs to be able to simplify complicated strategies.
    • Humans aren’t computers. Humans cannot brute memorize extremely complicated strategies. Instead, humans learn by developing intuition and understanding.
    • Solver strategies in poker are extremely complicated and generally impossible to memorize. One way people study poker with solvers is to input simplified strategies into the solver and testing how much the solver can punish it. If the punishment is small enough, then the simplified strategy can be used in real play.

Thus, for my Brawl Stars solver, I have the following goals:

  1. It needs to be as accurate as possible.
  2. The engine should be built using Rust (It needs to be fast).
  3. The Rust needs to be compiled to WASM (It needs to run in browser).
  4. It needs to solve both bans and picks (It needs to be as complete as possible).
  5. It needs to support node-locking (It needs to show how to punish bad moves.)
    • For example, if I know my opponent will always/never ban X brawler, I should be able to lock that strategy in the solver.
  6. It needs to be able to tailor strategies for a specific opponent.
    • Pro teams have data on what brawlers their opponents (and themselves!) are good at and like to play. My solver needs to be able to take this data into account.
  7. It needs to be able to simplify complicated strategies.
    • There are more than a hundred brawlers. A good UI and visualization strategies are critical to a solver that’s useful for study.

My strategy

Here is my high level plan for building this solver:

  1. Gather a dataset by collecting data from Brawl Stars’ API about which brawlers were picked and who won.
  2. Train an evaluation function on the dataset. Essentially, f(map, team1comp, team2comp) -> win_probability.
    • Some model architectures to try: XGBoost, NNUE, Embedding-based NN.
  3. Solve picks by implementing minimax by using the eval function to evaluate leaf nodes.
  4. Solve bans by implementing Counterfactual Regret Minimization (CFR) by using minimax to evaluate leaf nodes.
    • The runtime complexity of this almost definitely will explode. Some strategies to make it feasable:
      1. Do Monte-Carlo CFR.
      2. Train a heuristic model on partial draft states, so that we don’t need to fully run minimax every time.
  5. Build a UI.
  6. Productionalize the solver so people can use it. Also, open source everything.

Desired features:

  • Enable “fine tuning” of the eval function. For v1, we can allow the user to define rules such as “if X brawler is drafted, nerf/buff their win prob by P%”, or “if red has X and blue has Y, then…”, or “if a team has XY combo, then…” which extend the eval function.
  • Show threat: Highlight top brawlers if current pick is skipped.
  • Node-locking of bans
  • Database explorer of pro games
  • LLM explanations (I have doubts about how useful this is, and it’s likely more expensive than it’s worth, but this could be fun to try.)

My progress

I have a working eval function and I have implemented minimax, but they both could be improved a lot. So I’m somewhere around step 3. Originally, this post was going to be a progress update, but introducing the project already took quite a lot of words, so I will log my progress in another followup post.