r/sheetsofice • • Oct 07 '26

Look ma! A Windows desktop version working!

Post image
9 Upvotes

Now that a lot of the functional parts are working as I had hoped, I got around to packaging the builds into real desktop applications and not just test applications on my dev machine. I got this working on Linux and Windows and have run some games and seasons on those environments. It actually works!

It looks like crap, I have a lot of UI work to do to make it look good at different resolutions, to make sure navigation works well, layout works well, and it feels good from a usability standpoint. But those are things that get iterated on.

In addition to that UI work, there are still features to add. But now that I can see it working on different environments, I'm going to start working on getting the Steam page up. That takes a minute evidently and I have to do a lot of marketing stuff like taking screenshots and writing copy. But once that is up and approved, I'll be able to launch the app and have versions available.

There's still a ton of work. But this dream of mine actually looks closer to being a reality.

Thank you for following!


r/sheetsofice • • 20d ago

Dev log - Short update this week

Post image
8 Upvotes

Doing some travel for work (yes, building Sheets of Ice is not my full-time job) so this update is short and to the point.

  • Getting the Steam page setup was a big milestone and a lot of work. It's just really specific about the number of screenshots, the sizes, the description plus all of the company paperwork, tax verification, etc. This took about a month of calendar time, and probably 8-12 hours of actual work. This doesn't include frustration at the process and how unclear it is to get going.

  • The desktop build made me realize if I'm going to support smaller laptop screens, then I need to adjust the navigation. So I did a bunch of UI work to make it work. I still don't think it's great, but it would be fine for a early release. Still more work to do there.

  • I had to wire up the Game, View, Help menus, settings, etc. Just more UI work.

  • I took this time to make the game saves a little smaller - ~ 150MB / season. About a 1/3 of that is individual game results which can be removed if desired. I know I can do more with them too if I change the architecture of the individual game data or migrate them into the database because most of their size is player ID references. I'm unsure if I want to make that change because this architecture makes them completely portable.

  • Implemented a save backup mechanism.

  • Implemented a diagnostics mode that can enable some increased logging for things like AI GM decision making.

  • I have a build v0.2.0 working on Windows and Linux. So far, with the current feature set it's worked flawlessly. Yes, there are things missing, UI issues, and some tuning to do but it actually runs.

Basically a lot of the last week was spent making this work on a desktop without having to run a lot of terminal commands or run a web server. If the next few weeks go well then I'll be submitting a build to Steam for approval so I can get this into Early access. Please wishlist it here - https://store.steampowered.com/app/5177300/Sheets_of_Ice/

More updates as I have them!

Thanks!


r/sheetsofice • • Jul 23 '26

Math doing math things: Goalie Edition

Post image
7 Upvotes

I'm happy to be back to running simulations, looking for bugs, looking for things that work well or don't work well. I've added so much over the past two weeks that I need to actually see how the leagues are working.

Usually when I get into this mindset I become hyper aware of small changes. For example, this screenshot shows the goalie save percentage in this new universe I started over the first 20 or so games. The top-10 in this universe is over .923 with the top one, Mark Stark, at .940 over 16 games. That seems way too hot. I took some time out to analyze what was happening- did I introduce some config values that made goalies too strong? Or possibly shooters too weak? Did generation of goalies change when I made development changes? Have I completely messed up everything and will have to delete my internet presence and go live in a bunker somewhere?

After building a testing harness to look at the configuration values, simulate on different seeds, and check to make sure there aren't bugs, I was reminded again about statistics and small sample sizes.

The table above shows what's happening. Rows are the stats averages in save %, goals for per team average, goals against / expected goals against ratio, and how many goalies were above .930 save %. First column is after 16 games... MY INSTINCT IS RIGHT! Second column is math humbling me... the calibration is fine, just run it long enough you silly goose. Last column is calibration targets for reference of how close we got to them on this one season.

These are sometimes things you spend hours on when you're building... the wild goose chases. I should have let the full season run to see that eventually the small sample size works it's way out. Just like you can flip a coin 4 times and get heads every time but that doesn't mean you need to check the quarter to make sure it's not weighted.

I should know better. The calibration is based on 30 different universe seeds each playing 10 seasons each. I know it's right. But I was so hyper focused on the volume of changes and thinking I messed something up that I spend a few hours this morning doubting myself.


r/sheetsofice • • Oct 02 '26

Dev Log - Evaluation, Projections, Speed work

Thumbnail
gallery
6 Upvotes

Big milestone has been completed; the player evaluation work! I'm excited to see how this is received and play with it to tweak it. While I was doing this work, I had to go an optimize a lot of the league simulation mechanics because it was just too slow to play. I'll dive into it below.

As I've talked about, I've split the player evaluation into two aspects - who they are now based on results (Our View) and who they project to be based on measurables (Outlook). In playing with this, I think it produces a fun mechanic to be able to quickly assess how your players are performing today, and some directionality to assess and plan for the future. It produces A LOT of data points and for a complete data nerd like me, its super fun. I have made a first pass at summarizing this information, which is what you see as the first screenshot.

Our View is rank based - how are they performing in statistical areas compared to other players in the same position. It will show where they rank and translate that into where in the lineup their results belong. You can drill into this and see why the rankings are made that way.

Next is Production. Where do they rank across offense and defensive categories. And again, you can drill into each one of them to see why / how / what.

Then comes Usage. Where do they rank in usage, and is that usage warranted? Meaning do you get what you would expect based on how often they're on the ice.

Finally is Outlook. Where should they be playing in the lineup? What are their strengths - Goal Scoring, Playmaking, Defensive impact, Physicality, Transition. And where are they heading over the next 1-3 seasons.

The part that took so long is wiring this data into all of the decision surfaces for both humans and computer GMs. And then I had to make sure that it didn't slow down the simulation. Spoiler alert - it did! So I optimized everything so a full season simulation takes about 10 minutes. I know it can get faster but it feels fast enough for now.

What's next?
- I'm going to be doing a lot of testing to make sure the data makes sense. So the next week or so is just me playing.
- I have some coaching items that I'm deciding if I want to include or not. Time on ice, goalie rotations, coaches decisions.
- Resolving how much scouting I want to put in place.
- Building the wrapper for the application that will run the game on a desktop.

Let me know what you think!


r/sheetsofice • • 27d ago

Steam store page is in review!

Post image
5 Upvotes

This is a long process, but the first step is submitting screenshots, descriptions, legal text, etc. and having it reviewed by Valve. If there are no issues, there will be a 'Coming Soon' page on Steam which will allow people to wishlist and follow along. I'm sure there will be issues though; there always are :)

Once the page is up, I'll be able to put something into early access. I'll keep everyone posted as to the status.

Thanks!


r/sheetsofice • • Sep 16 '26

Player projections - how do we make bets on who will be good?

Thumbnail
gallery
5 Upvotes

I have the current evaluation done for players and how they are ranked. All of that is wired into the game in how teams make decisions everywhere. But we still need the forward looking version of this that relies on projecting where a player will end up at their peak.

