Pennant Games Documentation

Pennant Games is a basketball simulation game. Build your own players and teams, play exhibitions and full-season leagues with friends, and enter salary-cap competitions.


Getting Started

Pennant Games is currently in early access. There are three ways to play, each suited to a different level of commitment:

  • Competitions — free-to-play salary-cap challenges. No account required. The fastest way to try the game.
  • Exhibition games — pick any players, build two rosters, and simulate a game or series. Sign in to save lineups.
  • Leagues — create or join a league. Draft players, manage your roster, trade, and compete through a full season with playoffs and awards.

Create an account with your email to access exhibitions and leagues. If registration is closed, you can request an invite from the signup page. Once you're in, the first thing to do is build your team: create a few custom players, allocate stars and attribute points under your team's shared budget, and you're ready to enter exhibitions or join a league.

Exhibition Games

Exhibitions let you simulate games without being in a league. This is the fastest way to see the engine in action. Go to Play → Exhibition in the nav bar.

Game Modes

  • 5v5 — full team basketball with substitutions, coaching, and regulation quarters. Standard NBA-style game.
  • 3v3 — half-court three-on-three. Played to a target score (11 or 21), 1s and 2s scoring, no free throws. Higher turnover rate, more interior play.
  • 1v1 — half-court one-on-one. Pure ISO scoring — no assists, no chemistry. Highest turnover rate. Tests individual skill head-to-head.

3v3 and 1v1 use modified tuning: no home court advantage, no free throws (fouls change possession), faster possessions, and win-by-2 rule.

Building a Roster

For 5v5, each side needs at least 5 players (max 15). For 3v3, pick 3 players per side. For 1v1, pick 1 player per side. Use the search bar and filters to find players:

  • Search by name — type any part of a player's name
  • Filter by type — Custom, Virtual
  • Filter by position — PG, SG, SF, PF, C
  • Filter by star rating — exact star level (5, 4, 3, 2, 1)
  • Random fill — auto-populates a roster from filtered results

Selecting Starters

For 5v5, once you have 5 or more players, checkboxes appear next to each player name. Select exactly 5 to set your starting lineup. If you don't pick starters, the engine auto-selects the best player at each position by star rating.

Series Play

Choose between a single game or a best-of-3, 5, or 7 series. In a series:

  • Home court alternates using the 2-2-1-1-1 format (games 1-2 home, 3-4 away, 5 home, 6 away, 7 home)
  • Each game gets its own box score, shot chart, play-by-play, and AI recap
  • A game selector lets you switch between games in the series
  • After the series, a Three Stars section shows the top 3 performers by total Game Score
  • A Series Averages table shows per-game stats (including MPG) for every player across the series

Saving Teams

Save your favorite lineups as named exhibition teams. Saved teams appear on your dashboard with links to team detail pages. You can also delete saved teams you no longer need.

Competitions

Competitions are free-to-play challenges where you build a lineup under constraints and try to beat a preset opponent team. No account required to play — guests get a limited number of attempts, and signing in unlocks more.

How It Works

  1. Browse active competitions at /compete
  2. Select a competition — you’ll see the opponent lineup, the rules (salary cap, game mode, player restrictions), and the available player pool
  3. Build your lineup by picking players from the table. Each player has a salary based on their skill level (OVR 50 = $2, OVR 96 = $48). Stay under the salary cap.
  4. For 5v5 mode, assign positions to your starters. Optionally select a coaching strategy if the competition enables coaching.
  5. Hit Simulate — the game runs through the full simulation engine and you get a result with box score highlights

Salary System

Player salaries scale linearly from $2 (lowest-rated players) to $48 (highest-rated). This creates meaningful trade-offs: you can load up on one star and fill with budget picks, or build a balanced roster of mid-tier players. The salary cap varies by competition.

Competition Settings

Competitions can be configured with:

  • Game mode — 5v5 (full game with quarters), 3v3 (half-court to 21), or 1v1 (isolation to 11)
  • Era — 5v5 games can use era-specific tuning (1970s through 2020s, or WNBA rules)
  • Salary cap — total salary budget for your lineup
  • Player type restrictions — limit to Custom, Virtual, or any combination
  • Locked player — a required player that must be on your team (bypasses all other restrictions)
  • Block opponent players — prevent users from picking the same players as the opponent
  • Coaching — optionally enable coaching presets for both user and opponent
  • Attempt limits — configurable max attempts for guests and signed-in users

Stats & Leaderboard

Every attempt is recorded. The competition stats section (expandable on the results page) shows total attempts, win rate, average scores, and recent games. Signed-in users can view a “Want a hint?” section showing which players appear most often in winning and losing lineups.

Featured Challenges

The homepage features a “Today’s Challenge” and “Yesterday’s Challenge” (showing the win rate from prior play). These are curated by admins and rotate regularly.

Leagues

Leagues are where you compete with other users over a full season — draft, regular season, trades, playoffs, and awards.

Creating a League

