THE MYSTERY OF THE SANTA MARIA
RSS
← Devlog
v0.42 · v0.44.3–v0.44.8 · voice recording · tooling · testing · playtest

The line arrived half-finished

A metal workbench inside a cargo ship: a sheet of paper folded and unfolded many times, covered in illegible handwriting, a man's dark hands resting on the bench beside it, a pencil, an adjustable spanner and an open watertight container

Every spoken line in the game has a code name and a place in a list. A program builds that list: it reads the game files, pulls out the text and puts it in order. That list is what ends up in the hands of the person recording the voice. A name, a line, the words to say.

On 7 August an automatic check went looking for a word inside one of those lines and could not find it. The direction note asked for stress on exactly that word, so the check reported the fault the only way it knew how: that line no longer exists.

The line existed. It was in the game, written and working. It was missing from the list.

A truncated line is still a line

Lines in the code are not always written on a single row. They are often written in pieces, and the program stitches them back together before adding them to the list, because the voice actor has to receive the whole thing. When it hit a piece it could not read, it stopped and handed over whatever it had collected so far. Without telling anyone.

That was a decision, and it was written in the comment next to the code: better a line that comes up short than a line with a hole in the middle. For the case the author had in mind it works fine.

The case nobody had in mind is a different one. That particular line has two different endings, one for a player who has already found a certain thing and one for a player who has not. The program reached the fork, failed to recognise it, and stopped. Only the first half made it into the list.

The way it kept quiet is the part that matters. A truncated line is a valid line: it reads, it makes sense, it ends with a full stop. No tool could have caught it, because no tool knows how long a line is supposed to be. It would have reached the recording studio like that, and it would have been recorded like that.

Now both branches of a fork get resolved, each with its condition beside it. And everything else the program cannot read no longer slips by in silence: it stops with an error and names the piece of code that blocked it. If a line ever had more than eight different forms, it refuses to guess and says so. A sentence with eight forms is not a line any more, it is a piece of logic in disguise.

The only reason the fault surfaced at all is that somebody was looking for something else entirely.

One name is one take

With the program fixed, the fork is visible. And behind it sits the real problem, which had nothing to do with the tool.

The two versions of the line shared a single name. One name means one take in the studio: the actor reads it, records it, moves on. If two different sentences sit under the same name, one of them stays silent. Or worse, the wrong one gets recorded, because whoever is reading has no idea there is another.

Our own internal notes from two days earlier had already said it in plain words: this one needs two takes at the session. Then work moved on and the sentence stayed there, in a document nobody was rereading.

There are two names now. The old one stays attached to the branch the direction note was written for, so the note is not thrown away, and the second one is new. The game has 318 spoken lines, and all 318 have exactly one text.

One of the two sentences was also rewritten. It had been born on 5 August inside a fix, four days after the text revision closed, so it had never been through a reading pass. Set beside its twin, the flaw was obvious: it confirmed something the player had just seen with their own eyes, and it stole the punch from the line that follows, which is the point of the scene.

The rule nobody had decided

The two versions share their opening: four identical rows, and only the ending changes. Writing them out twice in full means keeping two copies of the same prose, and two copies drift apart sooner or later. A revision pass corrects one and not the other, and nobody notices until an actor reads it aloud.

The answer is to write those four rows once and refer to them from both places. Except that the extraction program could not read a reference like that: it found no text and stopped with a blocking error.

So the right way to write it was forbidden in practice, and nobody had decided to forbid it. It was the limit of a tool behaving like a rule of style.

The comment was an order

The same day, another written thing giving orders it had no right to give.

Until 30 July the pre-production documents sat outside the project, and our checking programs could read them but not change them. On 30 July that rule half-collapsed: the reading part survived, the ban on writing did not.

The comments inside the code, though, kept repeating the old rule. In six different places, in capitals: read only, never write, for any reason, not even to correct an obvious mistake.

On 7 August we read that comment and believed it. Three separate times in the same session we said a wrong direction note could not be corrected, because that file was not ours.

A comment quoting a decision that has fallen is not old documentation. It is an order, and whoever reads it carries it out. Those six places now say the right thing, and the ban that was genuinely useful stands on its real reason: a tool that measures does not fix what it is measuring, or the red disappears instead of being reported.

The register nobody checked

There is a program that hunts for names still sitting in the documents but gone from the game. Dead lines, in other words. It was flagging eight of them and asking for them to be dealt with.

