Files
2nd/10_Wiki/Topics/AI_and_ML/War-Commander-전투-시스템.md
T
2026-05-10 22:08:15 +09:00

220 lines
8.2 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
- 부모: [[RTS Game Design]] · [[Combat Resolution Systems]]
- 변형: [[Wargame ALB Combat]] · [[WARNO 전투 모델]] · [[Steel Division Combat]]
- 응용: [[Game Balance Tuning]] · [[Self-play RL Reward]]
- Adjacent: [[ECS Architecture]] · [[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) |