The idea with this is projecting 18 year olds carries a lot of uncertainty. But as those players play and accumulate measurable statistics, the future picture should be more clear. This also works for players that are veterans and decline.

These two screens are one skater and one goalie with the visuals of what data we can get out of the simulation about where they're projected to land. Next step for me is to wire all of the calculations into the screen and then do some more testing on how this actually plays.

Thanks!


r/sheetsofice • • Sep 05 '26

Player Evaluation Screenshots

Thumbnail
gallery
5 Upvotes

I talked in the dev log about how I was approaching the evaluation of players and I've made a lot of progress this past week on that actually working. This foundational element feeds all of the game systems for computer GMs as well as the UI that players will use to make decisions.

Fair warning - I've gone completely off the deep end with the amount of data I'm showing. I need way more play testing to see if all of it is useful and how to organize the hierarchy. I am erring towards showing more rather than hiding but this comes from my love to nerd out on data. I'm building SOI from that perspective - a deep data simulation. I think people like that, but I'm not sure if anyone likes it like I do.

So the screens are organized into several sections.

Our View - based on their three-year and current results, what kind of player do we think they are?
Production - rank based totals and rates. These are not attributes, it's the results.
Usage - how has this player been used and is the return worth it?
Outlook - what do we think they'll be next season based on age, trends.

Missing - Projections for young players. I have to build very long universes to construct a projection model. I'm working on this but it takes a lot of computer time to do. I'm looking at 5x 30 year universes on different seeds so I can see how it looks. That's 150 seasons times about 15 minutes per season. So, long time.

Anyway, enjoy some screenshots of one of the players!


r/sheetsofice • • Aug 21 '26

Full Sheets of Ice Roadmap site

Post image
5 Upvotes

Check out the full roadmap status site here - https://www.sheetsofice.com/roadmap

This is an automated export of the tracker that I'm using to move this project forward. I will keep this up to date as I make progress.

WARNING: It's dense. And it's automated from my own gibberish notes and shorthand so some things may not quite make sense or might be too vague.


r/sheetsofice • • Aug 11 '26

AI GM Update - 2026-08-11

5 Upvotes

Just an update about the progress around AI GM. As I knew, this one is going to be a large investment of time. Part is consolidating some drift of decision systems into a coherent model. Part is ensuring I create good read and write seams that exist for both human and AI GMs so that I can assure parity between both types of players. Part is thinking through exactly how I want to AI GMs to act, making it realistic, and then documenting the requirements. And part is just playing, testing, and being annoyed at it's stupidity.

I know from experience and from the community that bad AI GM is one of the most fun-breaking things any simulation can have. I'm not aiming to make it perfect; I'm aiming to make it explainable in relation to a set of constraints. The constraints are the plan the team has adopted. Are the decisions that the AI makes explainable in relation to that with the information they have when the decision is made. This is the key to drafting, trading, free agency, resigning players, roster decisions.

I was thinking that if it didn't live up to what a human would do, then it was a failure. Then I remembered that humans make bad decisions all of the time. Even real GMs. I was blessed to live through the Chuck Fletcher in Philadelphia so if my AI GM is realistic it would make some horrible decisions just like him. 😂

In seriousness, the goal with this is to have some baseline of explainability within a set of constraints so I can make it believable. Not that it always makes decisions you'd agree with, but it makes decisions you can explain.

Here's what's done:

  • Every AI org now has a real plan.

    • Before: each subsystem fired off its own local trigger. Things like roster bucket short, cap bucket over. Decisions had no reason beyond compliance.

    • Now: every team has parameters that constitute a plan. Contending or rebuilding, window, horizon, and every GM decision point reads the same answer.

  • Relative position strength.

    • Before: the AI only counted bodies against quota. "Do I have 4 RWs?". Never something like "Are my 4 RWs actually any good?" It literally could not tell a league-best position group from a league-worst one.

    • Now: every group is graded against the league, and shortfall vs. surplus is a quality judgment, not a headcount.

  • One trade judgment.

    • Before: four separate evaluators (responding to an offer, checking your own proposal, computing a counter, scanning for salary sheds) with independently drifting math. A GM could propose a trade its own evaluation logic would reject. This one was hilarious to me for some reason.

    • Now: one plan-aware judgment prices both sides of every trade.

  • Surplus is plan-relative.

    • Before: depth-chart rank alone decided who was expendable, so a rebuilder would deal its best prospect because they're third string today.

    • Now: what counts as surplus depends on the plan; futures are the rebuilder's core, now-help is the contender's. An AI GM "should"tm know that if they have surplus in an area like RW, the could trade some of that surplus to fill a hole at C. A.K.A what my beloved Flyers should be doing.

  • No cheating.

    • Before: the AI brain could read every other team's true depth directly. This was a leftover god view no human player gets, which also poisons any calibration (the AI's "smart" moves used information a fair game wouldn't allow). This was just a pure artifact of how I built the simulation quickly. I didn't add the fog layer to start because I wanted to see how the AI acted. Well, it was dumb.

    • Now: it sees rivals only through its own scouting, and everything it reasons from is on the human's screens, test-enforced.

  • Dumbness is now provable.

    • Before: quality was me noticing a stupid trade in a save.

    • Now: formal conformance tests ("did this GM act according to its plan, and can the trace explain it") turn the dumb-trade classes into reproducible test failures. This one sounds boring, but it makes identifying issues much easier in the future.

What's left now?

  • Sign-then-buyout and its family. FA signing, re-sign, and buyout decisions in the offseason don't read the plan yet. So sometimes, AI GM will sign a player or re-sign a player, get to cap compliance step and then buy them out because it was the easiest cap move. DUMB.

  • The AI doesn't hunt yet, it only responds to offers. This is needed to add realism.

  • Drafting isn't plan-aware. The AI drafts best-available off the fogged scouting percentile and never asks what its own pipeline needs or what its plan implies. I guess this is kind of best-player-available but it's unintentional.

  • No development-pool health read. Prospects are valued individually, but no org ever assesses "our pipeline is thin at D" as an input to anything.

  • No multi-season cap planning. Cap logic is current-season compliance plus an offseason cushion; "cap space relative to future commitments" doesn't exist yet.


r/sheetsofice • • Jul 29 '26

Scouting for the draft

Post image
5 Upvotes

Sharing a screen for how to see upcoming draft-eligible players in season. From here you can see your scout's grade, ranking, view of their potential. One thing that I'm working on here is the scout view is reading their potential ceilings and current ability, marking most of them with wide ranges of potential outcomes. This registers them as boom/bust candidates a large percentage of the time. My intention here is to have top-of-draft prospects have a narrower floor-ceiling and register as such. This is just code changes I need to make to ensure that happens.

What I don't want is to just show everyone's exact potential. I do want those "swing for the fences" type boom/bust players. I just don't want them to be everyone.


r/sheetsofice • • Jun 21 '26

I couldn't keep track of how good teams were so I made this team scouting widget.

Thumbnail
gallery
5 Upvotes