Go to Leagues → Create League and configure:

  • Max teams — how many users can join (2-30)
  • Games per team — regular season length (2-82)
  • Roster size — min and max players per team (8-15)
  • Playoff format — number of qualifying teams, series length (single game, Bo3, Bo5, Bo7)
  • Draft format — snake, linear, or auction
  • Draft rounds — how many rounds
  • Draft timer — seconds per pick before auto-draft kicks in (0 = no timer)
  • Draft player pool — which player types are available (Custom, Virtual)
  • Player type limits — max number of each player type a team can draft (e.g., max 3 legends)
  • Virtual players — allow virtual (NFT) players on rosters, and set how many can be used per game
  • Salary cap — optional cap on total team salary. Pick a currency symbol ($, €, £, ¥, ₩…) and scale label (K/M/B/none) so the number reads naturally for your league. Virtual players only count toward the cap while on the active roster (starters + bench).
  • OVR range — optional min/max OVR. Players outside the range are filtered from the draft pool, free agents, and waivers. Existing rostered players are grandfathered.
  • Allowed countries — restrict the player pool to one or more nationalities. Populated from the actual nationalities present in the player data.
  • Rolling join — when on, new members joining mid-season start in a pending state and are promoted to active at the next season advance. Use for open weekly leagues where anyone can join anytime but only enters the schedule the following week.
  • Trade deadline — block trades after a configurable point in the season

All the settings above are editable after creation under League → Settings. Cap amount, OVR range, and countries are grandfathered — tightening them later affects only future acquisitions, not current rosters.

Joining a League

Users can request to join a league, and the commissioner approves or declines requests. The commissioner can also invite users directly. When joining, you create a new team for that league — pick from 50 prefilled team names or enter your own. Each league has separate teams with separate rosters; the same player can be on different teams in different leagues.

League-Scoped Rosters

Rosters are league-specific. When a player is drafted or signed in League A, they're only on that team in League A. The same player can be drafted by a different team in League B. Trades and free agent signings only affect the league they happen in.

The one exception is virtual players — these are globally owned by wallet holders and can be brought into any league (subject to league rules). Virtual players are NOT available in the draft; they come from wallet claims only.

Season Flow

A full season follows this lifecycle:

  1. Setup — commissioner creates the league, users join and create teams
  2. Draft — snake/linear/auction format, ordered by inverse standings. Auto-GM can draft for teams. Player type limits enforced.
  3. Regular season — round-robin schedule generated automatically. Commissioner can simulate by day, week, month, all season, or up to a specific date.
  4. Standings — wins, losses, win %, games back, streak, last 10, point differential
  5. Trades — propose trades within the league. Both sides must agree. Commissioner can veto. Trade deadline enforced.
  6. Free agency — sign or release players. Free agents are league-specific — a player on a team in League A is still available in League B.
  7. Playoffs — top N teams seeded by record. Bracket with configurable series length.
  8. Awards — MVP, DPOY, ROY, All-NBA First & Second Team, Finals MVP. MVP and All-NBA are selected by WARP with a mild team-wins weighting (0.85 + 0.15 × teamWins / maxWins), so elite players on losing teams don't automatically win over near-peers on contenders. All-NBA uses the same score by position (2 guards, 2 forwards, 1 center per team).
  9. Advance — season ends, pending rolling-league joiners are promoted to active, per-league attribute deltas are computed (pending commissioner approval), new draft order set, next season begins

Simulation Controls

The commissioner controls when games are simulated:

  • One day — simulate all games scheduled for the next game day
  • One week — simulate the next 7 game days
  • One month — simulate the next 30 game days
  • Full season — simulate all remaining scheduled games

Bulk sims run in batches of 5 games. If a batch fails due to a transient network hiccup, the client retries up to 3 times before surfacing an error. Per-game writes are idempotent, so re-running a stuck batch never double-simulates. If the simulate-day endpoint times out, your progress is preserved and clicking Simulate again resumes from the next unplayed game.

If games get stuck in a simulating state (from an aborted run or deploy), the schedule page surfaces a Reset stuck button that flips them back toscheduled so you can re-run.

Schedule page

The schedule opens to the page containing the first unplayed game by default, so you land on "what's next" instead of having to page forward past completed weeks. Tabs: All, Scheduled, Simulating (only shown when there are stuck sims), Completed, Cancelled (shown when non-zero). A Gamecast button appears next to Simulate for scheduled games, and a Replay button for completed ones.

Trades

  • Propose trades involving players and/or draft picks from both teams
  • Player ownership is validated against the league roster (not global)
  • Resulting roster sizes must stay within league limits
  • When a salary cap is set, the proposer and recipient are both simulated against the cap; trades that would put either side over are blocked at proposal time and at acceptance
  • The commissioner can veto any trade
  • Trade deadline blocks new proposals after the configured game count

Free Agency & Waivers

Free agents are league-specific — players not on any team in that league. A player rostered in League A is still a free agent in League B. Virtual players that have not been claimed by any user are excluded from the pool.

All availability lists (draft pool, free agents, waivers) respect the league's OVR range, allowed countries, and max star rating. Signings and waiver claims also validate against the salary cap — a player you can't afford won't be added.

Player System

Every player in Pennant Games has a detailed attribute profile that drives how they perform in the simulation engine. There are no random dice rolls — every outcome is determined by attributes, coaching settings, fatigue, matchups, and context.

Player Types

TypeDescription
CustomPlayers you design yourself. Name, position, physicals, and every skill attribute under a shared team budget. Up to 12 per team. Private by default; publishable per player. See Custom Players.
VirtualOn-chain players from the original Swoops project. Claimable by wallet holders. Hidden from other users until claimed. See Wallet & Virtual.

