diff --git a/IdleSpectator/ActivityActionComposer.cs b/IdleSpectator/ActivityActionComposer.cs
index 8133278..2f84354 100644
--- a/IdleSpectator/ActivityActionComposer.cs
+++ b/IdleSpectator/ActivityActionComposer.cs
@@ -1,76 +1,10 @@
using System;
-using System.Collections.Generic;
namespace IdleSpectator;
/// Single deterministic action-selection pipeline.
public static class ActivityActionComposer
{
- private static readonly Dictionary BeatTemplates =
- new Dictionary(StringComparer.Ordinal)
- {
- ["BehUnloadResources"] = new[]
- {
- "unloads {carrying} at {place}",
- "delivers {carrying} into store{place_at}"
- },
- ["BehThrowResources"] = new[]
- {
- "throws {carrying} toward storage",
- "tosses {carrying} from the pack"
- },
- ["BehSocializeTalk"] = new[]
- {
- "talks{with}{place_at}",
- "shares words{with}{place_at}"
- },
- ["BehTryToSocialize"] = new[]
- {
- "tries to socialize{with}{place_at}",
- "looks for a conversation{with}{place_at}"
- },
- ["BehPlantCrops"] = new[]
- {
- "plants crops{place_at}{job_as}",
- "sets seed in the soil{place_at}"
- },
- ["BehCityActorFertilizeCrop"] = new[]
- {
- "fertilizes the crops{place_at}{job_as}",
- "feeds the soil{place_at}"
- },
- ["BehBuildTarget"] = new[]
- {
- "works the build{place_at}{job_as}",
- "raises construction{place_at}"
- },
- ["BehPoopOutside"] = new[]
- {
- "steps aside for a private moment outdoors",
- "tends to nature's call outside"
- },
- ["BehPoopInside"] = new[]
- {
- "steps aside for a private moment indoors",
- "tends to nature's call inside"
- },
- ["BehBoatFishing"] = new[]
- {
- "fishes from the boat{place_at}",
- "works the waters from aboard{place_at}"
- },
- ["BehBoatCollectFish"] = new[]
- {
- "collects the catch aboard{place_at}",
- "hauls in the boat's catch{place_at}"
- },
- ["BehClaimZoneForCityActorBorder"] = new[]
- {
- "claims border land{place_at}",
- "stakes new ground for the settlement{place_at}"
- }
- };
-
public static string Compose(
ActivityContext ctx,
string key,
@@ -82,31 +16,12 @@ public static class ActivityActionComposer
ctx ??= ActivityContext.Empty;
ProseVoice voice = EnsureVoice(ctx);
- if (!string.IsNullOrEmpty(key)
- && BeatTemplates.TryGetValue(key, out string[] beatBag)
- && voice.AssetKind != ActivityAssetKind.Vehicle)
- {
- return Pick(beatBag, subjectId, lineIndex);
- }
-
string verb = ActivityVerbMap.Resolve(key);
if (string.IsNullOrEmpty(verb))
{
- string factual = ActivityProse.FactualActionPhrase(rawFact, key, hasTarget);
- factual = ActivityClauseAssembler.StripSpeciesTokensPublic(factual, ctx);
- if (!string.IsNullOrEmpty(factual))
- {
- return factual;
- }
-
- string patterned = ActivityProse.PatternActionPhrase(key, hasTarget);
- if (!string.IsNullOrEmpty(patterned))
- {
- return patterned;
- }
-
- string humanized = ActivityProse.HumanizeKeyPublic(key);
- verb = string.IsNullOrEmpty(humanized) ? "move" : humanized.ToLowerInvariant();
+ // Future unknown tasks still get the mob's authored work voice.
+ // The exhaustive runtime audit blocks every current task from reaching this branch.
+ verb = "work";
}
string[] bag = ActivityActionLexicon.GetBag(voice, verb, hasTarget, ctx.Terrain);
diff --git a/IdleSpectator/ActivityClauseAssembler.cs b/IdleSpectator/ActivityClauseAssembler.cs
index f0f9d54..38c1ce8 100644
--- a/IdleSpectator/ActivityClauseAssembler.cs
+++ b/IdleSpectator/ActivityClauseAssembler.cs
@@ -56,11 +56,42 @@ public static class ActivityClauseAssembler
// Traits stay on the dossier chips - they only salt variety below, never named here.
- string pressure = BuildPressureClause(ctx, action);
- string line = subject + " " + action + pressure;
+ string target = BuildObservedTargetClause(ctx, action);
+ string carrying = BuildCarryingClause(ctx, action);
+ string pressure = BuildPressureClause(ctx, action + target);
+ string line = subject + " " + action + target + carrying + pressure;
return CollapseSpaces(line).Trim();
}
+ private static string BuildObservedTargetClause(ActivityContext ctx, string action)
+ {
+ if (ctx == null
+ || !ctx.TargetIsActor
+ || string.IsNullOrEmpty(ctx.TargetName)
+ || ctx.InCombat
+ || ctx.HasAttackTarget
+ || action.IndexOf("{target}", StringComparison.Ordinal) >= 0
+ || action.IndexOf("{with}", StringComparison.Ordinal) >= 0)
+ {
+ return "";
+ }
+
+ return " with {target}";
+ }
+
+ private static string BuildCarryingClause(ActivityContext ctx, string action)
+ {
+ if (ctx == null
+ || string.IsNullOrEmpty(ctx.CarryingLabel)
+ || action.IndexOf("{carrying}", StringComparison.Ordinal) >= 0
+ || action.IndexOf(ctx.CarryingLabel, StringComparison.OrdinalIgnoreCase) >= 0)
+ {
+ return "";
+ }
+
+ return " while carrying {carrying}";
+ }
+
private static string BuildSubject(ActivityContext ctx, string action, out bool placeInAppositive)
{
placeInAppositive = false;
diff --git a/IdleSpectator/ActivityProse.cs b/IdleSpectator/ActivityProse.cs
index be842b3..e6c4de5 100644
--- a/IdleSpectator/ActivityProse.cs
+++ b/IdleSpectator/ActivityProse.cs
@@ -1,395 +1,13 @@
-using System.Collections.Generic;
-
namespace IdleSpectator;
///
-/// Fact-preserving activity sentences with colored actor/target names.
+/// Fact-preserving activity sentence formatting with colored actor/target names.
+/// supplies templates from the verb map and authored species bags.
///
public static class ActivityProse
{
public const string NameColorHex = "#F0C14A";
- ///
- /// Long detailed templates. Tokens: {actor}{target}{species}{place}{place_at}{job}{job_as}{carrying}{with}.
- /// Never invent outcomes - only flavor observed tasks.
- /// Prefer for full alive composition; Variants seed action phrases.
- ///
- private static readonly Dictionary Variants = new Dictionary
- {
- ["attack"] = new[]
- {
- "{actor} strikes hard at {target}{place_at}",
- "{actor} presses the attack on {target}{place_at}",
- "{actor} lunges toward {target} with clear intent{place_at}"
- },
- ["fight"] = new[]
- {
- "{actor} fights {target} in a fierce clash{place_at}",
- "{actor} clashes with {target}{place_at}{job_as}",
- "{actor} trades blows with {target}{place_at}"
- },
- ["fighting"] = new[]
- {
- "{actor} is locked in combat with {target}{place_at}",
- "{actor} fights {target} without giving ground{place_at}",
- "{actor} clashes with {target}{place_at}"
- },
- ["hunt"] = new[]
- {
- "{actor} pursues {target}{place_at}",
- "{actor} stalks {target} from cover{place_at}",
- "{actor} closes in on {target}{place_at}"
- },
- ["BehAttackActorHuntingTarget"] = new[]
- {
- "{actor} hunts {target} and strikes when the moment opens{place_at}",
- "{actor} closes on {target} in the chase{place_at}",
- "{actor} strikes at {target} while hunting{place_at}"
- },
- ["heal"] = new[]
- {
- "{actor} tends carefully to {target}{place_at}",
- "{actor} works to heal {target}{place_at}",
- "{actor} binds {target}'s wounds with steady hands{place_at}"
- },
- ["check_heal"] = new[]
- {
- "{actor} checks over wounds with worried care{place_at}",
- "{actor} looks closely at injuries{place_at}",
- "{actor} takes stock of pain before moving on{place_at}"
- },
- ["cure"] = new[]
- {
- "{actor} seeks a cure for what ails them{place_at}",
- "{actor} works to recover from sickness{place_at}",
- "{actor} fights sickness with stubborn will{place_at}"
- },
- ["eat"] = new[]
- {
- "{actor} sits down to eat{place_at}{job_as}",
- "{actor} finds something to eat{place_at}",
- "{actor} finishes a meal{place_at}"
- },
- ["eating"] = new[]
- {
- "{actor} sits down to eat{place_at}{job_as}",
- "{actor} finds something to eat{place_at}",
- "{actor} finishes a meal{place_at}"
- },
- ["sleep"] = new[]
- {
- "{actor} settles into sleep and lets the world go quiet{place_at}",
- "{actor} rests deeply after the day's demands{place_at}{job_as}",
- "{actor} curls into sleep{place_at}"
- },
- ["decide_where_to_sleep"] = new[]
- {
- "{actor} searches for a safe place to sleep{place_at}",
- "{actor} weighs where to rest for the night{place_at}",
- "{actor} seeks shelter before settling down{place_at}"
- },
- ["random_move"] = new[]
- {
- "{actor} wanders without hurry{place_at}",
- "{actor} roams nearby, looking around{place_at}",
- "{actor} drifts along with nowhere urgent to be{place_at}"
- },
- ["city_idle_walking"] = new[]
- {
- "{actor} walks the streets at an easy pace{place_at}{job_as}",
- "{actor} strolls through the settlement, watching life pass{place_at}",
- "{actor} paces familiar paths between errands{place_at}"
- },
- ["move"] = new[]
- {
- "{actor} is on the move with purpose{place_at}{job_as}",
- "{actor} travels onward through the world{place_at}",
- "{actor} heads out toward the next mark{place_at}"
- },
- ["pollinate"] = new[]
- {
- "{actor} dusts the blossom with careful work{place_at}",
- "{actor} works the flower and leaves the air sweet{place_at}",
- "{actor} leaves pollen behind on the bloom{place_at}"
- },
- ["BehPollinate"] = new[]
- {
- "{actor} dusts the blossom with careful work{place_at}",
- "{actor} works the flower and leaves the air sweet{place_at}",
- "{actor} leaves pollen behind on the bloom{place_at}"
- },
- ["farm"] = new[]
- {
- "{actor} tends the fields with patient labor{place_at}{job_as}",
- "{actor} works the soil until it answers{place_at}",
- "{actor} farms the plot through the day{place_at}"
- },
- ["harvest"] = new[]
- {
- "{actor} harvests the ripe crop with practiced hands{place_at}{job_as}",
- "{actor} gathers the yield before it spoils{place_at}",
- "{actor} cuts the ripe fields clean{place_at}"
- },
- ["forag"] = new[]
- {
- "{actor} forages through wild growth for food{place_at}",
- "{actor} gathers what the land offers freely{place_at}",
- "{actor} searches the brush for forage{place_at}"
- },
- ["gather"] = new[]
- {
- "{actor} gathers stores for leaner days{place_at}{job_as}",
- "{actor} collects goods with steady purpose{place_at}",
- "{actor} forages supplies into the pack{place_at}"
- },
- ["mine"] = new[]
- {
- "{actor} delves the mine for ore and stone{place_at}{job_as}",
- "{actor} chips at the rock face with hard labor{place_at}",
- "{actor} works the dig until the haul is ready{place_at}"
- },
- ["build"] = new[]
- {
- "{actor} builds with focused craft{place_at}{job_as}",
- "{actor} raises walls and timber into shape{place_at}",
- "{actor} labors on construction until it stands{place_at}"
- },
- ["woodcut"] = new[]
- {
- "{actor} fells timber for the settlement's need{place_at}{job_as}",
- "{actor} takes an axe to the trees with measured swings{place_at}",
- "{actor} cuts wood and stacks the haul{place_at}"
- },
- ["fire"] = new[]
- {
- "{actor} races the blaze and fights to keep it down{place_at}",
- "{actor} douses flames before they claim more ground{place_at}",
- "{actor} battles the fire with urgent work{place_at}"
- },
- ["BehCityActorRemoveFire"] = new[]
- {
- "{actor} races the blaze and fights to keep it down{place_at}",
- "{actor} douses flames before they claim more ground{place_at}",
- "{actor} beats back the fire with urgent work{place_at}"
- },
- ["social"] = new[]
- {
- "{actor} talks at length{with}{place_at}{job_as}",
- "{actor} socializes and shares the moment{with}{place_at}",
- "{actor} converses warmly{with}{place_at}"
- },
- ["socialize"] = new[]
- {
- "{actor} talks at length{with}{place_at}{job_as}",
- "{actor} socializes and shares the moment{with}{place_at}",
- "{actor} joins company nearby{with}{place_at}"
- },
- ["lover"] = new[]
- {
- "{actor} seeks out {target} with unmistakable longing{place_at}",
- "{actor} is drawn toward {target} through the day{place_at}",
- "{actor} pursues {target}'s affection with quiet resolve{place_at}"
- },
- ["breed"] = new[]
- {
- "{actor} tries to start a family with {target}{place_at}",
- "{actor} courts {target} with clear intent{place_at}",
- "{actor} seeks offspring with {target}{place_at}"
- },
- ["sexual_reproduction"] = new[]
- {
- "{actor} tries to start a family with {target}{place_at}",
- "{actor} courts {target} with clear intent{place_at}",
- "{actor} seeks offspring with {target}{place_at}"
- },
- ["unload"] = new[]
- {
- "{actor} unloads {carrying} into store{place_at}",
- "{actor} delivers {carrying} after a long haul{place_at}",
- "{actor} empties the pack of {carrying}{place_at}"
- },
- ["BehUnloadResources"] = new[]
- {
- "{actor} unloads {carrying} at {place}",
- "{actor} delivers {carrying} into store{place_at}",
- "{actor} empties the pack of {carrying}{place_at}"
- },
- ["job"] = new[]
- {
- "{actor} looks for honest work{place_at}",
- "{actor} looks for a job that will keep them fed{place_at}",
- "{actor} searches for employment through the settlement{place_at}"
- },
- ["find_city_job"] = new[]
- {
- "{actor} seeks work in town{place_at}",
- "{actor} checks the available city jobs{place_at}",
- "{actor} searches the settlement for employment{place_at}"
- },
- ["find_house"] = new[]
- {
- "{actor} looks for a house to call home{place_at}",
- "{actor} seeks shelter and a lasting roof{place_at}",
- "{actor} searches for a place to settle{place_at}"
- },
- ["claim"] = new[]
- {
- "{actor} claims new ground for the settlement{place_at}",
- "{actor} stakes a claim on open land{place_at}",
- "{actor} takes claim of border ground{place_at}"
- },
- ["warrior"] = new[]
- {
- "{actor} follows the army with disciplined steps{place_at}",
- "{actor} marches with the warband{place_at}{job_as}",
- "{actor} keeps formation and waits for orders{place_at}"
- },
- ["army"] = new[]
- {
- "{actor} follows the army with disciplined steps{place_at}",
- "{actor} marches with the warband{place_at}",
- "{actor} keeps formation among the ranks{place_at}"
- },
- ["wait"] = new[]
- {
- "{actor} waits in watchful quiet{place_at}{job_as}",
- "{actor} holds still and lets the moment pass{place_at}",
- "{actor} bides time without wasting motion{place_at}"
- },
- ["make_decision"] = new[]
- {
- "{actor} considers next steps with care{place_at}",
- "{actor} weighs a choice before moving{place_at}{job_as}",
- "{actor} pauses in thought while the world waits{place_at}"
- },
- ["reflection"] = new[]
- {
- "{actor} reflects on what the day has asked{place_at}",
- "{actor} takes a quiet moment to think things over{place_at}",
- "{actor} settles into reflection away from noise{place_at}"
- },
- ["run_away"] = new[]
- {
- "{actor} flees hard for safer ground{place_at}",
- "{actor} runs for safety without looking back{place_at}",
- "{actor} retreats in a burst of fear{place_at}"
- },
- ["trade"] = new[]
- {
- "{actor} keeps a careful eye on traded goods{place_at}{job_as}",
- "{actor} barters over prices{place_at}",
- "{actor} makes a trading run{place_at}"
- },
- ["fish"] = new[]
- {
- "{actor} waits patiently for a bite{place_at}{job_as}",
- "{actor} casts for fish where the current runs{place_at}",
- "{actor} works the waters for a catch{place_at}"
- },
- ["family_group"] = new[]
- {
- "{actor} joins the herd and stays close to kin{place_at}",
- "{actor} seeks the family group across open ground{place_at}",
- "{actor} gathers with kin for safety and company{place_at}"
- },
- ["generate_loot"] = new[]
- {
- "{actor} gathers loot from what the fight left behind{place_at}",
- "{actor} claims spoils with practical hands{place_at}",
- "{actor} picks through loot before moving on{place_at}"
- },
- ["laughing"] = new[]
- {
- "{actor} laughs aloud and lets the mood carry{place_at}",
- "{actor} bursts into laughter without restraint{place_at}",
- "{actor} keeps laughing until short of breath{place_at}"
- },
- ["happy_laughing"] = new[]
- {
- "{actor} laughs with bright, unguarded joy{place_at}",
- "{actor} laughs happily among nearby company{place_at}",
- "{actor} chuckles aloud until the mood softens{place_at}"
- },
- ["just_laughed"] = new[]
- {
- "{actor} just finished laughing and catches a breath{place_at}",
- "{actor} settles after a laugh, still smiling{place_at}",
- "{actor} catches their breath from laughing{place_at}"
- },
- ["singing"] = new[]
- {
- "{actor} sings out for whoever will hear{place_at}{job_as}",
- "{actor} lifts a song into the open air{place_at}",
- "{actor} is singing through the quiet stretch{place_at}"
- },
- ["task_unit_play"] = new[]
- {
- "{actor} moves about in quick, restless bursts{place_at}",
- "{actor} darts back and forth for a while{place_at}",
- "{actor} bounds around with eager energy{place_at}"
- },
- ["just_played"] = new[]
- {
- "{actor} slows down after playing{place_at}",
- "{actor} stops to catch a breath{place_at}",
- "{actor} settles after a burst of activity{place_at}"
- },
- ["child_play_at_one_spot"] = new[]
- {
- "{actor} hops and pivots without wandering far{place_at}",
- "{actor} keeps busy in one small spot{place_at}",
- "{actor} turns and bounces in place{place_at}"
- },
- ["child_random_flips"] = new[]
- {
- "{actor} flips and tumbles about{place_at}",
- "{actor} rolls forward and springs upright{place_at}",
- "{actor} tries one quick flip after another{place_at}"
- },
- ["child_random_jump"] = new[]
- {
- "{actor} jumps about in quick bursts{place_at}",
- "{actor} leaps forward and doubles back{place_at}",
- "{actor} bounces around without settling{place_at}"
- },
- ["child_follow_parent"] = new[]
- {
- "{actor} follows a parent with careful steps{place_at}",
- "{actor} stays close to {target} through the day{place_at}",
- "{actor} trails after kin and will not stray far{place_at}"
- },
- ["random_fun_move"] = new[]
- {
- "{actor} frolics and wheels around{place_at}",
- "{actor} darts off and circles back{place_at}",
- "{actor} skips along without hurry{place_at}"
- },
- ["godfinger_random_fun_move"] = new[]
- {
- "{actor} moves in sudden, unpredictable turns{place_at}",
- "{actor} darts one way, then abruptly another{place_at}",
- "{actor} loops around in restless motion{place_at}"
- },
- ["try_to_read"] = new[]
- {
- "{actor} tries to read and settle into the page{place_at}",
- "{actor} opens a book and gives it quiet attention{place_at}",
- "{actor} settles in to read while the world softens{place_at}"
- },
- ["try_to_poop"] = new[]
- {
- "{actor} looks for a private moment away from eyes{place_at}",
- "{actor} tends to nature's call with hurried dignity{place_at}",
- "{actor} steps aside briefly for a private need{place_at}"
- },
- ["try_to_launch_fireworks"] = new[]
- {
- "{actor} tries to launch fireworks into celebration{place_at}",
- "{actor} readies a firework with careful hands{place_at}",
- "{actor} prepares a celebration blast for the sky{place_at}"
- }
- };
-
public static string ColorName(string name)
{
if (string.IsNullOrEmpty(name))
@@ -464,15 +82,10 @@ public static class ActivityProse
varietyId,
lineIndex);
+ // Unreachable by composer contract. Preserve empty output so missing authored coverage remains auditable.
if (string.IsNullOrEmpty(template))
{
- template = "{actor} attends to " + LowerFirst(HumanizeKey(key))
- + "{place_at}{job_as}";
- if (string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(rawFact))
- {
- template = GerundSentence(rawFact);
- }
-
+ return;
}
plain = Apply(template, ctx, colored: false);
@@ -526,34 +139,11 @@ public static class ActivityProse
}
}
- /// Action-only phrase from pattern heuristics (no subject).
- public static string PatternActionPhrase(string key, bool hasTarget)
- {
- string full = PatternTemplate(key, hasTarget);
- if (string.IsNullOrEmpty(full))
- {
- return "";
- }
-
- return ActivityClauseAssembler.StripSubject(full);
- }
-
- public static string HumanizeKeyPublic(string key)
- {
- return HumanizeKey(key);
- }
-
public static string HumanizeJobPublic(string jobId)
{
return HumanizeJob(jobId);
}
- /// Observed localized fact as an action-only phrase for unknown task ids.
- public static string FactualActionPhrase(string rawFact, string key, bool hasTarget)
- {
- return ActivityClauseAssembler.StripSubject(LocalizedTemplate(rawFact, key, hasTarget));
- }
-
/// Legacy helper used by older call sites / harness.
public static string Format(
ActivityKind kind,
@@ -670,362 +260,6 @@ public static class ActivityProse
return LowerFirst(s);
}
- private static string PatternTemplate(string key, bool hasTarget)
- {
- if (string.IsNullOrEmpty(key))
- {
- return null;
- }
-
- string k = key.ToLowerInvariant();
- const string clauses = "{place_at}{job_as}";
-
- if (k.StartsWith("try_to_"))
- {
- return "{actor} tries to " + HumanizeKey(k.Substring("try_to_".Length))
- + " with careful effort" + clauses;
- }
-
- if (k.StartsWith("check_"))
- {
- return "{actor} checks " + HumanizeKey(k.Substring("check_".Length))
- + " before deciding what comes next" + clauses;
- }
-
- if (k.StartsWith("find_"))
- {
- return "{actor} looks for " + HumanizeKey(k.Substring("find_".Length))
- + clauses;
- }
-
- if (k.StartsWith("decide_"))
- {
- return "{actor} decides " + HumanizeKey(k.Substring("decide_".Length))
- + " after a moment of thought" + clauses;
- }
-
- if (k.StartsWith("build_"))
- {
- return "{actor} builds " + HumanizeKey(k.Substring("build_".Length))
- + " with steady hands" + clauses;
- }
-
- if (k.StartsWith("boat_"))
- {
- return "{actor} " + BoatVerb(k.Substring("boat_".Length)) + clauses;
- }
-
- if (k.StartsWith("warrior_"))
- {
- return WarriorTemplate(k, hasTarget) + clauses;
- }
-
- if (k.StartsWith("socialize_"))
- {
- return hasTarget
- ? "{actor} spends time with {target}" + clauses
- : "{actor} looks for company" + clauses;
- }
-
- if (k.StartsWith("sexual_reproduction") || k.StartsWith("asexual_reproduction"))
- {
- return hasTarget
- ? "{actor} tries to start a family with {target}" + clauses
- : "{actor} tries to reproduce and carry life forward" + clauses;
- }
-
- if (k.StartsWith("child_"))
- {
- return "{actor} " + LowerFirst(HumanizeKey(k.Substring("child_".Length)))
- + " eagerly" + clauses;
- }
-
- if (k.StartsWith("ant_") || k.StartsWith("bee_") || k.StartsWith("ufo_")
- || k.StartsWith("dragon_") || k.StartsWith("worm_"))
- {
- return "{actor} " + LowerFirst(HumanizeKey(StripCreaturePrefix(k)))
- + clauses;
- }
-
- if (k.StartsWith("task_unit_"))
- {
- return LocalizedStyleFromId(k.Substring("task_unit_".Length), hasTarget);
- }
-
- if (k.Contains("laugh"))
- {
- return "{actor} laughs aloud and lets the mood carry" + clauses;
- }
-
- if (k.Contains("sing"))
- {
- return "{actor} sings out for whoever will hear" + clauses;
- }
-
- if (k.Contains("play") && !k.Contains("display"))
- {
- return hasTarget
- ? "{actor} plays with {target}" + clauses
- : "{actor} finds a way to amuse itself" + clauses;
- }
-
- if (k.Contains("wait"))
- {
- return "{actor} waits in watchful quiet" + clauses;
- }
-
- if (k.Contains("sleep"))
- {
- return "{actor} settles into sleep and lets the world go quiet" + clauses;
- }
-
- if (k.Contains("idle") || k.Contains("random_move") || k.EndsWith("_move")
- || k.Contains("walking"))
- {
- return "{actor} wanders without hurry" + clauses;
- }
-
- if (k.Contains("fight") || k.Contains("attack") || k.Contains("hunt"))
- {
- return hasTarget
- ? "{actor} strikes at {target} with clear intent" + clauses
- : "{actor} braces for a fight" + clauses;
- }
-
- if (k.Contains("heal") || k.Contains("cure"))
- {
- return hasTarget
- ? "{actor} tends carefully to {target}" + clauses
- : "{actor} tends to wounds with worried care" + clauses;
- }
-
- if (k.Contains("eat") || k.Contains("food"))
- {
- return "{actor} sits down to eat" + clauses;
- }
-
- if (k.Contains("farm") || k.Contains("harvest") || k.Contains("forag")
- || k.Contains("gather") || k.Contains("chop") || k.Contains("mine")
- || k.Contains("build") || k.Contains("woodcut"))
- {
- return "{actor} " + LowerFirst(HumanizeKey(k))
- + " with steady labor" + clauses;
- }
-
- if (k.Contains("trade") || k.Contains("fish") || k.Contains("unload")
- || k.Contains("claim") || k.Contains("fire"))
- {
- return "{actor} " + LowerFirst(HumanizeKey(k))
- + clauses;
- }
-
- return null;
- }
-
- private static string WarriorTemplate(string k, bool hasTarget)
- {
- if (k.Contains("follow"))
- {
- return hasTarget
- ? "{actor} follows {target} with disciplined steps"
- : "{actor} follows the army with disciplined steps";
- }
-
- if (k.Contains("train"))
- {
- return "{actor} trains for war with hard repetition";
- }
-
- if (k.Contains("join"))
- {
- return "{actor} tries to join the army and take a place in the ranks";
- }
-
- if (k.Contains("attack"))
- {
- return hasTarget
- ? "{actor} marches on {target} with the warband"
- : "{actor} marches to attack with the warband";
- }
-
- if (k.Contains("wait") || k.Contains("idle"))
- {
- return "{actor} holds formation and waits for orders";
- }
-
- return "{actor} " + LowerFirst(HumanizeKey(k.Replace("warrior_", "")))
- + " among the ranks";
- }
-
- private static string BoatVerb(string rest)
- {
- if (rest.Contains("fish"))
- {
- return "fishes from the boat and waits for a bite";
- }
-
- if (rest.Contains("trade"))
- {
- return "carries trade goods by boat";
- }
-
- if (rest.Contains("dock") || rest.Contains("return"))
- {
- return "returns to dock after time on the water";
- }
-
- if (rest.Contains("load"))
- {
- return "loads the boat for the next run";
- }
-
- if (rest.Contains("unload"))
- {
- return "unloads the boat and clears the hold";
- }
-
- if (rest.Contains("idle"))
- {
- return "waits aboard between trips";
- }
-
- return LowerFirst(HumanizeKey(rest)) + " aboard";
- }
-
- private static string StripCreaturePrefix(string k)
- {
- int idx = k.IndexOf('_');
- return idx > 0 && idx < k.Length - 1 ? k.Substring(idx + 1) : k;
- }
-
- private static string LocalizedStyleFromId(string rest, bool hasTarget)
- {
- const string clauses = "{place_at}{job_as}";
- if (rest == "play")
- {
- return "{actor} finds a way to amuse itself" + clauses;
- }
-
- if (rest == "wait")
- {
- return "{actor} waits in watchful quiet" + clauses;
- }
-
- if (rest == "walk")
- {
- return "{actor} walks at an easy pace" + clauses;
- }
-
- if (rest.Contains("social"))
- {
- return hasTarget
- ? "{actor} spends time with {target}" + clauses
- : "{actor} looks for company" + clauses;
- }
-
- return "{actor} " + LowerFirst(HumanizeKey(rest))
- + clauses;
- }
-
- ///
- /// Turn game localized labels like "Laughing" / "Job Seeking" into real sentences.
- ///
- private static string LocalizedTemplate(string rawFact, string key, bool hasTarget)
- {
- string loc = ExtractLocalizedBody(rawFact, key);
- if (string.IsNullOrEmpty(loc))
- {
- return null;
- }
-
- return GerundSentence(loc);
- }
-
- private static string ExtractLocalizedBody(string rawFact, string key)
- {
- if (string.IsNullOrEmpty(rawFact))
- {
- return null;
- }
-
- string body = rawFact;
- int arrow = body.IndexOf('→');
- if (arrow < 0)
- {
- arrow = body.IndexOf("->", System.StringComparison.Ordinal);
- }
-
- if (arrow >= 0)
- {
- body = body.Substring(0, arrow).Trim();
- }
-
- if (body.StartsWith("Task:", System.StringComparison.OrdinalIgnoreCase))
- {
- return null;
- }
-
- // Ignore if it's just the raw key.
- if (!string.IsNullOrEmpty(key)
- && body.Equals(key, System.StringComparison.OrdinalIgnoreCase))
- {
- return null;
- }
-
- return body.Trim();
- }
-
- private static string GerundSentence(string loc)
- {
- if (string.IsNullOrEmpty(loc))
- {
- return null;
- }
-
- string body = loc.Trim();
- // "Laughing" / "Job Seeking" / "Holding Still"
- if (IsGerundPhrase(body))
- {
- return "{actor} is " + LowerFirst(body)
- + "{place_at}{job_as}";
- }
-
- // Already a short verb phrase - still give it place/job room.
- return "{actor} " + LowerFirst(body) + "{place_at}{job_as}";
- }
-
- private static bool IsGerundPhrase(string body)
- {
- if (string.IsNullOrEmpty(body))
- {
- return false;
- }
-
- string[] parts = body.Split(new[] { ' ' }, System.StringSplitOptions.RemoveEmptyEntries);
- if (parts.Length == 0 || parts.Length > 4)
- {
- return false;
- }
-
- // Last token ends with -ing (Laughing, Seeking, Holding...)
- string last = parts[parts.Length - 1];
- return last.Length > 4
- && last.EndsWith("ing", System.StringComparison.OrdinalIgnoreCase);
- }
-
- private static string HumanizeKey(string key)
- {
- if (string.IsNullOrEmpty(key))
- {
- return "";
- }
-
- string s = key.Replace("Beh", "").Replace('_', ' ').Trim();
- // Collapse common noise words for readability.
- s = s.Replace("task unit ", "").Replace("type ", "");
- return s;
- }
-
private static string LowerFirst(string s)
{
if (string.IsNullOrEmpty(s))
@@ -1040,90 +274,4 @@ public static class ActivityProse
return char.ToLowerInvariant(s[0]) + s.Substring(1);
}
-
- private static string PickTemplate(string key, long subjectId, int lineIndex, bool hasTarget)
- {
- if (string.IsNullOrEmpty(key))
- {
- return null;
- }
-
- string[] bag = null;
- if (Variants.TryGetValue(key, out bag) && bag != null && bag.Length > 0)
- {
- return PreferTargetAware(bag, hasTarget, subjectId, key, lineIndex);
- }
-
- string lower = key.ToLowerInvariant();
- string bestKey = null;
- string[] bestBag = null;
- int bestLen = -1;
- foreach (KeyValuePair kv in Variants)
- {
- if (kv.Value == null || kv.Value.Length == 0)
- {
- continue;
- }
-
- if (lower.IndexOf(kv.Key, System.StringComparison.Ordinal) >= 0 && kv.Key.Length > bestLen)
- {
- bestLen = kv.Key.Length;
- bestKey = kv.Key;
- bestBag = kv.Value;
- }
- }
-
- if (bestBag == null)
- {
- return null;
- }
-
- return PreferTargetAware(bestBag, hasTarget, subjectId, bestKey, lineIndex);
- }
-
- private static string PreferTargetAware(
- string[] bag,
- bool hasTarget,
- long subjectId,
- string key,
- int lineIndex)
- {
- var suited = new List(bag.Length);
- for (int i = 0; i < bag.Length; i++)
- {
- string line = bag[i];
- bool needsTarget = line.IndexOf("{target}", System.StringComparison.Ordinal) >= 0;
- if (hasTarget || !needsTarget)
- {
- suited.Add(line);
- }
- }
-
- if (suited.Count == 0)
- {
- suited.AddRange(bag);
- }
-
- return suited[PickIndex(subjectId, key, lineIndex, suited.Count)];
- }
-
- private static int PickIndex(long subjectId, string key, int lineIndex, int count)
- {
- if (count <= 1)
- {
- return 0;
- }
-
- unchecked
- {
- int h = (int)(subjectId * 397) ^ (key?.GetHashCode() ?? 0) ^ (lineIndex * 31);
- h ^= (int)(UnityEngine.Time.unscaledTime * 10f);
- if (h < 0)
- {
- h = -h;
- }
-
- return h % count;
- }
- }
}
diff --git a/IdleSpectator/ActivitySpeciesVoice.cs b/IdleSpectator/ActivitySpeciesVoice.cs
index c4da63a..5acae30 100644
--- a/IdleSpectator/ActivitySpeciesVoice.cs
+++ b/IdleSpectator/ActivitySpeciesVoice.cs
@@ -17,10 +17,16 @@ public enum ActivityVoiceSource
///
public sealed class ActivitySpeciesVoice
{
- public static readonly string[] CoreVerbs =
+ public static readonly string[] AuthoredVerbs =
{
"move", "wait", "play", "eat", "sleep",
- "hunt", "fight", "social", "laugh", "work"
+ "hunt", "fight", "social", "laugh", "work",
+ "sing", "lover", "farm", "pollinate", "trade",
+ "fish", "haul", "heal", "fire", "flee",
+ "settle", "warrior", "read", "gather_life", "relieve",
+ "confused", "recharge", "strange_urge", "steal", "possessed",
+ "dream", "ignite", "extinguish", "group", "harvest_life",
+ "loot", "cry", "swear"
};
private readonly Dictionary _bags;
@@ -35,6 +41,20 @@ public sealed class ActivitySpeciesVoice
_bags = bags ?? new Dictionary(StringComparer.Ordinal);
}
+ public static bool IsAuthoredVerb(string verb)
+ {
+ string key = verb ?? "";
+ for (int i = 0; i < AuthoredVerbs.Length; i++)
+ {
+ if (AuthoredVerbs[i].Equals(key, StringComparison.Ordinal))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
public string[] GetBag(string verb, ActivityTerrain terrain)
{
string key = verb ?? "";
@@ -51,9 +71,9 @@ public sealed class ActivitySpeciesVoice
public bool HasCompleteCore()
{
- for (int i = 0; i < CoreVerbs.Length; i++)
+ for (int i = 0; i < AuthoredVerbs.Length; i++)
{
- if (!_bags.TryGetValue(CoreVerbs[i], out string[] bag)
+ if (!_bags.TryGetValue(AuthoredVerbs[i], out string[] bag)
|| bag == null
|| bag.Length < 2
|| string.IsNullOrEmpty(bag[0])
@@ -73,4 +93,12 @@ public sealed class ActivitySpeciesVoice
_liquidBags[verb] = bag;
}
}
+
+ internal void SetBag(string verb, string[] bag)
+ {
+ if (!string.IsNullOrEmpty(verb) && bag != null && bag.Length > 0)
+ {
+ _bags[verb] = bag;
+ }
+ }
}
diff --git a/IdleSpectator/ActivitySpeciesVoiceCatalog.cs b/IdleSpectator/ActivitySpeciesVoiceCatalog.cs
index a7d34f7..c19b243 100644
--- a/IdleSpectator/ActivitySpeciesVoiceCatalog.cs
+++ b/IdleSpectator/ActivitySpeciesVoiceCatalog.cs
@@ -16,6 +16,16 @@ public static partial class ActivitySpeciesVoiceCatalog
AddAnimalVoices(voices);
AddInvertebrateVoices(voices);
AddFantasyVoices(voices);
+ AddCivExtendedVoices(voices);
+ AddMammalExtendedVoices(voices);
+ AddAnimalExtendedVoices(voices);
+ AddInvertebrateExtendedVoices(voices);
+ AddFantasyExtendedVoices(voices);
+ AddCivSpecializedVoices(voices);
+ AddMammalSpecializedVoices(voices);
+ AddAnimalSpecializedVoices(voices);
+ AddInvertebrateSpecializedVoices(voices);
+ AddFantasySpecializedVoices(voices);
return voices;
}
@@ -91,6 +101,89 @@ public static partial class ActivitySpeciesVoiceCatalog
}
}
+ private static void AddExtended(
+ Dictionary voices,
+ string id,
+ string[] sing,
+ string[] lover,
+ string[] farm,
+ string[] pollinate,
+ string[] trade,
+ string[] fish,
+ string[] haul,
+ string[] heal,
+ string[] fire,
+ string[] flee,
+ string[] settle,
+ string[] warrior,
+ string[] read,
+ string[] gatherLife,
+ string[] relieve,
+ string[] confused,
+ string[] recharge,
+ string[] strangeUrge,
+ string[] steal,
+ string[] possessed,
+ string[] dream)
+ {
+ if (!voices.TryGetValue(id, out ActivitySpeciesVoice voice))
+ {
+ throw new InvalidOperationException("Extended voice has no base entry: " + id);
+ }
+
+ Set(voice, "sing", sing);
+ Set(voice, "lover", lover);
+ Set(voice, "farm", farm);
+ Set(voice, "pollinate", pollinate);
+ Set(voice, "trade", trade);
+ Set(voice, "fish", fish);
+ Set(voice, "haul", haul);
+ Set(voice, "heal", heal);
+ Set(voice, "fire", fire);
+ Set(voice, "flee", flee);
+ Set(voice, "settle", settle);
+ Set(voice, "warrior", warrior);
+ Set(voice, "read", read);
+ Set(voice, "gather_life", gatherLife);
+ Set(voice, "relieve", relieve);
+ Set(voice, "confused", confused);
+ Set(voice, "recharge", recharge);
+ Set(voice, "strange_urge", strangeUrge);
+ Set(voice, "steal", steal);
+ Set(voice, "possessed", possessed);
+ Set(voice, "dream", dream);
+ }
+
+ private static void Set(ActivitySpeciesVoice voice, string verb, string[] phrases)
+ {
+ voice.SetBag(verb, Contextualize(phrases));
+ }
+
+ private static void AddSpecialized(
+ Dictionary voices,
+ string id,
+ string[] ignite,
+ string[] extinguish,
+ string[] group,
+ string[] harvestLife,
+ string[] loot,
+ string[] cry,
+ string[] swear)
+ {
+ if (!voices.TryGetValue(id, out ActivitySpeciesVoice voice))
+ {
+ throw new InvalidOperationException("Specialized voice has no base entry: " + id);
+ }
+
+ Set(voice, "ignite", ignite);
+ Set(voice, "extinguish", extinguish);
+ Set(voice, "group", group);
+ Set(voice, "harvest_life", harvestLife);
+ Set(voice, "loot", loot);
+ Set(voice, "cry", cry);
+ Set(voice, "swear", swear);
+ }
+
private static string[] V(string first, string second)
{
return new[] { first, second };
diff --git a/IdleSpectator/ActivitySpeciesVoices.Animals.Extended.cs b/IdleSpectator/ActivitySpeciesVoices.Animals.Extended.cs
new file mode 100644
index 0000000..e88670c
--- /dev/null
+++ b/IdleSpectator/ActivitySpeciesVoices.Animals.Extended.cs
@@ -0,0 +1,259 @@
+using System.Collections.Generic;
+
+namespace IdleSpectator;
+
+public static partial class ActivitySpeciesVoiceCatalog
+{
+ private static void AddAnimalExtendedVoices(Dictionary voices)
+ {
+ AddExtended(
+ voices,
+ "chicken",
+ V("lifts its beak through a bright clucking phrase", "pulses its throat while its comb bobs in rhythm"),
+ V("sidles close with one wing lowered", "touches beak tips through slow head bobs"),
+ V("rakes backward with alternating clawed feet", "pecks in a measured row with tail raised"),
+ V("brushes its breast feathers through repeated crouches", "dips its beak while wing tips sweep past"),
+ V("extends its neck and taps its beak twice", "steps beak-first through a deliberate exchange"),
+ V("cocks one eye before stabbing its beak downward", "holds a low crouch before a quick beak snap"),
+ V("leans breast-first and drives with both feet", "hooks its beak forward while legs keep pushing"),
+ V("preens along a wing with careful beak strokes", "parts breast feathers with short inspecting pecks"),
+ V("fans both wings through forceful downward beats", "stamps its feet while flight feathers flick rapidly"),
+ V("hurries in high steps with wings spread wide", "ducks its comb and runs with tail feathers level"),
+ V("circles twice before folding its legs beneath", "scrapes with both feet and lowers its feathered breast"),
+ V("raises its spurs while wings brace outward", "marches with comb high and beak held forward"),
+ V("tracks side to side with one bright eye", "tilts its head between small beak-led nods"),
+ V("combs its beak through rapid low sweeps", "scratches once before pinching with its beak"),
+ V("drops its tail and flexes beneath puffed feathers", "crouches low while its vent feathers lift"),
+ V("turns its head in abrupt one-eyed checks", "crosses its feet while its comb swivels back"),
+ V("shudders from breast to wing tips in quick pulses", "stiffens both legs as neck feathers ripple"),
+ V("jerks its beak sideways between uneven wing flicks", "pivots on one foot while its head bobs off-beat"),
+ V("crouches behind spread wings and darts its beak", "tiptoes with neck tucked before a sudden peck"),
+ V("paces in rigid steps with feathers standing out", "twists its neck while both wings twitch together"),
+ V("tucks its beak beneath one wing as toes curl", "settles into feathered stillness with comb tilted"));
+
+ AddExtended(
+ voices,
+ "crab",
+ V("clicks alternating pincers beneath pulsing mouthparts", "raises both claws through a clattering cadence"),
+ V("crosses pincers gently beneath touching eyestalks", "sidesteps close with both claws folded inward"),
+ V("rakes backward with alternating pointed walking legs", "clips repeatedly with one pincer while eyestalks track"),
+ V("sweeps both antennae through precise brushing arcs", "opens its pincers around a series of delicate dabs"),
+ V("presents one open claw then closes it slowly", "passes a measured pincer tap from side to side"),
+ V("holds one claw poised before a sudden pinch", "probes in short arcs with both pincers parted"),
+ V("grips forward and rows backward on six legs", "leans its shell rim ahead while pincers pull"),
+ V("grooms a bent leg between careful pincers", "picks along its shell seam with the smaller claw"),
+ V("fans its mouthparts while claws beat downward", "stamps its walking legs beneath a lifted shell"),
+ V("scuttles crabwise with pincers guarding its face", "drops its shell low and pedals every leg rapidly"),
+ V("tests a circle with antennae before folding its legs", "presses its shell down as pincers sweep outward"),
+ V("brandishes the larger claw above a squared stance", "locks both pincers forward while legs spread wide"),
+ V("tracks a line with independently turning eyestalks", "taps each pincer tip while mouthparts count"),
+ V("clips in tiny bites with alternating claw tips", "rakes its walking legs as antennae inspect each pass"),
+ V("lifts its shell rim while rear legs flex", "settles low as its abdominal flap tightens"),
+ V("sidesteps twice then reverses with claws crossed", "aims its eyestalks apart while legs shuffle inward"),
+ V("vibrates every walking leg beneath a rigid shell", "pumps its mouthparts as both claws slowly rise"),
+ V("winds one pincer overhead while circling crabwise", "flicks its antennae crosswise through uneven claw taps"),
+ V("reaches under its shell rim with the smaller pincer", "backs away while one claw closes out of sight"),
+ V("jerks sideways as both eyestalks dip together", "marches stiff-legged while pincers open and shut"),
+ V("folds its claws beneath the shell with legs tucked", "rests on bent joints as eyestalks gradually lower"));
+
+ AddExtended(
+ voices,
+ "crocodile",
+ V("lifts its long snout through a rumbling bellow", "vibrates its armored throat beneath parted jaws"),
+ V("rests jaw-to-jaw with its tail curled", "rubs plated snouts through a slow sideward sweep"),
+ V("pushes its snout forward while foreclaws rake", "presses its belly low and scrapes with splayed claws"),
+ V("sweeps its broad muzzle through low brushing passes", "nudges forward as ridged scales skim repeatedly"),
+ V("opens its jaws halfway then closes them with care", "angles its armored head through a measured jaw display"),
+ V("holds only its eyes and nostrils high before snapping", "creeps belly-low with jaws poised for a sideways clamp"),
+ V("drives its plated shoulders behind a steady shove", "backs with jaw muscles locked and tail braced"),
+ V("scrapes its teeth gently along a foreleg scale", "rubs one plated flank with slow hind-claw strokes"),
+ V("lashes its heavy tail through broad beating arcs", "raises its chest and stamps with splayed forefeet"),
+ V("surges low with tail whipping behind its plates", "scrambles on spread legs with jaw clamped shut"),
+ V("circles with snout lowered before flattening its belly", "slides its armored side through a full-length turn"),
+ V("stands high on splayed legs with jaws agape", "sweeps its plated tail behind a forward-facing snout"),
+ V("tracks side to side with one ridged eyelid narrowing", "tilts its long jaw between deliberate tooth-lined pauses"),
+ V("rakes backward with foreclaws beside its muzzle", "roots with its snout through short armored thrusts"),
+ V("raises its tail base while hind legs straighten", "arches its plated back above a low belly press"),
+ V("turns in a tight arc around its planted forefeet", "halts mid-crawl as jaw and tail point opposite ways"),
+ V("shudders along every dorsal ridge from snout to tail", "pumps its throat while all four claws grip"),
+ V("rolls one shoulder as its jaws yaw sideways", "corkscrews its plated torso through a sudden half-turn"),
+ V("slides its lower jaw forward beneath closed teeth", "hooks its snout aside while foreclaws conceal a motion"),
+ V("stalks stiff-legged with tail twitching in sections", "snaps at empty space as armored eyelids flutter"),
+ V("rests chin-flat with teeth hidden and legs folded", "lies motionless while its heavy tail slowly curves"));
+
+ AddExtended(
+ voices,
+ "frog",
+ V("inflates its throat sac through a rolling croak", "pulses its round throat beneath a chirping trill"),
+ V("presses splayed forefeet close through matching blinks", "leans in with throat pulsing and hind legs folded"),
+ V("scrapes backward with webbed hind toes", "plants its forefeet while long legs kick in alternation"),
+ V("brushes its belly past with toes spread broadly", "dabs with forefeet between short throat pulses"),
+ V("extends both forefeet then draws them to its chest", "bobs on folded legs through a deliberate toe display"),
+ V("aims both eyes before a lightning tongue flick", "compresses its hind legs beneath a still snout"),
+ V("shoves from the hips in repeated squat-legged thrusts", "braces both forefeet while long hind legs drive"),
+ V("wipes one round eye with a flexible forefoot", "rubs its mottled flank using a folded hind leg"),
+ V("springs upright as forefeet pat rapidly downward", "puffs its throat while webbed toes slap in sequence"),
+ V("bounds in low arcs with forelegs reaching ahead", "kicks backward in rapid leaps with eyes wide"),
+ V("tests a small circle by hopping toe-first", "squats centrally with all four feet spread"),
+ V("rises tall on hind legs with forefeet thrust forward", "crouches like a spring while throat sac stays taut"),
+ V("follows marks with alternating eye swivels", "counts along with tiny foretoe taps and blinks"),
+ V("snaps its tongue between careful forward hops", "parts with splayed fingers during short collecting dabs"),
+ V("lifts its rump while forelegs hold a deep squat", "stretches both hind legs behind a lowered belly"),
+ V("hops sideways then freezes with crossed forefeet", "swivels each eye separately while toes flex"),
+ V("quivers through its thighs as throat sac pulses fast", "stiffens its forelegs while hind toes tremble"),
+ V("jerks through crooked hops with tongue briefly extended", "twists its squat body between mismatched leg kicks"),
+ V("crouches over its forefeet before a furtive tongue snap", "folds its hind legs tight while one foretoe hooks inward"),
+ V("bounces without rhythm as both eyes roll", "puffs and collapses its throat through rigid little jumps"),
+ V("draws every foot beneath its belly and blinks slowly", "rests squat with throat pulses becoming shallow"));
+
+ AddExtended(
+ voices,
+ "ostrich",
+ V("stretches its long neck through a hollow booming call", "clacks its broad beak while throat feathers pulse"),
+ V("weaves raised necks through mirrored curves", "fans short wings while lowering its beak close"),
+ V("scrapes backward with alternating two-toed feet", "bends its tall neck through repeated beak dips"),
+ V("sweeps breast feathers past in a low-necked pass", "brushes with short wing plumes while stepping precisely"),
+ V("extends its flat beak then draws its neck upright", "bows on long legs through a measured wing display"),
+ V("holds its neck rigid before a downward beak jab", "tracks intently then lunges on lengthening strides"),
+ V("leans its feathered breast into a long-legged drive", "hooks its beak as both two-toed feet push"),
+ V("preens beneath one short wing with its flat beak", "combs shaggy breast feathers through quick beak pinches"),
+ V("beats both short wings while stamping long feet", "fans loose plumes through forceful sideward sweeps"),
+ V("runs with neck lowered and wing tips spread", "takes bounding strides while tail plumes flatten"),
+ V("paces a broad circle before folding its knees", "scrapes twice and lowers its feathered body centrally"),
+ V("stands neck-high with one long leg lifted", "drives a two-toed kick beneath spread wing plumes"),
+ V("traces side to side with high-set eyes", "bobs its long neck through deliberate beak-led pauses"),
+ V("pinches repeatedly while striding in a straight line", "rakes with one two-toed foot before a deep beak dip"),
+ V("raises its tail plumes as long knees bend", "squats with wings lifted from its feathered flanks"),
+ V("crosses its long legs while neck looping backward", "stares past its own shoulder as wing tips twitch"),
+ V("shivers from tall neck to loose tail plumes", "locks both knees while breast feathers ripple downward"),
+ V("whips its neck in an uneven curve between stamps", "circles with one wing fanned and one folded"),
+ V("stoops behind spread plumes and hooks its beak inward", "tiptoes on two-toed feet with neck tightly curved"),
+ V("struts stiff-kneed as its long neck zigzags", "kicks aside while both short wings flap together"),
+ V("folds long legs beneath its feathered body", "rests with its neck curled and broad beak still"));
+
+ AddExtended(
+ voices,
+ "penguin",
+ V("raises its narrow beak through a braying phrase", "pumps its chest beneath a chain of sharp honks"),
+ V("taps beaks softly with both flippers lowered", "leans chest-close while matching slow head tilts"),
+ V("scrapes with broad webbed feet between beak dips", "patters in rows while flippers balance each bend"),
+ V("brushes its white breast through low waddling passes", "sweeps stiff flipper edges with short side steps"),
+ V("extends its beak and flares one flipper", "bows from the ankles through a deliberate beak tap"),
+ V("leans beak-first before a sudden neck snap", "fixes both eyes while its webbed feet stop paddling"),
+ V("shoves with its chest through heel-to-heel steps", "braces stiff flippers backward as broad feet drive"),
+ V("preens its white breast with tiny beak pinches", "runs its narrow beak along one stiff flipper"),
+ V("slaps both flippers in rapid downward strokes", "stamps webbed feet while its compact chest bucks"),
+ V("waddles rapidly with flippers stretched sideways", "drops its belly low and paddles with both feet"),
+ V("turns heel-to-heel before settling on its belly", "traces a compact circle with beak taps and steps"),
+ V("squares its chest behind outstretched flippers", "marches upright with narrow beak leveled forward"),
+ V("tracks a line through alternating head tilts", "touches its beak along a sequence of tiny nods"),
+ V("picks in quick rows while flippers hold balance", "rakes backward with webbed feet before a beak pinch"),
+ V("lifts its short tail above a deep ankle crouch", "rocks forward as belly feathers spread apart"),
+ V("waddles sideways while looking straight behind", "crosses its webbed feet as both flippers point inward"),
+ V("trembles from white chest into rigid flipper tips", "stiffens upright while its short tail vibrates"),
+ V("windmills one flipper through a lopsided turn", "jerks its beak upward between uneven foot pats"),
+ V("hunches behind both flippers and darts its beak", "sidles heel-first with narrow beak tucked low"),
+ V("paces upright as flippers twitch in unison", "pecks sharply while its compact body rocks backward"),
+ V("rests belly-down with flippers fitted to its sides", "tucks its beak low as broad feet stop flexing"));
+
+ AddExtended(
+ voices,
+ "piranha",
+ V("pulses its gill covers around a clicking jaw rhythm", "flares paired fins while teeth chatter in cadence"),
+ V("aligns flank-close with fins beating in synchrony", "circles tightly through matched tail flicks"),
+ V("rakes with its lower jaw as paired fins brace", "nudges repeatedly with its blunt snout and folded fins"),
+ V("brushes past with scales angled and fins extended", "fans its paired fins through a sequence of close passes"),
+ V("opens its toothed jaw then folds both fins", "presents one scaled flank through a measured pivot"),
+ V("fixes its round eye before a rapid tooth snap", "stills every fin before its compact body darts"),
+ V("drives snout-first with strong lateral tail beats", "locks its jaws while paired fins reverse together"),
+ V("scrapes one scaled flank with a fin ray", "works its lower jaw while gill covers open wide"),
+ V("whips its tail as every fin beats rapidly", "bucks its compact body through forceful gill pulses"),
+ V("darts in sharp angles with fins pinned close", "lashes its tail through a rapid zigzag retreat"),
+ V("circles tightly with snout angled inward", "hovers centrally as paired fins make tiny corrections"),
+ V("flares every fin behind a fully opened jaw", "charges in a straight burst with teeth exposed"),
+ V("tracks a sequence with one round eye", "ticks its jaw between deliberate paired-fin pauses"),
+ V("nips in careful rows with tail held nearly still", "probes snout-first between short jaw closures"),
+ V("arches its belly as the tail base rises", "angles its vent downward while paired fins spread"),
+ V("faces backward through a tight tail-led pivot", "rolls half sideways as its fins oppose each other"),
+ V("shivers from gill covers through the forked tail", "stiffens its fin rays while its jaw vibrates"),
+ V("spirals unevenly with one paired fin folded", "jerks tail-first while the toothed mouth gapes"),
+ V("nips furtively then hides its jaw beneath a turn", "slides flankwise with paired fins shielding its mouth"),
+ V("darts in rigid bursts as gill covers flutter", "snaps repeatedly while its forked tail twists"),
+ V("hangs nearly still with fins tucked to scales", "slows its tail beats as the lower jaw settles"));
+
+ AddExtended(
+ voices,
+ "seal",
+ V("raises its whiskered muzzle through a chesty bark", "pulses its throat beneath a run of blunt honks"),
+ V("touches whiskers softly with foreflippers folded", "rests muzzle-close through matching head tilts"),
+ V("rakes backward with broad foreflippers", "presses its chest low through repeated muzzle nudges"),
+ V("sweeps whiskers through close side-to-side passes", "brushes with foreflipper edges while its muzzle dips"),
+ V("extends its whiskered muzzle then folds one flipper", "rises chest-high through a measured foreflipper pat"),
+ V("aims its whiskers before a quick jaw clamp", "holds its hind flippers straight before surging snout-first"),
+ V("drives its broad chest through foreflipper pulls", "hooks its teeth as hind flippers brace together"),
+ V("combs its whiskers with one curled foreflipper", "scratches its thick flank using pointed hind claws"),
+ V("slaps both foreflippers through heavy downward beats", "bucks its chest while hind flippers clap together"),
+ V("lurches forward with foreflippers reaching fast", "bunches its thick body through rapid chest-first surges"),
+ V("turns a full circle on alternating foreflippers", "presses its belly centrally with muzzle sweeping around"),
+ V("props its chest high above squared foreflippers", "bares pointed teeth while hind flippers stiffen"),
+ V("follows a sequence with whiskers twitching", "nods its rounded head between deliberate flipper taps"),
+ V("probes in rows with its whiskered muzzle", "scrapes lightly with one foreflipper before a tooth pinch"),
+ V("raises its hind flippers above an arched rump", "flexes its thick belly behind planted foreflippers"),
+ V("rolls sideways while its muzzle stays forward", "crosses foreflippers as hind flippers fan apart"),
+ V("quivers from whiskered muzzle through thick shoulders", "stiffens both foreflippers while its chest trembles"),
+ V("twists through a crooked roll with jaws ajar", "jerks its head between mismatched flipper sweeps"),
+ V("hunches over folded foreflippers and snaps sideways", "inches backward with whiskers tucked against its muzzle"),
+ V("lurches stiff-bodied as both flippers twitch", "bites at empty space while its thick torso rolls"),
+ V("curls with foreflippers pressed against its chest", "rests its whiskered muzzle atop one broad flipper"));
+
+ AddExtended(
+ voices,
+ "snake",
+ V("raises its head through a long pulsing hiss", "flicks its forked tongue between breathy scales of sound"),
+ V("rests its jaw across a parallel coil", "matches slow tongue flicks with necks intertwined"),
+ V("pushes its snout ahead while ribs ripple forward", "presses broad coils through repeated sideward bends"),
+ V("brushes its scaled flanks through close looping passes", "sweeps its forked tongue along a winding route"),
+ V("extends its head then loops its neck inward", "lifts one body coil through a measured tongue display"),
+ V("holds its forked tongue still before striking", "compresses its front coils beneath an aligned jaw"),
+ V("loops around and contracts in traveling bands", "braces its tail while rib waves pull forward"),
+ V("rubs its jaw along a smooth body coil", "scrapes between scales with a brief tail-tip stroke"),
+ V("lashes its tail as rib muscles bunch rapidly", "rears its neck and pounds down through stacked coils"),
+ V("streams forward in narrow bends with head lowered", "uncoils rapidly as its tail whips behind"),
+ V("traces a tight circle before stacking its coils", "presses its belly scales into a compact spiral"),
+ V("raises a third of its body above braced loops", "flares its neck while jaws part around curved teeth"),
+ V("tracks a sequence with forked tongue samples", "nods its narrow head between deliberate coil shifts"),
+ V("probes in rows with snout and tongue together", "rakes belly scales backward through short rippling passes"),
+ V("lifts its tail while the rear coils tighten", "arches its scaled body above a flattened belly section"),
+ V("loops backward while its head keeps facing ahead", "knots its middle briefly as tail and neck cross"),
+ V("shivers along every scale from jaw to tail tip", "stiffens into a curve while its ribs pulse rapidly"),
+ V("corkscrews through uneven coils with tongue extended", "jerks its neck sideways as the tail circles opposite"),
+ V("folds its head beneath an outer coil", "slides tail-first while its jaw remains hidden"),
+ V("rears in rigid bends as its tongue flicks erratically", "snaps at empty space while body loops twitch"),
+ V("settles its jaw atop a tightly wound coil", "draws head and tail inward as rib waves slow"));
+
+ AddExtended(
+ voices,
+ "turtle",
+ V("extends its neck through a throaty chirping phrase", "clicks its hard beak while throat folds pulse"),
+ V("touches shell rims through slow neck stretches", "rests beak-close with foreclaws folded inward"),
+ V("scrapes backward with alternating foreclaws", "bends its long neck through repeated beak dips"),
+ V("brushes its shell edge through low deliberate passes", "sweeps with clawed forefeet while its beak points down"),
+ V("extends its neck and opens its hard beak slowly", "raises one foreclaw through a measured shell-rock"),
+ V("holds its neck rigid before a sudden beak clip", "plants all four claws before thrusting shell and head"),
+ V("drives shell-first as foreclaws pull in sequence", "hooks its beak forward while hind claws keep pushing"),
+ V("scrapes its beak gently along one foreleg scale", "rubs beneath its shell rim with a hooked hind claw"),
+ V("pumps all four legs as its shell rocks sharply", "stamps foreclaws while neck and beak jab downward"),
+ V("plods rapidly with neck stretched straight ahead", "pulls its shell in hurried alternating claw strokes"),
+ V("walks a small circle before drawing its limbs close", "presses its shell centrally as neck sweeps around"),
+ V("stands high on straightened legs beneath its shell", "drives forward behind a hard open beak"),
+ V("follows a sequence with slow sideward head turns", "taps one foreclaw between deliberate beak-led nods"),
+ V("clips in careful rows with its hard beak", "rakes backward with foreclaws before each neck reach"),
+ V("lifts its tail while hind legs brace the shell", "raises the rear shell rim above bent forelegs"),
+ V("turns backward while its neck stays extended ahead", "crosses its forefeet as head and tail angle sideways"),
+ V("shudders beneath its shell from neck to hind claws", "stiffens all four legs while shell plates vibrate"),
+ V("rocks unevenly as its neck loops to one side", "jerks its beak between mismatched foreclaw steps"),
+ V("withdraws its head behind the shell rim and bites", "sidles with one foreclaw tucked beneath its shell"),
+ V("plods rigidly as neck and tail twitch together", "snaps at empty space while its shell rocks backward"),
+ V("draws head and limbs beneath the shell rim", "rests its chin inside the shell as claws uncurl"));
+ }
+}
diff --git a/IdleSpectator/ActivitySpeciesVoices.Animals.Specialized.cs b/IdleSpectator/ActivitySpeciesVoices.Animals.Specialized.cs
new file mode 100644
index 0000000..da3cc69
--- /dev/null
+++ b/IdleSpectator/ActivitySpeciesVoices.Animals.Specialized.cs
@@ -0,0 +1,119 @@
+using System.Collections.Generic;
+
+namespace IdleSpectator;
+
+public static partial class ActivitySpeciesVoiceCatalog
+{
+ private static void AddAnimalSpecializedVoices(Dictionary voices)
+ {
+ AddSpecialized(
+ voices,
+ "chicken",
+ V("fans a spark into flame with rapid wingbeats", "pecks a spark into flame beneath beating primaries"),
+ V("beats flame low beneath overlapping wings", "smothers flame under spread breast feathers"),
+ V("presses feathered flanks among gathering kin", "tucks wing-to-wing into a clustered flock"),
+ V("draws visible essence through its pulsing throat", "pulls observed life-glow along raised neck feathers"),
+ V("searches with one bright eye and quick beak tilts", "reaches ahead with neck stretched and beak parted"),
+ V("wails through a trembling comb and open beak", "keens in thin clucks as its throat quivers"),
+ V("clacks its beak through a harsh squawk", "lashes both wings beneath a rasping cackle"));
+
+ AddSpecialized(
+ voices,
+ "crab",
+ V("clicks a spark into flame between closing pincers", "fans a spark into flame with beating mouthparts"),
+ V("clamps flame low beneath its broad shell rim", "beats flame down with alternating flattened claws"),
+ V("locks jointed legs beside gathering kin", "fits shell-to-shell into a clustered cast"),
+ V("draws visible essence through pulsing mouthparts", "pulls observed life-glow between raised pincers"),
+ V("searches with swiveling eyestalks and parted claws", "reaches ahead with one open pincer"),
+ V("rasps through fluttering mouthparts and lowered eyestalks", "clatters both pincers beneath a quivering shell"),
+ V("snaps raised pincers in a jagged clatter", "grinds its mouthparts under a rigid shell"));
+
+ AddSpecialized(
+ voices,
+ "crocodile",
+ V("breathes a spark into flame through parted jaws", "fans a spark into flame with a plated tail sweep"),
+ V("presses flame low beneath its armored belly", "beats flame down with broad sweeps of its plated tail"),
+ V("settles flank-to-flank among gathering kin", "fits its plated body into a jaw-aligned congregation"),
+ V("draws visible essence through vibrating throat plates", "pulls observed life-glow between rows of exposed teeth"),
+ V("searches with ridged eyes above a slowly opening jaw", "reaches forward with its long snout and spread foreclaws"),
+ V("bellows through a heaving armored throat", "moans between slack jaws as its tail trembles"),
+ V("claps its jaws around a gravelly roar", "lashes its plated tail beneath a guttural bark"));
+
+ AddSpecialized(
+ voices,
+ "frog",
+ V("puffs a spark into flame from its swelling throat sac", "fans a spark into flame with rapid webbed kicks"),
+ V("presses flame low beneath its broad belly", "beats flame down with slapping webbed hind feet"),
+ V("folds splayed feet among gathering kin", "presses squat flanks into a croaking cluster"),
+ V("draws visible essence through its pulsing throat sac", "pulls observed life-glow along an unfurling tongue"),
+ V("searches with separately swiveling round eyes", "reaches ahead with a flicking tongue and spread forefeet"),
+ V("keens through a collapsed throat sac", "trills thinly as its webbed toes quiver"),
+ V("blasts a raw croak through its swollen throat", "slaps both forefeet beneath a rasping chirr"));
+
+ AddSpecialized(
+ voices,
+ "ostrich",
+ V("fans a spark into flame with broad wing plumes", "puffs a spark into flame through its long feathered throat"),
+ V("beats flame low beneath sweeping short wings", "presses flame down with broad two-toed feet"),
+ V("weaves its raised neck among gathering kin", "presses feathered flanks into a long-legged cluster"),
+ V("draws visible essence along its extended throat", "pulls observed life-glow through fanned breast plumes"),
+ V("searches with high-set eyes and low beak sweeps", "reaches ahead on a fully extended neck"),
+ V("booms through a sagging feathered throat", "keens with its broad beak agape and neck bowed"),
+ V("clacks its broad beak beneath a harsh boom", "lashes short wings around a guttural hiss"));
+
+ AddSpecialized(
+ voices,
+ "penguin",
+ V("fans a spark into flame with rigid flipper strokes", "puffs a spark into flame through its narrow raised beak"),
+ V("beats flame low beneath alternating stiff flippers", "presses flame down with its dense feathered belly"),
+ V("fits shoulder-to-shoulder among gathering kin", "presses its white breast into a compact huddle"),
+ V("draws visible essence through its pumping chest", "pulls observed life-glow along both rigid flippers"),
+ V("searches through sharp head tilts and beak dips", "reaches ahead with narrow beak and one flared flipper"),
+ V("brays through a bowed head and shaking chest", "keens softly with its beak tucked against white breast feathers"),
+ V("honks harshly through a thrust-up beak", "slaps both flippers beneath a grating bray"));
+
+ AddSpecialized(
+ voices,
+ "piranha",
+ V("fans a spark into flame with beating fin rays", "snaps a spark into flame between chattering teeth"),
+ V("beats flame low with a whipping forked tail", "presses flame down beneath its compact scaled flank"),
+ V("aligns fin-to-fin among gathering kin", "fits its scaled flank into a tight shoal"),
+ V("draws visible essence through pulsing gill covers", "pulls observed life-glow between its parted teeth"),
+ V("searches with round eyes and sweeping paired fins", "reaches ahead with blunt snout and open toothed jaw"),
+ V("chatters its teeth as both gill covers shudder", "rasps through pumping gills and folded fins"),
+ V("gnashes exposed teeth behind flared gill covers", "whips its forked tail beneath a jagged jaw rattle"));
+
+ AddSpecialized(
+ voices,
+ "seal",
+ V("fans a spark into flame with broad foreflippers", "puffs a spark into flame past its whiskered muzzle"),
+ V("beats flame low beneath alternating foreflippers", "presses flame down with its thick chest and folded flippers"),
+ V("presses thick flanks among gathering kin", "fits whiskered muzzle to shoulder in a clustered rookery"),
+ V("draws visible essence through its heaving chest", "pulls observed life-glow along trembling whiskers"),
+ V("searches with sweeping whiskers and lifted muzzle", "reaches ahead with one broad foreflipper"),
+ V("moans through a lowered whiskered muzzle", "keens as its thick chest and throat quiver"),
+ V("barks harshly behind bared pointed teeth", "slaps both foreflippers beneath a guttural roar"));
+
+ AddSpecialized(
+ voices,
+ "snake",
+ V("breathes a spark into flame past its forked tongue", "fans a spark into flame with rapid rib pulses"),
+ V("presses flame low beneath stacked muscular coils", "beats flame down with broad sweeps of its scaled body"),
+ V("threads its coils among gathering kin", "stacks parallel loops into a clustered knot"),
+ V("draws visible essence through flicking tongue tips", "pulls observed life-glow along rippling belly scales"),
+ V("searches with forked tongue and sideward jaw turns", "reaches ahead on a straightened neck coil"),
+ V("hisses through a lowered jaw and slack coils", "keens in thin breath as its tail tip quivers"),
+ V("spits a harsh hiss between exposed fangs", "lashes its tail beneath a rasping jaw gape"));
+
+ AddSpecialized(
+ voices,
+ "turtle",
+ V("puffs a spark into flame through its hard beak", "fans a spark into flame with alternating clawed forefeet"),
+ V("presses flame low beneath its broad shell", "beats flame down with sweeping clawed forefeet"),
+ V("fits shell rim to shell rim among gathering kin", "folds clawed feet into a close-shelled cluster"),
+ V("draws visible essence through pulsing throat folds", "pulls observed life-glow along its patterned shell plates"),
+ V("searches with slow head turns and beak dips", "reaches ahead on an extended wrinkled neck"),
+ V("keens through a lowered beak and trembling throat folds", "rasps softly as its foreclaws curl beneath the shell rim"),
+ V("clacks its hard beak through a throaty hiss", "stamps clawed forefeet beneath a grating chirr"));
+ }
+}
diff --git a/IdleSpectator/ActivitySpeciesVoices.Civs.Extended.cs b/IdleSpectator/ActivitySpeciesVoices.Civs.Extended.cs
new file mode 100644
index 0000000..3d3a0ad
--- /dev/null
+++ b/IdleSpectator/ActivitySpeciesVoices.Civs.Extended.cs
@@ -0,0 +1,883 @@
+using System.Collections.Generic;
+
+namespace IdleSpectator;
+
+public static partial class ActivitySpeciesVoiceCatalog
+{
+ private static void AddCivExtendedVoices(Dictionary voices)
+ {
+ AddExtended(voices, "civ_acid_gentleman",
+ V("sings in clipped upright phrases", "holds each note behind a formal posture"),
+ V("courts with measured bows", "mates without loosening a rigid stance"),
+ V("cultivates in ruler-straight passes", "squares both shoulders while cultivating"),
+ V("pollinates with precise fingertip touches", "visits each bloom in strict order"),
+ V("trades through exacting hand gestures", "bargains with chin held level"),
+ V("fishes from a square-footed stance", "fishes in straight ruler-like pulls"),
+ V("hauls with back severely straight", "bears the weight at matching angles"),
+ V("tends wounds with level steady hands", "treats wounds in measured hand passes"),
+ V("faces the flames with cuffs held clear", "handles fire with formal precision"),
+ V("retreats in controlled backward strides", "flees without breaking upright form"),
+ V("settles into equal-ranked formation", "joins the civic cluster at exact spacing"),
+ V("drills behind a rigid forearm guard", "patrols in sharply measured steps"),
+ V("reads with one finger marking each line", "studies with chin and shoulders held square"),
+ V("gathers kin into ordered ranks", "collects spoils in matching groups"),
+ V("relieves the body from a rigid squat", "straightens immediately after relieving itself"),
+ V("starts one duty at conflicting angles", "pauses stiffly over a mistaken sequence"),
+ V("recovers with spine still vertical", "recharges through counted intervals of stillness"),
+ V("obeys an odd impulse through formal gestures", "answers the compulsion in exact measures"),
+ V("pilfers with cuffed hands held level", "takes covertly behind a rigid bow"),
+ V("moves under possession in rigid counts", "executes unseen commands without bending"),
+ V("dreams with hands folded symmetrically", "sleeps through small ceremonial gestures"));
+
+ AddExtended(voices, "civ_alpaca",
+ V("hums through a wool-soft throat", "sings with chin lifted above the fleece"),
+ V("courts in springy side steps", "mates beneath a close woolly press"),
+ V("cultivates with light four-footed pacing", "tends planted growth beneath bobbing fleece"),
+ V("pollinates with a soft probing muzzle", "brushes blooms beneath forward ears"),
+ V("trades through soft nose-led greetings", "bargains with ears tipped forward"),
+ V("fishes with long legs planted wide", "leans woolly chest-first and fishes"),
+ V("hauls against a padded shoulder", "carries weight in a fleece-deep sway"),
+ V("nuzzles wounds with slow wool-framed lips", "tends wounds beneath a lowered woolly neck"),
+ V("steps around flames on nimble feet", "faces fire with fleece drawn back"),
+ V("bounds away on long springing legs", "flees with ears flattened into the wool"),
+ V("settles with all four feet neatly tucked", "forms a close fleece-lined civic cluster"),
+ V("drills in high-stepping charges", "guards with chest wool pushed forward"),
+ V("reads with muzzle hovering close", "studies while long ears track each pause"),
+ V("herds kin with low humming calls", "gathers spoils against thick chest wool"),
+ V("relieves itself with tail held clear", "squats lightly on folded hind legs"),
+ V("turns long ears toward the wrong duty", "stutters through uncertain four-footed steps"),
+ V("recharges with legs folded under fleece", "rests upright in a woolly bundle"),
+ V("follows a strange urge in sideways hops", "bobs sideways under an inexplicable compulsion"),
+ V("pilfers with soft lips and lifted chin", "sidles away beneath upright ears"),
+ V("bounds possessed in stiff-legged pulses", "fleece trembles through each compelled bound"),
+ V("dreams with ears twitching above the wool", "dozes through tiny long-legged kicks"));
+
+ AddExtended(voices, "civ_armadillo",
+ V("chitters beneath rattling back plates", "sings through a half-curled shell"),
+ V("courts by circling plated flank to flank", "mates beneath overlapping armor"),
+ V("cultivates with low digging claws", "tends planted growth beneath bobbing plates"),
+ V("pollinates with a narrow snuffling snout", "nudges blooms beneath a domed back"),
+ V("trades through brisk shell taps", "bargains from a guarded half-curl"),
+ V("fishes with foreclaws braced low", "snuffles between short claw-led pulls"),
+ V("hauls beneath a plated shoulder", "rolls weight against the curved shell"),
+ V("tends wounds with small digging claws", "uncurls one plate at a time and treats wounds"),
+ V("curls beside flames behind thick plates", "tests fire from beneath a shell rim"),
+ V("scuttles away under lowered armor", "flees in a tight plated roll"),
+ V("scrapes and curls into civic formation", "settles with shell backs facing outward"),
+ V("drills in armored rolling charges", "guards from a clawed half-curl"),
+ V("reads with snout nearly touching", "studies beneath a raised plate edge"),
+ V("gathers kin into a plated ring", "rolls spoils beneath the shell curve"),
+ V("relieves itself from a low squat", "uncurls the plated rear to relieve itself"),
+ V("circles the wrong duty in a puzzled half-roll", "scratches at the wrong step with small claws"),
+ V("recharges tightly sealed in armor", "rests while overlapping plates settle"),
+ V("scuttles after an odd inward tug", "rolls onward under a strange compulsion"),
+ V("pilfers with one small hooking claw", "curls away around the taking"),
+ V("rattles possessed inside a rigid shell", "rolls under unseen direction"),
+ V("dreams in a fully plated curl", "sleeps while tiny claws paddle beneath armor"));
+
+ AddExtended(voices, "civ_bear",
+ V("sings in broad chest-deep rumbles", "holds a note through a lifted muzzle"),
+ V("courts with heavy shoulder sways", "mates in a broad paw-braced embrace"),
+ V("cultivates with sweeping forepaws", "tends planted growth behind a broad muzzle"),
+ V("pollinates with a wide lowered snout", "brushes blooms between blunt claws"),
+ V("trades with booming paw-led emphasis", "bargains while looming on hind legs"),
+ V("fishes with paws poised to scoop", "fishes with broad chest leaning forward"),
+ V("hauls high against a massive chest", "bears weight between sweeping forearms"),
+ V("tends wounds with broad slow paws", "sniffs over wounds before treating them"),
+ V("rears beside flames with paws raised", "handles fire behind a thick forearm guard"),
+ V("lumbers away before breaking into bounds", "flees with heavy paws pounding"),
+ V("settles into a broad paw-marked formation", "joins the civic cluster with a heavy chest brace"),
+ V("drills through weighty upright blows", "patrols with rolling shoulders"),
+ V("reads between two broad paws", "studies with muzzle lowered over the lines"),
+ V("calls kin together with a low roar", "scoops spoils against the chest"),
+ V("relieves itself from a heavy haunch squat", "rises broad-backed after relieving itself"),
+ V("swipes uncertainly between opposing duties", "rears and sniffs at a mistaken duty"),
+ V("recharges curled around both forepaws", "rests in deep belly-driven breaths"),
+ V("lumbers after a baffling inner pull", "answers it through ponderous paw sweeps"),
+ V("pilfers in one broad scooping paw", "lumbers away behind broad shoulders"),
+ V("rears possessed with claws spread", "moves under command in crushing steps"),
+ V("dreams through deep muzzle-rumbling breaths", "sleeps while massive paws flex"));
+
+ AddExtended(voices, "civ_beetle",
+ V("sings in dry wing-case vibrations", "clicks a measured carapace chorus"),
+ V("courts with antennae tracing paired arcs", "mates beneath locked wing cases"),
+ V("cultivates in straight six-legged measures", "tends growth with clipping mouthparts"),
+ V("pollinates beneath sweeping antennae", "walks each bloom on hooked feet"),
+ V("trades through coded feeler taps", "bargains with polished wing cases raised"),
+ V("fishes from six evenly braced legs", "fishes in jointed six-leg pulses"),
+ V("hauls under a hard domed back", "drives weight with all six legs"),
+ V("examines wounds with circling feelers", "tends wounds between delicate forelegs"),
+ V("faces flame behind sealed wing cases", "tests fire with one extended antenna"),
+ V("skitters away in a six-legged burst", "flees with feelers folded against the shell"),
+ V("settles into a geometric carapace cluster", "locks into civic formation along straight traces"),
+ V("drills with horn and shell aligned", "patrols in clicking six-step measures"),
+ V("reads by tracking lines with antennae", "studies beneath a lowered horn"),
+ V("signals kin into an antenna-linked group", "pushes spoils beneath the wing case"),
+ V("relieves itself with hind legs spread", "locks the forelegs while relieving itself"),
+ V("turns both feelers between conflicting duties", "clicks through an uncertain leg pattern"),
+ V("recharges with every joint locked", "rests sealed beneath the hard wing case"),
+ V("skitters under a strange antenna-led impulse", "clicks through it in rigid segments"),
+ V("pilfers between quick clipping forelegs", "withdraws beneath closed cases"),
+ V("marches possessed on synchronized legs", "wing cases rattle through compelled steps"),
+ V("dreams with antennae drawing slow circles", "rests while folded legs twitch in sequence"));
+
+ AddExtended(voices, "civ_buffalo",
+ V("sings in horn-framed bellows", "rolls a note through a massive chest"),
+ V("courts with broad forehead presses", "mates on firmly planted hooves"),
+ V("cultivates in heavy hoof-timed passes", "keeps horns level while tending planted growth"),
+ V("pollinates with a broad brushing muzzle", "moves between blooms beneath curved horns"),
+ V("trades through solid brow-led gestures", "bargains without shifting planted hooves"),
+ V("fishes with horns angled aside", "fishes through massive shoulder pulls"),
+ V("hauls from a thick horn-set neck", "pulls weight through four grinding hooves"),
+ V("nudges wounds with a broad muzzle", "tends wounds while standing horn-outward"),
+ V("faces flames with horns lowered", "stamps around fire on heavy hooves"),
+ V("thunders away with tail held straight", "flees behind a rolling wall of shoulders"),
+ V("settles in a horn-outward civic ring", "joins the formation through deep hoof presses"),
+ V("drills in low repeated charges", "patrols with horns maintaining a broad front"),
+ V("reads with muzzle lowered between horns", "studies while one hoof holds position"),
+ V("bellows kin into a guarded circle", "pushes spoils together with the broad brow"),
+ V("relieves itself on widely planted hooves", "flicks the tail clear while relieving itself"),
+ V("paws between two mistaken directions", "swings the horned head over a confused duty"),
+ V("recharges standing on locked heavy legs", "rests with chin sunk into the chest"),
+ V("charges toward an inexplicable duty", "obeys a strange tug with horns forward"),
+ V("pilfers behind the curve of one horn", "backs away on guarded hooves"),
+ V("stamps possessed in a rigid cadence", "drives forward beneath unseen direction"),
+ V("dreams with nostrils pulsing under the horns", "dozes while thick hooves scrape softly"));
+
+ AddExtended(voices, "civ_candy_man",
+ V("sings in bright crackling trills", "rings a note through glossy layers"),
+ V("courts with striped spinning bows", "mates in a springy wrapped embrace"),
+ V("cultivates in glossy heel-to-toe turns", "crinkles both hands through planted growth"),
+ V("pollinates with quick lacquered fingertips", "twirls between blooms on pointed heels"),
+ V("trades through wide striped flourishes", "bargains with palms turned brightly outward"),
+ V("fishes in a balanced glossy crouch", "fishes with elastic arms snapping straight"),
+ V("hauls against a hardened bright shoulder", "bears weight on springing striped legs"),
+ V("tends wounds with light crinkling fingers", "bends glossy limbs incrementally and treats wounds"),
+ V("circles flames on quick polished heels", "faces fire with glossy hands fluttering"),
+ V("skips away in sharp zigzag bounds", "flees with striped limbs snapping straight"),
+ V("settles into a neatly wrapped civic cluster", "aligns glossy edges with the formation"),
+ V("drills in snapping spiral turns", "patrols on bright quick heels"),
+ V("reads with one shiny finger tracing", "studies while striped shoulders stay square"),
+ V("crackles a call to gather kin", "folds spoils against a glossy chest"),
+ V("relieves itself in a compact crinkled squat", "unbends glossy knees after relieving itself"),
+ V("twists between mismatched duty steps", "crinkles uncertainly over the wrong duty"),
+ V("recharges folded into a bright compact curl", "rests while glossy limbs regain their spring"),
+ V("springs after an inexplicable impulse", "twirls onward under the strange compulsion"),
+ V("pilfers with quick lacquered fingers", "skips away with striped arms tucked"),
+ V("jerks possessed on rigid glossy joints", "striped limbs spin through compelled turns"),
+ V("dreams with striped limbs softly uncurling", "sleeps through tiny wrapper-like crackles"));
+
+ AddExtended(voices, "civ_capybara",
+ V("sings in low blunt-muzzled pulses", "hums steadily through a rounded chest"),
+ V("courts with slow flank-to-flank nudges", "mates on broad evenly planted feet"),
+ V("cultivates at an unhurried four-footed pace", "tends growth with a steady blunt muzzle"),
+ V("pollinates with whiskered nose touches", "ambles bloom to bloom on broad feet"),
+ V("trades through repeated chin-led nods", "bargains without shifting its broad stance"),
+ V("fishes from a low balanced crouch", "fishes by cycling both small forepaws"),
+ V("hauls against a solid rounded shoulder", "moves weight in broad measured steps"),
+ V("nuzzles wounds with a blunt nose", "tends wounds from a low broad stance"),
+ V("sits solidly beside the flames", "handles fire with whiskers held back"),
+ V("ambles away before lengthening its stride", "flees low with broad feet drumming"),
+ V("settles into a close flank-sharing group", "joins the formation at a measured pace"),
+ V("drills through compact shoulder shoves", "patrols without breaking its even stride"),
+ V("reads with blunt chin held close", "studies while small ears remain still"),
+ V("gathers kin through low pulsing calls", "pushes spoils together with both forepaws"),
+ V("relieves itself on folded broad haunches", "rises at the same measured pace afterward"),
+ V("stares between duties with whiskers twitching", "ambles through an uncertain wrong turn"),
+ V("recharges in a compact low curl", "rests with blunt chin sunk to the chest"),
+ V("follows a strange urge at the same slow pace", "ambles through it on measured paws"),
+ V("pilfers beneath a low rounded chest", "ambles away without lifting its head"),
+ V("moves possessed in unnaturally even steps", "obeys unseen direction with a fixed muzzle"),
+ V("dreams with whiskers pulsing softly", "dozes while broad forefeet paddle once"));
+
+ AddExtended(voices, "civ_cat",
+ V("sings in narrow purring rises", "trills with tail curled high"),
+ V("courts through arched circling rubs", "closes the mating crouch with paws braced"),
+ V("cultivates in silent paw-timed passes", "tends growth with tail balancing each turn"),
+ V("pollinates with delicate whiskered sniffs", "steps among blooms on soft paws"),
+ V("trades through slow blinks and tail flicks", "bargains with whiskers angled forward"),
+ V("fishes from a motionless paw-raised crouch", "fishes with quick hooking claws"),
+ V("hauls low between clenched teeth", "draws weight backward on padded paws"),
+ V("licks around wounds with a rough tongue", "tends wounds through light paw-tip taps"),
+ V("watches flames through narrowed eyes", "pats toward fire then snaps the paw back"),
+ V("springs away with spine arched", "flees low with tail streaming straight"),
+ V("settles after three tail-led circles", "joins the civic cluster cheek and flank first"),
+ V("drills in silent pouncing bursts", "patrols with claws sheathed and tail level"),
+ V("reads with one paw held firmly down", "tracks each line through narrowed eyes"),
+ V("calls kin with a throaty chirrup", "draws spoils inward beneath both paws"),
+ V("relieves itself in a low hind-leg squat", "scrapes backward after relieving itself"),
+ V("stalks the wrong duty with puzzled whiskers", "switches duties after an abrupt tail twitch"),
+ V("recharges curled nose-to-tail", "rests through a deep chest purr"),
+ V("pounces toward a baffling private impulse", "obeys the odd urge with twitching tail"),
+ V("pilfers with silent hooked claws", "slips away on noiseless paws"),
+ V("arches possessed with pupils fixed", "pads under command in stiff silence"),
+ V("dreams with paws kneading the air", "sleeps while whiskers and tail tip twitch"));
+
+ AddExtended(voices, "civ_chicken",
+ V("sings in sharp beak-led bursts", "crows with neck feathers lifted"),
+ V("courts through wing-dropped circling steps", "mates in a brief flapping crouch"),
+ V("cultivates through quick claw scratches", "pecks planted growth in repeated beats"),
+ V("pollinates by brushing blooms with feathers", "pecks among blossoms on quick feet"),
+ V("trades through brisk clucks and head bobs", "bargains with one sideways eye fixed"),
+ V("fishes with beak held motionless", "fishes by pecking in abrupt bursts"),
+ V("hauls in short beak-gripped tugs", "drags weight with wings spread for balance"),
+ V("preens slowly around wounds", "tends wounds with measured beak taps"),
+ V("flaps around flames with feathers raised", "pecks toward fire between quick retreats"),
+ V("scurries away with wings beating", "flees in darting head-low steps"),
+ V("settles into a close feathered civic circle", "joins the cluster through quick scratching turns"),
+ V("drills with spurred hopping strikes", "patrols in stiff head-bobbing strides"),
+ V("reads with one eye turned to each line", "reads each line with head-bobbing pecks"),
+ V("clucks kin into a tight cluster", "scratches spoils into a beak-reached heap"),
+ V("relieves itself in a brief feathered squat", "flicks the tail after relieving itself"),
+ V("pecks at the wrong duty in confusion", "turns each eye toward a different duty"),
+ V("recharges with beak tucked under wing", "rests in a fluffed rounded crouch"),
+ V("scurries after an unexplained pecking urge", "obeys the urge with wings half spread"),
+ V("pilfers in one quick beak jab", "darts away on scratching feet"),
+ V("struts possessed in abrupt rigid beats", "wings flap through each compelled step"),
+ V("dreams with one wing twitching", "dozes through tiny claw scratches"));
+
+ AddExtended(voices, "civ_cow",
+ V("sings in long dewlap-shaking tones", "moans a broad muzzle-led melody"),
+ V("courts with slow flank-brushing circles", "mates on four firmly spread hooves"),
+ V("cultivates in steady cud-chewing passes", "tends growth beneath a swinging dewlap"),
+ V("pollinates with a broad damp muzzle", "walks among blooms with tail flicking"),
+ V("trades through low calls and horn tilts", "bargains from a repeated hipshot stance"),
+ V("fishes with muzzle lowered between horns", "fishes muzzle-low at a steady pace"),
+ V("hauls through a broad horn-set neck", "draws weight on evenly grinding hooves"),
+ V("tends wounds with a wide slow tongue", "treats wounds from a broadside stance"),
+ V("faces flames with broad nostrils pulsing", "steps around fire on evenly placed hooves"),
+ V("trots away with dewlap swinging", "flees behind a broad lowered head"),
+ V("settles into a shoulder-close civic herd", "joins the formation through steady hoof steps"),
+ V("drills in sweeping horn-led turns", "patrols with head low and hooves even"),
+ V("reads with muzzle close beneath the brow", "studies while chewing in slow cycles"),
+ V("calls kin together in mellow waves", "pushes spoils inward with a broad muzzle"),
+ V("relieves itself with tail held aside", "stands hipshot while relieving itself"),
+ V("chews through a long uncertain pause", "turns the broad head between mistaken duties"),
+ V("recharges on folded heavy legs", "rests with muzzle laid against one flank"),
+ V("plods after an inexplicable inward nudge", "chews steadily through the compelled duty"),
+ V("pilfers beneath a broad lowered muzzle", "backs away on quiet hooves"),
+ V("walks possessed with dewlap held rigid", "obeys unseen direction on locked legs"),
+ V("dreams through slow cyclical chewing", "dozes while the tail flicks once"));
+
+ AddExtended(voices, "civ_crab",
+ V("sings in alternating claw clacks", "bubbles a sideways shell-borne rhythm"),
+ V("courts through mirrored pincer waves", "mates beneath interlocking side-held claws"),
+ V("cultivates in lateral eight-legged sequences", "tends growth with paired cutting pincers"),
+ V("pollinates with delicate pincer brushes", "sidesteps from bloom to bloom"),
+ V("trades through exact shell-and-claw taps", "bargains with eyestalks held level"),
+ V("fishes with both pincers poised", "fishes through sideways claw tugs"),
+ V("hauls between paired locking claws", "sidesteps weight beneath a raised shell"),
+ V("tends wounds with fine pincer tips", "circles wounds on evenly moving jointed legs"),
+ V("faces flames behind a lifted shell edge", "tests fire with one extended claw"),
+ V("scuttles sideways in a rapid retreat", "flees with eyestalks folded low"),
+ V("settles into a shell-outward civic ring", "joins the circle with paired pincers raised"),
+ V("drills in hammering claw combinations", "patrols laterally with pincers raised"),
+ V("reads with eyestalks tracking separate lines", "studies between two balanced claws"),
+ V("clacks kin into a tight shell cluster", "snips spoils into a central grouping"),
+ V("relieves itself beneath a lowered rear shell", "plants all jointed legs while relieving itself"),
+ V("sidesteps between contradictory duties", "waves both claws over a confused duty"),
+ V("recharges sealed beneath shell and limbs", "rests with pincers folded to the mouth"),
+ V("scuttles after a strange sideways compulsion", "alternates both claws under compulsion"),
+ V("pilfers in one narrow pincer snip", "sidles away behind the raised claw"),
+ V("clacks possessed in exact harsh beats", "moves under command on rigid jointed legs"),
+ V("dreams with eyestalks slowly retracting", "sleeps while folded pincers click once"));
+
+ AddExtended(voices, "civ_crocodile",
+ V("sings in deep jaw-parted rumbles", "rolls a note along a plated throat"),
+ V("courts through low tail-sweeping circles", "mates in a heavy splay-legged press"),
+ V("cultivates belly-low on clawed feet", "tends growth with plated back held flat"),
+ V("pollinates with the long snout lowered", "brushes blooms beneath still nostrils"),
+ V("trades through slow jaw and tail signals", "bargains without lifting the armored belly"),
+ V("fishes with jaws held motionless", "fishes with one sudden jaw snap"),
+ V("hauls backward in a low jaw-locked drag", "pulls weight with tail and splayed legs"),
+ V("nudges wounds with the closed snout", "tends wounds between slow claw-tip taps"),
+ V("lies plated and still beside flames", "tests fire with jaws slightly open"),
+ V("bursts away from a motionless crouch", "flees low with armored tail whipping"),
+ V("settles into a low civic wall of plated backs", "joins formation on firmly splayed feet"),
+ V("drills in jaw-led lunges and tail sweeps", "patrols belly-low behind armored ridges"),
+ V("reads with one eye fixed on each line", "studies between motionless open jaws"),
+ V("rumbles kin into a plated gathering", "sweeps spoils together with the heavy tail"),
+ V("relieves itself on braced splayed legs", "raises the plated rear while relieving itself"),
+ V("snaps between mismatched duty directions", "lies still over a confused duty"),
+ V("recharges flat beneath settled back plates", "rests with jaws open and eyes narrowed"),
+ V("slides toward an inexplicable compulsion", "answers it with plated belly held low"),
+ V("pilfers with one swift closing jaw", "slides away behind a sweeping tail"),
+ V("lunges possessed from complete stillness", "rigid jaws drive each compelled lunge"),
+ V("dreams with the plated tail slowly flexing", "sleeps while one eye opens briefly"));
+
+ AddExtended(voices, "civ_dog",
+ V("sings in muzzle-lifted howling phrases", "barks a tail-beating civic rhythm"),
+ V("courts through quick circling sniffs", "mates on braced hind legs"),
+ V("cultivates in nose-led bounding passes", "tends planted growth in brisk pawing bursts"),
+ V("pollinates with a soft searching nose", "bounds among blooms with ears forward"),
+ V("trades through paw taps and quick barks", "bargains with tail sweeping behind"),
+ V("fishes with one paw held poised", "fishes through sharp single-paw snaps"),
+ V("hauls in a firm jaw-held pull", "draws weight at a quick trot"),
+ V("licks wounds in repeated tongue strokes", "tends wounds with ears trained close"),
+ V("barks at flames from a paw-wide stance", "circles fire with nostrils pulsing"),
+ V("bounds away with ears streaming", "flees low as the tail draws tight"),
+ V("settles after repeated tail-led circling", "joins a close muzzle-facing civic cluster"),
+ V("drills in shoulder-first rushing tackles", "patrols nose-first with ears alert"),
+ V("reads with muzzle resting near the lines", "studies while one forepaw taps"),
+ V("calls kin together with repeated barks", "gathers spoils beneath both forepaws"),
+ V("relieves itself with one hind leg raised", "sniffs twice before relieving itself"),
+ V("paces between duties with ears askew", "sniffs at an obviously mistaken duty"),
+ V("recharges curled around twitching paws", "rests through long open-mouthed breaths"),
+ V("bounds after a baffling urge", "answers it with tail beating in bursts"),
+ V("pilfers between quick closing jaws", "trots away with ears flattened"),
+ V("stalks possessed on stiffened paws", "obeys unseen direction without sniffing"),
+ V("dreams with forepaws running in place", "sleeps through muffled muzzle twitches"));
+
+ AddExtended(voices, "civ_fox",
+ V("sings in quick narrow muzzle-notes", "barks a tail-curled rising refrain"),
+ V("courts through crossing tail-led circles", "mates in a light black-pawed crouch"),
+ V("cultivates through angled silent passes", "tends growth with quick crossing paw strokes"),
+ V("pollinates with a narrow whiskered muzzle", "threads between blooms on black paws"),
+ V("trades through oblique bows and ear tilts", "bargains with tail masking the paws"),
+ V("fishes from a poised tail-balanced crouch", "fishes with one hooking black paw"),
+ V("hauls by backing on quiet black feet", "draws weight beneath a level sweeping tail"),
+ V("licks wounds with a narrow moving tongue", "tends wounds with narrow paw-tip touches"),
+ V("circles flames in angled crossing steps", "tests fire with whiskers held sideways"),
+ V("darts away through crossing turns", "flees with brush held straight behind"),
+ V("settles into an offset civic formation", "joins it through angled body circuits"),
+ V("drills in feinting black-pawed rushes", "patrols by crossing its own earlier line"),
+ V("reads with the brush wrapped around its feet", "tracks each line through bright narrowed eyes"),
+ V("calls kin with clipped rising barks", "sweeps spoils inward beneath the long brush"),
+ V("relieves itself in a light hind-leg crouch", "flicks the brush aside while relieving itself"),
+ V("tilts both ears over conflicting duties", "circles a mistaken duty with puzzled whiskers"),
+ V("recharges nose-deep in the sweeping tail", "rests in a narrow black-pawed curl"),
+ V("slips after a peculiar inward whisper", "follows it on tiptoe black paws"),
+ V("pilfers with nimble narrow teeth", "weaves away behind the broad brush"),
+ V("paces possessed in unnaturally straight lines", "obeys unseen direction with tail rigid"),
+ V("dreams with brush and black paws twitching", "sleeps through tiny muzzle-led feints"));
+
+ AddExtended(voices, "civ_frog",
+ V("sings through a round pulsing throat", "croaks a springy civic refrain"),
+ V("courts with throat-puffed hopping displays", "folds long legs into the mating crouch"),
+ V("cultivates in compact repeated leaps", "handles planted growth between broad splayed hands"),
+ V("pollinates with quick tongue-tip touches", "springs bloom to bloom on folded legs"),
+ V("trades through rhythmic croaks and blinks", "bargains from a deep squat"),
+ V("fishes with tongue poised and eyes wide", "fishes in long tongue-led leaps"),
+ V("hauls in short two-handed hops", "drags weight with long hind legs braced"),
+ V("tends wounds with broad damp hands", "leans round-eyed while treating wounds"),
+ V("squats beside flames with throat pulsing", "springs around fire on tucked legs"),
+ V("bounds away in long rapid arcs", "flees with throat flat and eyes wide"),
+ V("settles into a close croaking cluster", "joins the formation through repeated short hops"),
+ V("drills in double-footed kicking leaps", "patrols by springing between low crouches"),
+ V("reads with both round eyes lowered", "tracks the lines with one broad fingertip"),
+ V("croaks kin into a facing circle", "gathers spoils between splayed hands"),
+ V("relieves itself in a deep compact squat", "unfolds long legs after relieving itself"),
+ V("hops between contradictory duty cues", "blinks broadly over the wrong duty"),
+ V("recharges folded into a tiny crouch", "rests while the round throat slows"),
+ V("springs toward an unexplained urge", "answers it in throat-pulsing hops"),
+ V("pilfers in a quick two-handed flick", "bounds away with eyes forward"),
+ V("leaps possessed in fixed repeating arcs", "the throat croaks through compelled leaps"),
+ V("dreams with long hind feet twitching", "dozes while the throat pulses silently"));
+
+ AddExtended(voices, "civ_garlic_man",
+ V("sings through rustling layered breaths", "crackles a papery civic tune"),
+ V("courts by unfurling outer layers", "bundles knobby limbs during mating"),
+ V("cultivates with alternating layered hands", "tends planted growth on knobby bobbing feet"),
+ V("pollinates with soft papery brushes", "rustles between blooms in layered turns"),
+ V("trades through peeling hand flourishes", "bargains with bundled layers drawn tight"),
+ V("fishes with knobby feet firmly planted", "fishes by rustling both layered arms"),
+ V("hauls against a densely layered shoulder", "bears weight on knotted feet"),
+ V("wraps wounds in overlapping outer layers", "tends wounds with knobby fingertips"),
+ V("draws papery layers back from flames", "circles fire with dry arms held wide"),
+ V("rolls away in a rustling rush", "flees with loose layers streaming"),
+ V("settles into a tightly layered civic cluster", "bundles into formation along concentric lines"),
+ V("drills in knotted head-first rushes", "patrols with papery arms spread"),
+ V("reads while smoothing each rustling layer", "studies with one knobby finger tracing"),
+ V("rustles kin into a layered cluster", "bundles spoils between both dry arms"),
+ V("relieves itself from a knobby-footed squat", "gathers loose layers after relieving itself"),
+ V("peels back layers over a mistaken duty", "bobs uncertainly between duties"),
+ V("recharges folded inside dry outer layers", "rests while papery edges settle"),
+ V("rustles after an inexplicable impulse", "unfolds through the duty layer by layer"),
+ V("pilfers behind loose overlapping layers", "rolls away on knobby feet"),
+ V("bobs possessed beneath rigid dry layers", "bundled arms jerk under compulsion"),
+ V("dreams as papery layers softly shift", "sleeps with knobby feet tucked inward"));
+
+ AddExtended(voices, "civ_goat",
+ V("sings in sharp horn-framed bleats", "trills with chin lifted above the beard"),
+ V("courts through high springing head tosses", "mates on nimble split hooves"),
+ V("cultivates in quick hoof-timed passes", "tends growth with browsing lips"),
+ V("pollinates with a nimble probing muzzle", "clatters among blooms on split hooves"),
+ V("trades through repeated horn tilts", "bargains from a high braced stance"),
+ V("fishes with beard hanging over the stance", "fishes from four nimble split hooves"),
+ V("hauls through a low horn-set neck", "draws weight with split hooves gripping"),
+ V("nuzzles wounds beneath curled horns", "tends wounds with slow browsing lips"),
+ V("bounds around flames with beard held clear", "faces fire behind lowered curled horns"),
+ V("scrambles away in high uneven leaps", "flees on clattering split hooves"),
+ V("settles into a high-standing horned cluster", "joins the formation with brisk hoof stamps"),
+ V("drills in sudden brow-first charges", "patrols with curled horns tipped forward"),
+ V("reads with beard brushing close", "studies while one ear cocks sideways"),
+ V("bleats kin into a head-to-head group", "nudges spoils together beneath the horns"),
+ V("relieves itself on flexed hind legs", "holds the short tail clear while relieving itself"),
+ V("nibbles at the wrong duty in confusion", "tilts horns between opposing duties"),
+ V("recharges kneeling on tucked split hooves", "rests with beard against the chest"),
+ V("leaps toward an inexplicable urge", "answers it on firmly split hooves"),
+ V("pilfers with agile browsing lips", "bounds away behind raised horns"),
+ V("charges possessed in repeated straight lines", "clatters under unseen direction"),
+ V("dreams with beard and hooves twitching", "dozes through tiny horn-led head tosses"));
+
+ AddExtended(voices, "civ_hyena",
+ V("sings in rising broken whoops", "cackles a slope-backed refrain"),
+ V("courts through looping shoulder-low runs", "mates on broad jaw-braced haunches"),
+ V("cultivates in sloping side-to-side passes", "tends growth with heavy jaws flexing close"),
+ V("pollinates with a broad sniffing muzzle", "loops among blooms on uneven shoulders"),
+ V("trades through cackling jaw displays", "bargains with sloped back held low"),
+ V("fishes from a crooked shoulder-heavy stance", "fishes with broad jaws snapping sideways"),
+ V("hauls in a crushing jaw grip", "draws weight with hindquarters driving"),
+ V("licks wounds between low pulsing whoops", "tends wounds with broad muzzle lowered"),
+ V("paces around flames with jaws parted", "faces fire from a low sloping crouch"),
+ V("lopes away in widening loops", "flees with shoulders low and jaws shut"),
+ V("settles into a shoulder-close laughing clan", "circles the civic group before lying low"),
+ V("drills through harrying jaw-first passes", "patrols in broad looping circuits"),
+ V("reads with jaws slightly parted", "studies while sloped shoulders rock"),
+ V("whoops kin into a close flank group", "crushes spoils into manageable groupings"),
+ V("relieves itself from crooked lowered haunches", "sniffs around after relieving itself"),
+ V("loops between duties with puzzled jaws open", "cackles once at a mistaken duty"),
+ V("recharges in a loose slope-backed sprawl", "rests with chin between heavy forepaws"),
+ V("lopes after a strange private compulsion", "answers it in slope-backed widening circles"),
+ V("pilfers inside heavy closing jaws", "veers away on crooked strides"),
+ V("cackles possessed without opening its jaws", "runs under command in rigid loops"),
+ V("dreams through broken throat-whoops", "sleeps while heavy jaws flex silently"));
+
+ AddExtended(voices, "civ_lemon_man",
+ V("sings in sharp rind-bright squeaks", "fizzes through a pointed-crown refrain"),
+ V("courts with springy rolling pivots", "presses rounded limbs together during mating"),
+ V("cultivates in bouncing segmented passes", "tends growth with rounded feet and quick palms"),
+ V("pollinates with pointed fingertip touches", "rolls between blooms before popping upright"),
+ V("trades through brisk rind-polishing gestures", "bargains with pointed crown held high"),
+ V("fishes from a springy rounded crouch", "fishes with quick puckered mouth pulses"),
+ V("hauls against the firm curved rind", "rolls weight on rounded feet"),
+ V("tends wounds with quick alternating palms", "leans the pointed crown away and treats wounds"),
+ V("pivots around flames with rind held back", "faces fire on bouncing rounded feet"),
+ V("rolls away before springing upright", "flees with pointed crown angled forward"),
+ V("settles into a neatly segmented civic cluster", "joins formation through rounded divisions"),
+ V("drills in rolling pointed-crown charges", "patrols with quick springing pivots"),
+ V("reads with mouth held in a pucker", "traces lines beneath the pointed crown"),
+ V("squeaks kin into a rounded cluster", "presses spoils together with both palms"),
+ V("relieves itself in a tight rounded squat", "straightens the pointed crown after relieving itself"),
+ V("rolls between mismatched duty segments", "puckers over an obviously mistaken duty"),
+ V("recharges curled against the firm rind", "rests with rounded feet tucked close"),
+ V("bounces after an inexplicable impulse", "answers it through pointed-crown rolling starts"),
+ V("pilfers with a quick rounded pivot", "rolls away beneath the pointed crown"),
+ V("jerks possessed on spring-locked limbs", "the pointed crown spins through compelled turns"),
+ V("dreams with rounded feet softly bouncing", "sleeps while the pointed crown tilts"));
+
+ AddExtended(voices, "civ_liliar",
+ V("sings in layered silvery trills", "chimes through unfurled throat-frills"),
+ V("courts through slow frill-unfolding bows", "mates in a slender layered embrace"),
+ V("cultivates with long interweaving hands", "tends planted growth beneath drifting frills"),
+ V("pollinates with delicate leaf-edge brushes", "glides bloom to bloom on slender steps"),
+ V("trades through broad many-layered gestures", "bargains with long fingers interlaced"),
+ V("fishes from a stem-straight stance", "fishes through supple long-armed arcs"),
+ V("hauls with layered arms braided together", "bears weight along a supple upright frame"),
+ V("wraps wounds in overlapping soft frills", "tends wounds with long leaflike fingers"),
+ V("unfurls around flames at a measured distance", "faces fire with layered edges drawn inward"),
+ V("glides away with frills streaming", "flees in long supple sweeping steps"),
+ V("settles into a facing circle of layered forms", "weaves the civic group into interlocking bands"),
+ V("drills in supple stem-led turns", "patrols with sharpened frills held outward"),
+ V("reads with one long finger following lines", "studies behind folded layered hands"),
+ V("chimes kin into a layered ring", "braids spoils together between slender arms"),
+ V("relieves itself in a folded upright crouch", "closes lower frills while relieving itself"),
+ V("unfurls toward two conflicting duties", "tilts layered hands over a confused duty"),
+ V("recharges enclosed by overlapping frills", "rests upright with slender hands joined"),
+ V("glides after an unaccountable inner pull", "unfurls through it in supple arcs"),
+ V("pilfers behind overlapping layered frills", "sweeps away on silent slender steps"),
+ V("unfurls possessed in severe symmetry", "rigid frills repeat the compelled pattern"),
+ V("dreams while layered edges slowly open", "sleeps as long fingers weave delicate patterns"));
+
+ AddExtended(voices, "civ_monkey",
+ V("sings in rapid chest-patting chatter", "howls a long-armed civic refrain"),
+ V("courts through tail-curled swinging displays", "grapples long limbs and tail during mating"),
+ V("cultivates with hands, feet, and tail alternating", "crouches nimbly while tending growth"),
+ V("pollinates with quick fingertip inspections", "swings among blooms with tail curled"),
+ V("trades through animated many-handed gestures", "bargains while hanging from the tail"),
+ V("fishes with one hand poised below the other", "fishes from a long-armed squat"),
+ V("hauls with tail and both hands braced", "bears weight across long swinging arms"),
+ V("grooms wounds with nimble fingertips", "tends wounds through long-fingered grooming"),
+ V("circles flames on hands and feet", "reaches toward fire then recoils up the arms"),
+ V("scrambles away on all four limbs", "flees with tail streaming behind"),
+ V("settles into a close grooming civic troop", "joins the troop through swinging circuits"),
+ V("drills in long-armed grappling turns", "patrols above and below on nimble limbs"),
+ V("reads while tracing with fingers and toes", "studies with tail curled around the stance"),
+ V("chatters kin into a hand-linked cluster", "gathers spoils with hands, feet, and tail"),
+ V("relieves itself from a low long-armed squat", "raises the curling tail while relieving itself"),
+ V("scratches its head between conflicting duties", "swings toward an obviously mistaken duty"),
+ V("recharges curled inside long arms and tail", "rests with both hands beneath the head"),
+ V("scrambles after a peculiar sudden urge", "answers it while hanging tail-first"),
+ V("pilfers with quick curling fingers", "swings away with tail wrapped tight"),
+ V("clambers possessed in repetitive limb patterns", "teeth chatter through compelled climbing"),
+ V("dreams with hands grasping empty air", "sleeps while tail and toes curl"));
+
+ AddExtended(voices, "civ_penguin",
+ V("sings in upright bill-led honks", "warbles while both flippers beat time"),
+ V("courts through formal flipper-spread bows", "huddles upright with flippers during mating"),
+ V("cultivates in waddling parallel passes", "tends growth with bill and flipper taps"),
+ V("pollinates with repeated narrow-bill touches", "waddles among blooms with flippers out"),
+ V("trades through stiff bows and bill clicks", "bargains while rocking heel to heel"),
+ V("fishes with narrow bill held poised", "fishes through belly-first lunges"),
+ V("hauls by sliding on the rounded belly", "pushes weight with both broad flippers"),
+ V("preens wounds with measured bill touches", "tends wounds through soft flipper presses"),
+ V("rocks beside flames with flippers shielding", "faces fire from a close upright stance"),
+ V("slides away on the rounded belly", "flees in short rapid waddles"),
+ V("settles into a shoulder-locked civic huddle", "joins the group with bill facing inward"),
+ V("drills in stiff bill-and-flipper jabs", "patrols with flippers spread for balance"),
+ V("reads with the narrow bill tracking lines", "studies while rocking on flat heels"),
+ V("honks kin into a packed huddle", "slides spoils inward between flippers"),
+ V("relieves itself from a brief upright squat", "lifts the short tail while relieving itself"),
+ V("waddles between mismatched duties", "tilts the bill over a confused duty"),
+ V("recharges with bill tucked under flipper", "rests upright inside the huddle"),
+ V("slides toward an inexplicable urge", "answers it with both flippers stiff"),
+ V("pilfers between narrow bill and chest", "waddles away behind spread flippers"),
+ V("marches possessed without its usual waddle", "the narrow bill honks through rigid steps"),
+ V("dreams with flippers paddling softly", "dozes while the narrow bill twitches"));
+
+ AddExtended(voices, "civ_piranha",
+ V("sings in sharp jaw-clicking pulses", "vibrates a fin-beaten civic refrain"),
+ V("courts through tight synchronized fin loops", "spirals through mating with synchronized tail flicks"),
+ V("cultivates in darting fin-led passes", "tends growth with quick shearing mouthparts"),
+ V("pollinates in level fin-guided passes", "darts among blooms without snapping"),
+ V("trades through flashing jaw-and-fin signals", "bargains in a tightly held hover"),
+ V("fishes in sudden fin-led lunges", "fishes with jaws poised between tail flicks"),
+ V("hauls by driving with tail and fins", "bears weight against a compact scaled flank"),
+ V("tends wounds with closed mouthparts", "hovers level while fins guide each touch"),
+ V("circles flames in quick snapping turns", "faces fire with fins making tiny corrections"),
+ V("darts away in a flashing straight burst", "flees with fins clamped close"),
+ V("settles into a tight fin-aligned civic school", "joins the school through circling ranks"),
+ V("drills in repeated jaw-first rushes", "patrols through coordinated fin turns"),
+ V("reads while hovering rigidly level", "tracks lines with quick eye and fin shifts"),
+ V("clicks kin into a close-moving school", "herds spoils together with snapping turns"),
+ V("relieves itself during a brief tail-held hover", "flicks away after relieving itself"),
+ V("circles between contradictory duty signals", "snaps once at a mistaken duty"),
+ V("recharges nearly motionless on tucked fins", "rests with only the tail tip correcting"),
+ V("darts after an inexplicable compulsion", "answers it in jaw-clicking loops"),
+ V("pilfers inside flashing shearing teeth", "veers away behind beating fins"),
+ V("darts possessed in rigid repeated circuits", "clicks jaws under unseen direction"),
+ V("dreams with fins making tiny corrections", "rests while the tail flicks in bursts"));
+
+ AddExtended(voices, "civ_rabbit",
+ V("sings in soft nose-trembling trills", "pipes a long-eared civic refrain"),
+ V("courts through high twisting leaps", "mates in a compact hind-leg crouch"),
+ V("cultivates in quick paired-foot passes", "tends growth with nimble forepaws"),
+ V("pollinates with twitching nose brushes", "bounds among blooms beneath upright ears"),
+ V("trades through ear tilts and paw taps", "bargains while sitting tall on haunches"),
+ V("fishes with forepaws held close together", "fishes with long ears laid backward"),
+ V("hauls in short double-footed bounds", "bears weight against a compact chest"),
+ V("nuzzles wounds with a trembling nose", "tends wounds between soft forepaws"),
+ V("hops around flames with ears flattened", "faces fire from a spring-loaded crouch"),
+ V("zigzags away in rapid paired bounds", "flees with long ears streaming backward"),
+ V("settles into a close ear-alert formation", "joins the group with quick forepaw taps"),
+ V("drills in alternating paw-boxing bursts", "patrols through sharp zigzag leaps"),
+ V("reads with ears rotating above the lines", "studies between two lifted forepaws"),
+ V("thumps kin into a compact gathering", "draws spoils close with quick paw sweeps"),
+ V("relieves itself on folded springy haunches", "raises the small tail while relieving itself"),
+ V("turns each long ear toward a different duty", "hops once toward the mistaken duty"),
+ V("recharges folded into a tight crouch", "rests with ears laid over the shoulders"),
+ V("bounds after an unexplained twitching urge", "answers it in ear-streaming hops"),
+ V("pilfers between two cupped forepaws", "zigzags away with ears low"),
+ V("boxes possessed at empty space", "leaps under command in rigid doubles"),
+ V("dreams with hind feet kicking softly", "dozes while long ears rotate"));
+
+ AddExtended(voices, "civ_rat",
+ V("sings in high whisker-twitching squeaks", "pipes a quick tail-curled civic refrain"),
+ V("courts through close nose-led circles", "mates in a low nimble crouch"),
+ V("cultivates in narrow whisker-guided turns", "tends growth with tiny gripping paws"),
+ V("pollinates with rapid whiskered sniffs", "scurries among blooms on quick toes"),
+ V("trades through paw rubbing and low squeaks", "bargains with whiskers pitched forward"),
+ V("fishes with both small paws poised", "fishes from a tail-balanced squat"),
+ V("hauls backward in a firm tooth-grip", "draws weight with the long tail balancing"),
+ V("grooms wounds between tiny moving paws", "tends wounds through alternating paw presses"),
+ V("sniffs around flames with whiskers recoiling", "faces fire from a low paw-ready crouch"),
+ V("scurries away through narrow turns", "flees with tail drawn straight"),
+ V("settles into a whisker-touching civic cluster", "joins the group through tight scurrying runs"),
+ V("drills in low darting bites", "patrols nose-first along every edge"),
+ V("reads with one paw tracking the line", "studies while whiskers sweep side to side"),
+ V("squeaks kin into a tail-linked cluster", "sorts spoils rapidly between both paws"),
+ V("relieves itself from a low tail-lifted squat", "combs whiskers after relieving itself"),
+ V("scurries between mismatched duties", "rubs both paws over a confused duty"),
+ V("recharges curled tightly around the tail", "rests with whiskers tucked to the chest"),
+ V("follows an odd nose-led compulsion", "scurries through it in whisker-led bursts"),
+ V("pilfers beneath the chest in small paws", "scurries away with whiskers flat"),
+ V("moves possessed in sharp repeated darts", "squeaks beneath unseen direction"),
+ V("dreams with paws sorting empty air", "sleeps while whiskers and tail twitch"));
+
+ AddExtended(voices, "civ_rhino",
+ V("sings in rough horn-backed bellows", "rumbles a thick-chested civic note"),
+ V("courts through heavy horn-side head sweeps", "mates on four massively planted feet"),
+ V("cultivates in deep hoof-timed passes", "tends growth beneath a lowered horn"),
+ V("pollinates with the broad lower lip", "walks between blooms behind an angled horn"),
+ V("trades through blunt horn-and-ear gestures", "bargains from an immovable stance"),
+ V("fishes with the horn angled aside", "fishes through thick shoulder thrusts"),
+ V("hauls behind a massive pushing brow", "drives weight on pounding broad feet"),
+ V("nudges wounds with the broad lower lip", "tends wounds while standing hide-outward"),
+ V("faces flames behind a lowered horn", "stamps around fire in heavy arcs"),
+ V("thunders away with horn held level", "flees on pounding thick legs"),
+ V("settles into a hide-and-horn civic barrier", "joins the formation through massive hoof presses"),
+ V("drills in direct horn-led charges", "patrols with thick hide facing outward"),
+ V("reads with small eyes close to the lines", "studies beneath the shadow of the horn"),
+ V("bellows kin into a heavy defensive ring", "pushes spoils together with the broad snout"),
+ V("relieves itself on widely braced thick legs", "raises the short tail while relieving itself"),
+ V("swings the horn between conflicting duties", "stamps over an obviously mistaken duty"),
+ V("recharges in a massive folded crouch", "rests with thick chin against the chest"),
+ V("charges after an inexplicable inner pull", "answers it with the heavy horn lowered"),
+ V("pilfers behind the lowered heavy horn", "backs away on heavy guarded feet"),
+ V("stomps possessed in an unbroken straight line", "obeys unseen direction without turning"),
+ V("dreams with broad feet grinding softly", "dozes while the heavy horn tilts"));
+
+ AddExtended(voices, "civ_scorpion",
+ V("sings in dry pincer-clicking measures", "rasps a tail-arched civic refrain"),
+ V("courts through mirrored claw and tail waves", "mates beneath crossed and lifted stingers"),
+ V("cultivates in eight-legged segmented passes", "tends growth between paired pincers"),
+ V("pollinates with delicate claw-tip touches", "skitters among blooms beneath a curled tail"),
+ V("trades through exact pincer signals", "bargains with stinger held ceremonially high"),
+ V("fishes with paired claws poised", "fishes beneath a balancing arched tail"),
+ V("hauls between locking heavy pincers", "draws weight on eight gripping feet"),
+ V("tends wounds with fine claw tips", "keeps the stinger clear and treats wounds"),
+ V("faces flames behind raised pincers", "tests fire beneath a tightly curled tail"),
+ V("skitters away with stinger flattened", "flees on eight rapid jointed feet"),
+ V("settles into a claw-outward civic circle", "aligns tail arches across the formation"),
+ V("drills in pincer grabs and stinger feints", "patrols with eight feet keeping cadence"),
+ V("reads with both claws held level", "studies beneath a motionless stinger"),
+ V("clicks kin into a pincer-linked group", "draws spoils inward with paired claws"),
+ V("relieves itself on spread rear legs", "lifts the arched tail while relieving itself"),
+ V("turns pincers toward conflicting duties", "trembles the stinger over a confused duty"),
+ V("recharges with limbs folded under armor", "rests beneath the tail's tight curve"),
+ V("skitters after a strange claw-led impulse", "answers it beneath a poised stinger"),
+ V("pilfers between tightly clasped pincers", "backs away beneath the raised tail"),
+ V("marches possessed on rigid synchronized legs", "strikes empty air under unseen command"),
+ V("dreams with pincers clicking softly", "sleeps while the curled tail tightens"));
+
+ AddExtended(voices, "civ_seal",
+ V("sings in bouncing whiskered barks", "honks a broad-flippered civic tune"),
+ V("courts through rolling flipper claps", "presses belly-down with flippers during mating"),
+ V("cultivates in low galumphing passes", "tends growth with broad flipper sweeps"),
+ V("pollinates with soft whiskered nose touches", "flops among blooms on broad flippers"),
+ V("trades through claps and whisker-led nods", "bargains while balanced upright"),
+ V("fishes with whiskers pitched forward", "fishes through sleek rolling body turns"),
+ V("hauls by sliding on the broad belly", "pushes weight with paired flippers"),
+ V("nuzzles wounds with a whiskered muzzle", "tends wounds using soft flipper presses"),
+ V("claps around flames from a low position", "faces fire with whiskers drawn back"),
+ V("galumphs away in rolling lunges", "flees belly-low on beating flippers"),
+ V("settles into a close whisker-touching cohort", "joins the cohort with broad flipper strokes"),
+ V("drills in rolling body-first charges", "patrols with alternating flipper strokes"),
+ V("reads propped upright on the belly", "tracks lines with whiskers almost touching"),
+ V("barks kin into a flipper-close gathering", "sweeps spoils inward across the belly"),
+ V("relieves itself from a low tail-lifted crouch", "claps once after relieving itself"),
+ V("rolls between duties with whiskers askew", "flops toward an obviously mistaken duty"),
+ V("recharges in a loose whiskered curl", "rests with nose against the tail"),
+ V("galumphs after a baffling impulse", "answers it through whiskered flipper claps"),
+ V("pilfers beneath one broad flipper", "slides away belly-first"),
+ V("flops possessed in exact repeated rolls", "whiskered barks punctuate each compelled roll"),
+ V("dreams with broad flippers paddling", "dozes while whiskers tremble"));
+
+ AddExtended(voices, "civ_sheep",
+ V("sings in soft fleece-muffled bleats", "warbles with woolly chest trembling"),
+ V("courts through close wool-brushing circles", "mates on four softly planted feet"),
+ V("cultivates in even fleece-bobbing passes", "tends growth with small repeated bites"),
+ V("pollinates with a soft wool-framed muzzle", "steps among blooms beneath drooping ears"),
+ V("trades through low bleats and brow dips", "bargains while fleece settles around the stance"),
+ V("fishes with wool held clear of the reach", "fishes from four close-set hooves"),
+ V("hauls against a thickly padded shoulder", "draws weight in even woolly steps"),
+ V("nuzzles wounds through soft fleece", "tends wounds with a slow narrow muzzle"),
+ V("edges around flames with wool pulled back", "faces fire behind a lowered thick brow"),
+ V("bounds away with fleece bouncing", "flees on close quick hooves"),
+ V("settles into a shoulder-tight civic flock", "joins the flock in a fleece-close cluster"),
+ V("drills in thick-browed rushing turns", "patrols with woolly flanks kept together"),
+ V("reads with muzzle beneath the woolly fringe", "studies while drooping ears hold still"),
+ V("bleats kin into a fleece-packed group", "nudges spoils inward with the soft brow"),
+ V("relieves itself on folded hind legs", "holds the woolly tail aside while relieving itself"),
+ V("turns drooping ears between mistaken duties", "nibbles uncertainly at the wrong duty"),
+ V("recharges folded into deep fleece", "rests with muzzle against one woolly flank"),
+ V("follows a strange flockless compulsion", "answers it on fleece-muted quick steps"),
+ V("pilfers beneath thick overlapping fleece", "trots away with ears low"),
+ V("marches possessed without flock formation", "fleece shivers through compelled steps"),
+ V("dreams with fleece shivering lightly", "dozes while small hooves twitch"));
+
+ AddExtended(voices, "civ_snake",
+ V("sings in long coiling hisses", "rattles a winding civic refrain"),
+ V("courts through paired rising coils", "mates in closely interwoven loops"),
+ V("cultivates in smooth coiling curves", "tends growth with a flicking tongue"),
+ V("pollinates with repeated tongue-tip tests", "winds among blooms in polished curves"),
+ V("trades through poised head and coil gestures", "bargains with tongue flicking in measured beats"),
+ V("fishes from a motionless raised coil", "fishes through a single coil-driven strike"),
+ V("hauls by winding loops around the weight", "draws backward through muscular coils"),
+ V("wraps wounds in a loose supporting loop", "tends wounds with repeated tongue tests"),
+ V("coils beside flames with head raised", "tests fire through rapid tongue flicks"),
+ V("flows away in tightening curves", "flees with head low and coils lengthened"),
+ V("settles into a low interlocking civic coil", "links the group through overlapping loops"),
+ V("drills in sudden coil-driven strikes", "patrols in silent looping curves"),
+ V("reads with tongue tracking each line", "studies from a neatly raised coil"),
+ V("hisses kin into an overlapping knot", "winds spoils together inside broad loops"),
+ V("relieves itself with the rear coils straightened", "recoils compactly after relieving itself"),
+ V("loops between contradictory duty cues", "raises the head over a confused duty"),
+ V("recharges knotted into compact coils", "rests beneath overlapping muscular loops"),
+ V("winds after a strange tongue-led impulse", "coils through it in repeated curves"),
+ V("pilfers inside one tightening loop", "flows away without a sound"),
+ V("strikes possessed at empty space", "coils under command in rigid symmetry"),
+ V("dreams with tongue flicking silently", "sleeps while polished coils tighten"));
+
+ AddExtended(voices, "civ_turtle",
+ V("sings in slow shell-deep tones", "wheezes a measured beak-led refrain"),
+ V("courts through slow shell-to-shell circles", "mates on four widely braced feet"),
+ V("cultivates in shell-shadowed passes", "tends growth with a clipping beaked mouth"),
+ V("pollinates with slow beak-tip touches", "plods among blooms beneath the ridged shell"),
+ V("trades through long nods over the shell rim", "bargains without changing its planted stance"),
+ V("fishes with beak poised beyond the shell", "fishes through slow shell-paced reaches"),
+ V("hauls beneath the weight-bearing shell", "draws steadily on short braced legs"),
+ V("nudges wounds with a slow hooking beak", "extends incrementally from the shell and treats wounds"),
+ V("faces flames from behind the shell rim", "tests fire with the beak then withdraws"),
+ V("plods away before drawing limbs inward", "flees under the protection of the shell"),
+ V("settles into a slow shell-rimmed civic ring", "joins the ring through repeated circuits"),
+ V("drills in shell-braced forward shoves", "patrols without breaking its measured pace"),
+ V("reads with chin resting on the shell rim", "tracks lines using slow beak movements"),
+ V("calls kin into a ridged-shell cluster", "pushes spoils together with the shell edge"),
+ V("relieves itself on short firmly planted legs", "extends the rear beyond the shell to relieve itself"),
+ V("turns slowly between conflicting duties", "withdraws halfway over a confused duty"),
+ V("recharges fully enclosed by the shell", "rests with chin on the ridged rim"),
+ V("plods after an inexplicable inner direction", "answers it through shell-paced steps"),
+ V("pilfers with a slow hooking beak", "withdraws behind the shell"),
+ V("marches possessed at an unnatural pace", "extends under command with eyes fixed"),
+ V("dreams with limbs shifting inside the shell", "sleeps while the beaked mouth moves"));
+
+ AddExtended(voices, "civ_unicorn",
+ V("sings in clear horn-lifted tones", "trills while the long mane settles"),
+ V("courts through high-stepping mane tosses", "mates on four high-braced legs"),
+ V("cultivates in high-hoofed passes", "tends growth beneath a lifted horn"),
+ V("pollinates with the horn tip held aside", "steps among blooms on light raised hooves"),
+ V("trades through high horn-led bows", "bargains with mane and tail held still"),
+ V("fishes with horn angled above the stance", "fishes on lightly planted high hooves"),
+ V("hauls through a high arched neck", "draws weight in high even steps"),
+ V("tends wounds beneath the horn tip", "tends wounds with slow muzzle nudges"),
+ V("circles flames with mane drawn clear", "faces fire behind a level pointed horn"),
+ V("gallops away with mane streaming", "flees in long horn-forward strides"),
+ V("settles into a horn-outward civic formation", "joins it through high hoof circuits"),
+ V("drills in poised horn-led charges", "patrols with lifted hooves and neck arched"),
+ V("reads with the horn held straight", "studies while the mane falls to one side"),
+ V("trills kin into a high-stepping group", "draws spoils together with alternating hoof nudges"),
+ V("relieves itself on lightly flexed hind legs", "holds the flowing tail clear while relieving itself"),
+ V("tosses the mane between opposing duties", "angles the horn over a confused duty"),
+ V("recharges with long legs folded evenly", "rests beneath a mane spread along the neck"),
+ V("canters after a strange inward summons", "answers it with horn held high"),
+ V("pilfers beneath a lifted narrow chin", "prances away behind the leveled horn"),
+ V("gallops possessed in severe straight lines", "the rigid mane follows each compelled stride"),
+ V("dreams with long hooves stepping softly", "dozes while the horn and mane tilt"));
+
+ AddExtended(voices, "civ_wolf",
+ V("sings in long muzzle-raised howls", "carries a shoulder-deep pack refrain"),
+ V("courts through close muzzle-and-flank circles", "mates on firmly braced hind legs"),
+ V("cultivates in coordinated pack-timed passes", "tends growth as paws alternate in formation"),
+ V("pollinates with scenting muzzle passes", "ranges among blooms on quiet paws"),
+ V("trades through low growls and ear signals", "bargains from a shoulder-close stance"),
+ V("fishes with muzzle poised and paws spread", "fishes through a swift jaw-led lunge"),
+ V("hauls in a firm jaw-held formation", "draws weight with rolling shoulders"),
+ V("licks wounds with slow repeated strokes", "tends wounds while standing flank-outward"),
+ V("circles flames with muzzle testing the air", "faces fire behind a low shoulder guard"),
+ V("ranges away in long driving strides", "flees with ears flat and tail low"),
+ V("settles into a close shoulder-linked formation", "joins it through pack-timed circuits"),
+ V("drills in coordinated flanking rushes", "patrols with shoulders rolling in formation"),
+ V("reads with muzzle between both forepaws", "studies while ears track every pause"),
+ V("howls kin into a shoulder-close pack", "gathers spoils within a guarded ring"),
+ V("relieves itself with one hind leg lifted", "tests the air after relieving itself"),
+ V("turns ears toward contradictory duties", "circles an obviously mistaken duty"),
+ V("recharges curled muzzle-to-flank", "rests with tail wrapped over the paws"),
+ V("ranges after a strange solitary compulsion", "breaks pack formation through compelled strides"),
+ V("pilfers in quick closing jaws", "slips away with flank held low"),
+ V("runs possessed without pack signals", "the raised muzzle howls through rigid strides"),
+ V("dreams with paws coursing in place", "sleeps through low muzzle-rumbles"));
+
+ AddExtended(voices, "dwarf",
+ V("sings in beard-shaking chest notes", "booms a compact marching refrain"),
+ V("courts through stout forearm clasps", "mates on short powerfully braced legs"),
+ V("cultivates in short forceful passes", "tends growth with beard tucked close"),
+ V("pollinates with thick fingertip taps", "moves bloom to bloom on compact strides"),
+ V("trades through blunt palm and beard gestures", "bargains with thick arms folded"),
+ V("fishes from a low immovable stance", "fishes with short beard-braced pulls"),
+ V("hauls against a stout shoulder", "bears weight on short driving legs"),
+ V("braces wounds with thick forearms", "tends wounds through compact hand presses"),
+ V("faces flames with beard gathered close", "handles fire from a deep braced crouch"),
+ V("retreats in short pounding strides", "flees with beard and elbows tucked"),
+ V("settles into a tightly joined civic formation", "aligns with it from a stout square stance"),
+ V("drills in compact hammering blows", "patrols with fists at a low guard"),
+ V("reads with one thick finger under each line", "studies above a beard spread on the chest"),
+ V("booms kin into a forearm-linked gathering", "stacks spoils in compact ordered groups"),
+ V("relieves the body from a stout squat", "straightens the beard after relieving itself"),
+ V("stamps between two conflicting duties", "pulls the beard over a confused duty"),
+ V("recharges in a short solid curl", "rests beneath a beard spread wide"),
+ V("marches after an inexplicable compulsion", "answers it with beard and jaw set"),
+ V("pilfers with thick compact fingers", "backs away behind folded forearms"),
+ V("stomps possessed in a harsh compact cadence", "marches under command with beard rigid"),
+ V("dreams with thick fists closing softly", "sleeps while short legs brace"));
+
+ AddExtended(voices, "elf",
+ V("sings in clear long-breathed phrases", "threads a light civic melody"),
+ V("courts through poised fingertip bows", "mates in a light long-limbed embrace"),
+ V("cultivates in near-silent even passes", "tends growth with long alternating fingers"),
+ V("pollinates with delicate fingertip brushes", "steps among blooms without stirring them"),
+ V("trades through small repeated hand signs", "bargains with head lightly inclined"),
+ V("fishes from a silent balanced stance", "fishes in fine long-fingered arcs"),
+ V("hauls with long arms held evenly", "bears weight on light measured steps"),
+ V("tends wounds with slender steady hands", "leans close and treats wounds in small touches"),
+ V("faces flames with long fingers held clear", "handles fire through silent measured gestures"),
+ V("withdraws in quick near-silent steps", "flees with long limbs gathered close"),
+ V("settles into a quietly ordered civic formation", "joins it through light even pacing"),
+ V("drills in swift narrow strikes", "patrols without sound on balanced feet"),
+ V("reads with a long finger tracing lines", "studies while head remains lightly bowed"),
+ V("calls kin together in a clear low phrase", "arranges spoils with slender exact fingers"),
+ V("relieves the body in a poised crouch", "rises lightly after relieving itself"),
+ V("tilts the head between incompatible duties", "places long fingers over a mistaken duty"),
+ V("recharges with limbs folded in balance", "rests through slow controlled breaths"),
+ V("glides after a strange inward prompting", "answers it with long fingers tracing silently"),
+ V("pilfers on light slender fingers", "steps away without a sound"),
+ V("moves possessed in severe straight measures", "obeys unseen direction without blinking"),
+ V("dreams with long fingers tracing the air", "sleeps while light feet shift"));
+
+ AddExtended(voices, "human",
+ V("sings in open breath-shaped phrases", "keeps rhythm with alternating hand taps"),
+ V("courts through close face-to-face gestures", "mates in a balanced two-armed embrace"),
+ V("cultivates in brisk alternating passes", "tends growth as both hands alternate"),
+ V("pollinates with alternating fingertip touches", "moves between blooms on steady feet"),
+ V("trades through animated hand bargaining", "negotiates with eyes fixed on the exchange"),
+ V("fishes with both hands held ready", "fishes through steady alternating arm pulls"),
+ V("hauls with shoulders and knees aligned", "bears weight between both arms"),
+ V("braces wounds with both hands", "kneels close and tends each wound"),
+ V("faces flames with forearms shielding", "handles fire from a balanced crouch"),
+ V("runs away with arms driving hard", "flees in quick alternating strides"),
+ V("settles into a hand-linked civic formation", "joins it through paced alternating turns"),
+ V("drills through balanced alternating hand strikes", "patrols with eyes and shoulders forward"),
+ V("reads with one finger tracking the line", "studies while shifting weight between feet"),
+ V("calls kin into an arm-linked gathering", "sorts spoils between quick alternating hands"),
+ V("relieves the body from a low squat", "stands and adjusts posture after relieving itself"),
+ V("hesitates between two incompatible duties", "starts the wrong duty before stopping"),
+ V("recharges with knees drawn close", "rests through slow even breaths"),
+ V("walks after an inexplicable duty impulse", "answers it with alternating hand sweeps"),
+ V("pilfers in one quick palm sweep", "backs away with hands held close"),
+ V("moves possessed in stiff alternating steps", "marches beneath unseen direction"),
+ V("dreams with fingers and eyelids twitching", "sleeps while feet make tiny steps"));
+
+ AddExtended(voices, "orc",
+ V("sings in tusk-bared booming chants", "pounds a broad chest through the refrain"),
+ V("courts through heavy forearm clashes", "mates on wide powerfully braced legs"),
+ V("cultivates in forceful shoulder-driven passes", "tends growth with broad hands and tusks high"),
+ V("pollinates with repeated knuckle touches", "moves among blooms on heavy feet"),
+ V("trades through loud tusk-framed bargaining", "negotiates with fists open at the sides"),
+ V("fishes from a deep shoulder-heavy crouch", "fishes through hard two-armed pulls"),
+ V("hauls against one massive shoulder", "heaves weight with both thick arms"),
+ V("braces wounds with broad hands", "tends wounds behind a tusk-bared guard"),
+ V("faces flames with fists raised", "handles fire while keeping tusks and chest clear"),
+ V("pounds away in long heavy strides", "flees with shoulders hunched and tusks forward"),
+ V("settles into a forearm-locked civic formation", "joins it through heavy heel stamps"),
+ V("drills in chopping fist-and-forearm blows", "patrols with tusks high and shoulders broad"),
+ V("reads with one heavy finger under the lines", "studies while tusks frame a lowered jaw"),
+ V("bellows kin into a shoulder-packed gathering", "heaves spoils into a guarded grouping"),
+ V("relieves the body from a deep wide squat", "rises with fists braced after relieving itself"),
+ V("growls between conflicting duties", "headbutts toward an obviously mistaken duty"),
+ V("recharges in a heavy loose sprawl", "rests with one fist closed against the chest"),
+ V("stalks after a strange compelling duty", "answers it with tusks and fists clenched"),
+ V("pilfers in one broad sweeping hand", "backs away behind raised forearms"),
+ V("marches possessed with fists locked", "strikes empty air beneath unseen command"),
+ V("dreams with tusks bared and fists flexing", "sleeps through low chest-deep growls"));
+ }
+}
diff --git a/IdleSpectator/ActivitySpeciesVoices.Civs.Specialized.cs b/IdleSpectator/ActivitySpeciesVoices.Civs.Specialized.cs
new file mode 100644
index 0000000..590ed5a
--- /dev/null
+++ b/IdleSpectator/ActivitySpeciesVoices.Civs.Specialized.cs
@@ -0,0 +1,351 @@
+using System.Collections.Generic;
+
+namespace IdleSpectator;
+
+public static partial class ActivitySpeciesVoiceCatalog
+{
+ private static void AddCivSpecializedVoices(Dictionary voices)
+ {
+ AddSpecialized(voices, "civ_acid_gentleman",
+ V("flicks a caustic spark into flame", "draws a green flame between rigid fingertips"),
+ V("presses both palms down against the flame", "sweeps a rigid forearm across the flames"),
+ V("bows into a gathering circle", "beckons the family together with one formal hand"),
+ V("draws a soul upward in an emerald strand", "coaxes life essence between poised fingers"),
+ V("searches the spoils with precise fingertips", "lifts spoils with a measured bow"),
+ V("weeps behind one upright hand", "releases a clipped, trembling sob"),
+ V("snaps out a curse through clenched teeth", "cuts the air with a rigid, scolding finger"));
+
+ AddSpecialized(voices, "civ_alpaca",
+ V("puffs a bright flame from pursed lips", "kicks a spark into a spreading flame"),
+ V("stamps broad feet through the flames", "presses a woolly chest down against the flame"),
+ V("hums while joining the herd", "nudges the family into a close cluster"),
+ V("draws a soul along a curling breath", "pulls life essence between soft lips"),
+ V("sniffs through the spoils", "hooks spoils closer with one forefoot"),
+ V("warbles through a streaming nose", "folds long ears through a breathy sob"),
+ V("spits a sharp curse through soft lips", "stamps both forefeet while swearing"));
+
+ AddSpecialized(voices, "civ_armadillo",
+ V("strikes plated claws into a flickering flame", "rolls a spark into a widening flame"),
+ V("rakes low claws across the flames", "presses a plated curl against the flame"),
+ V("uncurls among the gathering family", "trundles into a shell-to-shell group"),
+ V("draws a soul beneath overlapping plates", "cups life essence between curved claws"),
+ V("snuffles through the spoils", "rakes spoils beneath a plated forearm"),
+ V("chitters through a tightly curled body", "rocks inside the shell with dry sobs"),
+ V("clacks out a curse from a half-curl", "scrapes both claws while swearing"));
+
+ AddSpecialized(voices, "civ_bear",
+ V("claps broad paws around a newborn flame", "rakes a spark into a rising flame"),
+ V("beats heavy paws against the flames", "presses a broad forepaw over the flame"),
+ V("lumbers into the gathered family", "pulls the group close with both forelegs"),
+ V("draws a soul between cupped paws", "inhales life essence with a deep rumble"),
+ V("sniffs heavily through the spoils", "scoops spoils between broad paws"),
+ V("roars through a shaking muzzle", "covers the eyes with both paws and sobs"),
+ V("bellows a curse through bared teeth", "swears with both paws raised"));
+
+ AddSpecialized(voices, "civ_beetle",
+ V("rasps wing cases until a flame sparks", "clicks a bright flame between hooked feet"),
+ V("fans rigid wing cases against the flames", "scrapes jointed feet across the flame"),
+ V("clicks while entering the gathered group", "fits carapace to carapace among the family"),
+ V("draws a soul between trembling antennae", "guides life essence beneath the wing case"),
+ V("feels through the spoils with both antennae", "clasps spoils between hooked feet"),
+ V("rattles the wing case through thin cries", "folds every leg beneath a clicking sob"),
+ V("rasps out a curse with snapping mouthparts", "jabs both antennae while swearing"));
+
+ AddSpecialized(voices, "civ_buffalo",
+ V("strikes both horns into a bursting flame", "snorts a spark into a broad flame"),
+ V("stamps heavy hooves across the flames", "sweeps lowered horns through the flame"),
+ V("shoulders into the gathered herd", "calls the family into a horn-ringed group"),
+ V("draws a soul between curved horns", "pulls life essence into a deep breath"),
+ V("roots through the spoils with a broad muzzle", "hooks spoils inward with one horn"),
+ V("bellows with tears streaking the muzzle", "bows the heavy head through rumbling sobs"),
+ V("snorts out a rolling curse", "slashes both horns in a sharp arc while swearing"));
+
+ AddSpecialized(voices, "civ_candy_man",
+ V("snaps glossy fingers into a sparkling flame", "spins a bright flame from striped palms"),
+ V("claps glossy hands around the flame", "pats quick palms across the flames"),
+ V("twirls into the gathering family", "waves the group into a striped circle"),
+ V("draws a soul through spiraling fingers", "winds life essence around glossy hands"),
+ V("taps through the spoils with glossy fingertips", "tucks spoils against a striped chest"),
+ V("crackles through a high, wet sob", "covers glossy eyes with trembling hands"),
+ V("snaps out a brittle curse", "wags a striped finger while swearing"));
+
+ AddSpecialized(voices, "civ_capybara",
+ V("nudges a spark into a low flame", "breathes steadily until a flame catches"),
+ V("presses broad forepaws against the flames", "rolls a blunt muzzle across the flame"),
+ V("ambles into the gathered family", "settles flank-first among the group"),
+ V("draws a soul beneath a blunt chin", "pulls life essence between cupped forepaws"),
+ V("sniffs slowly through the spoils", "draws spoils close between both forepaws"),
+ V("squeaks through streaming eyes", "rests the muzzle low through bubbling sobs"),
+ V("chatters out a blunt curse", "slaps one broad forepaw while swearing"));
+
+ AddSpecialized(voices, "civ_cat",
+ V("strikes a claw-tip spark into flame", "whips a spark into a rising flame"),
+ V("bats quick paws against the flames", "presses both forepaws over the flame"),
+ V("threads into the gathered family", "winds tail-first through the group"),
+ V("draws a soul between hooked claws", "laps life essence from the air"),
+ V("paws silently through the spoils", "hooks spoils beneath one forepaw"),
+ V("yowls with whiskers wet", "hides the face beneath both paws and sobs"),
+ V("hisses a curse through flattened whiskers", "lashes the tail while swearing"));
+
+ AddSpecialized(voices, "civ_chicken",
+ V("scratches a spark into a darting flame", "flaps a small flame into a wider blaze"),
+ V("scratches both feet across the flames", "beats spread wings against the flame"),
+ V("clucks while joining the gathered group", "calls the family into a feathered group"),
+ V("draws a soul beneath a lifted beak", "pecks life essence into a pulsing strand"),
+ V("scratches briskly through the spoils", "pecks spoils into reach"),
+ V("keens with the beak held open", "tucks the face beneath one wing and sobs"),
+ V("squawks out a clipped curse", "spurs the air while swearing"));
+
+ AddSpecialized(voices, "civ_cow",
+ V("scuffs a hoof-spark into a steady flame", "blows a low flame into a broad flare"),
+ V("tramples heavy hooves through the flames", "sweeps a broad muzzle against the flame"),
+ V("lows while joining the gathered herd", "presses shoulder-first into the family group"),
+ V("draws a soul between wide nostrils", "pulls life essence beneath a heavy brow"),
+ V("sniffs through the spoils with a broad muzzle", "nudges spoils between split hooves"),
+ V("moans with tears tracing the muzzle", "bows the head through long, shaking sobs"),
+ V("bellows a deep curse", "stamps one split hoof while swearing"));
+
+ AddSpecialized(voices, "civ_crab",
+ V("clacks both claws into a snapping flame", "fans a spark into a sideways flame"),
+ V("presses both claws against the flames", "rakes jointed legs across the flame"),
+ V("sidesteps into the gathered family", "waves the group into a shell-close cluster"),
+ V("draws a soul between raised pincers", "pulls life essence beneath the shell"),
+ V("probes the spoils with both claws", "pinches spoils between polished pincers"),
+ V("bubbles through a shuddering shell", "covers both eyestalks with trembling claws"),
+ V("clacks out a jagged curse", "brandishes both pincers while swearing"));
+
+ AddSpecialized(voices, "civ_crocodile",
+ V("snaps broad jaws around a sudden flame", "whips a spark into a crawling flame"),
+ V("beats the flames with a plated tail", "presses a broad jaw against the flame"),
+ V("slides into the gathered family", "rumbles the group into a flank-close line"),
+ V("draws a soul between parted jaws", "pulls life essence beneath plated eyelids"),
+ V("sniffs low through the spoils", "drags spoils beneath one foreleg"),
+ V("rumbles with tears beneath plated lids", "rests the jaw low through heaving sobs"),
+ V("growls a curse through locked teeth", "lashes the tail while swearing"));
+
+ AddSpecialized(voices, "civ_dog",
+ V("scratches a paw-spark into lively flame", "pants a small flame into a wider flare"),
+ V("digs both forepaws across the flames", "beats the flame with quick paw strokes"),
+ V("bounds into the gathered family", "calls the group into a nose-close cluster"),
+ V("draws a soul along a lifted muzzle", "laps life essence from a wavering strand"),
+ V("sniffs rapidly through the spoils", "pulls spoils closer between both paws"),
+ V("whines with tears on the muzzle", "covers the nose with both paws and sobs"),
+ V("barks out a sharp curse", "stamps alternating paws while swearing"));
+
+ AddSpecialized(voices, "civ_fox",
+ V("flicks a black paw into a slender flame", "sweeps a spark into a spreading flame"),
+ V("beats the flames with a broad tail", "scrapes quick forepaws across the flame"),
+ V("slips into the gathered family", "curls tail-to-tail among the group"),
+ V("draws a soul around the tail tip", "pulls life essence between narrow jaws"),
+ V("sniffs sidelong through the spoils", "hooks spoils closer with one black paw"),
+ V("barks through wet whiskers", "folds the tail over the face and sobs"),
+ V("spits a quick curse through narrow teeth", "slashes the tail sideways while swearing"));
+
+ AddSpecialized(voices, "civ_frog",
+ V("flicks a tongue-spark into a bobbing flame", "inflates the throat and blows up a flame"),
+ V("slaps broad hands against the flames", "presses a broad tongue over the flame"),
+ V("hops into the gathered family", "croaks the group into a squat circle"),
+ V("draws a soul along the tongue", "pulls life essence into a pulsing throat"),
+ V("prods through the spoils with long fingers", "flicks spoils closer with the tongue"),
+ V("croaks through streaming round eyes", "folds low beneath a throbbing sob"),
+ V("ribbits out a booming curse", "slaps both hands down while swearing"));
+
+ AddSpecialized(voices, "civ_garlic_man",
+ V("rubs papery fingers into a crackling flame", "fans a spark into layered flame"),
+ V("beats loose layers against the flames", "presses knobby hands over the flame"),
+ V("rustles into the gathering family", "bundles the group into a layered cluster"),
+ V("draws a soul between folded layers", "wraps life essence around knobby fingers"),
+ V("rustles through the spoils with both hands", "tucks spoils beneath folded layers"),
+ V("crinkles through a dry, shaking sob", "covers the face with papery hands and weeps"),
+ V("crackles out a jagged curse", "shakes both knobby fists while swearing"));
+
+ AddSpecialized(voices, "civ_goat",
+ V("strikes split hooves into a jumping flame", "tosses a horn-spark into spreading flame"),
+ V("stamps split hooves across the flames", "sweeps curled horns through the flame"),
+ V("bounds into the gathered herd", "butts shoulder-first into the family group"),
+ V("draws a soul between curled horns", "pulls life essence beneath a lifted chin"),
+ V("noses quickly through the spoils", "hooks spoils closer with one horn"),
+ V("bleats with tears on the muzzle", "bows between sharp, shaking sobs"),
+ V("brays out a rasping curse", "clatters both forehooves while swearing"));
+
+ AddSpecialized(voices, "civ_hyena",
+ V("scrapes broad jaws into a crackling flame", "kicks a spark into a loping flame"),
+ V("rakes heavy forepaws through the flames", "snaps broad jaws against the flame"),
+ V("whoops while joining the gathered family", "shoulders into the close group"),
+ V("draws a soul between crushing jaws", "pulls life essence along a rising whoop"),
+ V("sniffs in circles through the spoils", "drags spoils close beneath one paw"),
+ V("whoops through streaming eyes", "folds sloping shoulders around broken sobs"),
+ V("cackles out a coarse curse", "snaps broad jaws while swearing"));
+
+ AddSpecialized(voices, "civ_lemon_man",
+ V("rubs pointed fingers into a fizzing flame", "sprays a spark into a sharp flame"),
+ V("presses rounded palms against the flames", "rolls a pointed crown across the flame"),
+ V("bounces into the gathering family", "pivots the group into a rind-close circle"),
+ V("draws a soul around the pointed crown", "presses life essence between rounded palms"),
+ V("taps through the spoils with pointed fingers", "rolls spoils closer with both hands"),
+ V("squeaks through streaming eyes", "folds both hands over the face and sobs"),
+ V("spits out a sharp curse", "jabs the pointed crown forward while swearing"));
+
+ AddSpecialized(voices, "civ_liliar",
+ V("rubs slender leaves into a silver flame", "unfurls a spark into layered flame"),
+ V("folds broad frills against the flames", "lashes sharpened leaves across the flame"),
+ V("glides into the gathering family", "unfurls the group into a facing circle"),
+ V("draws a soul along a supple stem", "folds life essence between layered frills"),
+ V("sifts through the spoils with slender fingers", "draws spoils beneath layered arms"),
+ V("chimes through trembling frills", "folds slender hands over the face and sobs"),
+ V("trills out a cutting curse", "flicks sharpened leaves while swearing"));
+
+ AddSpecialized(voices, "civ_monkey",
+ V("claps long hands into a flashing flame", "whips a spark into a growing flame"),
+ V("slaps broad palms against the flames", "presses a curling tail over the flame"),
+ V("swings into the gathered family", "chatters the group into a long-armed cluster"),
+ V("draws a soul around a curling tail", "pulls life essence between cupped hands"),
+ V("picks rapidly through the spoils", "grasps spoils with hands and tail"),
+ V("howls with both hands over wet eyes", "curls the tail tight through chattering sobs"),
+ V("shrieks out a tumbling curse", "slaps both palms while swearing"));
+
+ AddSpecialized(voices, "civ_penguin",
+ V("claps stiff flippers into a small flame", "pecks a spark into a rising flame"),
+ V("slaps broad flippers against the flames", "presses a rounded belly over the flame"),
+ V("waddles into the gathered family", "honks the group into a shoulder-close huddle"),
+ V("draws a soul along a narrow bill", "folds life essence between stiff flippers"),
+ V("pecks through the spoils", "slides spoils between both flippers"),
+ V("honks with tears along the bill", "hides the face beneath one flipper and sobs"),
+ V("squawks out a clipped curse", "claps both flippers while swearing"));
+
+ AddSpecialized(voices, "civ_piranha",
+ V("snaps bright teeth into a darting flame", "flicks the tail and spreads a thin flame"),
+ V("presses quick fins against the flames", "lashes a narrow tail over the flame"),
+ V("darts into the gathered family", "clicks the group into a tight-finned cluster"),
+ V("draws a soul between flashing teeth", "pulls life essence past pulsing gills"),
+ V("nips rapidly through the spoils", "tugs spoils between sharp teeth"),
+ V("chatters through trembling gills", "bows the head through thin, clicking sobs"),
+ V("snaps out a staccato curse", "bares flashing teeth while swearing"));
+
+ AddSpecialized(voices, "civ_rabbit",
+ V("scratches quick paws into a hopping flame", "kicks a spark into a spreading flame"),
+ V("beats long ears against the flames", "scrapes both forepaws across the flame"),
+ V("bounds into the gathered family", "thumps the group into an ear-close cluster"),
+ V("draws a soul between upright ears", "pulls life essence beneath a twitching nose"),
+ V("sniffs rapidly through the spoils", "cups spoils between both forepaws"),
+ V("sniffles with long ears folded low", "covers the nose with both paws and sobs"),
+ V("thumps out a sharp curse", "boxes the air while swearing"));
+
+ AddSpecialized(voices, "civ_rat",
+ V("scratches nimble claws into a thin flame", "whips a spark into a spreading flame"),
+ V("rakes both forepaws across the flames", "presses a bare tail over the flame"),
+ V("scurries into the gathered family", "squeaks the group into a whisker-close cluster"),
+ V("draws a soul along trembling whiskers", "winds life essence around a bare tail"),
+ V("sniffs quickly through the spoils", "pulls spoils close between nimble paws"),
+ V("squeals with whiskers dripping", "wrings both paws through rapid sobs"),
+ V("shrills out a jagged curse", "lashes the tail while swearing"));
+
+ AddSpecialized(voices, "civ_rhino",
+ V("drives the horn-tip into a bursting flame", "stomps a spark into a broad flame"),
+ V("tramples heavy feet through the flames", "sweeps the thick horn across the flame"),
+ V("stomps into the gathered herd", "shoulders the family into a horn-outward group"),
+ V("draws a soul along the heavy horn", "pulls life essence beneath thick eyelids"),
+ V("roots heavily through the spoils", "hooks spoils closer with the horn"),
+ V("bellows with tears beneath thick lids", "bows the heavy head through booming sobs"),
+ V("snorts out a crushing curse", "stamps both feet while swearing"));
+
+ AddSpecialized(voices, "civ_scorpion",
+ V("strikes the stinger into a green flame", "clacks both pincers into a spreading flame"),
+ V("rakes eight feet across the flames", "snips raised pincers against the flame"),
+ V("skitters into the gathered family", "clicks the group into a tail-outward ring"),
+ V("draws a soul along the arched stinger", "pulls life essence between heavy pincers"),
+ V("feels through the spoils with both claws", "clasps spoils between heavy pincers"),
+ V("clicks through a trembling plated body", "folds both pincers over the face and sobs"),
+ V("rasps out a dry curse", "jabs the arched stinger while swearing"));
+
+ AddSpecialized(voices, "civ_seal",
+ V("claps broad flippers into a bouncing flame", "barks a spark into a rising flame"),
+ V("slaps both flippers against the flames", "rolls a broad belly across the flame"),
+ V("galumphs into the gathered family", "barks the group into a whisker-close cluster"),
+ V("draws a soul along trembling whiskers", "folds life essence between broad flippers"),
+ V("sniffs through the spoils", "draws spoils close with both flippers"),
+ V("barks with tears dripping from whiskers", "covers the face with both flippers and sobs"),
+ V("honks out a blunt curse", "claps both flippers while swearing"));
+
+ AddSpecialized(voices, "civ_sheep",
+ V("strikes split hooves into a soft flame", "puffs a spark into a widening flame"),
+ V("stamps split hooves across the flames", "presses thick fleece against the flame"),
+ V("bleats while joining the gathered herd", "nestles into the family group"),
+ V("draws a soul through settling fleece", "pulls life essence beneath a lowered muzzle"),
+ V("sniffs gently through the spoils", "nudges spoils between both forehooves"),
+ V("bleats with tears along the muzzle", "buries the face in thick fleece and sobs"),
+ V("brays out a wavering curse", "stamps one forehoof while swearing"));
+
+ AddSpecialized(voices, "civ_snake",
+ V("flicks a forked tongue into a winding flame", "rattles a spark into a rising flame"),
+ V("presses tight coils against the flames", "lays overlapping loops across the flame"),
+ V("glides into the gathered family", "coils among the close group"),
+ V("draws a soul along a forked tongue", "winds life essence between tightening coils"),
+ V("tastes through the spoils", "loops spoils inside a curling tail"),
+ V("hisses with wet scales beneath the eyes", "knots into a tight coil and sobs"),
+ V("hisses out a winding curse", "strikes the air while swearing"));
+
+ AddSpecialized(voices, "civ_turtle",
+ V("scrapes a beaked spark into a low flame", "fans a small flame with broad forefeet"),
+ V("presses the shell rim against the flames", "rakes measured forefeet across the flame"),
+ V("plods into the gathered family", "settles shell-to-shell among the group"),
+ V("draws a soul beneath the shell rim", "pulls life essence between slow forefeet"),
+ V("probes slowly through the spoils", "draws spoils beneath the shell edge"),
+ V("wheezes with tears beneath lowered lids", "withdraws the face and sobs inside the shell"),
+ V("croaks out a slow curse", "snaps the beaked mouth while swearing"));
+
+ AddSpecialized(voices, "civ_unicorn",
+ V("touches the horn-tip to a radiant flame", "casts a bright flame from the lifted horn"),
+ V("presses split hooves against the flames", "stamps raised hooves across the flame"),
+ V("canters into the gathered herd", "bows the family into a horn-outward group"),
+ V("draws a soul along the shining horn", "winds life essence through a streaming mane"),
+ V("tests the spoils with the horn tip", "draws spoils closer between lifted hooves"),
+ V("trills with tears beneath the mane", "folds long legs through ringing sobs"),
+ V("rings out a piercing curse", "slashes the horn in a sharp arc while swearing"));
+
+ AddSpecialized(voices, "civ_wolf",
+ V("scratches a paw-spark into a lean flame", "howls a thin flame into a wider flare"),
+ V("rakes broad paws across the flames", "presses a heavy tail over the flame"),
+ V("trots into the gathered family", "calls the group into a muzzle-close ring"),
+ V("draws a soul along a lifted howl", "pulls life essence between bared teeth"),
+ V("sniffs methodically through the spoils", "drags spoils close beneath one paw"),
+ V("howls with tears along the muzzle", "covers the nose with both paws and sobs"),
+ V("growls out a rough curse", "bares every tooth while swearing"));
+
+ AddSpecialized(voices, "dwarf",
+ V("strikes thick knuckles into a bright flame", "cups a deep flame between stout hands"),
+ V("beats heavy palms against the flames", "stamps short feet across the flame"),
+ V("clasps forearms within the gathering group", "calls the family into a stout circle"),
+ V("draws a soul through a braided beard", "pulls life essence between thick fingers"),
+ V("sorts through the spoils with square hands", "tucks spoils beneath one stout arm"),
+ V("sobs into a bristling beard", "covers both eyes with thick, shaking hands"),
+ V("booms out a bearded curse", "shakes both square fists while swearing"));
+
+ AddSpecialized(voices, "elf",
+ V("traces slender fingers into a clear flame", "coaxes a silver flame between long hands"),
+ V("sweeps long fingers across the flames", "presses slender palms against the flame"),
+ V("bows into the gathering kin-group", "beckons the family into a facing circle"),
+ V("draws a soul between long fingertips", "guides life essence along an open palm"),
+ V("searches the spoils with light fingertips", "draws spoils beneath one slender arm"),
+ V("weeps behind long, trembling fingers", "releases a clear, unsteady sob"),
+ V("speaks a cutting curse through still lips", "points one long finger while swearing"));
+
+ AddSpecialized(voices, "human",
+ V("rubs bare palms into a sudden flame", "snaps a spark into a climbing flame"),
+ V("beats both hands against the flames", "stamps alternating feet across the flame"),
+ V("waves the family into a gathering circle", "steps among the forming civic group"),
+ V("draws a soul between cupped hands", "pulls life essence toward the chest"),
+ V("searches through the spoils with both hands", "gathers spoils against one forearm"),
+ V("weeps into both open hands", "draws shaking breaths between audible sobs"),
+ V("shouts a clipped curse", "jabs one finger while swearing"));
+
+ AddSpecialized(voices, "orc",
+ V("claps heavy fists into a roaring flame", "scrapes broad tusks into a spreading flame"),
+ V("pounds thick forearms against the flames", "stamps heavy feet across the flame"),
+ V("shoulders into the gathering group", "calls the family into a tusk-outward group"),
+ V("draws a soul between broad tusks", "pulls life essence into a clenched fist"),
+ V("rakes through the spoils with heavy hands", "hauls spoils beneath one thick arm"),
+ V("roars with tears across broad tusks", "bows over both fists through heavy sobs"),
+ V("barks out a brutal curse", "pounds both fists together while swearing"));
+ }
+}
diff --git a/IdleSpectator/ActivitySpeciesVoices.Fantasy.Extended.cs b/IdleSpectator/ActivitySpeciesVoices.Fantasy.Extended.cs
new file mode 100644
index 0000000..7951b91
--- /dev/null
+++ b/IdleSpectator/ActivitySpeciesVoices.Fantasy.Extended.cs
@@ -0,0 +1,836 @@
+using System.Collections.Generic;
+
+namespace IdleSpectator;
+
+public static partial class ActivitySpeciesVoiceCatalog
+{
+ private static void AddFantasyExtendedVoices(Dictionary voices)
+ {
+ AddExtended(voices, "UFO",
+ V("broadcasts a layered electronic hymn", "sings through synchronized hull tones"),
+ V("reproduces through pulsing silver light", "begins replication beneath cycling lights"),
+ V("tends growth with measured underlight", "cultivates in scanning passes"),
+ V("pollinates {target} through a soft tractor pulse", "sweeps pollen across {target} with controlled underlight"),
+ V("trades through sequenced signal flashes", "pulses colored lights during exchange"),
+ V("fishes with a narrow scanning beam", "tracks fish beneath pulsing sensors"),
+ V("hauls through steady lifting force", "moves the load beneath its hull"),
+ V("heals {target} under a soft scanning ray", "bathes {target} in modulated light"),
+ V("projects a concentrated heat ray", "fires a bright lower pulse"),
+ V("flees {target} in a silent silver rush", "banks away from {target} with lights streaming"),
+ V("settles into a stable hover", "anchors itself with downward force"),
+ V("patrols with sensor lights sweeping", "holds formation in guarded flight"),
+ V("reads through a traveling scan bar", "decodes marks in flickering lights"),
+ V("gathers life through calibrated scans", "samples living signals with underlight"),
+ V("vents a brief waste vapor", "purges residue beneath its hull"),
+ V("wobbles as its lights missequence", "spins while indicators flash irregularly"),
+ V("recharges with every light brightening", "draws power into its humming hull"),
+ V("jitters through erratic hover loops", "flashes compulsive signal bursts"),
+ V("steals {target} beneath dimmed lights", "reaches for {target} with lifting force"),
+ V("shudders under foreign signal pulses", "flickers as another force pilots it"),
+ V("sees {target} in projected dreams", "drifts dormant through waves of colored light"));
+
+ AddExtended(voices, "alien",
+ V("sings in clicking throat pulses", "layers chirps through its throat sac"),
+ V("reproduces with synchronized body pulses", "begins mating through mirrored gestures"),
+ V("tends growth with four quick hands", "cultivates through nimble fingerwork"),
+ V("pollinates {target} with trembling narrow fingers", "brushes pollen across {target} through rapid handwork"),
+ V("trades through taps and soft clicks", "braids its fingers during exchange"),
+ V("fishes with darting eyes and hands", "grabs near fish with springing reflexes"),
+ V("hauls against its springing shoulders", "moves the load with four hands"),
+ V("heals {target} through careful narrow fingertips", "presses {target} with clicking mouthparts"),
+ V("fires a sharp bioelectric pulse", "launches crackling force from its wrists"),
+ V("flees {target} in bounding sideways leaps", "scuttles away from {target} on springing legs"),
+ V("settles into a compact crouch", "claims space with tapping fingertips"),
+ V("stands guard on flexed legs", "patrols with darting eyes"),
+ V("reads by tracing marks rapidly", "studies symbols with unblinking eyes"),
+ V("gathers life with tasting fingertips", "samples living traces through mouthparts"),
+ V("relieves itself in a low crouch", "expels waste as its throat sac contracts"),
+ V("tilts as its eyes desynchronize", "fumbles while four hands disagree"),
+ V("recharges through pulsing throat sacs", "draws energy into springing limbs"),
+ V("twitches through compulsive hand patterns", "scuttles in abrupt repeated bursts"),
+ V("steals {target} with four synchronized hands", "lunges toward {target} with grasping fingers"),
+ V("jerks as its limbs move independently", "chatters while foreign pulses seize it"),
+ V("sees {target} in dreams as eyelids flutter", "curls tightly while throat colors ripple"));
+
+ AddExtended(voices, "angle",
+ V("sings in resonant celestial chimes", "voices a hymn through radiant pulses"),
+ V("reproduces within converging holy radiance", "begins mating as divine light swells"),
+ V("tends growth beneath measured brilliance", "cultivates with steady sacred light"),
+ V("pollinates {target} in a radiant wash", "guides pollen across {target} through holy light"),
+ V("trades beneath steady divine illumination", "pulses sacred light during exchange"),
+ V("fishes through revealing celestial light", "sweeps radiant force near fish"),
+ V("hauls within surrounding radiance", "moves the load through divine force"),
+ V("heals {target} beneath holy light", "bathes {target} in celestial brilliance"),
+ V("releases a searing sacred flash", "fires a focused surge of divinity"),
+ V("flees {target} as radiance streams behind", "withdraws from {target} in a burst of holy light"),
+ V("settles beneath a steadfast sacred glow", "holds its station with radiant presence"),
+ V("keeps watch in unwavering brilliance", "patrols as a celestial presence"),
+ V("reads as divine light reveals marks", "studies symbols within pale radiance"),
+ V("gathers life in revealing holy light", "reaches for living essence through sacred radiance"),
+ V("relieves itself in a fading shimmer", "releases waste beneath veiling radiance"),
+ V("flickers as its sacred glow falters", "wanders while divine pulses misfire"),
+ V("recharges in gathering celestial brilliance", "draws holy power into its presence"),
+ V("surges through repeated radiant flashes", "burns with an erratic sacred pulse"),
+ V("steals {target} beneath a muted sacred glow", "reaches for {target} through radiance"),
+ V("flares as foreign force grips it", "shudders beneath a distorted holy glow"),
+ V("sees {target} in radiant dreams", "rests as celestial visions pulse visibly"));
+
+ AddExtended(voices, "assimilator",
+ V("sings through several borrowed throats", "layers mismatched voices across its surface"),
+ V("reproduces by budding a pulsing mass", "begins mating as membranes intermingle"),
+ V("tends growth with braided tendrils", "cultivates through probing filaments"),
+ V("pollinates {target} with rippling surface cilia", "spreads pollen across {target} on tasting tendrils"),
+ V("trades through shifting grasping limbs", "layers borrowed voices during exchange"),
+ V("fishes with a snapping membrane", "senses fish through trailing filaments"),
+ V("hauls with braided grasping tendrils", "moves the load beneath its mass"),
+ V("heals {target} by matching living tissue", "covers {target} beneath a clear membrane"),
+ V("fires a hardened organic barb", "launches a dense pulse of tissue"),
+ V("flees {target} in rolling bodily surges", "flees {target} on rapidly pulling tendrils"),
+ V("settles by anchoring many filaments", "spreads into a rooted living mound"),
+ V("guards with hardened surface plates", "patrols on braided tendrils"),
+ V("reads through borrowed clustered eyes", "traces marks with tasting filaments"),
+ V("gathers life into sampling membranes", "draws living traces through cilia"),
+ V("expels waste through opening pores", "sheds a clouded outer membrane"),
+ V("ripples through mismatched borrowed forms", "stumbles as limbs repeatedly reform"),
+ V("recharges as inner pulses quicken", "draws energy beneath its surface"),
+ V("buds grasping hands in repeated cycles", "surges through rapid transformations"),
+ V("steals {target} with a sudden pseudopod", "reaches around {target} with a clear membrane"),
+ V("convulses as foreign patterns spread", "forms unfamiliar faces across its surface"),
+ V("sees {target} in borrowed dream-faces", "rests while remembered forms ripple"));
+
+ AddExtended(voices, "civ_crystal_golem",
+ V("sings in deep crystalline resonance", "rings harmonics through its faceted chest"),
+ V("reproduces as core light divides", "begins mating through synchronized core pulses"),
+ V("tends growth with heavy faceted hands", "cultivates beneath refracted core light"),
+ V("pollinates {target} through prismatic light pulses", "brushes pollen across {target} with crystal fingertips"),
+ V("trades with slow resonant hand taps", "pulses chest light during exchange"),
+ V("fishes through refracted glints", "closes faceted palms near fish"),
+ V("hauls against its massive crystal frame", "moves the load with stone hands"),
+ V("heals {target} through refracted core light", "presses {target} beneath glowing facets"),
+ V("fires a concentrated prismatic burst", "releases core light in a hot flash"),
+ V("flees {target} with heavy ringing strides", "flees {target} as core light races"),
+ V("settles into rooted statue stillness", "plants its faceted feet firmly"),
+ V("guards with broad crystal arms", "patrols in resonant heavy steps"),
+ V("reads through shifting facet reflections", "studies marks in core light"),
+ V("gathers life through vibrating fingertips", "draws living traces into its core"),
+ V("vents powdered residue from its seams", "sheds dull grit between crystal joints"),
+ V("staggers as core light scatters", "turns while facets flash inconsistently"),
+ V("recharges as its core intensifies", "draws energy through glowing seams"),
+ V("trembles with compulsive core surges", "strides as facets flash erratically"),
+ V("steals {target} with a heavy crystal hand", "reaches for {target} between glowing facets"),
+ V("cracks with invading dark pulses", "moves as foreign light fills its core"),
+ V("sees {target} in prismatic dreams", "rests as visions cross its facets"));
+
+ AddExtended(voices, "cold_one",
+ V("sings through chiming frozen breath", "voices a brittle frost cadence"),
+ V("reproduces amid mingling cold vapor", "begins mating as rime pulses"),
+ V("tends growth beneath numbing palms", "cultivates with measured cooling touch"),
+ V("pollinates {target} on emitted cold vapor", "brushes pollen across {target} with frost-rimmed fingers"),
+ V("trades with clicks of frozen teeth", "emits pale vapor during exchange"),
+ V("fishes by sensing warmth below", "closes whitening hands near fish"),
+ V("hauls with rigid frostbound limbs", "moves the load across slick rime"),
+ V("heals {target} beneath a frost sheen", "numbs {target} with a pale palm"),
+ V("fires a lance of intense cold", "releases a burst of hard rime"),
+ V("flees {target} in a skidding frost trail", "flees {target} behind emitted cold vapor"),
+ V("settles beneath an anchored ice crust", "plants stiff limbs in spreading rime"),
+ V("guards behind hardening frost", "patrols with whitening palms ready"),
+ V("reads as rime highlights marks", "studies symbols through pale eyes"),
+ V("gathers life through heat-sensing fingers", "draws living warmth into rime"),
+ V("relieves itself in brittle frozen waste", "expels waste beneath cold vapor"),
+ V("stares as frost pulses unevenly", "stumbles while rime locks its limbs"),
+ V("recharges as its rime thickens", "draws energy into a whitening core"),
+ V("scrapes compulsively at its own frost", "paces beneath surging cold vapor"),
+ V("steals {target} with a numbing quick palm", "reaches for {target} through hardening rime"),
+ V("jerks as black frost spreads", "moves beneath an invading cold pulse"),
+ V("sees {target} in dreams beneath sleeping ice", "rests as emitted vapor forms visions"));
+
+ AddExtended(voices, "crabzilla",
+ V("sings in thunderous shell resonance", "booms a rhythm through colossal plates"),
+ V("reproduces through booming pincer displays", "begins mating as shell plates rumble"),
+ V("tends growth beneath careful claw taps", "cultivates with immense measured pincers"),
+ V("pollinates {target} with sweeping pincer beats", "fans pollen across {target} beneath colossal claws"),
+ V("trades through monumental claw gestures", "rumbles its shell during exchange"),
+ V("fishes between immense closing pincers", "tracks fish with sweeping eye stalks"),
+ V("hauls beneath its fortress shell", "moves the load with colossal pincers"),
+ V("heals {target} by applying plated pressure", "presses {target} beneath a broad claw"),
+ V("fires a crushing pressure blast", "launches force between snapping pincers"),
+ V("flees {target} in thundering sideways strides", "flees {target} behind its fortress shell"),
+ V("settles on folded towering limbs", "anchors its shell with planted legs"),
+ V("guards behind raised colossal pincers", "patrols with eye stalks sweeping"),
+ V("reads through swiveling eye stalks", "studies marks with careful claw taps"),
+ V("gathers life through vibrating leg tips", "samples living motion with eye stalks"),
+ V("relieves itself beneath folded rear plates", "expels waste below its vast shell"),
+ V("clacks while eye stalks cross", "lurches as towering legs mistime"),
+ V("recharges as shell plates vibrate", "draws energy through planted leg tips"),
+ V("stamps through compulsive sideways surges", "snaps both pincers without cause"),
+ V("steals {target} with one sweeping pincer", "reaches for {target} beneath its shell"),
+ V("shudders as shell plates darken", "stomps beneath an invading pulse"),
+ V("sees {target} in rumbling dreams", "rests as eye stalks twitch"));
+
+ AddExtended(voices, "crystal_sword",
+ V("sings through a ringing crystal blade", "voices a clear hilt-deep peal"),
+ V("reproduces as prismatic light separates", "begins mating through crossed resonant tones"),
+ V("tends growth with careful blade glints", "cultivates beneath refracted light"),
+ V("pollinates {target} through sweeping flat-side passes", "guides pollen across {target} on prismatic pulses"),
+ V("trades with a formal hilt dip", "rings clearly during exchange"),
+ V("fishes in a swift point-first dive", "flashes beneath fish with its flat"),
+ V("hauls beneath its hovering guard", "moves the load with lifting resonance"),
+ V("heals {target} by laying its flat nearby", "bathes {target} in prismatic shimmer"),
+ V("fires a piercing crystal pulse", "releases a bright blast from its point"),
+ V("flees {target} in a ringing aerial sweep", "flees {target} point-first through prismatic light"),
+ V("settles point-down in steady hover", "anchors its presence through low resonance"),
+ V("guards upright with edge forward", "patrols in measured sweeping arcs"),
+ V("reads by tracing marks with light", "studies symbols reflected along its blade"),
+ V("gathers life through testing resonance", "draws living traces along its fuller"),
+ V("sheds cloudy residue from its facets", "vents dull particles beneath its guard"),
+ V("wobbles as its resonance breaks", "spins while prismatic light scatters"),
+ V("recharges as its facets brighten", "draws energy along its fuller"),
+ V("slashes through repeated empty sweeps", "rings in rapidly recurring bursts"),
+ V("steals {target} beneath a muted prismatic shimmer", "hooks toward {target} with its guard"),
+ V("jerks as dark resonance grips it", "rings harshly under foreign control"),
+ V("sees {target} in chiming dreams", "rests as visions shimmer along its blade"));
+
+ AddExtended(voices, "demon",
+ V("sings in a cracked furnace roar", "chants through smoking fangs"),
+ V("reproduces amid mingling embers", "begins mating with pulsing wingbeats"),
+ V("tends growth with ember-warm claws", "cultivates beneath controlled heat"),
+ V("pollinates {target} with careful wingbeats", "fans pollen across {target} with leathery wings"),
+ V("trades with horns lowered formally", "sheds red sparks during exchange"),
+ V("fishes with heat-sensing nostrils", "closes hooked claws near fish"),
+ V("hauls against its horned shoulders", "moves the load with clawed hands"),
+ V("heals {target} beneath claw heat", "presses {target} with ember-warm claws"),
+ V("fires a scorching throat burst", "hurls flame from both claws"),
+ V("flees {target} on smoking hooves", "flees {target} behind beating wings"),
+ V("settles within a scorched crouch", "plants smoking hooves firmly"),
+ V("guards with horns and claws raised", "patrols beneath folded wings"),
+ V("reads through ember-bright eyes", "traces marks with a hot claw"),
+ V("gathers life through flared nostrils", "draws living heat into embers"),
+ V("relieves itself in smoking waste", "expels waste beneath folded wings"),
+ V("snarls as sparks misfire", "stumbles when hooves flare unevenly"),
+ V("recharges around a red-hot core", "draws energy through smoking horns"),
+ V("lashes its tail compulsively", "paces beneath uncontrolled embers"),
+ V("steals {target} with a hooked claw", "reaches for {target} beneath one wing"),
+ V("convulses as black flame spreads", "moves beneath a foreign infernal pulse"),
+ V("sees {target} in ember-lit dreams", "rests while wing membranes twitch"));
+
+ AddExtended(voices, "dragon",
+ V("sings in rolling chest thunder", "voices a vast plated resonance"),
+ V("reproduces through synchronized wing displays", "begins mating amid pulsing throat glow"),
+ V("tends growth with careful foreclaws", "cultivates beneath measured warm breath"),
+ V("pollinates {target} with broad wingbeats", "fans pollen across {target} with controlled wings"),
+ V("trades with a formal horn dip", "rumbles its chest during exchange"),
+ V("fishes in a talon-first plunge", "tracks fish with unblinking eyes"),
+ V("hauls against its plated shoulders", "moves the load in closed talons"),
+ V("heals {target} beneath warming breath", "presses {target} with careful foreclaws"),
+ V("fires a narrow blazing torrent", "launches a throat-deep blast"),
+ V("flees {target} on vast wingbeats", "flees {target} with plated tail streaming"),
+ V("settles onto folded haunches", "anchors itself beneath spread talons"),
+ V("guards with wings half spread", "patrols beneath a horned gaze"),
+ V("reads with one unblinking eye", "traces marks using a foreclaw"),
+ V("gathers life through flared nostrils", "draws living traces in deep breaths"),
+ V("relieves itself beneath a raised tail", "expels waste in a plated crouch"),
+ V("tilts as its pupils lose focus", "missteps while tail and wings disagree"),
+ V("recharges as throat glow deepens", "draws energy beneath plated scales"),
+ V("snaps through compulsive wingbeats", "paces under surging throat light"),
+ V("steals {target} in a swift talon sweep", "reaches for {target} beneath its chest"),
+ V("thrashes as scales pulse darkly", "moves under an invading throat glow"),
+ V("sees {target} in smoke-lit dreams", "rests while vast wings twitch"));
+
+ AddExtended(voices, "druid",
+ V("sings in layered rustling tones", "chants as leaf fibers tremble"),
+ V("reproduces amid entwining living fibers", "begins mating as leaf patterns pulse"),
+ V("tends growth through coaxing palms", "cultivates with fresh root magic"),
+ V("pollinates {target} with rustling leaves", "guides pollen across {target} through curling vines"),
+ V("trades with a leaf-hood bow", "rustles living fibers during exchange"),
+ V("fishes with sensing root magic", "draws fish near through living fibers"),
+ V("hauls with tightening green vines", "moves the load through living growth"),
+ V("heals {target} beneath fresh green fibers", "binds {target} with curling growth"),
+ V("fires a burst of hard thorns", "launches force through snapping vines"),
+ V("flees {target} beneath streaming leaf fibers", "flees {target} on quick curling roots"),
+ V("settles as roots spread below", "anchors itself through living fibers"),
+ V("guards behind layered thorn growth", "patrols as leaves listen"),
+ V("reads as leaf veins trace marks", "studies symbols through living grain"),
+ V("gathers life through fine roots", "draws living traces into fresh growth"),
+ V("relieves itself into absorbing roots", "releases waste beneath folded leaves"),
+ V("turns as leaves rustle erratically", "stumbles while roots pull apart"),
+ V("recharges as fresh leaves unfurl", "draws energy through living fibers"),
+ V("sprouts vines in compulsive bursts", "paces while leaves pulse rapidly"),
+ V("steals {target} with a curling vine", "reaches around {target} with living fibers"),
+ V("jerks as black roots spread", "moves beneath invading thorn growth"),
+ V("sees {target} in leaf-veined dreams", "rests while roots trace visions"));
+
+ AddExtended(voices, "evil_mage",
+ V("sings in layered shadow whispers", "chants through violet sparks"),
+ V("reproduces amid merging dark sigils", "begins mating as shadows pulse"),
+ V("tends growth beneath violet force", "cultivates through crawling dark symbols"),
+ V("pollinates {target} with circling shadows", "guides pollen across {target} with violet sparks"),
+ V("trades with a hooded bow", "cycles dark sigils during exchange"),
+ V("fishes through a hovering violet gaze", "draws fish upward with shadow force"),
+ V("hauls within grasping shadows", "moves the load through violet force"),
+ V("heals {target} beneath binding dark symbols", "presses {target} with smoking fingertips"),
+ V("fires crackling violet force", "launches a burst of shadow"),
+ V("flees {target} inside emitted black vapor", "flees {target} as shadows fold inward"),
+ V("settles within hovering dark sigils", "anchors shadows beneath its robe"),
+ V("guards behind a violet barrier", "patrols with shadows circling"),
+ V("reads through crawling luminous symbols", "studies marks beneath violet light"),
+ V("gathers life through a circling gaze", "draws living traces into shadow"),
+ V("relieves itself beneath folded darkness", "expels waste inside layered shadow"),
+ V("flickers as sigils scramble", "wanders while shadows point elsewhere"),
+ V("recharges as violet symbols brighten", "draws energy into layered shadow"),
+ V("casts compulsive empty sigils", "paces amid uncontrolled dark sparks"),
+ V("steals {target} through a grasping shadow", "reaches for {target} with folded darkness"),
+ V("convulses beneath foreign pale symbols", "moves while foreign shadows pull"),
+ V("sees {target} in violet dreams", "rests as shadows reenact visions"));
+
+ AddExtended(voices, "fairy",
+ V("sings in tiny bell trills", "layers bright notes with wingbeats"),
+ V("reproduces amid mingling shimmer", "begins mating through synchronized glow pulses"),
+ V("tends growth with sparkling fingertips", "cultivates beneath a tiny warm glow"),
+ V("pollinates {target} with shimmering wingbeats", "dusts pollen across {target} with sparkling motes"),
+ V("trades through spiraling light ribbons", "trills brightly during exchange"),
+ V("fishes in quick shimmering dives", "tracks fish through pulsing glow"),
+ V("hauls within a sparkling lift", "moves the load on rapid wingbeats"),
+ V("heals {target} beneath bright motes", "bathes {target} in a tiny flash"),
+ V("fires a needle-thin sparkle", "launches a bright mote burst"),
+ V("flees {target} in looping wing flashes", "flees {target} with glow streaming"),
+ V("settles into a hovering shimmer", "perches with wings folded upright"),
+ V("guards with wings buzzing brightly", "patrols in tight glowing loops"),
+ V("reads by tracing marks in light", "studies symbols through tiny glints"),
+ V("gathers life into sparkling motes", "samples living traces with shimmer"),
+ V("relieves itself beneath veiling motes", "releases waste during a brief hover"),
+ V("loops as its glow pulses unevenly", "hovers while wings lose rhythm"),
+ V("recharges inside a swelling glow", "draws energy through shimmering wings"),
+ V("darts through compulsive tiny loops", "scatters motes in urgent bursts"),
+ V("steals {target} in a quick sparkling pass", "reaches for {target} through shimmer"),
+ V("jerks as its glow turns harsh", "flies under an invading pulse"),
+ V("sees {target} in glowing dreams", "rests as wings trace visions"));
+
+ AddExtended(voices, "fire_elemental",
+ V("sings in roaring flame harmonics", "crackles through a rising cadence"),
+ V("reproduces as core flame divides", "begins mating through mingling fire"),
+ V("tends growth with measured warmth", "cultivates beneath careful flame"),
+ V("pollinates {target} with controlled heat pulses", "guides pollen across {target} with thin flames"),
+ V("trades through sequenced spark bursts", "flares white during exchange"),
+ V("fishes by sensing cooler motion", "surrounds fish with curling heat"),
+ V("hauls within a lifting heat column", "moves the load through flowing flame"),
+ V("heals {target} beneath measured warmth", "presses {target} with a white fingertip"),
+ V("fires a roaring arm of flame", "launches a white-hot burst"),
+ V("flees {target} as streaming orange ribbons", "flees {target} in a sudden flare"),
+ V("settles into a steady upright blaze", "anchors around a white-hot core"),
+ V("guards as a broad wall of fire", "patrols in folding flames"),
+ V("reads as heat reveals marks", "studies symbols through flickering tongues"),
+ V("gathers life through trembling flames", "draws living warmth toward its core"),
+ V("sheds spent ash beneath itself", "vents dark smoke from its core"),
+ V("flares as tongues split repeatedly", "wavers while its core pulses unevenly"),
+ V("recharges around a whitening core", "draws energy through every flame"),
+ V("lashes out in compulsive firebursts", "surges through uncontrolled flares"),
+ V("steals {target} behind a curtain of flame", "reaches for {target} through lowered heat"),
+ V("blackens as foreign fire spreads", "moves beneath an invading blaze"),
+ V("sees {target} in ember dreams", "rests as flames replay visions"));
+
+ AddExtended(voices, "fire_elemental_blob",
+ V("sings in bubbly molten pops", "gurgles through bright crackles"),
+ V("reproduces by budding a hot lobe", "begins mating as molten surfaces mingle"),
+ V("tends growth with warm pseudopods", "cultivates beneath soft heat"),
+ V("pollinates {target} with popping heat bubbles", "brushes pollen across {target} with glowing lobes"),
+ V("trades through shaped molten gestures", "pops a bright bubble during exchange"),
+ V("fishes with a stretching hot lobe", "senses fish through surface ripples"),
+ V("hauls within several molten lobes", "moves the load across its surface"),
+ V("heals {target} beneath a warm fold", "covers {target} with controlled heat"),
+ V("fires a clinging heat glob", "launches a popping molten burst"),
+ V("flees {target} in wobbling molten hops", "flees {target} with flames streaming"),
+ V("settles into a broad hot puddle", "anchors through spreading molten folds"),
+ V("guards behind swelling fiery lobes", "patrols in bouncing molten surges"),
+ V("reads through traveling surface bubbles", "traces marks with a narrow pseudopod"),
+ V("gathers life across tasting folds", "draws living traces beneath its skin"),
+ V("expels dark slag from one fold", "sheds spent crust beneath itself"),
+ V("wobbles as bubbles reverse direction", "splits and rejoins in repeated cycles"),
+ V("recharges as its center brightens", "draws energy through molten skin"),
+ V("buds compulsive grasping lobes", "pops through urgent surface surges"),
+ V("steals {target} with a stretching pseudopod", "reaches around {target} with one fold"),
+ V("convulses as black bubbles spread", "moves while foreign pulses deform it"),
+ V("sees {target} in rippling dreams", "rests as bubbles form visions"));
+
+ AddExtended(voices, "fire_elemental_horse",
+ V("sings in furnace-bright whinnies", "nickers through a crackling mane"),
+ V("reproduces amid synchronized flame pulses", "begins mating through blazing prances"),
+ V("tends growth with warm careful hooves", "cultivates beneath controlled hoof heat"),
+ V("pollinates {target} with mane-driven pulses", "fans pollen across {target} with a fiery tail"),
+ V("trades through ember-bright muzzle dips", "flares one hoof during exchange"),
+ V("fishes with smoke-sensitive nostrils", "strikes near fish with a hot hoof"),
+ V("hauls against its blazing shoulders", "moves the load in a heated stride"),
+ V("heals {target} beneath a warming muzzle", "presses {target} with controlled hoof heat"),
+ V("fires a blazing forward breath", "launches sparks through a sharp snort"),
+ V("flees {target} on streaming fiery hooves", "flees {target} with mane blazing"),
+ V("settles onto folded ember legs", "plants four compact flame hooves"),
+ V("guards with mane fully raised", "patrols in a measured hot canter"),
+ V("reads through ember-bright eyes", "traces marks with one hot hoof"),
+ V("gathers life through flared nostrils", "draws living traces through warm breath"),
+ V("relieves itself beneath a lifted flame tail", "expels glowing waste in a crouch"),
+ V("sidesteps as mane pulses unevenly", "stamps while nostrils flare repeatedly"),
+ V("recharges as its mane whitens", "draws energy through glowing hooves"),
+ V("prances in compulsive fiery bursts", "stamps through uncontrolled sparks"),
+ V("steals {target} in a quick muzzle sweep", "reaches for {target} with glowing teeth"),
+ V("bucks as black flame spreads", "gallops beneath a foreign pulse"),
+ V("sees {target} in ember-lit dreams", "rests while blazing legs twitch"));
+
+ AddExtended(voices, "fire_elemental_slug",
+ V("sings in wet sizzling whistles", "bubbles through a molten trill"),
+ V("reproduces amid mingling mantle glow", "begins mating as hot bodies pulse"),
+ V("tends growth with a heated foot", "cultivates beneath mantle warmth"),
+ V("pollinates {target} with curling feeler sparks", "brushes pollen across {target} with flame feelers"),
+ V("trades through paired feeler curls", "pulses its mantle during exchange"),
+ V("fishes with heat-sensitive feelers", "surrounds fish in a slow hot fold"),
+ V("hauls atop its broad heated foot", "moves the load beneath a mantle fold"),
+ V("heals {target} under a warm body trail", "covers {target} with controlled mantle heat"),
+ V("fires a strip of clinging flame", "launches a hot mantle spark"),
+ V("flees {target} in a swift molten glide", "flees {target} beneath streaming feelers"),
+ V("settles into a low smoldering coil", "anchors through its broad heated foot"),
+ V("guards with both feelers blazing", "patrols along a narrow hot trail"),
+ V("reads by sweeping sensitive feelers", "traces marks with its heated foot"),
+ V("gathers life across tasting skin", "draws living traces through feelers"),
+ V("leaves a dark waste bead behind", "expels residue beneath its mantle"),
+ V("coils as feelers point apart", "glides while mantle pulses misfire"),
+ V("recharges as its mantle glows", "draws energy through its broad underside"),
+ V("curls through compulsive hot spirals", "flicks feelers in urgent bursts"),
+ V("steals {target} beneath a mantle fold", "reaches for {target} along its heated foot"),
+ V("writhes as black heat spreads", "glides beneath an invading pulse"),
+ V("sees {target} in mantle dreams", "rests as feelers trace visions"));
+
+ AddExtended(voices, "fire_elemental_snake",
+ V("sings in a crackling hiss", "rattles through bright flame notes"),
+ V("reproduces amid braided fiery coils", "begins mating as core flames pulse"),
+ V("tends growth within warm loose coils", "cultivates through measured body heat"),
+ V("pollinates {target} with sweeping coils", "guides pollen across {target} with a flame tongue"),
+ V("trades through paired coil gestures", "rattles its tail during exchange"),
+ V("fishes with a heat-sensitive tongue", "strikes near fish with glowing jaws"),
+ V("hauls within tightening fiery coils", "moves the load along its body"),
+ V("heals {target} beneath a warm coil", "surrounds {target} with controlled flame"),
+ V("fires a searing tongue bolt", "launches flame from raised jaws"),
+ V("flees {target} in a swift incandescent slither", "flees {target} with tail sparks"),
+ V("settles into a banked ember coil", "anchors through overlapping fiery loops"),
+ V("guards with head raised brightly", "patrols in tight burning curves"),
+ V("reads through tongue-tip heat changes", "traces marks with a glowing tail"),
+ V("gathers life through its split tongue", "draws living warmth into coils"),
+ V("expels glowing waste behind its coils", "leaves a dark residue pellet"),
+ V("knots as tongue flicks erratically", "turns while coils pull against themselves"),
+ V("recharges as every coil brightens", "draws energy through a flickering tongue"),
+ V("strikes through compulsive empty lunges", "rattles beneath uncontrolled flame"),
+ V("steals {target} within a swift coil", "reaches around {target} with its body"),
+ V("writhes as dark flame bands it", "slithers under a foreign pulse"),
+ V("sees {target} in coiling dreams", "rests while its tail twitches"));
+
+ AddExtended(voices, "fire_skull",
+ V("sings through a blazing hollow howl", "cackles in pitched jaw notes"),
+ V("reproduces as crown flame divides", "begins mating through synchronized jaw fire"),
+ V("tends growth with measured crown heat", "cultivates beneath careful flame breath"),
+ V("pollinates {target} with hollow-mouth pulses", "guides pollen across {target} with crown sparks"),
+ V("trades through formal jaw clacks", "pulses socket flame during exchange"),
+ V("fishes through heat-sensing sockets", "snaps fish between blazing teeth"),
+ V("hauls with gripping fiery jaws", "moves the load beneath its chin"),
+ V("heals {target} beneath measured flame breath", "presses {target} with warm teeth"),
+ V("fires a compact mouth bolt", "launches flame through open jaws"),
+ V("flees {target} with crown flame streaming", "flees {target} in a hollow rush"),
+ V("settles jaw-down in low hover", "anchors beneath a banked blue crown"),
+ V("guards with sockets fixed forward", "patrols in snapping fiery arcs"),
+ V("reads through pulsing empty sockets", "traces marks with crown light"),
+ V("gathers life through hollow nostrils", "draws living warmth into its crown"),
+ V("drops dark ash through its jaw", "vents spent soot from hollow sockets"),
+ V("spins as sockets flare unevenly", "chatters while crown flame misfires"),
+ V("recharges as its crown whitens", "draws energy through hollow jaws"),
+ V("snaps compulsively at empty space", "bobs through uncontrolled flame bursts"),
+ V("steals {target} in a sudden jaw snap", "reaches for {target} between blazing teeth"),
+ V("rattles as black flame crowns it", "flies under an invading socket glow"),
+ V("sees {target} in crown-lit dreams", "rests as jaws silently chatter"));
+
+ AddExtended(voices, "ghost",
+ V("sings in airy layered echoes", "warbles through a translucent form"),
+ V("reproduces as two auras intermingle", "begins mating through synchronized fading"),
+ V("tends growth with spectral pressure", "cultivates beneath a cool aura"),
+ V("pollinates {target} with spectral pressure", "guides pollen across {target} with translucent hands"),
+ V("trades through pulsing aura gestures", "bows its spectral form during exchange"),
+ V("fishes with an unseen lifting force", "tracks fish through its emitted mist"),
+ V("hauls through steady unseen pressure", "moves the load without contact"),
+ V("heals {target} beneath a spectral veil", "presses {target} with translucent hands"),
+ V("fires a chilling spectral pulse", "launches force through a sudden wail"),
+ V("flees {target} as a thinning pale streak", "flees {target} within its trailing mist"),
+ V("settles into a faint hovering veil", "anchors as a dim silhouette"),
+ V("guards with aura spread broadly", "patrols through silent drifting passes"),
+ V("reads by passing through marks", "studies symbols as its aura ripples"),
+ V("gathers life through spectral fingertips", "draws living traces into its emitted mist"),
+ V("releases cloudy residue through itself", "sheds a dim spectral waste"),
+ V("fades in and out irregularly", "drifts while hands pass through itself"),
+ V("recharges as its outline brightens", "draws energy into a hollow form"),
+ V("loops through compulsive fading passes", "wails beneath an urgent aura pulse"),
+ V("steals {target} through a passing spectral hand", "reaches for {target} within its emitted mist"),
+ V("distorts as foreign shadow crosses its mist", "moves beneath a foreign spectral pull"),
+ V("sees {target} in translucent dreams", "rests as its aura reenacts visions"));
+
+ AddExtended(voices, "god_finger",
+ V("sings by drumming its nail", "wiggles through a silent fingertip ballad"),
+ V("reproduces through paired fingertip pulses", "begins mating as nail glints synchronize"),
+ V("tends growth with its sensitive tip", "cultivates with measured fingertip presses"),
+ V("pollinates {target} with nail-tip taps", "brushes pollen across {target} with its fingertip"),
+ V("trades through a formal fingertip curl", "taps its nail during exchange"),
+ V("fishes with a sudden fingertip flick", "tests for fish with its sensitive tip"),
+ V("hauls by bracing its curved body", "nudges the load with its nail"),
+ V("heals {target} with measured pressure", "tends {target} with careful fingertip taps"),
+ V("fires a bright nail-tip pulse", "flicks a compact burst forward"),
+ V("flees {target} in upright hops", "slides away as its fingertip bends"),
+ V("settles upright on its rounded tip", "curls into a stable resting posture"),
+ V("stands guard with nail raised", "patrols in deliberate fingertip hops"),
+ V("reads by tracing marks with its nail", "taps symbols in measured sequence"),
+ V("gathers life through its sensitive tip", "samples living traces with its nail"),
+ V("relieves itself through a brief tip contraction", "expels waste while curled low"),
+ V("wobbles as its fingertip flexes backward", "taps unrelated marks in confusion"),
+ V("recharges as its nail gleams", "draws energy through its rounded tip"),
+ V("flicks repeatedly under a strange urge", "curls and uncurls without pause"),
+ V("steals {target} with a quick hook", "flicks {target} toward its curled body"),
+ V("jerks as a foreign pulse bends it", "taps in an imposed rhythm"),
+ V("sees {target} in fingertip dreams", "rests as its nail glints in sleeping pulses"));
+
+ AddExtended(voices, "greg",
+ V("sings in a wobbling nasal honk", "bellows notes through a slack jaw"),
+ V("reproduces through an uneven mating dance", "begins mating with elbows flung wide"),
+ V("tends growth with alternating hand pats", "cultivates in a lopsided crouch"),
+ V("pollinates {target} with windmilling hands", "brushes pollen across {target} with spread fingers"),
+ V("trades through an overlarge two-hand wave", "nods after each exchange gesture"),
+ V("fishes with abrupt two-handed grabs", "peers for fish beneath one arm"),
+ V("hauls against one oversized shoulder", "shoves the load with both palms"),
+ V("heals {target} with clumsy hand pressure", "pats {target} with splayed fingers"),
+ V("fires a forceful open-mouthed burst", "claps both hands into a shock pulse"),
+ V("flees {target} in a crooked shuffle", "lopes away with elbows swinging"),
+ V("settles into a wide heel squat", "plants mismatched feet and sways"),
+ V("stands guard with windmilling fists", "patrols in abrupt sideways hops"),
+ V("reads with its jaw hanging open", "follows marks using a waggling finger"),
+ V("gathers life through noisy close sniffs", "pokes at living traces with one finger"),
+ V("relieves itself in a slack-limbed squat", "expels waste with shoulders bouncing"),
+ V("stares while its hands copy each other", "turns in place with one eye narrowed"),
+ V("recharges as its limbs twitch awake", "draws energy through a wide yawn"),
+ V("hops twice whenever the urge strikes", "waves both hands in repeated bursts"),
+ V("steals {target} in a windmilling grab", "snatches {target} with both hands"),
+ V("lurches as its limbs move out of sequence", "grins while foreign force jerks its elbows"),
+ V("sees {target} in lopsided dreams", "sleeps while fingers mime crooked gestures"));
+
+ AddExtended(voices, "jumpy_skull",
+ V("sings through rapid tooth clacks", "rattles a tune inside its cranium"),
+ V("reproduces through synchronized jaw bounces", "begins mating as empty sockets pulse"),
+ V("tends growth with light crown taps", "cultivates through measured jaw hops"),
+ V("pollinates {target} with bouncing jawbeats", "puffs pollen across {target} through clenched teeth"),
+ V("trades with alternating tooth clicks", "bobs its cranium during exchange"),
+ V("fishes in quick jaw-first snaps", "tracks fish through tilted sockets"),
+ V("hauls with the load between its teeth", "pushes the load using its crown"),
+ V("heals {target} with light crown pressure", "tends {target} through pulsing socket light"),
+ V("fires a bolt between open jaws", "launches force in a snapping bounce"),
+ V("flees {target} in ricocheting hops", "boings away on its springing jaw"),
+ V("settles crown-down with jaw tucked", "balances quietly on its lower teeth"),
+ V("guards with teeth clenched forward", "patrols in quick rebounding arcs"),
+ V("reads by tapping symbols with teeth", "tilts one socket across the marks"),
+ V("gathers life through hollow socket pulses", "samples living traces with chattering teeth"),
+ V("drops waste through its open jaw", "expels residue during a low bounce"),
+ V("spins while its sockets point apart", "bounces between unrelated marks"),
+ V("recharges as its sockets brighten", "draws energy through clenched teeth"),
+ V("snaps repeatedly at a strange urge", "boings in place without stopping"),
+ V("steals {target} in a teeth-first hop", "clamps {target} between chattering teeth"),
+ V("rattles as foreign light fills its sockets", "bounces in an imposed rhythm"),
+ V("sees {target} in bouncing dreams", "rests as dim scenes cross its sockets"));
+
+ AddExtended(voices, "living_house",
+ V("sings through resonant inner rooms", "rings a tune through door and shutters"),
+ V("reproduces as its foundation stones divide", "begins mating while windows pulse together"),
+ V("tends growth with careful shutter movements", "cultivates through measured foundation taps"),
+ V("pollinates {target} with rhythmic shutter beats", "fans pollen across {target} through its doorway"),
+ V("trades through opening and closing windows", "rings from within during exchange"),
+ V("fishes with a swiveling window gaze", "snaps its door near passing fish"),
+ V("hauls against its broad foundation", "draws the load through its doorway"),
+ V("heals {target} with sheltering inner warmth", "tends {target} through a softly lit window"),
+ V("fires a forceful chimney pulse", "launches a blast through its doorway"),
+ V("flees {target} on lurching foundation stones", "shuffles away as shutters flap"),
+ V("settles with every foundation stone braced", "rests squarely with shutters tucked"),
+ V("guards behind a firmly shut door", "patrols with windows swiveling"),
+ V("reads by scanning marks through its windows", "opens shutters in response to symbols"),
+ V("gathers life through listening walls", "samples living motion with swiveling windows"),
+ V("expels waste through a brief door opening", "vents residue through its chimney"),
+ V("lurches as doors open out of sequence", "turns while its windows face different ways"),
+ V("recharges as every window brightens", "draws energy through its open doorway"),
+ V("rattles shutters under a strange urge", "opens and closes its door repeatedly"),
+ V("steals {target} through a sudden doorway snap", "draws {target} past its threshold"),
+ V("shudders as foreign light fills its windows", "moves while its door slams by itself"),
+ V("sees {target} in window-lit dreams", "rests as scenes flicker behind its windows"));
+
+ AddExtended(voices, "living_plants",
+ V("sings through rustling layered leaves", "rattles seed pods in a leafy cadence"),
+ V("reproduces as living fibers intertwine", "begins mating while central buds pulse"),
+ V("tends growth with fine probing roots", "cultivates through careful vine curls"),
+ V("pollinates {target} with shaking seed pods", "dusts {target} through trembling blooms"),
+ V("trades through paired tendril gestures", "opens a bright bloom during exchange"),
+ V("fishes with sensitive trailing roots", "curls a vine near passing fish"),
+ V("hauls with several tightening vines", "pulls the load across braided roots"),
+ V("heals {target} with soft binding fibers", "tends {target} beneath layered leaves"),
+ V("fires a cluster of hardened thorns", "snaps a vine into a forceful burst"),
+ V("flees {target} on rapidly probing roots", "pulls away with leaves streaming"),
+ V("settles as roots spread beneath its body", "folds broad leaves around its stem"),
+ V("guards behind thorned vines", "patrols with roots and tendrils extended"),
+ V("reads by tracing marks with tendrils", "turns leaf surfaces toward each symbol"),
+ V("gathers life through fine root hairs", "samples living traces with sensitive leaves"),
+ V("releases waste through opening leaf pores", "sheds a dark bead from its roots"),
+ V("twists as roots pull opposite ways", "turns while leaves open and close randomly"),
+ V("recharges as every leaf unfurls", "draws energy through its central bud"),
+ V("sprouts grasping vines under a strange urge", "shakes seed pods in repeated bursts"),
+ V("steals {target} with a curling tendril", "draws {target} between layered leaves"),
+ V("jerks as dark growth crosses its stem", "moves beneath an invading root pulse"),
+ V("sees {target} in leafy dreams", "rests while leaf veins replay dim scenes"));
+
+ AddExtended(voices, "mush_animal",
+ V("sings in soft gill-puff squeaks", "chuffs a tune beneath its broad cap"),
+ V("reproduces through a pulsing spore release", "begins mating as gills synchronize"),
+ V("tends growth with quick forepaw pats", "cultivates beneath a tilted cap"),
+ V("pollinates {target} with soft spore puffs", "brushes pollen across {target} with short paws"),
+ V("trades through cap dips and chirps", "puffs its gills during exchange"),
+ V("fishes with a porous snout", "pounces near fish with both forepaws"),
+ V("hauls against its squat shoulders", "pushes the load beneath its cap"),
+ V("heals {target} with soft gill puffs", "tends {target} using quick paw presses"),
+ V("fires a dense spore burst", "launches force from beneath its cap"),
+ V("flees {target} in cap-bobbing bounds", "scampers away on stubby feet"),
+ V("settles beneath its lowered cap", "curls into a squat spongy ball"),
+ V("guards with cap tilted forward", "patrols in quick snout-led bounds"),
+ V("reads by sniffing along marks", "taps symbols with one short paw"),
+ V("gathers life through trembling gills", "samples living traces with its snout"),
+ V("relieves itself beneath its lowered cap", "expels waste as its gills contract"),
+ V("paws at spores that are not there", "turns while its gills pulse unevenly"),
+ V("recharges as its gills swell", "draws energy beneath its broad cap"),
+ V("pounces repeatedly under a strange urge", "shakes spores from its cap without pause"),
+ V("steals {target} with a quick paw swipe", "nudges {target} beneath its cap"),
+ V("convulses as dark spores fill its gills", "bounds in an imposed rhythm"),
+ V("sees {target} in spore-filled dreams", "rests as spores form fleeting scenes"));
+
+ AddExtended(voices, "mush_unit",
+ V("sings in low papery gill notes", "voices a rhythm beneath its broad cap"),
+ V("reproduces through a measured spore release", "begins mating as cap pulses synchronize"),
+ V("tends growth with pale careful hands", "cultivates through controlled spore puffs"),
+ V("pollinates {target} with a directed spore plume", "brushes pollen across {target} with pale fingers"),
+ V("trades with a formal cap tilt", "presses its palms during exchange"),
+ V("fishes with tapping fingertips", "tracks fish through trembling gills"),
+ V("hauls against its stalk-like shoulders", "moves the load with both pale hands"),
+ V("heals {target} with measured palm pressure", "tends {target} beneath a soft spore veil"),
+ V("fires a compact hardened spore burst", "launches force between both palms"),
+ V("flees {target} in long cap-led strides", "marches away as gills pulse rapidly"),
+ V("settles upright beneath its lowered cap", "folds pale arms beneath hanging gills"),
+ V("guards with forearms raised", "patrols with cap tilted forward"),
+ V("reads by tracing marks with fingertips", "studies symbols while its gills pulse"),
+ V("gathers life through sensing spores", "samples living traces with tapping hands"),
+ V("relieves itself in a cap-covered squat", "expels waste as its gills close"),
+ V("tilts its cap between unrelated marks", "stares while its gills pulse out of sequence"),
+ V("recharges as its gills brighten", "draws energy through its stalk-like body"),
+ V("casts spore puffs under a strange urge", "taps both hands in repeated patterns"),
+ V("steals {target} with both pale hands", "draws {target} beneath its lowered cap"),
+ V("jerks as black spores cross its gills", "moves while foreign pulses bend its arms"),
+ V("sees {target} in cap-shadowed dreams", "rests as gill pulses form dim scenes"));
+
+ AddExtended(voices, "necromancer",
+ V("sings in layered papery whispers", "chants while pale fragments rattle"),
+ V("reproduces through paired spectral pulses", "begins mating as pale runes synchronize"),
+ V("tends growth with grave-pale fingertips", "cultivates beneath orbiting bone light"),
+ V("pollinates {target} with circling pale fragments", "guides pollen across {target} through spectral force"),
+ V("trades through measured rune flashes", "bows its hood during exchange"),
+ V("fishes with a searching spectral wisp", "draws near fish through pale force"),
+ V("hauls within grasping spectral hands", "moves the load through pale force"),
+ V("heals {target} with binding pale runes", "tends {target} using spectral fingertips"),
+ V("fires a grave-pale force bolt", "launches grasping spectral hands"),
+ V("flees {target} inside streaming pale runes", "glides away as bone light circles faster"),
+ V("settles within a low rune glow", "rests upright as pale fragments orbit"),
+ V("guards behind spectral hands", "patrols with bone light circling"),
+ V("reads through hovering pale runes", "traces symbols with a spectral fingertip"),
+ V("gathers life through a cold spectral wisp", "samples living traces with pale runes"),
+ V("relieves itself beneath folded robes", "expels waste as orbiting fragments turn aside"),
+ V("stares while pale runes reorder themselves", "turns as spectral hands point apart"),
+ V("recharges as bone light intensifies", "draws energy through raised fingertips"),
+ V("summons empty hands under a strange urge", "casts pale runes in repeated bursts"),
+ V("steals {target} with a spectral hand", "draws {target} into circling pale light"),
+ V("convulses as foreign runes cross its robe", "moves while foreign whispers leave its mouth"),
+ V("sees {target} in bone-lit dreams", "rests while pale runes replay visions"));
+ AddExtended(voices, "plague_doctor",
+ V("sings in filtered beak notes", "hums while round lenses vibrate"),
+ V("reproduces through a measured mating display", "begins mating as masked breaths synchronize"),
+ V("tends growth with precise gloved fingers", "cultivates beneath the lowered beak"),
+ V("pollinates {target} with careful glove strokes", "brushes pollen across {target} beneath its beak"),
+ V("trades through a formal masked bow", "raises one glove during exchange"),
+ V("fishes by tracking motion through round lenses", "snaps its long beak near fish"),
+ V("hauls against its coated shoulders", "moves the load with both gloves"),
+ V("heals {target} with measured gloved pressure", "examines {target} through round lenses"),
+ V("fires a narrow beak-directed pulse", "launches force between raised gloves"),
+ V("flees {target} with coat tails snapping", "hurries away beneath the forward beak"),
+ V("settles with gloved hands clasped", "rests upright beneath the long mask"),
+ V("guards with lenses fixed forward", "patrols in quick coated strides"),
+ V("reads through round mask lenses", "traces marks with one gloved finger"),
+ V("gathers life through filtered beak breaths", "samples living traces with close lens work"),
+ V("relieves itself beneath folded coat tails", "expels waste while the beak points aside"),
+ V("tilts its mask toward unrelated marks", "fumbles as gloved hands repeat different motions"),
+ V("recharges through slow filtered breaths", "draws energy behind the beaked mask"),
+ V("taps its beak under a strange urge", "flexes both gloves in repeated patterns"),
+ V("steals {target} with a quick gloved hand", "draws {target} beneath one folded sleeve"),
+ V("jerks as foreign vapor fills the beak", "moves while its lenses flash unnaturally"),
+ V("sees {target} in masked dreams", "rests as its gloved fingers twitch"));
+
+ AddExtended(voices, "printer",
+ V("sings through sequenced electronic tones", "chatters a tune through turning gears"),
+ V("reproduces through synchronized print cycles", "begins replication as indicators pulse together"),
+ V("tends growth with measured roller passes", "cultivates beneath a traveling scan bar"),
+ V("pollinates {target} with tray-driven puffs", "feeds pollen across {target} beneath its rollers"),
+ V("trades by printing matching marks", "beeps twice during exchange"),
+ V("fishes with its traveling scan bar", "snaps its tray near detected fish"),
+ V("hauls atop its extended tray", "moves the load through humming rollers"),
+ V("heals {target} with a scanning pass", "applies measured pressure to {target} with its tray"),
+ V("fires a rapid sheet burst", "launches a pulse from its scan bar"),
+ V("flees {target} on humming rollers", "trundles away with its tray rattling"),
+ V("settles with print head parked", "rests with tray tucked closed"),
+ V("guards with scan bar traveling", "patrols on steady humming rollers"),
+ V("reads through its narrow glass slit", "copies symbols beneath the scan bar"),
+ V("gathers life through calibrated scans", "samples living traces with its glass slit"),
+ V("ejects a strip of dark residue", "purges waste through its lower tray"),
+ V("feeds blank strips without printing", "flashes conflicting indicators"),
+ V("recharges as its display brightens", "draws power into humming internal gears"),
+ V("cycles its tray under a strange urge", "prints repeated marks without pause"),
+ V("steals {target} through snapping rollers", "draws {target} into its open tray"),
+ V("shudders as foreign marks fill its display", "runs an imposed sequence of gear turns"),
+ V("renders {target} in dim display dreams", "rests while its print head twitches"));
+
+ AddExtended(voices, "skeleton",
+ V("sings through hollow jaw clacks", "rattles a tune across bare ribs"),
+ V("reproduces through synchronized bone taps", "begins mating as rib cages resonate"),
+ V("tends growth with bony fingertips", "cultivates through alternating foot rakes"),
+ V("pollinates {target} with rib-driven puffs", "brushes pollen across {target} with finger bones"),
+ V("trades through measured jaw clicks", "raises a bare hand during exchange"),
+ V("fishes with empty sockets lowered", "snaps bare teeth near fish"),
+ V("hauls against its exposed rib cage", "moves the load with hooked bone fingers"),
+ V("heals {target} with careful bone pressure", "tends {target} using jointed fingertips"),
+ V("fires a rattling bone burst", "launches force through its open rib cage"),
+ V("flees {target} in clattering strides", "scatters away and reassembles farther on"),
+ V("settles into a neatly folded bone pile", "rests with hands hooked through ribs"),
+ V("guards with sharpened forearms raised", "patrols in hollow clattering steps"),
+ V("reads by tapping marks with finger bones", "tilts empty sockets across symbols"),
+ V("gathers life through vibrating bare feet", "samples living motion with empty sockets"),
+ V("drops dry waste through its pelvis", "expels residue between loose ribs"),
+ V("reassembles with bones misplaced", "turns while its jaw chatters at nothing"),
+ V("recharges as its bones resonate", "draws energy through its empty mouth"),
+ V("juggles knuckles under a strange urge", "detaches and replaces its jaw repeatedly"),
+ V("steals {target} with hooked finger bones", "draws {target} behind its rib cage"),
+ V("rattles as foreign light fills its sockets", "marches in an imposed bone rhythm"),
+ V("sees {target} in rattling dreams", "rests as dim scenes cross its sockets"));
+
+ AddExtended(voices, "tumor_monster_animal",
+ V("sings through several wet throats", "gurgles a rhythm across pulsing growths"),
+ V("reproduces as fleshy buds divide", "begins mating while nodules pulse together"),
+ V("tends growth with quick uneven paws", "cultivates beneath probing tendrils"),
+ V("pollinates {target} with trembling nodules", "brushes pollen across {target} with extra limbs"),
+ V("trades through pulsing sensory lobes", "raises a hooked limb during exchange"),
+ V("fishes with a ring of wet nostrils", "snaps clustered mouths near fish"),
+ V("hauls against its swollen shoulder", "moves the load with hooked extra limbs"),
+ V("heals {target} with soft tissue pressure", "tends {target} using probing tendrils"),
+ V("fires a hardened tissue barb", "launches force from a pulsing nodule"),
+ V("flees {target} on scrambling uneven limbs", "lopes away with growths shaking"),
+ V("settles around its largest pulsing mass", "folds several limbs beneath its body"),
+ V("guards behind hardened growths", "patrols with wet nostrils testing"),
+ V("reads by touching marks with tendrils", "turns clustered eyes across symbols"),
+ V("gathers life through sensitive nodules", "samples living traces with wet nostrils"),
+ V("expels waste through a puckered opening", "releases residue beneath folded limbs"),
+ V("stumbles as its limbs choose different paths", "snaps mouths while clustered eyes cross"),
+ V("recharges as its nodules throb", "draws energy through several mouths"),
+ V("paws at its flank under a strange urge", "twitches extra limbs in repeated bursts"),
+ V("steals {target} with a hooked extra limb", "draws {target} beneath a sensory lobe"),
+ V("convulses as dark pulses cross its growths", "moves while foreign force tightens its tendrils"),
+ V("sees {target} in pulsing dreams", "rests while clustered eyes flicker"));
+
+ AddExtended(voices, "tumor_monster_unit",
+ V("sings in overlapping throat pitches", "drums a rhythm across hardened nodules"),
+ V("reproduces as smaller hands interlace", "begins mating while clustered eyes synchronize"),
+ V("tends growth with three careful hands", "cultivates through a tasting tendril"),
+ V("pollinates {target} with several quick palms", "brushes pollen across {target} with extra fingers"),
+ V("trades through alternating hand signs", "blinks clustered eyes during exchange"),
+ V("fishes with a thin tasting tendril", "grabs near fish with a smaller hand"),
+ V("hauls against its oversized arm", "moves the load using three hands"),
+ V("heals {target} with several measured palms", "tends {target} through soft tissue pressure"),
+ V("fires a dense tissue pulse", "launches force from its oversized palm"),
+ V("flees {target} on mismatched legs", "lumbers away with extra arms swinging"),
+ V("settles with every hand braced", "folds extra limbs around its torso"),
+ V("guards behind an oversized forearm", "patrols with clustered eyes blinking"),
+ V("reads by tracing marks with three hands", "turns clustered eyes across symbols"),
+ V("gathers life through a tasting tendril", "samples living traces with clustered eyes"),
+ V("expels waste through a side opening", "releases residue beneath its swollen torso"),
+ V("reaches in several directions at once", "stares while clustered eyes blink out of sequence"),
+ V("recharges as its growths pulse faster", "draws energy into its swollen frame"),
+ V("wrestles its own hands under a strange urge", "drums nodules in repeated bursts"),
+ V("steals {target} with its smaller hands", "draws {target} behind its oversized arm"),
+ V("jerks as foreign pulses cross its abdomen", "moves while clustered eyes glow darkly"),
+ V("sees {target} in many-handed dreams", "rests while its nodules replay slow pulses"));
+
+ AddExtended(voices, "white_mage",
+ V("sings in clear pearl-bright notes", "chants while pale sigils pulse"),
+ V("reproduces through synchronized light patterns", "begins mating as pearl glows intermingle"),
+ V("tends growth with open glowing palms", "cultivates beneath woven pale light"),
+ V("pollinates {target} with pearl-bright motes", "guides pollen across {target} through pale light"),
+ V("trades through ordered sigil flashes", "bows its bright-edged hood during exchange"),
+ V("fishes with a searching luminous mote", "draws near fish through pale force"),
+ V("hauls within woven pale light", "moves the load between open palms"),
+ V("heals {target} with cleansing light", "tends {target} beneath pearl radiance"),
+ V("fires a concentrated pale pulse", "launches force between open palms"),
+ V("flees {target} inside streaming pale light", "glides away as sigils brighten"),
+ V("settles within ordered pale sigils", "rests with both palms open"),
+ V("guards behind a shining barrier", "patrols with pearl motes circling"),
+ V("reads as pale light reveals marks", "studies symbols through ordered sigils"),
+ V("gathers life through a luminous mote", "samples living traces with pearl light"),
+ V("relieves itself beneath a pale veil", "releases waste as sigils turn aside"),
+ V("flickers while sigils reorder themselves", "turns as pearl motes point apart"),
+ V("recharges as robe edges brighten", "draws energy through open palms"),
+ V("folds light under a strange urge", "casts empty sigils in repeated bursts"),
+ V("steals {target} with a pale force pulse", "draws {target} between open palms"),
+ V("shudders as dark sigils cross its robe", "moves while foreign light bends its hands"),
+ V("sees {target} in pearl-lit dreams", "rests as pale sigils replay visions"));
+
+ AddExtended(voices, "zombie",
+ V("sings in a broken throaty moan", "groans a rhythm through its crooked jaw"),
+ V("reproduces through a stiff mating display", "begins mating as dead limbs twitch together"),
+ V("tends growth with slow stiff fingers", "cultivates through repeated palm presses"),
+ V("pollinates {target} with dragging hand sweeps", "brushes pollen across {target} with stiff fingers"),
+ V("trades through a delayed hand raise", "groans once during exchange"),
+ V("fishes with an unbroken forward stare", "snaps broken teeth near fish"),
+ V("hauls against its stiff shoulders", "pushes the load with both rigid arms"),
+ V("heals {target} with slow hand pressure", "tends {target} using stiff fingertips"),
+ V("fires a hoarse mouth pulse", "launches force with both reaching hands"),
+ V("flees {target} in a dragging lurch", "shambles away with arms swinging"),
+ V("settles into a limp heap", "rests upright with jaw hanging"),
+ V("guards with both stiff hands raised", "patrols in slow dragging steps"),
+ V("reads with an unbroken stare", "traces marks using one rigid finger"),
+ V("gathers life through a ruined nose", "samples living traces with broken teeth"),
+ V("relieves itself without changing its stare", "expels waste in a stiff crouch"),
+ V("turns toward unrelated movement", "reaches while its feet remain planted"),
+ V("recharges as dead limbs twitch", "draws energy through its open mouth"),
+ V("reaches repeatedly under a strange urge", "rocks side to side without pause"),
+ V("steals {target} with both stiff hands", "draws {target} against its rigid chest"),
+ V("jerks as foreign force straightens it", "marches while dark pulses cross its limbs"),
+ V("sees {target} in twitching dreams", "rests as its fingers grasp at dim visions"));
+
+ AddExtended(voices, "snowman",
+ V("sings in cold hollow crunches", "rumbles a tune through packed sections"),
+ V("reproduces as packed sections bud", "begins mating while cold pulses synchronize"),
+ V("tends growth with stick-like limb taps", "cultivates through careful body pressure"),
+ V("pollinates {target} with broad limb sweeps", "brushes pollen across {target} with packed hands"),
+ V("trades through a rounded body dip", "waves one stick-like limb during exchange"),
+ V("fishes through pulsing cold-body effects", "scoops near fish with packed limbs"),
+ V("hauls against its rounded lower section", "pushes the load with both stick-like limbs"),
+ V("heals {target} with numbing body pressure", "tends {target} using packed hands"),
+ V("fires a burst of packed body snow", "launches cold force between raised limbs"),
+ V("flees {target} in a swaying waddle", "pivots away as packed sections wobble"),
+ V("settles into a stable stacked posture", "rests with stick-like limbs tucked"),
+ V("guards with both limbs spread", "patrols in slow rounded pivots"),
+ V("reads by tapping marks with one limb", "rotates its upper section across symbols"),
+ V("gathers life through cold-body pulses", "samples living traces with packed hands"),
+ V("releases waste beneath its lower section", "expels dark residue while sections compress"),
+ V("rotates its sections in conflicting directions", "points both limbs toward unrelated marks"),
+ V("recharges as its packed body brightens", "draws energy through stacked sections"),
+ V("twirls both limbs under a strange urge", "rotates its upper section repeatedly"),
+ V("steals {target} with a sweeping limb", "draws {target} against its rounded body"),
+ V("shudders as dark cold pulses spread", "moves while foreign force twists its sections"),
+ V("sees {target} in cold-pulsed dreams", "rests while cold-body pulses replay visions"));
+ }
+}
diff --git a/IdleSpectator/ActivitySpeciesVoices.Fantasy.Specialized.cs b/IdleSpectator/ActivitySpeciesVoices.Fantasy.Specialized.cs
new file mode 100644
index 0000000..adc2876
--- /dev/null
+++ b/IdleSpectator/ActivitySpeciesVoices.Fantasy.Specialized.cs
@@ -0,0 +1,333 @@
+using System.Collections.Generic;
+
+namespace IdleSpectator;
+
+public static partial class ActivitySpeciesVoiceCatalog
+{
+ private static void AddFantasySpecializedVoices(Dictionary voices)
+ {
+ AddSpecialized(voices, "UFO",
+ V("kindles flame beneath a focused heat ray", "spreads fire with a sweeping thermal beam"),
+ V("smothers flame beneath a cooling field", "dims fire with a pulsing suppression ray"),
+ V("gathers with kin through synchronized signals", "joins kin beneath matching light pulses"),
+ V("draws observed essence through a scanning beam", "samples visible life force beneath its hull"),
+ V("searches with a narrow scan", "reaches with a controlled lifting field"),
+ V("sounds a rising electronic trill", "pulses a wavering alarm tone"),
+ V("blasts clipped synthetic notes", "flashes harsh signals with a metallic buzz"));
+
+ AddSpecialized(voices, "alien",
+ V("sparks flame between clicking fingertips", "spreads fire with crackling wrist pulses"),
+ V("presses flame down with splayed hands", "quenches fire beneath a bioelectric pulse"),
+ V("gathers with kin through rapid clicks", "joins kin in mirrored body pulses"),
+ V("draws observed essence through tasting fingertips", "samples visible life force with its mouthparts"),
+ V("searches with four darting hands", "reaches with narrow grasping fingers"),
+ V("cries through a trembling throat sac", "releases a chain of bubbling chirps"),
+ V("chatters in jagged throat clicks", "snaps out a harsh clicking burst"));
+
+ AddSpecialized(voices, "angle",
+ V("kindles flame with holy radiance", "spreads fire through a surge of divine light"),
+ V("suppresses flame beneath sacred brilliance", "dims fire within steady celestial light"),
+ V("gathers with kin through shared holy radiance", "joins kin beneath shared divine light"),
+ V("draws life essence into holy radiance", "channels life force through celestial light"),
+ V("searches beneath revealing sacred light", "reaches through a pulse of divine radiance"),
+ V("sounds a sustained celestial chime", "releases a trembling hymn of light"),
+ V("voices sharp sacred tones", "flares with a harsh divine cadence"));
+
+ AddSpecialized(voices, "assimilator",
+ V("kindles flame with a searing membrane pulse", "spreads fire through reaching hot tendrils"),
+ V("smothers flame beneath a widening membrane", "draws fire into heat-drinking tissue"),
+ V("gathers with kin through braided tendrils", "joins kin by matching surface pulses"),
+ V("draws observed essence through tasting filaments", "absorbs visible life force beneath rippling tissue"),
+ V("searches with many probing feelers", "reaches through a forming grasping limb"),
+ V("cries through several borrowed throats", "releases mismatched wails across its surface"),
+ V("barks layered borrowed syllables", "snaps through a chorus of harsh voices"));
+
+ AddSpecialized(voices, "civ_crystal_golem",
+ V("kindles flame with a white-hot core pulse", "spreads fire through radiant crystal seams"),
+ V("suppresses flame beneath cooling crystal light", "draws fire into dimming core seams"),
+ V("gathers with kin through resonant core hums", "joins kin as inner lights pulse together"),
+ V("draws observed essence through luminous facets", "channels visible life force into its core"),
+ V("searches with refracted inner light", "reaches with broad crystalline hands"),
+ V("cries in a deep crystalline peal", "rings from every facet in trembling notes"),
+ V("booms in sharp core-deep pulses", "clashes its facets through a harsh resonance"));
+
+ AddSpecialized(voices, "cold_one",
+ V("kindles flame with a concentrated pale spark", "spreads fire from a pale crackling palm"),
+ V("smothers flame beneath hardening rime", "quenches fire with a numbing cold pulse"),
+ V("gathers with kin through clicking frozen teeth", "joins kin as cold vapors mingle"),
+ V("draws observed essence through a whitening palm", "pulls visible life force into its rime"),
+ V("searches with heat-sensitive fingers", "reaches with a frost-rimmed hand"),
+ V("cries in a thin ice-cracking shriek", "releases a long chime through frozen teeth"),
+ V("snaps out brittle frozen clicks", "rasps through a burst of cracking rime"));
+
+ AddSpecialized(voices, "crabzilla",
+ V("kindles flame between grinding mouthplates", "spreads fire with a vast heated breath"),
+ V("smothers flame beneath a colossal pincer", "quenches fire with a crushing shell-borne pressure"),
+ V("gathers with kin through booming pincer clacks", "joins kin as armored shells resonate"),
+ V("draws observed essence through sweeping eye stalks", "pulls visible life force between its mouthplates"),
+ V("searches with swiveling eye stalks", "reaches with a colossal open pincer"),
+ V("cries in a shell-rattling bellow", "clacks its mouthparts in thunderous pulses"),
+ V("snaps both pincers in a harsh barrage", "grinds out a booming plated rasp"));
+
+ AddSpecialized(voices, "crystal_sword",
+ V("kindles flame along its glowing edge", "spreads fire through a searing blade pulse"),
+ V("parts flame with a cooling edge", "draws fire into dimming crystal facets"),
+ V("gathers with kin through matching crystal peals", "joins kin as suspended blades resonate"),
+ V("draws observed essence along its fuller", "channels visible life force into its jeweled guard"),
+ V("searches with its point slowly testing", "reaches with a hovering hilt"),
+ V("cries in a high sustained ring", "trembles through a descending crystal peal"),
+ V("rings in sharp metallic bursts", "shivers its edge through a harsh bright note"));
+
+ AddSpecialized(voices, "demon",
+ V("kindles flame between blackened claws", "spreads fire with a scorching breath"),
+ V("smothers flame inside a smoking palm", "draws fire beneath ember-hot skin"),
+ V("gathers with kin through heated snarls", "joins kin as smoking bodies press close"),
+ V("draws observed essence through glowing fangs", "pulls visible life force into its hot core"),
+ V("searches with heat-sensing nostrils", "reaches with hooked claws"),
+ V("cries in a cracked furnace howl", "releases a throat-deep scorching wail"),
+ V("barks harsh syllables through smoking fangs", "snarls in short ember-spitting bursts"));
+
+ AddSpecialized(voices, "dragon",
+ V("kindles flame behind serrated teeth", "spreads fire with a broad searing breath"),
+ V("smothers flame beneath a plated foreclaw", "draws fire back through flared nostrils"),
+ V("gathers with kin through chest-deep rumbles", "joins kin as plated bodies resonate"),
+ V("draws observed essence through flared nostrils", "pulls visible life force between glowing teeth"),
+ V("searches with unblinking eyes", "reaches with an open foreclaw"),
+ V("cries in a vast chest-deep roar", "releases a long horn-rattling bellow"),
+ V("snaps out thunderous guttural syllables", "growls through bursts of bright sparks"));
+
+ AddSpecialized(voices, "druid",
+ V("kindles flame between bark-lined palms", "spreads fire through glowing sap"),
+ V("smothers flame beneath unfurling leaves", "draws fire into darkening living grain"),
+ V("gathers with kin through rustling leaf-signals", "joins kin as living fibers intertwine"),
+ V("draws observed essence through root-like fingers", "pulls visible life force into living grain"),
+ V("searches with curling rootlets", "reaches with a vine-wrapped hand"),
+ V("cries through a dry leafy rasp", "releases a low wooden groan"),
+ V("utters clipped syllables through rustling leaves", "snaps living grain in a harsh cadence"));
+
+ AddSpecialized(voices, "evil_mage",
+ V("kindles flame from violet fingertips", "spreads fire through crawling dark sparks"),
+ V("smothers flame beneath folded shadow", "draws fire into a dim violet aura"),
+ V("gathers with kin through layered whispers", "joins kin as dark auras overlap"),
+ V("draws observed essence into a shadowed palm", "pulls visible life force through violet sparks"),
+ V("searches through a circling violet eye", "reaches with a shadow-wrapped hand"),
+ V("cries in a thin echoing rasp", "releases a wavering chorus of whispers"),
+ V("hisses clipped words through violet static", "barks a harsh syllable as shadows pulse"));
+
+ AddSpecialized(voices, "fairy",
+ V("kindles flame from sparkling fingertips", "spreads fire through pulsing bright motes"),
+ V("dims flame beneath cooling shimmer", "smothers fire inside a veil of motes"),
+ V("gathers with kin through matching light pulses", "joins kin as tiny glows mingle"),
+ V("draws observed essence into sparkling motes", "pulls visible life force through its shimmer"),
+ V("searches with flickering motes", "reaches with both tiny hands"),
+ V("cries in a piercing bell-like trill", "releases a trembling chain of tiny notes"),
+ V("chirps sharp syllables in rapid bursts", "flashes harshly through a clipped trill"));
+
+ AddSpecialized(voices, "fire_elemental",
+ V("kindles flame from its white-hot core", "spreads fire through reaching tongues of flame"),
+ V("draws loose flame back into its core", "banks fire beneath a dim ember shell"),
+ V("gathers with kin as sparks intermingle", "joins kin through merging flame pulses"),
+ V("draws observed essence into its burning core", "pulls visible life force through licking flames"),
+ V("searches with thin reaching flames", "reaches with a forming arm of fire"),
+ V("cries in a roaring cascade of crackles", "releases a long furnace-like howl"),
+ V("snaps in harsh explosive pops", "flares through a jagged crackling burst"));
+
+ AddSpecialized(voices, "fire_elemental_blob",
+ V("kindles flame from a bubbling hot lobe", "spreads fire through clinging molten droplets"),
+ V("draws flame beneath a cooling crust", "smothers fire inside its soft molten body"),
+ V("gathers with kin through shared bubbling pulses", "joins kin as molten sides mingle"),
+ V("draws observed essence through a glowing pseudopod", "pulls visible life force beneath its liquid surface"),
+ V("searches with a wavering hot lobe", "reaches with a stretching pseudopod"),
+ V("cries in a wet chain of fiery pops", "gurgles through a long bubbling wail"),
+ V("bursts in harsh sputtering pops", "slaps its molten surface through a jagged hiss"));
+
+ AddSpecialized(voices, "fire_elemental_horse",
+ V("kindles flame between glowing teeth", "spreads fire through a blazing breath"),
+ V("draws flame into its ember-bright muzzle", "stamps fire beneath a cooling hoof"),
+ V("gathers with kin through furnace nickers", "joins kin as fiery manes mingle"),
+ V("draws observed essence through flared nostrils", "pulls visible life force into its burning chest"),
+ V("searches with a glowing muzzle", "reaches with ember-bright teeth"),
+ V("cries in a rising furnace whinny", "releases a long crackling nicker"),
+ V("snorts sharp bursts of sparks", "barks a harsh note through glowing teeth"));
+
+ AddSpecialized(voices, "fire_elemental_slug",
+ V("kindles flame beneath its glowing mantle", "spreads fire through a molten body ribbon"),
+ V("draws flame under a cooled black crust", "smothers fire beneath its broad heated underside"),
+ V("gathers with kin through touching flame feelers", "joins kin as glowing mantles pulse together"),
+ V("draws observed essence through heat-sensitive feelers", "pulls visible life force beneath its mantle"),
+ V("searches with sweeping flame feelers", "reaches with an extended glowing mantle"),
+ V("cries in a long wet sizzle", "releases a bubbling crackle through its mantle"),
+ V("pops in sharp hissing bursts", "rasps through a harsh chain of sizzles"));
+
+ AddSpecialized(voices, "fire_elemental_snake",
+ V("kindles flame behind a forked fire tongue", "spreads fire along its blazing coils"),
+ V("draws flame into banked coils", "smothers fire beneath overlapping ember scales"),
+ V("gathers with kin through braided burning coils", "joins kin as forked sparks pulse together"),
+ V("draws observed essence through its split flame tongue", "pulls visible life force along glowing coils"),
+ V("searches with a flickering forked tongue", "reaches with an opening fiery coil"),
+ V("cries in a long crackling hiss", "rattles out a wavering chain of pops"),
+ V("hisses in clipped searing bursts", "snaps its flame tongue through harsh crackles"));
+
+ AddSpecialized(voices, "fire_skull",
+ V("kindles flame inside its hollow mouth", "spreads fire through snapping blazing jaws"),
+ V("draws flame into empty sockets", "smothers fire beneath its dimming crown"),
+ V("gathers with kin through synchronized jaw clacks", "joins kin as hollow sockets flare together"),
+ V("draws observed essence through empty sockets", "pulls visible life force between blazing teeth"),
+ V("searches with fixed hollow sockets", "reaches with opening jaws"),
+ V("cries in a hollow fire-fed howl", "cackles through a trembling loose jaw"),
+ V("clacks out harsh tooth-borne bursts", "barks through a flare of roaring fire"));
+
+ AddSpecialized(voices, "ghost",
+ V("kindles pale flame in a spectral palm", "spreads fire through a wavering aura"),
+ V("smothers flame inside its translucent form", "dims fire beneath a chilling spectral pulse"),
+ V("gathers with kin through overlapping outlines", "joins kin as spectral auras mingle"),
+ V("draws observed essence into its hollow form", "pulls visible life force through a translucent hand"),
+ V("searches through a wavering outline", "reaches with a spectral hand"),
+ V("cries in a long airy wail", "moans through a trembling echo"),
+ V("rasps in clipped hollow syllables", "warbles through a harsh spectral pulse"));
+
+ AddSpecialized(voices, "god_finger",
+ V("kindles flame beneath its rounded tip", "spreads fire with a heated nail pulse"),
+ V("presses flame beneath its broad tip", "draws fire into a dimming nail"),
+ V("gathers with kin through fingertip taps", "joins kin as nails pulse together"),
+ V("draws observed essence through its sensitive tip", "pulls visible life force beneath its nail"),
+ V("searches with its tip flexing", "reaches with a slowly curling digit"),
+ V("cries through rapid self-drumming taps", "trembles out a rolling nail-borne rattle"),
+ V("taps out a harsh clipped sequence", "snaps its nail in sharp repeated bursts"));
+
+ AddSpecialized(voices, "greg",
+ V("kindles flame between rubbing palms", "spreads fire through a hot open-mouthed breath"),
+ V("smothers flame beneath both broad hands", "blows a forceful breath across the fire"),
+ V("gathers with kin through matching nasal honks", "joins kin in close shoulder contact"),
+ V("draws observed essence through spread fingertips", "pulls visible life force into its open mouth"),
+ V("searches with unblinking eyes", "reaches with both open hands"),
+ V("cries in a long nasal honk", "wheezes through a trembling throat"),
+ V("barks blunt syllables through clenched teeth", "snorts a harsh broken cadence"));
+
+ AddSpecialized(voices, "jumpy_skull",
+ V("kindles flame between chattering teeth", "spreads fire through snapping hot jaws"),
+ V("smothers flame beneath its heavy cranium", "draws fire into hollow sockets"),
+ V("gathers with kin through rapid jaw clacks", "joins kin as bare craniums rattle together"),
+ V("draws observed essence through hollow sockets", "pulls visible life force between chattering teeth"),
+ V("searches with tilted empty sockets", "reaches with an opening jaw"),
+ V("cries in a hollow rattling shriek", "cackles through uncontrollable jaw clacks"),
+ V("snaps out a harsh tooth-clacking barrage", "rattles its cranium through clipped bursts"));
+
+ AddSpecialized(voices, "living_house",
+ V("kindles flame within its glowing interior", "spreads fire through heat pulsing from its openings"),
+ V("smothers flame behind closing shutters", "draws fire into a darkened interior"),
+ V("gathers with kin through resonant inner bells", "joins kin as windows pulse together"),
+ V("draws observed essence through open windows", "pulls visible life force into its interior"),
+ V("searches through swiveling windows", "reaches with an opening doorway"),
+ V("cries through rattling windows and walls", "releases a long foundation-deep groan"),
+ V("slams its openings in harsh succession", "rings a sharp booming inner bell"));
+
+ AddSpecialized(voices, "living_plants",
+ V("kindles flame through heating sap", "spreads fire along glowing vines"),
+ V("smothers flame beneath broad folded leaves", "draws fire into thick cooling sap"),
+ V("gathers with kin through intertwining roots", "joins kin as leaf pulses synchronize"),
+ V("draws observed essence through fine root hairs", "pulls visible life force into its central bud"),
+ V("searches with probing roots", "reaches with a curling vine"),
+ V("cries in a long rustling rasp", "releases a dry pod-rattling wail"),
+ V("snaps leaves in a harsh cadence", "rattles dry pods through clipped bursts"));
+
+ AddSpecialized(voices, "mush_animal",
+ V("kindles flame through a hot spore puff", "spreads fire beneath a pulsing cap"),
+ V("smothers flame beneath its broad damp cap", "quenches fire with a dense cooling spore cloud"),
+ V("gathers with kin through synchronized gill puffs", "joins kin as broad caps press together"),
+ V("draws observed essence through porous gills", "pulls visible life force beneath its cap"),
+ V("searches with a porous snout", "reaches with quick forepaws"),
+ V("cries in a damp bubbling squeal", "chuffs through rapidly pulsing gills"),
+ V("snaps flat teeth through harsh squeaks", "puffs clipped rasping bursts from its gills"));
+
+ AddSpecialized(voices, "mush_unit",
+ V("kindles flame in a heated spore puff", "spreads fire beneath its broad cap"),
+ V("smothers flame under pulsing damp gills", "quenches fire with a dense cooling spore veil"),
+ V("gathers with kin through shared spore pulses", "joins kin as broad caps touch"),
+ V("draws observed essence through hanging gills", "pulls visible life force beneath its cap"),
+ V("searches with trembling fingertips", "reaches with a pale open hand"),
+ V("cries in a low papery wail", "releases a trembling puff through its gills"),
+ V("rasps clipped syllables beneath its cap", "snaps out harsh papery puffs"));
+
+ AddSpecialized(voices, "necromancer",
+ V("kindles grave-pale flame in one hand", "spreads fire through cold spectral wisps"),
+ V("smothers flame beneath a wan magic pulse", "draws fire into circling pale light"),
+ V("gathers with kin through layered bone-dry whispers", "joins kin as pale auras overlap"),
+ V("draws observed essence into a raised hand", "pulls visible life force through grave-pale magic"),
+ V("searches through a floating spectral wisp", "reaches with a pale open hand"),
+ V("cries in a papery hollow wail", "releases a chorus of rattling whispers"),
+ V("hisses clipped syllables through pale static", "rasps in a harsh bone-dry cadence"));
+
+ AddSpecialized(voices, "plague_doctor",
+ V("kindles flame through a narrow filtered breath", "spreads fire from a heated gloved palm"),
+ V("smothers flame beneath both gloved hands", "quenches fire through a cooling filtered breath"),
+ V("gathers with kin through measured beak clicks", "joins kin as masked heads incline together"),
+ V("draws observed essence through round mask lenses", "pulls visible life force into the narrow beak"),
+ V("searches through round dark lenses", "reaches with a gloved hand"),
+ V("cries in a muffled hollow rasp", "releases a long filtered wheeze"),
+ V("barks clipped syllables behind the beak", "snaps out harsh muffled sounds"));
+
+ AddSpecialized(voices, "printer",
+ V("kindles flame beneath an overheating print head", "spreads fire through a hot internal pulse"),
+ V("smothers flame beneath a cooling internal vent", "suppresses fire with a pulsing thermal cutoff"),
+ V("gathers with kin through synchronized status beeps", "joins kin as indicator lights match"),
+ V("draws observed essence through its scan bar", "samples visible life force across its glass slit"),
+ V("searches with a traveling scan light", "reaches with its extending tray"),
+ V("cries in a wavering electronic whine", "chatters its gears through a broken alarm"),
+ V("blasts sharp electronic tones", "rattles out a harsh mechanical sequence"));
+
+ AddSpecialized(voices, "skeleton",
+ V("kindles flame inside its hollow rib cage", "spreads fire through snapping bare fingers"),
+ V("smothers flame beneath interlocked bones", "draws fire into empty sockets"),
+ V("gathers with kin through matching bone rattles", "joins kin as bare ribs clack together"),
+ V("draws observed essence through empty sockets", "pulls visible life force into its rib cage"),
+ V("searches with its hollow gaze", "reaches with a bare jointed hand"),
+ V("cries in a hollow jaw-flapping wail", "rattles from skull to toes in long pulses"),
+ V("clacks teeth in a harsh barrage", "snaps finger bones through clipped beats"));
+
+ AddSpecialized(voices, "tumor_monster_animal",
+ V("kindles flame from a heated pulsing nodule", "spreads fire through a searing tendril"),
+ V("smothers flame beneath a broad fleshy lobe", "draws fire into cooling swollen tissue"),
+ V("gathers with kin through matching tissue pulses", "joins kin as sensory lobes touch"),
+ V("draws observed essence through wet nostrils", "pulls visible life force into a pulsing growth"),
+ V("searches with sensitive nodules", "reaches with a twitching tendril"),
+ V("cries through several throats at once", "releases a wet overlapping wail"),
+ V("snaps crowded teeth through harsh gurgles", "barks from several mouths in clipped bursts"));
+
+ AddSpecialized(voices, "tumor_monster_unit",
+ V("kindles flame in a throbbing heated palm", "spreads fire through a searing extra limb"),
+ V("smothers flame beneath an oversized hand", "draws fire into cooling pulsing tissue"),
+ V("gathers with kin through synchronized nodules", "joins kin as sensory tendrils touch"),
+ V("draws observed essence through clustered eyes", "pulls visible life force into a pulsing abdomen"),
+ V("searches with clustered blinking eyes", "reaches with several open hands"),
+ V("cries in overlapping throaty pitches", "releases a wet wail from several vents"),
+ V("barks clipped sounds from a sideways mouth", "snorts through several vents in harsh bursts"));
+
+ AddSpecialized(voices, "white_mage",
+ V("kindles flame in a pearl-bright palm", "spreads fire through cleansing light"),
+ V("suppresses flame beneath a pale luminous veil", "dims fire within cooling pearl light"),
+ V("gathers with kin through shared luminous pulses", "joins kin as pale auras overlap"),
+ V("draws observed essence through an open palm", "pulls visible life force into pearl-white light"),
+ V("searches through a revealing luminous mote", "reaches with a light-wrapped hand"),
+ V("cries in a clear sustained ring", "releases a trembling luminous hum"),
+ V("voices clipped ringing syllables", "flashes sharply through a harsh bright cadence"));
+
+ AddSpecialized(voices, "zombie",
+ V("kindles flame between stiff rubbing hands", "spreads fire through a hot broken-toothed breath"),
+ V("smothers flame beneath both stiff hands", "presses its cold body against the fire"),
+ V("gathers with kin through matching groans", "joins kin in close cold contact"),
+ V("draws observed essence through a ruined nose", "pulls visible life force into its open mouth"),
+ V("searches with an unbroken stare", "reaches with both stiff hands"),
+ V("cries through a long crooked-jaw groan", "gurgles in a wavering broken-throat call"),
+ V("barks hoarse clipped syllables", "snaps broken teeth through a harsh rasp"));
+
+ AddSpecialized(voices, "snowman",
+ V("kindles flame between its cold stick-like limbs", "spreads fire through a heat pulse from its packed body"),
+ V("smothers flame beneath its packed cold body", "quenches fire with a burst of its own cold powder"),
+ V("gathers with kin through matching body tremors", "joins kin as packed sides press together"),
+ V("draws observed essence through its rounded upper body", "pulls visible life force into its packed middle"),
+ V("searches by rotating its upper body", "reaches with both stick-like limbs"),
+ V("cries in a powdery body-deep crunch", "releases a long packed-body rumble"),
+ V("snaps its stick-like limbs in harsh beats", "crunches through a clipped rumbling burst"));
+ }
+}
diff --git a/IdleSpectator/ActivitySpeciesVoices.Fantasy.cs b/IdleSpectator/ActivitySpeciesVoices.Fantasy.cs
index 611e0cb..14e8431 100644
--- a/IdleSpectator/ActivitySpeciesVoices.Fantasy.cs
+++ b/IdleSpectator/ActivitySpeciesVoices.Fantasy.cs
@@ -31,16 +31,16 @@ public static partial class ActivitySpeciesVoiceCatalog
V("sorts material by shape with four quick hands", "fits task material with narrow fingers"));
Add(voices, "angle",
- V("slides point-first along a rigid path", "turns through a perfectly sharp corner"),
- V("balances on one luminous vertex", "hangs motionless between intersecting lines"),
- V("folds and unfolds into crisp new shapes", "traces a tiny polygon with luminous edges"),
- V("absorbs energy through its luminous edges", "draws energy into its center"),
- V("flattens into a dim, closed figure", "rests with every edge neatly aligned"),
- V("hunts {target} with straight geometric feelers", "hunts {target} from a rotating vertex"),
- V("attacks {target} with a razor-straight edge", "attacks {target} by closing its angles"),
- V("meets another outline edge to edge", "signals by changing the count of its corners"),
- V("chimes with laughter from every taut edge", "chimes a laugh in two exact intervals"),
- V("scores precise boundaries across task material", "squares a precision task one line at a time"));
+ V("glides beneath a mantle of holy radiance", "advances as divine light gathers around it"),
+ V("stands watch in unwavering celestial brilliance", "holds vigil within pale radiance"),
+ V("sends brief gleams through its aura", "pulses its radiant presence in a bright cadence"),
+ V("draws energy into its divine glow", "brightens as holy power fills its presence"),
+ V("dims to a quiet celestial ember", "rests within a gently fading aura"),
+ V("hunts {target} through revealing holy light", "hunts {target} as its radiance intensifies"),
+ V("attacks {target} with a surge of divine light", "attacks {target} in cleansing brilliance"),
+ V("greets nearby company with a sacred glow", "answers another presence with radiant pulses"),
+ V("chimes with bright celestial laughter", "laughs as celestial light ripples outward"),
+ V("casts divine radiance over its labor", "shapes each effort with steady divine light"));
Add(voices, "assimilator",
V("pulls itself forward on braided tendrils", "rolls its shifting bulk in measured surges"),
diff --git a/IdleSpectator/ActivitySpeciesVoices.Invertebrates.Extended.cs b/IdleSpectator/ActivitySpeciesVoices.Invertebrates.Extended.cs
new file mode 100644
index 0000000..0b77911
--- /dev/null
+++ b/IdleSpectator/ActivitySpeciesVoices.Invertebrates.Extended.cs
@@ -0,0 +1,459 @@
+using System.Collections.Generic;
+
+namespace IdleSpectator;
+
+public static partial class ActivitySpeciesVoiceCatalog
+{
+ private static void AddInvertebrateExtendedVoices(Dictionary voices)
+ {
+ AddExtended(
+ voices,
+ "acid_blob",
+ V("warbles through fizzing surface bubbles", "ripples its rim in a wet, rising cadence"),
+ V("folds a budding lobe slowly into a reproductive union", "tightens its surface around a pulsing germ"),
+ V("etches planting seams with a narrow acidic feeler", "bathes each planting point in a measured secretion"),
+ V("dusts reproductive grains from one tacky lobe to another", "rolls a pollen film across its adhesive rim"),
+ V("pinches off a measured bead and absorbs one in return", "opens a surface pocket to barter with pulsing rim-signals"),
+ V("sweeps a thin pseudopod in search of a catch", "fans a sensing film outward before snapping it inward"),
+ V("rolls its mass forward in a series of hauling surges", "anchors its rear rim and drags with a broad front lobe"),
+ V("lays a mild sealing film over {target}", "presses a cool regenerative lobe against {target}"),
+ V("spreads into a smothering sheet over the flame", "jets damp acidic foam at the flame"),
+ V("streams away in one stretched ribbon", "retracts every feeler and pours into a rapid glide"),
+ V("anchors a broad rim and raises a stable central mound", "spreads firm lobes until its mass rests securely"),
+ V("hardens its leading edge into a rippling guard", "raises a striking lobe charged with corrosive pressure"),
+ V("tracks each line with a hair-thin surface filament", "pulses paired eye-like spots from mark to mark"),
+ V("draws loose life-glow through its translucent skin", "cups a fading essence inside a sealed inner bubble"),
+ V("opens a rear pore and expels a spent acidic bead", "contracts from front to back and releases spent fluid"),
+ V("sends contradictory ripples around its rim", "splits its leading lobe twice before drawing both halves back"),
+ V("pulls its mass inward as inner bubbles brighten", "rests wide while restorative pulses thicken its center"),
+ V("raises an unbidden spire that curls into its own surface", "paddles one lobe against the rhythm of the rest"),
+ V("slides a silent filament toward {target}", "reaches an opaque surface pocket toward {target}"),
+ V("bucks as foreign pulses race through its mass", "forms jagged lobes that strike without its usual flow"),
+ V("drifts in sleep while dim shapes bloom beneath its skin", "replays slow phantom ripples across its resting pool"));
+
+ AddExtended(
+ voices,
+ "ant_black",
+ V("stridulates a clipped rhythm through its body plates", "clicks its mandibles beneath a steady antenna beat"),
+ V("aligns abdomen to abdomen in a brisk reproductive clasp", "circles once with linked feelers before mating"),
+ V("scores straight planting furrows with its mandibles", "tamps each planting point with all six feet"),
+ V("combs pollen along its forelegs and antennae", "presses its dusted body against receptive blossoms"),
+ V("barters with rapid paired feeler taps", "passes and receives with precise mandible grips"),
+ V("searches for a catch with jaws poised", "waits under still antennae before snapping its mandibles"),
+ V("locks its jaws on the haul and pulls in a straight course", "braces all six feet and drags without veering"),
+ V("grooms {target} with fine mouthpart strokes", "presses both antenna tips gently against {target}"),
+ V("beats at the flame with rapid abdomen sweeps", "scrapes a smothering path forward with its forelegs"),
+ V("scurries away in a low straight burst", "folds its feelers back and drives all six feet rapidly"),
+ V("tests its surroundings with brisk antenna taps before stopping", "settles all six feet into a compact ordered stance"),
+ V("sets its feet square and opens its mandibles", "advances in a disciplined line with antennae level"),
+ V("follows each mark with alternating feeler taps", "holds still while both antennae read from side to side"),
+ V("hooks a fading life-thread between its mandibles", "draws the gathered essence along both antennae"),
+ V("raises its abdomen and releases a compact dropping", "plants its forefeet as its abdomen briefly contracts"),
+ V("crosses and recrosses a straight path", "taps one antenna rapidly while the other holds rigid"),
+ V("folds low as energy returns through its six limbs", "grooms each leg in sequence during recovery"),
+ V("marches backward while its antennae insist forward", "repeatedly opens one mandible and closes the other"),
+ V("slips flattened antennae and mandibles toward {target}", "tries to pinch {target} before backing away silently"),
+ V("jerks in broken straight lines under an alien impulse", "snaps its jaws while both feelers curl against its head"),
+ V("tucks all six feet close as its antennae twitch in sleep", "makes faint marching motions beneath a resting crouch"));
+
+ AddExtended(
+ voices,
+ "ant_blue",
+ V("ticks its mouthparts in a measured ascending scale", "draws paired antenna arcs to a precise body hum"),
+ V("matches alternating feeler strokes before a balanced mating clasp", "joins abdomen tips while all six feet hold a careful stance"),
+ V("sets planting points at equal intervals with paired jaws", "levels each furrow with alternating forefoot strokes"),
+ V("maps pollen between crossing antennae and forelegs", "turns in exact angles while brushing reproductive dust onward"),
+ V("barters with mirrored feeler taps on both sides", "rotates paired mouthparts in a measured give-and-take"),
+ V("angles its antennae while searching for a catch", "closes both jaws in a precisely timed fishing snap"),
+ V("sets centered mandibles on the haul and steps backward evenly", "pulls with alternating six-foot braces"),
+ V("sweeps both antennae symmetrically over {target}", "tends {target} with equal strokes of its paired mouthparts"),
+ V("fans the flame with alternating wingless body pivots", "presses a measured smothering edge forward with both forelegs"),
+ V("retreats in exact zigzags with feelers laid back", "sidesteps away through alternating angular turns"),
+ V("surveys in widening antenna arcs before planting its feet", "settles into alignment with paired forefoot adjustments"),
+ V("holds a high squared stance with jaws centered", "paces in measured angular steps with mandibles ready"),
+ V("brackets each line between parallel antennae", "advances both feeler tips across the marks together"),
+ V("triangulates a loose life-spark between its feelers", "channels gathered essence down paired antennae in matched pulses"),
+ V("balances high and releases a neat abdominal pellet", "holds every foot fixed as its abdomen contracts"),
+ V("turns left and right by identical angles without advancing", "draws mismatched symbols with its crossing antennae"),
+ V("rests on straightened legs as strength pulses in pairs", "folds each limb in mirrored sequence while recharging"),
+ V("traces an exact circle with only one feeler", "steps in a rigid pattern its body did not choose"),
+ V("times a reach for {target} between alternating antenna sweeps", "tries to nip {target} before withdrawing in a precise zigzag"),
+ V("moves in impossible angles as foreign force bends its joints", "crosses both antennae tightly while its feet pace alone"),
+ V("rests narrow while paired feelers sketch silent patterns", "ticks its feet in symmetrical dream motions"));
+
+ AddExtended(
+ voices,
+ "ant_green",
+ V("scrapes its jaws in springing syncopation", "drums raised forelegs beneath a bouncing chirr"),
+ V("vaults into a hooked reproductive embrace", "links feelers overhead while abdomen tips meet"),
+ V("cuts planting slits with hooked forefeet", "vaults between planting points and presses them with its abdomen"),
+ V("sweeps pollen onward with raised forelegs", "hooks reproductive dust into the hairs of its wrists"),
+ V("barters with mandibles lifted high", "links its forelegs in an arched give-and-take"),
+ V("poises on folded hind legs while seeking a catch", "hooks downward with both raised forefeet"),
+ V("loops its forelegs around the haul and bounds backward", "hooks underneath and pulls in springing steps"),
+ V("clasps {target} gently between hooked wrists", "grooms {target} with elevated mandible strokes"),
+ V("beats both raised forelegs over the flame", "springs past the flame with broad abdomen sweeps"),
+ V("vaults away with forelegs tucked over its head", "bounds back in quick doubled leaps"),
+ V("hooks its forefeet down and settles its weight", "arches its body above six firm leg braces"),
+ V("raises both forelegs like hooked standards", "bounds forward with mandibles lifted for battle"),
+ V("holds the marks aloft between its forefeet", "reads each line with one hooked wrist"),
+ V("catches a life-glimmer between uplifted feelers", "channels gathered essence down its raised forelegs"),
+ V("rears on four feet and releases from its abdomen", "folds its forelegs overhead as its abdomen contracts"),
+ V("vaults forward and lands facing the same direction", "grooms one feeler while the other circles wildly"),
+ V("curls into a high-legged rest as vigor rebounds", "pumps its folded hind legs in a restoring rhythm"),
+ V("clasps its own antennae and tries to vault beneath them", "holds both forelegs aloft while spinning involuntarily"),
+ V("hooks one raised foreleg toward {target}", "tries to snag {target} before bounding away"),
+ V("rears repeatedly as an outside rhythm seizes its legs", "swings its hooked forefeet at empty intervals"),
+ V("curls around raised forelegs while hind legs twitch", "makes tiny sleeping vaults without leaving its crouch"));
+
+ AddExtended(
+ voices,
+ "ant_red",
+ V("clacks wide mandibles in a fierce rolling cadence", "stamps all six feet beneath a hard body rattle"),
+ V("locks into a forceful reproductive coupling", "circles with jaws spread before abdomen tips join"),
+ V("tears planting furrows with driving mandible strokes", "rams each planting point with its plated head"),
+ V("charges among blossoms with dusted body hairs", "scrapes pollen onward using forceful foreleg strokes"),
+ V("barters between jaws held wide", "seals its give-and-take with a hard antenna strike"),
+ V("crouches with mandibles open while seeking a catch", "lunges into a sudden six-legged fishing snap"),
+ V("clamps onto the haul and drives backward without pause", "shoves with head low and legs churning"),
+ V("braces {target} firmly between its jaws", "tends {target} with rapid mouthpart strokes"),
+ V("charges the flame with beating forelegs", "drives a smothering body sweep across the flame"),
+ V("bursts away with jaws still spread", "scrambles backward on splayed feet before turning"),
+ V("rams its head down before settling on braced feet", "paces with rigid antennae before dropping into a low stance"),
+ V("plants six feet wide and brandishes open mandibles", "surges into battle in short aggressive bursts"),
+ V("pins the markings beneath its forefeet", "jabs an antenna along each line in rapid strokes"),
+ V("seizes a life-flare between its jaws", "drives gathered essence down rigid feelers"),
+ V("braces low and expels a hard abdominal pellet", "keeps its jaws spread as its abdomen forcefully releases"),
+ V("charges three directions in quick succession", "locks its jaws open while antennae whip apart"),
+ V("crouches taut as energy surges back through its legs", "pumps its abdomen in hard restoring pulses"),
+ V("bites at its own forefeet under a sudden compulsion", "rushes in a tight circle with abdomen raised"),
+ V("snaps its jaws toward {target}", "tries to clamp {target} before retreating in a rapid burst"),
+ V("lunges in broken bursts as another will drives it", "clamps and releases its jaws against its own rhythm"),
+ V("rests low while dream-battles twitch through all six feet", "snaps its mandibles softly in sleep"));
+
+ AddExtended(
+ voices,
+ "bee",
+ V("sings through a bright sustained wing hum", "modulates its buzz with pulses of its abdomen"),
+ V("joins in a brief airborne reproductive coupling", "fans its wings during an abdomen-to-abdomen mating clasp"),
+ V("scrapes planting points with its forelegs", "presses each planting point using the tip of its abdomen"),
+ V("brushes pollen from body hairs into packed leg combs", "dusts reproductive grains onward with a vibrating abdomen"),
+ V("barters with a compact waggle", "gives and receives with precise mouthpart touches"),
+ V("hovers with forelegs poised while searching for a catch", "dips its legs and rises on a sudden fishing sweep"),
+ V("hooks its legs around the haul and beats upward", "pulls with wings buzzing at a deep pitch"),
+ V("fans warm pulsing air over {target}", "grooms {target} with delicate mouthpart strokes"),
+ V("buffets the flame with concentrated wingbeats", "drives cooling air directly at the flame"),
+ V("zips away with its abdomen tucked under", "accelerates in a rising line on frantic wings"),
+ V("tests its surroundings with antennae and circling flights", "settles after repeated abdomen presses against the surface"),
+ V("curls its abdomen forward and deepens its warning buzz", "holds a rigid hover with legs spread for combat"),
+ V("walks its forefeet along each line", "reads with both antennae angled over the marks"),
+ V("draws a life-glow into the pulse of its abdomen", "gathers loose essence through vibrating body hairs"),
+ V("hangs its abdomen and releases a tiny dropping in flight", "lands, lifts its abdomen, and contracts once"),
+ V("hovers sideways while its antennae point apart", "starts a waggle sequence and repeatedly breaks the pattern"),
+ V("rests with wings folded as its body hum steadies", "vibrates flight muscles in a low restorative pulse"),
+ V("waggles in a pattern that loops against itself", "grooms one wing while the other beats without command"),
+ V("slips toward {target} on muted wingbeats", "reaches both forelegs toward {target} before darting away"),
+ V("buzzes at a fractured pitch as its abdomen jerks", "flies in rigid angles under a foreign impulse"),
+ V("folds its wings while tiny flight tremors cross its body", "waggles faintly in sleep with antennae tucked"));
+
+ AddExtended(
+ voices,
+ "beetle",
+ V("rasps hooked feet against its plated sides", "clicks its wing cases in a hollow measured refrain"),
+ V("opens its wing cases during a close reproductive mounting", "locks hooked feet gently during mating"),
+ V("furrows planting lines with its hardened brow", "presses planting points beneath its plated body"),
+ V("brushes pollen onward with hairy forefeet", "parts its wing cases while reproductive dust crosses its back"),
+ V("barters with taps from both feelers", "takes measured turns with its hooked forefeet"),
+ V("plants hooked feet and searches for a catch", "snaps its head forward after a still feeler sweep"),
+ V("wedges its plated back beneath the haul", "grips and drags with forefeet on six braced legs"),
+ V("presses a smooth wing case against {target}", "tends {target} with careful mouthpart strokes"),
+ V("beats open wing cases against the flame", "shoves its plated front over the flame"),
+ V("trundles away with legs pumping beneath sealed cases", "opens its wing cases and bolts on buzzing wings"),
+ V("tests its footing with hooked feet before settling", "leans its hardened back into a stable resting brace"),
+ V("lowers its armored brow and spreads all six feet", "opens its wing cases into a broad warrior display"),
+ V("reads with short feeler sweeps", "pins each line beneath a hooked forefoot"),
+ V("cups a fading life-light beneath its wing cases", "draws gathered essence through seams in its plated back"),
+ V("raises its rear plates and releases a compact pellet", "anchors all six feet as its abdomen slowly pushes"),
+ V("rolls onto its back and pedals without direction", "opens one wing case while keeping the other sealed"),
+ V("locks its feet and rests as strength returns beneath its shell", "pulses its folded wings in a low restoring rhythm"),
+ V("rocks on its plated back with legs folded", "repeatedly opens and seals its wing cases without flight"),
+ V("hooks a folded foreleg toward {target}", "tries to catch {target} before withdrawing with wing cases shut"),
+ V("clatters as foreign force pries its plates apart", "marches stiffly while its feelers curl inward"),
+ V("seals its wing cases while sleeping legs slowly pedal", "rocks inside its plated rest through a hollow dream"));
+
+ AddExtended(
+ voices,
+ "bioblob",
+ V("warbles through elastic membrane pops", "pulses its rounded skin in a soft resonant sequence"),
+ V("buds a second pulse within a reproductive membrane join", "mingles inner currents around a tightening germ"),
+ V("forms shallow planting pockets with rhythmic squeezes", "presses each planting point beneath a rounded membrane dimple"),
+ V("rolls pollen across its adhesive outer skin", "pulses reproductive dust from one temporary pocket to another"),
+ V("forms two clear barter chambers in its membrane", "trades with alternating contractions of its surface pockets"),
+ V("extends a springy membrane tube in search of a catch", "snaps a sensing bulge inward with a whole-body squeeze"),
+ V("wraps gripping pockets around the haul and heaves", "bounds backward with its membrane held taut"),
+ V("spreads a warm regenerative film over {target}", "pulses restorative fluid against {target} through a membrane patch"),
+ V("flattens its damp body across the flame", "pumps cooling fluid through a broad outer blister"),
+ V("bounds away in rapid whole-body contractions", "stretches forward and recoils into a springing escape"),
+ V("widens its base and firms the settling membrane", "pulses downward until its rounded body holds steady"),
+ V("hardens its front into a resilient bulwark", "compresses into a taut spring ready to strike"),
+ V("forms clear lens-spots that move across each line", "ripples written marks beneath a thin sensing membrane"),
+ V("draws a life-spark into a glowing inner vesicle", "surrounds gathered essence with concentric pulses"),
+ V("opens a temporary pore and squeezes out spent matter", "contracts its inner chamber and releases spent fluid"),
+ V("wobbles between two incompatible shapes", "sends pulses inward when its rim tries to move outward"),
+ V("draws membrane tight as inner fluid brightens", "rests in a dome while deep restorative pulses recur"),
+ V("pinches off a bead and repeatedly reels it back", "bounces in place as one inner current reverses"),
+ V("extends a nearly invisible membrane pocket toward {target}", "tries to fold its reaching membrane over {target}"),
+ V("jerks into sharp shapes under an alien current", "pops and swells as foreign pulses seize its membrane"),
+ V("sags into sleep while luminous forms drift inside", "quivers around slow inner dream-currents"));
+
+ AddExtended(
+ voices,
+ "butterfly",
+ V("flutters a papery rhythm beneath a faint thoracic hum", "fans broad wings in a slow singing cadence"),
+ V("joins abdomen tips in a delicate reproductive pairing", "holds a close wing-to-wing mating posture"),
+ V("scores planting points with slender feet", "presses each planting point beneath the tip of its abdomen"),
+ V("dusts broad wings and legs with pollen", "unfurls its feeding tube while reproductive grains brush onward"),
+ V("barters while circling in matched wing arcs", "curls its forelegs in a delicate give-and-take"),
+ V("skims with feeding tube uncurled while seeking a catch", "dips slender feet and lifts on one broad fishing sweep"),
+ V("clasps the haul with its legs and laboring wings", "leans its whole flight into the pull"),
+ V("fans {target} with slow warming wingbeats", "touches {target} gently with its feeding tube tip"),
+ V("beats broad wings hard across the flame", "folds and opens its wings in repeated smothering strokes"),
+ V("rises away in steep uneven spirals", "folds its legs tight and drives forward on rapid wingbeats"),
+ V("tests its footing lightly and comes to rest", "holds its wings upright while its feet establish a steady brace"),
+ V("spreads its wings into a broad warning plane", "dives to battle with slender legs extended"),
+ V("walks its feeding tube along written lines", "opens and closes its wings as slender feet track each mark"),
+ V("catches a life-glimmer between its wing scales", "draws gathered essence along the veins of its wings"),
+ V("hangs its abdomen and releases a tiny dropping", "holds its wings still as its abdomen briefly contracts"),
+ V("spirals upward, folds, and drops before opening again", "uncurls its feeding tube toward nothing and recoils"),
+ V("rests with wings spread as warmth returns through their veins", "pumps its thorax slowly beneath closed wings"),
+ V("beats left and right wings in opposing rhythms", "loops downward under an unbidden abdominal curl"),
+ V("settles near {target} with wings concealing its legs", "reaches curled forelegs toward {target} before lifting away"),
+ V("flaps in rigid jolts as an outside will pulls its abdomen", "folds its wings midflight under a foreign impulse"),
+ V("sleeps behind closed wings while the edges faintly tremble", "makes slow dream-flights with tucked, twitching legs"));
+
+ AddExtended(
+ voices,
+ "flower_bud",
+ V("rustles layered petals in a rising vegetal refrain", "hums through a vibrating hollow stalk"),
+ V("presses its receptive center into a reproductive bloom", "twines rootlets while pollen reaches its opened core"),
+ V("parts planting seams with branching root tips", "cups each planting point beneath a leaf"),
+ V("opens its crown and brushes pollen across receptive petals", "shakes reproductive dust from anther to central folds"),
+ V("barters by cupping and uncurling paired leaves", "inclines its crown as leaf tips give and receive"),
+ V("extends a fine root filament in search of a catch", "snaps a curled leaf closed after a patient tremor"),
+ V("winds rootlets around the haul and contracts its stalk", "braces its base while paired leaves pull"),
+ V("lays a sap-rich leaf over {target}", "presses regenerative pollen gently onto {target}"),
+ V("folds damp petals over the flame", "fans broad leaves directly at the flame"),
+ V("hitches away on frantic root contractions", "draws every petal closed and bends rapidly from danger"),
+ V("sinks fine roots into a steady settling brace", "opens its crown as its stalk establishes a firm base"),
+ V("stiffens its stalk and closes petals into a pointed crown", "spreads leaves around a root-braced warrior stance"),
+ V("traces each line with a curling leaf tip", "turns its crown as root hairs sense each mark"),
+ V("draws life-light into its receptive center", "channels gathered essence down the veins of its petals"),
+ V("opens a basal pore and sheds spent fibrous residue", "contracts its root crown and expels dry fibers"),
+ V("turns its crown between opposing directions", "opens alternating petals while its stalk coils"),
+ V("roots deeply as sap rises through its stalk", "closes its petals while restorative light pulses at the center"),
+ V("twines its own leaves around its stalk without cause", "opens one petal repeatedly against the rhythm of the crown"),
+ V("folds its leaves toward {target} and retracts its roots", "tries to cup {target} between closing petals"),
+ V("lashes its leaves as foreign sap pulses seize the stalk", "blooms and closes in jagged involuntary bursts"),
+ V("bows into sleep while dream-petals open inside the bud", "twitches its rootlets beneath a softly pulsing crown"));
+
+ AddExtended(
+ voices,
+ "fly",
+ V("buzzes a thin wavering melody on glassy wings", "rubs its wings into a sharp repeating trill"),
+ V("clasps in a brief reproductive pairing on braced legs", "joins abdomen tips while forefeet drum rapidly"),
+ V("scratches planting points with bent forelegs", "tamps each planting point with quick six-foot steps"),
+ V("brushes pollen onward with hairy feet and body", "rubs reproductive dust from forelegs to hind legs"),
+ V("barters with rapid forefoot drums", "sponges and releases with lowered mouthparts"),
+ V("hovers in abrupt stops while searching for a catch", "darts downward and snaps back on whining wings"),
+ V("grips the haul with all six feet and beats backward", "pulls in short bursts of wing speed"),
+ V("sponges {target} with careful mouthpart presses", "grooms {target} with rapid foreleg strokes"),
+ V("buffets the flame with whining wingbeats", "darts past the flame in repeated cooling passes"),
+ V("shoots away through a chain of right-angle turns", "folds its forelegs and accelerates on blurred wings"),
+ V("samples its footing with each foot before settling", "orbits tightly before bracing on all six legs"),
+ V("faces forward with wings spread and forelegs raised", "charges into battle in abrupt aerial bursts"),
+ V("wipes its eyes before tracking each line", "drums bent forefeet along the printed marks"),
+ V("draws a life-flicker across its many-faceted eyes", "gathers loose essence through vibrating wing veins"),
+ V("lifts its abdomen and releases a minute dropping", "rubs its forelegs as its abdomen releases"),
+ V("darts in a square and misses the final turn", "wipes one eye repeatedly while circling on three legs"),
+ V("rests with wings flat as flight muscles regain their hum", "vibrates its thorax in a low restoring buzz"),
+ V("loops upside down and hovers there too long", "rubs its hind legs while both forelegs point rigidly ahead"),
+ V("lands silently beside {target} on padded feet", "reaches all six legs toward {target} before lifting"),
+ V("jerks through angular flight under a foreign command", "buzzes in broken pulses as its legs grasp at nothing"),
+ V("sleeps with wings flat while its feet make tiny wiping strokes", "twitches through silent dream-darts"));
+
+ AddExtended(
+ voices,
+ "garl",
+ V("rustles papery layers beneath a reedy leaf whistle", "shivers its narrow leaves in a dry descending song"),
+ V("braids receptive root fibers in a reproductive joining", "parts its layered bulb while pollen settles into its core"),
+ V("rakes planting seams with fibrous roots", "presses each planting point beneath its layered bulb"),
+ V("catches pollen among narrow leaves and papery folds", "shakes reproductive dust downward along its stalk"),
+ V("barters by opening and closing two papery layers", "alternates curled leaf tips in a measured give-and-take"),
+ V("threads a fine root outward in search of a catch", "jerks its bulb backward when root fibers tighten"),
+ V("hooks root bundles around the haul and leans away", "wedges its dense bulb behind and drives forward"),
+ V("binds {target} with a sap-damp layer", "presses pungent regenerative fibers against {target}"),
+ V("lashes narrow leaves across the flame", "presses its dense damp bulb against the flame"),
+ V("scrambles away on bunching root fibers", "folds its leaves tight and lurches rapidly aside"),
+ V("spreads root fibers into a broad settling hold", "stacks its layered bulb firmly above anchored roots"),
+ V("stiffens narrow leaves into a bristling crown", "swings its dense bulb from a root-braced warrior stance"),
+ V("runs a leaf tip beneath each line", "parts papery layers as root fibers trace the marks"),
+ V("draws life-light between its layered skins", "pulls gathered essence down its fibrous roots"),
+ V("parts its basal layers and expels spent pulp", "tightens its bulb and sheds dry fibers"),
+ V("winds root fibers in opposite directions", "fans one leaf while every other leaf folds"),
+ V("rests its bulb low as sap pressure returns", "draws strength inward through tightly coiled roots"),
+ V("peels one papery layer back and wraps it again", "braids its own leaf tips under an unbidden impulse"),
+ V("folds dry skins toward {target}", "tries to draw {target} between layered bulb scales"),
+ V("thrashes its leaves as foreign pressure twists the stalk", "lurches on roots that contract outside its rhythm"),
+ V("bows its stalk while sleeping roots slowly curl", "rustles inside closed papery layers as it dreams"));
+
+ AddExtended(
+ voices,
+ "grasshopper",
+ V("scrapes a bright skipping song from leg against wing", "pulses its hind legs through a rising chirr"),
+ V("clasps tightly during a balanced reproductive mounting", "joins abdomen tips with hind legs folded close"),
+ V("kicks planting furrows with spined hind feet", "presses planting points beneath short forefoot stamps"),
+ V("brushes pollen onward with its body and jointed legs", "springs between pollinating contacts with dusted feet"),
+ V("barters with alternating forefoot taps", "gives and receives with precise serrated mouthparts"),
+ V("crouches on folded hind legs while seeking a catch", "springs upward after a sudden fishing snap"),
+ V("grips the haul with its forefeet and hops backward", "drives forward with both hind feet"),
+ V("combs {target} with delicate forefoot strokes", "presses its mouthparts carefully against {target}"),
+ V("kicks across the flame with broad hind-leg sweeps", "leaps past the flame while fanning both wings"),
+ V("launches away in successive full-length bounds", "folds its feelers back and springs without pause"),
+ V("tests its footing with deep hind-foot presses", "settles into a stable four-point crouch"),
+ V("raises on extended hind legs with jaws working", "bounds into battle forefeet-first"),
+ V("tracks each line with one long feeler", "holds the markings between forefeet while mouthparts tick"),
+ V("catches a life-spark between extended feelers", "draws gathered essence through a resonant wing pulse"),
+ V("lifts its abdomen and drops a compact pellet", "folds its hind legs as its abdomen briefly releases"),
+ V("springs straight up and lands facing backward", "scrapes one broken chirr while both feelers cross"),
+ V("crouches low as strength coils into its hind legs", "pumps both jumping limbs with slow restoring bends"),
+ V("kicks one hind leg while the other stays locked", "leaps in place under an unexplained abdominal twitch"),
+ V("snatches at {target} with folded forefeet", "tries to clasp {target} before bounding away"),
+ V("launches in jagged bursts under a foreign rhythm", "scrapes a harsh chirr while its hind legs kick alone"),
+ V("sleeps with long legs folded as tiny jumps twitch within", "moves its mouthparts through a faint dream-chirr"));
+
+ AddExtended(
+ voices,
+ "lemon_snail",
+ V("sings through a wet rasp beneath its shell lip", "rocks its shell to a slow foot-pulsed hum"),
+ V("presses foot to foot in a reciprocal reproductive joining", "touches mating pores beneath crossed feelers"),
+ V("rasps shallow planting seams with its toothed tongue", "presses planting points beneath the broad front of its foot"),
+ V("collects pollen on its moist body and feeler tips", "glides reproductive dust across receptive surfaces"),
+ V("barters with touches from both long feelers", "ripples the front of its foot in a slow give-and-take"),
+ V("extends its eyestalks while searching for a catch", "casts its head forward and recoils beneath its shell"),
+ V("sets its muscular foot against the haul and ripples backward", "anchors its shell while the broad foot pushes"),
+ V("lays a healing trail of mucus over {target}", "presses the soft rim of its foot against {target}"),
+ V("draws damp mucus over the flame", "swings its shell down in a slow smothering press"),
+ V("glides away on rapid foot ripples with feelers withdrawn", "pulls its head beneath the shell while sliding aside"),
+ V("seals its broad foot into a stable settling grip", "tests the boundary with fully extended eyestalks"),
+ V("rears beneath its shell with all feelers forward", "swings its shell from a firmly anchored warrior stance"),
+ V("traces each line with the tips of its eyestalks", "rasps lightly beneath the marks with its toothed tongue"),
+ V("draws a life-glow into the spiral of its shell", "gathers loose essence along its shining mucus trail"),
+ V("raises its shell and releases a soft waste pellet", "contracts its muscular foot and slowly releases waste"),
+ V("extends one eyestalk while withdrawing the other", "glides in a circle as its shell tilts the opposite way"),
+ V("rests half withdrawn as vigor ripples through its foot", "seals close while restorative moisture gathers beneath its shell"),
+ V("waves crossed feelers while its foot moves backward", "rasps at its own shell lip under a strange impulse"),
+ V("slides silently toward {target} with feelers tucked", "tries to arch its broad foot over {target}"),
+ V("twists beneath its shell as foreign pulses seize its foot", "lashes its feelers in movements outside its slow rhythm"),
+ V("sleeps sealed close while eyestalks twitch within", "rocks its shell slowly as spiral forms fill its dream"));
+
+ AddExtended(
+ voices,
+ "lil_pumpkin",
+ V("rattles its hollow ribs beneath a vine-tip rhythm", "whistles through a curling stem in bouncing notes"),
+ V("twines receptive tendrils into a reproductive joining", "opens its crown as pollen reaches the seeded core"),
+ V("parts planting seams with forked tendril tips", "rolls its ribbed base over each planting point"),
+ V("catches pollen on curling vines around its crown", "flicks reproductive dust inward with springing tendrils"),
+ V("barters by looping and releasing two tendrils", "rocks its ribbed side in a measured give-and-take"),
+ V("uncurls a thin vine while searching for a catch", "snaps the tendril back into a tight coil"),
+ V("winds several tendrils around the haul and rolls backward", "braces its ribbed body while coiled vines pull"),
+ V("wraps a sap-rich tendril around {target}", "presses its soft inner vine gently against {target}"),
+ V("rolls its broad ribbed body over the flame", "lashes damp vine coils directly at the flame"),
+ V("bounds away on recoiling tendrils", "rolls rapidly with crown bent and vines tucked"),
+ V("spreads tendrils into a firm settling lattice", "sets its rounded base while the crown straightens"),
+ V("stiffens coiled vines around its ribbed body", "butts forward from a tendril-braced warrior stance"),
+ V("runs a forked vine tip along each line", "tilts its crown while tendrils trace the marks"),
+ V("draws life-light through its crown into the seeded hollow", "gathers loose essence along curling vine veins"),
+ V("lifts its base and releases spent fibrous pulp", "contracts its hollow body and expels dry fibers"),
+ V("rolls forward while every tendril pulls backward", "coils its crown vine around one rib repeatedly"),
+ V("rests round and still as sap fills each tendril", "pulses its hollow core in a slow restoring rhythm"),
+ V("ties two of its own vines into a tightening loop", "bounces on its base while the crown twists sideways"),
+ V("curls broad tendrils toward {target}", "tries to loop its vines around {target} before rolling away"),
+ V("rattles violently as foreign force plucks its vines", "rolls in broken arcs under an outside impulse"),
+ V("sleeps on one rib while tendrils curl and uncurl", "echoes soft dream-knocks inside its hollow body"));
+
+ AddExtended(
+ voices,
+ "sand_spider",
+ V("drums eight feet in a dry intricate song", "rasps mouthparts beneath alternating leg taps"),
+ V("locks legs in a careful reproductive embrace", "transfers a mating pulse through paired front appendages"),
+ V("rakes planting lines with alternating front legs", "tamps planting points with four paired foot presses"),
+ V("combs pollen through the hairs of its legs", "steps reproductive dust onward across eight contact points"),
+ V("barters with measured front-foot taps", "alternates folded forelegs in a precise give-and-take"),
+ V("casts a fine silk line while searching for a catch", "feels along the silk with widely spread feet before jerking back"),
+ V("binds the haul in silk and pulls with all eight legs", "walks backward while paired feet drag"),
+ V("lays a sealing silk pad over {target}", "grooms {target} with fine mouthpart strokes"),
+ V("casts a dense silk sheet over the flame", "beats four pairs of legs in a smothering press"),
+ V("scuttles away sideways on low-splayed legs", "retracts its front pair and darts in an angular retreat"),
+ V("anchors silk before folding into a settled crouch", "reads surface tremors through eight feet before settling"),
+ V("rears on its hind pairs with front legs spread", "pivots sideways in a low fighting stance"),
+ V("follows each line with alternating front feet", "reads tiny tremors along a taut silk filament"),
+ V("wraps a life-glimmer in a pulsing silk knot", "draws gathered essence inward through all eight feet"),
+ V("raises its abdomen and releases a compact dropping", "holds on four feet as its rear briefly contracts"),
+ V("lifts the wrong leg in every paired sequence", "spins half a turn and freezes with feet crossed"),
+ V("settles low as vigor returns through eight joints", "flexes each paired leg in a slow restoring wave"),
+ V("ties a silk loop around its own forelegs", "drums three feet while the other five hold rigid"),
+ V("casts silk toward {target} with rapid rear pulses", "tries to fold its front legs around {target}"),
+ V("jerks on stiffened legs as alien tremors command it", "strikes with its front pair outside its usual rhythm"),
+ V("folds into sleep while feet answer phantom vibrations", "spins a tiny dream-thread beneath its resting body"));
+
+ AddExtended(
+ voices,
+ "scorpion",
+ V("clacks both pincers in a hollow antiphonal song", "rattles its plated tail beneath measured claw beats"),
+ V("clasps pincers during a paired reproductive turning", "joins bodies beneath a carefully arched tail"),
+ V("shears planting seams with opposing claws", "presses each planting point with the flat of a pincer"),
+ V("brushes pollen onward between fine pincer hairs", "guides reproductive dust with alternating claw tips"),
+ V("barters between open pincers", "alternates one claw and the other in a measured give-and-take"),
+ V("holds one open claw while searching for a catch", "snaps both pincers inward after a tail-balanced pause"),
+ V("grips the haul with both claws and walks backward", "hooks underneath while eight legs pull"),
+ V("holds {target} steady in one pincer", "applies a minute regenerative sting to {target}"),
+ V("beats the flame with broad opposing claws", "presses its plated body low over the flame"),
+ V("sidesteps away with tail curled tight overhead", "retreats rapidly while both pincers guard its front"),
+ V("tests its footing with claw tips and walking legs", "lowers its plated body into a settled eight-foot brace"),
+ V("opens both pincers and poises its tail above", "advances sideways to battle with its plated guard raised"),
+ V("runs one claw tip beneath each line", "holds the markings between pincers while tail segments count"),
+ V("catches a life-spark between closing claws", "draws gathered essence down the arch of its tail"),
+ V("raises its rear plates and releases a compact dropping", "sets all eight feet as its abdomen pushes"),
+ V("circles its own tail while one claw opens and shuts", "sidesteps left as both pincers insist right"),
+ V("rests low as strength returns along its plated tail", "folds its claws beneath a slow restorative pulse"),
+ V("clasps its own tail tip between careful pincers", "walks backward beneath an involuntary claw rhythm"),
+ V("snaps one claw toward {target} while the other guards", "tries to pinch {target} before withdrawing sideways"),
+ V("strikes downward as foreign force arches its tail", "clacks its pincers in a rhythm it does not control"),
+ V("sleeps beneath a lowered tail while claw tips twitch", "dreams of a silent paired turn beneath its arched tail"));
+
+ AddExtended(
+ voices,
+ "smore",
+ V("flaps broad layers in a soft stacked refrain", "pipes a thin note through clustered springy stalks"),
+ V("presses yielding layers into a reproductive joining", "braids ribbonlike leaves as pollen reaches the inner fold"),
+ V("parts planting seams with bundled stalk tips", "compresses its broad lower layer over each planting point"),
+ V("catches pollen between broad yielding layers", "flicks reproductive dust onward with ribbonlike leaves"),
+ V("barters by pinching and opening two soft layers", "alternates bending shoot tips in a gentle give-and-take"),
+ V("extends a ribbonlike leaf while searching for a catch", "snaps stacked layers shut after a trembling pause"),
+ V("clamps the haul between broad layers and shuffles backward", "bends bundled stalks into a springing push"),
+ V("presses a soft sap-filled layer over {target}", "wraps {target} between warm yielding folds"),
+ V("claps broad layers over the flame", "fans the flame with rapid stacked flaps"),
+ V("bounds away on compressed springy stalks", "folds its ribbonlike leaves and shuffles rapidly aside"),
+ V("spreads bundled shoots into a steady settling base", "aligns its stacked crown above a firm fibrous brace"),
+ V("compresses its layers into a dense springing guard", "raises ribbonlike leaves from a broad warrior stance"),
+ V("slides a leaf tip beneath each line", "tilts stacked layers as bundled shoots trace the marks"),
+ V("cups a life-glow between yielding inner folds", "draws gathered essence through its springy stalks"),
+ V("parts its lowest layers and expels spent fibrous residue", "compresses its crown and sheds soft fibers"),
+ V("tilts each layer in a different direction", "wraps one ribbonlike leaf around the entire stack"),
+ V("rests compressed while vigor fills its bending shoots", "slowly expands each layer with a restoring pulse"),
+ V("claps its upper layers without separating the lower ones", "braids its own leaves under an unbidden bounce"),
+ V("closes soft layers toward {target}", "tries to pinch {target} between yielding folds"),
+ V("buckles and springs as foreign force compresses its crown", "flaps unevenly under a pulse outside its body"),
+ V("settles into sleep while inner layers softly rise and fall", "bounces on folded shoots as muted dreams pulse within"));
+ }
+}
diff --git a/IdleSpectator/ActivitySpeciesVoices.Invertebrates.Specialized.cs b/IdleSpectator/ActivitySpeciesVoices.Invertebrates.Specialized.cs
new file mode 100644
index 0000000..cabf02b
--- /dev/null
+++ b/IdleSpectator/ActivitySpeciesVoices.Invertebrates.Specialized.cs
@@ -0,0 +1,207 @@
+using System.Collections.Generic;
+
+namespace IdleSpectator;
+
+public static partial class ActivitySpeciesVoiceCatalog
+{
+ private static void AddInvertebrateSpecializedVoices(Dictionary voices)
+ {
+ AddSpecialized(
+ voices,
+ "acid_blob",
+ V("kindles flame beneath a searing pseudopod", "spreads flame with a sweep of its acidic rim"),
+ V("smothers flame beneath a broad liquid fold", "suppresses flame with jets from its pulsing pores"),
+ V("pools against its kin in a ring of touching rims", "merges its outline into a visible cluster with kin"),
+ V("draws the observed life essence through a feeding film", "cups the observed life essence inside a contracting vacuole"),
+ V("probes for spoils with a hair-thin pseudopod", "reaches for spoils with an opening surface pocket"),
+ V("burbles as its membrane dimples in rapid waves", "spills a wavering gurgle through its trembling rim"),
+ V("raises a jagged lobe and spits a sharp wet hiss", "slaps its rim down as surface bubbles crackle"));
+
+ AddSpecialized(
+ voices,
+ "ant_black",
+ V("kindles flame with rapid mandible strikes", "spreads flame with straight abdomen sweeps"),
+ V("smothers flame beneath stamping forefeet", "suppresses flame with rapid abdomen beats"),
+ V("packs into a straight-bodied cluster with kin", "locks antennae into a visible rank among kin"),
+ V("draws the observed life essence between closed mandibles", "pulls the observed life essence along both antennae"),
+ V("probes for spoils with brisk antenna taps", "reaches for spoils with narrowly opened mandibles"),
+ V("stridulates in clipped pulses as its antennae shiver", "folds low while its mandibles click unevenly"),
+ V("clacks its mandibles in a hard measured burst", "stamps all six feet beneath rigid antennae"));
+
+ AddSpecialized(
+ voices,
+ "ant_blue",
+ V("kindles flame with alternating mandible scrapes", "spreads flame through precise abdomen pivots"),
+ V("smothers flame with paired forefoot presses", "suppresses flame beneath symmetrical abdomen fans"),
+ V("forms an angular cluster with evenly spaced kin", "crosses antennae in a visible lattice among kin"),
+ V("draws the observed life essence between parallel antennae", "channels the observed life essence through paired mouthparts"),
+ V("probes for spoils with mirrored antenna arcs", "reaches for spoils with both mandibles centered"),
+ V("ticks its mouthparts as both antennae droop", "draws uneven antenna spirals beneath a thin stridulation"),
+ V("clicks both mandibles in an exact descending pattern", "cuts rigid angles with its antennae while its feet stamp"));
+
+ AddSpecialized(
+ voices,
+ "ant_green",
+ V("kindles flame with hooked foreleg scrapes", "spreads flame with bounding abdomen flicks"),
+ V("smothers flame beneath crossing forelegs", "suppresses flame with broad sweeps of its raised abdomen"),
+ V("arches its forelegs across a cluster of kin", "hooks antennae into a visible ring among kin"),
+ V("draws the observed life essence between uplifted feelers", "pulls the observed life essence down its hooked forelegs"),
+ V("probes for spoils with one raised foreleg", "reaches for spoils with both mandibles lifted"),
+ V("scrapes a skipping chirr as its forelegs curl", "bows beneath raised forelegs while its jaws rasp"),
+ V("flings both hooked forelegs overhead with a harsh chirr", "scrapes its mandibles while its abdomen snaps upward"));
+
+ AddSpecialized(
+ voices,
+ "ant_red",
+ V("kindles flame with forceful mandible grinding", "spreads flame with charging abdomen sweeps"),
+ V("smothers flame beneath pounding forefeet", "suppresses flame with hard full-body swipes"),
+ V("wedges into a dense cluster with braced kin", "raises spread mandibles inside a visible knot of kin"),
+ V("draws the observed life essence through parted mandibles", "drags the observed life essence along rigid antennae"),
+ V("probes for spoils with forceful antenna thrusts", "reaches for spoils with mandibles spread wide"),
+ V("rattles its body plates as its jaws open and close", "crouches low beneath a broken stridulating rasp"),
+ V("clashes its mandibles and lashes both antennae", "rears on four feet with a hard abdominal rattle"));
+
+ AddSpecialized(
+ voices,
+ "bee",
+ V("kindles flame with a rapid sting scrape", "spreads flame beneath beating wings"),
+ V("smothers flame with dense wingbeat pulses", "suppresses flame beneath sweeping abdomen fans"),
+ V("lands in a tight wing-to-wing cluster with kin", "locks legs into a visible hanging cluster with kin"),
+ V("draws the observed life essence along its unfurled tongue", "pulls the observed life essence between vibrating mouthparts"),
+ V("probes for spoils with antennae and tongue extended", "reaches for spoils with its forelegs spread"),
+ V("releases a wavering buzz as its abdomen contracts", "hangs its antennae beneath a broken wing hum"),
+ V("drives a harsh buzz through flared wings", "curls its stinger forward while its wingbeats rasp"));
+
+ AddSpecialized(
+ voices,
+ "beetle",
+ V("kindles flame with scraping mandibles", "spreads flame beneath opening wing cases"),
+ V("smothers flame under its plated abdomen", "suppresses flame with repeated wing-case claps"),
+ V("presses wing cases into a plated cluster with kin", "interlocks hooked feet in a visible mound with kin"),
+ V("draws the observed life essence between its mandibles", "pulls the observed life essence beneath closed wing cases"),
+ V("probes for spoils with clubbed feelers", "reaches for spoils with hooked forefeet"),
+ V("rasps its feet along its plates as its feelers sag", "clicks its wing cases through a low uneven tremor"),
+ V("snaps its wing cases open with a hollow crack", "rakes hooked feet across its plates in a harsh rasp"));
+
+ AddSpecialized(
+ voices,
+ "bioblob",
+ V("kindles flame with a hot contracting membrane", "spreads flame through bouncing membrane flicks"),
+ V("smothers flame beneath an expanding membrane pocket", "suppresses flame with pulsing jets from its pores"),
+ V("presses its membrane into a quivering cluster with kin", "stacks pulsing lobes in a visible mound among kin"),
+ V("draws the observed life essence through its translucent membrane", "pulls the observed life essence into a pulsing inner vesicle"),
+ V("probes for spoils with budding membrane nubs", "reaches for spoils with an expanding ingestion pocket"),
+ V("warbles through membrane pops as its body sags", "contracts around a low wobbling internal hum"),
+ V("pops its membrane in a sharp percussive chain", "thrusts a blunt lobe upward through a bubbling rasp"));
+
+ AddSpecialized(
+ voices,
+ "butterfly",
+ V("kindles flame with rapid feeding-tube scrapes", "spreads flame beneath fanning wing scales"),
+ V("smothers flame beneath overlapping wings", "suppresses flame with downward wingbeat fans"),
+ V("folds wing edges into a visible cluster with kin", "links slender legs in a hanging cluster among kin"),
+ V("draws the observed life essence along its coiled feeding tube", "pulls the observed life essence between trembling mouthparts"),
+ V("probes for spoils with its feeding tube uncoiled", "reaches for spoils with its slender forelegs"),
+ V("flutters in broken pulses as its feeding tube curls", "bows its antennae beneath a thin wing-scale hiss"),
+ V("lashes its feeding tube through a burst of wingbeats", "claps its wings while its antennae snap outward"));
+
+ AddSpecialized(
+ voices,
+ "flower_bud",
+ V("kindles flame with rasping rootlets", "spreads flame with quick petal fans"),
+ V("smothers flame beneath closing petals", "suppresses flame with broad leaf sweeps"),
+ V("weaves rootlets into a visible cluster with kin", "presses closed crowns together in a dense cluster of kin"),
+ V("draws the observed life essence through its root hairs", "pulls the observed life essence into its layered bud"),
+ V("probes for spoils with uncurling rootlets", "reaches for spoils with cupped lower leaves"),
+ V("bows its stalk as its petals rustle in broken pulses", "folds its crown inward beneath a papery keening"),
+ V("snaps its petals wide with a dry crackle", "whips its leaves while its closed crown rasps"));
+
+ AddSpecialized(
+ voices,
+ "fly",
+ V("kindles flame with rasping mouthparts", "spreads flame beneath blurred wingbeats"),
+ V("smothers flame with hammering wing pulses", "suppresses flame beneath sweeping abdominal fans"),
+ V("hooks legs into a visible buzzing cluster with kin", "packs wing-to-wing inside a tight cluster of kin"),
+ V("draws the observed life essence through its sponging mouthparts", "pulls the observed life essence between rubbing forefeet"),
+ V("probes for spoils with forefeet and mouthparts", "reaches for spoils with its sponging tube extended"),
+ V("buzzes in broken drops as its forelegs cover its eyes", "folds its wings beneath a wavering high whine"),
+ V("grinds its forefeet beneath a piercing buzz", "flares its wings and spits a jagged wing whine"));
+
+ AddSpecialized(
+ voices,
+ "garl",
+ V("kindles flame with fibrous root scrapes", "spreads flame through whipping leaf tips"),
+ V("smothers flame beneath layered bulb skins", "suppresses flame with dense leaf fans"),
+ V("braids roots into a visible cluster with kin", "packs layered bulbs into a rustling cluster of kin"),
+ V("draws the observed life essence through its fibrous roots", "pulls the observed life essence between layered bulb skins"),
+ V("probes for spoils with fine root fibers", "reaches for spoils with curling leaf tips"),
+ V("bows its stalk beneath a long papery rustle", "closes its leaves as its bulb layers creak"),
+ V("lashes its leaves through a dry cutting hiss", "shakes its layered bulb in a hard papery rattle"));
+
+ AddSpecialized(
+ voices,
+ "grasshopper",
+ V("kindles flame with scraping hind legs", "spreads flame through forceful wing fans"),
+ V("smothers flame beneath stamping hind feet", "suppresses flame with downward wing pulses"),
+ V("folds hind legs into a visible cluster with kin", "crosses feelers inside a tight crouching cluster of kin"),
+ V("draws the observed life essence between side-working jaws", "pulls the observed life essence along its folded hind legs"),
+ V("probes for spoils with sweeping feelers", "reaches for spoils with both forefeet"),
+ V("scrapes a descending chirr as its hind legs fold", "crouches beneath a stuttering wing rattle"),
+ V("kicks both hind legs through a harsh chirr", "saws a jagged rasp from leg against wing"));
+
+ AddSpecialized(
+ voices,
+ "lemon_snail",
+ V("kindles flame with rapid radula strokes", "spreads flame with broad sweeps of its muscular foot"),
+ V("smothers flame beneath its muscular foot", "suppresses flame with wet mantle contractions"),
+ V("presses shells into a visible spiral cluster with kin", "overlaps muscular feet in a close cluster of kin"),
+ V("draws the observed life essence along its rasping radula", "pulls the observed life essence beneath its mantle"),
+ V("probes for spoils with extended eyestalks", "reaches for spoils with the front of its muscular foot"),
+ V("withdraws its eyestalks beneath a low shell scrape", "ripples its foot beneath a wavering mantle hiss"),
+ V("whips both feelers through a wet rasp", "rocks its shell while its radula grates sharply"));
+
+ AddSpecialized(
+ voices,
+ "lil_pumpkin",
+ V("kindles flame with rubbing tendril tips", "spreads flame through whipping vines"),
+ V("smothers flame beneath its ribbed body", "suppresses flame with coiling tendril sweeps"),
+ V("laces tendrils into a visible cluster with kin", "presses ribbed sides into a tight cluster of kin"),
+ V("draws the observed life essence through its curling tendrils", "pulls the observed life essence into its hollow core"),
+ V("probes for spoils with split tendril tips", "reaches for spoils with an uncoiling vine"),
+ V("droops its crown beneath a hollow internal knock", "curls every tendril as its ribbed body creaks"),
+ V("snaps its tendrils through a hollow body rattle", "jerks its crown upward while its vines whip"));
+
+ AddSpecialized(
+ voices,
+ "sand_spider",
+ V("kindles flame with rasping mouthparts", "spreads flame through rapid foreleg sweeps"),
+ V("smothers flame beneath four paired leg presses", "suppresses flame with dense silk casts"),
+ V("interlaces eight legs in a visible cluster with kin", "packs low beneath a lattice of touching legs with kin"),
+ V("draws the observed life essence through its mouthparts", "pulls the observed life essence along taut silk"),
+ V("probes for spoils with lifted forelegs", "reaches for spoils with hooked front feet"),
+ V("folds all eight legs beneath a dry mouthpart tremor", "drums an uneven cadence as its body flattens"),
+ V("rears four forelegs through a cutting rasp", "strikes its hooked feet together in a hard dry burst"));
+
+ AddSpecialized(
+ voices,
+ "scorpion",
+ V("kindles flame with grinding pincer tips", "spreads flame through arcing tail sweeps"),
+ V("smothers flame beneath closing pincers", "suppresses flame with broad plated-body sweeps"),
+ V("locks pincers into a visible cluster with kin", "arches tails over a tight cluster of kin"),
+ V("draws the observed life essence between its pincers", "pulls the observed life essence along its segmented tail"),
+ V("probes for spoils with open pincer tips", "reaches for spoils with one claw extended"),
+ V("lowers its tail beneath a wavering pincer clack", "folds its claws inward as its body plates rattle"),
+ V("snaps both pincers through a hard plated crackle", "lashes its tail overhead while its claws clack"));
+
+ AddSpecialized(
+ voices,
+ "smore",
+ V("kindles flame with fibrous stalk scrapes", "spreads flame through flapping crown layers"),
+ V("smothers flame beneath compressing crown layers", "suppresses flame with broad ribbon-leaf fans"),
+ V("presses stacked crowns into a visible cluster with kin", "weaves springy stalks through a close cluster of kin"),
+ V("draws the observed life essence through its fibrous stalks", "pulls the observed life essence between yielding crown layers"),
+ V("probes for spoils with ribbonlike leaves", "reaches for spoils with opening crown layers"),
+ V("compresses its crown beneath a soft layered flap", "folds its stalks inward through a wavering rustle"),
+ V("claps its crown layers in a sharp dry burst", "whips its ribbonlike leaves while its stacked body rattles"));
+ }
+}
diff --git a/IdleSpectator/ActivitySpeciesVoices.Mammals.Extended.cs b/IdleSpectator/ActivitySpeciesVoices.Mammals.Extended.cs
new file mode 100644
index 0000000..92ba879
--- /dev/null
+++ b/IdleSpectator/ActivitySpeciesVoices.Mammals.Extended.cs
@@ -0,0 +1,534 @@
+using System.Collections.Generic;
+
+namespace IdleSpectator;
+
+public static partial class ActivitySpeciesVoiceCatalog
+{
+ private static void AddMammalExtendedVoices(Dictionary voices)
+ {
+ AddExtended(
+ voices,
+ "alpaca",
+ V("hums through a raised muzzle in wavering notes", "sings a soft phrase while its long neck sways"),
+ V("courts with close humming and a lifted tail", "mates with long legs planted and neck extended"),
+ V("farms in light, padded steps with split lips busy", "plants and presses with its long neck lowered"),
+ V("brushes pollen onward through its trailing fleece", "carries pollen along its muzzle and wool"),
+ V("trades with ears upright and muzzle bobbing", "barters through soft hums and neck dips"),
+ V("fishes with neck stretched and split lips poised", "fishes with eyes lowered and padded feet held steady"),
+ V("hauls with fleece bunching above a straight back", "leans forward on padded feet and draws steadily"),
+ V("heals {target} through delicate split-lip nudges", "kneels and hums while licking {target} gently"),
+ V("stokes fire with its long neck drawn back", "fans the flames through quick muzzle dips"),
+ V("flees in long, rocking bounds with fleece flying", "gallops away on padded feet with neck extended"),
+ V("settles by folding long legs beneath thick fleece", "kneels carefully as padded joints fold under its chest"),
+ V("stands warrior-straight with neck high and ears fixed", "braces behind a spit and a forward kick"),
+ V("reads with long neck curved and ears still", "reads line by line through slow, precise head tilts"),
+ V("gathers life with split lips and careful foot placement", "gathers life with its long neck lowered"),
+ V("squats on folded hind legs with tail lifted", "relieves itself while balancing on padded feet"),
+ V("turns its long neck between conflicting directions", "steps sideways as its upright ears swivel unevenly"),
+ V("recharges kneeling beneath a curtain of fleece", "rests its weight low while its jaw rolls slowly"),
+ V("pivots stiff-legged as a strange urge takes hold", "stretches its neck forward and paws in short bursts"),
+ V("steals with soft-footed steps and mobile split lips", "snatches quickly, then retreats behind swaying fleece"),
+ V("jerks its long neck while its padded feet stamp", "moves in rigid bounds with ears pinned flat"),
+ V("dreams with folded legs twitching beneath its fleece", "hums faintly as its long neck shifts in sleep"));
+
+ AddExtended(
+ voices,
+ "armadillo",
+ V("squeaks a dry tune beneath its plated brow", "sings in clipped chirps while armor bands flex"),
+ V("courts by circling low and touching pointed snouts", "mates with broad claws braced beneath overlapping armor"),
+ V("farms by raking in alternating foreclaw strokes", "plants with snout low and shell rocking"),
+ V("pushes pollen onward with its narrow snout", "carries pollen beneath its plated underside"),
+ V("trades with quick sniffs and foreclaw taps", "barters from beneath its armored brow"),
+ V("fishes with broad claws poised and snout extended", "fishes low while armor bands rise with each breath"),
+ V("hauls backward with digging claws locked down", "pushes steadily behind an armored shoulder"),
+ V("heals {target} through small snout touches", "heals {target} while keeping broad foreclaws tucked"),
+ V("stokes fire with short foreclaw scrapes", "fans the flames from beneath its plated brow"),
+ V("flees in a rapid armored scuttle", "scrambles away with armor bands pumping over short legs"),
+ V("settles by scraping with broad foreclaws", "turns in a low circle and tucks beneath its shell"),
+ V("faces battle behind overlapping plates and flexed claws", "holds a warrior crouch with pointed snout forward"),
+ V("reads with snout tracking side to side", "reads steadily beneath a motionless plated brow"),
+ V("gathers life through careful sniffs and shallow scrapes", "gathers life with broad claws opening lightly"),
+ V("raises its armored tail and crouches low", "relieves itself with foreclaws planted wide"),
+ V("scuttles in crossing circles with snout darting", "halts halfway into a curl and opens again"),
+ V("recharges curled around its soft underside", "rests low while overlapping bands loosen"),
+ V("scrabbles abruptly under a strange urge", "rises on hind feet and paddles broad claws"),
+ V("steals with pointed snout low and claws silent", "hooks away quickly beneath its plated body"),
+ V("bucks beneath its armor and rakes both claws forward", "uncurls in rigid jolts with snout snapping upward"),
+ V("dreams curled tightly as armor bands pulse", "scrapes faintly in sleep with one broad foreclaw"));
+
+ AddExtended(
+ voices,
+ "bandit",
+ V("sings under the breath with one hand at the throat", "threads a low tune through quick measured breaths"),
+ V("courts through close gestures and deliberate body turns", "mates with hands braced and hips rocking steadily"),
+ V("farms in a crouch with quick, exact handwork", "plants through alternating reaches and fingertip presses"),
+ V("dusts pollen onward with nimble fingertips", "transfers pollen through quick turns of both wrists"),
+ V("trades through clipped words and counting fingers", "barters with one hand held close"),
+ V("fishes from a low stance with both hands poised", "fishes with narrowed eyes and still shoulders"),
+ V("hauls with bent knees and both arms drawing", "shifts its grip through compact hand-over-hand pulls"),
+ V("heals {target} with fast, precise fingers", "heals {target} with one hand braced and the other pressing"),
+ V("stokes fire with face turned and forearm raised", "fans the flames through quick wrist turns"),
+ V("flees through sharp turns and low sprinting steps", "retreats with shoulders tucked and hands close"),
+ V("settles by lowering one foot and then the other", "crouches with shoulders tucked and hands drawn close"),
+ V("takes a warrior stance with hands high and knees loose", "advances behind feints and a narrow profile"),
+ V("reads with one finger marking each line", "reads in quick jumps of narrowed eyes"),
+ V("gathers life with cupped hands and exact fingertips", "gathers life while shifting between knees and toes"),
+ V("squats with back turned and shoulders alert", "relieves itself while checking both sides"),
+ V("cycles through three interrupted gestures", "turns twice with hands hovering at different angles"),
+ V("recharges in a tight crouch with hands tucked", "rests lightly while breathing through closed lips"),
+ V("moves under a strange urge through repeated wrist flicks", "paces a tight loop while fingers flex in sequence"),
+ V("steals with a hooked finger and immediate retreat", "slips close, palms quickly, and turns away"),
+ V("moves in clipped angles with hands rigidly spread", "jerks upright as each shoulder pulls against the other"),
+ V("dreams with fingers twitching against folded arms", "makes silent feints while curled in shallow sleep"));
+
+ AddExtended(
+ voices,
+ "bear",
+ V("sings in deep pulses through a broad muzzle", "rumbles a tune while massive shoulders sway"),
+ V("courts upright with muzzle rubbing and heavy huffs", "mates with broad hind paws planted and forepaws braced"),
+ V("farms through deep scoops of long curved claws", "plants with shoulders rolling behind both paws"),
+ V("smears pollen onward across its broad muzzle", "carries pollen through thick fur on wide paws"),
+ V("trades with low grunts and open forepaws", "barters upright on heavy haunches"),
+ V("fishes with muzzle low and one forepaw hovering", "fishes by swiping with long curved claws"),
+ V("hauls with jaws set and massive shoulders driving", "drags backward on broad plantigrade paws"),
+ V("heals {target} with small foreclaw presses", "heals {target} through close muzzle touches"),
+ V("stokes fire with muzzle lifted and forearms back", "fans the flames with broad furred paws"),
+ V("flees in a pounding four-pawed gallop", "lumbers away as heavy shoulders rise and fall"),
+ V("settles by turning its broad body and scraping once", "drops onto its haunches before curling muzzle to paws"),
+ V("rises warrior-tall with both forepaws spread", "charges behind a roar and rolling shoulders"),
+ V("reads upright with forepaws held against its chest", "reads through slow sweeps of its broad muzzle"),
+ V("gathers life between broad cupped paws", "gathers life with claw tips beneath a lowered muzzle"),
+ V("squats heavily with short tail lifted", "relieves itself on braced hind paws"),
+ V("swings its broad head through opposing arcs", "rises halfway, drops down, and turns again"),
+ V("recharges curled densely with paws over muzzle", "rests on its haunches while shoulders slowly slacken"),
+ V("rocks upright under a strange urge and bats above its chest", "paces heavily while rubbing both forepaws together"),
+ V("steals with one broad paw and a backward shuffle", "hooks away quickly beneath a lowered muzzle"),
+ V("rears in stiff jolts with foreclaws spread", "lurches on all fours as its broad head snaps sideways"),
+ V("dreams with paws kneading and muzzle rumbling", "paddles all four paws while twitching on its side"));
+
+ AddExtended(
+ voices,
+ "buffalo",
+ V("sings in a chest-deep bellow beneath curved horns", "rolls a low tune through its beard and broad muzzle"),
+ V("courts by circling with horned head held broadside", "mates on planted hooves beneath a rising shoulder hump"),
+ V("farms with broad muzzle low and hooves pressing firmly", "plants through short, horn-guided pushes"),
+ V("brushes pollen onward through its hanging beard", "carries pollen across its broad muzzle"),
+ V("trades through deep grunts and measured horn dips", "barters broadside on four hooves"),
+ V("fishes with nostrils flared and horned brow low", "fishes motionless with beard hanging"),
+ V("hauls through its neck and massive shoulder hump", "leans forward as broad hooves dig in"),
+ V("nudges and licks {target} slowly", "heals {target} with curved horns angled aside"),
+ V("stokes fire with horned brow lowered", "fans the flames with short, heavy head sweeps"),
+ V("flees in a rolling gallop beneath tossing horns", "thunders away with shoulder hump surging"),
+ V("settles by folding thick legs under a massive chest", "turns broadside and lowers its horned head"),
+ V("holds a warrior line with horns level and hooves spread", "drives forward behind its heavy skull"),
+ V("reads with broad muzzle tracing each line", "reads through slow turns of its horned head"),
+ V("gathers life using careful muzzle sweeps", "gathers life low beneath its brushing beard"),
+ V("arches its heavy tail and spreads its hind hooves", "relieves itself beneath a level horned head"),
+ V("pivots its horned head while hooves step out of rhythm", "starts a charge, checks, and turns broadside"),
+ V("recharges chest-down with legs folded beneath", "stands ruminating while its shoulder hump settles"),
+ V("bucks under a strange urge and tosses both horns", "stamps in a tight square with beard swinging"),
+ V("steals by hooking quickly with its broad muzzle", "edges away behind a shield of curved horns"),
+ V("lurches in rigid surges with horns sweeping", "stamps unevenly as its heavy head jerks low"),
+ V("dreams with hooves kicking beneath a heaving chest", "bellows faintly while its horned head shifts"));
+
+ AddExtended(
+ voices,
+ "capybara",
+ V("sings in soft whistles through a blunt muzzle", "purrs a bubbling tune with rounded ears flicking"),
+ V("courts through nose touches and close body circling", "mates on short legs with webbed toes spread"),
+ V("farms with broad incisors clipping and forefeet pressing", "plants low behind a blunt muzzle"),
+ V("pushes pollen onward with whiskers spread", "carries pollen across its bobbing blunt nose"),
+ V("trades through soft whistles and brief muzzle dips", "barters seated squarely on folded feet"),
+ V("fishes with webbed toes braced and whiskers forward", "fishes with blunt chin held low"),
+ V("hauls by gripping firmly with broad incisors", "pushes forward on short legs behind a broad chest"),
+ V("nibbles {target} lightly with broad incisors", "heals {target} with careful forefoot presses"),
+ V("stokes fire with blunt muzzle tilted away", "fans the flames through short head bobs"),
+ V("flees in compact bounds on short legs", "scampers away with webbed toes splayed wide"),
+ V("settles by folding its feet under a barrel body", "turns once and rests its blunt chin low"),
+ V("faces battle with incisors bared and chest low", "holds a compact warrior crouch on splayed toes"),
+ V("reads with whiskers brushing close to each line", "reads through small turns of its blunt muzzle"),
+ V("gathers life with incisors and careful forefeet", "gathers life with whiskers fanned around its muzzle"),
+ V("raises its short tail and squats on splayed hind toes", "relieves itself with barrel body held level"),
+ V("bobs between directions while rounded ears flick", "scampers a half-circle and freezes nose-first"),
+ V("recharges in a square loaf on folded feet", "rests chin-down while its barrel sides slow"),
+ V("hops repeatedly as a strange urge takes hold", "bobs its blunt head and paddles both forefeet"),
+ V("steals with a quick incisor grip and low retreat", "nudges close, snatches, and scampers away"),
+ V("jerks in compact hops with incisors exposed", "paddles stiff forefeet while its blunt head twists"),
+ V("dreams with webbed toes twitching beneath its body", "whistles faintly as its blunt muzzle bobs"));
+
+ AddExtended(
+ voices,
+ "cat",
+ V("sings in rising yowls with whiskers pushed forward", "trills a tune while its tail curls and uncurls"),
+ V("courts through calling, circling, and cheek presentation", "mates with hind paws planted and tail held aside"),
+ V("farms with precise paw scrapes and close sniffing", "plants with tucked claws and twitching tail"),
+ V("brushes pollen onward on silent paws", "carries pollen across whiskers and cheek fur"),
+ V("trades with measured chirps and one careful paw", "barters seated behind a curling tail"),
+ V("fishes with body flattened and forepaw hovering", "fishes by striking with unsheathed claws"),
+ V("hauls backward with teeth set and paws braced", "hooks and draws with curved foreclaws"),
+ V("licks {target} roughly between gentle paw touches", "heals {target} with whiskers forward and claws tucked"),
+ V("stokes fire with whiskers drawn back", "fans the flames with its curling tail"),
+ V("flees in low, elastic bounds with tail streaming", "springs away as hind claws drive hard"),
+ V("settles by kneading twice and circling tightly", "folds paws beneath its chest and wraps its tail"),
+ V("takes a warrior crouch with back rippling", "advances sideways with ears flat and claws bare"),
+ V("reads with pupils tracking steadily across each line", "reads through tiny whiskered head turns"),
+ V("gathers life with delicate paw hooks", "gathers life while nose and whiskers pulse"),
+ V("squats with hind legs spread and tail lifted clear", "relieves itself before scraping with both forepaws"),
+ V("turns after its own tail, then freezes abruptly", "steps toward two directions with ears swiveling apart"),
+ V("recharges curled nose-to-tail with paws hidden", "rests in a compact loaf while whiskers slacken"),
+ V("chatters under a strange urge and paws repeatedly", "arches, sidesteps, and lashes its tail without pause"),
+ V("steals with a silent paw hook and backward spring", "closes its teeth quickly and slips away low"),
+ V("stalks in rigid steps with pupils stretched wide", "jerks its head sideways while claws open and close"),
+ V("dreams with paws kneading and tail tip flicking", "chirps asleep as hind legs make tiny pounces"));
+
+ AddExtended(
+ voices,
+ "cow",
+ V("sings in long lowing notes through a broad muzzle", "rolls a slow tune beneath a swinging dewlap"),
+ V("courts with flank sniffing and chin resting across a back", "mates on cloven hooves with tail raised aside"),
+ V("farms with broad muzzle sweeping and hooves pressing", "plants in slow passes beneath a wide forehead"),
+ V("sweeps pollen onward across its broad muzzle", "carries pollen on its rough tongue and nose"),
+ V("trades through low calls and slow forehead dips", "barters while chewing between low signals"),
+ V("fishes with broad muzzle lowered and nostrils flaring", "fishes on quietly planted cloven hooves"),
+ V("hauls with broad chest forward and neck straight", "draws steadily as cloven hooves brace"),
+ V("licks {target} with a broad rough tongue", "heals {target} with its forehead angled aside"),
+ V("stokes fire with broad muzzle lifted", "fans the flames with slow tail switches"),
+ V("flees in a heavy gallop with dewlap swinging", "runs away on pounding cloven hooves"),
+ V("settles by folding its forelegs beneath a broad belly", "turns slowly and lowers its heavy body"),
+ V("holds a warrior stance with forehead low and hooves wide", "drives ahead behind a swinging horned head"),
+ V("reads with broad muzzle moving along each line", "reads through slow, square head turns"),
+ V("gathers life using tongue, muzzle, and careful hooves", "gathers life low beneath a broad forehead"),
+ V("raises its tail and spreads its hind hooves", "relieves itself while continuing a slow jaw roll"),
+ V("steps forward and back while its broad head swings", "turns from one side to the other with nostrils flaring"),
+ V("recharges belly-down while chewing in circles", "rests on folded legs with tail and ears barely moving"),
+ V("kicks its hind heels under a strange urge", "sidesteps repeatedly with forehead dipping"),
+ V("steals with a swift tongue curl and muzzle withdrawal", "edges close, closes its broad lips, and backs away"),
+ V("stamps in uneven beats as its head jerks", "lurches broadside with tail rigid and jaw still"),
+ V("dreams with cloven hooves twitching under its belly", "lows softly as its broad muzzle shifts"));
+
+ AddExtended(
+ voices,
+ "dog",
+ V("sings in rising howls with muzzle lifted", "threads yips into a tune while its tail keeps time"),
+ V("courts through circling, sniffing, and close tail signals", "mates on braced paws with hindquarters aligned"),
+ V("farms by digging in alternating forepaw strokes", "plants nose-first with tail held level"),
+ V("pushes pollen onward with repeated nose passes", "carries pollen across its muzzle with ears forward"),
+ V("trades through short barks and alternating paw taps", "barters seated upright on its haunches"),
+ V("fishes with nose low and one forepaw raised", "fishes with a sudden snap after holding still"),
+ V("hauls with jaws firm and all four paws driving", "pulls backward while shoulders bunch"),
+ V("licks and nudges {target} carefully", "heals {target} with ears fixed forward"),
+ V("stokes fire with nose turned and tail lowered", "fans the flames through quick paw strokes"),
+ V("flees in long bounds with ears swept back", "sprints away as hind paws drive beneath its body"),
+ V("settles by circling twice and testing with its nose", "scrapes briefly, then folds nose beneath tail"),
+ V("stands warrior-alert with hackles raised and paws spread", "advances behind bared teeth and braced forelegs"),
+ V("reads with nose tracing beneath each line", "reads through quick head tilts"),
+ V("gathers life with nose close and forepaws moving", "gathers life with careful jaw grips and short sniffs"),
+ V("squats on bent hind legs with tail lifted", "relieves itself while forepaws hold steady"),
+ V("tilts its head from side to side and circles", "starts forward, wheels back, and sniffs again"),
+ V("recharges curled tightly with nose beneath tail", "rests flank-down while paws and ears slacken"),
+ V("chases a strange urge through tight, repeated circles", "bows, springs, and paws in quick succession"),
+ V("steals with a quick jaw grip and bounding retreat", "slips close nose-first, snatches, and trots away"),
+ V("moves in stiff lunges with hackles standing", "opens and closes its jaws while its head jerks sharply"),
+ V("dreams with paws running and muzzle softly yipping", "twitches on its side as its tail taps"));
+
+ AddExtended(
+ voices,
+ "fox",
+ V("sings in clear yips through a pointed muzzle", "threads rasping notes while its brush sways"),
+ V("courts with gekker calls and brush-led circles", "mates on narrow paws with brush lifted aside"),
+ V("farms through neat forepaw scrapes and precise sniffs", "plants lightly with pointed muzzle low"),
+ V("brushes pollen onward with its trailing brush", "carries pollen across its narrow muzzle"),
+ V("trades through quick chirps and delicate paw gestures", "barters seated behind a curled brush"),
+ V("fishes from a still crouch with ears fixed", "fishes by pouncing forepaws-first"),
+ V("hauls with narrow jaws set and paws skimming backward", "draws in short pulls beneath a level brush"),
+ V("nibbles and licks {target} delicately", "heals {target} with pointed ears held forward"),
+ V("stokes fire with whiskers tucked and brush high", "fans the flames with quick brush sweeps"),
+ V("flees in light bounds with brush streaming", "darts away on narrow paws through abrupt turns"),
+ V("settles by circling tightly beneath its own brush", "scrapes with quick forepaws and tucks its muzzle"),
+ V("takes a warrior crouch with ears flat and brush level", "darts forward behind bared narrow teeth"),
+ V("reads with pointed muzzle tracking each line", "reads with ears pricked and brush curled close"),
+ V("gathers life using precise paw taps and muzzle touches", "gathers life lightly with whiskers fanned"),
+ V("arches its brush and crouches on narrow hind paws", "relieves itself with pointed muzzle held alert"),
+ V("pivots between sounds with ears pointing apart", "pounces one way, checks, and circles back"),
+ V("recharges curled beneath its sweeping brush", "rests with pointed muzzle tucked and paws hidden"),
+ V("springs vertically under a strange urge", "gekker-calls while whipping around after its brush"),
+ V("steals with a delicate bite and instant sidestep", "slips close on narrow paws and darts away"),
+ V("stalks in angular jolts with brush rigid", "snaps sideways as its pointed ears flatten"),
+ V("dreams with narrow paws paddling beneath its brush", "yips faintly while its pointed muzzle twitches"));
+
+ AddExtended(
+ voices,
+ "goat",
+ V("sings in broken bleats beneath a lifted chin", "trills nasally while its beard quivers"),
+ V("courts through horn rubs, sniffs, and raised forequarters", "mates on hard cloven hooves with hind legs braced"),
+ V("farms with split lips clipping and hooves pressing", "plants through short, horn-guided pushes"),
+ V("pushes pollen onward with mobile split lips", "carries pollen along its beard and muzzle"),
+ V("trades through nasal calls and compact horn dips", "barters balanced squarely on hard hooves"),
+ V("fishes with horizontal pupils fixed and muzzle low", "fishes with forehooves planted close"),
+ V("hauls with forehead down and cloven hooves gripping", "draws in springing pulls through its narrow chest"),
+ V("licks {target} with careful lip and tongue strokes", "heals {target} with horns angled along its back"),
+ V("stokes fire with beard lifted and muzzle back", "fans the flames through compact head tosses"),
+ V("flees in steep, springing bounds", "scampers away with beard and short tail raised"),
+ V("settles by placing each hoof and folding narrow legs", "turns once with horns high before kneeling"),
+ V("stands warrior-ready on stiff legs with horns forward", "rears and drives down behind a compact headbutt"),
+ V("reads with horizontal pupils following each line", "reads through tiny bearded head tilts"),
+ V("gathers life with mobile lips and exact hoof placement", "gathers life close beneath its brushing beard"),
+ V("lifts its short tail and squats on bent hind legs", "relieves itself with forehooves planted together"),
+ V("hops between positions while horizontal pupils scan", "starts to rear, drops, and turns in place"),
+ V("recharges chest-down on folded narrow legs", "rests squarely while chewing with a sideways jaw"),
+ V("rears repeatedly under a strange urge", "twists stiff-legged while tapping its horns together"),
+ V("steals with split lips and a backward hop", "snatches quickly, then bounds clear on hard hooves"),
+ V("bucks in rigid bursts with beard snapping", "jerks its horned head while hooves stamp crosswise"),
+ V("dreams with stiff legs kicking beneath its chest", "bleats softly as its beard and muzzle twitch"));
+
+ AddExtended(
+ voices,
+ "hyena",
+ V("sings in whooping pulses through heavy jaws", "cackles a jagged tune beneath rounded ears"),
+ V("courts through close sniffing and sloping-body circles", "mates with powerful forequarters braced and hindquarters aligned"),
+ V("farms with crushing jaws and alternating forepaw scrapes", "plants low beneath raised shoulders"),
+ V("pushes pollen onward with persistent muzzle passes", "carries pollen across its heavy muzzle"),
+ V("trades through whoops and measured jaw clacks", "barters from a high-shouldered stance"),
+ V("fishes with heavy head low and rounded ears fixed", "fishes by snapping from braced forequarters"),
+ V("hauls with jaws locked and shoulders driving", "drags backward as the sloping back tightens"),
+ V("nibbles {target} carefully with its front teeth", "heals {target} with massive jaws held still"),
+ V("stokes fire with heavy muzzle turned aside", "fans the flames through powerful forepaw strokes"),
+ V("flees in an endurance lope with back sloping", "runs away as high shoulders pump steadily"),
+ V("settles by circling on long forelegs and lowering its jaws", "folds belly-down beneath its raised shoulders"),
+ V("takes a warrior stance with crushing jaws open", "surges forward behind powerful forequarters"),
+ V("reads with heavy muzzle moving under each line", "reads while rounded ears remain still"),
+ V("gathers life with strong forepaws and controlled incisors", "gathers life beneath a lowered heavy neck"),
+ V("squats with short hindquarters lowered and tail raised", "relieves itself while forelegs stay nearly straight"),
+ V("lopes a crooked loop and snaps back around", "shifts between crouch and standing as ears swivel"),
+ V("recharges belly-down with jaws across both paws", "rests on one flank while high shoulders loosen"),
+ V("cackles under a strange urge and wheels repeatedly", "bounds crookedly while its heavy jaws open and close"),
+ V("steals with a crushing jaw grip and loping retreat", "creeps in high-shouldered, snatches, and wheels away"),
+ V("lurches behind rigid forequarters with jaws clacking", "twists its sloping body as the heavy head jerks"),
+ V("dreams with jaws opening and long forelegs twitching", "whoops faintly while curled beneath raised shoulders"));
+
+ AddExtended(
+ voices,
+ "monkey",
+ V("sings in patterned hoots while both hands beat time", "threads chatter into a tune with tail balancing"),
+ V("courts through grooming gestures and close body displays", "mates with hands braced and long tail held clear"),
+ V("farms with nimble thumbs turning and pressing", "plants from a squat with both hands"),
+ V("moves pollen with careful finger-and-thumb pinches", "carries pollen on fingertips while its tail counterbalances"),
+ V("trades through rapid chatter and open-palmed gestures", "barters by counting across nimble fingers"),
+ V("fishes in a crouch with one hand hovering", "fishes by snatching while the other hand braces"),
+ V("hauls with both hands clasped and feet pushing", "draws backward with long tail held straight"),
+ V("heals {target} with precise fingertips", "heals {target} carefully with both hands while squatting"),
+ V("stokes fire with quick hands and face turned aside", "fans the flames with open palms"),
+ V("flees in four-limbed bounds with tail streaming", "scrambles away as hands and feet alternate rapidly"),
+ V("settles by patting and turning with both hands", "squats low and wraps its long tail close"),
+ V("takes a warrior crouch with hands spread and teeth bared", "leaps forward behind a slap and grappling reach"),
+ V("reads with one finger following each line", "reads through quick eye shifts and head tilts"),
+ V("gathers life through nimble two-handed sorting", "gathers life with precise thumb-and-finger pinches"),
+ V("squats deep with tail lifted clear", "relieves itself while balancing on feet and one hand"),
+ V("reaches three ways while its tail counters each turn", "rises on its hind feet, drops, and chatters in place"),
+ V("recharges curled with hands beneath its chin", "rests in a compact squat while tail wraps close"),
+ V("claps repeatedly under a strange urge", "leaps and lands while fingers spread and curl"),
+ V("steals with one quick hand and a tail-balanced retreat", "palms swiftly, then bounds away on all fours"),
+ V("jerks through broken gestures with fingers splayed", "scrambles in place as head and tail snap opposite ways"),
+ V("dreams with fingers grasping and tail slowly curling", "chatters softly while hands paddle beneath its chin"));
+
+ AddExtended(
+ voices,
+ "rabbit",
+ V("sings in soft honks with nose pulsing rapidly", "chatters a tiny rhythm beneath upright ears"),
+ V("courts through circling, chin contact, and high leaps", "mates on powerful hind feet with ears laid back"),
+ V("farms with rapid forepaw scrapes and incisor clips", "plants crouched on folded hind legs"),
+ V("pushes pollen onward through quick nose-first hops", "carries pollen on its muzzle with ears upright"),
+ V("trades through nose touches and light forepaw taps", "barters sitting tall on long hind feet"),
+ V("fishes from a low crouch with ears fixed forward", "fishes with nose rapidly twitching"),
+ V("hauls with incisors gripping and hind feet pushing", "draws backward through quick, low hops"),
+ V("licks and nibbles {target} gently", "heals {target} with upright ears held still"),
+ V("stokes fire with short forepaw scrapes", "fans the flames through quick nose-first hops"),
+ V("flees in accelerating bounds on long hind feet", "darts away through sharp leaps with ears flattened"),
+ V("settles by scraping with both forepaws and turning", "folds hind legs beneath a compact loaf"),
+ V("takes a warrior posture tall on hind feet", "boxes forward with rapid forepaw strikes"),
+ V("reads with nose tracking beneath each line", "reads while one upright ear swivels"),
+ V("gathers life with incisors clipping and forepaws pressing", "gathers life from a low hind-leg crouch"),
+ V("raises its short tail over bent hind legs", "relieves itself in a compact crouch"),
+ V("hops toward one side while both ears point elsewhere", "freezes, turns, and launches into a second direction"),
+ V("recharges in a compact loaf with feet hidden", "rests stretched low while long ears settle"),
+ V("leaps and twists under a strange urge", "darts in tight circles before kicking both hind feet"),
+ V("steals with one incisor nip and a sudden bound", "edges close nose-first, snatches, and darts away"),
+ V("jerks through crooked hops with ears rigid", "boxes forward as its nose stops twitching"),
+ V("dreams with hind feet kicking beneath a compact body", "honks faintly while ears and whiskers twitch"));
+
+ AddExtended(
+ voices,
+ "raccoon",
+ V("sings in raspy trills with black forepaws clasped", "chirrs a tune while its ringed tail keeps balance"),
+ V("courts through face sniffing and two-pawed grooming", "mates on plantigrade paws with ringed tail held aside"),
+ V("farms with sensitive fingers sifting and turning", "plants while crouched behind a masked face"),
+ V("moves pollen delicately with both black paws", "carries pollen on sensitive fingers with ringed tail trailing"),
+ V("trades through chirrs and quick finger counts", "barters sitting upright on plantigrade haunches"),
+ V("fishes with sensitive forepaws spread and hovering", "fishes by plunging both black paws together"),
+ V("hauls with fingers hooked and arched back pulling", "draws backward on nimble plantigrade paws"),
+ V("heals {target} through careful two-pawed touches", "heals {target} fingertip-first beneath its mask"),
+ V("stokes fire with black paws held back", "fans the flames with its raised ringed tail"),
+ V("flees in an arched-back gallop with tail streaming", "scampers away on nimble plantigrade paws"),
+ V("settles by patting around with both sensitive paws", "turns and curls masked muzzle against ringed tail"),
+ V("stands warrior-upright with black claws spread", "lunges from its haunches behind both grasping paws"),
+ V("reads with one black finger tracing each line", "reads beneath motionless dark facial markings"),
+ V("gathers life through two-pawed feeling and precise pinches", "gathers life with sensitive fingers spread"),
+ V("squats on plantigrade hind paws with ringed tail raised", "relieves itself while both forepaws stay planted"),
+ V("rubs its paws together, turns, and checks again", "reaches in opposite directions beneath a twitching mask"),
+ V("recharges curled around its ringed tail", "rests on its side with black forepaws folded"),
+ V("rubs its forepaws under a strange urge", "rolls and rights itself while ringed tail lashes"),
+ V("steals with both sensitive paws and a quick tuck", "palms swiftly beneath its chest and scampers away"),
+ V("jerks upright with black fingers rigidly spread", "paddles both forepaws as its masked head snaps"),
+ V("dreams with black paws rubbing and ringed tail twitching", "chirrs asleep while sensitive fingers flex"));
+
+ AddExtended(
+ voices,
+ "rat",
+ V("sings in thin squeaks while whiskers keep rhythm", "chirps a quick tune between soft incisor bruxes"),
+ V("courts through whisker contact and rapid close circling", "mates on small hind feet with bare tail extended"),
+ V("farms by gnawing, scraping, and pressing with pink paws", "plants low behind chisel incisors"),
+ V("sweeps pollen onward with fanned whiskers", "carries pollen across its pointed muzzle"),
+ V("trades through rapid squeaks and clasped pink paws", "barters upright with bare tail balancing"),
+ V("fishes with pointed muzzle low and paws hovering", "fishes by snapping with chisel incisors"),
+ V("hauls with incisors locked and hind feet driving", "drags backward while bare tail braces each turn"),
+ V("licks {target} between tiny paw presses", "heals {target} beneath a fan of trembling whiskers"),
+ V("stokes fire with whiskers pulled back", "fans the flames through rapid forepaw strokes"),
+ V("flees in a low scurry with bare tail streaming", "darts away through tight turns on close-set feet"),
+ V("settles by scraping rapidly and curling around its tail", "turns in place before tucking pointed muzzle down"),
+ V("stands warrior-upright with incisors bared", "rushes low behind whiskers and chisel teeth"),
+ V("reads with pointed muzzle passing beneath each line", "reads while round ears hold still"),
+ V("gathers life using pink paws and precise incisor nips", "gathers life with whiskers sweeping both sides"),
+ V("squats on small hind feet with bare tail lifted", "relieves itself while forepaws hover at its chest"),
+ V("scurries in two crossing arcs and freezes upright", "turns with whiskers aimed one way and ears another"),
+ V("recharges curled tightly around its bare tail", "rests belly-down with pointed muzzle on pink paws"),
+ V("bruxes rapidly under a strange urge and wheels", "clasps its paws while bare tail lashes in circles"),
+ V("steals with a fast incisor grip and low retreat", "snatches between pink paws and scurries away"),
+ V("jerks upright with incisors chattering hard", "runs in broken circles as its bare tail stiffens"),
+ V("dreams with pink paws clasping and tail curling", "squeaks asleep while whiskers pulse rapidly"));
+
+ AddExtended(
+ voices,
+ "rhino",
+ V("sings in rough squeals beneath a heavy horn", "rumbles a blunt tune through thick folded lips"),
+ V("courts through horn-side rubbing and close scenting", "mates on three-toed feet with massive shoulders braced"),
+ V("farms by pressing with broad lip and heavy feet", "plants through short, horn-led pushes"),
+ V("sweeps pollen onward with its square lip", "carries pollen across thick folded lips"),
+ V("trades through rough snorts and slow horn dips", "barters standing square on three-toed feet"),
+ V("fishes with small ears fixed and broad lip low", "fishes beneath a level horn"),
+ V("hauls with horn base low and shoulders driving", "leans its folded hide forward on stout legs"),
+ V("heals {target} through broad-lip nudges", "heals {target} with heavy horn angled aside"),
+ V("stokes fire with horn and muzzle lifted", "fans the flames through heavy head sweeps"),
+ V("flees in a pounding charge on three-toed feet", "runs away with folded hide shaking over thick shoulders"),
+ V("settles by folding stout legs beneath thick hide", "turns heavily and lowers horn and chin"),
+ V("holds a warrior line with horn level", "charges forward behind massive skull and shoulders"),
+ V("reads with square lip passing beneath each line", "reads through slow horned head sweeps"),
+ V("gathers life with broad lip and careful foot pressure", "gathers life low beneath its heavy horn"),
+ V("raises its short tail and bends thick hind legs", "relieves itself while three-toed feet stay spread"),
+ V("pivots heavily as small ears point opposite ways", "starts a charge, halts, and swings its horn aside"),
+ V("recharges flank-down on thick folded hide", "rests with stout legs tucked and horn angled low"),
+ V("bucks under a strange urge and tosses its horn", "stamps a tight pattern on three-toed feet"),
+ V("steals with a quick square-lip grip and shoulder turn", "edges close beneath its horn and tramps away"),
+ V("lurches in rigid charges as its horn snaps sideways", "stamps unevenly beneath twitching folded hide"),
+ V("dreams with three-toed feet pushing and horn shifting", "rumbles asleep while its thick lips pulse"));
+
+ AddExtended(
+ voices,
+ "sheep",
+ V("sings in wavering bleats through a narrow muzzle", "threads soft nasal notes while dense fleece trembles"),
+ V("courts through woolly cheek rubs and close circling", "mates on narrow hooves with fleece pressed close"),
+ V("farms with split lip clipping and small hoof presses", "plants beneath a lowered woolly brow"),
+ V("brushes pollen onward through its fleece", "carries pollen on its muzzle and wool"),
+ V("trades through short baas and gentle forehead dips", "barters while standing square beneath its fleece"),
+ V("fishes with narrow muzzle low and ears angled forward", "fishes on close-planted hooves"),
+ V("hauls with fleece bunching over narrow shoulders", "draws steadily while small hooves brace"),
+ V("heals {target} through careful muzzle nudges", "heals {target} with woolly forehead angled aside"),
+ V("stokes fire with fleece held back", "fans the flames through quick muzzle dips"),
+ V("flees in stiff, bouncing strides with wool shaking", "runs away on narrow hooves beneath dense fleece"),
+ V("settles by folding slim legs beneath a round fleece", "turns once and tucks muzzle against wool"),
+ V("takes a warrior stance behind lowered woolly brow", "drives forward from braced hooves with forehead first"),
+ V("reads with narrow muzzle tracing below each line", "reads while ears angle from the fleece"),
+ V("gathers life with split lip and delicate hoof placement", "gathers life beneath a curtain of wool"),
+ V("raises its short tail over bent hind legs", "relieves itself with narrow forehooves together"),
+ V("steps in a tight square while ears angle apart", "lowers its forehead, checks, and turns again"),
+ V("recharges round-bodied on folded legs", "rests muzzle-deep against fleece while sides slow"),
+ V("springs stiff-legged under a strange urge", "thrusts its forehead forward and hops backward"),
+ V("steals with split lips and a quick woolly turn", "nudges close, grips briefly, and trots away"),
+ V("bucks in rigid hops with fleece shuddering", "jerks its woolly forehead down as hooves cross"),
+ V("dreams with narrow hooves twitching beneath fleece", "bleats faintly while its woolly cheek shifts"));
+
+ AddExtended(
+ voices,
+ "unicorn",
+ V("sings in clear nickers beneath its spiral horn", "whinnies a bright tune while its long mane ripples"),
+ V("courts through arched-neck passes and muzzle touches", "mates on bright cloven hooves with horn held high"),
+ V("farms with precise hoof presses and horn-guided turns", "plants beneath a flowing mane"),
+ V("pushes pollen onward with mobile lips", "carries pollen along its muzzle beneath a lifted horn"),
+ V("trades through bell-like nickers and measured head dips", "barters with spiral horn upright"),
+ V("fishes with horn angled aside and muzzle low", "fishes on motionless cloven hooves"),
+ V("hauls with arched neck straightening into each pull", "draws steadily while bright hooves brace"),
+ V("heals {target} through gentle touches of mobile lips", "heals {target} with spiral horn angled past one shoulder"),
+ V("stokes fire with mane and tail drawn back", "fans the flames through high forehoof strokes"),
+ V("flees in a light canter with mane streaming", "gallops away beneath a level spiral horn"),
+ V("settles by folding bright legs and curving horn aside", "turns once before resting beneath its mane"),
+ V("stands warrior-tall with spiral horn aligned", "surges forward behind high forehooves and lowered horn"),
+ V("reads with muzzle following beneath each line", "reads through small, poised turns of its horn"),
+ V("gathers life with mobile lips and exact hoof placement", "gathers life with spiral horn lifted"),
+ V("raises its flowing tail and bends its hind legs", "relieves itself on balanced cloven hooves"),
+ V("steps high in crossing directions with ears flicking", "turns its arched neck twice and paws once"),
+ V("recharges on folded legs with mane draped close", "rests muzzle-low while its spiral horn angles aside"),
+ V("rears under a strange urge and paws in sequence", "canters a tight ring with mane and tail streaming"),
+ V("steals with mobile lips and a light backward step", "dips beneath its horn, grips quickly, and canters away"),
+ V("moves in rigid high steps as its horn jerks", "rears abruptly with mane snapping across its neck"),
+ V("dreams with bright hooves cantering against folded legs", "nickers asleep while spiral horn and ears shift"));
+
+ AddExtended(
+ voices,
+ "wolf",
+ V("sings in a long howl with muzzle raised", "weaves yips into a tune while its chest expands"),
+ V("courts through muzzle licks, circling, and tail signals", "mates on long braced legs with bushy tail aside"),
+ V("farms with powerful forepaw scrapes and nose checks", "plants from an efficient, low stance"),
+ V("pushes pollen onward through steady nose-led passes", "carries pollen across its muzzle with tail level"),
+ V("trades through low whines and measured muzzle gestures", "barters seated tall on its haunches"),
+ V("fishes from a flattened crouch with ears fixed", "fishes with a sudden snap after holding still"),
+ V("hauls with jaws set and long legs driving", "draws backward while shoulders stay level"),
+ V("licks {target} and nibbles with careful teeth", "heals {target} with ears held forward"),
+ V("stokes fire with muzzle turned aside", "fans the flames with its bushy tail"),
+ V("flees in a long, fully extended lope", "runs away with level back and ears swept flat"),
+ V("settles by circling and scraping with strong forepaws", "folds chest-down with chin between extended paws"),
+ V("takes a warrior stance with ears forward and jaws open", "rushes ahead from a level-backed crouch"),
+ V("reads with muzzle tracking under each line", "reads while pointed ears remain fixed"),
+ V("gathers life with nose close and forepaws precise", "gathers life from a long-legged crouch"),
+ V("squats on bent hind legs with bushy tail raised", "relieves itself while forelegs remain straight"),
+ V("fans between directions with nose and ears angled apart", "starts a lope, checks sharply, and circles"),
+ V("recharges curled tightly beneath its bushy tail", "rests chest-down with chin over long forepaws"),
+ V("bows and springs repeatedly under a strange urge", "circles in an efficient lope while snapping upward"),
+ V("steals with a quick jaw grip and silent retreat", "stalks close nose-first, snatches, and lopes away"),
+ V("paces in rigid lines with hackles lifted", "jerks its muzzle sideways while jaws snap shut"),
+ V("dreams with long legs running beneath a curled body", "howls faintly while its bushy tail twitches"));
+
+ AddExtended(
+ voices,
+ "worm",
+ V("sings as a faint rasp through contracting segments", "pulses a soft rhythm along its bristled underside"),
+ V("courts by aligning and rippling beside another body", "mates through close segment contact and coordinated contractions"),
+ V("farms by drawing its front segments forward", "plants through slow, bristle-anchored ripples"),
+ V("pushes pollen onward through looping body contact", "carries pollen along its segments in forward pulses"),
+ V("trades by curling close and tapping its tapered front", "barters through measured body pulses"),
+ V("fishes with its tapered front held motionless", "fishes through a sudden full-body contraction"),
+ V("hauls by anchoring bristles and shortening its body", "draws backward through wave after muscular wave"),
+ V("heals {target} through gentle front-segment contact", "heals {target} through tiny controlled contractions"),
+ V("stokes fire through short front-segment ripples", "fans the flames with its tapered front"),
+ V("flees through rapid contractions and flattened curves", "crawls away as bristles drive in quick succession"),
+ V("settles by coiling segment over segment", "sweeps its tapered front once before relaxing"),
+ V("takes a warrior coil with front segments lifted", "lashes forward from a bristle-anchored curve"),
+ V("reads by passing its tapered front along each line", "reads through tiny lateral ripples"),
+ V("gathers life with its mouth opening and controlled pulls", "gathers life through delicate front-segment contractions"),
+ V("contracts its rear segments and holds still", "relieves itself while the tapered front remains extended"),
+ V("crawls into a loop and reverses halfway", "points its tapered front one way as the body pulls another"),
+ V("recharges in a loose coil with bristles relaxed", "lies extended while faint pulses travel end to end"),
+ V("knots into repeated loops under a strange urge", "lashes and recoils while its rear segments stay fixed"),
+ V("steals by hooking its front segments and contracting away", "creeps close, grips briefly, and ripples back"),
+ V("writhes in broken waves with bristles scraping", "stiffens segment by segment before snapping into a coil"),
+ V("dreams as slow ripples pass along its resting body", "twitches its tapered front while loosely coiled"));
+ }
+}
diff --git a/IdleSpectator/ActivitySpeciesVoices.Mammals.Specialized.cs b/IdleSpectator/ActivitySpeciesVoices.Mammals.Specialized.cs
new file mode 100644
index 0000000..d1bb80d
--- /dev/null
+++ b/IdleSpectator/ActivitySpeciesVoices.Mammals.Specialized.cs
@@ -0,0 +1,240 @@
+using System.Collections.Generic;
+
+namespace IdleSpectator;
+
+public static partial class ActivitySpeciesVoiceCatalog
+{
+ private static void AddMammalSpecializedVoices(Dictionary voices)
+ {
+ AddSpecialized(
+ voices,
+ "alpaca",
+ V("blows through split lips until a small flame kindles", "breathes through split lips to spread the flame"),
+ V("presses padded feet over the flame", "snuffs flame beneath a dense fold of fleece"),
+ V("hums and folds into a shoulder-close herd", "threads its long neck among gathered kin"),
+ V("draws visible life essence up its long neck into parted lips", "pulls glowing life essence through its fleece toward its chest"),
+ V("probes for spoils with split lips and an extended neck", "reaches for spoils between careful padded feet"),
+ V("wails through a raised muzzle in wavering breaths", "hums in long pulses with its neck stretched high"),
+ V("pins its ears, stamps its padded feet, and spits", "jerks its long neck and grinds out a nasal rasp"));
+
+ AddSpecialized(
+ voices,
+ "armadillo",
+ V("rakes broad foreclaws together until flame kindles", "fans flame outward with rapid flexes of its armor bands"),
+ V("curls its plated body over the flame to smother it", "scrapes flame flat beneath overlapping armor"),
+ V("tucks its plated flank into a shell-close cluster of kin", "presses its plated flank among gathered kin"),
+ V("draws visible life essence between its claws and under its plates", "pulls glowing life essence along its armor bands toward its chest"),
+ V("sniffs for spoils with its pointed snout", "hooks toward spoils with one broad foreclaw"),
+ V("squeals beneath a tightly folded plated brow", "chatters in dry bursts while its armor bands pulse"),
+ V("hunches behind its plates and rakes both foreclaws", "snaps its pointed snout and chatters through clenched jaws"));
+
+ AddSpecialized(
+ voices,
+ "bandit",
+ V("rubs quick palms until flame kindles between them", "cups the flame and spreads it with flicking fingers"),
+ V("claps both palms over the flame to smother it", "pinches the flame down between quick fingertips"),
+ V("signals with two fingers and closes ranks with kin", "slips shoulder to shoulder among gathered kin"),
+ V("draws visible life essence into cupped hands", "pulls glowing life essence along spread fingers toward the chest"),
+ V("searches for spoils with quick eyes and probing fingers", "reaches toward spoils with one hand held low"),
+ V("cries out through cupped hands in a sharp broken call", "hunches with mouth open and breath pulsing audibly"),
+ V("jabs two fingers outward and spits clipped syllables", "sets the jaw, bares the teeth, and hisses through them"));
+
+ AddSpecialized(
+ voices,
+ "bear",
+ V("rubs broad forepaws until flame kindles between the pads", "fans flame outward with heavy sweeps of both forepaws"),
+ V("smothers flame beneath crossed forepaws", "presses a broad muzzle over the flame and huffs it out"),
+ V("presses its heavy shoulder among gathered kin", "rises among gathered kin and draws them close with broad forepaws"),
+ V("draws visible life essence between its claws and into its chest", "pulls glowing life essence through its broad muzzle with deep breaths"),
+ V("sniffs for spoils with its broad muzzle sweeping", "reaches toward spoils with hooked foreclaws"),
+ V("roars with its muzzle lifted and forepaws spread", "huffs in deep pulses while its shoulders heave"),
+ V("bares its teeth and pounds both forepaws together", "rears with claws spread and growls in clipped bursts"));
+
+ AddSpecialized(
+ voices,
+ "buffalo",
+ V("snorts through broad nostrils until flame kindles beneath its muzzle", "sweeps its horned head to spread the flame"),
+ V("stamps the flame beneath broad cloven hooves", "presses its heavy muzzle down and snorts the flame out"),
+ V("pushes shoulder to shoulder into a close herd", "bellows and joins the gathered herd flank-first"),
+ V("draws visible life essence along its horns into its brow", "pulls glowing life essence through its broad muzzle toward its chest"),
+ V("sniffs for spoils beneath its horned brow", "reaches toward spoils with its broad muzzle"),
+ V("bellows with its beard shaking beneath a raised muzzle", "moans in chest-deep pulses while its nostrils flare"),
+ V("drops its horned brow, stamps, and snorts sharply", "swings its beard and grinds out a deep nasal rumble"));
+
+ AddSpecialized(
+ voices,
+ "capybara",
+ V("gnashes broad incisors until flame kindles", "fans flame outward with quick sweeps of its blunt muzzle"),
+ V("presses webbed forefeet over the flame", "snuffs flame beneath its broad wet muzzle"),
+ V("whistles and settles flank to flank among kin", "tucks its barrel-shaped body into a compact gathering of kin"),
+ V("draws visible life essence between its orange incisors", "pulls glowing life essence along its whiskers toward its chest"),
+ V("sniffs for spoils with whiskers spread", "reaches toward spoils with webbed forefeet"),
+ V("whistles through a long piercing note", "squeals with its blunt muzzle lifted"),
+ V("chatters its incisors and stamps both webbed forefeet", "bares broad incisors and barks in short bursts"));
+
+ AddSpecialized(
+ voices,
+ "cat",
+ V("scrapes tucked claws until flame kindles", "lashes its tail to fan flame outward"),
+ V("pats the flame down with rapid sheathed paws", "covers the flame beneath crossed forepaws and snuffs it"),
+ V("trills and threads into a tail-close gathering of kin", "presses flank to flank among gathered kin"),
+ V("draws visible life essence along its whiskers into its chest", "pulls glowing life essence between curved claws"),
+ V("sniffs for spoils with whiskers thrust forward", "reaches toward spoils with one careful paw"),
+ V("yowls with its jaw wide and whiskers flared", "wails in rising notes with its tail held rigid"),
+ V("flattens its ears, lashes its tail, and spits", "arches its back and growls through bared teeth"));
+
+ AddSpecialized(
+ voices,
+ "cow",
+ V("snorts through broad nostrils until flame kindles beneath its muzzle", "sweeps its broad muzzle to spread the flame"),
+ V("stamps flame beneath a cloven forehoof", "presses its broad muzzle down and snorts the flame out"),
+ V("lows and presses flank to flank into the herd", "presses its broad muzzle among gathered kin"),
+ V("draws visible life essence along its horns into its chest", "pulls glowing life essence through its broad muzzle"),
+ V("sniffs for spoils with its broad muzzle", "reaches toward spoils with a rough extended tongue"),
+ V("lows in a long resonant call with its muzzle raised", "moans in deep pulses while its broad throat vibrates"),
+ V("stamps a cloven hoof and bellows through flared nostrils", "swings its horned head and grinds out a rough lowing"));
+
+ AddSpecialized(
+ voices,
+ "dog",
+ V("scrapes its foreclaws until flame kindles", "pants across the flame and fans it outward"),
+ V("pats the flame down with quick forepaws", "presses its muzzle close and huffs the flame out"),
+ V("barks and folds into a shoulder-close pack", "presses its nose among gathered kin until flanks touch"),
+ V("draws visible life essence along its whiskers into its chest", "pulls glowing life essence through its open jaws"),
+ V("sniffs for spoils with its nose sweeping", "reaches toward spoils with one extended forepaw"),
+ V("howls with its muzzle lifted and throat stretched", "whines in repeated pulses while its chest trembles"),
+ V("bares its teeth, stamps, and barks in clipped bursts", "bristles along the spine and growls through a fixed jaw"));
+
+ AddSpecialized(
+ voices,
+ "fox",
+ V("scratches narrow claws together until flame kindles", "sweeps its brush to spread the flame"),
+ V("beats the flame down beneath quick forepaws", "wraps its broad brush over the flame and smothers it"),
+ V("gekker-calls and slips into a brush-close gathering of kin", "circles once and presses flank to flank among kin"),
+ V("draws visible life essence along its whiskers into its chest", "pulls glowing life essence through its pointed muzzle"),
+ V("sniffs for spoils with its pointed muzzle low", "reaches toward spoils with a narrow forepaw"),
+ V("screams through an open muzzle with its brush rigid", "yips in a rapid chain while its throat pulses"),
+ V("pins its ears, lashes its brush, and gekkers sharply", "bares narrow teeth and spits a rasping bark"));
+
+ AddSpecialized(
+ voices,
+ "goat",
+ V("scrapes hard forehooves together until flame kindles", "snorts through split lips to spread the flame"),
+ V("stamps the flame beneath hard cloven hooves", "presses its split lips over the flame and snorts it out"),
+ V("bleats and shoulders into a horn-close herd", "presses its bearded chin among gathered kin"),
+ V("draws visible life essence along its horns into its brow", "pulls glowing life essence through its split lips toward its chest"),
+ V("sniffs for spoils beneath its beard", "reaches toward spoils with mobile split lips"),
+ V("bleats in a long broken call with its jaw trembling", "wails nasally while its beard shakes"),
+ V("stamps both forehooves and jerks its horns forward", "bares its lower teeth and snorts in clipped bursts"));
+
+ AddSpecialized(
+ voices,
+ "hyena",
+ V("grinds heavy teeth until flame kindles", "pants over the flame and fans it outward"),
+ V("pounds the flame beneath powerful forepaws", "presses its heavy muzzle close and huffs the flame out"),
+ V("whoops and shoulders into a close clan of kin", "sets its high shoulders among gathered kin and presses flank to flank"),
+ V("draws visible life essence between massive premolars", "pulls glowing life essence through its broad muzzle into its chest"),
+ V("sniffs for spoils with its heavy muzzle low", "reaches toward spoils with one powerful forepaw"),
+ V("whoops in a rising cascade with jaws spread", "cackles in breathless bursts while its shoulders jolt"),
+ V("raises its shoulders, bares its teeth, and chatters", "snaps its jaws and growls in broken pulses"));
+
+ AddSpecialized(
+ voices,
+ "monkey",
+ V("rubs nimble palms until flame kindles between them", "fans flame outward with quick alternating hands"),
+ V("claps both hands over the flame to smother it", "beats the flame down with flat rapid palms"),
+ V("hoots and presses shoulder to shoulder among kin", "reaches both arms into a gathering of kin and joins it"),
+ V("draws visible life essence into cupped hands", "pulls glowing life essence along curled fingers toward its chest"),
+ V("searches for spoils with quick eyes and probing fingers", "reaches toward spoils with one long arm"),
+ V("hoots with its mouth rounded and throat pulsing", "shrills in repeated notes while both hands clutch its chest"),
+ V("bares its teeth, slaps both palms, and chatters", "jabs one hand outward and barks in clipped syllables"));
+
+ AddSpecialized(
+ voices,
+ "rabbit",
+ V("gnashes its incisors until flame kindles", "fans flame outward with rapid forepaw strokes"),
+ V("pats the flame down with quick forepaws", "presses both forepaws over the flame and smothers it"),
+ V("honks and settles into a flank-close cluster of kin", "tucks its long ears among gathered kin"),
+ V("draws visible life essence between its incisors", "pulls glowing life essence along its long ears toward its chest"),
+ V("sniffs for spoils with its nose pulsing", "reaches toward spoils with both small forepaws"),
+ V("squeals with its ears rigid and mouth open", "honks in repeated breaths while its hind feet tremble"),
+ V("thumps both hind feet and chatters its incisors", "pins its ears and grinds out a sharp nasal grunt"));
+
+ AddSpecialized(
+ voices,
+ "raccoon",
+ V("rubs sensitive forepaws until flame kindles", "fans flame outward with quick sweeps of its ringed tail"),
+ V("claps black forepaws over the flame to smother it", "beats the flame down beneath nimble plantigrade paws"),
+ V("trills and presses into a ringed-tail cluster of kin", "feels along nearby flanks and joins gathered kin"),
+ V("draws visible life essence between sensitive fingers", "pulls glowing life essence along its ringed tail into its chest"),
+ V("feels and sniffs for spoils with spread black fingers", "reaches toward spoils with both nimble forepaws"),
+ V("screeches with its pointed muzzle lifted", "trills in broken pulses while its forepaws clutch together"),
+ V("arches its back, bares its teeth, and chatters", "slaps both forepaws down and growls in rasping bursts"));
+
+ AddSpecialized(
+ voices,
+ "rat",
+ V("gnashes orange incisors until flame kindles", "lashes its bare tail to fan flame outward"),
+ V("pats the flame down with quick pink paws", "coils its bare tail over the flame and smothers it"),
+ V("squeaks and huddles into a whisker-close knot of kin", "presses its whiskered muzzle among gathered kin"),
+ V("draws visible life essence along its whiskers into its chest", "pulls glowing life essence between its orange incisors"),
+ V("sniffs for spoils with whiskers sweeping", "reaches toward spoils with both pink forepaws"),
+ V("squeals with whiskers flared and incisors bared", "chirps in rapid pulses while its bare tail coils tightly"),
+ V("bruxes its incisors and lashes its bare tail", "rears with pink paws spread and hisses through bared teeth"));
+
+ AddSpecialized(
+ voices,
+ "rhino",
+ V("snorts through thick lips until flame kindles beneath its horn", "sweeps its massive horn to spread the flame"),
+ V("stamps the flame beneath a broad three-toed foot", "presses its thick muzzle down and snorts the flame out"),
+ V("grunts and presses thick shoulders into the herd", "presses its folded hide among gathered kin"),
+ V("draws visible life essence along its horn into its brow", "pulls glowing life essence through its thick lips toward its chest"),
+ V("sniffs for spoils beneath its heavy horn", "reaches toward spoils with its broad square lip"),
+ V("squeals with its horn raised and small ears spread", "moans in rough pulses while its thick throat vibrates"),
+ V("stamps a three-toed foot and blasts a hard snort", "swings its horn and grinds out a chest-deep rasp"));
+
+ AddSpecialized(
+ voices,
+ "sheep",
+ V("scrapes narrow forehooves together until flame kindles", "snorts through split lips to spread the flame"),
+ V("stamps the flame beneath narrow cloven hooves", "presses dense fleece over the flame and smothers it"),
+ V("bleats and presses fleece to fleece into the flock", "tucks its woolly muzzle among gathered kin"),
+ V("draws visible life essence along its curled horns", "pulls glowing life essence through its fleece toward its chest"),
+ V("sniffs for spoils through its woolly muzzle", "reaches toward spoils with a mobile split lip"),
+ V("bleats in a long wavering call with its jaw trembling", "wails nasally while its dense fleece quivers"),
+ V("stamps narrow hooves and jerks its curled horns", "bares its lower teeth and grinds out a broken baa"));
+
+ AddSpecialized(
+ voices,
+ "unicorn",
+ V("draws a spark down its spiral horn until flame kindles", "sweeps its spiral horn to spread the flame"),
+ V("presses the flame flat beneath bright cloven hooves", "touches its spiral horn to the flame and snuffs it"),
+ V("nickers and joins a mane-close herd of kin", "arches its neck among gathered kin until flanks touch"),
+ V("draws visible life essence along its spiral horn into its brow", "pulls glowing life essence through its flowing mane toward its chest"),
+ V("searches for spoils with its horn angled low", "reaches toward spoils with mobile lips"),
+ V("whinnies with its spiral horn raised and throat stretched", "cries in clear ringing notes while its mane trembles"),
+ V("strikes a cloven forehoof and tosses its spiral horn", "pins its ears and snorts through bared teeth"));
+
+ AddSpecialized(
+ voices,
+ "wolf",
+ V("scrapes strong foreclaws until flame kindles", "pants over the flame and fans it outward"),
+ V("pounds the flame beneath broad forepaws", "presses its muzzle close and huffs the flame out"),
+ V("howls and folds shoulder to shoulder into the pack", "sets its long-legged flank among gathered kin"),
+ V("draws visible life essence along its muzzle into its chest", "pulls glowing life essence between its strong jaws"),
+ V("sniffs for spoils with its nose sweeping low", "reaches toward spoils with one broad forepaw"),
+ V("howls with its muzzle lifted and throat extended", "whines in repeated breaths while its chest pulses"),
+ V("raises its hackles, bares its teeth, and growls", "snaps its jaws and barks in hard clipped bursts"));
+
+ AddSpecialized(
+ voices,
+ "worm",
+ V("rasps its bristled underside until flame kindles", "whips its front segments to spread the flame"),
+ V("coils its segmented body over the flame to smother it", "presses contracting segments across the flame and suppresses it"),
+ V("twines into a close knot of gathered kin", "threads its tapered front between kin and presses segmented bodies together"),
+ V("draws visible life essence along contracting segments toward its mouth opening", "pulls glowing life essence through rippling body bands"),
+ V("probes for spoils with its tapered front", "reaches toward spoils by extending its front segments"),
+ V("rasps in long pulses through contracting segments", "rustles in repeated dry ripples with its front raised"),
+ V("coils tightly, lashes its front segments, and rasps", "braces its tiny bristles and whips forward with a dry hiss"));
+ }
+}
diff --git a/IdleSpectator/ActivityVerbMap.cs b/IdleSpectator/ActivityVerbMap.cs
index 0d0886d..f7d2e10 100644
--- a/IdleSpectator/ActivityVerbMap.cs
+++ b/IdleSpectator/ActivityVerbMap.cs
@@ -6,21 +6,67 @@ namespace IdleSpectator;
/// Maps every live task shape to an action concept; no creature voice logic.
public static class ActivityVerbMap
{
+ private static readonly string[] BehaviorBeatKeys =
+ {
+ "BehUnloadResources",
+ "BehThrowResources",
+ "BehSocializeTalk",
+ "BehTryToSocialize",
+ "BehPlantCrops",
+ "BehCityActorFertilizeCrop",
+ "BehBuildTarget",
+ "BehPoopOutside",
+ "BehPoopInside",
+ "BehBoatFishing",
+ "BehBoatCollectFish",
+ "BehClaimZoneForCityActorBorder"
+ };
+
public static string Resolve(string key)
{
if (string.IsNullOrEmpty(key)) return "";
string k = key.ToLowerInvariant();
+ if (ActivitySpeciesVoice.IsAuthoredVerb(k)) return k;
if (k.Contains("laugh")) return "laugh";
if (k.Contains("sing") || k.Contains("just_sang")) return "sing";
+ if (k == "start_fire") return "ignite";
+ if (k == "put_out_fire" || k.Contains("extinguish") || k.Contains("fireman")) return "extinguish";
+ if (k.Contains("family_group")) return "group";
+ if (k.Contains("soul_harvested")) return "harvest_life";
+ if (k.Contains("loot")) return "loot";
+ if (k.Contains("crying") || k.Contains("just_cried")) return "cry";
+ if (k.Contains("swore") || k.Contains("swear")) return "swear";
+ if (k.Contains("madness")) return "confused";
+ if (k == "follow_desire_target" || k == "task_unit_weird_desire") return "strange_urge";
+ if (k == "task_unit_follow_family" || k == "child_follow_parent") return "group";
+ if (k == "possessed_following") return "possessed";
+ if (k == "poop_inside" || k == "poop_outside" || k == "try_to_poop"
+ || k == "behpoopinside" || k == "behpoopoutside") return "relieve";
+ if (k == "status_confused" || k == "task_unit_confused") return "confused";
+ if (k == "replenish_energy" || k == "task_unit_replenish_energy") return "recharge";
+ if (k == "strange_urge_finish" || k == "task_strange_urge_finish") return "strange_urge";
+ if (k == "try_to_steal_money" || k == "try_to_take_city_item") return "steal";
+ if (k == "possessed") return "possessed";
+ if (k == "try_affect_dreams") return "dream";
+ if (k == "behthrowresources") return "haul";
+ if (k.StartsWith("diet_")) return "eat";
+ if (k == "city_walking_to_danger_zone" || k == "farmer_random_move"
+ || k == "random_move_towards_civ_building") return "move";
+ if (k == "warrior_army_captain_idle_walking_city"
+ || k == "warrior_army_leader_move_random") return "warrior";
+ if (k == "boat_transport_check_taxi") return "settle";
+ if (k == "punch_a_building") return "fight";
+ if (k == "run_to_water_when_on_fire") return "flee";
+ if (k == "try_to_launch_fireworks") return "play";
+ if (k == "type_bonfire") return "work";
+ if (k == "random_house_building") return "settle";
if ((k.Contains("play") && !k.Contains("display"))
|| k.Contains("fun_move") || k.Contains("frolic") || k.StartsWith("child_")) return "play";
if (k.Contains("hunt") || k == "behattackactorhuntingtarget") return "hunt";
if (k.Contains("fight") || k.Contains("attack") || k.Contains("tantrum")) return "fight";
- if (k.Contains("social") || k.Contains("talk") || k.Contains("trysocialize")
- || k.Contains("crying") || k.Contains("just_cried") || k.Contains("swore")
- || k.Contains("madness")) return "social";
+ if (k.Contains("social") || k.Contains("talk") || k.Contains("trysocialize")) return "social";
if (k.Contains("lover") || k.Contains("breed") || k.Contains("reproduction")
- || k.Contains("desire")) return "lover";
+ || k.Contains("reproduc") || k.Contains("desire")) return "lover";
if (k.Contains("farm") || k.Contains("plant") || k.Contains("fertiliz")
|| k.Contains("harvest") || k.Contains("hoe")) return "farm";
if (k == "work" || k.Contains("mine") || k.Contains("woodcut") || k.Contains("chop")
@@ -33,43 +79,62 @@ public static class ActivityVerbMap
if (k.Contains("trade") || k.Contains("barter") || k.Contains("tax")
|| k.Contains("boat_trading")) return "trade";
if (k.Contains("fish")) return "fish";
- if (k.Contains("unload") || k.Contains("throw_resource") || k.Contains("carrying")) return "haul";
+ if (k.Contains("unload") || k.Contains("throw_resource") || k.Contains("carrying")
+ || k.Contains("store_resource") || k.Contains("boat_load_units")) return "haul";
if (k.Contains("heal") || k.Contains("cure")) return "heal";
- if (k.Contains("fire") || k.Contains("fireman") || k.Contains("blaze")) return "fire";
+ if (k.Contains("fire") || k.Contains("blaze")) return "fire";
if (k.Contains("sleep") || k.Contains("wakeup") || k.Contains("burrow")) return "sleep";
if (k.Contains("eat") || k.Contains("food") || k.Contains("meal") || k.StartsWith("diet_")) return "eat";
if (k.Contains("run_away") || k.Contains("flee") || k.Contains("retreat")
|| k.Contains("danger_check") || k.Contains("banish") || k.Contains("kill_unruly")) return "flee";
+ if (k == "task_unit_run_to_water") return "flee";
if (k.Contains("job") || k.Contains("employ") || k.Contains("find_house")
- || k.Contains("claim") || k.Contains("king_") || k.Contains("leader_")
+ || k.Contains("claim") || k.StartsWith("king_") || k.StartsWith("leader_")
|| k.Contains("citizen") || k.Contains("join_city") || k.Contains("check_city")
|| k.Contains("check_plot") || k.Contains("family_check") || k.Contains("embark")
|| k.Contains("boat_return") || k.Contains("force_into_a_boat")
- || k.Contains("boat_transport") || k.Contains("boat_check") || k.Contains("investigate"))
+ || k.Contains("boat_transport") || k.Contains("boat_check") || k.Contains("investigate")
+ || k == "check_join_empty_nearby_city" || k.Contains("progress_plot")
+ || k == "task_unit_plot" || k.Contains("return_to_dock")
+ || k == "try_new_plot" || k == "try_to_return_to_home_city"
+ || k == "try_to_start_new_civilization" || k == "type_house" || k == "type_well")
return "settle";
if (k.Contains("warrior") || k.Contains("army") || k.Contains("formation")
- || k.Contains("invincible")) return "warrior";
+ || k.Contains("invincible") || k == "type_barracks"
+ || k == "type_training_dummies") return "warrior";
if (k.Contains("wait") || k == "reflection" || k.Contains("hold_still")
- || k.Contains("make_decision") || k.Contains("think") || k.Contains("stuck")) return "wait";
+ || k.Contains("make_decision") || k.Contains("think") || k.Contains("stuck")
+ || k == "nothing" || k == "sit_inside_boat" || k.StartsWith("stay_in_")
+ || k == "task_unit_nothing") return "wait";
if (k.Contains("idle") || k.Contains("random_move") || k.Contains("walking")
|| k.EndsWith("_move") || k.Contains("wander") || k == "move"
|| k.Contains("dragon_") || k.Contains("godfinger") || k.Contains("follow_")
|| k.StartsWith("ant_") || k.StartsWith("ufo_") || k.StartsWith("worm_")
- || k.Contains("slide") || k.Contains("land") || k.Contains("fly")) return "move";
+ || k.Contains("slide") || k.Contains("land") || k.Contains("fly")
+ || k.StartsWith("move_") || k == "random_swim" || k.Contains("teleport")
+ || k == "task_unit_walk" || k == "possessed_following") return "move";
if (k.Contains("read")) return "read";
- if (k.Contains("loot") || k.Contains("family_group")) return "gather_life";
+ if (k == "pickaxe" || k.StartsWith("print_") || k == "punch_a_tree"
+ || k.Contains("repair_equipment") || k == "ruins"
+ || k == "type_fruits" || k == "type_poop" || k == "type_tree"
+ || k == "type_vegetation" || k == "type_bonfire") return "work";
+ if (k == "type_flower" || k == "type_hive") return "pollinate";
+ if (k == "type_crops") return "farm";
return "";
}
public static bool HasActionCore(string key)
{
- return !string.IsNullOrEmpty(Resolve(key))
- || !string.IsNullOrEmpty(ActivityProse.PatternActionPhrase(key, false))
- || !string.IsNullOrEmpty(key);
+ return !string.IsNullOrEmpty(Resolve(key));
}
public static List EnumerateLiveTaskIds()
{
return ActivityAssetCatalog.EnumerateLiveTaskIds();
}
+
+ public static string[] EnumerateBehaviorBeatKeys()
+ {
+ return (string[])BehaviorBeatKeys.Clone();
+ }
}
diff --git a/IdleSpectator/ActivityVoiceHarness.cs b/IdleSpectator/ActivityVoiceHarness.cs
index 7c0e180..944c7c0 100644
--- a/IdleSpectator/ActivityVoiceHarness.cs
+++ b/IdleSpectator/ActivityVoiceHarness.cs
@@ -15,11 +15,7 @@ public sealed class ActivityVoiceAuditResult
/// Exhaustive live-library gates for voice classification and prose fingerprints.
public static class ActivityVoiceHarness
{
- private static readonly string[] FingerprintKeys =
- {
- "move", "wait", "task_unit_play", "task_eat", "task_sleep",
- "task_hunt", "task_attack", "social", "laugh", "work"
- };
+ private static readonly string[] FingerprintKeys = ActivitySpeciesVoice.AuthoredVerbs;
private static readonly string[] AwkwardProseFragments =
{
@@ -57,7 +53,15 @@ public static class ActivityVoiceHarness
"eagerly",
"contentedly",
"stubborn focus",
- "stubborn persistence"
+ "stubborn persistence",
+ "pollinating work",
+ "fishing task",
+ "healing task",
+ "hauling task",
+ "stealing motion",
+ "tends the healing",
+ "works the farm",
+ "waits over the fishing"
};
private static readonly string[] UngroundedTerrainFragments =
@@ -72,7 +76,16 @@ public static class ActivityVoiceHarness
"close to the ground",
"nose to the ground",
"damp play",
- "wet quiet"
+ "wet quiet",
+ " in water",
+ " through water",
+ " underwater",
+ " on the shore",
+ " across the field",
+ " in the field",
+ " tests the ground",
+ " gaining ground",
+ " grounded "
};
public static ActivityVoiceAuditResult RunAudit(string outputDirectory)
@@ -96,6 +109,9 @@ public static class ActivityVoiceHarness
int terrainLeaks = 0;
int variantBaseFail = 0;
int authoredPhraseFail = 0;
+ int unmappedTasks = 0;
+ int missingTaskBags = 0;
+ int routedTasks = 0;
string sample = "";
string vehicleFingerprint = null;
var fingerprints = new Dictionary(StringComparer.Ordinal);
@@ -245,6 +261,38 @@ public static class ActivityVoiceHarness
}
}
+ List taskKeys = ActivityVerbMap.EnumerateLiveTaskIds();
+ string[] beatKeys = ActivityVerbMap.EnumerateBehaviorBeatKeys();
+ for (int source = 0; source < 2; source++)
+ {
+ int count = source == 0 ? taskKeys.Count : beatKeys.Length;
+ for (int i = 0; i < count; i++)
+ {
+ string taskKey = source == 0 ? taskKeys[i] : beatKeys[i];
+ string verb = ActivityVerbMap.Resolve(taskKey);
+ routedTasks++;
+ if (string.IsNullOrEmpty(verb))
+ {
+ unmappedTasks++;
+ AddSample(ref sample, taskKey + ":unmapped-task");
+ continue;
+ }
+
+ foreach (string baseId in liveBases)
+ {
+ string[] bag = ActivitySpeciesVoiceCatalog.GetBag(
+ baseId,
+ verb,
+ ActivityTerrain.Unknown);
+ if (bag == null || bag.Length < 2)
+ {
+ missingTaskBags++;
+ AddSample(ref sample, baseId + ":" + taskKey + ":missing-bag=" + verb);
+ }
+ }
+ }
+ }
+
int pairFail = PairwiseFailures(ref sample);
bool liveContextOk = VerifyLiveContext(ref sample);
try
@@ -273,6 +321,8 @@ public static class ActivityVoiceHarness
&& terrainLeaks == 0
&& variantBaseFail == 0
&& authoredPhraseFail == 0
+ && unmappedTasks == 0
+ && missingTaskBags == 0
&& pairFail == 0
&& liveContextOk;
return new ActivityVoiceAuditResult
@@ -294,6 +344,9 @@ public static class ActivityVoiceHarness
+ " terrainLeaks=" + terrainLeaks
+ " variantBaseFail=" + variantBaseFail
+ " authoredPhraseFail=" + authoredPhraseFail
+ + " routedTasks=" + routedTasks
+ + " unmappedTasks=" + unmappedTasks
+ + " missingTaskBags=" + missingTaskBags
+ " pairFail=" + pairFail
+ " liveContextOk=" + liveContextOk
+ " sample='" + sample + "'"
@@ -304,9 +357,9 @@ public static class ActivityVoiceHarness
{
int failures = 0;
string label = ActivityAssetCatalog.SpeciesDisplayLabel(baseSpeciesId);
- for (int i = 0; i < ActivitySpeciesVoice.CoreVerbs.Length; i++)
+ for (int i = 0; i < ActivitySpeciesVoice.AuthoredVerbs.Length; i++)
{
- string verb = ActivitySpeciesVoice.CoreVerbs[i];
+ string verb = ActivitySpeciesVoice.AuthoredVerbs[i];
string[] bag = ActivitySpeciesVoiceCatalog.GetBag(
baseSpeciesId,
verb,
diff --git a/IdleSpectator/AgentHarness.cs b/IdleSpectator/AgentHarness.cs
index 06aaf7e..27f9c4d 100644
--- a/IdleSpectator/AgentHarness.cs
+++ b/IdleSpectator/AgentHarness.cs
@@ -1857,6 +1857,20 @@ public static class AgentHarness
detail = $"hist='{hist}' needle='{needle}' act={WatchCaption.LastActivityShown} life={WatchCaption.LastLifeShown}";
break;
}
+ case "dossier_history_not_contains":
+ {
+ string needle = string.IsNullOrEmpty(cmd.value) ? cmd.label : cmd.value;
+ string hist = WatchCaption.LastHistoryJoined ?? "";
+ if (string.IsNullOrEmpty(hist))
+ {
+ hist = WatchCaption.LastHistoryPreview ?? "";
+ }
+
+ pass = !string.IsNullOrEmpty(needle)
+ && hist.IndexOf(needle, System.StringComparison.OrdinalIgnoreCase) < 0;
+ detail = $"hist='{hist}' excludes='{needle}' act={WatchCaption.LastActivityShown} life={WatchCaption.LastLifeShown}";
+ break;
+ }
case "activity_count":
{
long id = WatchCaption.CurrentUnitId;
diff --git a/IdleSpectator/HarnessScenarios.cs b/IdleSpectator/HarnessScenarios.cs
index 8bdae65..7b4ed77 100644
--- a/IdleSpectator/HarnessScenarios.cs
+++ b/IdleSpectator/HarnessScenarios.cs
@@ -487,7 +487,7 @@ internal static class HarnessScenarios
Step("act13e", "assert", expect: "activity_prose_library"),
Step("act13f", "assert", expect: "activity_taxonomy_audit"),
Step("act14", "activity_force", asset: "laughing", label: "Laughing", count: 1, value: "angle"),
- Step("act14b", "assert", expect: "activity_log_contains", value: "chime"),
+ Step("act14b", "assert", expect: "activity_log_contains", value: "celestial"),
Step("act14c", "activity_force", asset: "eating", label: "Taking a meal", count: 1),
Step("act15", "activity_force", asset: "farm", label: "Tends the fields", count: 1),
Step("act16", "activity_force", asset: "hunt", label: "Hunts", count: 1, expect: "Barkley"),
@@ -507,7 +507,7 @@ internal static class HarnessScenarios
Step("act20b", "assert", expect: "activity_names_colored"),
Step("act20c", "assert", expect: "activity_log_contains", value: "Barkley"),
Step("act21", "assert", expect: "dossier_history_shown", value: "1", label: "min", tier: "activity"),
- Step("act22", "assert", expect: "dossier_history_contains", value: "Harness pollen"),
+ Step("act22", "assert", expect: "dossier_history_not_contains", value: "Harness pollen"),
Step("act23", "assert", expect: "caption_layout_ok"),
Step("act24", "screenshot", value: "hud-activity_idle_smoke.png"),
Step("act25", "wait", wait: 0.55f),
diff --git a/IdleSpectator/mod.json b/IdleSpectator/mod.json
index f68a1c2..45c4c85 100644
--- a/IdleSpectator/mod.json
+++ b/IdleSpectator/mod.json
@@ -1,7 +1,7 @@
{
"name": "IdleSpectator",
"author": "dazed",
- "version": "0.12.79",
+ "version": "0.12.84",
"description": "AFK Idle Spectator (I) + Lore (L). Detailed living activity prose by default.",
"GUID": "com.dazed.idlespectator"
}