Design techniques and C# examples for intentionally flawed AI that feels human—and is often tougher to beat.
When developers think about AI in games, the focus is often on making it smarter: efficient resource managers, tactically sharp combatants, or hyper-optimized decision systems. But there’s a paradox here—sometimes, the most effective AI isn’t the one that always makes the best choice. It’s the one that doesn’t.
A flawless, rules-driven AI can become predictable. Once players understand its logic, they can “solve” it—exploiting patterns to guarantee victory. Unpredictability, by contrast, breaks the player’s script.
“I’d rather spar with someone trained than a beginner. The trained fighter is predictable. The beginner is dangerous precisely because they’re unpredictable.”
That insight maps directly to game AI. A perfectly rational opponent may be impressive, but an opponent that occasionally overcommits, hesitates, or makes a suboptimal move can throw the player off balance. Unpredictability becomes a weapon.
“Artificial stupidity” is not arbitrary failure. Poor randomness feels unfair or immersion-breaking. Instead, it’s the purposeful introduction of believable, context-aware flaws that mimic human imperfection.
Instead of picking the max utility every time, choose from a weighted distribution.
public static class AIDecisionHelper
{
public static T ChooseWithWeights<T>(IReadOnlyList<(T option, float weight)> options)
{
float total = 0f;
for (int i = 0; i < options.Count; i++) total += MathF.Max(0f, options[i].weight);
float roll = UnityEngine.Random.Range(0f, total);
float acc = 0f;
for (int i = 0; i < options.Count; i++)
{
acc += MathF.Max(0f, options[i].weight);
if (roll <= acc) return options[i].option;
}
return options[^1].option; // fallback
}
}
Usage in Tempus Inceptum (resource choice):
var resourceChoice = AIDecisionHelper.ChooseWithWeights(new List<(string, float)>
{
("Crop", 0.70f), // best
("Lumber", 0.20f), // sub-optimal
("Fur", 0.10f) // weak
});
// Proceed to plan around 'resourceChoice'
Inject small noise into utility values to simulate human inconsistency without chaos.
float EvaluateResource(string resource, float basePriority)
{
// ±20% jitter; clamp to keep within sane bounds
float noise = UnityEngine.Random.Range(-0.2f, 0.2f);
float score = basePriority * (1f + noise);
return Mathf.Clamp(score, 0f, basePriority * 1.4f);
}
Coroutines that introduce decision latency; great for build/commit timing.
IEnumerator DelayedAction(System.Action action, float maxHesitationSeconds)
{
yield return new WaitForSeconds(UnityEngine.Random.Range(0f, maxHesitationSeconds));
action?.Invoke();
}
// Example:
// StartCoroutine(DelayedAction(() => PlaceProductionBuilding(plan), 3.0f));
Profiles bias the chance and magnitude of non-optimal decisions.
public enum RiskProfile { Cautious, Balanced, Reckless }
float GetDecisionModifier(RiskProfile profile)
{
// Returns a multiplier the AI applies to a chosen action's utility,
// sometimes skewing toward a mistake based on personality.
float r = UnityEngine.Random.value;
switch (profile)
{
case RiskProfile.Cautious:
// 10% chance to undervalue aggressive plays
return (r < 0.10f) ? 0.6f : 1f;
case RiskProfile.Balanced:
// 20% chance to slightly misjudge either way
return (r < 0.20f) ? (r < 0.10f ? 0.8f : 1.2f) : 1f;
case RiskProfile.Reckless:
// 30% chance to overvalue risky plays
return (r < 0.30f) ? 1.5f : 1f;
}
return 1f;
}
Use state and goals to justify occasional errors that still “fit” the faction’s character.
void BuildFoodOrTimber(FactionState faction)
{
bool needsFood = faction.NeedsFoodNow();
float mistakeChance = 0.15f; // tune per difficulty & personality
if (needsFood && UnityEngine.Random.value < mistakeChance)
{
// Misjudges urgency; narrative: "short-term cash need" or "misread"
Build("TimberYard");
}
else
{
Build("Farm");
}
}
Artificial stupidity is not the opposite of artificial intelligence; it’s a design tool that makes AI feel human and—crucially—harder to beat. By layering weighted choices, fuzzy utilities, timed hesitation, risk profiles, and contextual mistakes, Tempus Inceptum creates opponents that are intelligent, fallible, and formidable.
Perfect AI can be mastered. Flawed AI keeps players on edge.