using System.Collections.Generic;
namespace IdleSpectator;
///
/// Fact-preserving multi-variant activity lines (anti-stale dossier feed).
///
public static class ActivityProse
{
private static readonly Dictionary Variants = new Dictionary
{
["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 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;
}
}
}