Index: src/armour.c
===================================================================
--- src/armour.c	(revision 0)
+++ src/armour.c	(revision 0)
@@ -0,0 +1,39 @@
+/*
+	This file is part of Warzone 2100.
+	Copyright (C) 1999-2004  Eidos Interactive
+	Copyright (C) 2005-2007  Warzone Resurrection Project
+
+	Warzone 2100 is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	Warzone 2100 is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with Warzone 2100; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "armour.h"
+
+float armour_damage_reduction;
+float armour_table[MAX_ARMOUR];
+
+void armour_table_init()
+{
+	unsigned int	i;
+
+	// 1.5% per point
+	armour_damage_reduction = 0.985f;
+	armour_table[0] = 1.0f;
+	armour_table[1] = armour_damage_reduction;
+
+	for (i = 2;i < MAX_ARMOUR;i++)
+	{
+		armour_table[i] = armour_table[i-1] * armour_damage_reduction;
+	}
+}
Index: src/armour.h
===================================================================
--- src/armour.h	(revision 0)
+++ src/armour.h	(revision 0)
@@ -0,0 +1,32 @@
+/*
+	This file is part of Warzone 2100.
+	Copyright (C) 1999-2004  Eidos Interactive
+	Copyright (C) 2005-2007  Warzone Resurrection Project
+
+	Warzone 2100 is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	Warzone 2100 is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with Warzone 2100; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#ifndef _armour_h
+#define _armour_h
+
+// 1000 starting index 1
+#define MAX_ARMOUR 1001
+
+extern float armour_damage_reduction;
+
+extern float armour_table[MAX_ARMOUR];
+
+extern void armour_table_init(void);
+
+#endif
Index: src/droid.c
===================================================================
--- src/droid.c	(revision 2418)
+++ src/droid.c	(working copy)
@@ -84,6 +84,7 @@
 // FIXME Direct iVis implementation include!
 #include "lib/ivis_opengl/screen.h"
 #include "scriptfuncs.h"			//for ThreatInRange()
+#include "armour.h"					//for armour table
 
 
 #define DEFAULT_RECOIL_TIME	(GAME_TICKS_PER_SEC/4)
@@ -155,7 +156,7 @@
 SDWORD droidDamage(DROID *psDroid, UDWORD damage, UDWORD weaponClass, UDWORD weaponSubClass, DROID_HIT_SIDE impactSide)
 {
 	// Do at least one point of damage
-	unsigned int actualDamage = 1, armour;
+	unsigned int actualDamage, armour, level;
 	float        originalBody = psDroid->originalBody;
 	float        body = psDroid->body;
 	SECONDARY_STATE		state;
@@ -209,26 +210,23 @@
 
 	clustObjectAttacked((BASE_OBJECT *)psDroid);
 
-	// If the shell penetrated the armour work out how much damage it actually did
-	if (damage > armour)
-	{
-		unsigned int level;
+	actualDamage = damage * armour_table[armour];
 
-		actualDamage = damage - armour;
+	// Retrieve highest, applicable, experience level
+	level = getDroidLevel(psDroid);
+	level = MAX(level, cmdGetCommanderLevel(psDroid));
 
-		// Retrieve highest, applicable, experience level
-		level = getDroidLevel(psDroid);
-		{
-			unsigned int cmdLevel = cmdGetCommanderLevel(psDroid);
-			level = MAX(level, cmdLevel);
-		}
+	// Reduce damage taken by EXP_REDUCE_DAMAGE % for each experience level
+	actualDamage = (actualDamage * (100 - EXP_REDUCE_DAMAGE * level)) / 100;
 
-		// Reduce damage taken by EXP_REDUCE_DAMAGE % for each experience level
-		actualDamage = (actualDamage * (100 - EXP_REDUCE_DAMAGE * level)) / 100;
-
-		debug( LOG_ATTACK, "        penetrated: %d\n", actualDamage);
+	// minimum damage 1?
+	if (actualDamage == 0)
+	{
+		actualDamage = 1;
 	}
 
+	debug( LOG_ATTACK, "        damaged: %d\n", actualDamage);
+
 	// If the shell did sufficient damage to destroy the droid, deal with it and return
 	if (actualDamage >= psDroid->body)
 	{
Index: src/feature.c
===================================================================
--- src/feature.c	(revision 2418)
+++ src/feature.c	(working copy)
@@ -58,8 +58,10 @@
 #include "display3d.h"
 #include "gateway.h"
 
+#include "armour.h"					//for armour table
 
 
+
 /* The statistics for the features */
 FEATURE_STATS	*asFeatureStats;
 UDWORD			numFeatureStats;
@@ -268,7 +270,7 @@
 SDWORD featureDamage(FEATURE *psFeature, UDWORD damage, UDWORD weaponSubClass)
 {
 	// Do at least one point of damage
-	unsigned int actualDamage = 1;
+	unsigned int actualDamage;
 	float		body = (float) psFeature->body;
 	float		originalBody = (float) psFeature->psStats->body;
 
@@ -284,11 +286,13 @@
 		return 0;
 	}
 
-	if (damage > psFeature->psStats->armour)
+	// Damage has penetrated - reduce body points
+	actualDamage = damage * armour_table[psFeature->psStats->armour];
+	debug( LOG_ATTACK, "        penetrated: %d\n", actualDamage);
+
+	if (actualDamage == 0)
 	{
-		// Damage has penetrated - reduce body points
-		actualDamage = damage - psFeature->psStats->armour;
-		debug( LOG_ATTACK, "        penetrated: %d\n", actualDamage);
+		actualDamage = 1;
 	}
 
 	// If the shell did sufficient damage to destroy the feature
Index: src/main.c
===================================================================
--- src/main.c	(revision 2418)
+++ src/main.c	(working copy)
@@ -67,6 +67,8 @@
 #include "winmain.h"
 #include "wrappers.h"
 
+#include "./armour.h"					//to initialise armour table
+
 #ifndef DATADIR
 # define DATADIR "/usr/share/warzone2100/"
 #endif
@@ -847,6 +849,9 @@
 	//set all the pause states to false
 	setAllPauseStates(FALSE);
 
+	// Initialise armour table
+	armour_table_init();
+
 	// Do the game mode specific initialisation.
 	switch(GetGameMode())
 	{
Index: src/structure.c
===================================================================
--- src/structure.c	(revision 2418)
+++ src/structure.c	(working copy)
@@ -89,6 +89,8 @@
 #include "scores.h"
 #include "gateway.h"
 
+#include "armour.h"					//for armour table
+
 #define MODULE_PIES_ENABLED
 
 // Possible types of wall to build
@@ -1312,7 +1314,7 @@
 					UDWORD weaponSubClass)
 {
 	// Do at least one point of damage
-	unsigned int actualDamage = 1;
+	unsigned int actualDamage;
 	float		body = (float) psStructure->body;
 	float		originalBody = (float) psStructure->pStructureType->bodyPoints;
 
@@ -1345,11 +1347,13 @@
 	// Tell the cluster system it has been attacked
 	clustObjectAttacked((BASE_OBJECT *)psStructure);
 
-	if (damage > psStructure->armour)
+	// Damage has penetrated the armour
+	actualDamage = damage * armour_table[psStructure->armour];
+	debug( LOG_ATTACK, "        damaged: %d\n", actualDamage);
+
+	if (actualDamage == 0)
 	{
-		// Damage has penetrated the armour
-		actualDamage = damage - psStructure->armour;
-		debug( LOG_ATTACK, "        penetrated: %d\n", actualDamage);
+		actualDamage = 1;
 	}
 
 	// If the shell did sufficient damage to destroy the structure