Positions

Every player has a primary position and an optional secondary position: PG (Point Guard), SG (Shooting Guard), SF (Small Forward), PF (Power Forward), C (Center).

The engine does not enforce traditional 5-position lineups. You can run 5 point guards or no center if you want — but there are consequences. Teams with all 5 positions represented get a chemistry bonus. Substitutions prefer same-position replacements. And positions affect stamina drain rates (guards tire faster than bigs).

Custom Players

Custom players are user-designed basketball players that live on a custom team. You pick the name, position, physicals, stars, and every skill attribute — all under a shared team budget that keeps things balanced.

Custom teams are a sandbox: a team is either a custom team or a real-player team, never mixed. Leagues can host both kinds of teams side-by-side as long as the commissioner has allowed custom teams in.

Creating Your First Custom Player

  1. Open your dashboard and find the Custom Teamssection. Click Create your first team (or + New teamif you already have one), give the team a name, and hit Create.
  2. You're dropped straight into the team's custom roster editor at /teams/[teamId]/custom-roster.
  3. Click + Add Player. A new player starts with 3 stars and every attribute at 75 (a "default" player — 75 OVR, balanced across all skills).
  4. Fill in name, position, height/weight/age, country, stars, and attributes. The budget panel at the top tracks your team's usage live. Over-budget values turn red; the server will reject a save that exceeds the pool.
  5. Toggle Public if you want the player to show up in public player lists. Leave it private if you're still tuning or want to keep your build secret until league time.
  6. Click Create player. Repeat up to 12 times. Every new player unlocks more budget to redistribute across the roster.

The Team Budget

Custom players aren't capped per-player — they're capped per-team. Each filled roster slot unlocks both:

  • +3 stars into the team's star pool
  • +1,800 attribute points into the team's attribute pool

A "default" player (3 stars, every attribute at 75) uses exactly one slot's worth of budget. Fill all 12 slots and you've unlocked 36 stars and 21,600 attribute points to spread however you want.

That's the core design: every player you create increases your total budget, but the budget is shared. Want a 5-star superstar? You need 5 stars worth of pool — which means other players on the roster are below 3 stars. Want a roster of twelve 80-OVR role players? The points are there, but you'll have no 5-star headliner. Choosing whose ratings to "steal" from is the game.

Bounds

FieldRangeDefault
Stars per player1 – 53
Attribute values30 – 99 (24 attrs)75
Height60 – 96 inches76" (6'4")
Weight140 – 400 lbs200 lbs
Age18 – 4524
Roster size0 – 12 custom players

Hidden Attributes

The 5 hidden attributes — consistency, hot-hand, foul tendency, injury proneness, and usage tendency — are rolled randomly within sensible bounds when a custom player is created. You don't assign them, they don't cost budget, and they give every custom player a little individuality so two 75-OVR shooters don't behave identically.

Privacy

Custom players default to private. Privacy is tiered:

ViewerWhat they see
You (the owner)Everything — every private and public custom player on your team.
AdminsEverything.
Members of a league your team is currently inFull attributes, stars, OVR — league-mates can scout each other's rosters while the league is live.
Members of a league your team was in, now completedIdentity only — name, position, photo. Attributes, stars, and OVR hide again so stats pages for the completed league still render player names without re-exposing live ratings.
Everyone elsePublic customs show up in /players and team rosters. Private customs are hidden entirely (404 on the detail page, filtered out of lists).

Publishing a player is a per-player toggle, not a team-wide one. You can keep most of your roster public and keep a few "secret weapons" private until league day.

Entering a League

When you enter a team into a league, the league's commissioner settings decide what happens:

  • Allow custom players — if off, teams with any custom players are rejected at join time. A league commissioner who wants an all-real-players competition can set this to off.
  • Enforce custom budget — if on, the team's custom roster is validated against the star and attribute-point budget at join time. A team over budget is rejected. If off, a team can bring arbitrarily strong customs (useful for sandbox or exhibition-style leagues).

Both toggles are set in the league creation wizard. The budget math is the same one you see live in the roster editor — if your meters are green, you'll pass.

Editing After Creation

Custom players are fully editable any time outside of a live league. Inside a live league, edits to your team's custom players do propagate to the league — there's no snapshot at join time. League commissioners should expect this and use the budget-enforcement toggle when it matters.

Finding Custom Players

The /players page has a Custom filter pill with two sub-filters:

  • All — every public custom player, plus any of your own (public or private).
  • Mine — every custom on a team you own, public or private.

Private customs from teams you don't own never appear here. To see a private custom from a current league-mate, open the team page directly or the league roster view.

Skill Attributes

Each player has 24 visible skill attributes rated on a 30-100 scale, plus 5 hidden attributes (0-1 scale) that control consistency, streakiness, foul tendency, injury risk, and usage. The 24 visible attributes are grouped into categories and each one directly controls specific aspects of the simulation engine.

