All glory to Jesus Christ, Faithful and True.

"And he hath on his garment, and on his thigh written: King of Kings, and Lord of Lords." Apocalypse 19:16

Systems inventory

Dunk's Bible Palace & Bible Scape

A full accounting of two connected works: a typological study site with its own data discipline, and a Bible themed game server built on the 2004scape engine. Counts are read from the working tree, not estimated.

Compiled 15 October 2026 · typology at 154 entries · site at commit 8f70c09

IMetrics and Features

A Bible study site that checks itself the way a scholar would, and a game world rebuilt around Scripture, both kept by one discipline: verify from the primary source or leave it blank, check the live result rather than the local one, and prove a fix by making it fail first.

154typology entries, each grading its own evidence
41lint rules for theology
287quotations of the Fathers found in their own works
9⅓ hrsof narration in a cloned voice, made locally
129,947verses searchable in five texts
66quests with biblical titles
  • The data grades its own claims. Each entry is graded patristic (72), scriptural (41), traditional (17) or interpretive (23). After twenty two primary text checks, a blank source field means verified absent, not unexamined.
  • There is a linter for theology. Forty one rules: Catechism references must resolve to real text, citation tiers must agree with their footnotes, names must follow the translation in use.
  • Every entry is checked, and checked again. A quotation put in a Father’s mouth is searched for in that Father’s own works. Each entry is read against Denzinger and fingerprinted, so any edit sends it back. On 6 October every entry was checked three ways: against Haydock, in two passes testing 4,792 factual claims, and in a doctrine reread; corrections went in, 50 citations of the Fathers were added and three grades rose.
  • Haydock under every verse. Haydock’s 1859 Catholic commentary, 20,842 notes, stands under every verse it explains, on verse pages and in the Motif Searcher, in Todd Easton’s transcription, credited on every page.
  • The wheel is a literary structure, not navigation. Only entries with a chiastic partner join it: twenty five of the forty six citing the Apocalypse, and that is correct. The Flood swell turns on the one unpaired line of Genesis 6 to 9: And God remembered Noe.
  • The whole Bible on one page. Within and Without winds all 35,804 verses into a spiral round the Resurrection, with 298,490 cross references and every entry drawn across it; a reader can trace the shortest chain between any two verses or watch Scripture answer itself in canon order.
  • Every verse pairing read by meaning. Each Douay verse was scored against its Hebrew and Greek through word glosses; 427 chapters were read in full, 717 pairings were corrected, each challenged by a second reader, and a blind sample of unflagged chapters found one miss in thirty six.
  • A pattern is counted before it is claimed. Every third day in the Douay was counted and read blind by two readers against a rule written first, beside the second, fourth and seventh days and forty days: Scripture names the third day far more often, but it marks a turning point no more often than they do.
  • Its encouragement is sourced. Each of the 189 lines in Quotes is a sentence from an entry and opens that entry.
  • A game whose board believes no browser. Heal Coliseum, a healing game in three battles of Scripture, puts a victory on its shared board only after the server has fought the same battle again on the same engine, which reaches the browser’s result to the last bit; the score shown is the server’s own. It was attacked in four rounds before it went live.
  • The game is a full reskin, not a theme. Nearly every named NPC renamed, quests rewritten in substance, and a standing rule that no instrument of the Passion is worn as gear.

IIThe site

Two HTML pages, the Bible Palace and the prayer book, backed by a Python standard library server. No framework, no build step, no database.

7,612lines, index.html and prayers.html
18JSON data files
8420service port
0build steps

Endpoints

RoutePurpose
/api/entriesThe typology corpus
/api/tagsTag index for filtering
/api/bible/books, /api/bible/…Douay-Rheims lookup by book and chapter
/api/prayersPrayer texts
/prayersDunk's Prayer Book, its own page
/entry/<id>One entry as its own page, with its own head and its text in the HTML
/sitemap.xmlBuilt from the corpus on each request, so never stale
/robots.txtThe site's own, pointing at the sitemap
/wheelThe palace with the Apocalypse wheel open, with its own title, description and preview; the address follows the wheel, so it can be linked and the back button works. Sitemap and llms.txt
/constellationLikewise, with the constellation open; /map redirects here. Sitemap and llms.txt
/timelineLikewise, with the timeline of types and fulfilments open. Sitemap and llms.txt
/quotesThe palace with Quotes open. Sitemap
/leadsThe palace with Leads open, behind the edit password. Unlinked, not in the sitemap
/floodThe Flood chiasm. Sitemap and llms.txt
/SpiralWheelWithin and Without, the whole Douay as one spiral; /spiralwheel also answers, with data and modules under /spiral/
/ThreeThe Third Day census, also /three. Sitemap, no button
/healcoliseumHeal Coliseum, the healing game; /HealColiseum, /raphidim and /Raphidim also answer. Sitemap and llms.txt
/api/coliseum/…The game’s server endpoints, for ranked battles, names and the shared board. The engine is served beside them even when the board is down, so practice still works
/api/readingsThe day’s Mass readings as citations, for the spiral, from the USCCB feed, or for a day the feed no longer holds from the Catholic Readings API, cached per day; only a real day within sixty days of today
/llms.txtA plain summary for language models, with every entry by tier. Not a file: built per request, like the sitemap
/api/rosaryThe mysteries of the Rosary with their Scripture and figures
/api/journalJournal entries, read and write
/api/saintsButler's Lives index
/api/speak, /api/speak/availableNarration audio by cache key; whether narration exists
/api/examenThe examination questions. No POST, so no answer can reach the server
/api/motifOne word across the five texts, with the entries citing each hit
/api/parallel/…Every text for one verse, where the numbering is established, with the Catechism paragraphs citing it
/api/fathers/…The Catena Aurea, Schaff's Fathers and Haydock's notes on one verse, for the Motif Searcher
/api/leads, /api/leads/refresh, /api/leads/markLeads for new entries: open locally, behind the edit password on the read-only public server, where PasswordGuard counts every wrong guess. Rerunning the finder and Keep, Pass or a note need the password everywhere; on the live server the finder runs at low priority under a memory cap, and marks are kept in the server’s state/ folder, which git never touches
/api/entries/checkRuns the linter on one entry before it is saved
/api/strength/…An entry's strength report
/dadinventoryshareA large print copy of this page, unlisted and noindexed
/saints/, /myst/, /fonts/, /icons/, /siteimages/Static trees

Verse pages. Each shows “Haydock's commentary”, folded under “Read on” when long, credited to Todd Easton, with CCC 597-598 where a note blames the Jews and CCC 818 where it argues against the Reformation. On 6 October two slips in the site's Douay were mended: a stray heading “Hebrews Psalm 10” at Psalm 9:21, and drbo's misprint “soil” for “son” at 4 Kings 15:5.

