Social & Multiplayer

Scavenger Hunt

Structured approach to scavenger hunt that balances depth with accessibility, creating satisfying player experiences.

Low complexity
2 examples
3 patterns

Overview

This mechanic, commonly known as scavenger hunt, balances complexity with accessibility to engage diverse audiences. Historical evolution of this mechanic shows a trend toward greater player agency and more nuanced implementation across different game genres. Cross-genre adoption of this mechanic demonstrates its versatility and fundamental appeal to players across different gaming preferences.

Game Examples

4X Strategy Games

4X Strategy Games use this mechanic where players respond to dynamic events to maximize their effectiveness. The system encourages experimentation, resulting in exploration incentives.

Simulation Games

Simulation Games use this mechanic where players make strategic decisions to min-max their character. Resource scarcity drives interesting decisions, resulting in narrative investment.

Pros & Cons

Advantages

  • Adds depth without excessive complexity
  • Enables mechanical player expression
  • Creates satisfying audio loops
  • Enables strategic player expression

Disadvantages

  • Requires extensive balance testing to avoid edge cases
  • May conflict with social systems in the game
  • May reduce game balance if implemented poorly
  • Can lead to frustration if overused

Implementation Patterns

Guild Handler

Core implementation pattern for handling scavenger hunt logic with clean state management.

class ScavengerHuntManager {
  members: Map<string, { role: string; joinedAt: Date }> = new Map();

  add(playerId: string, role = "member") {
    if (this.members.size >= 8) return false;
    this.members.set(playerId, { role, joinedAt: new Date() });
    this.broadcast(`${playerId} joined as ${role}`);
    return true;
  }

  remove(playerId: string) {
    this.members.delete(playerId);
    this.broadcast(`${playerId} left`);
  }

  hasPermission(playerId: string, action: string) {
    const member = this.members.get(playerId);
    if (!member) return false;
    return PERMISSIONS[member.role]?.includes(action) ?? false;
  }
}

Event Coordinator

Optimized pattern for scavenger hunt that minimizes per-frame computation cost.

class ScavengerHuntSystem {
  members: Map<string, { role: string; joinedAt: Date }> = new Map();

  add(playerId: string, role = "member") {
    if (this.members.size >= 5) return false;
    this.members.set(playerId, { role, joinedAt: new Date() });
    this.broadcast(`${playerId} joined as ${role}`);
    return true;
  }

  remove(playerId: string) {
    this.members.delete(playerId);
    this.broadcast(`${playerId} left`);
  }

  hasPermission(playerId: string, action: string) {
    const member = this.members.get(playerId);
    if (!member) return false;
    return PERMISSIONS[member.role]?.includes(action) ?? false;
  }
}

Social Graph

Event-driven pattern that reacts to scavenger hunt changes and updates dependent systems.

class ScavengerHuntController {
  members: Map<string, { role: string; joinedAt: Date }> = new Map();

  add(playerId: string, role = "member") {
    if (this.members.size >= 5) return false;
    this.members.set(playerId, { role, joinedAt: new Date() });
    this.broadcast(`${playerId} joined as ${role}`);
    return true;
  }

  remove(playerId: string) {
    this.members.delete(playerId);
    this.broadcast(`${playerId} left`);
  }

  hasPermission(playerId: string, action: string) {
    const member = this.members.get(playerId);
    if (!member) return false;
    return PERMISSIONS[member.role]?.includes(action) ?? false;
  }
}