# Army power calculator

## Recommended Posts

I'm currently designing an army power calculator for matched play (although it could easily be amended with other values). I will likely be making it in Excel eventually with drop down menus to select your army however to start you will have to input your units manually.

What I would like help with is the actual calculations, so any input is welcome on how different things should be weighted and so on. This is what i have so far:

Battleplan Factor(BF). Uses all six battleplans to consider relative power for each

Mortal Wounds(MW). Average output from army in one turn including spells and abilities etc.

Average Damage(AD). Average normal output from army in one turn not calculating melee for ranged units incorporating rend.

Resilience®. Total wounds combined with save, so a 3 wound model with 4+ save is equal to 6 wounds. Include bonus for healing spells and abilities.

Points(P). The division by points and subsequent multiply by 2000 is to account for armies with reinforcement and leftover points which can't be calculated for obvious reason. So this evens their power out with differently pointed armies.

Explanation:

The three main factors for a lists power seem to be average damage, mortal wounds and ability not to die. Everything else seems to be more Battleplan related. This can all be calculated to a fairly normal value ~200-300 for 2000 points I think. This can then be multiplied by the Battleplan factor to consider total proficiency.

I think the Battleplan factors are the most subjective part of the calculator so anyone with matched play experience please feel free to add your input on what you think are the top three things that influence winning each Battleplan, I have put my own initial thoughts below in priority order:

Battleplan factors(need weighting):

1. top two unit offensive ability, top two defensive ability, Model count.

2. top three speed units, offensive ability, reinforcement points.

3. Total Battleline points, Battleline offensive ability,

4. Model count, defensive ability, reinforcement points

5. Top three heroes defensive ability, number of monster heroes.

6. Average speed, reinforcement points, total drops(consider battalions)

Notes:

If unit has teleport style ability or deployment rule use speed value as 20"

##### Share on other sites

I've actually been developing a calculator of unit effectiveness in PHP since it is too complex to fiddle with in Excel at this point given all the abilities out there.  The other challenge is assigning an appropriate weight to the offensive and defensive figures.  I'll post some stuff up a bit later on.

##### Share on other sites

So this block gets the total damage of a unit as tested against armor saves 3+,4+,5+, and 6+ and creates an average.  It considers base size a factor where a 10" frontage can only be occupied by so many models and the range of the weapon will factor in.  Additionally it calculates bonus attacks, bonus mortal wounds, and conversion to mortal wounds in addition to considering bonuses to those rolls increasing the odds of occurrence.

I also have a section that calculates a models durability based on a calculation (total unit wounds * 1/2 damage abilities * FNP * armor plus rend guard) to determine the total number of wounds that have to be rolled to kill them - testing against rend 0, -1, and -2.

I want to add bravery as a factor of durability.  Something like minimum number of wounds (as determined by durability) needed to force a 1/6 chance of losing a model.

Once I get all the final pieces sorted (ranged stuff, too) i'll convert this to a class and eventually if I can get a good database of units and weapons you could potentially pick an army plus battalions and get a number spit out.

