Skip to content

How Lines Are Chosen

This page explains how Townstead makes its choices, so you can predict what your lines do.

For each slot, Townstead only uses parts that pass every check below.

CheckThe part is left out when
VoiceThe part’s voice is not one of the speaker’s voices.
Speakerstages or personalities do not match the speaker.
ChildrenThe speaker is a child, the part is marked, and the voice’s children rule does not allow it.
Subjectsubjects, variants, valence or provenance do not match the subject.
Registerregisters does not allow the line’s register.
LengthThe conversation has fewer lines than min_lines.
Final lineThe line is the last one, and the part asks a question or opens a required pair.
StateA state condition is false.
StanceThe slot is match or oppose, and the part’s stance does not fit.
QuestionThe part asks about a slot that was already said, or that the subject does not have.
Held stanceThe part takes the other stance on a thread that the speaker already took a stance on.
RequirementsA requires entry is false.
PerspectiveA persp slot is the wrong person, or was not yet said (without introduces).
PlaceholdersThe text names a slot that the subject does not have, names a demonym that the culture does not have, or names a person without persp who is the speaker or the listener.
GateThe gate weight is 0.
PositionThe part asks a question, and the slot is not the last.
GreetingThe part is a greeting, and the line already has one.

When no part is eligible for a slot, Townstead cannot build the line.

Townstead picks one eligible part at random, by score:

score = weight × gate weight × (1 + 0.5 × specificity) × thread factor

A part written for a narrow moment is more likely than a general part, when both fit. Specificity counts the conditions that narrow the part:

  • one each for variants, stages, personalities, registers, valence, provenance, min_lines, and a gate;
  • one for each state key, each requires entry, and each persp slot.

So a part with a variant and one requirement scores 2 × as much as a general part with the same weight. General parts still appear, and they are the fallback when nothing narrower fits.

A thread is a label for what a part is about, such as weather.crops or weather.boots. The part before the dot is the thread’s root. After a part with a thread, the next parts prefer the same thread:

The next part’s threadFactor
The same thread× 5
The same root, such as weather.mud after weather.boots× 2.5
A different root× 0.5
No thread× 1

With this rule, a conversation stays on one point for a few lines, instead of jumping between points. Townstead’s lines use the roots weather, need, biome, venue, company and danger.

A villager also keeps a stance on a thread. After “Rain is good for the crops.” (+, weather.crops), the same villager does not say “The crops are ruined.” (-, weather.crops) about the same subject.

Townstead remembers which parts were used recently in each village, because a player hears everyone in the village. A used part is skipped until every eligible part of its pool was used. Then the pool starts again.

A speaker with a culture voice gets marked parts at the share that the voice sets. See Marked Parts.

Villagers raise what matters to them. A subject instance has an urgency, and Townstead multiplies the topic’s weight by max(0.1, 1 + 3 × urgency):

GoalSourceUrgency
Share fresh newschronicle_account0.6 × fidelity + 0.2 for a story learned in the last day. -0.3 when the listener already knows it.
Complain about a needneed0.4 for a mild need, 0.8 for a strong one, 1.0 for freezing or sweltering.
Warn about dangermob_sighting0.9 for a sighting today, 0.5 for an older one.
Seek companycompanyaffection / 50, at most 0.8.
Talk about an infectioninfection0.6 for a fresh bite, 0.8 for a fever, 0.9 when the listener has a fever.

A villager with fresh news is 2 to 3.4 times as likely to tell it, depending on how well they believe it. A villager does not repeat news the listener already knows, unless nothing else is available.

Each villager has an interest in going on, from 0 to 1. Townstead uses interest to decide how long a conversation lasts.

At the start, a villager’s interest is:

  • their chattiness with this partner,
  • plus affection toward the partner divided by 60, from -0.2 to 0.2,
  • minus 0.1 when their mood is low,
  • plus the fever effect below,
  • plus 0.25 and some randomness: more for idle chats, less at hangouts.

After each line:

EventChange
Every line-0.035 for both in an idle chat, -0.012 at a hangout.
Two lines in a row with the same stance+0.04 for both.
Two lines in a row with opposite stances-0.05 for both.
A joke is praised+0.12 for the teller, +0.05 for the listener.
A joke gets a groan-0.08 for the teller, -0.03 for the listener.
A question is answered+0.03 for the one who asked.
A pause at a hangout+0.12 for both.

The less interested villager sets the pace:

  • In an idle chat, before each new topic after the first, the chance that the chat ends is 1 - interest.
  • The chance of an expansion is interest.
  • With interest below 0.12 after the greeting, an idle chat can end with no topic at all.
  • At a hangout, low interest brings pauses.

A zombie infection with a fever changes interest:

VillagerChange
The villager with the fever-0.15
A close friend of the sick villager (affection 30 or more)+0.1
An anxious, shy, introverted, sensitive, crabby or grumpy villager-0.25
Anyone else-0.05

After a topic in the grief register, a humor topic is 10 × less likely for the rest of the conversation. A speaker with a fever is 5 × less likely to start a humor topic.

The state key mood describes how the conversation feels. Lines can require it with "state": {"mood": "tense"}.

MoodWhen
tenseThe villagers clashed twice (opposite stances from different speakers), or they started tense and have had fewer than 4 lines.
warmThe less interested villager is at 0.6 or more, or they started warm and they are both still at 0.35 or more.
flatThe more interested villager is below 0.3.
(missing)Anything else.

A conversation starts tense between strained villagers, and warm between friends. When one villager has a fever, it starts tense unless they are friends.

A player sees a line in chat within 20 blocks of the speaker: in white within 10 blocks, and in grey beyond. Each player sees the line in their own language.

When no player is within 48 blocks of the speaker, Townstead builds no text and plays no gestures. The conversation still goes on at about 3 seconds per line, and its effects still apply: gossip, relationship changes, memories and outcomes.