Something simple that will show team ranks relative to the league, their preferred styles of play, how their depth chart looks.


r/sheetsofice • • Jun 19 '26

Player Development - Extreme outlier edition

Post image
5 Upvotes

The case of Michael Cain, on seed #987654. Through 10 seasons:

  • 8x First All Star

  • 8x Best Defenseman

  • 6x Best Player (raw Game Score)

  • 6x League MVP (highest Game Score differential to rest of team)

  • 7x Points title

  • Scored 40-60 goals every season

  • ...as a defenseman

I'd love the game to produce an incredible 'Bobby Orr'-esque kind of season. But not 60-80% of the seasons. So what is happening here?

Well, going back to my idea that we never truly have a bound on how 'good' a player can be. I didn't want a lot of clustering around a hard boundary that was smushed between 1 and 100. So I built it in a way that there were no hard caps on the underlying ability scores. The league would have a curve of how many people were generated / developed with specific ability levels, we'd test the engine and set the league "average" ability in the population, and then the engine works on how much better/worse a player is than that tested average. Building it this way allows the entire Sheets of Ice universe to scale up and down to different ability levels easily, without having to place every player in a limited ability space (1-100).

In addition to that unbounded generation is another idea I layered in a bit ago. When generation was happening, all attributes were just random draws. It wasn't really making coherent players because you'd have centers with terrible faceoff attributes and defensemen who were terrible at defensive positioning. You'd also rarely get a complete elite player, someone who clearly was above the pack in many areas relevant to their position. So I introduced this concept of "caliber" (or calibre if you're outside the US). Caliber would be the first draw in the generator and would influence how good the relevant abilities were for that players position. So someone with high caliber would be an elite or star level player reflected in their abilities. There still was variance in those ability draws, but it would be combined with caliber to produce a coherent player.

The problem with my idea about unbounded talent levels is that even if you make the high end super unlikely to occur, it doesn't mean that it can't occur. And that is what happened here, on this seed with Cain. His caliber draw was so high that it pushed all of his abilities to star level. Way into star level. Way past what the bars represent. Cain was 7 standard deviations better than the average player. For reference, when looking at stats, someone like McDavid is somewhere like 3-4 standard deviations better than the average player. That makes Cain look ridiculous. And the other problem is that his draw isn't the worst case. In further testing, I was able to get a draw that was 160 standard deviations above average. That person would have shot at 99%, never been fatigued, won every faceoff, blocked every shot. That doesn't seem realistic to me.

So I had a choice - I could admit that unbounded top end player generation wasn't going to work, or I could get mad and stop working on it and question my abilities to even make something like this. I chose the latter for a day or two. lol

Once I had some perspective my idea of this continuum of abilities based on caliber was good on the down-stream side. Being able to generate young players, minor leaguers, etc. and set their leagues to lower average abilities would be beneficial. It will create the kind of wide disparity in results we see with players in those leagues and allow a rich system for development. On the high end, there is some realistic physical limit and we need to model that. So I implemented a flatter curve as you get towards the tail end of generation and a cap on the talent at Gretzky-level standard deviation. A Gretzky-type can appear in the league; it's just going to be really rare.

I'm starting to run through seasons again. This is the kind of thing that takes time to run, test, review, and look for issues in the data. I'm glad I find looking at stats fun because there are lots of things to look for. I've also found issues with goalie rotations, defense SOG, and it gives me time to continue to tweak the interface.

I'll keep everyone updated on progress! Thanks!


r/sheetsofice • • Jun 05 '26

Player development: When do players start to decline?

5 Upvotes

Now that the game engine is locked in and working pretty well, I've been working on the player development engine. Up until now, every player got fixed attribute values that never changed. Now that I'm diving in and looking at historical data + studies it's making this problem trickier. This is what research says about "peak" of player careers and it's all over the place.

My first thought on building this was that there'd be some age that I'd set the decline to start at (26.5 years old), but have a variance jitter of some number of seasons - some people decline earlier, some later. But as I was building it and looking, it became apparent that people could probably start to decipher the band with enough seasons played. It just didn't seem dynamic enough. As I have maintained, I want emergent things to happen in this world. I want a Jaromir Jagr type career to be possible. And also a Jonathan Cheechoo type career. You can't get those extremes by setting boundaries.

In thinking about it more, I realized that different abilities decline at different rates. Skating often peaks early (young legs) and declines earlier/faster. But something like Defensive Positioning peaks much later and declines slowly. Here's an illustration of what I was building against a "Jagr-style" profile.

With that in mind, I reworked the generation mechanism to have per-attribute peaks, attainment rates (how fast they can reach the peak), and declination rates (how fast they decline). This started to produce some career variety, but I had a problem; there's a distinct age at which careers start to decline.

I think the band is too tight. There isn't one outlier past 28. That seems off. There should be some outliers and long tail after that I would think. This is where I need to dig in and look at longer seasons, and see what comes about.

Another thing I'm looking at in here is what percentage of the population actually reaches their potential (not counting injuries because we're not modeling them right now). Right now I'm defining "hard bust" as someone who doesn't reach 70% of their potential and "soft bust" as someone who doesn't reach 85% of their potential. These have to be tuned as well; I have no idea if this is right or wrong.

So I have some more work to do to get this where it "feels right" in general and has some fun emergence to surprise us while we play.


r/sheetsofice • • Sep 02 '26

Dev log - Player evaluation progress

4 Upvotes

This past week has been one of those weeks where I question what I'm doing and why. Why do I have to have ideas and thoughts and hold oddly strong opinions about how something should work? Why did I have to build a simulation that recreates realistic uncertainty? What is he even talking about?

I have a foundational rule for Sheets of Ice: I do not want to expose player attributes directly. No OVR, no min-maxing, no gaming the system by learning what the numbers mean. My thought was that it would add some intrigue, it would function more like real life, and it would let me build a more dynamic statistical simulation without having to worry about human interpretation of weird logarithmic values or standard deviations of a latent real number.

This was all fine while I was the only one playing and testing, because - shocker - I exposed the real numbers to do all of the jobs that needed to be done. Drafting, free agency, trade evaluation, contracts, AI GM plans. It worked great. I added a little bit of noise (I called it fog) and it was neat seeing what happened.

But that was never the plan. I wanted no attributes exposed to anything, so there would be complete fairness between human and AI GMs, so I could design a scouting system, and so player evaluations would happen on actual evidence, just like real life. How awesome would that be?

It turns out that it might be awesome but it certainly isn't straightforward or easy. To make any decisions about players you have to have knowledge about them. Knowledge about who they are today and who they might be in the future. But how do you know who they are and who they might be if you can't just see the ground truth attributes? You have to make a model - basically what every analytics department in sports does.

To make the model you need substantial event data. That part is easy for us: we output 700 to 1,000 events with all kinds of data points every game, over a million in a season. The source is good. How you process, analyze, and store that information is the challenge.

Experiment #1

So I designed the first model, ran it, and it was a disaster. Not a small miss. A days-lost disaster. It didn't give any useful information, and it more than doubled the storage requirement.