```<?php

\$unitA = array (
'unitCount'=>10,
'baseSize'=>32,
'weapons'=>array (
0=>array('attacks'=>2,'range'=>1,'toHit'=>3,'toWound'=>3,'rend'=>1,'chargeRend'=>FALSE,'damage'=>1,'chargeDamage'=>FALSE,'hitAttack'=>6,'hitMortal'=>FALSE,'woundAttack'=>FALSE,'woundMortal'=>FALSE,'hitConvert'=>FALSE,'woundConvert'=>FALSE,'multiplyHits'=>FALSE,'multiplyWounds'=>FALSE),
1=>array('attacks'=>1,'range'=>1,'toHit'=>5,'toWound'=>4,'rend'=>0,'chargeRend'=>FALSE,'damage'=>1,'chargeDamage'=>FALSE,'hitAttack'=>FALSE,'hitMortal'=>FALSE,'woundAttack'=>FALSE,'woundMortal'=>FALSE,'hitConvert'=>FALSE,'woundConvert'=>FALSE,'multiplyHits'=>FALSE,'multiplyWounds'=>FALSE)
),
'weaponsChamp'=>array (
0=>array('attacks'=>3,'range'=>1,'toHit'=>3,'toWound'=>3,'rend'=>1,'chargeRend'=>FALSE,'damage'=>1,'chargeDamage'=>FALSE,'hitAttack'=>6,'hitMortal'=>FALSE,'woundAttack'=>FALSE,'woundMortal'=>FALSE,'hitConvert'=>FALSE,'woundConvert'=>FALSE,'multiplyHits'=>FALSE,'multiplyWounds'=>FALSE),
1=>array('attacks'=>1,'range'=>1,'toHit'=>5,'toWound'=>4,'rend'=>0,'chargeRend'=>FALSE,'damage'=>1,'chargeDamage'=>FALSE,'hitAttack'=>FALSE,'hitMortal'=>FALSE,'woundAttack'=>FALSE,'woundMortal'=>FALSE,'hitConvert'=>FALSE,'woundConvert'=>FALSE,'multiplyHits'=>FALSE,'multiplyWounds'=>FALSE)
),
'rerollHit'=>0,
'plusHit'=>0,
'rerollWound'=>0,
'plusWound'=>0,

'wounds'=>1,
'save'=>4,
'rerollSave'=>0,
'plusSave'=>1,
'ignoreRend'=>1,
'mysticShield'=>0,

'move'=>5,
'bravery'=>10
);
/*
\$unitB  = array (
'wounds'=>1,
'save'=>4,
'rerollSave'=>0,
'ignoreRend'=>0,
'mysticShield'=>0
);
*/

\$opposingArmor = array(3,4,5,6);

function calculateOffense (\$unitA,\$opposingArmor) {

\$totalDamage = 0;

foreach (\$unitA['weapons'] as \$key=>\$weaponValues) {

\$toHit = ((7 - \$weaponValues['toHit'] + \$unitA['plusHit'])/6) + (\$unitA['rerollHit']/6 * ((7 - \$weaponValues['toHit'] + \$unitA['plusHit'])/6));
\$toWound = ((7 - \$weaponValues['toWound'] + \$unitA['plusWound'])/6) + (\$unitA['rerollWound']/6 * ((7 - \$weaponValues['toWound'] + \$unitA['plusWound'])/6));
//restrict attacks based on size - also remove champ

\$maxInCombat = 0;
if (\$weaponValues['range'] == 1) {
if (\$unitA['baseSize'] == 25) {
\$maxInCombat = (21 - 1);
} elseif (\$unitA['baseSize'] == 32) {
\$maxInCombat = (11 - 1);
}
} elseif (\$weaponValues['range'] == 2) {
if (\$unitA['baseSize'] == 25) {
\$maxInCombat = (31 - 1);
} elseif (\$unitA['baseSize'] == 32) {
\$maxInCombat = (17 - 1);
}
} elseif (\$weaponValues['range'] == 3) {
if (\$unitA['baseSize'] == 25) {
\$maxInCombat = (42 - 1);
} elseif (\$unitA['baseSize'] == 32) {
\$maxInCombat = (22 - 1);
}
}

\$unitA['unitCount'] > \$maxInCombat ? \$attacks = \$maxInCombat * \$weaponValues['attacks'] : \$attacks = (\$unitA['unitCount'] - 1) * \$weaponValues['attacks'];

foreach (\$opposingArmor as \$save) {
\$step1 = 0;

//isset(\$weaponValues['chargeRend']) ? \$rend = \$weaponValues['chargeRend'] : \$rend = \$weaponValues['rend'];
//isset(\$weaponValues['chargeDamage']) ? \$damage = \$weaponValues['chargeDamage'] : \$damage = \$weaponValues['damage'];
\$rend = \$weaponValues['rend'];
//Can't rend into negative armor
if ((7 - \$save - \$rend) < 0) {
\$penetration = 1;
} else {
\$penetration = 1 - ((7 - \$save - \$rend)/6);
}

//successful attacks plus bonus attacks, bonus mortal, and conversion to mortal -- convert happens after all bonuses
\$step1 = \$attacks * \$toHit;

!\$weaponValues['hitAttack'] ? \$bonusAttacks = 0 : \$bonusAttacks = \$step1 * ((7 - \$weaponValues['hitAttack'] + \$unitA['plusHit'])/6);
\$step1 += \$bonusAttacks;
!\$weaponValues['multiplyHits'] ? \$step1 = \$step1 : \$step1 = \$step1 * \$weaponValues['multiplyHits'];
!\$weaponValues['hitMortal'] ? \$bonusMortal = 0 : \$bonusMortal = \$step1 * ((7 - \$weaponValues['hitAttack'] + \$unitA['plusHit'])/6);
!\$weaponValues['hitConvert'] ? \$covertMortal = 0 : \$covertMortal = \$step1 * ((7 - \$weaponValues['hitConvert'] + \$unitA['plusHit'])/6);
\$step1 = \$step1 - \$covertMortal;

//successful wounds plus bonus wounds, bonus mortal, and conversion to mortal -- convert happens after all bonuses
\$step2 = \$step1 * \$toWound;
!\$weaponValues['woundAttack'] ? \$bonusWounds = 0 : \$bonusWounds = \$step1 * ((7 - \$weaponValues['woundAttack'] + \$unitA['plusWound'])/6);
\$step2 += \$bonusWounds;
!\$weaponValues['multiplyWounds'] ? \$step1 = \$step1 : \$step1 = \$step1 * \$weaponValues['multiplyWounds'];
!\$weaponValues['woundMortal'] ? \$bonusMortal = 0 : \$bonusMortal = \$step1 * ((7 - \$weaponValues['woundAttack'] + \$unitA['plusWound'])/6);
!\$weaponValues['woundConvert'] ? \$covertMortal = 0 : \$covertMortal = \$step1 * ((7 - \$weaponValues['woundConvert'] + \$unitA['plusWound'])/6);
\$step2 = \$step2 - \$covertMortal;

//sum total damage plus mortal wounds caused
\$totalDamage += \$step2 * \$penetration * \$weaponValues['damage'];
\$totalDamage += (\$bonusMortal * \$weaponValues['damage']) + (\$covertMortal * \$weaponValues['damage']);

}

}

foreach (\$unitA['weaponsChamp'] as \$key=>\$weaponValues) {

\$toHit = ((7 - \$weaponValues['toHit'] + \$unitA['plusHit'])/6) + (\$unitA['rerollHit']/6 * ((7 - \$weaponValues['toHit'] + \$unitA['plusHit'])/6));
\$toWound = ((7 - \$weaponValues['toWound'] + \$unitA['plusWound'])/6) + (\$unitA['rerollWound']/6 * ((7 - \$weaponValues['toWound'] + \$unitA['plusWound'])/6));
\$attacks = \$weaponValues['attacks'];

foreach (\$opposingArmor as \$save) {
\$step1 = 0;

//isset(\$weaponValues['chargeRend']) ? \$rend = \$weaponValues['chargeRend'] : \$rend = \$weaponValues['rend'];
//isset(\$weaponValues['chargeDamage']) ? \$damage = \$weaponValues['chargeDamage'] : \$damage = \$weaponValues['damage'];
\$rend = \$weaponValues['rend'];
//Can't rend into negative armor
if ((7 - \$save - \$rend) < 0) {
\$penetration = 1;
} else {
\$penetration = 1 - ((7 - \$save - \$rend)/6);
}

//successful attacks plus bonus attacks, bonus mortal, and conversion to mortal -- convert happens after all bonuses
\$step1 = \$attacks * \$toHit;

!\$weaponValues['hitAttack'] ? \$bonusAttacks = 0 : \$bonusAttacks = \$step1 * ((7 - \$weaponValues['hitAttack'] + \$unitA['plusHit'])/6);
\$step1 += \$bonusAttacks;
!\$weaponValues['multiplyHits'] ? \$step1 = \$step1 : \$step1 = \$step1 * \$weaponValues['multiplyHits'];
!\$weaponValues['hitMortal'] ? \$bonusMortal = 0 : \$bonusMortal = \$step1 * ((7 - \$weaponValues['hitAttack'] + \$unitA['plusHit'])/6);
!\$weaponValues['hitConvert'] ? \$covertMortal = 0 : \$covertMortal = \$step1 * ((7 - \$weaponValues['hitConvert'] + \$unitA['plusHit'])/6);
\$step1 = \$step1 - \$covertMortal;

//successful wounds plus bonus wounds, bonus mortal, and conversion to mortal -- convert happens after all bonuses
\$step2 = \$step1 * \$toWound;
!\$weaponValues['woundAttack'] ? \$bonusWounds = 0 : \$bonusWounds = \$step1 * ((7 - \$weaponValues['woundAttack'] + \$unitA['plusWound'])/6);
\$step2 += \$bonusWounds;
!\$weaponValues['multiplyWounds'] ? \$step1 = \$step1 : \$step1 = \$step1 * \$weaponValues['multiplyWounds'];
!\$weaponValues['woundMortal'] ? \$bonusMortal = 0 : \$bonusMortal = \$step1 * ((7 - \$weaponValues['woundAttack'] + \$unitA['plusWound'])/6);
!\$weaponValues['woundConvert'] ? \$covertMortal = 0 : \$covertMortal = \$step1 * ((7 - \$weaponValues['woundConvert'] + \$unitA['plusWound'])/6);
\$step2 = \$step2 - \$covertMortal;

//sum total damage plus mortal wounds caused
\$totalDamage += \$step2 * \$penetration * \$weaponValues['damage'];
\$totalDamage += (\$bonusMortal * \$weaponValues['damage']) + (\$covertMortal * \$weaponValues['damage']);

}

}

return ROUND(\$totalDamage / 4,1);
}

echo calculateOffense(\$unitA,\$opposingArmor);```