AbbrAttributeWhat It Controls
TVOL3PT VolumeTendency to shoot three-pointers. Higher = more 3PA per game. 70% player tendency + 30% coaching.
MVOLMid-Range VolumeTendency to take mid-range jumpers. Higher = more mid-range FGA.
IVOLInterior VolumeTendency to score inside — layups, dunks, post-ups. Higher = more paint touches.
TACC3PT AccuracyThree-point shooting percentage. Maps to a 30-50% range (attribute 30 → 30% FG, attribute 100 → 50% FG).
MACCMid-Range AccuracyMid-range shooting percentage. Maps to a 35-56% range.
IACCInterior AccuracyInside scoring percentage — layups, dunks, post moves. Maps to a 53-79% range.
CFTSCharity StripeFree throw percentage. Maps to a 62-94% range.
DRAWDraw FoulsAbility to get to the free throw line. Increases foul rate on shot attempts.
CRSHCrash the GlassOffensive rebounding. Increases team OREB rate and individual board probability.
CTRLBoard ControlDefensive rebounding. Increases team DREB rate and individual board probability.
VISCourt VisionPassing and assist generation. Higher = more assists on made shots, better ball movement.
RIMGRim GuardInterior defense and shot blocking. Reduces opponent interior FG% and drives block probability.
LOCKLockdownPerimeter defense and steals. Reduces opponent perimeter FG%. Uses individual matchup defense.
STRStrengthPhysical toughness. Affects rebounding contests, post defense, and contact play.
MOTMotorEffort plays and hustle. Affects loose balls, rebounding effort, and shot contests.
AWRAwarenessBasketball IQ and positioning. Reduces turnovers and improves defensive rotations.
DURDurabilityStamina and injury resistance. Higher = slower fatigue drain, lower injury risk.
PRESPresenceStar gravity and drawing double teams. Affects team chemistry and shot creation.
ADPAdaptabilityVersatility and scheme fit. Contributes to OVR and team chemistry.
OBALLOff-Ball MovementMovement without the ball — cuts, screens, catch-and-shoot. More touches in ball-movement systems.
POSTPost GameBack-to-basket scoring. Shifts shot selection toward interior and improves inside make%.
TRNSTransitionFast break scoring and playmaking. Increases transition play probability after steals/rebounds.
CLTCHClutchPerformance in final 5 min of close games (within 10 pts). -4% to +6% FG% modifier.
PIQPassing IQAssist quality and turnover avoidance. Reduces TO rate and increases assist conversion.

Stats Reference

The simulation engine tracks comprehensive statistics for every player and team. Here's what each stat means and how it's calculated.

Basic Stats (per game)

StatMeaning
PPGPoints per game. Total points scored divided by games played.
RPGRebounds per game. Offensive + defensive rebounds divided by games played.
APGAssists per game. Total assists divided by games played.
SPGSteals per game. Total steals divided by games played.
BPGBlocks per game. Total blocks divided by games played.
TOPGTurnovers per game. Lower is better.
MPGMinutes per game. Total minutes played divided by games played.
FGA/GField goal attempts per game.
3PA/GThree-point attempts per game.
FTA/GFree throw attempts per game.
FG%Field goal percentage. FGM / FGA.
3P%Three-point percentage. 3PM / 3PA.
FT%Free throw percentage. FTM / FTA.

League and team stat tables separate Regular Season from Playoffs— totals are never combined. The Career view sums across all seasons for the selected type, and the same team across multiple seasons collapses into a single sub-row in the career view.

Advanced Stats

StatMeaningFormula
GSGame Score — single-number measure of overall performance (Hollinger formula)PTS + 0.4×FGM - 0.7×FGA - 0.4×(FTA-FTM) + 0.7×ORB + 0.3×DRB + STL + 0.7×AST + 0.7×BLK - 0.4×PF - TOV
PPPPoints per possession — scoring efficiencyPTS / (FGA + 0.44×FTA + TOV)
eFG%Effective field goal % — adjusts for three-pointers being worth more(FGM + 0.5×3PM) / FGA
TS%True shooting % — includes free throws in efficiencyPTS / (2 × (FGA + 0.44×FTA))
URnUsage rate — how many possessions a player uses (not pace-adjusted)(FGA + 0.44×FTA + TOV) / minutes
TO%Turnover percentage — turnovers as a % of possessions used. Lower is better.TOV / (FGA + 0.44×FTA + TOV)
TFPGTurnovers + fouls per game — negative contributions. Lower is better.(TOV + 0.4×PF) / GP

Ratings, Stars & OVR

Overall Rating (OVR)

Each player's OVR is computed as a position-weighted average of their 24 visible attributes. Different positions value different attributes:

  • Point Guards — Court Vision, Awareness, and Presence matter most. Deep Range and Lockdown are important but not dominant.
  • Shooting Guards — Pull-Up Game, Lockdown, and Presence are key. Scoring efficiency and perimeter defense define the position.
  • Small Forwards — The most balanced position. Presence and Adaptability are weighted highest, rewarding versatile two-way players.
  • Power Forwards — Crash the Glass, Inside Game, and Board Control lead. Scoring and rebounding dominate.
  • Centers — Crash the Glass, Board Control, Rim Guard, and Strength are all weighted at 1.0. Interior dominance is everything.

Irrelevant attributes are zeroed out — a point guard isn't penalized for low Rim Guard, and a center isn't penalized for low Deep Range.

Star Rating

StarsOVR RangeWho's Here
5 ★90+All-time greats, current superstars (Jordan, LeBron, Jokic, Wembanyama)
4 ★80-89All-Stars, franchise players (Tatum, AD, Dirk, Wade)
3 ★67-79Quality starters, solid role players, top college prospects
2 ★55-66Rotation players, bench contributors, average college players
1 ★Below 55End-of-bench, deep reserves

