Files
2nd/10_Wiki/Topics/AI_and_ML/전투 전술(Battle Strategies).md
T
koriweb d8a80f6272 chore(wiki): dangling 링크 canonical 정규화 (768파일/1200건)
이름만 다른(표기 변형) [[위키링크]]를 대상 문서의 canonical 제목으로 치환해
끊겼던 1,200개 링크를 연결. 제목/파일명 정규화 일치만 적용하고 별칭 매칭은
과병합 위험으로 제외(애매성 가드). 원본은 _link_reconcile_backup/ 에 백업.
도구: Datacollect/scripts/link_reconcile_apply.mjs

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 12:24:15 +09:00

6.4 KiB
Raw Blame History

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-전투-전술-battle-strategies 전투 전술(Battle Strategies) 10_Wiki/Topics verified self
Battle Strategies
전투 전술
Combat Tactics
none A 0.9 applied
game-design
rts
tactics
combat
2026-05-10 pending
language framework
typescript ECS/BehaviorTree

전투 전술 (Battle Strategies)

매 한 줄

"매 전투 전술은 unit composition × terrain × tempo 의 곱". RTS/wargame design 의 핵심 axis 로, Sun Tzu 의 고전 doctrine 에서 출발해 modern wargame (WARNO, Steel Division 2, Broken Arrow) 에서는 fog-of-war + recon priority + combined-arms 로 진화. AI opponent 는 utility-based scoring 과 behavior tree 로 구현.

매 핵심

매 4대 축

  • Composition: unit roster 의 다양성 — infantry / armor / artillery / recon / support
  • Terrain: cover, elevation, choke point — line-of-sight 와 movement cost 의 변형
  • Tempo: 매 OODA loop — observe → orient → decide → act, 반복 주기
  • Information: fog-of-war, recon, EW (electronic warfare) — 정보 비대칭 활용

매 doctrine 분류

  • Attrition: 매 firepower 압박 — losses 를 강제, 적 reinforcement curve 를 break
  • Maneuver: 매 flanking + encirclement — Schwerpunkt (focal point) 에 mass 집중
  • Defensive-elastic: 매 layered defense — kill zone 유도 후 counter-attack
  • Asymmetric: 매 guerilla / hit-and-run — engagement 거부, 공급망 공격

매 응용

  1. RTS AI controller — utility scoring 으로 매 frame 행동 선택.
  2. Wargame mission design — objective gating 으로 player 가 doctrine 학습.
  3. Auto-battler balance — 상성 표 + composition entropy 측정.

💻 패턴

Utility-based unit AI

type UnitState = { hp: number; ammo: number; pos: Vec2; supply: number }
type Action = "attack" | "retreat" | "hold" | "flank"

function score(s: UnitState, a: Action, ctx: BattleCtx): number {
  switch (a) {
    case "attack":  return s.ammo * 0.4 + ctx.enemyExposed * 0.6 - s.hpDeficit * 0.5
    case "retreat": return s.hpDeficit * 0.8 - ctx.allyNearby * 0.3
    case "hold":    return ctx.cover * 0.7 + ctx.objectiveDist * -0.2
    case "flank":   return ctx.enemyFlankExposed * 0.9 - s.supply * 0.4
  }
}

function pickAction(s: UnitState, ctx: BattleCtx): Action {
  const actions: Action[] = ["attack", "retreat", "hold", "flank"]
  return actions.reduce((best, a) =>
    score(s, a, ctx) > score(s, best, ctx) ? a : best
  )
}

Threat assessment grid

function buildThreatMap(units: Unit[], grid: Grid): Float32Array {
  const map = new Float32Array(grid.w * grid.h)
  for (const u of units) {
    if (u.team !== "enemy") continue
    const range = u.weaponRange
    for (let dy = -range; dy <= range; dy++) {
      for (let dx = -range; dx <= range; dx++) {
        const x = u.pos.x + dx, y = u.pos.y + dy
        if (!grid.inBounds(x, y)) continue
        const dist = Math.hypot(dx, dy)
        if (dist > range) continue
        map[y * grid.w + x] += u.firepower * (1 - dist / range)
      }
    }
  }
  return map
}

Schwerpunkt detection

function findSchwerpunkt(allies: Unit[], threatMap: Float32Array, grid: Grid): Vec2 {
  let bestScore = -Infinity, bestPos = allies[0].pos
  for (const u of allies) {
    const idx = u.pos.y * grid.w + u.pos.x
    const massNearby = allies.filter(a => Vec2.dist(a.pos, u.pos) < 200).length
    const threatGap = 1 / (threatMap[idx] + 0.1)
    const score = massNearby * threatGap
    if (score > bestScore) { bestScore = score; bestPos = u.pos }
  }
  return bestPos
}

Tempo controller (OODA)

class TempoController {
  private lastDecisionAt = 0
  private cycleMs = 800

  tick(now: number, ctx: BattleCtx) {
    if (now - this.lastDecisionAt < this.cycleMs) return
    const obs = this.observe(ctx)
    const orient = this.orient(obs)
    const decision = this.decide(orient)
    this.act(decision)
    this.lastDecisionAt = now
    this.cycleMs = Math.max(300, 800 - ctx.pressureLevel * 100)
  }
}

Recon priority queue

function reconTargets(unknown: Cell[], objectives: Vec2[]): Cell[] {
  return unknown
    .map(c => ({
      cell: c,
      score: objectives.reduce((s, o) => s + 1 / (Vec2.dist(c.pos, o) + 1), 0),
    }))
    .sort((a, b) => b.score - a.score)
    .slice(0, 5)
    .map(x => x.cell)
}

Combined-arms morale boost

function moraleBonus(unit: Unit, allies: Unit[]): number {
  const nearby = allies.filter(a => Vec2.dist(a.pos, unit.pos) < 150)
  const types = new Set(nearby.map(a => a.type))
  return types.size >= 3 ? 0.25 : types.size >= 2 ? 0.1 : 0
}

매 결정 기준

상황 Approach
Numeric superiority + open terrain Attrition + frontal mass
Mobile force vs static defense Maneuver, flank Schwerpunkt
Outnumbered, defensive Elastic defense + kill zones
Unknown enemy composition Recon-heavy, delay engagement
Long campaign, supply-limited Asymmetric, denial

기본값: combined-arms balanced doctrine + recon-first opening.

🔗 Graph

🤖 LLM 활용

언제: tactical AI scripting, mission designer 의 pacing 검증, opening-book 생성. 언제 X: 매 frame-tight pathfinding 의 inner loop — LLM latency 가 너무 큼, behavior tree 에 위임.

안티패턴

  • Single-unit doctrine: 단일 병종 spam — counter unit 1 종류로 전체 collapse.
  • Static formation: tempo 무시 — 매 적의 OODA 가 빨라 reactive 가 됨.
  • Recon skip: 매 fog-of-war 무시 → blind commit, ambush 함정.
  • Schwerpunkt 부재: 매 force dispersion → 어디서도 decisive mass 못 만듦.

🧪 검증 / 중복

  • Verified (Eugen Systems WARNO design docs, US FM 3-0 Operations).
  • 신뢰도 A.

🕓 Changelog

날짜 변경
2026-05-08 Phase 1
2026-05-10 Manual cleanup — battle tactics doctrine + AI scoring patterns