They had already been dealt with. All eight were in the register of withdrawn names, with a date and a reason, and four had gone down along with the three verbs we removed a few days before. That program simply did not read the register. It never had: the word did not appear anywhere in its source.

That was deliberate at first, and the reasoning is sound. A tool that already knows which lines are dead is worthless as an independent check, and the first time it ran it found things on its own that somebody had already decided. But without a final comparison it stays red forever over finished work, and a check that is red by construction stops being a check. It now classifies as before, then looks at the register: anything already recorded gets listed and passed over, anything not recorded stops everything.

In the same half hour we had also added the opposite alarm, for a name recorded as dead that is still alive in the game. It looked free. We ran it and it flagged 103 cases, all of them normal behaviour covered by a rule we already knew about. Removed immediately. An alarm that goes off 103 times for nothing is worse than no alarm, and it is exactly the flaw that piece of work was correcting.

We are keeping the lesson, and writing it out in full: a check gets tested both ways before you believe it, not after.

In one place, on one disk

Then the biggest thing of the day, which is a risk rather than a fault, and one we had been carrying for months.

The pre-production documents — the architecture of the story, the room texts, the direction notes for the voice work, the character sheets — were sitting in a folder on the computer, outside any version control. They are the most valuable material in the project, because what reaches the recording studio comes out of there. They existed in one place, on one disk. And on that same day we had changed four of them.

They are now in the project repository, alongside the code. Not the whole folder: it weighs 2.1 GB and most of that is video, recordings and print files, which have no business in a code repository. One audio file alone is 704 MB, and the service hosting the project rejects anything over 100. The documents went in, and they come to 222 files for 5.1 MB in total.

The original was deleted, and that is not a detail. Two copies of the same thing drift apart with the first piece of work done on either. It had already happened to us: an old copy left lying around once had us saying a document did not exist when it did.

One of those sheets deserves a line of its own, because it dates from 30 July and we never wrote about it. It is the portrait of Nketo Bosendo, the man who wrote the letter found on board. The first generated image came back as a Mediterranean white man, which is precisely the risk the sheet warned about. It took four attempts. That sheet is not game material and will never appear on screen: it exists for the people who draw and the people who record, so they know who is being talked about.

Three things from 4 August

Three corrections from a few days earlier are still owed, skipped when they came out. Lined up together, they turn out to be relatives of everything else: in all three we were telling somebody something that was not true.

The packages we send to testers stop working after a while, because an old version out in the wild does more harm than good. Until 4 August the date was written by hand inside the game, and somebody had to remember to change it before every delivery, which is the surest way to forget. The computer now works it out at the moment it builds the package: seven days flat from that day. Every package carries its own, and the old one dies when the new one is born.

That turned up a mistake in the Italian that the fixed date had been hiding. The game was writing the equivalent of “stops working on the 11 August”, where Italian requires the article to elide. With a single day, chosen by hand, nobody would ever have noticed. Now that the day changes with every package, the sentence has to hold for any date, and a month has 31 of them. We fixed them all. What found the mistake was a photograph of the real screen.

We had asked Mario to attach a save file to a report, and the path we gave him does not exist. The folder really is called something else, all lower case and with hyphens, and it has been called that from the start. The wrong path had been sitting in a comment inside the code since the second playtest, and that is where it got copied into the notes for testers. For two months, every person who reported a fault to us was asked for a file inside a folder that was not there. A desk review had even ticked it off as verified: it checked that the code asked for the folder the right way, and took the name in the comment on trust.

The remedy that springs to mind first is renaming the folder, and it is the thing not to do. It would move the data for anyone who has already played: the saves would stay where they are and the game would stop seeing them, with no error on screen, just ten empty slots. The ugly name is the right name, and the comment now explains why, so the temptation does not come back.

Michele Bancheri is one of the testers, and his surname was going around the project spelled two ways: seven times one way, five the other. It is now spelled one way, the right one. Of all those places only one counted, and it is the note the testers actually read.


We only saw the thread running through these days once we lined things up. Almost everything that had broken was written for somebody else: a line for the person who has to record it, a path for the person who has to attach a file, a comment for the person who opens that file six months from now.

Code that is wrong usually stops working, and makes itself known. A sentence written for a person can stay wrong for months without giving any sign, because it goes on reading perfectly well.