← Dev log

The scorpion in bandages

A screenshot arrived from somebody else’s desert campaign. The caption read «поранений піщаний скорпіон» — a wounded sand scorpion. The picture showed a muscular man in bandages and a hood, standing upright, facing the viewer, with claws and a stinger attached to him.

Gender is grammar

Every character carries a gender field. It exists for one reason:

Russian adjectives agree with the noun’s gender, so “friendly” and “alive” have no single correct rendering without it: дружелюбен / дружелюбна, жив / жива.

A name does not tell you the gender, so the DM states it outright. The field is grammatical, and the DM’s instructions say exactly that.

The image layer read the same field as anatomy:

GENDER_WORD = {"m": "man", "f": "woman", "n": "creature"}

So every request to the model opened with Subject: a hulking and massive man. and put the scorpion’s description underneath it.

«Скорпион» is a masculine noun. The DM set m, and it was right to — anything else and every adjective around the character goes wrong. The neuter looks like a way out, since it yields “creature” instead of “man”, but it is almost unreachable: dragon and wolf are masculine, snake is feminine. There is no value of this field that gives you both correct prose and a correct picture.

So the thing to fix was the data model, not the instructions.

Eight pictures

We settled it by measuring rather than arguing: eight renders against the world’s real style and its real anchor. The same description every time, and it mentioned no clothing at all — chitin, eight legs, claws, a tail.

The control — current code, nothing changed — came back as a man in a hood, a robe and a sash. None of that was in the description. It came from the Subject: a … man line and from the world’s own material notes. Which means the DM’s writing was never the problem; the road it travelled was.

Two things then fell out, and both made the job smaller. Only one thing needs to change: the noun. And a generic noun is enough — “a large animal, a beast, not a person” — with no species in it, because the model takes the species from the description anyway. So no new translatable field, and no splitting the image cache per language.

That became a morphology field with two values, humanoid and beast. The default reaches neither the prompt, nor the cache key, nor the descriptor file beside the picture — which is what stops anything already painted from being repainted.

The measurement was right; generalising it was not

A few hours later a bone dragon turned up in play. Marked beast, the field arriving exactly where it should, the request to the model carrying “a beast, not a person” — and the picture was a biped with square shoulders, wearing its armour like a breastplate.

The scorpion had proved nothing about the dragon.

The frame says:

The entire figure from head to feet, standing upright and facing the viewer

A scorpion has no upright option — there is nothing for that instruction to act on. A dragon has one. And a single request now held “a beast, not a person” alongside four instructions pointing the other way: stand upright; the legs and feet must be visible; the world’s own materials, which list robes, aprons and boots; and a closing line calling the subject one of this world’s people.

Against a dragon, the four win.

We replaced one line with “in its own natural stance and anatomy — however this kind of creature actually stands or moves, not a human posture”. The biped became a quadruped. The armour stayed, because the description asked for it and was entitled to, but it now sits on the animal as barding rather than on a chest as a cuirass.

Do not tell a picture what to contain

On the second pass we stepped on our own rake.

The new frame rules said: “the whole creature, end to end, at its own true scale”. A slug whose description calls it enormous came back ringed by peasants holding torches. We had asked the model for true scale, and it dutifully supplied something to measure the scale against.

The rule now says the creature is alone in the frame, and says nothing about how big it is.

Both mistakes have the same shape, and it is the one thing worth taking away:

A sentence describing what should be in the picture is an invitation to draw something extra. We forbade clothing, and the animals came back in bandages — the world’s materials were arguing with the frame, and the model split the difference. We asked for scale, and got a crowd. The frame’s job is body plan and cropping; the rest is not its business.

Found along the way

While testing all this, it turned out the world editor could not save a single character from any finished world — not one field. The server answered every save with an error.

The cause was a validation call passing id twice: once from the URL, once from the data itself, because every record that entered the database through a world’s own decomposition carries its id inside its data too. Only characters created directly in the editor worked, since their data arrives with no id in it.

The tests missed it for an unpleasant reason. Each one creates its own character first — through the very same request. So each built its fixture the way that works, and could no longer fail the way that breaks. The new test therefore takes a record from a finished world instead of making one.

The fix is one line. How long the defect had been there, nobody knows.

What next

Morphology currently knows exactly two values: person and beast. Winged, serpentine and amorphous are deliberately absent — each value should have a verified picture behind it rather than a guess.

In the comic, beasts are still drawn as people: it has its own frame, its own keys and its own staging, and that is a separate piece of work.