Files
2nd/10_Wiki/Topics/AI_and_ML/Dynamic Difficulty Adjustment (DDA).md
T
2026-05-10 22:08:15 +09:00

9.5 KiB

id, title, category, status, canonical_id, aliases, duplicate_of, source_trust_level, confidence_score, verification_status, tags, raw_sources, last_reinforced, github_commit, tech_stack
id title category status canonical_id aliases duplicate_of source_trust_level confidence_score verification_status tags raw_sources last_reinforced github_commit tech_stack
wiki-2026-0508-dda Dynamic Difficulty Adjustment (DDA) 10_Wiki/Topics verified self
DDA
dynamic difficulty
rubber banding
AI Director
flow state
adaptive difficulty
none B 0.85 applied
game-design
dda
dynamic-difficulty
flow
ai-director
player-modeling
adaptive
2026-05-10 pending
language applicable_to
game design
Game Design
Adaptive Learning
ML Curriculum

Dynamic Difficulty Adjustment (DDA)

매 한 줄

"매 player skill 의 real-time 매 difficulty 의 dial". Csikszentmihalyi 의 Flow zone 의 maintain. 매 Left 4 Dead 의 AI Director, 매 racing 의 rubber banding. 매 modern: 매 ML-driven player model + 매 ethical detect (gaming the system). 매 LMS adaptive learning 의 same principle.

매 핵심

매 mechanism

  1. Player metric: 매 win rate, HP remaining, time, deaths.
  2. Skill estimate: 매 sliding window of recent.
  3. Adjustment: 매 enemy stats / spawn / hint.
  4. Subtle: 매 obvious 의 player 의 frustrate.

매 famous example

  • Left 4 Dead AI Director (Valve): 매 zombie spawn 의 control.
  • Resident Evil 4: 매 difficulty 의 silent.
  • Mario Kart: 매 rubber banding (item, speed).
  • Crash Bandicoot: 매 attempt 후 의 adjust.
  • Mario AI (research): 매 student 의 player.

매 method

  • Heuristic: 매 simple rule.
  • Bayesian player model: 매 skill posterior.
  • RL-based: 매 difficulty 의 policy 학습.
  • MCTS-based: 매 lookahead.

매 ethical / design constraint

  • Subtle: 매 player 의 perception X.
  • Fair feel: 매 effort-reward.
  • Not patronize: 매 매 player 의 skill ↑ 의 acknowledge.
  • No gaming detection: 매 player 의 intentional poor 의 abuse.

매 응용

  1. Action / shooter: 매 enemy difficulty.
  2. Racing: 매 rubber banding.
  3. Puzzle: 매 hint.
  4. MMO raid: 매 boss adjustment.
  5. Edu game / LMS: 매 question difficulty.
  6. AI tutor: 매 explanation depth.
  7. Aim training: 매 Cognitive Training Software (eg Aim Lab_KovaaKs) 의 adaptive scenario.

매 modern AI 응용

  • Player modeling: 매 ML 의 skill 의 estimate.
  • RL-based DDA: 매 difficulty controller 의 train.
  • Generative content: 매 procedurally adapted level.

💻 패턴

Sliding window skill estimator

class SkillEstimator {
  private history: number[] = [];
  
  recordOutcome(win: boolean, time: number, hpLost: number) {
    const score = (win ? 1 : 0) * (60 / Math.max(time, 1)) * (1 - hpLost / 100);
    this.history.push(score);
    if (this.history.length > 20) this.history.shift();
  }
  
  estimateSkill(): number {
    if (!this.history.length) return 0.5;
    return this.history.reduce((a, b) => a + b, 0) / this.history.length;
  }
}

AI Director-style (probabilistic)

class AIDirector {
  threatLevel = 0;  // 0-1
  
  update(player: Player) {
    const recentDamage = player.recentDamageTaken();
    const ammoLow = player.ammo < 30;
    const downtime = player.timeWithoutCombat();
    
    // 매 raise threat 의 calm
    if (downtime > 30) this.threatLevel = Math.min(1, this.threatLevel + 0.05);
    
    // 매 ease 의 stress
    if (recentDamage > 50 || ammoLow) this.threatLevel = Math.max(0, this.threatLevel - 0.1);
  }
  
  shouldSpawnEnemy(): boolean {
    return Math.random() < this.threatLevel;
  }
  
  enemyComposition() {
    if (this.threatLevel < 0.3) return 'easy_pack';
    if (this.threatLevel < 0.7) return 'mixed';
    return 'horde';
  }
}

Rubber banding (racing)

function applyRubberBand(car: Car, leader: Car) {
  const distanceBehind = leader.position - car.position;
  
  // 매 subtle catch-up
  if (distanceBehind > 100) {
    car.maxSpeed *= 1.05;  // 매 5% boost
    car.itemDropChance *= 1.5;  // 매 better items
  } else if (distanceBehind < -50) {
    // 매 leader 의 small handicap
    car.maxSpeed *= 0.98;
  }
}

