← All posts

Squad5 min read

Faces and names: soldiers from all over the world

How Terminal Leave soldiers got a country, an origin, a name and a portrait that agree with one another — and how the game came to speak two languages.

... by then soldiers had callsigns, ranks and skills, but lacked the main thing: they didn’t look or sound like people. A soldier’s card held a callsign and some numbers, with a placeholder where the face should be. The next step (the project was still called UOR) changed that, and along the way the game learned to speak two languages. The two jobs turned out to be more connected than I expected.

Where a soldier starts

The first version of generation simply picked everything at random: a country, a first name, a surname and a face, each on its own, with no tie to the rest. The result was people in whom nothing matched: a Brazilian first name, a Scandinavian surname, a face from a third continent.

The second version brought half the order. A country was picked by its population weight, the first name and surname came from that country’s set, and the person at least sounded whole. The population weight, though, made the pool monotonous: China and India together gave about a third of all recruits, and hiring was mostly Chinese and Indian soldiers. On top of that, the origin was worked out from the country after the fact, only to pick a picture, and the face could still disagree with the name.

The third version turns the order around: origin first, everything else after. Now every soldier comes from one chain, and each link depends on the one before it:

  1. Origin. There are ten: Slavic, Western European, Mediterranean, Nordic, Middle Eastern, South Asian, East Asian, Southeast Asian, African, Latin American. Each has a weight — how often it turns up among recruits. Population still counts in the weights, but evened out, so the big countries no longer crowd out the rest.
  2. A country within that origin. Each group has its own list of countries with their own weights. One country can sit in several groups: people of different origins live in a multinational country, and two soldiers from France don’t have to look alike.
  3. Sex. There are women in the recruit pool, but fewer of them than men.
  4. First name and surname — from that country’s set. Today there are almost two hundred sets, one per country, and they hold only real names: from a couple of dozen to over a hundred per list.
  5. Portrait — from those that match the origin and sex.

The soldier comes out whole: you can guess from the name where they’re from, and the face doesn’t contradict it. The squad, meanwhile, comes out mixed. The shared recruit pool holds people from many countries.

The whole chain runs off one seed, like the rest of generation in the game: the same seed gives the same person. The portrait and the name have no effect in battle. The simulation never reads them, and battle determinism doesn’t depend on them.

Surnames

In many languages a surname depends on sex: Ivanov and Ivanova. At first I wanted to derive the female form by a rule — add an ending and be done. A rule breaks on the first exception, and surnames have more exceptions than rules. A Russian surname ending in “-ykh” doesn’t change at all. A Polish one changes only sometimes: Kowalski becomes Kowalska, but Nowak stays Nowak. A Lithuanian one changes its whole tail, not one letter: Kazlauskas — Kazlauskaitė. Iceland uses a patronymic instead of a surname, and a daughter’s is different: not “-son” but “-dóttir”.

So surname forms live in the data. A country’s set can carry a second list — female forms, paired with the male ones by position. Where it’s absent, men and women share the surnames. It takes longer to prepare and works more reliably: a mistake in the data is visible and fixed in one line, while a mistake in a rule would have to be hunted down across every country at once.

Portraits

A portrait is matched on two traits — origin and sex. Portraits are kept as a list, each tagged with both. Generation takes the ones that fit and picks one, so the tenth soldier from the same country doesn’t have to look like the first. The weak spot comes from the same place: some combinations still have few portraits, and their faces repeat more visibly than I’d like.

The portrait shows wherever the soldier does: in the dossier, the equipment screen, the hiring screen, the memorial, and in battle on the selected soldier’s panel.

Two languages

At the same time the whole game became bilingual: the battle interface, the HQ, item names, messages — in Russian and in English. The language is picked up from the browser, the choice is remembered, and you can switch it on the front page and in the HQ settings.

The dictionaries use no third-party library. Both are declared with one and the same shape, so if a string appears in one language and is missing in the other, the code simply won’t build. Strings with numbers are small functions rather than templates with placeholders: each language decides for itself how a number fits into its sentence.

Proper names are a separate question. A callsign a player gave a soldier in Russian has to read somehow for an opponent playing in English, and the other way round. A callsign can’t be translated — “Shmel” has no canonical English name. So callsigns, weapon nicknames and squad names are transliterated: the alphabet changes, the meaning doesn’t. The transliteration is approximate, and sometimes the result looks clumsy. In exchange, the screen never mixes two alphabets in one line.

What’s stored is always what the player typed. Transliteration happens only on display, so the rename window can’t prefill the altered form and write it back.

Soldiers’ own names are stored in one spelling: Cyrillic for the countries that use it in documents, Latin for the rest. The client renders them in the other language — from a dictionary of known names, and where a name isn’t there, by the same transliteration rules.

Why all this

I could have kept “Soldier 1” and “Soldier 2” and worked on mechanics. But persistent soldiers are one of the game’s pillars, and it doesn’t stand without a face. Losing “Soldier 4” costs nothing. Losing a person with a name you’ve been through ten battles with is something else.

More on what happens to soldiers next — in “Every soldier has a face”.