Every landing in VIPER 11 ends with a number. Roll to a stop on the runway and the LANDED card comes up with a score out of a hundred under it, and a line for each thing that went into it. Takeoffs and taxiing get one too. The numbers had to be fair enough to argue about, the same for every player on the same day, and hard to fake, with no server watching the flight. This note is about how each of those works, and where each one stops.
What a good landing is
Instructors grade a landing on a handful of things, and the game uses the same handful: how hard the wheels met the runway, and where; the centreline, the wings, the angle of attack down final; and whether it stopped on the runway rather than in the dirt past the end. Each is a single raw measurement, turned into points by one small function. Full points up to a value the card calls ideal, none from a value where it stops counting, a straight line between:
band(v, full, zero) = 1 at or better than full, 0 at or worse than zero, linear betweenpoints = max × band(v, full, zero), to one decimal
For a landing the six items add up to a hundred:
- Sink rate, 35 points. How fast the jet was descending when the main wheels touched. Full points under 200 feet a minute, none from 800. Past 900 the gear gives way, and that’s a crash, not a score.
- Aiming point, 15. How far past the threshold the wheels touched, against the 1,000 ft markers. Full points within 250 ft of them either way, none 1,500 ft off. Touching down before the runway starts is zero.
- Centreline, 15. How far the main gear was from the painted centreline at the touch. Within 5 ft is full, 40 ft is nothing.
- On-speed AoA, 15. The F-16 is flown down final at an angle of attack, 13°, not a speed. The game averages the angle from 1.5 nm out to 50 ft, gear down, and scores the difference: within 1° is full, 4° off is nothing.
- Wings level, 10. Within 2° of bank at the touch, nothing past 10°.
- Stopped on the runway, 10. Yes or no: stopped with the main wheels still on the runway, never having left it. A jet still rolling 45 seconds after it landed doesn’t count.
Figure 1 · Score a landing
src/score/formulas.ts, loaded on this page as it is) scoring a landing at Nellis in the F-16. The strip at the top is the first 4,000 ft of the runway seen from above: drag on it to put the wheels down somewhere else. The gold band is where the aiming point earns full points. It starts on the landing in the loop at the top of the page, which floated a little long.The landing in the loop at the top of this page scored 94. It touched down at 113 feet a minute, on the centreline, wings level, on speed, and stopped. It lost six points for one thing: it floated, and the wheels met the runway 1,732 ft past the threshold, 732 ft beyond the markers. That earns 9.2 of the 15.

