"매 단일 병종은 counter 가 있고, 매 multi-arms 는 counter 의 counter". 1차 대전 후 독일군 Stoßtruppen 에서 doctrine 화, 2차 대전 Blitzkrieg 와 modern AirLand Battle (FM 100-5) 의 핵심. RTS/wargame 에서는 매 unit synergy graph + bonus stacking 으로 modeling.
매 핵심
매 doctrine 본질
상호보완: 매 병종이 다른 병종의 weakness 를 cover
synergy bonus: presence 자체로 stat boost (morale, accuracy, suppression)
threat dilemma: 적이 1 axis 만 counter 못 함 — multi-axis 로 강제 trade-off
tempo amplifier: 매 arm 이 다른 arm 의 OODA 를 가속
매 5대 arm (modern)
Infantry: terrain hold, urban, recon-by-fire
Armor: shock, breakthrough, overmatch
Artillery: suppression, area denial, indirect kill
Air: deep strike, CAS (close air support), reconnaissance
EW/Cyber: jamming, sensor blind, comm denial
매 응용
RTS army composition validator — entropy + synergy score.
functioncompositionEntropy(army: Unit[]):number{constcounts: Record<string,number>={}for(constuofarmy)counts[u.arm]=(counts[u.arm]??0)+1consttotal=army.lengthletH=0for(constkincounts){constp=counts[k]/totalH-=p*Math.log2(p)}returnH// higher = more diverse
}
Threat dilemma checker
functionposesDilemma(myArmy: Unit[],enemyDoctrine: ArmType[]):boolean{constmyArms=newSet(myArmy.map(u=>u.arm))constcounters=newSet(enemyDoctrine.flatMap(a=>COUNTERS_FOR[a]))// 매 적이 모든 my-arms 를 동시에 counter 할 수 없으면 dilemma
return[...myArms].some(a=>!counters.has(a))}
Suppression + assault combo
classCombinedAssault{asyncexecute(infantry: Unit[],artillery: Unit[],target: Vec2){// 매 step 1: artillery suppression
awaitartillery[0].fireSuppression(target,{duration: 30})// 매 step 2: infantry advance under suppression
constadvanceBonus=0.3for(constiofinfantry)i.modifyAccuracy(advanceBonus)awaitPromise.all(infantry.map(i=>i.moveTo(target)))// 매 step 3: artillery shifts to depth
awaitartillery[0].shiftFire(target.add({x: 0,y: 200}))}}
Air-armor pincer
functionplanPincer(armor: Unit[],air: Unit[],enemy: Position):Plan{return{armorAxis:{from:enemy.flank("west"),bearing:"east"},airAxis:{strikeAt: enemy.flank("east"),timing:"T+30s"},rationale:"armor fixes, air kills retreat — 매 dilemma",}}
EW + artillery deep strike
asyncfunctiondeepStrike(ew: Unit,arty: Unit,hvt: HighValueTarget){awaitew.jamRadar(hvt.airDefense,{duration: 60})// 매 SAM blind window 에 artillery 가 deep target 타격
awaitarty.fireMission(hvt.position,{round:"GMLRS",count: 6})}