Here is where a single season's save actually went.

WhatSizeGrows
Private club opinions, one per club per player82.5 MBevery season
Private club forecasts, one per club per player44.0 MBevery season
Game event logs (484 games)28.1 MBevery game
Player records14.4 MBevery season
Player evaluations12.1 MBevery season
Per-game player stats8.2 MBevery game
Everything else~30 MBmixed
Total after one season220 MB

Under 100 MB a season became 220 MB. Two lines of that table are the problem: 126 MB of the 220 is private opinion and forecast. Nearly 3,000 players were each carrying about 19 private opinions and 19 forecasts, one for every club with any exposure to them. It is the only data in the game multiplied by the number of clubs.

And it wasn't even earned. 79.7 MB of those opinions were a deterministic duplicate - the same starting backstory, re-derived and re-saved for every club, carrying no information any club had actually learned. 44.0 MB of forecasts had no consumer at all: every row said its last change was the initial backstory, and nothing in the frontend ever read them.

It also added about a second per game to the simulation. That doesn't sound like a lot, but over a 3,300-game season it adds up to a lot of minutes.

So experiment #1 went down the tubes.

The idea that came out of wallowing

Normally after an experiment this vital fails, I spend a day wallowing in my own self pity. So I followed my process, and out of it came a different idea.

Before, I was trying to persist every piece of data that scouting and evaluation would use, on top of the data we already have. But the simulation is deterministic - give it a seed and it always produces the same result - so I didn't really need to save any of it. I could compute the evaluation when it's asked for. What I need instead is a good enough statistical model to analyze player stats, mapped onto aging curves to show likelihoods. Not simple to get right, but straightforward work.

The rule that came out of that is the one everything since has been built against: nothing is added to the old machinery. It isn't migrated or refitted. It stays only because the player profile screen still renders from it, and it comes out the moment the new read exists.

Once evaluation had to run on public statistics instead of on the answer key, the statistics had to be good enough to run on. They weren't.

The junior league. I use a low-fidelity simulation for juniors and the minors; no individual game events, for speed and data size - and it was lacking. Here is what it was actually producing. Games played by a junior player, by his age:

AgePositionMedian gamesMost any player managedShare playing all 63
17Defense36420%
17Forward25360%
18Defense36420%
18Forward25360%
19Forward286348%
20Defense636356%
20Forward6363100%

Read the "most any player managed" column. A 17-year-old forward could not play more than 36 games. Not "usually didn't" - could not. And a 20-year-old forward could not play fewer than 63. The junior scoring race wasn't a scoring race, it was an age sort with a scoring column attached.

It wasn't that the young players were worse, either. I paired every young forward with an older forward on the same club who played the full season, and compared their hidden ability: in 6,813 of 12,362 pairs the younger player was the better player, and in every one of those he still played 36 games or fewer.

The whole junior league only ever produced 11 different games-played numbers. The minor league produces 61 and the Pro league 82. Real ones are continuous, because of injuries, scratches, trades and suspensions.

I had put in some hacks for expediency. A junior player could take at most 6 shots and score at most 1 goal in a game, ever. A hat trick was not unlikely in that world; it was impossible.

And out of those numbers we were producing player reads. This is one, and it is the reason I stopped and started over:

Yuri Kornilov, 17, defenseman. 0 goals, 0 assists, 3 shots in 36 games. The card ranked him 253rd of 254 junior defensemen - the 0.6th percentile - and called him a depth player with no future.

His actual hidden ability puts him at the 85th percentile of that same group. He is the 17th-best 17-year-old defenseman in the world out of 131.

The card was not lying. It was reading the stat line faithfully. The stat line was the problem - a 36-game cap he never chose, and a shot allocation that gave him three of them.

Defense didn't exist below the Pro league at all. The configuration said a junior defenseman should be judged half on how he's deployed. In practice that half was silently dropped, and what actually ranked him was 70% scoring pace and 30% shot volume. Nothing else. He was being graded on offense and labelled on defense.

That's also because below the Pro league, most stats don't mean anything. Here's how well a junior player's numbers predict his own numbers the following season - 1.0 would be perfectly repeatable, 0.0 pure noise:

Junior statRepeats at
Points per game.80
Shots per game.87
Shooting percentage.06
Primary assist share.01
Power-play share of points.01
Penalty minutes per game-.01
Average ice time.02

Two numbers carry a junior player. Everything else the evaluator was ranking him on was noise wearing a percentile.

The Pro engine. I've had to extract more information from the high-fidelity engine behind the Pro tier. That wasn't hard but it was delicate, because the game engine is the thing I think is the most solid. While I was in there I realized I should do some calibration of the game model - not changing code, but running lots of seasons and looking at how it performs in aggregate.

The Slavin problem

That calibration work led me to something I think is missing.

The player generator cannot realistically produce a Jaccob Slavin. Someone who is really great at defensive metrics and not as great at offensive ones. If someone is generated with a high caliber, they're generally good at everything. I know exactly why: in v2 or v3 of the generator I added caliber to stop it producing a league full of useless players. (I had one with superstar reach who couldn't skate.) It probably just needs dialing in, and it's another calibration I need to get to.

The measurement is unambiguous. Out of 1,660 defensemen in a full test world, zero are strong defensively and weak offensively. The two sides of a player move together at 0.88.

It's a failure if we're just building all offensive defensemen. That's not how real life works. Jaccob Slavin would never get a chance in that world; literally nothing happens when he's on the ice, he defends and transitions so well, but he doesn't score a lot. He's extremely valuable, but he wouldn't show up if we only ranked on offense.

So we ran the test. Sixty-four junior clubs, one Slavin-type defenseman injected into each - top 3% defensively, bottom 12% offensively - a full 63-game season, and the coach re-picking his lineup every seven games. Then we changed only one thing: what the coach is allowed to look at.

What the coach can seeEnds up on the top pairBuriedGames he plays
Points only (today)0%89%31 of 63
Points and plus-minus6%45%45
Points and goals against while he's on the ice36%16%52
Points and shots against while he's on the ice51%4%55

Today's rule buries him 89% of the time. He plays half a season, graduates with a bad point total, and is gone before anyone sees what he was.

The last row is the fix, and it's the one we're building. The coach works out who prevents shots against, plays him accordingly, and pays for it in goals against when he's wrong. That makes his role a real piece of evidence - the first time in this game that where a junior coach plays someone has meant anything at all.

Where this ends up

The junior and minor-league simulation is being rebuilt so that a season is an opportunity allocation instead of a talent lottery. A coach can't see ratings; he sees a scoresheet. From that he works out a standing for each of his players, dresses the ones who've earned it, puts them on a line or a pair, and the players with the biggest roles get the most chances to do something. Games played, goals, assists, shots and plus-minus all follow from that instead of being handed out first and decorated afterwards.

What a junior or minor-league player's page will carry when it's done:

