A 5-on-5 hockey engine that plays a full game between the Boston Bruins and the Montreal Canadiens on a regulation rink. Real rosters, player ratings built from published 2025-26 statistics, selectable team systems you can change mid-game, line changes the way benches make them, three officials and the NHL's rules. It is a decision and physics model, not a scripted animation, and every number that drives it can be traced to its source.
The teams
Boston is the home team at TD Garden and attacks to the right in the first and third periods. Both clubs dress their 2026-27 opening lineups: four forward lines, three defense pairs and two goalies, with scratches and injuries listed on the roster sheets. Each skater's ratings come from his 2025-26 season as recorded by MoneyPuck: shooting from individual expected goals and finishing, passing from primary assists and on-ice expected goals, defense from on-ice expected goals against relative to his team plus takeaways and blocked shots, faceoffs from his real win rate, and a penalty tendency from his penalties per 60. Skating speed and acceleration scale with his rating against NHL EDGE tracking benchmarks. Goalies save by danger tier at their real 2025-26 rates and freeze the puck at their own observed tendency. Small samples are shrunk toward average, and players who changed clubs carry their previous club's numbers, noted per player.
How a game is played
The engine runs the clock in real time at 1x. Every tick, the player with the puck makes a read. In the offensive zone he weighs his own shot against the best pass: how likely each one is to score, a defender in his lane or on his stick, and whether the pass will get there. A good look from the slot is a shot. A teammate with a clearly better look gets the puck. A perimeter look goes through traffic, and a point man fires when the lane is there. A teammate with a step on the last defender gets sprung, a lead forward at the far blue line gets the headman pass, and otherwise he carries, chips or dumps the puck in according to his team's entry system. Under pressure in his own zone with no safe pass, he bangs it off the glass, and on the penalty kill he clears it the length of the ice as soon as he gets it. Held too long with nothing on, he moves it to the nearest safe option. Passes lead the receiver and the receiver skates to meet them; long and hurried passes are harder to hit, and a defender's stick in the lane can knock one off line. In the offensive zone a receiver settles the puck before his next pass.
Everyone else takes a spot from the team's current system: breakout, neutral-zone attack, offensive-zone shape, forecheck, defensive-zone coverage, power play or penalty kill. The breakout is not a set of fixed spots. Once a team has the puck in its own end the forwards leave their support positions and burst north ahead of it, timing the rush so they take the pass in stride, and the carrier wheels out with speed. Through the neutral zone all three forwards are at full effort. In the offensive zone the cycle keeps moving: corner, half wall and net front rotate between the three forwards every few seconds, and nobody stands still on any shape. A dump and chase is a hard rim around the boards to the far corner with the weak-side forward already sprinting to beat the defense to it.
On the other side of the puck, the forecheck's first man pressures and the second man takes the next pass on a 2-1-2 or a left wing lock. Defensemen play gap control that reads the carrier's speed, never let an attacker behind them, box out the net-front man and step into shooting lanes. The center owns the slot and plays goal-side of the most dangerous man between the dots. Wingers shade the high men on their side, and anyone who gets to the slot is picked up first. Man coverage has the defensemen take the forwards and the forwards take the points; each defender stays with his man between him and the net, and only the man on the puck carrier pressures him. While a pass is on its way, the defense plays the receiver. Back-checkers caught above the puck sprint. Shots are blocked, miss, or reach the goalie, who is a line squared to the shooter. Every puck that reaches him gets one save roll: the better the chance and the weaker he is on that kind of shot, the likelier a goal. Rebounds go to the corner, and traffic in the crease makes him cover it up.
Line changes and fatigue
Forwards and pairs change separately, on the fly only when the moment is right: our carrier is through the neutral zone and can dump it in, or the other team is retrieving a puck deep in their own end. Nobody changes off a loose puck, during a rush against, or while the puck is in our zone. Each bench has two doors: forwards change through the door at the attacking end and defense through the door at the defending end, and both swap when the teams change ends for the second period. Forwards sit at their door's end of the bench and defense at theirs, the next unit stands at its door as a shift gets long, first man off nearest his door, replacement on once he is within a stick length. A tired skater near his door swaps himself out alone when play is at the far end, and a turnover mid-change can draw a too-many-men minor. At stoppages the visitors change first and Boston gets the last change and can match lines. Shifts target about 45 seconds for forwards and 55 for defense, the top lines and pairs get the most ice, the first power-play unit stays out longer, penalty killers go short, and the bench shortens late in a close game.
Shift length is not a hard rule. After about 30 seconds a skater starts to fade, losing top speed, acceleration and hands, so his passes and shots get sloppier and he is easier to strip, and by 65 seconds he is gassed. A unit stuck defending plays through it, which is where tired legs cost goals. A gassed unit clears the puck at the first chance, even at the cost of an icing, and takes the first half-decent window to get off. A ring around a skater shows how tired he is, amber when fading and red when gassed, and the roster sheet shows the seconds on his current shift.
Rules and officials
Offside with the tag-up rule and a delayed call. Hybrid icing judged at the end-zone dots, waived while shorthanded, and the team that iced cannot change. Minor penalties drawn at each player's real rate, with power plays and the penalty-box clock. Goalie freezes when there is traffic in the crease. Offside and icing calls are tuned to land at league rates per game. Three officials work NHL mechanics: the referee at the goal line in the zone, the lead linesman on the blue line for offside, the trail linesman on the red line for icing. A tie goes to a five-minute sudden-death overtime, played at full strength here, and then a shootout, three shooters each and sudden death after that, with each shooter's chance scaled by his shooting and the goalie's quality in tight.
Physics and calibration
Skating is calibrated to NHL EDGE tracking: top speeds of 19 to 23 mph by skater, bursts on rushes, breakouts and chases, cruising otherwise. Wrist shots run 58 to 85 mph and point shots 80 to 100; the dump is about 85 mph around the glass. Every unblocked attempt gets an expected-goal value from a model fit on two seasons of MoneyPuck shot data, times the shooter's own finishing over those seasons, and the goalie's save roll starts from that value. The danger tiers follow MoneyPuck's expected-goal thresholds. The next section has the details. The engine is balanced at the NHL-average settings, the tick mark on each slider; the defaults it ships with run hotter on speed and shot volume because that is more fun to watch. The Game plan lab compares the baseline's per-game numbers with each team's real 2025-26 numbers and the league average, and gives each one a verdict: on target within 15 percent, above or below, well above or well below past half. That table is the honest statement of where the engine still differs from the real game.
The models, technically
Time and motion. The game advances in steps of 0.03 seconds of game time. Every skater, both goalies and the puck have a position and a velocity on a 200 by 85 foot rink. Each step a skater picks a target point and accelerates toward it, limited by his top speed (27 to 33 feet per second by his skating rating, the range NHL EDGE reports) and his acceleration, both scaled by effort (cruising, sprinting, bursting) and by fatigue. The puck moves on its own: friction slows it, the boards return most of its speed, and a pass leaves the stick at a speed and with an aiming error that depend on the player's rating, the distance and how tired he is. A shot hits the net as often as real shots of the same danger did in 2025-26 (about 63% of low-danger shots, 69% of medium and 78% of high); a miss goes just wide of a post. A goalie is a segment that turns to square up to the puck and moves within his crease.
Decisions. The players are not trained by machine learning. They follow a rule-based policy written from coaching references, and every threshold in it is kept as data that can be questioned. Each team's system gives every skater a spot in his team's own frame of reference, mirrored to the end it attacks and to the side the puck is on, and moving with the puck and the play. The nearest man chases or pressures, defensive coverage pairs defenders with attackers or with areas, and the puck carrier reads the ice every step: he scores his own shot with the expected-goal model, scores each teammate as a pass (the receiver's expected goals, times the chance the pass gets through the lane, times the pressure on him), and shoots, passes, carries or dumps by comparing them against thresholds.
Expected goals. A logistic regression fit on 237,055 unblocked NHL shots from the 2024-25 and 2025-26 seasons, from MoneyPuck's public shot data, with empty nets and shootouts left out. Its inputs are distance and angle to the net with curved and combined terms of both, shot type, rebound, power play or shorthanded, a shot off the wrong wing, and the puck's speed since the previous event; the engine does not track the last two and uses their league averages. Trained on one season and tested on the other, it scores a log loss of 0.226, against 0.218 for MoneyPuck's own model with many more inputs. Every shooter with 60 or more shots gets a finishing multiplier, his goals against his expected goals, shrunk toward average.
Saves. Each puck that reaches the goalie gets one save roll. The chance of a goal is the shot's expected goals divided by the share of unblocked shots of that danger that hit the net (expected goals count misses too; the roll only sees pucks on net), scaled by that goalie's real goal rate in the shot's danger tier against the league's, and by one calibration factor. That factor, 1.02, keeps goals per game at the league rate while the engine still creates more good chances than real defenses allow; the chance counts themselves are not scaled, so the gap stays visible in the comparison with the real teams.
Ratings. A skater's shooting, passing, defense and faceoff ratings are percentiles of his 2025-26 rates per 60 minutes among skaters with 300 or more minutes, shrunk toward average for anyone under 600 minutes. A goalie's save rate in each danger tier is shrunk toward the league's with 150 shots' worth of average play.
Measured, calibrated, assumed. Three kinds of numbers drive the game, and they are kept apart. Measured: the ratings, the save rates, the expected-goal model and the real rates the game is compared with. Calibrated: values chosen so the simulated league reproduces a measured rate, such as skating speeds against EDGE, shot volume against attempts per game, the save factor against goals per game, and offside and icing calls against league rates. Assumed: the formations and decision rules from coaching references, which nothing has measured yet. The Game plan lab's comparison with the real teams shows where the assumed parts miss.
The Game plan lab's statistics. A test and its baseline play the same seeded games: each game draws every random number from its own generator, started from the game's seed, so the two versions share every bounce until a change makes play go another way. This is the common-random-numbers method from simulation studies, and it lets a hundred games separate two plans that would otherwise need many more. The result for each game is the difference between the two versions; the verdict is the mean difference with a 95% interval, 1.96 standard errors either side, and a clear edge or a clear cost means the whole interval is on one side of zero. The engine also does its own trigonometry and logarithms with exact arithmetic, so a seed plays the same game in every browser.
What full tracking data would change
Everything above is built from public data: the play-by-play (where each shot, hit and faceoff happened), shift charts, season totals and EDGE's summaries of skating speed. The NHL also records puck and player tracking: the position of every skater, both goalies and the puck many times a second, for every game. Those vectors would change each model in a specific way.
- Movement. Each player's real acceleration, top speed, turning and stopping, measured from his own frames, instead of two numbers scaled from a rating.
- Decisions. With all ten skaters' positions at every pass, shot and carry, the carrier's choices could be fit to what players actually did in the same situations, and pass completion fit to real lanes and real defenders, instead of rules written from coaching references.
- Expected goals. The biggest gain. Whether a shot goes in depends on things the public data does not record: where the goalie was and whether he was set, screens in front of him, the pass that set the shot up and how far it moved him, the shooter's speed. Models built on tracking use them, and they separate goals from saves far better than a model that knows only where the shot came from.
- Goalies. Saves from the goalie's real position, depth and movement on each shot, instead of one save rate per kind of shot.
- Systems and coverage. Each team's real forecheck, breakout and coverage, measured from where its players stand, instead of drawn from coaching references. That is also the fix for the engine's biggest known error, too many good chances against, because coverage could be tuned to real defensive positioning instead of to totals.
- Validation. Real game situations loaded into the engine and its choices scored against the players' choices, shift by shift, and strategy effects checked against real results. That is the step that would let a coaching staff trust what the Game plan lab says.
None of that needs a different engine. Every model sits behind a data file or a single function, so each one can be replaced by a fitted version as the data arrives.
Glossary
The systems
Using it
Watch plays one game on the rink. Pause it, change the speed (0.5x is the one for following sight lines) or start a new game; the scoreboard shows the shots, each team's share of the chances and the power play. Effects draws skate trails, streaks on hard shots and passes, ripples on takeaways and blocked shots, a flash on big saves and the goal light. Sticks draws each skater's stick. Sight lines shows what the puck carrier sees in the offensive zone: his open look at the net, the shadow each defender casts over it, and his best pass, with how likely each one is to score. Below the rink each team's game plan reads as a sentence. Edit plan opens both plans with what every choice means, and a change takes effect on the next play. The box score, the play by play and the rosters fold open underneath.
Review a game judges every shot of a finished game: the one you just watched, once the final horn sounds, or any game the lab played, opened from its results with Review it, without watching it first. Your recent games are listed there; the lab's stay in this browser and are played again exactly when you reopen one. Print or save as PDF, there and in the lab, makes a report for paper: in the lab, the baseline, its comparison with the real teams and every test; in Review a game, the shot you are viewing on one page, with the play at the release, the call, his read and the played-out pass. Your browser's print dialog prints it or saves it as a PDF. It judges every shot by what the shooter saw when he let it go: his own look at the net, after any defender in his lane or on him, against his best pass, the receiver's look times the chance the pass gets there. These are the same values he decided with and the sight lines draw. A shot is a better pass missed when a pass was worth clearly more, a close call when one was worth a little more, and the right call otherwise. Each team gets a count and the goals it left on the table, a strip shows every shot of the game in order, and any shot opens on the rink as it stood at the release, with the sight lines frozen and a replay of the six seconds before it. It also says why he shot: his look beat his passes, he threw it on net from the outside, he took the shot he had, he had held it too long, a breakaway or a one-timer. Positions are exact, because the game is the simulation. The review judges the choice, not the result.
Each plan is seven systems and an aggression dial. The dial sets how hard the team plays on and with the puck: higher means checkers go after the carrier harder, with more takeaways and more penalties, skaters shoot more from ordinary spots, and the carrier holds the puck a beat longer looking for a play. It does not change the forecheck, gap control or line changes; those come from the systems.
The Game plan lab answers whether a change would help, apart from the game you watch, with plans of its own for both teams. Pick the team you coach and set both plans; they start from the same plans as the game on the rink, are remembered in your browser, and reset to the originals with one link. Run the baseline: your plan against theirs, 100 games unless you pick another number, at the NHL-realistic settings, in about a minute on most computers. It says how your team does, and folds out a comparison of those games with what the real teams did in 2025-26. Then change either plan, one choice or several, and Test against the baseline: the plans as they are now play the same games as the baseline. The same games means each game starts from the same random numbers, so the bounces match until a change makes play go another way, and a gap between them is the changes, not the schedule. Each test is named for what it changed (the choice itself, or how many changes past three), lists the changes and gets a sentence and three verdicts for your team, net chances, goal difference and points, each a clear edge, too close to call or a clear cost. Trust net chances first: points need far more games to separate. Changed choices are marked in both plans. Rerun the baseline makes the plans as they are now the new baseline and clears the tests. Both buttons wake up only once something has changed since the run they would repeat. Find the best option, folded under the tests, answers a narrower question: which forecheck, breakout or other choice suits your team against this opponent, and whether that choice matters at all. It plays every option of one choice on the baseline's games, the rest of your baseline plan unchanged, ranks them by net chances, says in a sentence which one is best or that none separates, and puts a clear winner into your plan with one button, ready to test with your other changes. Any test or ranking can be folded down to its one-line answer or removed, with an undo until the next run. The baseline and the tests are kept in your browser, so they are still there after watching a game or reloading the page. Watch these plans in a game copies both lab plans to the Watch view and starts a game with them. Any single game of the lab can be watched or reviewed: the baseline card and each test have a picker, a test's games sorted so the ones that show its verdict come first, with the test plans or the baseline plans. Watch it plays the game on the rink exactly as it did in the lab; Review it goes straight to Review a game with every shot of it.
Settings, in the Watch controls, holds the sliders for the game you watch, with a tick at the value calibrated to NHL tracking; the lab always plays at the tick. Settings and the Watch plans can be saved in your browser or exported to share, and the data sources are listed there too. The version number is at the bottom of the page.
What it is not
It is not a replay of real games. Player movement is a decision model, tuned against public aggregates, not tracking data, so the engine can be systematically wrong in ways the calibration table will show. Ratings reflect one season of results and a weak defensive proxy, and systems are drawn from coaching references, not from either club's actual playbook. Everything that drives it, from rosters to formation coordinates to the speed of a rimmed puck, is kept as plain data with its sources, so any of it can be questioned and corrected without touching the engine.
Where this could go
With tracking data the same rink could also replay a real game exactly as it happened, and the useful tools follow: a player-specific view that replays his shifts with the alternatives the model would have taken at each read (the pass he had, the lane he did not take, the change that came a beat late); a pre-scout mode that loads an opponent's observed systems and tendencies and lets a coach test breakouts and entries against them before the game; a special-teams lab for power-play shapes against a specific kill; and a development tool that shows a young player the difference between his reads and a veteran's in identical spots. Shot-location data, which is public, would tighten the expected-goal model and give each shooter his real map, and line data would let the engine score its combinations against the real results of those same combinations. None of that requires a different engine; it requires feeding this one real frames.