Progressive web app

  • A service worker with a versioned cache, now typology-shell-v314, registered with updateViaCache: 'none' and an explicit reg.update(). It saves 33 files for offline use, each checked on the live site on 7 October; one missing file fails the whole install, which is how two retired star images, still on its list, kept offline use from working between 20 September and 7 October.
  • Navigations are network first, so the shell can always replace itself; everything else is cache first, and activate deletes every old cache. Two exceptions belong to Heal Coliseum: its files under /coliseum/ are network first, the kept copy used only offline, where the game plays practice anyway, and /api/coliseum/*, like the rest of the live API, never comes from a cache.
  • A Cloudflare cache rule makes /sw.js bypass cache, so the worker is never held stale at the edge.
  • In production the server runs read only and refuses every write but Heal Coliseum’s, which writes nothing outside its own state (section X).
  • One guard on every password door. The edit, prayer, leads and Coliseum keeper’s doors all check through PasswordGuard, which limits wrong guesses, so a password cannot be worn down by guessing, while a visitor who has given the right password before is still heard.
Immutable is a promise about a URL, not about a file

Narration cached for a year as immutable, on a URL keyed by the entry, outlived every rewrite of the entry. The header now sends an ETag with must-revalidate, and the request carries a version marker, because a script's fetch still answers from the HTTP cache after a hard refresh.

Theming

  • A day and night toggle, gold on black and blood red at night, swapped by redefining the token set; both palettes are sampled from the banner art. The verse header, banner, star, candle and grail swap with it. The artwork is inspired by the work of J. Kirk Richards.

Being found at all

  • An address for every entry. Until 21 September entries lived after the #, which a browser never sends, so none could be indexed. /entry/<id> carries its own title, description, canonical address, preview and schema.org data.
  • The words in the HTML. The server writes the entry's text into the page for crawlers that run no script; the page drops it once it draws the entry. Checked by fetching a page as Googlebot with script disabled.
  • Announced. tools/indexnow.py submits new addresses to IndexNow (Bing, DuckDuckGo, Yandex); the server proves ownership by serving the key at its own address. Ownership is verified at Google by DNS and at Bing by a meta tag, with the sitemap submitted to both.
A page of its own is a page you have to keep whole

Entry pages splice into index.html: the head between <!--SEO--> and <!--/SEO--> is replaced, and the text goes into <!--PRERENDER-->. Rename a marker and every entry page keeps the generic title. Anything every page needs, such as the Bing tag, must sit above the opening marker.

Announce a page when it is public, not when it is written

The public server is read only, so announcing at save time would tell Bing about a 404. Announcing is a deploy step that remembers what it has sent.

The browser paints its own dropdowns, and assumes daylight

A select's open list is drawn by the browser, for a light page unless told otherwise; color-scheme: dark on the root, with options in the page's ground and ink, fixed the tag filter and the Pilgrimages menu.

Telling people from machines

The access log records the real address from CF-Connecting-IP, since through the tunnel everything arrives from localhost, and the referrer. tools/readers, and Bible Palace Readers in AdminTools, count only people. A household, grouped by network because a phone renumbers itself, counts once it loads the fonts or entries, and is set aside for ever if it probes for WordPress or PHP, wears the fake “iPhone OS 13_2_3” name, or once called itself a crawler. Visiting means a page past the front, not the prayer book, the Flood or the wheel, which the service worker preloads. Location uses a local DB-IP database keyed by a hash, so no address is stored.

On 5 October: 33 households had read past the front page, 23 came back, 3 were regulars and 6 listened, against 1,599 machines. Google sent 25; ChatGPT fetched pages 14 times for people, nearly all verse pages. On 12 October: 37 had read past the front page, 29 came back, 3 were regulars and 9 had listened to 52 narrations; Google sent 27 and Bing 3, and ChatGPT fetched 47 times for people. From 8 October about 313 Facebook previews a day arrived, nearly all of the home page and evenly spread across Meta's own addresses: a scheduler re-checking the page, not people sharing it. Meta's crawler read 113,737 pages. The prayer book’s Rosary is the most used thing on the site.

Colour is decoration, brightness is the work

The site is built by someone who is colourblind, so no colour carries meaning: reading text stands apart by brightness alone, 17:1 or better on both pages, and gold and crimson, used only on borders, rules, headings and button lettering, still clear 3:1 for a line and 4.5:1 for text. Ratios are measured against the real background and quoted when a colour changes, never judged by eye.

A dark picture on a dark page is still a card

The banner's dark ground was a sixth brighter than the page, so it read as a card, and masks only moved the edge. mix-blend-mode: screen drops every dark pixel to the page colour and adds only the fire.

A phone's first screen cannot be laid out in CSS alone

The home page opens with everything down to Play all entries on screen and the entry count below the fold. On a phone the header's height follows the banner's width, so it is measured once the banner loads and stretched to the room left, again on resize and rotation. A narrow tier trims the star, type and buttons; under 700 points high the star goes. The switch and button are centred, clear of the torches and grails in the bottom corners.

A row taken out of the toolbar is a row the first screen has to give back

On 12 October the five ways of seeing the entries (Within and Without, Constellation, Wheel, Flood, Timeline) folded into one Graphs menu, and the toolbar went from four rows to three: Bible, Prayers, Motif Searcher, Inventory; BibleScape, Graphs, Pilgrimages, Quotes; Saints, Examination of Conscience, Add entry. The row saved let the entry count climb onto a 1080p first screen. A gap under Play all hid it again but read as empty space, so on desktop screens at least 900 points high the banner grows from 39 to 45.8 rem instead, and the picture takes the row back. On a phone the double width Examination of Conscience goes last, so no button stands alone, and the three menus are given the buttons' height outright, because a select ignores line-height. On 14 October + Add entry left the toolbar for a Games menu, the entry form still opening from Leads, and Games and Quotes swapped places; on 15 October the Games menu became one Coliseum button, straight to Heal Coliseum. The rows now read Bible, Prayers, Motif Searcher, Inventory; BibleScape, Graphs, Pilgrimages, Coliseum; Saints, Examination of Conscience across two cells, Quotes.

IIIThe typology corpus

Each entry pairs Old Testament texts with their New Testament fulfilment, reads them through the four senses and is graded by the strength of its evidence.

154entries
22fields each
476links, all reciprocal
140approved tags
144with a Catechism reference
122quoting a Father

Warrant tiers

The distinguishing feature of the dataset: every entry states on the page how strong its claim is.

TierCountMeans
scriptural41The New Testament names or quotes the Old Testament text
patristic72A Father makes the connection, quoted in the entry
traditional17Long standing Church usage with no single citable origin
interpretive23The author's own reading, resting on pattern or verbal correspondence

Entry schema

FieldHolds
ot_ref, ot_text, ot_ref_2, ot_text_2, nt_ref, nt_textOne or two Old Testament passages and the New Testament fulfilment, quoted in full
connectionThe literal sense: what links the two
tropologicalThe moral sense: what it asks of the reader
anagogicalThe final sense: where it lands at the end
warrant, warrant_noteThe tier, and what the evidence does and does not show
patristic_sourceA quoted Father, or empty when none was verified
ccc_refCatechism paragraph, checked against a fetched cache
butlers_saintA saint whose life embodies the pattern
motifsPills, checked for near duplicates across the corpus
prefiguring_figuresCross links to the persons a type is carried by
related_idsChips, kept reciprocal by the linter
tags, eraFiltering, and the eight era columns of the timeline

Search covers every field, not just titles. An entry may also carry pinned, which the server sorts on ahead of the creation date, so that entry opens the site and heads the playlist; Beseleel's tabernacle holds it now.

The empty fields are load bearing. Thirty one entries carry no patristic source and nine no Catechism reference, each left empty because a search found nothing on point: the shepherd’s rod is one of the nine because no paragraph of the Catechism cites any of its verses. A blank records a verified absence, and the site never fills one to look complete.

Every entry checked three ways, 6 October

All 145 entries were read beside Haydock’s notes on the verses they cite, then twice checked claim by claim against the texts on the workstation, 4,792 claims in all (every verse reference, count, speaker, order of events, and Greek or Hebrew word), then the changed entries were read again sentence by sentence against Denzinger and the Catechism. Each finding was put to a second reader told to refute it before it went in. Nothing found undid an entry’s link; the slips were details, about one claim in thirty five.

CheckConfirmed
Haydock’s notes on each cited verse38
Claims, first pass (2,106 tested)53
Claims, second pass with fresh readers (2,686 tested)52
King James spellings of names, by a scan13
Doctrinal wording, in 26 of the 96 entries reread36

The doctrinal points were sentences that say the wrong thing taken at their word, none of them heresy: the Cross ending “sacrifice” where the old sacrifices were meant, the Second Coming written as if it were not a real event to come, omission treated as no sin, Christ’s substitution for sinners denied in passing. The same work traced 121 readings Haydock credits to the Fathers into the Fathers’ own texts; 50 found in English are now cited, St Jerome on Moses and Paul and on Lot’s household among them, and three grades rose, babel-pentecost-tongues and kept-back-by-fraud to patristic and come-lord-jesus to traditional.

IVThe Apocalypse wheel

Not a list of verses. The chiastic structure of the entire book, rendered as a navigable ring.

101nodes
50mirrored pairs
12:9the hinge
  • Pairs are matched by letter, not by position: A mirrors A1, B mirrors B1, and so on inward. A node out of verse order crosses the pairing; 13:1 once stood before 12:17 and left RR answered by the beast.
  • The centre is the dragon thrown down, YY at 12:9, the one node with no partner. The first arm ascends from 1:1 to 12:9, the second descends from 12:10 to 22:20, so A 1:1 "things that must happen quickly" answers A1 22:20 "I am coming quickly".
  • Cross references to typology entries are computed at runtime from every entry's nt_ref; nothing is maintained by hand. Matching is by exact verse key, so of forty six entries citing the Apocalypse only twenty five light a node, ringing thirty of the 101. That is the structure being selective, not the data being wrong.

How it behaves

  • Force directed physics (centre pull, node repulsion, spring links, a hard containment wall) with a deterministic instant settle: the layout resolves before it is shown.
  • Opens centred on the 12:9 and 12:10 turn, and snaps back to centre on every zoom step.
  • Mirror pair highlighting, dim on hover, a pulse glow on the hinge, and a staggered entrance.
  • Pointer Events throughout, so mouse and touch share one path: drag, pinch zoom, boosted touch pan, tap to zoom in and again to zoom out.
  • Background paintings in the manner of Michelangelo, one for day and one for Night Watch, swapping with the theme, in WebP.
  • A verse detail panel: a right side card on desktop, a full bleed bottom panel on mobile.
  • Cross chiasm links. A node matching a typology entry is ringed with a glowing dashed circle, expandable inline, with recursive drill down through related entries.
  • An address of its own, /wheel, with a slim bar: Back to palace, Night Watch, List and Reset. On a phone the labels shorten to Palace and Night, the wheel sits in the middle of the screen and the list opens below it. A first open hint banner is remembered in localStorage.
The first drag after a load, and the grab circle on top

Drags failed in three ways that looked like one. A later node's wide grab circle lies over an earlier node's dot, so a press could seize the wrong node; now the dot nearest the pointer wins. The entrance scaled whole nodes, grab circles included, from the wheel's corner; now it grows only the dot, in place. A direct load of /wheel built the palace behind at the same moment, freezing a drag for up to a second; now the palace waits for the wheel to sit idle two and a half seconds and skips its painting while covered. The wheel also waits for the entry list, or its cross reference rings are dropped.

A freeze the page did not cause

Clicks on the palace sometimes went unanswered for a second or two. Closing the wheel rebuilt the page, because the step that skips painting the palace behind a direct /wheel load also ran when the wheel opened from the palace; now it runs only on a direct load. In Firefox the entry cards going in as one block held a click; they now go in twelve at a time. The rest was not the site. A freeze of about two seconds, some two and a half seconds after each home page load, on no other page and with no script slow, is Malwarebytes Browser Guard scanning the settled page, some 5,400 elements; a clean Firefox had none. Putting the site on its allow list ended it, but other visitors running it will still meet the pause.

VWithin and Without

The whole Douay wound into one spiral, Genesis at the rim and the Resurrection at the centre, with the cross references, the entries and the studies drawn across it. Named for the scroll of Apocalypse 5:1, “a book written within and without”, which the spiral resembles seen end on.

35,804verses on one curve
298,490cross references
2,061typology verse pairs, type to antitype
7ways in
  • Every verse in its place. Two arms of one Archimedean spiral at one unit of curve per verse, so distance along the curve is distance in the canon. At /SpiralWheel, first in the toolbar's Graphs menu.
  • Cross references from OpenBible.info (CC BY 4.0), 344,799 rows mapped onto the Douay numbering and checked against the UBS tables; four with no place in the Douay are left out. The seven deuterocanonical books, which that dataset does not cover, have no cross references; the typology layer reaches four of them (Judith, Wisdom, Ecclesiasticus and 2 Machabees), and no entry yet cites Tobias, Baruch or 1 Machabees. A slider sets how many readers’ votes a link needs, twenty by default.
  • The entries and the studies. Each typology entry drawn from type to antitype; the Third Day study’s verses as lanes beside the coil, told apart by shape, not colour: a turning point a larger filled disc, an ordinary day a small dot, a day of the Law a diamond, an unlabelled verse a hollow ring.

How it is built

tools/build_spiral.py reads bible.json, the OpenBible zip (committed, and refused if its SHA-256 fingerprint differs from the one recorded in SOURCE.json), the hand table spiral/versification.json, the UBS tables in tools/ubs/ for the check below, and the studies. It writes spiral/data/, spiral/MAPPING_REPORT.md and, into spiral.html, a fingerprint of each script in its address, so a changed script is fetched afresh; the same inputs give the same bytes on every run.

  • Mapping to the Douay. The hand table’s 388 rules go first and place 241 chapters: the 208 whose verse counts differ, and 33 whose counts match but whose verses are divided differently, ten of them Psalms. Any other chapter whose count differs stops the build; the other 948 of the 1,189 map verse for verse. A verse goes to the Douay verse holding most of what it says.
  • Every row accounted for. The 344,799 rows are 3,534 under one vote, 4 unmapped (King James Song of Songs 1:1, the book’s title, which the Douay prints as a heading), 46 joining a verse to itself, 42,725 duplicates merged and 298,490 chords; the build stops if the sum differs.
  • Checked two ways. A second route made without the hand table, King James to Hebrew to Douay through the UBS tables and the site’s Hebrew alignment, agrees on 31,008 verses and differs on 74, all in the report. Ten anchors check a Douay home by a phrase of its text, so King James Jonah 1:17 must land on Jonas 2:1.
FileHoldsBytes
manifest.jsonBuild hash, geometry, credit, every other file’s SHA-25610,923
positions.f32x and y for each verse, each a 4-byte decimal number (float32)286,432
chapters.json73 books, 1,334 chapters31,875
kjv-map.jsonThe verse map, read by the daily readings188,704
studies.jsonThe Third Day lanes111,803
xref/b00.bin to b72.bin, 66Every chord touching a book, 10 bytes each5,321,500
xref/band-*.bin, 8Every chord once, by vote step1,790,940
xref/t0-*.bin, 8Chapter pairs per vote step, at most 4,000342,900
All 87 files8,085,077

The geometry

One curve, r = a + bθ, its coils 8 units apart. Verses are placed by arc length, one unit each, never by angle, and the arc table is tested against the exact formula. The centre radius a is solved so that arm one’s rim is twice it: 163.86 and 327.72 units.

  • Arm one winds clockwise inward from Genesis 1:1 at the top to John 21:25 at the edge of the centre: 31,632 verses in 20.48 coils.
  • Arm two is the same curve turned half a round, from Acts 1:1, opposite John 21:25, outward to Apocalypse 22:21 at 59% of the rim: 4,172 verses in 3.72 coils, 4 units from arm one.
  • Spacing. A coil holds about 1,030 verses at the centre and 2,059 at the rim. Neighbours are 1 unit apart and no two verses are closer than 0.999, which at full view is 0.97 px in a 1366 by 768 window, less under a browser’s own bars, and 0.49 px on a phone 375 px wide.

Drawing it

Drawn with the browser’s 2D canvas on three canvases stacked one over another: #sky for the static layers, #flow for what moves, #glow for the highlight. A copy of the d3 library, version 7.9.0, kept in the repository rather than fetched from another site, gives the zoom; its quadtree, an index that splits the wheel into quarters and each quarter again, finds the verse under the pointer.

  • Drawn once per view. The static layers are painted into one picture kept off screen, the size of the screen. A pan or zoom slides and scales that picture each frame; where it no longer fills the screen it is painted afresh, at most every 120 ms, at once when the level of detail changes, and 60 ms after the gesture ends.
  • Detail by zoom. Below 3.5 pixels per unit, chords summed by pair of chapters; above, the 2,500 strongest verse chords on screen; from 10, a dot per verse.
  • One quadratic curve per chord, its control point, the point that sets which way and how far the curve bows, pulled toward the centre, less for a short chord, and lifted where the curve would cut the centre, so chords gather in a bright ring round the Resurrection. Those no curve can carry round run straight across, by Dunk’s choice. A test runs all 560,725 chord shapes; none leaves the wheel.
  • Loaded as needed. The first picture needs the page, d3, the page’s scripts and four data files (the manifest, the positions, the chapters and the chapter pairs at 20 votes); a test holds them under 1.5 MB, and they come to 875,264 bytes. It painted in 423 ms on the dev server on 5 October, before the seven features were added, and has not been timed since. Book chords load when needed, typology comes live from /api/entries with no rebuild, and every address carries a fingerprint of its file’s contents, so a changed file gets a new address and browsers may keep each one for a year.

Seven ways in

  • Reach. How far a verse’s links travel, as a share of the canon, above what its place gives by chance (0.5 at either end, 0.25 in the middle). The 87 verses with thirty or more links at 20 votes are ranked; beacons grow with rank, the upper half ringed, and a tour visits the top twelve.
  • Light from type to antitype. 468 arcs, from the first verse of each Old Testament reference to the first of each New Testament one. Each pulse takes 5 seconds, its tail toward the type. Each arc’s turn comes round every 146 seconds at 468 arcs, the turns spread by the golden ratio so that neighbouring arcs never fire together, and about sixteen move at once; a fixed arrowhead under reduced motion.
  • The shortest chain. A breadth first search over the cross references at the slider’s threshold: every chain of one link is tried, then every chain of two, and so on, so the first found is a shortest. Among equal chains the strongest weakest link wins, then the vote total, then the lowest verse number. The 2,061 verse pairs the typology entries cite may join in at no votes, so they win no tie. Traced hop by hop and kept in the address; the panel says these are chains readers compiled, not steps the sacred writers intended.
  • Scripture answering itself. The chords sorted by later verse and the wheel written in canon order in 30, 90 or 180 seconds, which the caption says is not the order of writing; each link lights as its later verse is reached, a spark flying back to the verse it answers.
  • Today’s readings. The day’s Mass readings under badges lettered I, Ps, II and G, with the links between them. tools/spiral_readings.py takes citations only, from the USCCB’s feed or the Catholic Readings API. The lectionary numbers as the Hebrew and Greek do, so its verses pass through the site’s own alignment and a hand table of 127 places; of 1,472 distinct citations from two years of readings, all are read; 424 of them (every Old Testament and deuterocanonical citation outside the Psalms, and one for each psalm) were compared with the Douay text, and sixteen ranges needed correcting.
  • Sound, off until asked for. Each verse a note on the C major pentatonic, sixteen steps from C3 to C6, Genesis lowest and the Apocalypse highest, panned left to right. A chosen verse strums its links, each step as loud as the square root of its votes: Genesis 1:1 spans all sixteen, John 14:6 a tight cluster.
  • The 3D scroll. A helix 2.4 times the rim’s radius tall, which seen from above is the wheel. Its library, three.js r170, loads only when asked for; up to 24,000 chords, 8,000 on a small screen. Without WebGL or with reduced motion, the flat wheel stays.

Moving around

  • Pointer and keys. A mouse takes the nearest verse within 8 px, a finger within 22; hovering lights every chord touching it, a click opens the panel, and the arrows step along the coil.
  • Search takes the Douay names of all 73 books and the King James and modern names where they differ, always with Douay numbers, and reports a miss rather than guessing. Where a King James name is also a Douay one the Douay book is meant, so 2 Kings 2 is the Douay’s (King James 2 Samuel 2).
  • The address holds the view, as in #path=genesis/3/15~apocalypse/12/9, rewritten in place so Back leaves the page.

Checks

  • The build. tools/build_spiral.py --check passed on 7 October: the data on disk matches a fresh build, anchors 10 of 10.
  • The tests. 46 Python and 26 Node tests pass, from the geometry and the mapping to the routes and the seven features.
  • Still open. Of the 47 chapters where the UBS route differs, three have no note: Leviticus 15 and Numbers 15 and 27.

What the wheel showed

Among the 87 verses with thirty or more strong links, Genesis 1:1 reaches furthest, 0.66 of the Bible against 0.48 for the next; its strongest link to the last book is Apocalypse 4:11, thou hast created all things. John 14:6 is the busiest Gospel verse and reaches almost the least: of its 62 strong links only one, to Isaias 35:8, leaves the New Testament, and its reach, 0.07, is the sixth lowest of the 87. Busy is not the same as near: Matthew 6:33 and 7:7, with 52 and 49 links, reach 0.21 and 0.20. And 41 entries pair verses no cross reference joins, the Eve and Mary knot among them, and three of the newest, I Will Ascend into Heaven, Samson Carries Away the Gates and Booz the Near Kinsman, whose links are the Fathers' alone.

A layout can make any busy verse look like a pattern

Genesis 1:1 hangs from the top of the wheel in a tall, even dome, but most of that is its place: any verse at the top of a circle with links spread through the canon makes a symmetrical fan, and a verse at either end of the canon reaches 0.50 of it even at random. Of Genesis 1:1’s 0.66, 0.16 is its own. So the page ranks all 87 verses by reach above what their place would give, and sizes and brightens each beacon by that rank.

VIThe Flood swell

A second chiasm with a page of its own: Genesis 6 to 9 drawn as one swell of water across a painting of the ark.

31stations
15mirrored pairs
8:1athe hinge
9stations an entry cites
  • Thirty one stations in verse order, the waters rising on one arm and falling on the other, each paired with its twin across the crest: D′ at 9:11, the promise of no flood henceforth, answers D at 6:17, “I will bring the waters of a great flood upon the earth”.
  • The centre, Genesis 8:1a, And God remembered Noe, is the one station with no partner, drawn beneath the ark.
  • A dashed ring marks a station an entry cites, found at runtime from the entries’ references, as the wheel’s rings are. Four entries ring nine stations: Noe’s ark and Baptism, the door in the side of the ark, the bow in the cloud, and the Spirit over the waters, which cites Genesis 8:1 and so rings the hinge itself.

How it behaves

  • The line ripples slowly outward from the ark on both arms, and lies still under reduced motion.
  • Every station is sprung to its place and its neighbours, so dragging one pulls the water round it and it settles back. Dragging the water pans; a pinch or the mouse wheel zooms.
  • A tap, hover, or arrow keys and Enter choose a station and its twin: two cards, one chord between them, and a light running back and forth between the pair. Escape clears.
  • Rank lines draws every pairing at once. List opens the stations in verse order, indented by depth like the wheel’s list; choosing one selects it on the swell, and on a phone the panel closes.
  • A painting for each watch, the ark alone by day and its lit window by night; the bar holds Back to palace, the watch switch, List and Rank lines.
  • Its own address, /flood, reached from the Graphs menu on the palace toolbar and listed in the sitemap and llms.txt.

VIIThe Third Day census

Every third day the Douay names, counted, read blind and set beside four other numbered days, at /Three.

240census verses in five families
0.93agreement of two blind readers, kappa
21sources checked in their own texts
18.1%of verses using three join it to a day
  • Counted, not remembered. Every verse naming a third day, three days or nights, after two days or the day after tomorrow, with every second, fourth and seventh day and forty days beside them, grouped into events so a story told twice counts once. Searches for missed wordings ran until one found none.
  • Read blind. A rule written first decides whether God, His angel or His anointed acts on the day. Two readers, blind to which day each verse named and to what was tested, agreed on 237 of 248; a third settled the rest by the rule’s wording alone. The readers were instances of an AI model; the page says so and why that limits what their agreement proves.
  • What held. Scripture counts days in threes: 18.1% of verses using three join it to a day or night, against 2.5% for two and 3.5% for four; only seven, the week, is higher, and years show no such pull. What did not: a named third day is a turning point in 28 of 65 events, the fourth in 5 of 11, the second in 7 of 22, a difference well within chance, while forty days, the control expected to run high, does, 10 of 13. The page reports both, with the rate under three ways of drawing the census border.
  • The sources checked. Origen, Cyprian, Tertullian, Athanasius, Irenaeus, Cyril, Chrysostom, Augustine and Aquinas, the creeds, the Easter Vigil of both rites and the Catechism, each read in its own text first. Five usual references proved wrong and are marked corrected (Matthew 12:40 is in Aquinas’s question 51, not 53).
  • Built from its data. tools/build_third_day.py writes the page from studies/third_day.json, computing every figure on it, so the two cannot drift; the whole census downloads as a table.

VIIIQuotes

The strongest lines in the entries, lit one at a time from a broken pitcher.

189lines
116entries quoted
1screen, no scrolling

Quotes replaced the Leads button on the palace. It is built on Gideon’s three hundred, who carried “empty pitchers, and lamps within the pitchers” (Judges 7:16) and broke them to let the light out.

The page

  • Judges 7:20 at the head, large: “And had broken their pitchers, they held their lamps in their left hands.” The trumpeters' banner and Numbers 10:1-2 came down on 12 October, and the verse moved up from the foot, where it had stood alone; the pitcher grew into the room they left.
  • A photographed clay pitcher with a photographed torch inside, cut into four shards along its own crack.
  • Breaking it: the pitcher shakes, the crack glows, the shards fly apart and fade, and the torch rises in a widening glow. The line appears, signed Dunk, with its entry.
  • Read the entry opens it in the side panel, Copy copies the line, and Another pitcher sets down a fresh one. A count shows how many have been read, and no line is lit twice until every one has been.
  • Back to palace on the left of the bar and on the right a Day and Night Watch slider, labelled with the mode it goes to.
  • One screen without scrolling, checked with the longest line on a small phone, a tall phone and a short laptop. With reduced motion the shards and torch fade in place.
A blend needs something to blend with

The photographs sit on black, and mix-blend-mode: screen drops the black into the page. The shards blended one by one, and while the pitcher shook its animation gave it a layer of its own, so the shards blended against nothing and their black corners showed as boxes, by day and by night. The pot now blends as one group and the shards inside it draw normally.

The lines

Each line is one encouraging sentence that stands alone, taken from an entry, nearly all from its moral reading or its reading of the last things, and at most 173 characters. None is Scripture or a Father, so each is signed Dunk. Lint rule 34 holds every line word for word to its entry, so six were updated on 6 October to follow corrections there. Rule 33 watches for a lowercase he or him for God or for Christ.

Addresses

/quotes opens the palace with Quotes showing, for bookmarking. /quotes.json serves the list in a fresh random order on every request, open to other sites, so a browser’s new tab page can draw its line from it. Leads now opens only at /leads, behind its password.

The picture that lost its shadow

Both photographs sit on black, so cutting the pitcher out took its shadow too; blending them onto the page keeps it. The glow behind the torch is wider than a phone, so the view must be clipped at its edges or the page scrolls sideways; that rule was lost once in a later edit.

IXViews and content

The constellation

Every entry as a star, joined to its related entries, on the Apocalypse wheel’s engine and look.

  • The wheel’s physics. Centre pull, repulsion between every pair, a spring per link and a containment wall, settled before drawing so the sky opens still. Drag a star and its neighbours follow, then settle back.
  • Built for 800. A far cell of stars acts as one weight at its centre of mass (Barnes-Hut), so a step costs n log n rather than n squared, and the links are drawn as one path. On a synthetic 800 stars and 1,630 links it opens in under half a second, at 3 milliseconds a step against nearly 5 for pairwise repulsion alone.
  • A sky the shape of the screen. The wall is an ellipse, wide on a laptop and tall on a phone, its area growing with the entries, so the spacing that holds at 153 will hold at 300.
  • Tier by ring, never by colour. Two rings for scriptural, one for patristic, dashed for traditional, bare for interpretive, with a legend. Size follows links; the most connected star pulses like the wheel’s hinge and is named first. A name shows only where it clears every name and star placed, and holds its size under zoom, so closer looks name more.
  • Hover lights a star’s neighbours and links, with its references in a tooltip; tap zooms in and opens the entry, tap again steps out. List gives every entry, most connected first; Night Watch, Reset, pinch and wheel zoom.
  • The heavenly host behind it. A painting after Hildegard of Bingen’s choirs of angels (Scivias I.6), in the manner of Blake and Michelangelo: the host round a rose window, gold by day, crimson for Night Watch. Dimmed to about two fifths, it leaves a gold star at about 3:1, measured, against nine tenths of the picture; every star keeps a black outline. A seeded starfield twinkles unless the device asks for reduced motion.

The timeline

Type and fulfilment. Each entry stands twice: in the era of its Old Testament type, in book and chapter order, and in the New Testament era that fulfils it. Hover or tap one and an arc rises from type to each fulfilment, lighting its related entries.

  • The type’s era is the era field; fulfilment eras are read from the New Testament references at runtime, so nothing is kept by hand.
  • A card’s left edge gives its tier: double, solid, dashed or dotted. Columns scroll separately; choosing an entry brings every place it stands into view. Zoom by button, pinch, or Ctrl and the wheel.
  • An era outside the eight falls silently to Eschaton; linter rule 27 catches it.
EraEntriesCovers
Creation21Genesis 1 to 11
Patriarchs19Genesis 12 onward, and Job
Exodus41Exodus, Numbers, Deuteronomy
Monarchy51Judges, Kings, Psalms, Isaias, Osee, the Canticle
Exile21Ezechiel, Daniel, Zacharias, Isaias in part, Judith, Malachias
Christ83Fulfilments in the Gospels
Church66Fulfilments in Acts and the Epistles
Eschaton47Fulfilments in the Apocalypse

The type columns hold the 153 entries; the fulfilment columns hold 196, as an entry fulfilled in two eras stands in both.

Reading and writing

ViewBuilt from
Entry list and detailFull text search and tag filtering across every field
Bible readerDouay-Rheims chapter browser with verse jump and Challoner's notes beneath their verses, opened from any entry, wheel node or story
JournalPersonal entries, writable when not read only; its toolbar button went to Flood on 23 September, the data untouched
Flood/flood, Genesis 6 to 9 as thirty one stations turning on Genesis 8:1a; its own section
Prayers/prayers, Dunk's Prayer Book: twenty prayers in four sections, the guided Rosary and prayer for the hour, each with its Latin and an About panel of Scripture, Fathers and Catechism
Saints/saints/, the whole Butler's Lives, searchable, not a scraped snapshot: server.py proxies to the Lives of the Saints API at request time. Separate from the per entry saint attributions in the corpus

Content volume

73books, Douay-Rheims
1,334chapters
35,804verses
20prayers
7narrative games
46game scenes

The whole Douay-Rheims, Deuterocanon included, is served from local JSON with no outside dependency. Challoner's 1,894 notes came stuck to the ends of 1,407 verses, so the reader showed them as Scripture and narration read them aloud; tools/split_douay_notes.py files each under its verse.

The games

GameOpens atNodes
Passion Weekjerusalem9
Joseph in Egyptcoat8
The Nativityannunciation8
Who Do You Say I Am?calling6
Acts of the Apostlespentecost6
The Apocalypsepatmos5
Saul's Conversionroad4
  • A node based engine with flag gated choices: hotspots carry flag, requires, gate and trial, so an earlier decision opens or blocks a later one. labelWhen relabels a choice once a flag is set; elseMessage toasts why a blocked action will not open. Each story keeps its own persistent save.
  • The menu is Pilgrimages on the toolbar. BibleScape, renamed from DunksBibleScape on 12 October, offers Play and Hiscores, each in a new tab; Within and Without, the Constellation, the Wheel, Flood and the Timeline sit in the Graphs menu between them. Heal Coliseum, a game of another kind, has its own Coliseum button after Pilgrimages and its own section, below.

XHeal Coliseum

A raid healing game in three battles of Scripture, at /healcoliseum from the toolbar’s Coliseum button, with a shared board that believes no score until the server has fought the battle again itself.

3fights on one engine
60integer ticks a second
8remedies
4rounds of attack before it went live
213attacks tried and held
209 + 144Python and Node tests
  • Its names. It began on 14 October as Divine Favor, a raid healer in the manner of a World of Warcraft Holy Paladin. It was made Bible themed the same day as Raphidim, on Exodus 17, and renamed Heal Coliseum when it grew to three fights; /raphidim still answers. It went live with the shared board at commit 89fd0af on 15 October.
  • The field. The player is a Levite among forty men of the eight tribes, five to a tribe, with eleven other healers whose healing is pooled and shown in a tally. Two men take the heavy blows in front and twenty six fight. The enemy gives way only while the fighting men stand: its strength is counted in seconds of the whole army fighting, about 95 in the first phase and 120 in the second. The battle is lost if the player falls, if fewer than twelve stand, or at sundown, 330 seconds in.
  • The grade is the statue of Daniel 2: Head of fine gold from 99, Gold from 90, Silver 75, Brass 50, Iron 25, Clay below. Healing per second against the fight’s target (430, 403 and 337) gives up to 62, a victory 30; each death beyond two costs 2.5, each point of wasted healing over 20% costs 0.45, and each wound anointed adds 0.6, up to 6. A loss is held under 50.

Anti-cheat at a glance

  • Scores cannot be faked. The browser sends only what was pressed; the server fights the battle again itself, and the score on the board is the server’s own.
  • The future cannot be seen. A battle’s luck is revealed as it is fought, so nobody, the server included, can plan the battle ahead.
  • Tickets. Every ranked battle needs a signed ticket that is good once, for one fight and one name.
  • Real time. A ranked battle must be fought as it happens; pausing or slowing it turns it into practice.
  • Bot checks, with review. Play that looks more like a program than a person is held for the keeper to judge rather than refused, so a strong player is never turned away by a statistic.
  • Names. A name can be locked with a password, and look-alike spellings count as the same name.
  • Battle counts. Every ranked battle a name fights is counted, only the owner can raise a locked name’s count, and counts never go down.
  • The keeper’s controls. The keeper can approve or reject held runs, remove scores and ban names, behind a password that guessing cannot wear down.
  • The site stays safe. The game’s endpoints are flood limited and fenced off from the rest of the palace, which carries on unharmed if the board goes down.

The three fights

Every fight has two phases on the same engine. What differs is its names, how hard its blows land, how much of the damage the other healers make good (70%, 67% and 65%), how deep its wounds fester, and whether one huge blow is called before it falls.

FightFirstThen
Raphidim: Amalec (Exodus 17:8). The gentlestAmalec’s archers: volleys that glance from one man to his neighbours, and the raiders’ charge across three tribes, warned by the tribes’ namesThe whole host: sling stones on everyone, burning arrows, festering wounds to anoint, heavy blows on Josue. Twice Moses lifts up his hands and for 12 seconds no blow lands; manna lets the oil flow freely for 20
Valley of the Terebinth: Goliath (1 Kings 17). HarderThe giant with the Philistine lines, and his spear, “like a weaver’s beam”: every 9 to 12 seconds one man is marked, and 1.6 seconds later takes 2,300 to 2,800The pursuit to Accaron once the stone is fixed in his forehead: arrows from the hills, spear wounds, the rearguard on Jonathan; the Philistines scatter and no blow lands
Bethzacharam: the Elephants (1 Machabees 6). The hardest: the other healers carry leastArrows from the towers, an elephant’s charge, and a beast trampling one marked man every 11 to 14 seconds for 2,200 to 2,700Eleazar runs beneath the great beast, and the king’s host comes on: the blaze of the shields on everyone, burning darts, deep wounds, the phalanx on Judas; Judas rallies the men and no blow lands

A festering wound strikes every 2 seconds for 20 unless it is anointed. While no blow lands the enemy gives way 2.2 times as fast.

Remedies and binds

RemedyMouse and keysTouchDoes
Balm of GalaadLeft click, 1Arm, tap1.5 s, 140 oil, 600 to 680 (Jeremias 8:22)
Bind Up WoundsShift+Left, 2Hold a man2.5 s, 660 oil, 2,200 to 2,500 (Luke 10:34)
Laying on of HandsRight click, 3Arm, tapAt once, 335 oil, 900 to 970, every 30 s, calling on Fervent Prayer first when it is ready (Mark 16:18)
Anoint with OilMiddle click or Ctrl+Left, 4Arm, tap120 oil; heals a festering wound (James 5:14)
Fervent Prayer5Tap90 oil; the next healing is abundant, every 2 min (James 5:16)
A Double PortionShift+9Arm with a second tapOnce a battle: heals as much as your own full health, 4,900, and spends all the oil (4 Kings 2:9)
The Girdle of EliasShift+1Tap33% faster for 20 s, every 5 min (3 Kings 18:46)
The Widow’s CruseShift+7Tap1,350 to 2,250 oil, every 2 min (3 Kings 17:16)
  • Mouse and keys. Keys 1 to 5 act on the soldier under the mouse, or the last one clicked, and each button’s corner names its binds (“2 · Shift+Left”). A remedy pressed in the last 0.4 seconds of another waits its turn. W, A, S and D move: moving stops what is in hand, and while moving only the instant remedies work. P pauses.
  • Touch. A tapped remedy is armed: it glows and its corner reads Armed in words, and every soldier tapped then gets it, cast as the finger lifts so a slide casts nothing. Holding a soldier for 450 ms gives Bind Up Wounds whatever is armed. Prayer, the Girdle and the Cruse work at once; after Laying on of Hands or A Double Portion the last heal is armed again. A large Stop button takes the movement keys’ place and ends what is in hand.
  • Oil trickles back, faster after five seconds without spending (“be still”, Psalms 45:11), much faster in the boon. A remedy heals its least as it lands; the rest of its roll, the blessing, and whether it was abundant, follow a moment later. Abundant healing, about one in five, returns the oil it cost.

The layout

  • One screen. The title, with the battle’s calls in red beside it, and a pill reading Ranked battle or Practice in words. The cast bar centred above the grid, the oil bar straight beneath it in a thick black frame with its numbers outlined, messages such as Your hands are busy in a line under it, off the grid. The eight tribes as raid frames, the enemy’s bar and warnings below, the remedies along the foot.
  • Tiles in the palace’s colours, calling as a side stripe, a striped white preview of the heal in hand, names in pale letters with a crisp black edge. The player’s own tile carries a solid YOU badge. A marked man’s frame pulses.
  • On the right an arcade cabinet of high scores (rank, healing per second, name, and battles fought as “x37”), with the healers’ tally under it. A smaller window keeps that column beside the battle; only phone widths stack it below. On a phone the cast and oil bars stick to the top and the remedies are pinned to the foot in two rows of four, Stop down the side.
  • It opens in Night Watch, the palace’s red lamp on black, unless the player last chose day, which is ember gold on the void. The start card holds the fight, Night Watch and sound, the name and lock box, the story and the binds; the cards are dialogs, with the page behind them inert.

The engine

coliseum/engine.js is the one source of truth. The page plays it in real time and the server replays it under Node, and the two must reach the same result to the last bit.

  • Seeded and counted. Every random number comes from a seeded generator; the clock is an integer count of ticks, 60 to the second; every sort has a total comparator. The player’s presses, each with the tick it falls on, are the only thing that changes a battle.
  • Exact arithmetic only. Addition, subtraction, multiplication, division, floor, round, square root, Math.imul and integer bit operations, which IEEE 754 makes exact in every engine. No exponential, logarithm, power or trigonometry, no exponent operator, no clock, no locale, no number formatting. coliseum/tests/static.js scans the engine and fails if one creeps in.
  • The same everywhere. coliseum/tests/crossengine.js plays many battles and prints one fingerprint, all 7cf82958, identical in V8 (Node, on this PC and on the server), JavaScriptCore (bun) and SpiderMonkey (headless Firefox 158).
  • Built to match. Engine version 4, hash d868d99e0921. tools/build_coliseum.py builds healcoliseum.html from coliseum/healcoliseum.src.html, loading the engine from /coliseum/engine.js by its hash and carrying its full SHA-256; the server gives a ranked ticket only to a page whose engine is byte for byte its own, so a stale page plays practice. --check fails if the page is out of date, and --preview writes a standalone copy that plays practice only.

A ranked battle

  • The ticket. Before a ranked battle the page asks for a ticket, signed with a key only the server holds and naming the fight, the engine and the name. It is good once, and only for a short while.
  • Luck revealed as it is fought. The battle’s randomness is not handed out at the start. As the battle goes on, the page sends what has been pressed and receives the luck for what comes next, made from the presses already committed, so the future does not exist, even on the server, until the presses that lead to it are fixed, and the past cannot be rewritten once it is out. A heal’s luck is settled only once it can no longer be stopped.
  • The replay. At the end the server replays the whole battle from the presses alone, on its own copy of the engine. The score on the board is the replay’s, never the browser’s.
  • Real time. A ranked battle must be fought at the speed it happens. On the page, Pause, a hidden tab or a long stall turns the battle into practice and gives up its ticket; on the server, a battle that ran slower or faster than real time allows is refused or held, with a modest allowance for an ordinary connection’s hiccups.
  • Verdicts. Each run is given one of three. What no honest page could send is refused. Timing that a person very rarely produces sends the run to the keeper’s review instead of refusing it, because no check is certain enough to turn a strong player away; the checks speak only when chance cannot explain what they see. Everything else goes straight on the board.
  • The review queue. A held run waits with the engine it was judged by, shown to the keeper in plain words. The queue is bounded so that no one visitor or name can crowd out anyone else’s run. Approving replays the run again and records the replay’s own result, so a held run can never be worth more than it was.

Names

  • Latin only. Two to twelve characters: Latin letters, accents welcome, digits, spaces, hyphens and apostrophes. Other scripts and mixed alphabets are refused, as are blocked words. Levite, the name everyone shares when the field is left empty, never goes on the board; a refused name fights practice and says why.
  • Look-alike names. A name is kept by a key that folds case and the letters and digits that look alike, so one name cannot be passed off as another, and a ban on a name covers its look-alikes.
  • Optional locks. Tick the lock box and give a password of 6 to 64 characters. The server keeps only a slow, salted hash of it, and a remember-me token keeps the device signed in, likewise kept only as a hash. A name already in use cannot be locked simply by asking for it.
  • Wrong passwords. Wrong guesses are limited and lock out for longer each time, while a remembered device is always heard. The keeper’s door is guarded like every other password door (section II).

Battles fought

The board counts every ranked battle each name fights at each fight, won, lost or left, and shows the count beside the name (“37 battles”). There is no daily cap: a name that fights hundreds of battles to keep its luckiest says so beside its score.

  • The name is settled at the ticket and signed into it, and a battle goes on the board only under its ticket’s name. It counts once, early in the battle, whether it is then won, lost or left; a ticket never used counts nothing.
  • A locked name’s ticket needs its token or password, so only its owner can raise its count; keeping the count one’s own is one reason to lock a name.
  • Counts only go up. Deleting a score or releasing a name leaves them, and a crash can neither lose a count nor double one.

Floods, and the rest of the site

  • Flood limits. Every one of the game’s endpoints is rate limited for each visitor and for everyone together, a visitor may have only a few battles under way at once, and oversized requests are refused before they are read.
  • The read-only exemption. The game’s writes are the only ones the public server accepts. They write nothing but the board’s own state, and every request is limited and size checked before it is read.
  • The import guard. The palace loads the game’s server code and builds the board under a net. If either fails, the game’s endpoints stand down, the engine is still served so the game plays practice, and the rest of the palace never notices.

State and the keeper’s tool

The board keeps its state in its own folder on the live box, written atomically under one lock, and no file path is ever built from what a request sends. The signing key never leaves the server, passwords are kept only as hashes, and no address is stored. Battles under way live in memory only, so a restart ends them and the page plays on as practice. The keeper has an admin tool on the box for the review queue, the boards, names and bans, and backups; its password is never typed on the command line.

The rebalance

Rebalanced so that standing idle loses every fight, with each fight’s healing target set so that an expert bot’s victories average about grade 95. The owner chose: cleansing is optional and padding is allowed, with no penalty for wounds left and 0.6 a grade for each anoint; Raphidim stays the gentle fight; there is no daily cap on battles; and the board shows battles fought. Three bots in coliseum/tests/bot.js play at a person’s pace, seeing the field a little late, as a person does: idle presses nothing, plain is a decent greedy healer, expert paces its oil and saves marked men. Three hundred seeds per fight and bot, on the final engine:

FightBotWinsHealing a secondGrade on winsDeaths
Raphidimidle0%0–22.5
Raphidimplain98.7%43094.02.47
Raphidimexpert100%41595.30.99
Terebinthidle0%0–23.1
Terebinthplain83.3%40781.98.86
Terebinthexpert98.0%41095.02.83
Bethzacharamidle0%0–24.7
Bethzacharamplain60.7%40481.015.06
Bethzacharamexpert93.7%41095.56.23

On Raphidim the plain bot grades 94.0 on its wins against the expert’s 95.3, so the gentle fight does not tell a decent healer from an expert; that was left so on purpose.

Four rounds against it

Built and attacked by teams of agents over 14 and 15 October, about 12% of a weekly plan limit in all. Rounds 1 and 2 each had a red team, a fix pass, then a fresh re-attack and a critic against the fixed version. Round 3 fixed what those last two found and was attacked again by a re-attack and a critic. Round 4 built the battle counts, attacked them, fixed them and attacked the fixed version.

RoundFindingsConfirmedAttacks held
1. The board353176
2. Review, phones, rebalance483690
3. The last re-attack8633
4. Battles fought per name11614
All four10279213

Of the 79 confirmed findings, 72 were fixed in the pass that followed, nearly every one with a regression test. The other seven were settled otherwise: made harder rather than stopped, left as a deliberate choice, such as Raphidim staying gentle, or found to be no defect. The rounds also mended the phone layout and the site’s other password doors.

The tests grew with the rounds, from 60 Node and 58 Python to node coliseum/tests/run.js at 144 and py -m unittest tests/test_coliseum.py at 209, both passing again on 15 October. Beside them, live_page.js plays the built page against the real board (28 checks), layout_chrome.js checks in headless Chrome that every soldier fits a phone and the grid never jumps, crossengine.js gives the fingerprint, and bot.js and balance.js give the benchmarks.

The first record. On 15 October Dunk set the first verified record, at Bethzacharam, the hardest fight: 538 healing a second, grade 100, Head of fine gold, 4.1% of his healing wasted, nine wounds anointed, eight men fallen, won in 3:26, under his locked name, after three battles. The expert bot averages 410 there.

Accepted limits

No system fully stops a skilled bot playing in real time at a person’s pace; this one makes it harder, and sends suspicious runs to the keeper’s review rather than trusting them.

A score the browser sends is a score anyone can type

The game’s first high scores were the page’s own, kept on the device, and any number a browser reports can be typed by hand. So the shared board never takes the browser’s result: the browser sends only what was pressed, and the server fights the battle again on its own copy of the engine; the number on the board is the replay’s.

Randomness given at the start is the whole future

Hand a battle all its luck at the start and a program can search the whole battle offline for the perfect run. So the luck arrives as the battle is fought, made from the presses already committed, and nobody, the server included, can see far ahead.

Math.exp is not the same number in every browser

Engines may differ in the last bit of an exponential or a sine, and one bit, carried through a five minute battle, can decide who dies. So the engine uses only arithmetic that is exact everywhere, a static test forbids the rest, and the one exponential it needs, the other healers’ 3 second smoothing, is written in as a literal.

A paused battle is a thinking battle

Freezing or slowing the game lets a player or a program study the field. So a pause makes the battle practice, and the server’s allowance for lag does not refill, because an allowance that can be refilled will be.

XINarration

Every entry can be read aloud in a cloned voice, generated ahead of time so no visitor waits on synthesis.

153entries narrated, all current
1.7 GBaudio cache
11 mincompute per entry
5,000character ceiling
  • Coqui XTTS-v2 on CPU, cloning from one reference recording in Narrations/.
  • Read in order: title, Old Testament reference and quote, any second text, New Testament reference and quote, the connection, then the tropological and anagogical senses. Warrant, sources and saint are not read.
  • Cached as sha256(cache_key + text)[:20].wav, so any edit to a spoken field makes a new file and stale audio is never served. Batch runs skip existing files, so they resume.
  • The 68 entries the 6 October corrections changed were recorded again on the workstation and uploaded on 7 October, with the new entries’; all 153 recordings are current, and tools/audio_check.py finds none missing and none left over.
  • tools/audio_check.py lists orphaned recordings and entries lacking a recording of their current text, on both machines, and removes leftovers on request.
  • A change of capitals or spelling reads the same aloud, so its recording is renamed to the new text’s key, not made again; on 27 September that saved some twelve hours of compute.
  • Text past 5,000 characters is truncated silently, in the audio only, while the page still reads correctly. The entry form refuses it; a direct file edit goes around the form, and linter rule 19 catches that, as it did two entries that had lost their last words.
  • The public server ships the cache without the TTS stack: audio is generated locally and copied up, never regenerated in production.
  • The availability gate, /api/speak/available, reports only whether the server has a synthesiser or any recording, not whether the thing asked for exists, so a button can pass it and still fail: every prayer once carried one, and eight of the nine answered 500.
  • On typology cards and the map and timeline popups; deliberately not on Prayers, Bible or Journal, which are for reading and writing.

Play all

  • A single control under the Night Watch switch plays every entry on screen in turn, so a search or tag filter narrows it. All 153 run nine hours and fifty three minutes, measured from the cache on 13 October.
  • The next recording is fetched while the current one plays, so an eight megabyte file never stalls the queue; an entry with no recording is skipped silently.
  • Back and Next flank the play and stop button only while something plays. Back restarts the current entry, stepping to the previous one only near the beginning.
  • The media session is populated: a phone's lock screen shows the entry title, and its pause and skip controls work without unlocking.

XIIThe linter

A custom checker for theological data, forty one rules long, enforcing citation hygiene, internal honesty and the reverence of the house style. It cannot and does not judge doctrine. Rules 39 to 41 and a wider rule 1 came on 6 October, each for a kind of slip two full reading passes kept missing.

RuleChecks
1Douay-Rheims name forms on whole words, quoted text exempt: Noe not Noah, Isaias not Isaiah. Its map of King James names grew by 37 on 6 October, Pharaoh for Pharao among them
2Ambiguous 1 Kings and 2 Kings citations, since the Douay numbering differs
3Patristic tier with an empty source, a real bug; traditional tier listed for awareness only
4Every Catechism reference resolves against a locally fetched cache of paragraph text
5Tag drift against an approved list of 139
6Entries tagged as explicit New Testament typology, surfaced for manual review
7Near duplicate motifs, by Jaccard similarity
8A warrant badge contradicted by its own warrant note
9Em and en dashes, or a hyphen with a space either side standing in for one, in authored prose, quoted translation exempt. It reads the corpus, not the page, so the site's interface was swept by hand
10Every related_ids target exists, and every link is declared on both sides
11Greek lemmas an entry's Septuagint shares with its Greek New Testament, ranked by rarity, so xylon stands out and kai does not
12Whether a scriptural badge records that it was checked in the originals rather than asserted from the English
13An explicit citation sharing almost nothing with its Septuagint verse, which usually means the writer followed the Hebrew
14One noun running through three or more entries, invisible to rule 11, which compares an entry only with itself. Report only
15A verse just outside the citation sharing more with the other Testament, as Romans 15:12 quotes Isaias 11:10 where the entry cited 11:1. A question, not a fault
16Transliterated Greek in a note but absent from the verses it cites. It cannot catch a wrong gloss, only a word on the wrong verse, the error that survives rereading
17One word cited two ways by the two corpora, hiding a real match from rule 11. Reported, never merged, since aleipho and exaleipho are different words
18Every quotation that claims to be scripture, read as running text against the Douay the site serves; a quotation spanning two verses is not an error and is not reported. Matching each word within three verses, as it first did, let sixteen altered quotations through
19An entry too long for its narration, whose audio is cut mid-sentence while the page reads correctly. Warns from 90%
20A cited verse not in the Douay, which resolves to nothing and so looks like a real result of no shared vocabulary
21A patristic quotation not found in the Father it names, sought on folded text in Schaff's 37 volumes and the Catena Aurea. Gregory's Moralia, not in Schaff, is checked by hand against the Library of the Fathers and recorded in quotes_verified.json
22A tier the strength report does not bear out: patristic with no Father's words found and none citing both verses; scriptural with no word shared in any language; interpretive or traditional where a Father cites both. A question. --clear-tier records in tier_checked.json who was read and why; a Father not yet read reopens it
23A Catechism paragraph citing none of the entry's verses, listed beside those that do. A suggestion, not a fault
24Two entries on the same Old and New Testament chapters, which rule 7's wording comparison misses; related pairs for awareness only
25A note arguing from the Greek or Hebrew of a passage the site has not matched, so a reader cannot check it in the Motif Searcher. A book the language never had, like the Hebrew of Wisdom, does not count
26Derived files out of step: leads or strength reports older than typology.json, a missing strength report, narration missing or left over. Each line names the command that refreshes it
27An era the timeline does not know, which it would silently draw under Eschaton, at the end of history. The server checks the era only when an entry is created
28A verse in King James wording where the Douay reads otherwise, from a list of six such as "eat dust" for "earth shalt thou eat". Unquoted prose only
29A citation the Douay cannot resolve, or any part of a reference field the parser could not read at all
30Quotations of the Fathers reported located or not; a miss may be a chapter nobody harvested, so it reports rather than accuses. Hand checks go in quotes_verified.json with where each was read. All 287 are accounted for
31A Catechism reference that is not one paragraph the cache holds
32An entry not yet read against Denzinger. Each reading is stored as a fingerprint of the prose, so any edit brings the entry back; tools/mark_doctrine_checked.py records a new reading. All 153 are current. A change of capitals or spelling alone is re-marked only once shown to be nothing more
33A lowercase he, him, his, thee or thy in a sentence naming God, in the entries, the prayer book, the Rosary and the Examination; the capitals are kept for the Father, the Son and the Holy Ghost, not even for Our Lady, and a sentence that would open with one meaning a man is written so it cannot be mistaken. Each sentence is read once and cleared, coming back only if edited, since a pattern cannot tell God finished his works from God speaks to him, meaning Moses
34A line in Quotes that no longer stands word for word in the entry it names, under that entry’s current title
35American spelling or a curly apostrophe in authored prose. The house style is British with -ise and plain apostrophes; quoted sources keep their own
36A sacred word to read against the house style: the Cross, Temple, Law, Passion, Resurrection, Ascension, Christ’s Blood and Body, Baptism and the Bridegroom where they mean His, each cleared once where the lowercase is right. St. and Holy Spirit cannot be cleared
37Rules 1, 9 and 28 run over the prayer book, the Rosary, the Examination and Quotes
38Loose stars in the constellation: an entry with no related entries or a single link, or a group apart from the main sky. Report only, a reminder to link a new entry; every entry has been in the main sky since 27 September
39A capitalised word in an entry’s own prose that the Douay never uses; its first run found 13 King James names the readers had missed. Words found right go in tools/douay_words_allowed.json
40A quotation of three words or more beside a verse reference that is nowhere the Douay’s wording, such as "God remembered Abraham". Non-Scripture quotations read once go in tools/quotes_not_scripture.json
41A verse named inside the prose that is not on the site; rule 20 checks only the three reference fields. It caught a bare "(16:25)" after "as Job said", which reads as Job

The night the corpus was audited

On 21 September every text field was checked against its sources. It found six citations reading Psalm where the Douay's book is Psalms, thirteen that continued with a bare chapter and so were invisible to every tool, twenty two verses stored from the middle with no mark of the elision, a few smaller slips, and one quotation that does not exist.

The instrument was wrong more often than the corpus

Of the problems first reported, one was real. The rest were the checks: a near-quotation rule that flagged sixty of ninety five entries and missed the case it was built for; a Fathers check that compared character for character and stopped at paragraph breaks Schaff's editors had added; a quote splitter that took the author's connecting sentence for a Father. A checker that cries wolf is worse than none, because the corpus is then edited to satisfy it.

Normalising a reference silently destroys its narration

A recording is named by a hash of the text read aloud, and the reference fields are read aloud. Correcting Psalm to Psalms and writing out bare chapters silenced twenty one entries until each was generated again, with nothing visible on the page. Before any mass edit of ot_ref, ot_ref_2 or nt_ref, count the recordings it will cost; patristic_source, warrant_note, tags and the Catechism reference are not narrated.

Proving the Fathers, not trusting them

Rules 21 and 30 cannot use schaff_passages.jsonl, which keeps only paragraphs that cite scripture, so a sentence of Ambrose with no verse in it would be reported missing. tools/build_fathers_fulltext.py walks the same CCEL volumes and keeps every paragraph, 74,224 of them, 90 MB, local and gitignored like the other sources.

Checked against Denzinger

On 23 September every sentence the site says in its own voice was read against Denzinger's Sources of Catholic Dogma (the English of the older numbering) and the Catechism. Nothing taught against the faith was found. One line contradicted a definition as worded: the burning bush said Mary gave her consent "and nothing else" to the conception, where Leo's Tome and the Second Council of Constantinople define that the Word took His flesh from her (D 144, 218). It now says she gave her own flesh, and seven smaller things were put right with it. It is a careful reading, not an imprimatur.

A keyword sweep finds topics, not claims

A first pass searched by the vocabulary of defined doctrine and caught the burning bush only because that sentence happened to say Mary. Three of the eight corrections were in sentences no keyword would have found. The reading that counts is the whole reading.

Each of the 433 pairings of an entry and a Catechism paragraph was also read side by side: no contradiction, and six references exchanged for a paragraph nearer the point. fetch_ccc_cache.py pulls paragraph text for any new reference into ccc_cache.json, currently 145 paragraphs; the linter itself never touches the network.

What the linter cannot do, done by hand

Rule 4 checks that a Catechism paragraph exists, not that it is on point, so every attribution was read back against the text it names.

  • No false attribution was found, to a Father or to the Catechism.
  • Four entries named a Father without quoting him. All four now carry his own words.
  • Four quotations were paraphrased inside quotation marks. Rule 21 caught what rereading had not; each now carries the translation's exact words.
  • One citation is a Doctor, not a Father. Aquinas on the forty days; the field says so on the page.

XIIIGreek and Hebrew

Every entry was written from the Douay-Rheims, and a link that holds in English can fail in the writers’ own languages. Three corpora are cached locally so a claimed echo can be checked where it was made.

1,021distinct verses in the reference fields
3source corpora
87notes recording a check in the originals
1entry the Greek overturned
CorpusSourceAnswers
SeptuagintCATSS, lemma taggedWhat the New Testament writers were reading
Greek New TestamentSTEPBible TAGNTWhat they wrote
HebrewSTEPBible TAHOTWhat the Old Testament says

Only the two Greek texts are compared with each other. CATSS is for non-commercial use and this repository is public, so neither the corpora nor the cache built from them is committed: the fetch script pulls the data once, and the language rules run on the workstation and report themselves skipped on the server.

Looking things up

  • tools/claims_lookup.py verse "Book c:v" prints a verse in the Douay, Latin, Septuagint or Greek New Testament, and Hebrew. find greek|lxx|hebrew|latin|douay WORD [--lemma] counts every verse and occurrence, labelling Septuagint and Hebrew hits with the Douay verse they map to (the Septuagint’s 1 Machabees 1:54 is the Douay’s 1:57).
  • tools/father_search.py searches the Fathers on the workstation by verse, by words or by exact phrase.

What it found

  • The tree and the Cross are one word. The Greek Genesis and the Apocalypse call the tree of life xylon, and the apostles choose xylon over the ordinary word for cross.
  • One entry was wrong. The onyx entry traced that stone from Eden to the City, but the Septuagint has none at Genesis 2:12 and the Apocalypse has sardonyx where Ezechiel had onyx. It now rests on the seven stones Ezechiel 28:13 and Apocalypse 21:19-20 share.
  • Two writers follow the Hebrew rather than the Greek. The Apocalypse has the key of Isaias 22:22, which only the Hebrew has, and Matthew writes my son where the Septuagint has his children; both are evidence of deliberate citation. Paul recites the Septuagint word for word at Romans 15:12.
  • Ten entries carried warrant nobody had claimed, among them metopon across Ezechiel 9:4 and Apocalypse 7:3.
  • No tier was changed. The tiers record who draws a connection, and a shared Greek word does not make one writer cite another.
  • The hand audits overturned nothing more. Every patristic and Catechism citation held against its source; the faults were four entries paraphrasing a Father, one stale caveat and the eleven King James drifts below.
A versification mismatch is silent

It returns the wrong verse without an error: Douay Psalm 109 is Hebrew Psalm 110, so the Melchisedech entry was read against the wrong psalm. Alignment is now checked by scoring each verse's English glosses against its Douay text, and the caches follow each text’s own numbering, so Numbers 16:36-50 finds the Greek and Hebrew 17:1-15. Of Ecclesiasticus, whose Vulgate adds whole verses, only chapter 24 is mapped verse by verse.

STEPBible writes two references where numbering differs

Dan.4.26(4.23) gives the standard reference, then the Hebrew in brackets; a pattern expecting the row marker straight after the verse silently drops every verse in such a passage, which is all of Daniel 4. The bracketed one matches a Douay citation, since the Vulgate numbers with the Hebrew.

The corpora spell the same word differently

Xylon from CATSS and from STEPBible compared unequal, one composing its accents and the other not, so the tool ran clean and found almost nothing; normalising both at cache build took the entries sharing a lemma from 29 to 57. Lemma forms differ too: an iota subscript on sozo, or CATSS cutting exaleipho to aleipho, which means anoint. Rule 17 lists these, but listing is not mending, so the builder now rebuilds each compound from the prepositions CATSS lists beside the root, allowing for elision and assimilation, which changed 2,150 Septuagint lemmas and halved rule 17’s list, from 298 to 147.

The exemption is the hiding place

Rule 1 enforces Douay name forms but exempts quotations, so it missed all eleven that had drifted toward the King James, such as Ishmaelites for Ismaelites and continueth for abideth: memory overriding the page.

An exit code that is always red says nothing

Eight rules print on a clean corpus and two of them set the failure flag, so the linter exited 1 even when clean and gated nothing. Report-only rules now only report, and exit 0 means nothing is wrong. Rules 8 and 16 turned it red again on 24 September and were sharpened; rule 16 also caught a Greek phrase placed in 1 Kings 1:24 that stands in 1:25.

A console can kill a clean run

On a cp1252 console the linter died printing the Greek of rules 11 and 17 after every check had passed. Its streams are now reconfigured to UTF-8 with replacement.

A backslash that became a backspace

Rule 16 skips words the prose also capitalises, using \b for a word boundary. A shell turned each \b into a real backspace on its way into the file, so the pattern printed correctly and matched nothing until 27 September, when the same happened to the new rule 33; the repair changed no result.

The Greek column was a poor scan

The first Swete text had Latin letters inside Greek words in 374 verses and words run together in 176, so Genesis 9:8 lost the name Noe. 24,606 verses were retaken from a clean digitisation of the same edition, matching Ecclesiasticus and Daniel by words, not numbers. The Latin letters fell to 17 and the run-together words to none.

A verse the Greek lacks borrowed its neighbour’s

The cache builder took CATSS’s verse at the Douay number even where the site’s Greek column knew the verse was missing: the Septuagint has no Jeremias 33:14 to 26, so the bud of justice met its 33:15, which is the Hebrew 26:15, and Daniel 3:24 to 90 took Hebrew 3:24 to 33, which the Douay numbers from 3:91. A verse the site marks absent is now left uncached in both languages.

The Hebrew was filed under one name for each verse

Entries cite Psalm and Psalms, and the builder kept one Douay verse for each Hebrew verse, chosen by Python’s hash seed, so a verse cited both ways had Hebrew under one spelling only and verses past a chapter’s end took real verses’ Hebrew. A missing book code and a source calling the Song of Songs the Canticle of Canticles left Esther, 1 and 2 Esdras and the Canticles with none. Now 169 verses have gained Hebrew, 44 phantom verses have lost it, the 18 cited verses still without it are in books that have none, and the build is the same whatever the seed and takes nine minutes, not twenty one.

An unchecked entry looks like a checked one

An entry whose verses are missing from the cache is reported as sharing no vocabulary, like a real result; adding an entry without re-running the fetch script causes it. The rule now names the missing side and says the entry was compared against nothing.

XIVThe Motif Searcher

The corpora in the previous section privately check an entry already written. This public tool does the opposite: it searches one word across the whole of five texts, side by side, which is how a motif gets found rather than confirmed.

5texts searched
129,947verses indexed
41MB on disk
39MB resident
TextEditionLicenceVerses
Douay-RheimsThe site's ownPublic domain35,804
LatinClementine VulgatePublic domain35,809
HebrewWestminster Leningrad Codex, via morphhbText public domain23,213
SeptuagintSwete 1909, via lxx-swete and eliranwong/LXX-Swete-1930 (GPL-3)CC BY-SA 4.027,182
Greek New TestamentSBLGNTCC BY 4.07,939

None of these is the linter's corpus: STEPBible asks not to be redistributed and CATSS is non-commercial, so both stay on the workstation, while every text here can be served publicly.

Alignment, and why a column goes blank

Hebrew, Greek, Latin and Douay number their verses differently, and a mismatch is silent, giving a plausible wrong verse. A column is filled only where the published UBS versification tables establish which verse corresponds, and a differing number is printed: Douay Psalm 109:4 shows its Hebrew as [Psalms 110:4].

TextVerses mappedCoverage
Latin35,804every verse of the Bible
Hebrew23,19864.8%, which is the protocanon
Septuagint25,34670.8%
Greek New Testament7,93222.2% of the Bible, every New Testament verse the critical text has

The shortfalls are mostly not gaps in the tool: the Hebrew has no New Testament or Deuterocanon, and where two traditions disagree about what a verse is, the column says so rather than guessing.

The word underneath

A Douay search shows the Latin, Hebrew and Greek word behind each verse’s English: lamb is agnus in 161 verses and agna, a ewe lamb, in 4, mostly kebes in the Hebrew, and arnion 28 times and amnos 3 in the Greek. Tapping a word shows only its verses, and a whole word option stops wood finding wormwood. A search in Latin, Greek or Hebrew groups its forms by dictionary word, except in the Septuagint, which carries no dictionary.

No word by word alignment of the Douay existed, so one was built. The dictionary words come from Whitaker's WORDS for the Latin, read directly because its Python port was too slow, morphhb and Strong's for the Hebrew, and MorphGNT and Dodson for the Greek. The English was paired by competitive linking, the strongest pair in a verse first, so lux cannot go to darkness once light has taken it; grammar words are left out on both sides. The Douay was translated from the Latin, so the Latin is the closest match, and the page says so. Contracted perfects such as abiit are tried again with the v restored, a word the Vulgate capitalises only in mid sentence is a name, so Core is not corus, the north-west wind, and a dictionary word with no endings is read as itself, so the Douay’s “morning” goes to mane the adverb, not to a command to remain.

TableRows
Douay verses with word links35,786
Latin forms resolved to a dictionary word41,135 of 46,373
Dictionary words with a headword and gloss23,179

The Fathers on a verse

A verse opens what the Fathers said about it, streamed from the server like the corpora: 12,588 Catena Aurea comments on the four Gospels, each under the Father Aquinas names, and 25,956 passages from the Schaff edition by way of CCEL, placed on 91,103 verse references from the translators’ footnotes. Where a commentary sets a verse as a heading and comments beneath it, as Chrysostom does, the paragraphs beneath are joined to the heading. References are renumbered to the Douay first, so Psalm 110 lands on Psalm 109. Both are credited at the foot of the site. Beneath the Fathers, a folded section gives Haydock's commentary on the verse, credited to Todd Easton.

Leads for new entries

tools/entry_leads.py turns the Fathers and the dictionary words into leads. fathers lists the passages citing both of an entry’s verses in one breath, usually a Father drawing the connection himself; 60 of the 153 entries have one. candidates ranks the 90,041 Old and New Testament pairs no entry cites yet, best per pair of chapters. A Father citing both verses counts, double when he speaks of types or figures; the Catena Aurea’s Fathers, who quote without references, are tied to a verse by three shared rare words or five in order. Tuned against the chapter pairs the entries already cite, 24 of 145 ranked in the top 500 of 233,000, about fifty times chance.

The leads open at /leads, behind the edit password, whose wrong guesses PasswordGuard counts, as cards: both verses with the Vulgate, shared words glossed from the Douay’s own wording (coccum is scarlet, not “insect”; 898 of the 979 shared words take the Douay’s word, the dictionary covers the rest), the other strong partners of each verse, the Fathers’ passages centred on the sentence that echoes both verses, buttons into the Motif Searcher, and Start an entry, which fills the entry form, its way in since + Add entry left the toolbar on 14 October. Leads can be kept, passed and noted, and the marks follow you between devices; kept leads gather in a Shortlist, marked done once an entry cites both verses, and a passed lead’s chapters are skipped at the next refresh. Pass has an Undo, Copy puts a lead on the clipboard as plain text, a filter searches references, verses, Latin, Fathers and notes, new leads carry a badge, and closing a verse opened from a lead returns to the same place in the list.

Refresh walks one Old Testament verse at a time instead of holding all 1.19 million pairs, taking 16 seconds and 307 MB at home. On the live box it runs at low priority under a hard memory cap, writes to its own state folder, and starts by itself a few minutes after a deploy that changed the entries.

Checks when an entry is saved

The entry form calls the linter's own functions before saving, so it cannot disagree with tools/lint_typology.py. Errors stop the save: a dash, a patristic warrant with no source, a verse the Douay does not have, a related entry that does not exist, an entry too long for its narration. Warnings need a second press: a non Douay name form, an ambiguous Kings, a quotation not in the Douay’s wording, a Catechism paragraph not yet read, a Father's words not found in the Fathers, and, from rules 24 and 25, chapters an entry already covers and a note arguing from a Greek or Hebrew verse the site has not matched.

The Catechism on a verse

tools/build_ccc_index.py reads the Vatican's online edition, ties each footnote to the paragraph whose text carries its marker, and renumbers the RSV references to the Douay, so Ps 110:4 is filed under Psalms 109:4. It keeps paragraph numbers against verses, none of the Catechism's text, and the verse view and every lead card link the paragraphs citing a verse. Checked by hand against CCC 410, 489, 1537 and 2130.

IndexCount
Footnotes read3,678
References placed7,622
Douay verses cited4,351
Paragraphs citing scripture1,167

How strong is this connection?

Every entry opens a strength report from tools/entry_strength.py: the dictionary words its verses share and how rare each is, whether the link holds in Latin, Greek and Hebrew, whether a quoted Father's words were found in the Fathers, which Fathers cite both verses, whether the Catechism paragraph given has been read, and which paragraphs cite the verses. A missing Septuagint alignment is reported as such, not as an absent word, and verses that share no word are said to rest on the image, which is common and not a weakness. 114 of the 153 entries share a word that holds in all three languages, and the Catechism cites a verse of 134.

Filling the Greek column

tools/build_lxx_alignment.py matches Septuagint chapters in three published steps: Swete aligned with the CATSS Septuagint takes a Rahlfs label (only labels are taken from CATSS), the UBS Septuagint table carries Rahlfs to the Hebrew numbering, and the verified Hebrew map carries that to the Douay. A chapter is accepted only if its glossed Greek matches the Douay better than the same map shifted a verse or two, a test correct chapters passed in 79 of 80 tries. Nehemiah, which lxx.tsv had filed inside Esdras B, and Ecclesiastes, from the second copy of Swete, were added. Ecclesiasticus, Judith and Tobias get no new pairings, since the Vulgate follows a different form of each, and 252 verses the Septuagint lacks, or carries elsewhere in its own order, are labelled as such.

The Hebrew column’s other blanks are the Greek additions the Hebrew never had, Daniel 3:24 to 90, Daniel 13 and 14, and Esther 10:4 to the end of chapter 16, and the column says so. Four chapters left unmatched, Psalms 15, 125 and 135 and Isaias 45, were matched by hand.

Every pairing read by meaning, 5 October

tools/audit_alignment_content.py glosses each original verse into English from the workstation’s word glosses and scores every pairing against the Douay beside its neighbours. In twenty seconds it flags a neighbour that fits clearly better, an original verse nothing points to, and a Douay verse that holds two. A flag is a lead: 427 flagged chapters were read in full, every change had to quote its matching words, and a second reader tried to refute each. 716 of 720 held, 2 were amended and 2 rejected; of thirty six unflagged chapters read blind, one needed a change.

The seventeen chapters of the Gospels, Acts and Romans that showed no Greek, about six hundred and eighty verses, are filled. A verse a text lacks, as the critical Greek lacks John 5:4, says so on its own page with the reason from langs/absent.json. Where a Douay verse holds more than one original verse, langs/alignment.json keeps the one it holds most of, which is what thirteen tools read, and langs/alignment_more.json lists the rest for the verse pages: “shown from Osee 6:2, 6:3”. The UBS cross check now agrees on 31,008 verses.

The Latin column follows Challoner

Challoner’s edition divides some verses unlike the Vulgate, printing Psalm 150 in five verses and Amos 9 in fourteen. The Douay text was right; the Latin beside it, paired by number, slipped by one, lost its last line or showed nothing. Sixteen chapters are now paired by reading: the Thessalonian letters, Ecclesiasticus 29, Judith 4, Tobias 7, 2 Kings 13, Amos 9, Isaias 45 and 46, and Psalms 15, 19, 28, 42, 125, 135 and 150. A sweep of every chapter for proper names standing in the neighbouring Latin verse found no other. The English to Latin word links follow the same pairing.

Repairing the Septuagint

Swete’s scanned text had three kinds of damage, each mended by a script that refuses to write unless every row it touches is as the scan left it: verses run into the one before were split out, the long plus verses of the Kings got labels such as (16a), and gaps were filled from a second digitisation of Swete, among them Daniel 12:5 to 13 and, in Theodotion’s Greek, Susanna and Bel and the Dragon. Esther’s additions A to F, 105 verses, are filed under the Vulgate numbers Swete prints beside them, so Mardochai’s dream stands at Douay 11, and the scan’s misnumbered Esther 10:4 to 11 is gone.

What it says about the corpus

Every result is checked against the 1,021 verses the 153 entries cite: serpent returns 57 verses, 8 of them cited, and the uncited rest are verses the work has not reached. Tapping an entry name opens that entry beside the results rather than over them.

Counting verses is not checking them

Alignments built on verse count offsets gave wrong verses that looked right: Genesis 2:10 showed 2:9. An offset correct for most of a book fails precisely where the numbering diverges, the only place anyone would think to look.

A second parser under-reports quietly

A reference pattern written for the cross-reference missed eleven verses written as a continuation of the previous book, as in Apocalypse 12:3; 13:1, and they read as uncited, the one wrong answer this feature must never give. It now uses the same parser as the language tooling.

The box has no room to hold this in memory

The game server takes about 880 MB of the same machine, so every text and index here is streamed a line at a time from disk with an early exit: 41 MB of corpora costs 39 MB resident, measured on the live process.

CCEL's tags drop the hundreds from a psalm

For psalms above a hundred CCEL’s tag loses the hundred: Ps. cx. 1 is tagged Psalm 10:1, which filed 842 citations of Psalms 100 to 150 under the wrong psalm. The printed numeral is now the authority wherever it is a hundred more than the tag.

The verified map was wrong where the audit could not see

A shift of one verse keeps the rhythm of long and short verses, which is all a length audit measures: Joel 2:28 passed while showing the Greek of 3:1, and Job 16 and Osee 1 had the same kind of shift. Only reading by sense finds them, and a correction stands only where the sense clearly favours it or a run of neighbouring verses moves together.

A correct table still has wrong chapters

Comparing long and short verses in the Latin against the Hebrew and Greek found Greek Jonas 2, Canticles 6, Isaias 64 and Jeremias 39 misaligned, and chapters of Judith where the Vulgate follows a different recension and no pairing is honest, so those show nothing. A flag still needs reading: Greek Psalms 3, 52, 69, 94 and 95 were flagged and found aligned, the statistics thrown by headings the Douay counts as a verse.

Attribution by volume is wrong by volume

Schaff's volumes bind several authors together, so naming passages by volume credited Tertullian to Athanasius and Rufinus to Jerome. Each work is now attributed by its own title, spurious letters are labelled as such, and a work that cannot be pinned to one author is left unnamed.

Greek needs a face that has its accents

The site’s Garamond has no Greek, and Georgia, next in its list, lacks the accented letters of polytonic Greek. Every Greek text, in the Motif Searcher, the verse pages, the Fathers’ passages and the entries, is marked lang="grc" and set in Gentium, Palatino or Times, and twenty Greek words in the Fathers typed with their breathing beside the vowel are mended as they are shown.

Git rewrites text it believes it understands

Line ending normalisation on checkout would corrupt the tab separated corpora, so a .gitattributes marks langs/ as binary. The same trap ate 44 lines of server.py when LF blocks spliced into a CRLF file were converted again.

XVHaydock’s commentary

George Leo Haydock’s Catholic commentary of 1859 stands under every verse it explains, on the verse pages and in the Motif Searcher, in the transcription Todd Easton made and John Paul Wohlschied keeps online. Every page that shows a note credits Todd.

20,842notes, on all 1,334 chapters
47repairs from Todd’s own e-book
46errors reported back to the transcriber
11 MBloaded a book at a time
  • Permission. Todd shut his site in 2018 and gave the files to several people; John Paul rehosts them at johnblood.gitlab.io/haydock and on 3 October 2026 said the site may use them, crediting Todd. The 1859 text is public domain.
  • Two witnesses. tools/haydock_extract.py reads Todd’s web pages and, separately, his 2012 e-book of the same text. Each chapter is taken from the page whose printed 1859 Douay matches the site’s, so five pages titled with the wrong chapter still land in the right place, and two pages cut off partway are replaced by complete copies.
  • Read before shown. Every note where the two witnesses differ, or whose opening quotation sits in another verse, went to a reader and then to a second reader told to refute the change: 10 notes the web pages had lost were restored, 25 cut short were completed, 8 filed under the wrong verse were moved. commentary/haydock_corrections.json keeps each repair and why.
  • The site’s numbering. Haydock counts every chapter from one, as the Vulgate does; the site keeps drbo.org’s numbers, which give the second half of Psalm 9 as 9:101 to 9:118 and start Psalms 115 and 147 at 10 and 12, so the builder carries each note across by its place in the chapter.
  • Given as written. Where a note lays the Passion on the Jewish people, the page adds the Church’s teaching (CCC 597 to 598); where it argues against the Reformation, the line on separated brethren (CCC 818). Each fires only beside the words that call for it.
  • Given back. The 39 note errors and 7 page faults went to John Paul on 6 October, with the cause of his broken download links: the pages still point at Todd’s old tripod address, and the e-books are already in his repository.

Comparing Haydock’s printed Douay with the site’s found two slips in the site’s own text, both mended: a heading, “Hebrews Psalm 10”, run into Psalm 9:21 by the import, and “the king’s soil” for “son” at 4 Kings 15:5, a misprint the site had inherited from drbo.org. It also found phrases the standard online Challoner drops that the 1859 text and the Latin keep, such as “and there arose a great cry in Egypt” at Exodus 12:30; those are left as the standard text has them.

XVIThe prayer book

The prayers of the Church and the whole Rosary at /prayers, checked as an entry is and joined back to the typology.

20prayers
20mysteries of the Rosary
50links to figure entries
74steps in the guided Rosary

The page

The page takes the home page's shape (John 3:30, the star, the banner, Jeremias 33:3 and a grid of buttons) and opens on that title page with the contents below the fold. Links go by address: /#entry= opens an entry, /#bible= a verse in the reader, /#examen the Examination of Conscience, and a card's prayer links open /prayers# at the prayer or mystery.

Sources

The English follows the Baltimore Catechism of 1885 where it prints the prayer, with the traditional Holy Ghost; the Latin is the liturgical text. Every Scripture reference resolves in the Douay, every Father's words are found in Schaff, and each Catechism excerpt is copied from the Vatican text. The histories correct two common errors: the Memorare is not St Bernard of Clairvaux's, and the Anima Christi is older than St Ignatius. Psalm 22 has no Amen, as the Douay prints none.

The Rosary

The Rosary closes the book: the Joyful, Luminous, Sorrowful and Glorious mysteries, each with its Douay Scripture, a short meditation and the entries that prefigure it, 50 links chosen by hand rather than matched by verse, at least one for every mystery. The day's set opens by itself, following Rosarium Virginis Mariae 38. The Hail Mary carries St Gregory of Nyssa and St Ambrose on Luke 1:28 from the Catena Aurea. Every entry card ends with the mysteries and prayers it belongs to.

Praying with the day

A panel at the top names the season, reckoning Easter by the Gregorian computus and Lent, Eastertide, Advent and Christmastide from it, and offers the prayers for morning, noon or evening by the clock: the Baltimore Catechism's morning and evening orders, the Examination of Conscience in the evening, and the Angelus at noon, which gives way to the Regina Caeli from Easter to Pentecost. Pray Now also lists the saints of the day from Butler's Lives, each opening to the start of the life. The guided Rosary goes one prayer at a time, with a bead counter for each decade, arrow keys to move and the day's mysteries by default. The scriptural Rosary, switched on under Pray the Rosary, shows a Douay verse before each Hail Mary, ten for every mystery, two hundred chosen by hand; each mystery on the page also lists its ten. The Angelus and Regina Caeli are in English as EWTN gives them, the Morning Offering is the USCCB's, and the guardian angel and faithful departed prayers are the Baltimore Catechism's. The prayers are not narrated for now.

The prayers

PrayerPrayer
The Sign of the CrossThe Memorare
The Our FatherThe Anima Christi
The Hail MaryThe Act of Contrition
The Apostles' CreedPrayer to St Michael the Archangel
The Glory BeThe Hail Holy Queen
The AngelusThe Regina Caeli
The Morning OfferingPrayer to the Guardian Angel
For the Faithful DepartedPsalm 22, The Lord ruleth me
The Litany of LoretoThe Litany of the Sacred Heart
The Stations of the CrossThe Seven Sorrows of Mary

Added for praying

The Litany of Loreto is as the Holy See now publishes it, in the traditional English forms; the Litany of the Sacred Heart is in the English of the version Leo XIII approved in 1899; the Stations give the nine told in the Gospels their verses and mark the five from tradition; the Seven Sorrows follow the Servite chaplet.

A switch under the epigraph turns the book from bold black on white by day to bold white on black at night, bold in both so it holds at arm's length in poor light. Night swaps the rose banner for the black-rose frame with two angels holding swords; both banners are centred on one canvas, so the picture does not move at the switch. The buttons are the reverse of the page, edged in dark blood red as a missal prints its rubrics. A Latin beside button sets the Latin next to the English in two columns; both settings are remembered on the device. After the first visit the page, prayers, Rosary and entries are kept on the device, so the book opens in a church with no signal.

XVIIExamination of Conscience

A hundred and nine questions before Communion, and a page built so that it cannot remember a single answer.

109questions
56marked grave matter
14sections
0answers stored anywhere
SectionCovers
The Ten CommandmentsTen sections, each opening with its verse from Exodus
The precepts of the ChurchMass and rest, annual confession, the Easter duty, fast and abstinence, support of the Church; the first four bind gravely
The seven capital sinsRoots rather than acts, not scored
The duties of one's stateSpouse, parent, child, work, neighbour
The BeatitudesA direction rather than a floor, kept out of the verdict
Before you approachThe Eucharistic fast and a situation the Church cannot recognise: not sins, but both bear on receiving today

How it reaches a verdict

Grave matter is one of three conditions and never decides alone, so marking a grave item opens two further questions: was it known to be seriously wrong at the time, and was it freely chosen. The Catechism, 1857.

AnswersVerdict
Knew it, chose it freelyConfession before Communion. 1 Corinthians 11:27-29; the Catechism, 1385 and 1457; canon 916, including its provision for grave necessity
Cannot say, or left unansweredConfession, the safer course in real doubt about grave sin
Did not know, or was not freeNot mortal. Venial sin does not bar Communion; confessing it is commended, not required. The Catechism, 1458

The page ends by saying it forgives nothing, only the sacrament does, and where it and a confessor differ the confessor is right.

One box, one thing

Seventeen questions joined two sins with an "or", even opposites such as despair and presumption, so one tick could not say which was meant and the line it put in the list carried to the confessional was ambiguous. Ors naming alternative objects of one act (God, our Lady, the saints) stay.

The examination has a period, and the page never said so

It covers since your last good confession; a sin confessed and absolved is forgiven, needs no second confession and does not bar Communion (the Catechism, 1456).

The hour runs to Communion, not to Mass

Canon 919 says one hour before Holy Communion. A weekday Mass reaches Communion in about half an hour, so counting from Mass makes a kept fast look broken.

The most sensitive thing here is held nowhere

Answers live in one object in the browser tab: no localStorage, URL or POST, only a GET for the questions, so the access log has nothing to record. Verified by reading storage and log after a full examination.

XVIIIDunk's Bible Scape

A Bible themed private server on the 2004scape and LostCity TypeScript engine, running as four cooperating processes.

ProcessPortRole
Game server8888World, client delivery, scripts
Login server43500Accounts, saves, hiscore tables
Friend server45099Friends list and private messaging, its own entrypoint
Admin panel8898Deliberately never exposed through the tunnel

Content scale

4,836models
4,673locs
4,081objects
1,391NPCs
1,376animations
1,297db rows
377player vars
66quest folders

Scope of the changes

LostCity supplied the engine and its content; the Bible themed work, this server's own, is nearly all content: 516 quest files, 242 area files, 177 general configs and scripts, 64 drop tables and 219 new models. Engine and client changed only for the staff crown, the experience bar and the spellbook's rune count, so the server can still take LostCity's fixes.

176commits, 24 Aug to 10 Sep
1,414files changed since the reskin
37,078lines added
23,758lines removed
66quests with biblical titles
1quest written from scratch
96items on custom models
758quest and area files touched

The reskin

A reworked quest changes its substance, not just its names: in The Burned Scroll, once Rune Mysteries, wizards are scribes, their tower's burning is King Joakim burning Jeremias's scroll (Jeremias 36), and runecrafting is cutting words into stone. Named NPCs carry biblical names, bar a few outlying stock characters; town names and role titles such as guard or banker stay. The Cross, thorns, nails and spear are never items; crosses as emblems are allowed.

A QA sweep cleared the three faults blind find and replace leaves: phrases in one word slots ("A the people of Bethlehem bard"), quest log and journal titles disagreeing on 22 quests, and stock names left in shop titles, level messages and item descriptions. A reverence pass made a lake spirit's offering a payment in fish to Jerusha the harpist, and a totem pole a pillar of witness (Josue 24:26).

Quest listTitles
Free quests, 18Gideon's Spies, Abraham's Feast, Binding of Asmodeus, The Burned Scroll, Bezalel's Quest, The Bones of Joseph, Jacob and Esau, The Mad King, Sacred Stones, Hidden Treasure, Rescue of Joash, David & Michal, Shearing Time, Shield of Ehud, Ahimelech's Sword, Slaying Og, Witch of Endor, Watch Tower
Members quests, 48Among them That Woman Jezebel, The Lions' Den, The Walls of Jericho, The Fiery Furnace, The Valley of Dry Bones and Saul's Conversion

Saul's Conversion, a quest written from scratch

The one quest with no stock original, played through from start to finish: Acts 9, sized against Legends' Quest, with a desert crossing mechanic of its own.

PartDetail
StagesFifteen, in one player variable: the errand for the letters, three desert legs (Bedabin Camp, the open desert, Shantay Pass), the blinding, Ananias's vision, the baptism, the plot and the escape
PeopleTheophilus, Saul, Ananias and the Damascus zealots, with their own dialogue, and the Sealed Letters quest item
CombatZealots who come for Saul once the plot is out, and desert wolves on the road
RewardThe Helmet of Salvation and the Belt of Truth, the last two pieces of the Armour of God (Ephesians 6)
Size531 lines of script and config, registered like any stock quest

Daniel's den of lions

The Lions' Den reworks Fight Arena into Daniel's Babylon, with the Satrap as the arena's general and two of Daniel's companions, Hananiah and Mishael (Daniel 1:6), as the prisoners you free. Beside it stands a repeatable challenge on Daniel 6, written from scratch.

PartDetail
WhereA den in the rock east of the Bedabin camp, entered through the Midianite Trader
WavesFive: two young lions, three young lions, three desert lions, four desert lions, then the Great Lion alone
The Great LionBlack, three times the size of the rest, 550 hitpoints and 300 defence; one attack in four is a ranged roar, so you switch between Protect from Missiles and Protect from Melee
RewardDavid's Ring on every clear, described from Psalms 17:40, and a one in two chance of Onyx, a black lion pet that "broods constantly"
SafeguardsLeaving by walking, teleporting or dying ends the attempt and clears every lion in the den's four map zones. Kills count through a queue on the player, since a lion that died while the player was mid special attack was once dropped silently and the reward never came

The Evil One in the cow field

A boss written from scratch, set deliberately in the most ordinary field in the game.

PartDetail
WhereThe Lumbridge cow field, raised by the farmer once Shearing Time is done
The beastThe red dragon of Apocalypse 12:3, seven heads and ten horns, on its own model; level 365 and 400 hitpoints, the game's highest level monster
The fightMelee, with one attack in four a breath of fire up to 65, or 20 under Protect from Magic
RewardDragon bones, and a one in two chance of the Mini One, "all the menace, none of the size", a follower on the same model
EngineeringThe model lacks the attachment points hit effects expect, so any spell effect drawn on it crashed the client; its fire breath copies the King Black Dragon's ranged variant, drawn only on the player, and the staff of Moses' root spell skips its impact effect here

The gods renamed

The stock game's three gods appear nowhere a player can see; only _unpack, the reference copy the packer skips, still names them. Molech is the idol the Douay condemns for child sacrifice (Leviticus 18:21), Asherah the Canaanite goddess Israel kept falling back to. Internal identifiers such as zamorak_cape keep their stock names on purpose: renaming them would mean re-registering every pack entry for no visible change, and would cut the server off from upstream fixes.

StockNow
Saradominthe Lord: Cape, Staff, Statue and Portal of the Lord, and the god spell Wrath of the Lord
ZamorakMolech: Cape, Staff, Robe, Statue and Altar of Molech, the Monk of Molech and Molech Wizard, Molech's potion, the Molech armour set, and Flames of Molech
GuthixAsherah: Cape, Staff, Statue and Portal of Asherah, and Claws of Asherah
The god booksThe Holy book, the Unholy book and the Book of balance
Other idolsLesser cults became Canaanite or Philistine: the Staff and Guardian of Dagon, the Dagon pendant, and Hazael, Priest of Baal

XIXCustom content

219custom models
166custom configs
1sprite sheet redrawn, of 54
25custom scripts

Item lines built from scratch

96 items use models made for this server, across 70 config files, besides recolours of stock models.

LineDetail
SeraphiteOre, bar and scimitar: a white recolour of rune, mined continuously from a seam that never depletes, smelted on the furnace and smithed straight from the anvil
AlmondLogs and strung and unstrung shortbows and longbows, from two scripted trees: level 60, a yew's rate, twice Magic tree experience, never felled
Onyx toolsAxe and pickaxe with no level requirement. The pickaxe mines at the engine's fastest rate; both yield a second ore or log half the time, with the experience to match
Skilling petsTwelve followers, one per gathering and artisan skill, at 1 in 1,000 per action: Rock of Horeb, Simon's Catch, Cedar of Lebanon, The Widow's Cruse, Ember of the Bush, Tubal's Hammer, Bezalel's Chisel, Jonathan's Arrow, Balm of Gilead, Hind of the Dawn, Achan's Wedge, and Urim and Thummim
The Armour of GodSix pieces from Ephesians 6; the Helmet of Salvation and Belt of Truth are the reward for Saul's Conversion
The Four HorsemenConquest, War, Famine and Death, one item each
The lineman's kitClass 3 Vest, FR Duck Pants, Steel Toes, Class E Hard Hat and Hard Halo, Steel Toe Boots, Tic Tracer, Fall Arrest Harness and Grave Shift. Working tools: the hot stick (Wrath of the Lord special), the digger bar (Strike), and the cant hook, which fells a tree from the equipment slot
Emo's setThe Silent Treatment, Chip on Shoulder, Rock Bottom, Bleed Black, Worn Thin, The Last Word, Wilting Halo, Mourning Boots, Fingerless, The Long Walk Home, Closure, Band Tee, Skinny Jeans, Reluctant Shorts and Thrifted Cardigan
Other petsEach with its own lines: Lamby, Luna, Onyx the black lion, the Mini One from the Evil One, Baggage, Ten, Duck, Phillip, Scruffy and Sad
The Harlot's setBlanky, Diary, Robe, Skirt, Uggs and Wig, after the women of Apocalypse 17 and Proverbs 7
Herod's setCape, Pajama Top, Pajama Bottoms and Socks, after Herod of Acts 12, eaten of worms
The Duck setDuck Halo, Robe Top, Skirt, Cloak and Boots in yellow linen marked with crosses, with the Duck Book
The Martyr's setRobe Top and Bottom, Chainbody, Cloak, Mitts and Skirt, in white linen and mail bearing crosses
Other robesAbel's Shirt and Kilt; the Nazirite robes; the Harpazo robes and cloak, white hemmed the colour of the sky; the black Anathema robes; Simon's Top and Legs, after Simon Magus (Acts 8:20)
Crowns and halosThe Crown of Glory, an amulet of glory with unlimited teleports that still respects the level 30 wilderness block. The Crown of Life. The Saint's, Rapture and Accursed Halos, rings of white, blue and dark red light
David's Harp and the FiddleThe harp, reward for Ruth the Moabitess, sings a line from the Psalms over the player's head at every stroke. The Fiddle is a blackened harp that "plays, but it does not preach"
Cain's RockThe stock pet rock made a weapon, stroked rather than swung, with a line on every hit
Moses' Staff110 magic attack; every hit that lands casts Entangle's freeze, from the spell's data so it lasts exactly as long. The Thieving reward choice at the end of The Brickyards of Pithom
The Cup of WrathEvery swing pours out a fire wave. Sold at the Varrock sword shop for 1,200,000 coins
The Cup of TremblingReward for Noah's Vineyard, with slightly lower bonuses than the Cup of Wrath and no fire wave. Wielding it means drinking first: 10 hitpoints, Strength up, Attack wrecked, camera shaken, one of four lines
Preach booksDear Diary, the Lineman's Tome and the Duck Book, wieldable off hand, each with its own lines and an animation that shows the right book
Named artefactsJoseph's Key, banking from anywhere. Elijah's Girdle, passive Agility while running. Jeremiah's Hammer. The Fiery Furnace, burning every log at once and naming each by count. Fisher of Men. Bury charms that bury bones as they drop

XXGame systems

  • Hiscores. Per skill and overall boards, a web page in the admin panel's style, read live for online players and from the raw .sav otherwise, since the stored tables update only at logout. Admin add and remove by key.
  • Staff crowns. A third rank, Monk Mod: a wider sprite sheet, an extra appearance packet byte on server and client, and the crown drawn everywhere one appears: chat, right click menus, the trade screen and preach dialogue.
  • Experience bar and drops. A live bar with configurable colours; drops stop cleanly below it.
  • Quality of life defaults. Make all on left click at furnace, anvil, fletching and stringing, and one click at a range or fire cooks the whole batch. The bank remembers the last withdrawal amount, moving interrupts smithing, and general stores buy in bulk at high alchemy value.
  • Custom gathering. Continuous mining until the inventory fills, custom trees with their own depletion rates, and a rock that never depletes.
  • Starter kit. Granted once, in the first login block that opens the design screen and only after the flag is set, so a disconnect cannot grant it twice: 99 Magic, twenty thousand coins, Samaritan's Well, Joseph's Key, Jeremiah's Hammer, Elijah's Girdle and the Fiery Furnace. Magic is kept off the hiscores and overall totals, where every account would tie.
  • Samaritan's Well and the spellbook. The well supplies every rune server side, but the client greyed spells from its own rune count; it now counts a rune present when the inventory holds the well, for objects whose name ends in rune.
  • Worn item actions. Fell and Strike work from the worn equipment panel as well as the pack, and the panel offers only an item's real options. The fell cooldown survives logout.
  • A shorter start. Tutorial Island is skipped; the chat word filter is off on client and server.
  • Joining without a website. There is no sign-up page: the login server makes an account the first time a new name logs in. The New User screen opens the login box with “New here? Pick any name and password. Your account is made when you log in.”, and a wrong password adds “New player? That name may be taken.”
  • The client page. A red sword favicon, point down so it cannot read as an inverted cross, and link previews that show the game.
  • Rigging. Custom cloaks carry the stock cloak's vertex labels, so they deform with the body in animations.

XXIEngine traps worth remembering

Each of these cost real rework.

Recolours are rgb15, not hsl16

Config recolours pass through rgb15toHsl16. Colours decoded from an .ob2 are already hsl16, so reusing them converts twice and silently matches nothing. Black 0, white 32767, gold 27302; 9152 is not gold, it renders bright green.

Animations substitute the held model

Sequences carry replaceheldright and replaceheldleft, so a custom tool or book animates as the stock item the sequence names. Copy the seq and point it at the custom item.

obj2ob2 defaults to double sided winding

Which doubles the face count. Pass normal for thin panels like capes.

No vertex labels means no deformation

Without .vlab data a worn model stays rigid. Copy the label distribution from the equivalent stock model by relative height.

Experience is stored times ten

Player.stats caps at 2,000,000,000 for the 200m ceiling; read raw, hiscores are ten times too high.

Never checkout the pack directory on the server

Build outputs are in git but the cache index is not, so restoring them corrupts the cache and crash loops the server. Deploy deletes the index and rebuilds.

world.json overrides .env

Flags in data/config/world.json beat environment variables. Friends and private messaging sat off there for months while .env said on.

A missing attack sound aborts the whole swing

Damage and experience come before sound_synth, the hit and attack delay after, so a weapon with no sound for its style gave experience on a target that never took damage. Blame the call the log names, not the animation above it. Guarded in melee, ranged and both pvp scripts.

Combat routed on stale state

%damagetype kept the last weapon's style until a swing recomputed it; an axe took a bow's ranged style, died in projectile code before recomputing, and stuck. Routing now reads the style off the weapon in hand.

Deploy does not build the client

The browser gets the committed bundle engine/public/client/client.js; deploy only repacks and restarts, so nothing compiles a client change. Run bun run bundle.ts in webclient and copy out/client.js into place, or the change stays invisible while appearing deployed.

The Python server does not implement HEAD

It answers 501 Unsupported method, so HEAD checks and uptime monitors see an error page.

XXIIInfrastructure

PieceDetail
HostHetzner VPS, 2 cores, 2 GB, 38 GB disk
IngressCloudflare Tunnel; the admin port is never published
ServicesFive systemd units: game, login, friend, typology, cloudflared
DeployOne command: pull, repack the cache, restart, settle pass, restart login
Nightly backupTimer at 00:00 UTC (8 pm Eastern): saves, keypair, world config, hiscores and the database, kept thirty days
Full archiveBoth trees plus an atomic sqlite3 .backup snapshot, taken by hand, pulled off box
Admin toolsdeploy, players, status, visitors, biblescape-backup

Backups are checked by extracting from the archive and comparing checksums with the source, never by file size.