Abstract
Problem: How did the AI system work in Arcanum: Of Steamworks and Magick Obscura, a game built in the late 1990s with severe hardware constraints?
Approach: Tim Cain walks through the architecture of Arcanum's AI — from sector-based world streaming and heartbeat-driven NPC updates, to combat awareness propagation, crime detection via dead bodies, and the role of factions in NPC decision-making.
Findings: Arcanum used a heartbeat system (similar to what Unity later adopted) where NPCs received periodic AI ticks every ~3 seconds, with the rate slowing based on distance from the player to conserve CPU. Combat awareness propagated via radius-based events with loudness levels. Dead bodies stored their killer's identity, enabling guards and faction members to investigate crimes — and players could drag corpses to hide evidence.
Key insight: By tying AI update frequency to player distance and guaranteeing off-screen initialization, Arcanum achieved complex NPC behaviors on 1998 hardware through elegant resource management rather than raw computational power.
Sector Streaming and Creature Loading
Arcanum's world was divided into sectors arranged on a grid. The viewport was deliberately sized so that when standing in the center of a sector, only that sector was visible. At most, a player could see four sectors at once (when standing near a grid corner where four sectors meet). This meant the engine never needed more than four sectors loaded simultaneously.
As the player moved toward a sector edge, the engine would pre-load adjoining sectors and unload distant ones. When sectors loaded, all creatures within them were instantiated and began receiving AI updates.
The Heartbeat System
All AI was driven by heartbeats — periodic ticks every three seconds (Tim initially remembered two, but confirmed three from the source code). This is essentially the same pattern Unity uses today, but Troika implemented it in 1998.
First Heartbeat
When a creature activated (its sector loaded), it received a special "first heartbeat." This was guaranteed to happen off-screen — either before a fade-in for instanced areas, or because approaching sectors are always beyond the viewport. During this first heartbeat, creatures could safely perform setup that would look strange if visible: teleporting to positions, wielding weapons, checking inventory, or starting animations.
Distance-Based Heart Rate
A critical optimization: heartbeat frequency decreased based on tile distance from the player. Within close range, creatures got the full 3-second rate. Beyond about 30 tiles, the rate was at its slowest. This was purely a CPU conservation measure — there simply weren't enough cycles to give every loaded creature a full-speed heartbeat.
The tradeoff was acceptable because distant creatures were off-screen. If a walking NPC got a slower heartbeat, they'd "jump" along their path rather than smoothly walking — but nobody could see it happen.
Four AI States
Every creature had four basic AI states:
- Not Fighting — Normal behavior: walking around their shop, patrolling, living their life according to their social class
- Fighting — Active combat
- Fleeing — Triggered when health dropped below a configurable percentage (some creatures had this set to zero, meaning they'd never flee). Fleeing lasted a set number of seconds, after which the creature would stop and enter the Not Fighting state — they wouldn't return to combat
- Surrendered — Could be triggered by spells or charisma-based abilities. The creature would stop fighting and wouldn't resume unless attacked again or their health recovered above ~80%
Combat Awareness and the Radius System
When an attack occurred, the system broadcast events using two radii — one around the attacker and one around the victim. The radius size depended on the attack's loudness level:
- Quiet — Very small radius (stealth attacks, tampering)
- Normal — Regular radius
- Loud — Large radius
The attacker's broadcast said "I'm attacking this target" — alerting followers and faction members who might want to help. The victim's broadcast said "I'm being attacked" — alerting guards and allies.
Line of Sight and Identity
A subtle detail: the victim's broadcast only identified the attacker if the victim could actually see them. If shot from far away, nearby NPCs would know the direction of the attack but not the attacker's identity until they had line of sight. This made ranged stealth attacks meaningfully different from melee combat.
Tampering Events
The same radius system handled non-combat crimes. Picking locks, pickpocketing, and other "tampering" actions broadcast quiet events. If a guard or faction member was within the small quiet radius, they'd investigate. Since guards helped every faction, they'd respond to any tampering they detected.
Dead Bodies and Crime Investigation
One of Arcanum's more sophisticated AI features: dead bodies remembered their killer. When an NPC discovered a corpse, the system checked whether they cared (same faction as the victim, or a guard). If they cared, they'd read the killer's identity from the body and begin searching for them.
The Combat Focus Timer
The killer's identity (called "combat focus") was stored on the body but would expire after roughly 15 in-game minutes — but only if the player had left the area. If the player stayed nearby, the evidence persisted.
Body Dragging
Borrowed from Fallout, players could click and drag corpses to hide them. This interacted with the investigation system: drag a body to an alley before guards patrol past, and nobody discovers the crime.
Corpse Decay
Bodies decayed into blood splatters after 24 in-game hours. Blood splatters disappeared after two days. This guaranteed that all evidence of a crime would eventually vanish, giving patient players a clean escape.
The Arrow Trap Bug
Tim recounts a memorable early bug: traps were implemented as attacks on whoever triggered them. When a companion triggered an arrow trap, the companion's AI registered the trap as an attacker — and walked over to punch it. Since traps were destructible objects with health, the companion would dutifully beat the inanimate object to death. The fix was teaching NPCs that inanimate objects don't have hostile intent.
YouTube Algorithm vs. Audience
Tim opens the video with a wry observation: YouTube's analytics told him technical videos like this one attracted fewer viewers and recommended he make more "gossipy" content ("Why I Quit Fallout 2," "Why I Quit WildStar"). Yet his actual comment sections consistently requested more technical deep-dives. He chose to follow his audience over the algorithm.
References
- Tim Cain. YouTube video. https://www.youtube.com/watch?v=NhIIydTvIcQ