OVR vs. In-Game Impact

OVR measures how complete a player is — it rewards well-rounded players who contribute across all facets of the game. A 90 OVR player is elite at most things their position demands. But OVR does not measure how impactful a player will be in a specific system.

In-game impact depends on how a player's skills fit the coaching scheme and team composition. A specialist like Klay Thompson (elite three-point shooting and off-ball movement, but limited playmaking and rebounding) may have a modest OVR, but on a team running a ball-movement, three-point-heavy scheme, the engine will:

  • Feed them the ball — Off-Ball (OBALL) directly increases a player's chance of being selected as the shooter, especially in high ball-movement systems
  • Get them the right shots — Three Volume (TVOL) pushes their shot selection toward threes (70% player tendency + 30% coaching)
  • Make those shots count — Three Accuracy (TACC) gives them near-ceiling 3PT percentage

The same logic applies to every specialty: a rim-protecting center with high Rim Guard will contest and block shots even if his offensive skills are limited. A pass-first point guard with elite Court Vision and Passing IQ will generate assists and reduce turnovers even if he can't score.

Draft for your system, not just OVR. A 74 OVR sharpshooter on a three-and-D team will outperform a 80 OVR jack-of-all-trades who doesn't fit the scheme. The engine rewards the right player in the right role.

How Ratings Are Derived

Player attributes are computed from real basketball statistics, not manually assigned. The system converts per-game stats (PPG, RPG, APG, shooting splits, etc.) into the 24-attribute system using calibrated formulas:

  • Shooting attributes use a volume × efficiency composite (makes per game × shooting percentage)
  • Legend ratings include an era adjustment — players from the 1990s-2000s slow-pace era get their volume stats scaled up to modern equivalent
  • College ratings include pace adjustment (48/40 scaling), age bonuses for younger prospects, and team context discounts for players on stacked rosters
  • Elite scaling pushes top-tier attributes closer to 100, simulating that the best players don't just have good stats — they dominate

Hidden Attributes

In addition to the 24 visible attributes, each player has 5 hidden attributes (0-1 scale) that affect in-game behavior:

  • Consistency — game-to-game variance. High consistency = reliable performance. Derived from Awareness.
  • Hot Hand Tendency — likelihood of going on streaks (consecutive makes boost shooting). Derived from Deep Range.
  • Foul Tendency — how often the player commits fouls. Derived from Strength.
  • Injury Proneness — base injury risk per possession. Inverse of Durability.
  • Usage Tendency — how much the player demands the ball. Derived from scoring attributes. High-usage players take more shots.

Simulation Engine

The engine is a pure-logic, possession-by-possession Monte Carlo simulator. It takes two Team objects (rosters, coaching settings, starting lineups) and produces a complete game result with every play recorded.

Possession Flow

Every possession follows this sequence:

  1. Transition check — after turnovers and defensive rebounds, team Transition (TRNS) skill affects fast break probability. Fast breaks produce higher-percentage interior looks.
  2. Non-shot foul check — defensive fouls can occur before a shot attempt. If the team is in the bonus, free throws are awarded.
  3. Turnover check — probability based on offensive awareness and passing IQ (PIQ) vs defensive lockdown, coaching intensity, shot clock pressure, and fatigue. High PIQ reduces turnovers. If a steal, the matchup defender (the player guarding the ball handler) is 3x more likely to get credit.
  4. Shot selection — the shooter is chosen by usage tendency, modified by coaching ball movement and off-ball movement (OBALL). High OBALL players get more catch-and-shoot opportunities when ball movement is high. Post game (POST) shifts shot selection toward interior. Shot type (3PT, MID, INT) is selected based on coaching tendencies and the shooter's attribute affinities.
  5. Defensive contest — the engine assigns individual defensive matchups by position. Perimeter shots are contested 70% by the matchup defender + 30% team help defense. Interior shots blend the matchup defender with the best rim protector.
  6. Block check — interior and mid-range shots can be blocked. The matchup defender and best rim protector compete for the block, weighted by Rim Guard + Motor.
  7. Make/miss resolution — probability determined by shooter attributes, stamina, hot/cold hand, consistency variance, defensive contest, clutch modifier, momentum, chemistry, and home court advantage.
  8. Rebound — on misses, offensive vs defensive rebound probability is computed from Crash the Glass vs Board Control, with height bonuses. Individual rebounder selected by weighted random.
  9. Free throws — awarded on shooting fouls (2 or 3 depending on shot type) or bonus situations.
  10. Substitution check — after each possession, the engine checks for fouls outs, injuries, fatigue, foul trouble, minutes management, and garbage time. Subs prefer same-position replacements.

Fatigue System

Every player has a stamina meter (0-1) that drains each possession based on their position (PGs drain fastest at 1.1x, Centers slowest at 0.9x) and durability attribute. As stamina drops:

  • Shooting accuracy decreases
  • Turnover probability increases
  • Players are subbed out when stamina falls below 35%
  • Bench players recover stamina while sitting

Chemistry

Team chemistry is computed from three factors:

  • Presence score (40%) — average Presence attribute of on-court players
  • Adaptability score (40%) — average Adaptability, representing how well players fit together
  • Position balance (20%) — bonus for having all 5 positions represented. Running 5 PGs gives only 20% of this bonus.

