DEV Community

Christ-loisele Atidegla
Christ-loisele Atidegla

Posted on

A 256-state binary system from Benin, and what it takes to encode it correctly

Fa is the divination system of the Fon people of Benin, where I am from. The Yoruba practise it as Ifá, and the two share their figures exactly.

The structure is binary, and I mean that literally rather than as a metaphor.

The mechanism

A figure is two columns. Each column has four positions. Each position carries either one stroke or two.

Four positions with two states each gives sixteen possible columns. Two columns side by side gives 2⁸ = 256 signs. Those sixteen columns are the sixteen principal dù, and the 256 pairs are the complete space.

Two instruments produce them. Sixteen palm nuts, called ikin, worked in eight passes. Or a chain of eight pods, opele in Yoruba and agumaga in Fon, thrown once so all eight land together. Either way the right-hand column is produced first, and that decides the name of the resulting sign.

There is a rule in the palm nut method that is inverted from what everyone guesses, including me before I checked:

One nut left in the hand means a double stroke. Two nuts left means a single.

It is the most frequently miscopied detail in casual descriptions of the procedure, so the test suite asserts it in both directions where a refactor cannot quietly flip it.

The relations are the interesting part

Once the sixteen figures are written down as bit patterns, structure falls out that is worth looking at as a programmer.

Reversal: turn a figure upside down. Four of the sixteen read the same either way: Gbé, Yèku, Woli and Di. The other twelve pair off into six couples. Four plus twelve, and the reversal operation is its own inverse.

Complement: swap every single stroke for a double and vice versa. This pairs all sixteen into eight couples with no fixed points at all, which follows from four positions never being able to all differ from themselves.

Those two operations partition the same sixteen elements in two different ways, and the partitions do not agree. That turns out to be load bearing, as the next section shows.

The hard part was the data

I expected the code to be the work. It is a few hundred lines of bit manipulation and the tests write themselves: assert that sixteen figures cover all sixteen four-position states exactly once, assert 256 distinct signs, assert every name parses back to the sign it came from.

The hard part was establishing what the figures are.

Sources disagree. Not on the mathematics, which nobody disputes, but on which name attaches to which figure and in what order they are listed. Ordering varies by region: the sequence I use is given by fongbebenin.com for the Fon dù and by ileifa.org for the Yoruba odù, and those two agree position for position, but at least one published Beninese list moves Ka to eleventh. Wikipedia's own table carries an editorial note saying the order varies.

So the library treats rank as a stable handle for indexing and says explicitly that it is not a claim about seniority. The seniority ordering of the 256 is lineage-specific and is not encoded at all.

Two figures were harder than that, and they get their own article.

What is deliberately not in it

There are no verses and no readings. A sign comes back with its figure, its names in Fon and Yoruba, and its structural relations, and nothing about what it means.

That line is drawn on purpose. The interpretive corpus is enormous, it is taught differently by different lineages, and a good deal of it is knowledge that belongs to initiates. Compressing it into a JSON file would produce something both inaccurate and presumptuous.

An application that has the standing to carry interpretation can carry it, keyed on the index or the name this gives it. The library's job is to make sure the structure underneath is right.

Using it

npx @catidegla/fadu cast
Enter fullscreen mode Exit fullscreen mode
  Loso Fu
  Ìrosùn Òfún

  │ │    │
   │     │
  │ │   │ │
   │    │ │

  1122|2121   mixed, index 79 of 255
  pods, in order: o o c c c o c o
Enter fullscreen mode Exit fullscreen mode

The more useful direction is reading a physical throw rather than simulating one, which is what an application actually needs:

import { readIkin } from '@catidegla/fadu';

readIkin([2, 2, 2, 2, 1, 1, 1, 1]).fon;   // 'Gbé Yèku'
Enter fullscreen mode Exit fullscreen mode

A pass that leaves no nuts, or three, is refused rather than being turned into a figure nobody cast.

Casting draws from the platform CSPRNG instead of Math.random, which costs nothing and seemed like the minimum for the subject matter.

69 tests, zero dependencies, and data/du.json and data/signs.json ship so the data is usable from any language. fadu.

As far as I can find, there was no comparable open source library in any language. That absence is why it exists, and it is also the warning: there is nothing to check the figures against except the sources, which is why they are cited in full.

Top comments (0)