Roster Relay has a rule that I thought was going to be extremely simple:
Two players are connected if they appeared for the same franchise in the same season.
That's it.
No advanced stats.
No subjective judgment.
No committee meeting.
Either the two guys were on the same team that year or they weren't.
This seemed like one of the easier parts of building the game.
Then I started working with actual sports data.
“Same team” immediately needs a definition
Let's say two football players were both Raiders.
Great.
Except one played for the Oakland Raiders and another played for the Las Vegas Raiders.
Same franchise?
For Roster Relay, yes.
The Rams create the same question.
St. Louis Rams. Los Angeles Rams.
Same franchise.
The Seattle SuperSonics becoming the Oklahoma City Thunder is another example where the city and name change, but the underlying franchise history continues.
So the actual rule isn't quite:
Did the jerseys have the same words on them?
It's closer to:
Did these players appear for the same underlying franchise during the same qualifying season?
That requires the data to know which historical team identities belong together.
Otherwise you get a game where two players really do belong to the same franchise history, but the computer says:
Never teammates.
There is very little more irritating in a trivia game than knowing you're right and having the game confidently tell you you're wrong.
Then there is the small matter of what a “season” is
Baseball is relatively cooperative here.
The 2014 MLB season happened in 2014.
Thank you, baseball.
Basketball decided to make things more interesting.
An NBA season might be 2014–15.
So if two players were teammates during that season, what exactly do I store?
2014?
2015?
“2014–15”?
And how should I show it to a player without making the database and the interface disagree about what year we're talking about?
Roster Relay internally represents the season consistently and then formats it according to the sport. NBA connections get the familiar two-year display, while MLB and NFL use the named calendar season. The team-history display has to follow those same rules so a player's career doesn't suddenly look like it happened a year later than the connection you just made.
This is a small detail.
It is also exactly the kind of small detail that would bother me every single time I saw it wrong.
Trades are where the fun starts
Now imagine a player gets traded during the season.
He appears for Team A.
Then Team B.
Another player spends the entire year with Team B.
Were they teammates?
If they both actually appeared for Team B during that season, yes.
That's the rule.
Roster Relay isn't trying to determine whether they were best friends, whether their lockers were next to each other, or whether they were simultaneously on the active roster for a particular Tuesday road trip.
It needs a consistent, verifiable game definition.
So the shared franchise-season is what counts.
That means a player can have multiple qualifying team-seasons in the same year.
It also means some connections look strange until the game reveals the team and season and you think:
Oh right. He was there for like two months.
Those are some of my favorite sports-memory moments.
A player can be connected in more than one way
Here's another thing I hadn't thought much about before building the game.
Two players might have shared multiple team-seasons.
Maybe they were teammates for several years.
Maybe their careers overlapped on more than one franchise.
So when the game asks:
How are these two connected?
there isn't necessarily one answer.
The validation system can return multiple shared team-seasons when they exist. The scoring logic then needs to decide which connection the route is actually using, especially because repeated use of the same team-season affects Links and Rarity differently under the anti-padding rules.
This is where a rule that sounded binary starts turning into:
Yes, they were teammates. Actually, they were teammates three different times. Now please determine which of those relationships matters for this particular path.
Sports are very considerate this way.
The game's version of history needs to be consistent
Sports fans are also very good at arguing about edge cases.
Was someone “on the team” if he appeared in one game?
What about postseason only?
What about someone who was signed but never appeared?
What if he was on an injured list?
What about a practice squad?
What about a two-way contract?
You could build increasingly complicated definitions forever.
I don't want Roster Relay to require a law degree.
The game needs a rule that is understandable and that can be applied consistently across thousands of players.
So the basic standard is based on the roster records the game actually uses: if the data shows both players appearing for the same franchise in the same season under that league's dataset, the connection counts.
That's why I describe it as a game rule, not the one true philosophical definition of “teammate.”
Sports databases themselves can disagree around transactions, roster status and historical naming. The important thing is that Roster Relay applies its rule consistently and shows the player the shared team-season when a link is accepted.
If something still looks wrong, I want people to tell me.
I have learned not to underestimate the ability of sports fans to notice one weird roster row from 2006.
The player search has its own version of this problem
Names seem easier than franchises.
They're not.
There are players with the same name.
There are punctuation differences.
Suffixes.
Accents.
Hyphens.
Nicknames.
Names that look almost identical when normalized for search.
And the game needs to make it easy enough that somebody can type the name they remember without needing to know exactly how the underlying dataset stores it.
The current search prioritizes exact and prefix matches before looser substring matches, because autocomplete that technically contains the correct player somewhere near the bottom is not especially helpful when you're trying to make a quick move.
Again, none of this is the interesting part of the game.
That's why it needs to work.
The interesting part is remembering the player.
The interface should get out of the way.
Headshots matter more than I expected too
This is less of a data-validity problem and more of a sports-memory thing.
I really like having the players' faces appear when you add them to the route.
A name might make you think:
I vaguely remember him.
Then the headshot appears and suddenly:
OH, that guy.
That visual recognition is part of the payoff.
It's one reason I care about making Roster Relay feel more like a collection of player cards than a database query with a scoreboard attached.
Of course, headshots introduce their own annoyances.
Different leagues have different image sources.
Older players may have missing images.
Data can be incomplete.
URLs change.
There is apparently no aspect of sports data that looks at a simple requirement and says:
Sure, I'll just work forever.
And then the computer has to verify your route
When you type a player during Roster Relay, the game can't simply trust the browser.
Otherwise somebody could tell it:
Yes, Paul Skenes and Yogi Berra were definitely teammates.
and award themselves a tremendous route.
The server validates each connection against the underlying roster records.
For submitted results, the current implementation also verifies the endpoints and teammate edges and derives the scoring information on the server rather than simply accepting whatever numbers the browser sends.
That is another thing that probably sounds like excessive engineering for a game about remembering athletes.
It is.
But if you're going to show community statistics and compare people's routes, the results should at least represent routes the game itself considers valid.
Otherwise the “average Links” number eventually becomes the average of legitimate players plus somebody who discovered the developer console.
Some messiness is actually the best part
The funny thing is that a lot of these edge cases are annoying to build around but great for the game.
A trade that makes the data harder to model can create an excellent connection.
A forgotten one-year stint can unlock an entire route.
A franchise relocation can bridge two generations of fans.
A player you mentally associate with one team may turn out to have spent six weeks somewhere else, and that six-week stop is exactly what gets you to the finish.
Those are the moments where Roster Relay works best for me.
It's not just:
Do you know this player's career?
It's:
Do you remember the strange corners of this player's career?
Sports history is full of those corners.
That's also why I don't want the game correcting reality into something cleaner
It would be tempting to simplify the data.
Only count the team a player is most associated with.
Ignore short stints.
Drop weird partial seasons.
Maybe require some minimum number of games.
That would make parts of the system easier.
It would also remove a lot of what makes the game fun.
If a guy really played there, I generally want that stint available.
The fact that everybody forgot about it is not a bug.
That may be the whole point.
The difficult part is making sure the forgotten stint is real.
The rule still has to be understandable
This is something I keep coming back to when building games.
You can have incredibly sophisticated machinery underneath a rule that should take one sentence to explain.
That's good.
The player should not need to understand franchise-normalization tables, season-formatting logic, network graphs or server-side route validation.
They need to understand:
Same franchise. Same season. That's a link.
Everything underneath exists to make that simple sentence behave the way a reasonable player expects it to behave.
Because if the game says two people weren't teammates when you know they were, you don't care how elegant the backend is.
You think the game is broken.
And you're probably not coming back tomorrow to see whether I fixed my franchise IDs.
Sports data is messy, but at least there is a lot of it
I should give sports some credit.
This data can be frustrating, but professional sports also have an enormous amount of historical information available.
People care deeply about rosters, statistics, transactions, awards, games played and almost every other measurable part of sports history.
That makes a game like Roster Relay possible.
The challenge is taking all of those records, which were not created specifically so I could build a daily teammate-chain game, and turning them into one consistent set of rules.
Sometimes that means normalizing franchises.
Sometimes it means making three sports agree on what a season label looks like.
Sometimes it means figuring out which shared roster a connection should use.
And sometimes it means staring at a player and thinking:
There is absolutely no way he played for them.
Then looking it up.
And realizing:
Oh yeah. He did.
Which, really, is the whole game.