Guide

Population

A new career fills every tier up to its size with generated players, and each season a youth intake tops the world back up. If your mod adds real players, the generated ones can end up stronger than them. data/population.json controls how many players are generated and how strong they can be.

The file holds one object (an array of them also works). Every field except id is optional. A field you leave out keeps the game's default. Without the fields in the table below, the game behaves exactly as before: the core pack's own data/population.json (core.population) only holds the tuning at the game's numbers, which doesn't switch them on.

{
  "id": "acme.population",
  "capToNamed": { "percentile": 50, "growth": 1 },
  "genderLevelOffset": { "f": -6 },
  "womenShare": 0.06,
  "potentialHeadroom": 14
}
FieldDefaultWhat it does
tierSizes1: 32, 2: 96, 3: 128, 4: 128, 5: 220Players per tier, named and generated together, e.g. { "3": 100 }. The total is also the size the youth intake keeps the world at, and 3 is how many non-card holders stay in tier 3 each season.
levelsthe game's bandsPer tier { "mean", "sd", "min", "max" }. A generated player's level is drawn from N(mean, sd), and the final overall level (after attribute noise and style) is kept inside [min, max].
potentialHeadroom28The most potential a generated player gets above their level (teenagers get the most). The game's headroom ranges, including the youth intake's, are scaled to fit.
genderLevelOffset{ "m": 0, "f": 0 }Added to generated players' level by gender. The band and the named-player cap move with it, so { "f": -6 } puts generated women 6 below where generated men would be.
womenShare0.10 (0.15 in tier 5, 0.14 youth)Share of generated players, and of each youth intake, who are women (0 to 1).
capToNamedoffKeeps generated players below the named ones. See below.

Capping generated players to the named ones#

"capToNamed": { "percentile": 50, "margin": 0, "growth": 2, "minNamed": 3 }

  • For each tier, the cap is that percentile of the named players' overall levels in the tier, plus margin. With 50 and a margin of 0, no generated player starts above the tier's median named player. The human doesn't count.
  • A tier with fewer than minNamed named players uses the cap of the nearest tier above. If no tier above has one, the tier has no cap.
  • A generated player's potential is at most the cap plus growth. Each off-season, a generated player can't develop past their potential, and their potential never rises.
  • Youth intake: each season's youngsters get the same caps for their tier (4 or 5). Their potential is bounded by the Tour Card tier's cap (tier 2) plus growth. A youngster can still grow into a pro, just not past the named players. Caps are recalculated each season from the named players still active.

levels and capToNamed work together: the final level stays inside [min, max] and under the cap.

Several mods#

Records apply in load order: fields from later mods win, per tier for tierSizes and levels. If you reuse another mod's id, your record replaces theirs and moves to the end of the load order. You can also patch it, like any record:

{ "target": "population:acme.population", "patch": { "genderLevelOffset": { "f": -4 } } }

A named player's Tour Card year#

A new career gives each named player in tiers 1 and 2 a Tour Card that runs to the starting season or the next, chosen at random. A mod that knows a player's real card can set it in their record in data/players/:

{ "id": "acme.player.jones", "tier": 1, "tourCardUntil": 2027 }

tourCardUntil is the last season of the card. A year before the career's first season means the player starts without a card. Leave it out and the card is drawn as before. Setting it on some players doesn't change anything else in a new world: the other players and the rest of the world are the same as without it.

Club juniors#

youth.club gives a new world a group of beginners on top of its tier sizes, at the lowest tier: { "count": 120, "age": [8, 13], "level": [6, 26] } makes 120 children aged 8 to 13 whose typical rating runs from 6 at the youngest age to 26 at the oldest (each one a few points either side). They are the opponents of the junior events with an ability band or a low age limit. Computer players younger than the tuning value population.juniorOnlyAge (14) only enter events that have a maxAge. Leave club out and no such players are made.

Tuning: styles, followers, youth and retirement#

These fields tune how players are made and how long they last. They're always in force (the core pack sets them to the game's numbers), and setting them doesn't switch on the fields above.

{
  "id": "acme.population",
  "archetypes": { "showman": { "crowdHandling": 14, "composure": -2 } },
  "followers": { "1": [100000, 2000000] },
  "youth": { "gemChance": 0.05 },
  "retirement": { "midAge": 56, "pros": 0.4 }
}
FieldDefaultWhat it does
archetypessee belowStyles of generated player: points added to each attribute around their level. The six styles are fixed; an archetype given replaces the game's offsets for it
followers1: 60,000–1,200,000, 2: 5,000–90,000, 3: 600–9,000, 4: 150–4,000, 5: 20–800A new player's followers per tier, [fewest, most]; the better they are within the tier, the more
reputation1: 70–98, 2: 45–75, 3: 25–50, 4: 10–35, 5: 2–20A new player's reputation (0–100) per tier, [lowest, highest]
youthgemChance 0.07, headroom [6, 22], gemHeadroom [20, 28]Each season's youth intake: the share who are gems, and the potential above their level for ordinary youngsters and for gems
retirementsee belowA computer player's chance of retiring at a season's end

The core archetypes:

ArchetypeOffsets
scorerscoring +5, finishing −4, checkoutKnowledge −2, crowdHandling +2
finisherscoring −3, finishing +5, checkoutKnowledge +5, bullAccuracy +3
grinderconsistency +6, concentration +5, stamina +6, crowdHandling −4, tempoControl +3
showmancrowdHandling +10, composure −3, consistency −3, bullAccuracy +2
nervycomposure −8, resilience −6, scoring +2, finishing +1
balancednone

Retirement: below youngAge (40) the chance is young (0.004). From then it's 1 / (1 + e^−(age − midAge) / spread), with midAge 53 and spread 3.5. Add pub (0.05) for a tier 5 player older than pubAge (45). Add weak (0.08) for a player below level weakLevel (50) who is older than weakAge (30). Then multiply by pros (0.5) in tiers 1 and 2, because pros hang on longer. The living world's farewell-season announcements use the same chances. retirement merges per field.

Records merge in load order: per archetype for archetypes, per tier for followers and reputation, per field for youth and retirement, per trait id for traits. The core record is population:core.population, so { "target": "population:core.population", "patch": { "youth": { "gemChance": 0.1 } } } works too.

The next generation#

