8.2 KiB
8.2 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-war-commander-전투-시스템 | War Commander 전투 시스템 | 10_Wiki/Topics | verified | self |
|
none | A | 0.85 | applied |
|
2026-05-10 | pending |
|
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
- Base damage — 매 weapon stat (e.g., 100).
- Armor reduction — 매
damage * (1 - armor_class_mult[target_armor]). - Range falloff — 매 distance / max_range 의 linear or step decay.
- Cover modifier — 매 terrain (forest -25%, building -50%).
- Critical / random roll — 매 hit chance / crit multiplier.
- 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.
매 응용
- 매 RTS combat solver 의 prototype.
- 매 game balance simulation (1000-run Monte Carlo).
- 매 tabletop wargame digital adaptation.
- 매 ML self-play agent 의 reward shaping.
💻 패턴
매 Damage 공식 core
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
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
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)
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
@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
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
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) |