Shoot While You Are Moving
A robot that stops to shoot wastes the match. Stopping costs a second to slow down, a second to aim and a second to get going again. Do that ten times and you have given away half the match.
So shoot while you drive. This is one of the hardest things a good team does, and the reason is not the mechanism. It is the maths.
The game piece keeps your speed
Throw a ball from a moving truck and it does not go where you threw it. It goes where you threw it plus where the truck was going. A game piece leaving a robot at 6 m/s, from a robot driving at 3 m/s, travels at 9 m/s over the ground.
A shot can be in the air for over a second. A robot at 4 m/s covers four metres in that time. So the correction is not small. It is bigger than the goal.
Aim where the goal will be
The trick is to aim at a different place than the goal. Pick the point that puts the goal under the game piece when it comes down. That point is the goal, moved back by however far the robot travels while the piece is in the air:
aim_point = goal - robot_velocity * flight_time
Now read that line again and find the problem.
The answer depends on itself
flight_time comes from the shot table, and you look up the shot table by
distance. Which distance? The distance to the aim point. Which you do not
have yet, because you need the flight time to work it out.
This is a fixed point: a value that appears on both sides of its own equation. You cannot rearrange your way out of it. What you do instead is guess, work out the answer, and use that answer as the next guess:
- Guess: the distance to the real goal.
- Look up the flight time for that distance.
- Work out the aim point, and its distance.
- That distance is a better guess. Go back to step 2.
Each round is closer than the last. Stop when the number stops moving.
The task
A robot that stops to shoot wastes the whole match. Good teams shoot while they drive. That is much harder than it sounds.
A game piece leaving a moving robot keeps the speed of the robot. Throw it forwards at 6 m/s from a robot doing 3 m/s, and it travels at 9 m/s. Drive sideways and it goes sideways too.
So do not aim at the goal. Aim at the place that puts the goal under the game piece when it lands.
Write aim(px, py, vx, vy). Return two things:
- the heading to point the shooter, in radians
- the distance to look up in the shot table
flight_time(distance) tells you how long a shot of that distance is in the
air. shot(distance) gives you the speed and the time together. The table
covers 2 m to 14 m.
The game piece must land within 0.20 m of the goal in all nine cases. The robot moves at up to 4 m/s, and a shot can be in the air for over a second, so the robot travels several metres while the game piece flies.
Here is the part that makes this hard. To know where to aim, you need the flight time. To know the flight time, you need the distance. To know the distance, you need to know where to aim. The answer depends on itself.
The code operates in your browser. The page sends nothing to a server and saves your work on this computer. Press Ctrl+Enter to run it.
Why the obvious answers fail
tools/validate-shoot.py measures every one of these against the nine cases:
| Answer | Worst miss | Cases scored |
|---|---|---|
| Aim straight at the goal | 4.69 m | 1 of 9 |
| Correct once | 1.40 m | 2 of 9 |
| Correct twice | 0.37 m | 6 of 9 |
| Correct three times | 0.10 m | 9 of 9 |
| Correct four times | 0.03 m | 9 of 9 |
One correction is not a small error. It is 1.4 m, a miss by a whole robot. The first correction uses the flight time for the wrong distance. At these speeds the wrong distance is metres out.
Do not write “correct three times” in your code. Write “correct until it stops changing”, and stop after a fixed number of rounds whatever happens. A robot that waits for a number that never settles has stopped being a robot.
This is real.
shot_calc.pyon the 2026 robot solves the same problem with a numerical optimiser and drag and Magnus effect, and writes the answers into a lookup table.lookup_table.pyreturns a time of flight for exactly this reason.