Chemistry affects assist rate, turnover rate, and shooting accuracy (approximately ±1-2% FG).

Momentum

Teams on a scoring run get a small shooting boost (up to ~2% per consecutive scored possession). This creates realistic runs and momentum swings.

Clutch Mode

When the game is within 5 points in the final 2 minutes, clutch mode activates. The dedicated Clutch (CLTCH) attribute provides a -4% to +6% FG% modifier. Players with high Clutch get a shooting boost; players with low Clutch get penalized. This simulates the real-world phenomenon of stars rising in big moments.

Hot/Cold Hand

Players can get hot (consecutive makes) or cold (consecutive misses). The Hot Hand tendency hidden attribute controls how likely streaks are to develop. A hot shooter gets up to a ~3% FG boost; a cold shooter gets a similar penalty.

Coaching Settings

Each team has configurable coaching settings that affect gameplay:

CategorySettingEffect
OffensePace (1-10)Game speed — higher pace = more possessions, faster clock consumption
Offense3PT TendencyHow often the team shoots threes vs mid-range vs interior
OffenseBall MovementHigher = more uniform shot distribution; lower = star-heavy usage
OffenseFast BreakLikelihood of transition plays after turnovers/rebounds
DefenseIntensity (1-10)Aggressive defense creates more steals but also more fouls
DefenseHelp DefenseHow much team help compensates for weak individual matchups
RotationDepth (8-12)How many players get regular minutes
RotationStarter MinutesTarget minutes for starters (28-40)
RotationGarbage TimePoint margin threshold to pull starters in blowouts

Defensive Matchups

The engine uses individual matchup defense rather than generic team defense. Each offensive player is matched to the defender closest to their position:

  • A PG is primarily guarded by the opposing PG (or SG if the PG is a weak defender)
  • A C is primarily guarded by the opposing C
  • Perimeter shots (3PT/MID) are contested 70% by the individual matchup + 30% by team help defense
  • Interior shots are 50/50 between the matchup defender and the best rim protector
  • The help defense coaching setting determines how much team defense compensates for a weak individual matchup

This means a team with one elite perimeter defender (like a Kawhi Leonard) won't lock down all five opponents — only the player he's matched against.

Era System

Leagues can optionally select a basketball era that adjusts the simulation engine to match the style of play from that decade. The era system modifies ~30 tuning parameters without changing any engine code — it adjusts shot distribution, pace, foul rates, rebounding, and more.

Available Eras

EraStyleKey Differences
2020s (Modern)Analytics EraHigh 3PT volume (38%), fast pace, spacing-oriented, fewer mid-range shots
2010sThree-Point RevolutionRising 3PT (30%), transition to small ball, faster than 2000s
2000sIsolation EraSlow pace, mid-range dominant (32%), fewer threes (22%), defensive era
1990sPhysical EraHand-checking, low 3PT (18%), strong post play, high foul rates
1980sShowtime EraFast pace, minimal 3PT (8%), high assist rates, up-tempo
1970sPre-Three-PointNo three-point line, 65% interior scoring, very physical, fastest pace

How It Works

Each era is a set of overrides to the engine's default tuning knobs. When a league has an era set, the overrides are applied before each game simulation. The era affects:

  • Shot distribution — percentage of 3PT, mid-range, and interior attempts
  • Pace — average seconds per possession (faster era = more possessions = higher scores)
  • Foul rates — more physical eras have higher foul rates
  • Rebounding — older eras have higher offensive rebound rates
  • Shooting accuracy — 3PT accuracy ranges are adjusted for eras before the line existed
  • Home court advantage — stronger in older eras

Coaching settings still apply on top of era adjustments. A team running a “Run & Gun” offense in a 1990s era league will still push pace — but the baseline is slower than modern, so the effective pace will be more moderate.

Player attributes are NOT modified by era — a modern sharpshooter still has high TACC and TVOL. But in a 1980s league, the era's low baseThreeRate means fewer 3PT attempts league-wide, and even the best shooters will take more mid-range and interior shots.

Setting an Era

The commissioner selects the era when creating the league, or changes it in league settings before games begin. The era is shown as a badge on the league page.

AI GM

Pennant Games includes AI-powered General Manager features that can manage teams autonomously or provide on-demand advice to human managers.

Two Modes

  • AI-Managed Team — commissioners can enable AI GM on any team in the league. Once enabled, the AI autonomously handles drafting, trade evaluation, lineup setting, and waiver claims for that team.
  • Ask the GM — click the “Ask the GM” button on any team or league page to open the AI sidebar. Get analysis and recommendations for roster moves, lineup decisions, coaching strategy, and more — without giving up control.

What It Covers

  • Draft picks — AI evaluates the available player pool, team needs, and positional fit to recommend or auto-select the best pick
  • Trade evaluation — AI analyzes proposed trades for value, roster impact, and positional balance
  • Lineup setting — AI recommends optimal starters and rotation based on matchups and player attributes
  • Waiver claims — AI identifies high-value free agents that fill roster gaps
  • Coaching strategy — AI suggests coaching settings (pace, 3PT tendency, defensive intensity, rotation depth) based on roster analysis

Transparency

