Witchaven game mechanics

Here are some in-depth looks at how certain aspects of the game behave. I have tried my best to document the game's behavior accurately, but be aware that in some cases I may have misinterpreted the game's source code, or strange bugs in the behavior may manifest that I haven't caught yet.

Leveling up [top]

Grondoval gains experience both by killing enemies (or having them meet an "accident" at the hands of other monsters or the environment) and by collecting treasures. For every level he gains, his attack power and maximum health are increased. The duration of scare, night vision and fly spells is also lengthened.

In Witchaven I, experience level had a greater part to play in the game; certain spells and dual wielding attacks required reaching a certain experience level first. It was also possible to be level drained by the Willow Wisp.

Although it is not too hard to attain max level in Witchaven II, in the original game it generally requires full use of the Glass Skull artifacts, and avoiding death/level drains.

Level Experience New ability
1st 0
2nd 2,250 Freeze spell, Magic Arrow spell
3rd 4,500 Fly spell, Open Doors spell
4th 9,000 Fireball spell, dual wield broad sword + dagger
5th 18,000 Nuke spell, dual wield broad sword + morning star
6th 36,000
7th 75,000
8th 180,000
9th / Hero 280,000

Witchaven II added named experience levels, but compared to the first game, the table is rather "flat" with every level coming at 10,000 point intervals. The maximum level cap is also lower (reasonable, I suppose, given that there were fewer dungeons as well.) Level requirements for spells and attacks were dropped, most likely because these abilities are assumed to be carried over from the previous adventure.

Level Experience
Veteran 0
Warrior 10,000
Swordsman 20,000
Hero 30,000
Champion 40,000
Superhero 50,000
Lord 60,000

Enemy HP randomizer [top]

When a level is set up, the HP of every enemy is randomized as follows:

First, a base HP is chosen for the monster depending on its type.

Then, a random percent value is rolled up. This can be from 0 to 19 percent.

Flip a coin.
If heads, the monster's HP will be added to by that percent of the base HP.
If tails, the monster's HP will be subtracted from by that percent of the base HP.

In both cases, the result is multiplied by the difficulty level before being finalized. This means that monsters have approximately their base HP on easy, double on medium, triple on hard and quadruple on very hard.

The final value is rounded to an integer.

This takes place in the adjusthp function in WHAVEN.C; setupboard, also in WHAVEN.C, calls the function and provides the base HP values.

End of level rating [top]

Witchaven II added a mechanic where you are rated on your performance in a level upon reaching the end of it. The better your rating, the more bonus XP you can be awarded. During the intermission, the game calculates percent of kills and percent of treasures collected. It then takes the mean of the two percentages and uses it to determine a rating as follows:

Rating Min. score XP Bonus
Poor 0% None
Average 40% 500
Good 70% 1,000
Perfect 95% 1,500

The "perfect" label is, as you can see, a bit of a misnomer. You needn't actually achieve a perfect score to be rated "perfect", only get close enough.

It is also worth noting that some of the items that count toward the item score cannot be collected if you are at the maximum (potions and spells, for example). Using these items liberally, and sometimes even wasting them, may become necessary to achieve a good item collection rating.

Armor, shields and the Adamantine Ring [top]

The effects of armor are calculated in the code that handles melee attacks. As far as I can tell, armor and shields don't have any effect against projectile attacks. When a monster lands a melee attack, quite a bit goes on in the code, and protection is calculated in several layers. For those that want to read along, these calculations take place in the attack function of WHOBJ.C.

First, if the player has the Adamantine Ring (which, once collected, is lost only upon death), there is a 50% chance that the attack will be negated by it.