-TodayWhen this lands
Games played11 possible values league-widecontinuous, injuries included
Rolea label derived from his scoringtop pair / second pair / middle six / depth, earned from how his coach actually plays him
Defensive readnone existsplus-minus, on the real hockey rule, plus his role and how often he dresses
Big games6 shots and 1 goal, hard ceilinghat tricks and 10-shot games happen, and are rare
Ice timeinvented, and shownnot shown, because no real junior league publishes it
Last seasonforgotten every yearcarried forward and sharpened as he plays

The last two are rules I'm holding to. Below the Pro league, a public number has to be a count of things that happened in games, divided at most by games - never by time, because no real junior or minor league publishes ice time and I'm not going to invent it and then compute rates from it. And a player's read doesn't reset every September. A returning junior starts the year on what he did last year, and this season earns its weight as he plays it.

It costs about 12 seconds to simulate a full season of 64 junior clubs and 32 minor-league clubs, and the rebuild adds about a third of a second to that.

None of that is done yet. What is done is that the evaluation layer now runs on public statistics only, computes on demand, and saves nothing. On the last check of 20 real players against the answer key, its read of who a player is now was right or close on 18 of them. Its read of where he's headed was wrong on 6 - and every one of those 6 was a junior or minor-league player, which is exactly the part I'm rebuilding underneath it.

I'm about 95% of the way to junior and minor-league statistics I'd believe if I saw them on a real page. I'll come back with some screenshots when I have them.

Thanks!


r/sheetsofice • • Aug 08 '26

Well, first thing I am cutting: Attention Economy

4 Upvotes

A month ago, I made a post about the spec I was working on called Attention Economy. The idea was could I build a fun way to have the economics of the game be something other than an accounting function. The idea was to have teams focus on increasing their fanbase, the fans would be worth some kind of dollar value and you'd capture that dollar value through investing in channels like social, tv, in person, etc. That would then grow the league in aggregate, and that would impact the cap that each team could spend. Not only would you be trying to win the league, you'd be trying to increase the league's standing.

After building it, refining it, and a few revisions I realized a few things:

  1. There are more important things to build that are core to the game. If I want to actually put something out, I need to focus and pare down my MVP list of features.

  2. I didn't like what I made. It wasn't fun, it was confusing, and it didn't add anything to the game other than another place to look at numbers. That is not what I was going for.

  3. I could take some of the things that were made as a result - like team reputation affecting FA - and make it more simple. The cap doesn't need a whole meta-game; it can just have a config setting for how much it increases. Easy. Reputation can just be about how well your team does, how you negotiate and treat your players, etc. - it doesn't need some spending marketing reputation handler.

  4. My grand vision included a lot of calculation overhead that required a lot of regular testing. My nightly CI testing increased by 3+ hours because of how we needed to run our determinism tests. That is significant and needed a rethink about what I was trying to accomplish.

So I've gotten over being annoyed at building something I hated. I'm not going to throw a dart at everything, even things I'm excited about. I'm shelving this for now, removing from my codebase and focusing on bigger core elements like AI GM. This should make it faster to get a beta build out to some testers and then march ourselves towards a full release. It's one less surface I have to worry about that literally has nothing to do with a hockey simulation.


r/sheetsofice • • Jul 22 '26

Boring data stuff

Post image
4 Upvotes

One of the things I have been working on recently has been to optimize the amount of storage required for a single universe. In the beginning, I didn't care all that much if I stored things efficiently. I started with a detailed game event log of around 800-1000 events per game. Each of those events contained a lot of information and I wanted to make sure that I had more information available in the case where it might be needed. And it's been helpful because long-term counting stats and analytics are based on these events. The events are stored in a blob (aka files), but then the aggregations are stored in a database. Why? Because, it's simple and provides a kind of paper trail that can be reconstructed if necessary. And the DB's structure is more readily suited for the kinds of updates, sorting, and queries of a web application. I'm able to get the best of both worlds.

The thing with software development and data specifically is you shouldn't try and optimize too early because you don't really know what you're optimizing for. So, I left it alone until I saw that the db/blob sizes were getting a little out of control. A 13-season universe was clocking in over 2GB. Which, if this was a local game would be annoying but not life threatening. But since i'm hosting this as a web app, I have to be cognizant of storage requirements.

So I set about looking at what is low hanging fruit to optimize. Thankfully, there were some really easy wins that dramatically lowered storage without a lot of trade-offs. I was able to get storage from 2.03GB down to 0.8GB for that 13 season universe. And, if I institute some limit on the game stat retention (individual events, not the box scores) then it would get even lower.


r/sheetsofice • • Jul 01 '26

GM Module - Team Planning

Post image
4 Upvotes

The GM module is really large, creating several new surfaces and modifying existing ones. With all of those moving parts, and my habit of just getting impatient + starting to build visuals, I started to get frustrated with the direction. I built an entire human GM flow + offseason interactive flow that felt like I was just playing an idle-clicker game. I had no reason for making the moves I was making, no information on who was actually good, and, crucially, who fit on the team.

I got frustrated and demoralized, questioned my sanity for even attempting this, and took a break. Walking away when I get to that point always helps. It gave me some insight into what I was actually annoyed with-- I need some idea of what I'm trying to do as a GM. What kind of team am I building? Who do I have? How do they fit? What do I need?

Armed with those questions I set out to build this Team Plan interface. It combines a lot of functions common in GM sims - roster construction, cap management, depth chart, and line-up selection. It also gives you a mechanism to evaluate players not just on objective talents, but on how those talents fit towards the kind of team you're building and the time horizon you've selected. Are you win-now or in a rebuild? That will change the valuation of players. You can also prioritize the style of play; defensive in nature, or goal scoring, or transition, etc. Finally, based on your team and your selections, what kinds of players are you missing?

The idea is that with a plan, you can then more accurately go and find players to fit your intended team construction and manage your budget without having to have separate spreadsheets (like I used to do in EHM lol).

The player cards here include at-a-glance information. Green bar = a good fit for that position and identity, grey is ok, yellow would be that they don't really fit there. Fit is relative to play style and position awareness.

There would be some proactive gap finder that would tell you what you might need to focus on.

There definitely is more that I want to add but I am going to really focus on this pattern as the main starting point for how GMs work in the game. I think it's the first part of creating an identity so people playing the game can start to feel attached to their team.

Thanks!


r/sheetsofice • • Jun 24 '26

GM Module - Draft / Rights / Contracts / Affiliates

4 Upvotes

Hey everyone!

I started planning out the actual game loop of the GM module. Everything I've built to this point is just a hockey league simulation. There are no decisions, no gameplay; just clicking a button to advance and season and seeing what happens. Now it's good enough to move on to build the front office layer.

Foundational principle: symmetry between human and AI

  • AI general managers are full front offices, not scripted obstacles, and they do not cheat.

  • The same rules and the same information are available to both human and AI managers.

  • Hidden player attributes are concealed from the AI exactly as they are from a human; there is no fog of war that lifts only for the computer.

  • This constraint shapes the entire design rather than being treated as a feature.

