Prophecy / Oracle
Design pattern addressing prophecy / oracle, defining how this system creates engagement and supports the overall game experience.
Overview
As a core game system, prophecy / oracle provides meaningful choices and consequences for player actions. Designers must carefully balance the system's depth against its learning curve, ensuring that new players can engage while experienced players find room for mastery. Understanding the design principles behind this mechanic helps developers create more engaging and balanced game experiences.
Game Examples
Submarine Games
Submarine Games use this mechanic where players weigh competing priorities to tell their own story. Each decision has cascading consequences, resulting in competitive depth.
4X Strategy Games
4X Strategy Games use this mechanic where players coordinate with teammates to collect all available items. Failure states are informative rather than punishing, resulting in high replayability.
Extraction Shooters
Extraction Shooters use this mechanic where players time their actions precisely to support their team effectively. Visual and audio feedback make the interaction satisfying, resulting in exploration incentives.
Pros & Cons
Advantages
- Enables mechanical player expression
- Enhances tactical without disrupting core gameplay
- Provides clear contextual feedback on player actions
- Enables creative player expression
- Creates natural tension between players
Disadvantages
- May reduce game balance if implemented poorly
- Can lead to toxicity if overused
- May create a skill gap for new players
Implementation Patterns
NPC Scheduler
Data-driven implementation that loads prophecy / oracle configuration from external definitions.
class ProphecyOracleController {
currentNode: string = "greeting";
flags: Set<string> = new Set();
getDialogue() {
const node = DIALOGUE_TREE[this.currentNode];
return {
text: node.text,
choices: node.choices.filter(c =>
!c.requires || c.requires.every(f => this.flags.has(f))
)
};
}
choose(choiceIndex: number) {
const node = DIALOGUE_TREE[this.currentNode];
const choice = node.choices[choiceIndex];
if (choice.setsFlag) this.flags.add(choice.setsFlag);
this.currentNode = choice.next;
return this.getDialogue();
}
}Dialogue Controller
Event-driven pattern that reacts to prophecy / oracle changes and updates dependent systems.
class ProphecyOracleProcessor {
currentNode: string = "start";
flags: Set<string> = new Set();
getDialogue() {
const node = DIALOGUE_TREE[this.currentNode];
return {
text: node.text,
choices: node.choices.filter(c =>
!c.requires || c.requires.every(f => this.flags.has(f))
)
};
}
choose(choiceIndex: number) {
const node = DIALOGUE_TREE[this.currentNode];
const choice = node.choices[choiceIndex];
if (choice.setsFlag) this.flags.add(choice.setsFlag);
this.currentNode = choice.next;
return this.getDialogue();
}
}