--- 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) |