Skip to content

Feature Stat Book

Brennan Hatton edited this page Sep 14, 2026 · 1 revision

A Note From Faulthurst — the stat book

Since: v0.669.0 (PR #1113) · toned follow-ups + rate-judged kills: v0.886.0 (PR #1417)

A one-page written book signed by Faulthurst, the mod's watching narrator, that names one real number from the reader's current run. It is the coin-flip half of a stats_book loot slot (the other half is a tall leaderboard book), and a Stat Room dimensional carriage shelves one per subject.

The page

Three sentences, each its own translation key so every locale can reorder freely:

Brennan, forgive the intrusion.

You've made it to carriage 14.

Would you have believed that, a few carriages ago?
Part Count Chosen by
Opener — always names the reader 15 (open.0–14) roll seed stamped at the container; open.6 (the bare name) is weighted to 50 %
Stat line — one live number 18 subjects (stat.<id>) first refresh in a hand, from what the holder has actually done (RunStatSubject.eligible); then fixed
Tail — a closing remark 61 (tail.0–60) the same seed, drawn from the pool the stat's tone allows

The number keeps refreshing (1 Hz, only when the rendered string changes) until the book is opened, when RunStatBookTag.lock freezes the page for good.

Tone — he reads the room

Every tail is tagged positive / neutral / negative (RunStatBookFactory.TAIL_TONES); every stat reading is kind / plain / grim. Positive tails never follow a grim reading; negative tails only follow one; neutral fits anything. So "You've killed 3 passengers." is closed with "Would you do it again?" or "I counted every one." — never "Good. Go further."

Reading Subjects Tails allowed
kind friends, tamed, books read/written, love notes, pacifist carriages; a kill count of zero positive, neutral
plain carriage, playtime, chests, distance, damage taken, strangers passed, no-chest streak, backwards, death notes; a kill count within budget positive, neutral
grim a kill count over budget neutral, negative

Kills are judged by rate

RunStatSubject.read(run) judges the three kill subjects against the carriages travelled (KillBudget):

Subject plain up to zero-kill line (kind)
things killed 25 per 100 carriages "You've killed nothing at all, N carriages in."
echoes put down 1 per 500 "You've put down no echoes, N carriages in."
passengers killed 1 per 250 "You haven't killed a single passenger, N carriages in."

The zero line needs the run to be 3+ carriages in, and — for echoes and passengers — at least one PlayerMob to have been met, so it never remarks on something that could not have happened. Its number is the carriage count, so it is a .none plural family in every locale.

Files

  • narrative/RunStatSubject.java — subjects, floors, Tone, KillBudget, Reading, read(run)
  • narrative/RunStatBookFactory.java — composition, TAIL_TONES, opener weighting, tailPool
  • narrative/RunStatBookEvents.java / RunStatBookTag.java — refresh sweep, stamped seed/subject, lock on open
  • lang/*.json — book.dungeontrain.statbook.{open,tail,stat}.*
  • portal/PortalRoomStatShelves.java — one note per subject in a Stat Room (51 books with the boards)

Known residual

Derived subjects (pacifist, the kill .none lines) collapse to 0 once disqualified — an unopened note that had chosen one would refresh to "…0 carriages…". Tracked on the project board.

Clone this wiki locally