All AI decisions are logged with reasoning so users and commissioners can review why the AI made each choice. The AI is powered by Claude (Anthropic) using the fast, cost-effective Haiku model for all decisions.

Fantasy Leagues

Fantasy leagues let you draft real NBA players and score based on actual NBA game results — a fantasy basketball mode built on top of the existing league infrastructure.

How It Works

  1. Create a fantasy league — choose fantasy mode when creating a league
  2. Filter the draft pool — narrow the available players to specific NBA teams (e.g., playoff teams only)
  3. Draft real NBA players — uses the same snake, linear, or auction draft system as simulation leagues
  4. Score from real games — daily scoring is pulled from actual NBA box scores
  5. Manage your roster — set active lineups, work the waiver wire, and make trades throughout the season

Roster Slots

Fantasy rosters use positional slots: PG, SG, SF, PF, C, G, F, UTIL, plus bench spots. Only players in active slots score points on game days.

Scoring Systems

Commissioners choose from three configurable scoring systems:

  • ESPN Standard — traditional category-based scoring
  • Yahoo Standard — Yahoo's default fantasy basketball scoring
  • Points Plus — simplified points-based system

Daily Scoring

Scoring runs automatically via a cron job at 6 AM ET each day, pulling the previous day's NBA box scores. Commissioners can also manually trigger scoring for any specific date.

Standings & Stats

Fantasy leagues include dedicated standings and a player stats leaderboard ranked by fantasy points. The existing trades, waivers, and free agent systems all work within fantasy leagues.

Game Results & Visualization

Every simulated game produces comprehensive results:

AI Game Recap

Each game generates a 4-5 paragraph sportswriter-style narrative recap covering the game flow, key performers, shooting comparisons, and the final outcome. Series games get individual recaps for each game.

Win Probability Chart

A real-time win probability curve tracks each team's chance of winning throughout the game. The model uses a statistical approach based on the current margin and time remaining — the standard deviation of possible outcomes shrinks as the game progresses, so a 10-point lead means more in Q4 than Q1.

Game Flow Chart

A step-function line chart shows both teams' cumulative scores over time. Hover over any point to see the exact score, play description, and game clock. Quarter boundaries are marked with vertical lines.

Shot Chart

An interactive half-court visualization of every shot attempt:

  • Green circles = made shots (dark green for 3PT, medium for MID, light for INT)
  • Red × marks = missed shots (same shade system)
  • Hover tooltip = shows shooter's last name and distance from basket
  • Filter by quarter or by player to focus on specific situations

Box Score

Full per-player statistics including minutes, points, FG/3PT/FT splits, rebounds (offensive + defensive), assists, steals, blocks, turnovers, personal fouls, plus/minus (tracked per-possession), and Game Score (Hollinger formula). Starters are separated from bench players.

Team Comparison

Side-by-side team stats with shooting splits, rebounding, assists, steals, blocks, turnovers, and fouls. Includes the Four Factors of basketball analytics: eFG% (effective field goal percentage), TOV% (turnover rate), ORB% (offensive rebound rate), and FT Rate (free throw rate relative to field goal attempts).

Play-by-Play

Every event in the game is recorded with quarter, game clock, team, play type, and natural language description. Filter by quarter or player to review specific sequences.

Gamecast Live Play

Gamecast is an ESPN-style live playback of any simulated game. Click Gamecastnext to Simulate on the schedule page (for unplayed games) or Replay on a completed game to open it.

How it works

The simulation runs to completion server-side in one pass, then the browser plays back the stored play-by-play with an adjustable cadence. There's no per-tick server cost — all the playback state is derived client-side from the game's PBP rows.

  • For a scheduled game, clicking Gamecast kicks off the sim behind a progress bar, then auto-starts playback when it's done.
  • For a completed game, Replay jumps straight to playback. Anyone can replay any completed game.

Live panels

  • Sticky scoreboard — team scores, live win-probability per team, quarter + game clock, and a rolling play ticker showing the current event.
  • Play feed — newest on top, grouped with player avatars for the primary and secondary actors (shooter + assister, blocker + shooter, etc.). Scoring plays get a green +N chip.
  • Live box score — points, FG / 3PT splits, rebounds, assists, steals, blocks, turnovers, and minutes, updating every play. Players on the floor are listed first with a green dot; bench players are separated below a divider and sorted by minutes played.
  • Live shot chart — every shot builds up dot-by-dot as plays advance. The newest shot pulses briefly to draw the eye. Filter by quarter or player at any time.

Controls

  • Play / Pause, and a 0.5× / 1× / 2× / 4× speed selector. 1× = 2 seconds per play; scoring plays get a small extra hold so the shot-chart pulse has time to land.
  • Skip to the start of Q2, Q3, Q4, the last 2:00 of the game, or the end. Skip is instant — the cursor jumps, the panels recompute from there.
  • When the game ends, a Final banner appears with a link back to the full game summary.

Attribute Aging & Performance Curves

Players evolve across seasons per league. Each league keeps its own cumulative delta on top of the baseline attributes, so the same player can develop differently in two different leagues based on how they're used.