##### Share on other sites

I still need to validate all the results, but here are some test values...

Saurus Guard w/ +1 save from hero :

Offense Index:  6
Defense Index:  43.33
MW Index:       0
Bravery Index:  100% (You have to kill 100% of a min-sized unit to cause a test -- this can go above 100% with bravery mods)

plus scar-vet and Fire Lance --

Offense Index:  16.74
Defense Index:  43.33
MW Index:       4.48
Bravery Index:  100%

plus mystic shield and reroll saves --

Offense Index:  16.74
Defense Index:  160
MW Index:       4.48
Bravery Index:  100%

And for comparison some Chosen with daemonic power:

Offense Index:  11.36
Defense Index:  94
MW Index:       3.11
Bravery Index:  60%

And IJ Brutes:

Offense Index:  14.66
Defense Index:  94
MW Index:       0
Bravery Index:  20%

##### Share on other sites

Looks interesting! A lot more complex than what I was aiming for. Certainly look forward to seeing it when you've finished.

##### Share on other sites

Yea I got a little carried away! Does anyone know if the SCGT has a database of warscrolls?  If I could find one to poach it'd make things a bit easier.

##### Share on other sites

I thought that I thought about warhammer too much... ##### Share on other sites

• 4 weeks later...      These are the first factions I have completed for my calculator. Hopefully it matches up with how units perform in practice.

##### Share on other sites

Ive actually been work8ng on something similar to this 9n Excel for a while. Mine is geared towards the relative power of a unit, scoring their damage output, wound absorbtuon, etc.

Definitely would love to collaborate!