Two verdicts
The big word above the number is older than the number. It is the touchdown’s own grade, the one the tower comments on: GREASED IT up to 180 feet a minute, SOLID to 360, FIRM to 600, ARRIVAL beyond. Each fault knocks it down one more: more than 30 ft off the centreline, touching down less than 300 or more than 3,000 ft past the threshold, more than 10° of bank.
So the word and the number can disagree, and they are allowed to. The word is about the moment the wheels touched. The number is about the whole landing, from the last mile and a half of final to the stop. A soft touchdown 2,000 ft down the runway, at the end of a final flown 3° slow, is still GREASED IT. It is also an 81.
Takeoffs and taxiing
A takeoff is scored from brake release to 1,000 ft above the ground with the gear up. Five things, in the same bands:
- Rotation, 25. The airspeed when you first pull back, against the rotation speed: 152 kt in the F-16, 142 in the F-35C. Within 3 kt is full, 20 kt off is nothing. Pulling too early counts against you too.
- Centreline on the roll, 20. The furthest the main gear wandered before liftoff, 5 ft and 40 ft.
- A smooth pitch-up, 20. The peak pitch rate after rotation, smoothed over a fifth of a second so a twitch doesn’t count. Under 6.5° a second is full, 14 is nothing.
- Gear up, 15. Up before its 300 kt limit is full; 30 kt over with it still hanging is nothing.
- To 1,000 ft, 20. Par is 24 seconds from brake release in the F-16, 28 in the heavier F-35C, and the points run out 25 seconds later.
The taxi runs from Ground’s clearance to the hold-short line: the time (par 45 seconds, 20 points), how closely the nosewheel followed the yellow line (30 points, measured as the root-mean-square offset over the distance, full within 1.5 ft), speed discipline (30 points, the seconds spent over 25 kt on the straights or 10 kt in the turns) and mishaps (20 points, all or nothing: wheels in the dirt, a crossed hold line). A departure is the taxi and the takeoff together, weighted 40 and 60.
Figure 2 · Every band
A headless test suite flies scripted landings and takeoffs through the real flight model to keep the bands honest: a careful run has to score high, a sloppy one (an early pull, late gear, a yanked rotation) lower, and a gusty crosswind landing still has to be good for a decent score.
The daily challenge
A score only means something next to other scores of the same thing. So every day there is one challenge, and everyone in the world flies the identical setup: the same airport, the same jet, the same task, the same wind with the same gusts at the same moments, the same time of day and the same clouds.
There is no server deciding it. The challenge is a pure function of the date in UTC. Day 1 is Monday 19 October 2026. Each week has an airport and a jet, in a six-week rotation (Nellis in the F-16, Hill in the F-16, Key West in the F-35C, and round again with the jets swapped). Each weekday has a task: a calm landing on Monday, a takeoff on Tuesday, then crosswinds, gusts, a taxi where the airport has a taxi route, and golden hour or dusk at the weekend.
Everything else comes from a small random number generator seeded with the date. It picks which side the wind comes from, how far off the runway and how hard (a crosswind day is 55–95° off the nose at 10–18 kt), the gusts, the time of day, the cloud cover and the seed that lays out every cumulus. Your browser and the server run the same code on the same date and get the same answer, so there is nothing to look up and nothing to keep in sync.
Figure 3 · The challenge on any date
challengeFor(date) from src/score/challenge.ts, run here. The strip is the week, Monday to Sunday. The runway points up the page: the arrow is where the wind comes from, the trace under it is the wind speed over the first minute of the flight, gusts and all, exactly as the flight model will feel it.The wind is not decoration. The flight model takes a wind field, a function of time that returns the air’s velocity, and the aerodynamics see the jet’s speed through the air, not over the ground. So in a crosswind the jet crabs on final and drifts if you let it, the airspeed jumps when a gust arrives, and on the runway a crosswind weathervanes the nose into it. The gusts are two sine waves, 7.3 and 2.9 seconds long, plus a slow 6° veer, all with phases from the date and timed by the flight’s own clock: a gust arrives at the same second of your approach as everyone else’s.
The share card
After a challenge the card offers a Share button, and the game draws an image for it: the number, the grade word and the task over a darkened frame of your own flight, at 1,200 by 675 pixels. On a phone it goes to the system share sheet with the image attached; on a desktop you can copy a line of text or download the picture. The line is short on purpose, so it reads in a group chat: VIPER 11 · Day 42 · Hill AFB · 94 · GREASED IT · viperoneone.com.
Not trusting the client
Everything above runs in your browser, and anything on your machine can be changed. A leaderboard that simply accepted a number would be topped by a hundred within the hour. So the server takes nothing on trust that it can check.
A score arrives with three things. The breakdown: every item’s raw value and points. A summary of the flight: the key moments and samples, such as the touchdown’s speed, sink rate and attitude, the time of brake release and of liftoff, how far the jet rolled. And the run log: every input you gave the jet, frame by frame.
The server scores the raw values again with the same formulas.ts, so the points have to follow from the measurements. Then it checks that the measurements agree with the summary, that every value is inside what the jet can physically produce, and that the summary describes a flight that could have happened: an approach and a stop take time, a jet can’t reach 1,000 ft sooner than its engines allow, a taxi can’t cover its route faster than its own top speed. A challenge score must name that day’s airport, jet and task, and its log must have been flown in that day’s wind. And a player can only post so often.
Table · The run log
| Run | Frames | Flight time | Log |
|---|---|---|---|
| A scripted landing from 6 nm, still air | 9,885 | 166.6 s | 10.3 kB |
| The same in a crosswind, 15 kt gusting 21 | 10,042 | 169.6 s | 14.4 kB |
| A takeoff to 1,000 ft | 2,398 | 40.6 s | 3.4 kB |
| A taxi and takeoff | 7,044 | 119.1 s | 10.6 kB |
labs/10-game/score.ts). Each frame is a byte for how many fixed flight steps it took and a byte saying which inputs changed, then only those; a run of identical frames is two bytes. The crosswind landing needs more input, so its log is bigger. Every one of these replays bit for bit.The run log is the long-term answer. The flight model steps a fixed 1/120 of a second. Each frame the game feeds it a whole number of steps, carrying the remainder to the next frame, and the inputs are rounded before the flight sees them: the stick and rudder to 1/127, the throttle and brakes to 1/255. What is recorded is exactly what was flown. Feed the log back through a fresh flight and it lands in the same place to the last bit, scores the same and says the same grade word. The server keeps every log.
Replaying it on the server is the next step, and it isn’t switched on yet, for an honest reason. Bit for bit holds inside one JavaScript engine, but another engine’s maths library can differ in the last bit of a sine. The test suite measures what that does: most runs end within a metre and score the same, the crosswind landing moved 11 m and lost a point, and one deliberately sloppy landing drifted 130 m and never landed at all. A jet flown close to the ground amplifies the smallest difference, so replay has to run in the player’s engine, or allow for the drift, before it is fair.
So, plainly, what a cheater can and can’t do today. They can’t post a score that doesn’t add up, a breakdown that disagrees with its own flight, a flight the jet couldn’t fly, or a challenge in some other day’s wind. But the checks are a filter, not a proof. Someone who understood the game well enough could still build a run that is consistent and physically possible, and v1 can’t tell it from a real one. The server only counts attempts that are posted, not ones flown and quietly thrown away. And nothing can tell whether a person or a program held the stick: the loop at the top was flown by the test suite’s own key-pressing pilot. What the server can do is make faking a score more work than flying one, and keep every log, so that when replay arrives every score on the board can be flown again.
The boards, and how much help you had
There is a board for every airport, jet and task, and three ways to read it: today’s challenge, this week’s (the same airport and jet all week), and all time. Each shows the top twenty and, if you’re signed in, your own best and rank. Only your best counts on each board, and between two equal scores the earlier one ranks higher. Posting needs a callsign, checked for slurs, crudeness and real people’s names before it appears anywhere. Reading the boards needs nothing at all.

Some help flies the jet for you: the runway assist that holds the centreline, the climb guide, automatic rotation and gear, the autopilot that brings you home. A run flown with any of them is still scored, and the card shows the number and names the help, but it stays off the boards. A challenge is always flown without them.
Other help only tells you things, and comes in three settings: Cadet (the compass, the steerpoint diamond, approach gates all the way home, the flight HUD, a line explaining each radio call), Pilot (the default) and Ace (none of it: the runway’s number, the tower and the cockpit’s own instruments). None of these changes the jet, so they all post to the same boards, but the setting is stored with every score as a tag, so that one day an Ace landing can be told apart from a Cadet one. The loop at the top was flown on Ace.