# 2020-04-28

The fictional D'ni numeral system that players must deduce in Riven is a base-25 positional system, with the twist that its 25 digits are constructed using an unrelated base-5 scheme in which the would-be fives place is orthogonally overlaid to form a single glyph:

The number 241, for example, is written as , i.e. 9 in the twenty-fives place and 16 in the ones place:

Given the amount of symmetry in the notation I thought it would be fun to generate these procedurally. The following registers a custom html element that renders as an inline D'ni numeral:

``const strokes = [  "M 16 20 h 4",  "M 18 2 V 38",  "M -0.5 2 C 12 10 12 30 -0.5 38",  "M 18 2 L 0 20 m 0 0 L 18 38",  "M 36 11 H 18 V 38",];define("dni-numeral", {  value: 0,  content: ({ value }) => {    const digits = [...iterDigits(value, 25)];    const width = 12 + 36 * digits.length;    return html`<svg viewBox=\${`0 0 \${width} 40`} style="height: 1em;">      <g fill="none" stroke="currentColor" stroke-width="3">        \${svg`<path d="M 0 2 H \${width} M 0 38 H \${width} M 6 2 V 38 \${          digits.map((_, i) => `M \${6 + 36 * (1 + i)} 2 V 38`).join(" ")        }" />`}        \${digits.map((d) => iterDigits(d, 5)).map(([p1, p5], i) =>          svg`<g transform="translate(\${width - 6 - 36 * (i + 1)})">            \${(p1 !== 0 || !p5) && svg`<path d=\${strokes[p1]} />`}            \${p5 && svg`<path d=\${strokes[p5]} transform="rotate(-90)" />`}          </g>`)}      </g>    </svg>`;  },});``

Using it is as simple as:

``Preheat the oven to <dni-numeral value="350"></dni-numeral> degrees.``

This opens the door to such fun things as a D'ni numeral clock—

—or an interactive converter: