Abstract
Problem: How did Arcanum's random encounter system work, and how did it differ from Fallout's approach?
Approach: Tim Cain revisited the original Arcanum source code to trace how the random encounter system was implemented, including its timer mechanics, encounter tables, designer overrides, and integration with the quest/story system.
Findings: Arcanum used a timed event queue to check for encounters every 5–11.6 game hours, with location-based encounter tables influenced by terrain, time of day, sleep state, and designer-placed radius overrides. Story-driven encounters (like the Molochean Hand assassins) piggy-backed on this system via quest state triggers. A separate monster generator system handled persistent spawning locations.
Key insight: The random encounter system was deeply intertwined with Arcanum's general-purpose timed event queue, giving designers enormous flexibility through script overrides, encounter counters, and story state hooks — but the code ended up stuffed inside a UI module rather than its own clean module.
Timer and Frequency
Random encounters were driven by Arcanum's timed event system — a general-purpose queue that any game system could push events into, operating on either real time or game time (with a secondary "game time two" variant that ignored pauses).
The system checked for a random encounter every 300–700 game minutes (roughly 5 to 11.6 game hours). Whether or not an encounter triggered, the timer reset for another 5–11.6 hours. This meant you could get two encounters in a 12-hour period if the rolls were short, or just one if they weren't.
Encounters could only fire while the player was on a world map sector without a town map. They triggered during fast travel (where game time sped up), manual walking between sectors, or even just standing still — the system only cared about the passage of game time.
Encounter Tables and Terrain
Each encounter check consulted a table based on the player's exact location (sector and tile), the base terrain type (light forest, desert, coastal, plains, grasslands, etc.), and the time of day. A light forest during the day had different encounters than the same forest at night.
Entries in the table had two key properties:
- Power setting — easy, average, or powerful, set by the designer
- Frequency — a roll chance, checked sequentially down the list; designers could move entries higher and increase frequency to make them more common
The system walked down the list checking frequencies until one triggered. Crucially, frequencies were automatically increased if the player was sleeping — a design choice that was part realism, part fun, and part a nudge to sleep indoors rather than in the wilderness.
Designer Overrides and Radius Circles
Designers could place override points with a radius anywhere on the world map. If an encounter triggered within that radius, a custom table replaced the default terrain-based one.
This was used for locations like ruins without town maps — a designer could drop a point on the ruin with a small radius pointing to an undead-heavy table, so passing through that area meant skeletons and zombies instead of generic wildlife.
When multiple override circles overlapped, the smaller radius took precedence (the logic being it was more specific/concentrated). Ties in radius were broken by distance to center, and beyond that, by detection order — though Tim noted that final tiebreaker probably never actually triggered in practice.
Spawning and Formation
When an encounter triggered, creatures were spawned at a set distance from the player and arranged using a formation scatter function to prevent them from stacking on top of each other. The encounter data specified:
- Creature types and counts (single type or mixed groups)
- Equipment for humanoids (armor, weapons, wielded)
- Loot for creatures
- Possibly loot containers, though Tim was uncertain on this detail
Encounter Counters and Script Hooks
Every encounter tracked how many times it had been triggered. Since Tim had put script overrides on everything, designers could write scripts that:
- Capped a special encounter at a certain number of occurrences, then deleted the override
- Scaled difficulty by adding extra creatures on repeated triggers
- Spawned a boss creature after a threshold number of encounters
This gave designers fine-grained control over encounter progression without touching the core system.
Story-Driven Encounters
Arcanum had 27 defined story states marking key points in its non-linear storyline. Quests and story states could inject their own timed events into the encounter system.
This is how the Molochean Hand assassins worked: once the player reached a certain point in the story, timed events would fire that spawned the assassins as if they were random encounters. After spawning, these story encounters pushed the random encounter timer forward by several hours to prevent a regular encounter from piling on moments later.
Unfinished Feature: Occupied Sector Check
Tim found a commented-out check with a programmer's note saying "didn't have time to do this." The intended behavior: if a random encounter would trigger in a sector that already had living creatures spawned in it, the encounter would be delayed.
The goal was to prevent piling encounters on top of existing enemies. Tim personally thought the overlap could have been fun — enemies from different factions might fight each other — but acknowledged the probability of all conditions aligning was vanishingly small. He expressed curiosity about whether any player ever witnessed such an occurrence.
Monster Generators: A Separate System
Tim emphasized that random encounters and monster generators were completely different systems. Monster generators were objects placed at specific world locations containing:
- A creature list with equipment/loot data (similar to encounter tables)
- Their own independent timer
- Script overrides for conditions (time of day, quest state, spawn count limits)
These were used in dungeons and the overworld to provide an endless supply of monsters until the player completed some condition that triggered the spawner to stop. They were location-bound, not event-queue-driven like random encounters.
References
- Tim Cain. YouTube video. https://www.youtube.com/watch?v=-sB_AnqAG5w