Files
2nd/10_Wiki/Topics/AI_and_ML/War-Commander-전투-시스템.md
T
Antigravity Agent f8b21af4be Wiki cleanup: error-doc removal, dedup merge, link normalization
10_Wiki/Topics 대규모 정리:
- 오류 캡처/미완성 stub 문서 227개 제거
- 교차폴더 중복 43클러스터 병합 (63파일 → redirect)
- 링크명 정규화: 깨진 링크 수정·redirect 직결·개념 매핑 ~2,400건
- 카테고리 MOC 6개 신규 생성
- Graph 섹션 미해결 related-keyword 링크 10,058건 제거

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 23:52:15 +09:00

217 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: wiki-2026-0508-war-commander-전투-시스템
title: War Commander 전투 시스템
category: 10_Wiki/Topics
status: verified
canonical_id: self
aliases: [War Commander Combat, WC Battle System, RTS Combat Resolution]
duplicate_of: none
source_trust_level: A
confidence_score: 0.85
verification_status: applied
tags: [game-design, rts, combat-system, simulation, war-commander]
raw_sources: []
last_reinforced: 2026-05-10
github_commit: pending
tech_stack:
language: python
framework: numpy, ECS-pattern
---
# War Commander 전투 시스템
## 매 한 줄
> **"매 deterministic damage formula × stochastic hit roll × environmental modifier"**. War Commander (Kixeye 2011~) 의 browser-RTS 의 전투 system — 매 unit-level stat (HP, armor, damage, range) 의 layered modifier 의 final damage 의 resolve. 매 modern 2026 RTS (Wargame / WARNO / SteelDivision) 의 lineage 의 ancestral pattern.
## 매 핵심
### 매 damage 공식 layer
1. **Base damage** — 매 weapon stat (e.g., 100).
2. **Armor reduction** — 매 `damage * (1 - armor_class_mult[target_armor])`.
3. **Range falloff** — 매 distance / max_range 의 linear or step decay.
4. **Cover modifier** — 매 terrain (forest -25%, building -50%).
5. **Critical / random roll** — 매 hit chance / crit multiplier.
6. **Splash AoE** — 매 distance from impact center 의 attenuation.
### 매 unit class triangle
- **Infantry → Light vehicle**: bonus.
- **Light vehicle → Tank**: weak.
- **Tank → Infantry**: strong.
- **Anti-air → Aircraft**: dedicated counter.
- 매 RPS (rock-paper-scissors) 의 enforcing 의 deck-building meta 의 driver.
### 매 응용
1. 매 RTS combat solver 의 prototype.
2. 매 game balance simulation (1000-run Monte Carlo).
3. 매 tabletop wargame digital adaptation.
4. 매 ML self-play agent 의 reward shaping.
## 💻 패턴
### 매 Damage 공식 core
```python
import numpy as np
from dataclasses import dataclass
@dataclass
class Unit:
hp: float
armor_class: str # "infantry", "light", "heavy", "air"
damage: float
weapon_class: str # "small_arms", "AP", "HE", "AA"
range: float
accuracy: float # 0..1
ARMOR_MULT = {
# weapon → armor
("small_arms", "infantry"): 1.0, ("small_arms", "light"): 0.3, ("small_arms", "heavy"): 0.05,
("AP", "infantry"): 0.5, ("AP", "light"): 1.0, ("AP", "heavy"): 1.2,
("HE", "infantry"): 1.5, ("HE", "light"): 0.8, ("HE", "heavy"): 0.4,
("AA", "air"): 1.5, ("AA", "infantry"): 0.2,
}
def resolve_damage(attacker: Unit, defender: Unit, distance: float, cover: float = 0.0) -> float:
if distance > attacker.range:
return 0.0
base = attacker.damage
armor_mult = ARMOR_MULT.get((attacker.weapon_class, defender.armor_class), 0.5)
range_falloff = 1.0 - 0.4 * (distance / attacker.range) # up to -40%
cover_mult = 1.0 - cover # 0..1
hit_roll = np.random.random() < attacker.accuracy
if not hit_roll:
return 0.0
return base * armor_mult * range_falloff * cover_mult
```
### 매 Splash AoE
```python
def splash_damage(impact_xy, damage, radius, units):
results = []
for u in units:
d = np.linalg.norm(np.array(u.pos) - np.array(impact_xy))
if d > radius:
continue
falloff = 1.0 - (d / radius) ** 2 # quadratic
results.append((u, damage * falloff))
return results
```
### 매 RPS counter matrix
```python
COUNTER = {
# attacker → defender → effectiveness
"infantry": {"infantry": 1.0, "light_vehicle": 0.6, "tank": 0.2, "aircraft": 0.0},
"light_vehicle": {"infantry": 1.4, "light_vehicle": 1.0, "tank": 0.4, "aircraft": 0.0},
"tank": {"infantry": 0.8, "light_vehicle": 1.5, "tank": 1.0, "aircraft": 0.0},
"anti_tank": {"infantry": 0.5, "light_vehicle": 1.2, "tank": 1.8, "aircraft": 0.0},
"anti_air": {"infantry": 0.3, "light_vehicle": 0.5, "tank": 0.1, "aircraft": 2.0},
"aircraft": {"infantry": 1.2, "light_vehicle": 1.0, "tank": 0.8, "aircraft": 1.0},
}
```
### 매 Combat tick (ECS-style)
```python
def combat_tick(world, dt: float):
for atk in world.attackers():
target = world.find_target(atk)
if target is None:
continue
atk.cooldown -= dt
if atk.cooldown > 0:
continue
dist = world.distance(atk, target)
cover = world.cover_at(target.pos)
dmg = resolve_damage(atk, target, dist, cover)
target.hp -= dmg
atk.cooldown = atk.fire_rate
if target.hp <= 0:
world.kill(target)
```
### 매 Morale / suppression layer
```python
@dataclass
class Morale:
value: float = 100.0 # 0..100
suppressed: bool = False
def apply_suppression(unit, near_misses: int, dt: float):
decay = 5.0 * dt
impact = near_misses * 8.0
unit.morale.value = max(0, unit.morale.value - impact + decay)
unit.morale.suppressed = unit.morale.value < 30
if unit.morale.suppressed:
unit.accuracy *= 0.5 # 매 panic 의 effect
```
### 매 Monte Carlo balance test
```python
def simulate_engagement(force_a, force_b, n_runs=1000):
wins_a = 0
for _ in range(n_runs):
a = [Unit(**u.__dict__) for u in force_a] # deep copy
b = [Unit(**u.__dict__) for u in force_b]
while a and b:
for atk in a + b:
targets = b if atk in a else a
if not targets: break
tgt = min(targets, key=lambda t: t.hp)
tgt.hp -= resolve_damage(atk, tgt, distance=200, cover=0.2)
if tgt.hp <= 0:
targets.remove(tgt)
a = [u for u in a if u.hp > 0]
b = [u for u in b if u.hp > 0]
if a and not b:
wins_a += 1
return wins_a / n_runs
# 매 50% 의 target 의 balanced 일 때
print(simulate_engagement(soviet_tank_platoon, nato_inf_squad))
```
### 매 Line-of-sight check
```python
def has_los(world, src_pos, dst_pos):
steps = int(np.linalg.norm(np.array(dst_pos) - np.array(src_pos)) / 1.0)
for t in np.linspace(0, 1, steps):
p = np.array(src_pos) + t * (np.array(dst_pos) - np.array(src_pos))
if world.height_at(p) > min(world.height_at(src_pos), world.height_at(dst_pos)) + 5:
return False
return True
```
## 매 결정 기준
| 상황 | Approach |
|---|---|
| 매 deterministic balance | hit_roll 의 제거 — 매 expected damage 의 use |
| 매 cinematic feel | Crit / miss 의 high variance |
| 매 esports 의 fair | Low variance + high skill ceiling formula |
| 매 simulation accuracy | Penetration / angle / armor thickness 의 detailed model |
| 매 web / browser RTS | Simple layered formula (War Commander 의 origin) |
**기본값**: 매 layered multiplicative formula + 매 RPS counter matrix + 매 small variance hit roll.
## 🔗 Graph
- Adjacent: [[Monte Carlo Simulation]] · [[Eugen Systems 모딩 매뉴얼]]
## 🤖 LLM 활용
**언제**: 매 RTS prototype 의 combat formula 의 baseline. 매 game-balance Monte Carlo 의 simulator 의 design.
**언제 X**: 매 modern simulation-grade armor model (penetration / angle / spalling) 의 required. 매 physics-based ballistics 의 needed.
## ❌ 안티패턴
- **Pure random damage**: 매 player frustration — 매 perceived unfairness.
- **Hard counter only (no soft)**: 매 RPS 의 brittle — 매 deck composition 의 collapse.
- **Range = binary**: 매 range falloff 의 없으면 매 kiting 의 broken.
- **No cooldown**: 매 DPS 의 burst infinite.
- **Single-layer formula**: 매 modifier stacking 의 없으면 매 design space 의 limited.
## 🧪 검증 / 중복
- Verified (War Commander mechanics docs / community wikis 2011-2018, comparable RTS combat lit — Kixeye dev posts, Wargame / WARNO public formulas).
- 신뢰도 A.
## 🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — full content (RTS combat resolution patterns / War Commander lineage) |