demonstration 8 of 11 · sprites.html
The sprite library
Every shape the site can draw, next to the ontology class it belongs to. A word with no shape of its own borrows its nearest ancestor's, so a sheepdog draws as a dog.
What it demonstrates
This page answers a question the other game pages raise: when the engine has to draw a word, how does it decide what to draw?
The answer is that it walks the class hierarchy. Not a lookup table with a default, and not a similarity score. It asks what the word is a kind of, and keeps asking, and takes the first answer it has a shape for.
The catalog groups every class the two sprite tiers cover. Each card shows the class, its shape, and the ancestor chain that resolved it.
Two boxes at the bottom make it interactive. Ask the catalog a question. Or describe a scene in words and watch it compose a row of sprites from the nouns you used.
Chat you can replayChat you can replay
These are assertions from the resolver's own test file and from the inference corpus. Both work over the same taxonomy.
A poodle has its own sprite, so nothing is walked.
resolveSpriteForClass("poodle") -> the poodle sprite
Asserted in test/adapters/sprite-map.test.mjs. data/sprites/poodle-icon.toml carries its own pompom-cut shape.
A sheepdog has none, so it walks one hop and draws as a dog. This is the worked fallback example the codebase itself uses.
sheepdog rdfs:subClassOf dog resolveSpriteForClass("sheepdog") -> the dog sprite
Asserted in test/adapters/sprite-map.test.mjs, against the seed taxonomy in src/domain/spider-fly-world.mjs.
The walk passes straight through an ancestor that has no shape either.
with the spider shape removed from the registry: spider -> arachnid (no shape) -> animal (shape) resolveSpriteForClass("spider") -> the animal sprite
Asserted in test/adapters/sprite-map.test.mjs.
A word with no taxonomy at all still lands somewhere honest: the declared root.
resolveSpriteForClass("wombat", no taxonomy) -> the animal sprite
Asserted in test/adapters/sprite-map.test.mjs.
The same chain, asked as a question in chat. The answer cites each premise it used.
tmct> every poodle is a dog tmct> is a poodle an animal yes — poodle is a kind of dog; dog is a kind of animal (source: corpus:human /r/IsA); so poodle is an animal
Corpus row inference-mixed-source-isa-chain-cites-both-premises in test/corpus/inference.jsonl.
What it looks like
The catalog, grouped, with each class beside the shape it resolved to.
What it works out
The walk. classAncestorChain in src/domain/sprite-map.mjs is a breadth-first walk over rdfs:subClassOf rows. It starts with the class itself, collects every superclass transitively, nearest first, and guards against cycles.
The pick. resolveSpriteAsset walks that chain and returns the first term the sprite set actually has an entry for. If it reaches the end without a hit, it falls back to a declared root, animal by default.
This is retrieval, not a heuristic. The chain is made of real facts, and you can read them:
- poodle rdfs:subClassOf dog
- sheepdog rdfs:subClassOf dog
- dog rdfs:subClassOf animal
- spider rdfs:subClassOf arachnid
- arachnid rdfs:subClassOf animal
- fly rdfs:subClassOf insect
- insect rdfs:subClassOf animal
Why it matters elsewhere. Every scene on the site is drawn this way. The manor resolves its shapes through this same function, which is why a room can render a word the artist never drew.
Two tiers. A small icon tier for lists and chips, and a large tier with facing, pose and emotion parameters for pages that draw a scene. The large tier is the only one that carries face geometry, which is why the emotional sprites live there.
How it is builtHow it is built
data/sprites/*.toml holds the icon tier. data/sprites-large/*.toml holds the large tier. Both are plain data, validated at load.
src/domain/sprite-map.mjs holds the chain walk and the resolver. src/domain/sprite-templates.mjs turns a template into a drawable asset.
src/services/sprite-catalog-viz.mjs builds the catalog. It resolves every card through the real resolver against real ontology rows rather than restating a mapping, so a card on this page cannot disagree with what a game page draws.
The taxonomy rows come from the spider-and-fly world's seed taxonomy plus the WordNet corpus bands.
The catalog is split across a landing page and one page per group, all sharing a single browser bundle, because the composer reads the whole catalog whichever page it sits on.
Related workRelated work
Class hierarchies and the fallback that comes with them.
- W3C, OWL 2 Primer, Recommendation, 11 December 2012.
rdfs:subClassOfand what transitivity over it licenses. - W3C, RDF 1.1 Semantics, Recommendation, 25 February 2014.The formal meaning of the chain the resolver walks.
- W3C, SKOS Reference, Recommendation, 18 August 2009.Broader and narrower concepts, the same shape of relation in a looser vocabulary.
- Aristotle, Prior Analytics I.1 (24b18–20); Bobzien, “Ancient Logic”, Stanford Encyclopedia of Philosophy.The syllogism. All poodles are dogs, all dogs are animals, therefore all poodles are animals, which is exactly the walk.
- ConceptNet 5.7.0 relations.The
/r/IsArelation behind many of the taxonomy rows in the corpus. - Reiter, “On Closed World Data Bases”, in Logic and Data Bases, Plenum, 1978.A word with no chain falls to the declared root, which is a stated default rather than a guess.
Credits and further reading
Assets and reading.
- WordNet, for much of the taxonomy behind the catalog's ancestor chains.
- ConceptNet 5.7.0, for the
/r/IsArows. public/models/CREDITS.md, for the three-dimensional model credits used by the town square.- Fact based world visualisation, the page that puts this resolver to work in a scene.
- README for the full bibliography.