Using a shield adds further protection, with about a 20% chance of blocking an attack if the shield is being held (Witchaven II requires a blow to come from the front to be blocked, but Witchaven I doesn't). An oddity is that fists are considered a "shield up" weapon, even though the shield graphic isn't displayed with them. If the blow is successfully deflected here, the shield will not be damaged.

If the shield fails in its attempt to completely block the blow, it is damaged by 2 shield points in Witchaven I, or a random amount from 0 to 49 in Witchaven II. However, in Witchaven II, a bug results in the damage being added to shield points rather than subtracted, rendering shields essentially indestructible.

In Witchaven I only, there is a chance for armor to reduce a monster's base damage before the rest of the attack is calculated. The chance is x in 100 where x is 8 for leather, 16 for chain, and 24 for plate. If successful, the base value drops from 15 to 5, which then undergoes further calculations depending on monster type (some monsters ignore the value set here.)

Once the monster's attack damage is calculated, there's a check to see if the player has any shield points left. In Witchaven I, this simply halves melee damage whenever the player has a shield, even if using a two-handed weapon. In Witchaven II, the additional protection happens only if the shield was damaged by a blow earlier. The random amount of damage that was taken by the shield is subtracted from the monster's attack damage.

Finally, body armor gets a chance to absorb some of the damage. Armor type is usually determined by which suit of armor the player picked up previously, but certain special items also alter what type of armor the player's armor points are treated as. The two games calculate armor protection differently.

In Witchaven I:
Leather halves damage taken, and loses 4 armor points when hit.
Chain quarters damage taken, and loses 2 armor points when hit.
Plate quarters damage taken, loses 1 armor point when hit, and has a 50% chance to prevent all HP loss. (50% may not be what the programmers intended, however it is what the code will probably do.)

In Witchaven II:
A random value is calculated depending on armor type, and the armor receives that much damage, while any remaining damage is done to HP. The random range is 0-4 for leather, 0-9 for chain, and 0-19 for plate.

Some conditions in the armor check code do not work properly.
Immediately after the Adamantine ring check, there is supposed to be an x in 15 chance that the monster's attack will miss. x has a base value of 10, and receives +1 if wearing leather armor, +2 for chain and +3 for plate. However, the condition never triggers due to C's order of operations (to fix it, the krand()&15 call should be enclosed in its own set of parentheses). Here's the bit of the source:
if(krand()&15 < plr->armortype+10 )

The Onyx Ring was apparently also meant to be a protective item, but due to incomplete coding, does not function.

Treasure chests [top]

The process for determining what's inside a treasure chest isn't that complicated, but it is a bit long due to the number of options that can occur.

First, a random roll of 0-6 is made, which breaks the options up into categories like so:

0: Random potion. Makes a second roll, from 0-4:

  • 0: Health Potion
  • 1: Strength Potion
  • 2: Cure Poison Potion
  • 3: Resist Fire Potion
  • 4: Invisibility Potion

1: Random spell. ONE charge is added to the spell, even in Witchaven II. Makes a second roll, from 0-7:

  • 0: Scare Scroll
  • 1: Night Vision Scroll
  • 2: Freeze Scroll
  • 3: Magic Arrow Scroll
  • 4: Open Door Scroll
  • 5: Fly Scroll
  • 6: Fireball Scroll
  • 7: Nuke Scroll

2: You get treasure worth a random amount from 100-499 XP.

3: Random weapon. Makes a second roll, from 1-5:

  • 1: Dagger
  • 2: Morning Star
  • 3: Short Sword
  • 4: Battle Axe
  • 5: Pike Axe

4: Random armor. Due to a bug, always gives Hero Time, but is supposed to make a second roll from 0-3:

  • 0: Hero Time helmet
  • 1: Plate Armor
  • 2: Chain Mail
  • 3: Leather Armor

5: Supposed to give a 50-50 chance of either a poison trap or treasure worth a random amount from 100-500 XP. Due to bugs, always chooses treasure and some values in the range may be impossible (though it will never pick a value outside the range.)

6: The chest explodes. Fire resistance will protect you from injury.

Technically, chests are never truly "empty". When you get an empty chest, it's because the item it chose to give you was something you weren't able to collect (due to already having the maximum of a potion or spell, for instance.) Therefore, when collecting chests it's generally to your benefit not to carry the maximum of anything when you can help it.