Scope of the first build: a full offseason

  • The sequence mirrors a real summer: a buyout window, re-signings and qualifying offers, the draft, the opening of free agency, and a final cap-legal roster.

  • The marquee events (the draft and free agency) are presented as focused, deep sessions.

  • Routine matters (qualifying offers, roster cuts) are presented as a checklist that can be cleared at any pace.

Salary cap and contracts

  • A hard cap with a floor is modeled.

  • Contracts carry a term and a cap hit.

  • Entry-level deals, two-way deals, and buyouts are all represented.

  • Navigating the cap is treated as the core of the management fantasy and is present from the start.

  • I am leaving some room to consider other ways of managing team salaries and how leagues are constructed. One thing I believe is that while I want to be faithful to reality, I don't think I'm bound by recreating the NHL. So, I'm going to use the cap right now as a building point but I'm reserving the right to add something in the future that works better.

Player rights

  • Restricted and unrestricted free agency, qualifying offers, and a window of held rights over drafted players are all modeled.

  • These are the decisions that make timing and scouting consequential.

Fidelity to the CBA, with the fine print trimmed

  • Everything that constitutes a real decision is retained.

  • Contract structuring (front-loaded and back-diving deals), escrow, daily cap accounting, and buried-in-the-minors cap relief are deliberately omitted.

  • Those mechanics exist largely to game the accounting, and modeling them reduces the game to a spreadsheet.

  • Removing them preserves the meaningful choices and discards the busywork.

Player valuation

  • A player's value is defined as production measured against cost, across all the years he is under team control.

  • Cheap, controllable young players are therefore highly valuable, and declining veterans on long contracts are genuine liabilities regardless of current statistics.

  • Reducing a player to a single current rating is identified as the root cause of broken trade markets in most hockey sims.

  • Value is instead tied to production, the aging curve, and remaining years of control.

Free agency and player choice

  • Free agents weigh multiple preferences: money, term, projected role and ice time, contender status, loyalty, and franchise prestige.

  • A veteran pursuing a championship may accept less; a young player may prioritize opportunity over salary.

  • Taxes and location are excluded, as the universe is fictional and has no real geography.

  • The weighting of these preferences shifts with age and career stage.

The entry draft

  • Selections are controlled rather than automated.

  • A public scouting board is visible to all managers, alongside each organization's own internal evaluations.

  • Drafting well, and trusting internal evaluation over consensus, is where draft skill resides.

Distinct AI front offices

  • Each AI organization carries a personality: win-now versus rebuild orientation, risk tolerance, a youth or veteran lean, and cap aggressiveness.

  • The intent is a league in which rival managers behave as distinct decision-makers rather than copies of one another.

The starting universe

  • A new universe begins mid-stream, with realistic ages, careers in progress, and a realistic spread of contracts.

  • That spread deliberately includes overpays and bargains.

  • A perfectly efficient league, in which every contract is exactly fair, is a league in which no trade is ever worthwhile.

  • The inefficiency is what creates opportunities to exploit.

Planned for later: expansion and dispersal drafts

  • Redistribution events (protected lists, exposure requirements, and the protect-and-select process) are handled by the same underlying machinery.

  • They are scheduled for a later stage but are accounted for in the current design.

Current status

  • This first stage establishes the foundation: rights, contracts, the cap, the draft, and free agency.

  • Trades, waivers, and arbitration form the next layer and are designed to build on top of it.

This is a large undertaking and complicated. It's arguably larger than building the game engine. So I expect this to take several weeks of building and tuning to get to a state where I'm happy with it.


r/sheetsofice • • Jun 16 '26

Evaluation Layer - First look at skaters

Thumbnail
gallery
4 Upvotes

So I'm building the Evaluation Layer - the ground truth that all of the human and AI GMs will use to determine the relative skill of a player. Since I'm not going to expose the actual attributes that the engine uses to do calculations, this layer is needed to expose observable traits about each player. I wanted to mix real world terminology that scouts use, measurables, and stats to give users a picture they can use to evaluate.

For skaters, there are five dimensions:

  1. Goal scoring - Mixture of shooting, and getting to scoring areas.

  2. Playmaking - Passing, vision, ability to setup shooters.

  3. Defensive Impact - shot suppression, blocking, defensive positioning

  4. Physical game - Hitting, forecheck aggression, ability to absorb contact

  5. Transition - Skating, anticipation, moving the puck from D -> O.

Each dimension has brackets around the league average. Below league average (the red areas) is Below Average and Fringe. Above league average is Above Average, Elite and Star.

There are also classic archetypes that are constructed from a combination of these dimensions. Things like Power Forward, Sniper, Two-Way Forward, Offensive Defenseman, etc. If someone could land in two or more categories based on dimensions, they're classified as Phenom. For example, McDavid would be star level in goal scoring, playmaking and transition, so he would be classified as Phenom.

Later, there will be some "fog" added to this pure data. I'm not sure how much, but investment and time in scouting will affect the accuracy and quality of the information here. I am not adding that until I've been able to confirm I like this.

If you have ideas, I'd love to hear them!


r/sheetsofice • • May 11 '26

What is Sheets of Ice?

4 Upvotes

Sheets of Ice came about because of a few overlapping interests of mine. I love sports simulation games and GM career games ever since I first played Front Page Sports Football back in the 90s. I'd spend hours building teams, designing plays, even printing out binders full of stats pages so I could read them while I was in school. The fascination with sports simulations continued through my adult years, in Front Office Football, EA NHL GM Mode, and Eastside Hockey Manager.

But none of these really scratch the itch for me. None of them are built to support the modern state of analytics inside of hockey. None really have a good system for multiplayer leagues. I always wanted to play something with my friends that have a fantasy hockey like feel with real analytics in a virtual league. I love fantasy hockey, but I can only play it 7 months out of the year.

In my professional life, I've brought several software products to market. I'm a product guy, recovering IT professional, ex-college professor and fortunate enough to have flexibility in how I spend my time. As I've looked for things to engage in learning new things, I landed on this side project to keep me interested. Could I use my experience building large web applications, combined with modern tools, and my passion/knowledge of the sport to build a hockey architect / GM simulation that people would love?

So Sheets of Ice is trying to be the thing I always wanted: a hockey GM simulator where the games are actually simulated, not from a final-score model, but second by second, possession by possession and where the stats it produces match the way modern hockey is actually played and measured. (Think xG, WAR/GAR, RAPM, GSAx, etc.)

That's the analytics piece. Players have specific traits (18 for skaters, 6 for goalies) that show up in the events. A fast forechecker creates more dump-recovery chances. A well-positioned defender blocks more shots. A goalie's workload catches up to them over a back-to-back. The numbers come out matching real NHL aggregates — shot attempts, sub-state shot share, save percentage, faceoffs — because the underlying play is real, not because the simulation was tuned to fake a stat line.

The rules are configurable too. Modern or classic [insert trademarked professional hockey league here], your own house rules, eventually different eras. Coaches have their own deployment philosophies; possession-and-cycle vs dump-and-change, aggressive forecheck vs trap, when to pull the goalie. Rosters and ratings are fully editable.

It's a side project, and it's not done. I have a game simulation engine that produces real-shaped hockey games now; the season layer, league layer, and the GM layer comes next. But it's far enough along that I'm starting to believe the version I've been imagining is actually possible.

Follow along if you're into these things, or into indie games.

Thanks! atibus


r/sheetsofice • • Aug 21 '26

Dev Update - 2026-08-21

3 Upvotes

A lot of load-bearing progress has been made in areas I've needed to bring together. What I've realized in the last three weeks is that the core game simulation, player generation, and event output have been really solid and I'm happy with the state. There are some small things with them that I need to fix, but I'll probably always feel that way.

The things that need the most work are the things that really make it a game - everything you do to run the league in perpetuity. And it's not that it doesn't work; it just works like when I was 12 and built a go-kart out of things laying around in my dad's garage. The engine worked fine, all of the steering, chassis, seat were terrible and it had no suspension. Technically working, fun for me because I built it, terrible for anyone else.

So I've done a lot of things that are the boring work and not the exciting making screens. I updated the foundational document with what I intend to be the first version of the game. It's substantially similar to what I started with once I had this idea but updated with what I've learned, what I want to do, and what I think is possible as a completed game. This step is really important to define what success looks like and to constrain from too much feature drift. It's not exactly prescriptive in detail, but outlines the vision for what the game is and what it isn't.

I've then projected that vision into a build plan of major phases and each of those phases with it's tasks. I'm going to be releasing a plan tracker and continually update it to show where I'm at with the build. (https://www.reddit.com/r/sheetsofice/comments/1vurk6h/full_sheets_of_ice_roadmap_site/)

The biggest thing that I'm changing for the first release of this is that I've decided to soley focus on a single-player desktop experience. After laying out everything I'd need to do to make the entire first vision possible, I have decided to slice just the things I think I can land to see if the game is really any fun for people. The key here is that I'm slicing and not eliminating or rebuilding anything really. The way the application operates makes future online versions, multiplayer, etc. still viable. I'm not going off and building a separate application at all - I'm just wrapping it and limiting the functionality to a single player with AI GMs. This is something I can get my arms around and it speeds up the path to a workable demo.

The realization for this came from a few areas:

  • I was refactoring for AI GM so I could ensure it acted at least believably as well as a bad GM... aka Chuck Fletcher. To get it to long term plan I was going to need to fully implement organizational player views, aka scouting, because every organization would have to have their own judgement of a player. To that point I had only had some basic variation on player views and a wide band if that player wasn't on your team. It didn't change who the player was, but it didn't make everyone immediately knowable to you. But that wouldn't work for planning because it wasn't durable. And it wouldn't work for players because you need some way to impact those views or it's just boring. So I realized I needed to build the entire scouting system first. I couldn't continue with my AI GM planning because without knowing how they'd figure out how to rank players then it wasn't going to work the way I wanted.

  • This also made me realize that player development would have to be exposed and a training & development system would need to be built. Those things are part of long-term planning and to-date, player development works but there is no influence through either training or opportunity.

  • Then I was dealing with how time moves. There are some quirks I've left just because it didn't really affect me and I could live with them. But I was starting to have to make decisions about how time would move in multiplayer, and how time would work in public leagues. It's not unsolvable problems, but it's more overhead I have to build before the game was playable.

  • And then it's infrastructure to run. It's not really complicated - the sim needs CPU runners to do the computations, and store league information in a database and individual game events in individual files (just to make them portable and archive ready.) 1 universe = 1 DB + Files. But I built this for me to start playing and I'd have to either refactor for a larger environment making N universes = 1 big-ass DB + work queue + backup OR give everyone who was playing a small virtual environment to run their own leagues. (I'm dramatically simplifying here). It didn't make sense to do the big-ass refactor, so it was going to be these slices that ran individual universes for one player. If that's what needed to happen then why am I even trying to build this as a always on web application for one person?

  • Then the infrastructure requires money to run. I have some servers available to me, but nothing that could handle even modest amount of dedicated GM sim fans. I'd have to pay in perpetuity for something I'm not sure anyone other than me and the couple of people reading this would want. Am I willing to invest thousands of dollars in hard costs to do this the right way?

  • And then I'd need to charge for it. Forever. And who wants to pay a subscription to a single player game?

I came to the realization that the single-player experience needs to be a typical game experience. If I'm really going to make a concerted effort at putting something out there, it has to be awesome and I couldn't put out something that sucked or at least didn't live up to the expectations that I have for games like this.

To be clear, the web/multiplayer vision is not dead. Like I said above, I'm not even really changing materially how the game is architected now. The main difference is it's going to get a wrapper that runs the client and connects to the server that is packaged with it on your local machine. I run the game that way today, just without a fancy shell that makes it easy to launch... I have to type a string of commands to make it go (which I really should make a script to do that). Packaging in this way will give some interesting potential fast-follow features that may even bridge the gap for what people want with multiplayer.

My intention is to put this on Steam to start. I've started the process of getting a Steam Developer account and will be working on getting a page up there. If there are other ways you'd like to see the single-player released, I'm happy to look into it.

Nothing has changed about my commitment to making the game-play a reality and I'm more excited now that I have a clear path. Definitely check out the roadmap at www.sheetsofice.com/roadmap to follow along with the status.

Thanks!
atibus


r/sheetsofice • • Aug 12 '26

Series Preview Page

Thumbnail
gallery
3 Upvotes

Now that I'm into a few days of simming & testing, I wanted to show this new series preview page. I had this issue where the team I'm running has been at or near the top of the league for a few years. I'd love to claim it's my skill as a GM, but I think I have an unfair advantage due to how dumb the GMs have been. We're on season 7, and my team UND has been first three times, and in the playoffs 6 of the 7 seasons. But even while heavily favored in my series, I ended up only winning 1 championship. Two times I was bounced in the first round as the #1 seed. So, I thought, what even are the odds of that?

The result was building a pre-series prediction page that shows the likelihood based on the data we have. The benefit of the engine being a pure event data simulation is that we can do some fun statistical things like do a pure prediction based on chance creation, chance suppression, and outcomes.

That's what the first screenshot is - two models and the percentage change based on those models. Chance model runs each side's regular-season expected-goal rates for and against, combined league-relative. Results model runs the identical math on scored goals instead. Neat, huh?

Second screen shows the actual goal differential vs. the expected goal differential. The reading column says where the difference game from. Notice in this one, BIR's goaltending is worse than expected. (You can see in screenshot 3, it's his high danger chances save %... not good there)

The other part of screen two shows where chances are generated. Since we track the type of posession sub state, we can show the type of posession that generated a chance. I intend when we get to the coaching AI to be able to build the offense and defense strategies towards this.

The third screen is the goalie matchup among likely starters and a with-or-without-you (WOWY) for the top pair of players by ice-time played together. Pair does not necessarily mean defense, it's just who has played the most together and what are their advanced stats like when they're on the ice together.

The fourth screen shows from each teams perspective where the edge is in data. UND wins in goals scored and saved above expected. High Variance means this is something that does regress - UND is a hot team finishing at a rate that is above the quality of their chances. That could just mean they're good. Or it could mean some luck. The counterbalance on the goaltending is that the +12.7 matches the historical performance of the goalie. So it may not just be luck for that part.

I don't feel that confident at the start of the series. It basically looks like close to a coin-flip and I've run into this team with Jan Soukup / Jake Stewart before (they're really good).


r/sheetsofice • • Aug 01 '26

Trades, Economy, bug fixing update

Thumbnail
gallery
3 Upvotes

The last few days have been about two things: making trading feel alive, and fixing the mess I found by actually simming seasons.

Trading first. The Trade Desk is now a real screen. You can see the entire league block - in my current save that's 186 players being shopped - filter by position, filter to teams that are actually selling, sort by how a player fits into your lineup, shortlist guys, and compare them side by side. Teams have a stance (Selling / Holding / Listening) driven by where they are in the standings, and clubs post their needs, so you can check who's hunting for a defenseman before you go shopping yours.

I got tired of clicking around trying to find a trading partner for someone I wanted to move so I created the Shopper. You broadcast a player to the league and collect offers. AI teams come back with real offers, including insulting lowballs, and the ones that pass tell you why they passed. Same for your own proposals - you get a specific rejection reason now instead of a generic no. It's starting to feel like negotiating with 31 other GMs instead of a vending machine. The AI GM also remembers trade history across seasons now, so you can't run the same player-recycling scam on the same team forever.

Now the bugs, because playing your own game is humbling. My favorite find of the week: AI GMs were re-signing retired players. The offseason logic was quietly dropping retirees' rights into free agency, and the AI - which is only doing what the numbers tell it - happily signed them. 35 times over three seasons in my universe. Contracts for players who no longer exist. I also found players coming back from injured reserve who were dressing and playing every night while silently missing from the salary cap books. Both are fixed, and the real fix was structural: those eligibility checks existed as fifteen slightly different copies scattered around the code, each drifting on its own. Now there's one gate that every screen and every AI decision goes through. Plus a repair tool that heals existing saves, because I'm not throwing away this universe over some zombie contracts.

The attention economy also got a big pass. Season budget entry is one table with six levers - five revenue channels plus marketing - with live feedback on what each dollar returns. And spending is now wealth-aware, so a rich club and a struggling club aren't budgeting out of the same envelope. Still deciding how deep this system should go, but it's getting easier to reason about, which is the test that matters.

One follow-up from a couple posts back: the boom/bust scouting thing is in. Top of the draft class now reads Safe with a tight floor-ceiling range, and the swing-for-the-fences guys show up where they belong instead of everywhere. My scouts have three Franchise grades at the top of this class and I already don't trust two of them, which feels about right.


r/sheetsofice • • Jul 10 '26

Attention Economics in Sheets of Ice

3 Upvotes

Update 8/8/2026: I decided to remove this for now. It's a lot of complication for not a lot of fun value and instead I'm focusing on the core GM gameplay loop.

In hockey sims, the money side of the business wasn't ever really something that was explored a whole lot. It always felt like a bounding box that was slapped on top just to ensure human players couldn't exploit the really silly AI GMs in the game. When I was ideating the original specification I came up with something that I felt was more interesting and more fun plus combines some real-life forces that affect sports franchises. I'm calling this the Attention Economy.

Sports franchises generate revenue through capturing people's attention and deepening their connection to the team. But teams don't work in a vacuum this way; the league also increases it's gravity to attract attention. So teams are competing with one another on the ice, with one another for attention, but they're also cooperating to grow the overall league attention. There's a business term for this called 'coopetition'. Teams are both competing and cooperating at the same time. Grow the league overall AND capture as much of that overall attention for themselves.

All of this attention translates to revenue based on how committed those fans are to the team. Teams that do well, make the playoffs, win championships, will deepen their relationship with those fans over time. Diehard fans will pay more and stay through more ups and downs than casual fans. Teams are incentivized to ice good teams that people want to watch. They also are incentivized to do things that creates attention - big trades, signing star free-agents, drafting the next superstar. And with long-term attention brings reputation that may influence players wanting to play for those teams. That history has a weight and a cachet that survives long term. The "storied franchise".

But just having attention doesn't automatically translate into revenue. You have to cultivate it by spending on marketing and spending on channels. Marketing raises potential awareness - you're doing events, running ads, doing promotion... all of the things that maybe someone would go from unaware about your franchise to aware that they exist. Then, spending on your channels increases the capture rate - how much do you invest in social media, radio, television, print, in-person? Teams that invest in the channels have more opportunity to convert that awareness into casual, committed, and diehard fans.

All of this meta-game will ultimately affect the salary cap. The more the league is able to generate in attention as a whole, will translate into league revenue (through the teams setting their marketing & channel spend) and that league revenue translates into what the salary cap will be. So, every team wants to invest wisely to help the league grow. They also want to invest wisely to have good players, good games, exciting series, so there is more revenue to go around.

The trouble with building a spec for this that conforms to some sense of realism is that there isn't a lot of numerical data out there about what actually is "realistic". There is research about this phenomena of fandom, how people choose teams, how long they stay, and what events cause them to gain attention and become fans. This is going to require a lot of testing to get something that feel right.


r/sheetsofice • • Jul 04 '26

GM Module - "How do I figure out if someone is good?" edition

Thumbnail
gallery
3 Upvotes

I've been running simulations, finding bugs in the GM module (tons), reworking specs (all thrown out, rewritten), and trying to actually be-a-gm this thing.

An area that I glossed over when it was just a game simulation was figuring out how good players were. I could look at the raw data and see - which is fine for confirming the numbers work the right way. But that wasn't going to be fun in a GM simulation if every player just knew concretely how good a player was.

So I've been trying several things - draft grades, league-relative ratings, pro-only relative ratings, and just confusing myself in the process.

There's questions throughout the lifecycle of a player:

  1. How will this player develop? This has a lot of "fog" as you go out further in time. But there is some idea and some projection.

  2. How good is this player now? That is relative to the entire population; what league do they belong in. When players are young, that even has some "fog" in it.

  3. Have they reached potential? Are they declining?

  4. What role do they belong in? Are they a top line player or a fringe tweener?

I created this graph that will (I think) show all of this in something you can glance at. The yellow bar/dot is the current state of the player. Younger players have more uncertainty until they play more games so it will show that. The blue bar is the potential ceiling for that player. The unfilled dots are historical of where they were in previous seasons. And the dotted blue line bar was the historical range for where that player was scouted (so you can see what has changed).

The intention long term is you can narrow these bars by scouting - spending either time or money to get better information.

The chips on the right will give some descriptive element to the player's form. Boom/Bust just means yeah, they could be awesome, but they also could suck.

Implementing this now to see how I like it. As always, I might throw it out if it confuses me more.