Bayesian player model (IRT-inspired)

import numpy as np

class BayesianPlayer:
    def __init__(self, prior_mean=0, prior_var=1):
        self.skill_mean = prior_mean
        self.skill_var = prior_var
    
    def update(self, item_difficulty, success):
        """매 item response theory."""
        # 매 expected probability
        p_success = 1 / (1 + np.exp(-(self.skill_mean - item_difficulty)))
        
        # 매 posterior update (simplified Kalman)
        info = p_success * (1 - p_success)
        self.skill_var = 1 / (1 / self.skill_var + info)
        self.skill_mean += self.skill_var * info * (int(success) - p_success)
    
    def select_difficulty(self, items, target_p=0.7):
        """매 just-beyond comfort."""
        return min(items, key=lambda d: abs(
            1 / (1 + np.exp(-(self.skill_mean - d))) - target_p
        ))

RL-based DDA

class DifficultyController:
    """매 RL 의 매 player 의 engagement 의 maximize."""
    
    def __init__(self):
        self.policy = QNetwork()
    
    def select_difficulty(self, player_state):
        actions = ['decrease', 'maintain', 'increase']
        q_values = self.policy(player_state)
        return actions[q_values.argmax()]
    
    def reward(self, player_state):
        # 매 engagement = match length + retention + flow indicator
        return (
            player_state.session_length * 0.3 +
            (1 if player_state.continued_after_match else 0) * 0.5 +
            player_state.subjective_satisfaction * 0.2
        )

Detect gaming the system

def detect_throw_match(player_history):
    """매 player 의 intentional poor 의 detect."""
    recent = player_history[-10:]
    
    # 매 sudden drop in performance
    historical_avg = np.mean([h.score for h in player_history[:-10]])
    recent_avg = np.mean([h.score for h in recent])
    
    if recent_avg < historical_avg * 0.4:
        return 'WARN: possible throwing for DDA exploit'
    return None

Subtle communication (UX)

function hidePlayerSeesAdjustment() {
  // 매 ❌ 매 obvious
  if (showText) showMessage('Difficulty decreased due to your performance');
  
  // 매 ✅ 매 silent
  // 매 just adjust enemy stats internally.
  // 매 player 의 say "I'm getting better!" 매 actually 의 difficulty 의 ease.
}

A/B test (DDA effectiveness)

def ab_test_dda(players_a_no_dda, players_b_with_dda):
    return {
        'session_length_a': mean(p.session_length for p in players_a_no_dda),
        'session_length_b': mean(p.session_length for p in players_b_with_dda),
        'retention_d7_a': retention(players_a_no_dda, days=7),
        'retention_d7_b': retention(players_b_with_dda, days=7),
        'satisfaction_a': mean(p.satisfaction for p in players_a_no_dda),
        'satisfaction_b': mean(p.satisfaction for p in players_b_with_dda),
    }

LMS adaptive (similar pattern)

def adaptive_quiz(student, item_pool):
    skill = student.estimated_skill
    
    # 매 zone of proximal development
    target_difficulty = skill + 0.5  # 매 just-beyond
    next_item = min(item_pool, key=lambda i: abs(i.difficulty - target_difficulty))
    
    response = present(next_item, student)
    student.update_skill(next_item.difficulty, response.correct)
    return next_item

Procedural difficulty (level generation)

def generate_level(player_skill):
    return {
        'enemy_count': int(10 + player_skill * 20),
        'enemy_hp': 100 * (1 + player_skill * 0.5),
        'puzzle_complexity': int(player_skill * 5),
        'time_limit': 300 - int(player_skill * 100),
        'powerup_density': max(0.1, 0.5 - player_skill * 0.3),
    }

매 결정 기준

Genre DDA approach
Action / Shooter AI Director (Valve-style)
Racing Rubber banding (subtle)
Puzzle Hint frequency
MMO raid Stat-tier difficulty
RPG Side content
Edu game Adaptive item (IRT)
Esports / competitive NO DDA (fairness)
Casual mobile Subtle DDA + retention focus

기본값: 매 Bayesian player model + 매 subtle adjust + 매 A/B test + 매 detect gaming.

🔗 Graph

🤖 LLM 활용

언제: 매 game design. 매 adaptive learning system. 매 personalized challenge. 언제 X: 매 esports / fairness-critical (no DDA).

안티패턴

  • Obvious DDA: 매 player 의 perception → 매 motivation lose.
  • Patronizing: 매 매 player 의 skill 의 acknowledge X.
  • Punishing skilled play: 매 better → 매 harder feel of unfair.
  • No detection 의 throw: 매 exploit.
  • DDA in competitive: 매 fairness violation.
  • Too aggressive adjust: 매 whiplash.

🧪 검증 / 중복

🕓 Changelog

날짜 변경
2026-05-08 Phase 1
2026-05-10 Manual cleanup — mechanism + 매 AI Director / rubber band / Bayesian / RL / detect-throw code