What changes

  • Aging — a per-year drift based on effective age vs. the player's peak age. Young players grow, peak-age players hold steady, older players decline on physical attrs while mental attrs keep rising into the mid-30s.
  • Performance curve — over or under-performance vs. league medians bumps the related attribute group. Strong rebounding raises rebounding attrs, strong efficiency raises accuracy attrs, heavy turnover loss nudges passing IQ down, etc.
  • Results combine into one cumulative delta that's added on top of the baseline attribute values (clamped to 30–100).

Commissioner review

Deltas are computed automatically when you advance the season, but they start in a pending status and do nothing until approved. Open League → Attribute Deltas to review per-player breakdowns: aging and performance contributions are shown separately per attribute, and the resulting base → effective preview tells you what each player will look like once approved. You can edit individual deltas inline, approve selected players, approve all pending at once, or reject — rejecting deletes the pending row so you can re-run the curve later.

Season flow

Once approved, deltas affect simulations, stats displays, team roster views, and the league leaders page for that season. Base players.attr_* values are never mutated — the overlay is applied at read time, so different leagues can coexist without interference.

Wallet & Virtual Players

Virtual players come from the original on-chain basketball project — 3,662 ERC-721 NFT players across 723 Ethereum wallets. About 2,500 of these played at least one Swoops game and are currently imported into Pennant Games; players that were minted but never played are not imported (there’s no performance data to derive meaningful attributes from).

Virtual Player Ratings

Virtual players use a multi-step conversion pipeline that respects both the revealed Swoops player skill ratings (PSRs) and their actual game performance:

  1. Revealed PSRs mapped directly — Swoops shooting, defense, rebounding, and intangible ratings are mapped to their Pennant equivalents as the anchor values.
  2. Position-specific percentiles — Unrevealed attributes are derived from game stats using Swoops position-specific percentile tables. A guard with 1.33 BPG is elite (99th percentile among guards), even though 1.33 is only average for a center.
  3. PSR-stat blend — For attributes that have both a revealed PSR and a stat-derived value, the two are blended 60/40 (PSR weight / stat weight). Strong game performance can push a revealed value up to +8 (elite guard blocks pushing a revealed 70 defensive rating higher); weak performance can pull it down up to -5.
  4. Win rate discount — Players with losing records have their stat-derived attributes pulled toward league average. Volume stats on bad teams don’t reflect true skill.
  5. Empty stats penalty — High-volume scorers with losing records AND low/no revealed scoring PSRs get an additional discount. High revealed PSRs provide “credibility” that reduces the penalty, since the stats are backed by known skill.
  6. Targeted dominance boost — MVP-caliber performance and awards (MVP, DPOY, All-Star) apply a boost to intangibles (presence, adaptability, motor) but NOT a blanket floor on all attributes.
  7. Rank ordering correction — A player’s top-3 Swoops PSR attributes are nudged up (max +5) to ensure they remain among the player’s highest Pennant attributes. Prevents a shooting specialist from ending up with higher strength than their shooting.
  8. Original Swoops star preserved — The star rating displayed on the site is always the NFT’s original Swoops star, regardless of where their performance-derived OVR lands on our scale. A 3-star Swoops NFT with elite performance might have a 4-star OVR on our site but still shows as 3-star (its NFT identity).
  9. No aging curve — Virtual player attributes are historical records of Swoops performance. They are not aged down based on Swoops “age” (which was a made-up property of each NFT).

The OVR calculation itself uses the same WARP-inspired position-weighted formula as all other player types, so virtual players are directly comparable to legends, current NBA, and college prospects.

Claiming Your Players

  1. Go to your dashboard and find the Wallet section
  2. Connect your Ethereum wallet (MetaMask or any wallet extension)
  3. Review the verification prompt — confirms this is a free signature, not a transaction
  4. Sign the nonce-protected message — proves wallet ownership without spending gas
  5. Players are auto-claimed — any legacy players on that wallet are linked to your account

You can connect multiple wallets if your virtual players are spread across them. The signing message includes a one-time nonce to prevent replay attacks.

Using Virtual Players

  • Exhibitions — add to any exhibition lineup freely
  • Leagues — bring onto your league team if the league allows virtual players. Each league sets how many virtual players can be used per game (e.g., max 3).
  • Available everywhere — the same virtual player can be on different teams in different leagues simultaneously. They're your players globally.
  • NOT in the draft — virtual players come from wallet claims only, not the draft pool
  • Rename — assign a custom display name that appears everywhere the player is shown

Ownership Verification

Since virtual players are NFTs that can be traded on OpenSea and other marketplaces, Pennant Games verifies on-chain ownership before each game simulation. If an NFT has been transferred to a different wallet since claiming, the player is automatically unclaimed and removed from league rosters. The new wallet holder can then claim and use them.

Security

  • Wallet addresses are never exposed in public API responses
  • Signatures use a one-time nonce with 5-minute expiry to prevent replay
  • The signed message explicitly states it does not approve transactions or transfers
  • A wallet can only be linked to one account — prevents multi-account exploits

Virtual players are not visible to other users in player searches or free agency until claimed.

Contact

Pennant Games is under active development. For questions, feedback, or bug reports, email hello@pennantgames.com.

Disclaimer

Pennant Games is an independent basketball simulation game. It is not affiliated with, endorsed by, or connected to the NBA, NBPA, any professional basketball league, or any prior basketball game project. Historical player names and statistics are used under First Amendment protections as established in CBC Distribution v. Major League Baseball Advanced Media (2007).