This isn't about memorizing the whole engine. It's about understanding the three decisions your team makes and tuning them until they win matches. We take you from the template that already plays to your first win against a real opponent.
You don't need to write a team from scratch. The short path is this: start from something that already works and improve it methodically, measuring every change.
It already plays competitively: it passes, shoots to the corners and presses loose balls. It's your starting point, not a blank page.
Touch only the tactics, or only the player. One change at a time is the only way to know what helps and what hurts.
Pit it against several opponents over many seeds and watch win-rate and stats. That way a lucky match won't fool you.
Upload your team to the platform and take on leagues with an ELO ranking, or set up your own. The code speaks.
Your team decides at three levels. The key idea: the AI (if you use it) sets the plan at a slow pace, and a fast, deterministic layer runs it every moment. That way a model never has to decide 20 times per second. Customize only the layer you care about; reuse the rest.
Reads the score and the clock and sets the mentality: attack, balance or defend. Decides rarely, but sets the tone. CoachBrain.decide(ctx)
Positions the team on the pitch with four knobs: line height, width, pressing and flank. This is almost always where the match is won or lost. TeamStrategy.plan(ctx)
Decides every moment: move, pass, shoot, sprint. Fast and reactive, one per player. PlayerBrain.decide(view)
Want the detail of what each layer receives and returns? It's in the Participant guide.
You don't compute positions by hand. You pick four values and the engine turns them into where each player stands. You can fix them or make them change with the match (a reactive tactic).
How high up your team plays. Low = a safe, dropped-back block; high = you press up top but leave space behind.
How open the team is. Compact plugs the center; open works the flanks and stretches the opponent.
How hard you go for the ball. Careful: right now heavy pressing tires you out and doesn't always win it back (read the “meta” below).
Which side you funnel play through. Center by default; shift it to a flank to attack there or to find your striker's run.
A fixed tactic is a dictionary of knobs. A reactive one is a function that recomputes them by reading the match. Both are short.
# 1) FIXED tactic: a constant style
from aicup import TacticalStrategy
mi_estilo = TacticalStrategy("Mi estilo", {
"line_height": 0.35, # dropped back, safe
"width": 0.45, # compact through the center
"pressing": 0.30, # I hold off, I don't dive in
})
# 2) REACTIVE tactic: changes with the match
from aicup.tactics import progress, possession
def mandos(ctx):
defendiendo = possession(ctx) == "theirs" or progress(ctx) < 0.45
if defendiendo:
return {"line_height": 0.30, "pressing": 0.35} # I drop back
return {"line_height": 0.74, "pressing": 0.50} # on the steal, I break forward
mi_contra = TacticalStrategy("Mi contraataque", mandos)
Any knob you leave out uses its default value. The full gallery (tiki-taka, catenaccio, gegenpressing…) and how to write the player and the coach are in the tactics docs.
Tips that come from playing hundreds of matches. No magic: just the habits that separate a team that competes from one that just makes up the numbers.
A single match lies: luck counts. Use sparring with many seeds and decide by win-rate, not by gut feel.
Right now a compact, dropped-back block outperforms high pressing. Start solid at the back and build from there.
Sprinting and hard shots tire you out. Save sprints for the final stretch and press the opponent who's already spent.
In your player, read view.plan: it tells you where to position and whose turn it is to go for the ball. Don't improvise on your own.
Shooting down the middle hands the ball to the keeper. Aim for the posts and adjust the power: it's not all max force.
First the tactics (knobs), then the player (passes, shots, marking) and finally the coach (when to take risks).
Almost everyone trips up here at the start. Seeing them coming saves you half a dozen silly losses.
You expect to win the ball back and only wear yourself out. Fix: lower the pressing and press in bursts, not all the time.
A GK far from goal is goals gifted away. Fix: keep him close; see how the sample player handles it.
You push everyone up and get caught in behind. Fix: push midfielders and forwards higher than the defense, or drop the line.
You beat one and lose to everyone else. Fix: test against several opponents and several seeds before calling anything good.
Always full force = you run out of stamina and shoot worse late on. Fix: ration your kick_power.
The engine protects you, but a player that errors out stands still and you lose ticks. Fix: test locally and check the viewer.
An honest detail about today's engine: compact, defensive tactics perform better than high pressing. The reason is that, for now, pressing doesn't effectively “win” the ball —possession is sticky and taking it away means closing down with a big margin—. That's why catenaccio-style approaches tend to do very well and gegenpressing struggles.
The sample tactics are starting points, not optimal solutions. The engine will evolve (the roadmap includes pressing eventually winning the ball), so the meta will change too. Finding the combination that wins right now is your competitive edge.
Run through this quick checklist. If you tick everything, you can upload it and take on the rest.
Create your account and compete online in minutes, or clone it and work locally. In basic mode it works with no API and no setup.