Battle System

*Note: these formulas are pulled from the source code for the js version of larn running at larn.org. ularn/xlarn/other variants might have different formulas*

## Monster Attacks Player

When a monster attacks a player, there is a process to determine what happens next:

1. Check Protections
2. Determine Bias
3. Check Invisible & Charm
4. Damage Calculation
5. Special Attack Calculation
6. Attack Roll
7. Damage Application

#### **Check Protections**

```
/\* in player.js, when picking up an item, set player passives \*/
if (item.matches(OSPIRITSCARAB))
 pickup ? player.NEGATESPIRIT++ : player.NEGATESPIRIT--;
if (item.matches(OCUBEofUNDEAD))
 pickup ? player.CUBEofUNDEAD++ : player.CUBEofUNDEAD--;

/\* spirit naga's and poltergeist's do nothing if scarab of negate spirit \*/
if (player.NEGATESPIRIT || player.SPIRITPRO) {
 if (monster.matches(POLTERGEIST) || monster.matches(SPIRITNAGA)) return;
}

/\* if undead and cube of undead control \*/
if (player.CUBEofUNDEAD || player.UNDEADPRO) {
 return;
}

```
**Explanation**

* If the player is holding a scarab of negate spirit or currently has spirit protection scroll active, they are immune to attacks from poltergeist and spirit naga
* If the player is holding a cube of undead control or currently has undead protection scroll active, they are immune to attacks from vampire, wraith, and zombie
* If any of the above options are true, the entire damage application process is cancelled

#### **Determine Bias**

```
var bias = getDifficulty() + 1;

```
**Explanation**

* The bias factor is set as the game difficulty +1
	+ *Example: if the game difficulty is 0, then the bias is equal to 1*
* This bias factor will be relevant when monster rolls for attack. Generally the higher the bias factor, the more likely you are to be hit by monster attacks

#### **Check Invisible & Charm**

```
if ((player.INVISIBILITY > 0) && (rnd(33) < 20)) {
 updateLog(`The ${monster} misses wildly`);
 return;
}
if ((player.CHARMCOUNT > 0) && (rnd(30) + 5 \* monster.level - player.CHARISMA < 30)) {
 updateLog(`The ${monster} is awestruck at your magnificence!`);
 return;
}

```
**Explanation**

* If player is invisible, the monster has a 19 in 33 (57.57%) chance of missing, otherwise they land the hit
* If player uses the charm monster spell, the monster has a variable chance of being charmed and missing, based on monster level and player charisma level
	+ *Example: If monster level is 3 and player charisma is 12 and the charm spell is active, the monster has a rnd(30) + 3 < 30 (90.90%) chance of missing*

#### **Damage Calculation**

When struck by a monster, the following formula is used to determine **how much damage is taken**

```
var dam;
if (monster.matches(BAT)) {
 dam = 1;
} else {
 dam = monster.damage;
 dam += rnd(((dam < 1) ? 1 : dam)) + monster.level;
}

if ((dam -= player.AC) < 0) dam = 0;
 if (dam > 0) {
 player.losehp(dam);
}

```
**Explanation**

* If the attacking monster is a bat, damage is always 1
* Otherwise, calculated damage is set as monster base damage + monster level + random number between 1 and monster damage
	+ *Example: if monster base damage is 2 and monster level is 1, then calculated damage could be between 4 and 5 inclusively*
* If calculated damage - player AC is less than 0, no damage is taken
	+ *Example: If monster damage is 3 and player AC is 3, no damage is taken\*
* Otherwise, player loses HP equal to calculated damage

#### **Special Attack Calculation**

```
if (monster.attack > 0)
 if (((dam + bias + 8) > player.AC) || (rnd(((player.AC > 0) ? player.AC : 1)) == 1)) {
 if (spattack(monster.attack, x, y)) {
 // spattack returns 1 if the monster disappears (theft)
 return;
 }
 playerHit = true;
 bias -= 2;
 //cursors();
 }

```
**Explanation**

* This is only calculated if the monster has a special attack, signified by ATT > 0 (see table in Monsters)
* The special attack will land if either of these conditions is met:
	1. calculated damage + bias + 8 is greater than player AC
		+ *Example: If bias is 1 (game difficulty is 0) and calculated damage is 4, the player must have an armor class of 13 or higher to avoid this condition*
	2. The generated random number between 1 and player AC is equal to 1
		1. *Example: If player AC is 12, there is a 1 in 12 chance of this condition being met, therefore, the higher your AC, the less likely it is for special attacks to land*
		2. *Also Note: if player AC is 0, there is a 100% chance that special attacks will land*
* If the special attack was a theft, the monster will disappear without applying damage
* Otherwise, the bias will be decreased by 2, and an attack roll will be performed.

#### **Attack Roll**

When struck by a monster, the following formula is used to determine **whether the attack is hit or missed:**

```
((dam + bias) > player.AC) || (rnd(((player.AC > 0) ? player.AC: 1)) == 1)

```

**Explanation**

* If calculated damage + bias is higher than player AC (armor class), the hit lands
	+ *Example: if calculated damage is 3 and bias is 1, player must have armor class of 4 or higher for monster to miss*
* A random number is generated using a range of 1 - player AC. If the random number is equal to 1, or if the player's AC is 0, the hit lands
	+ *Example: if player AC is 3, they have a one in 3 chance of being hit*

**Observations on hit-or-miss formula**

* The addition of bias to the hit-or-miss formula means that a player's AC must always be higher than the attacking monster's calculated damage in order for the attack to miss. The amount of required AC for an attack to miss depends on difficulty level (at difficulty 0, you only need calculated damage `+ 1` AC)
* Even if player armor class is greater than calculated damage + bias, you still have a one-in-AC chance of being hit
* When player AC is 0, all attacks to the player will hit

#### **Damage Application**

When struck by a monster, the following formula is used to determine **how much damage is taken**

```
if ((dam -= player.AC) < 0) dam = 0;
 if (dam > 0) {
 player.losehp(dam);
}

```
**Explanation**

* If calculated damage `- player AC` is less than 0, no damage is taken
	+ *Example: If calculated damage is 3 and player AC is 3, no damage is taken*
* Otherwise, player loses HP equal to calculated damage

### **References**

1. ↑ https://github.com/primeau/Larn/blob/c57403cc6d8bc911246ad62729872365f9f8c0da/monster.js