HP: Damage: Attack Range: Move Speed: Speed Multiplier: Spawn Mode:

Configure settings and submit the form to start the simulation.

ancestor-stopped: This cell wasn't run because an ancestor was stopped with `mo.stop`:
ancestor-stopped: This cell wasn't run because an ancestor was stopped with `mo.stop`:
ancestor-stopped: This cell wasn't run because an ancestor was stopped with `mo.stop`:

Lanchester's Laws

Lanchester's laws are mathematical models that describe the power relationship between opposing forces in combat. The Square Law applies to aimed fire combat where each unit can engage any enemy:

dBdt=αR,dRdt=βB\frac{dB}{dt} = -\alpha R, \quad \frac{dR}{dt} = -\beta B

Where:

  • B(t)B(t) = number of Blue units at time tt
  • R(t)R(t) = number of Red units at time tt
  • α\alpha = effectiveness of Red forces (kills per unit per time)
  • β\beta = effectiveness of Blue forces (kills per unit per time)

Solving the Equations

Dividing the two equations:

dBdR=αRβB    βBdB=αRdR\frac{dB}{dR} = \frac{\alpha R}{\beta B} \implies \beta B \, dB = \alpha R \, dR

Integrating both sides:

βB2βB02=αR2αR02\beta B^2 - \beta B_0^2 = \alpha R^2 - \alpha R_0^2

This gives us Lanchester's Square Law:

βB2αR2=βB02αR02=constant\beta B^2 - \alpha R^2 = \beta B_0^2 - \alpha R_0^2 = \text{constant}

Equal Strength Case (α=β\alpha = \beta)

When both armies have equal effectiveness, the equation simplifies to:

B2R2=B02R02B^2 - R^2 = B_0^2 - R_0^2

If Blue wins (meaning R0R \to 0), the surviving Blue force is:

Bfinal=B02R02B_{\text{final}} = \sqrt{B_0^2 - R_0^2}

This only has a real solution when B0>R0B_0 > R_0. The square law explains why concentration of force matters: doubling your army doesn't just double your advantage—it quadruples it.

ancestor-stopped: This cell wasn't run because an ancestor was stopped with `mo.stop`:
ancestor-stopped: This cell wasn't run because an ancestor was stopped with `mo.stop`:
ancestor-stopped: This cell wasn't run because an ancestor was stopped with `mo.stop`:
ancestor-stopped: This cell wasn't run because an ancestor was stopped with `mo.stop`: