266 lines
6.5 KiB
C#
266 lines
6.5 KiB
C#
using System.Collections.Generic;
|
|
|
|
namespace IdleSpectator;
|
|
|
|
/// <summary>
|
|
/// Fact-preserving multi-variant activity lines (anti-stale dossier feed).
|
|
/// </summary>
|
|
public static class ActivityProse
|
|
{
|
|
private static readonly Dictionary<string, string[]> Variants = new Dictionary<string, string[]>
|
|
{
|
|
["fighting"] = new[]
|
|
{
|
|
"Locked in combat",
|
|
"Trading blows",
|
|
"In the fray",
|
|
"Clash of steel"
|
|
},
|
|
["fight"] = new[]
|
|
{
|
|
"Locked in combat",
|
|
"Trading blows",
|
|
"In the fray"
|
|
},
|
|
["attack"] = new[]
|
|
{
|
|
"Strikes at {target}",
|
|
"Presses the attack on {target}",
|
|
"Lunges toward {target}"
|
|
},
|
|
["hunt"] = new[]
|
|
{
|
|
"Hunts {target}",
|
|
"Stalks {target}",
|
|
"On the trail of {target}"
|
|
},
|
|
["eating"] = new[]
|
|
{
|
|
"Taking a meal",
|
|
"Eating",
|
|
"Breaking hunger"
|
|
},
|
|
["eat"] = new[]
|
|
{
|
|
"Taking a meal",
|
|
"Eating",
|
|
"Breaking hunger"
|
|
},
|
|
["sleep"] = new[]
|
|
{
|
|
"Sleeping",
|
|
"Resting",
|
|
"Deep in slumber"
|
|
},
|
|
["random_move"] = new[]
|
|
{
|
|
"Wandering",
|
|
"Roaming aimlessly",
|
|
"Drifting along"
|
|
},
|
|
["pollinate"] = new[]
|
|
{
|
|
"Dusts the blossom",
|
|
"Works the flower",
|
|
"Leaves pollen behind",
|
|
"Humming over petals"
|
|
},
|
|
["farm"] = new[]
|
|
{
|
|
"Tends the fields",
|
|
"Works the soil",
|
|
"Farming the plot"
|
|
},
|
|
["harvest"] = new[]
|
|
{
|
|
"Harvests the crop",
|
|
"Gathers the yield",
|
|
"Cuts the ripe fields"
|
|
},
|
|
["mine"] = new[]
|
|
{
|
|
"Delves the mine",
|
|
"Chipping ore",
|
|
"Deep in the dig"
|
|
},
|
|
["build"] = new[]
|
|
{
|
|
"Building",
|
|
"Raising walls",
|
|
"At the worksite"
|
|
},
|
|
["gather"] = new[]
|
|
{
|
|
"Gathering stores",
|
|
"Foraging supplies",
|
|
"Collecting goods"
|
|
},
|
|
["woodcut"] = new[]
|
|
{
|
|
"Felling timber",
|
|
"Cutting wood",
|
|
"Axe to the trees"
|
|
},
|
|
["fire"] = new[]
|
|
{
|
|
"Fighting the blaze",
|
|
"Dousing flames",
|
|
"Racing the fire"
|
|
},
|
|
["fireman"] = new[]
|
|
{
|
|
"Fighting the blaze",
|
|
"Dousing flames",
|
|
"Racing the fire"
|
|
},
|
|
["social"] = new[]
|
|
{
|
|
"Socializing",
|
|
"In conversation",
|
|
"Among companions"
|
|
},
|
|
["lover"] = new[]
|
|
{
|
|
"Seeking a lover",
|
|
"Drawn to {target}",
|
|
"Heart on the path"
|
|
},
|
|
["unload"] = new[]
|
|
{
|
|
"Unloads goods in town",
|
|
"Delivers the haul",
|
|
"Empties the pack at home"
|
|
},
|
|
["store"] = new[]
|
|
{
|
|
"Stores supplies",
|
|
"Stocking the village",
|
|
"Puts goods away"
|
|
},
|
|
["fish"] = new[]
|
|
{
|
|
"Fishing",
|
|
"Casting for fish",
|
|
"Working the waters"
|
|
},
|
|
["trade"] = new[]
|
|
{
|
|
"Trading",
|
|
"Bartering goods",
|
|
"On a trade run"
|
|
},
|
|
["run_away"] = new[]
|
|
{
|
|
"Fleeing",
|
|
"Running for safety",
|
|
"In retreat"
|
|
},
|
|
["make_decision"] = new[]
|
|
{
|
|
"Considering next steps",
|
|
"Weighing a choice",
|
|
"Paused in thought"
|
|
},
|
|
["wait"] = new[]
|
|
{
|
|
"Waiting",
|
|
"Holding still",
|
|
"Biding time"
|
|
},
|
|
["BehPollinate"] = new[]
|
|
{
|
|
"Dusts the blossom",
|
|
"Works the flower",
|
|
"Leaves pollen behind"
|
|
},
|
|
["BehUnloadResources"] = new[]
|
|
{
|
|
"Unloads goods in town",
|
|
"Delivers the haul",
|
|
"Empties the pack at home"
|
|
},
|
|
["BehAttackActorHuntingTarget"] = new[]
|
|
{
|
|
"Hunts {target}",
|
|
"Strikes prey",
|
|
"Closes on the quarry"
|
|
},
|
|
["BehCityActorRemoveFire"] = new[]
|
|
{
|
|
"Dousing flames",
|
|
"Fighting the blaze",
|
|
"Beats back the fire"
|
|
}
|
|
};
|
|
|
|
public static string Format(
|
|
ActivityKind kind,
|
|
string key,
|
|
string rawFact,
|
|
string target,
|
|
long subjectId,
|
|
int lineIndex)
|
|
{
|
|
if (string.IsNullOrEmpty(rawFact) && string.IsNullOrEmpty(key))
|
|
{
|
|
return "";
|
|
}
|
|
|
|
string template = PickTemplate(key, subjectId, lineIndex);
|
|
if (string.IsNullOrEmpty(template))
|
|
{
|
|
return rawFact ?? key ?? "";
|
|
}
|
|
|
|
string t = string.IsNullOrEmpty(target) ? "their mark" : target;
|
|
return template.Replace("{target}", t);
|
|
}
|
|
|
|
private static string PickTemplate(string key, long subjectId, int lineIndex)
|
|
{
|
|
if (string.IsNullOrEmpty(key))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
string[] bag = null;
|
|
if (Variants.TryGetValue(key, out bag) && bag != null && bag.Length > 0)
|
|
{
|
|
return bag[PickIndex(subjectId, key, lineIndex, bag.Length)];
|
|
}
|
|
|
|
string lower = key.ToLowerInvariant();
|
|
foreach (KeyValuePair<string, string[]> kv in Variants)
|
|
{
|
|
if (lower.IndexOf(kv.Key, System.StringComparison.Ordinal) >= 0
|
|
&& kv.Value != null
|
|
&& kv.Value.Length > 0)
|
|
{
|
|
return kv.Value[PickIndex(subjectId, kv.Key, lineIndex, kv.Value.Length)];
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
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);
|
|
// Extra jitter so back-to-back repeats of the same task shift.
|
|
h ^= (int)(UnityEngine.Time.unscaledTime * 10f);
|
|
if (h < 0)
|
|
{
|
|
h = -h;
|
|
}
|
|
|
|
return h % count;
|
|
}
|
|
}
|
|
}
|