Each winter's intake has a shape. The numbers live in data/tuning.json under nextgen.* (see Tuning), the words in data/texts/nextgen.json.

  • Waves. The gem chance and an ordinary youngster's headroom follow a slow cycle: sin(2π × (year − phase) / nextgen.generations.period) with the phase seeded from the career, multiplied by gemAmp (0.5) and headroomAmp (0.15). period 0 or both amplitudes 0 switch it off. The same draws are made; only the chance a gem draw is tested against and the size of the one headroom draw change.
  • National programmes. A nation at band nextgen.programmes.bandMin (3, Strong) or above for seasonsToOpen (2) seasons opens one, named from the text nextgen.programme.name ("{nation} Darts Academy"); seasonsToClose (3) seasons below the band close it. A career's first rollover opens them quietly where darts already stands that high. Each winter a programme claims share (0.5) of its nation's newcomers, best potential first (no draw), giving each headroom (4) more potential (never past the nation's cap from nations.json), professionalism (6) more professionalism, and growth (0.12) on the winter's development until untilAge (23). Graduates carry a "Class of {year}, {programme}" line on their page and a timeline line.
  • Your academy. A facility with graduates above 0 (data/facilities.json: the youth academy 1, the campus 2) brings that many real youngsters of your own country into the world each winter, made on the academy stream at nextgen.academy.minAge (15) to the intake's oldest age, with nextgen.academy.headroom (3; campusHeadroom 5 with two or more) and taking newcomers' places. A facility with gemBonus (the scholarship fund, 0.04) adds to the gem chance of your country's newcomers. What they do pays you back: legacy points (legacy.json points.graduate*), imagePerGraduate (1) image a season for each one holding a card, followersPerMilestone (300), news, a letter for the first card, and the vsGraduate story condition (data/events/narrative/nextgen.json carries three stories with the academy-mentor flag).
  • Hype. A computer player under nextgen.hype.maxAge (23) gains hype on a Tour Card at cardAge (20) or under (card 25), a win over a top-upsetRank (16) player (upset 12) or a top-bigUpsetRank (8) one (bigUpset 20), a tier 1–2 title (title 30), a major final (majorFinal 40) and a rising feature (rising 15); a showboat gains showboatGain (1.3) times more. It decays decay (3) a week, decayPlayed (1) in a week they played while at quietBelow (25) or more, capped at cap (100); only a player under the age today gains, and hype ends for anyone at the age on the calendar year's 1 January (at the first week of the year, even while a world championship holds the season open). Bands at bands [25, 50, 75] take the words nextgen.hype.band.0 to .3; crossing one upward is a story. Effects: pressure (0.06) × hype/100 on televised stages, crowd (0.05) × hype/100 off their crowd hostility at home, sponsor (1) × hype/100 on a sponsor signing or upgrading, news (0.5) × hype/100 on their stories' weight, rivalry (0.5) on a rivalry seed between two youngsters. Falling from bustFrom (50) to under bustTo (25) within bustWeeks (20) of the peak is a bust:'s slump once (bustProfessional 0.5 softens it for a professional). The human is never hyped (fame covers them).
  • The changing of the guard. At each rollover the world's top nextgen.generations.guardTop (32) is measured: median birth year, mean age, shares by five-year band. A median moving guardShift (2) or more years in one season is news (nextgen.guard.*), naming the youngest in the top and whoever dropped out.

The World page's Next generation tab shows all four; an older save gets the state at its next rollover.

Conduct traits#

traits is the list of conduct traits a computer player can carry (two at most, the best-scoring ones). Each trait says how it is scored from the player and what it changes:

{
  "id": "acme.population",
  "traits": [
    {
      "id": "tinkerer",
      "named": true,
      "weights": { "professionalism": -0.4, "temperament": { "volatile": 0.35 }, "media": { "confident": 0.2 }, "style": { "frontrunner": 0.4, "showman": 0.3 } },
      "effects": { "switch": 2 }
    }
  ]
}
  • weights: the score is ambition × (ambition − 50) / 50 + professionalism × (professionalism − 50) / 50, plus the media weight of the player's media manner (humble, confident, showman, reserved, fiery), the temperament weight of their temperament (calm, steady, volatile) and the style weight of their style on the oche (showman, grinder, frontrunner, steady), plus seeded noise of up to ai.traits.noise. A trait counts when its score passes ai.traits.minScore; a player takes the top ai.traits.perPlayer, so a player can have one or none. The answer is written on the player's record the first time the world needs it, so a change of data never changes a trait under a player.
  • effects: multipliers on the chances the world already draws against, by name; a missing one is 1. churn (the main sponsor dropping the player, the agency switch), upgrade (a bigger sponsor or darts brand when hot), switch (leaving the darts brand, a darts change in a slump), coach (a new coach in a slump), dartitis (the dartitis chance), swing (the form and composure of hot streaks and slumps), heat (how fast meetings heat a rivalry), social (the feed's posts about the player's stories), feud (the feud chance: a feud needs the product of the two players' values above 1), loyalty (how fast brand loyalty grows).
  • named: false keeps the trait off real (named) players; the core pack gives every trait to everyone.
  • Texts: ai-traits.<id>.name and ai-traits.<id>.blurb in data/texts/ for the Player page.

The core traits: loyal, mercenary, tinkerer, superstitious, hothead, showboat, professional, restless (data/population.json). Every player the world follows (the top 64 and tiers 1 to 2) also throws a real set of their darts brand (the item nearest their sponsor tier, by hash) whose levers are the human's kit rules pulled towards neutral by ai.kit.scale; brand loyalty (ai.kit.*) slows a brand switch. Feuds between two hotheads (world.feud.*) run through words, a bust-up and a grudge match with pressure on the oche. See tuning.

Saves#

Population settings are copied into a save when the career is created. A career you load picks up the installed packs' settings: generated players already in the world stay as they are, and the settings apply from the next youth intake, refill and retirements.

Checking the effect#

The schema is the population settings reference.

Keeping the lower tiers busy: refill#

Trial Week lifts its whole field to Contender Tour level every winter, which drains the pub (tier 5) and development (tier 4) circuits. refill lists tiers the game tops back up to their tierSizes with generated players of all ages (faces from the library): once after Trial Week finishes and again at each season rollover. The world never grows past 25% over the sum of tierSizes.

{ "id": "mymod.population", "tierSizes": { "4": 180, "5": 360 }, "refill": [4, 5] }

Written for Darts Player Simulator 0.50.32. Built from the game's own schemas and its base pack.