function unitClass(game, player, name, type) {
/*==============================================================================
shipClass
requires: createLayer() function
==============================================================================*/
	this.name = name;
	this.baseName = name.replace(/([^a-zA-Z0-9])/g, "", name);
	this.game = game;
	this.player = player;
	this.type = type;
	this.facing = 3; //left
	this.health = 100;
	this.hitPoints = 10;
	this.typeName = this.game.unitTypes[this.type].name;
	this.moveAndAttack = this.game.unitTypes[this.type].moveAndAttack;
	this.moveAllowance = this.game.unitTypes[this.type].moveAllowance;
	this.weaponMinRange = this.game.unitTypes[this.type].weaponMinRange;
	this.weaponMaxRange = this.game.unitTypes[this.type].weaponMaxRange;
	this.baseDamage = this.game.unitTypes[this.type].baseDamage;
	this.canCapture = this.game.unitTypes[this.type].canCapture;
	this.captureLevel = 0;
	this.hasMoved = false;
	this.state = 0; // 0 = ready
	this.x = 0;
	this.y = 0;
	this.path = new Array();
	this.backupPath = new Array();	

	this.unitLayerObj = createLayer(this.baseName+'Lyr','unitsDiv',0,0,32,32,'',null,null,10);
	this.unitLayerObj.parent = this;
	
	if (this.unitLayerObj.style) { this.unitStyle=this.unitLayerObj.style; } else { this.unitStyle=this.unitLayerObj; };
	this.unitStyle.backgroundImage = 'url("images/'+this.game.player[this.player].colour+'/unit.gif")';
	this.unitStyle.backgroundPosition = (-32*this.type)+'px '+(-32*this.facing)+'px';

	this.unitLayerObj.onmousedown = function() {
		this.parent.unitClicked();
	};
	
	/*---------------------------------------------
		Unit states
		0: Ready
		1: Move Mask Open
		2: Moving
		3: Has moved
		4: Did not move
		5: Attack Mask Open
		6: Firing
		7: Exhausted
	---------------------------------------------*/	
	
	this.setState = function( state ) {
		this.state = state;
		this.displayUnitStatus();
	};
	
	this.unitClicked = function() {
		if (this.player == this.game.activePlayer && !this.game.buildingActive) {
			if (this.state == 0 && this.game.unitActive == false) { // Ready
				this.game.unitActive = true;
				this.updateUnitDisplay(true);
				this.createMoveMask();
				this.displayUnitStatus();
			} else if (this.state == 1) { // Move Mask Open
				this.finishMove(false);
			} else if (this.state == 3) { // Has moved
				this.exhaust();
			} else if (this.state == 5) { // Attack Mask Open
				if(this.mask) this.destroyMask();
				this.exhaust();
			};
		};
	};
	
	this.unitUndo = function() {
		if (this.state == 1) { // Move Mask Open
			// Close move mask, reset unit to ready;
			this.game.unitActive = false;
			this.updateUnitDisplay(false);
			this.destroyMask();
			this.setState(0); 
			return false;
		} else if (this.state == 3 || this.state == 5) { // Has moved or Attack Mask Open
			this.destroyMask();
			this.rewindPath();
		};
	};
	
	this.createMoveMask = function() {
		this.setState(1); // Move Mask Open
		this.mask = new moveMaskClass(this);
	};
	
	this.createAttackMask = function() {
		this.setState(5); // Attack Mask Open
		this.mask = new attackMaskClass(this);
	};
	
	this.destroyMask = function() {
		if (this.mask) {
			this.mask.destroyNodes();
			delete this.mask;
		};
	};

	this.setFacing = function( newFacing ) {  
		this.facing = newFacing;
		this.unitStyle.backgroundPosition = (-32*this.type)+'px '+(-32*this.facing)+'px';
	};
	
	this.setPosition = function( newX, newY ) {  
		this.x = newX;
		this.y = newY;
		this.unitStyle.left = newX*32+"px";
		this.unitStyle.top = newY*32+"px";
	};
	
	this.setHealth = function( newHealth ) {  
		this.health = newHealth;
		this.hitPoints = Math.round(this.health/10);
		if (this.health > 0 && this.hitPoints == 0) this.hitPoints = 1;
		this.updateUnitDisplay(false);
	};
	
	this.updateUnitDisplay = function(active) {
		var tmpStr = '';
		if (active) tmpStr = '<img src="images/active.gif" width="32" height="32" border="0">';
		if (this.hitPoints < 10) tmpStr += '<div class="unitHealth">' + this.hitPoints + '</div>';
		if (this.captureLevel) tmpStr += '<div class="unitCapture'+this.game.player[this.player].colour+'"></div>';
		this.unitLayerObj.innerHTML = tmpStr;
	};
	
	this.exhaust = function() {
		// Code to write move to server
		// Write move
		// Write action: wait, attack(who, damage), capture
		if (this.hasMoved) this.captureLevel = 0; // Has moved
		this.backupPath = new Array();
		this.setState(7); // Exhausted 
		this.destroyMask();
		this.game.unitActive = false;
		this.updateUnitDisplay(false);
		this.unitStyle.backgroundImage='url("images/'+this.game.player[this.player].colour+'/exhausted.gif")';
	};

	this.ready = function() { 
		this.setState(0); // Ready 
		this.destroyMask();
		this.backupPath = new Array();
		this.hasMoved = false;
		this.updateUnitDisplay(false);
		this.unitStyle.backgroundImage='url("images/'+this.game.player[this.player].colour+'/unit.gif")';
	};
	
	this.damage = function( damage ) {
		var newHealth = this.health - damage;
		if (newHealth <= 0) { 
			this.destroy(); 
			return true;
		} else {
			this.setHealth(newHealth);
			return false;
		}
	};
	
	this.destroy = function() {
		destroyLayer(this.baseName+'Lyr','unitsDiv');
		for (var i=0; i<this.game.player[this.player].units.length; i++) {
			if (this.game.player[this.player].units[i] == this) this.game.player[this.player].units.splice(i,1);
		};
	};
	
	this.attack = function( unitToAttack, distanceToTarget ) {
		// calculate damage
		var unitToAttackDefense = this.game.mapTypes[this.game.mapArray[unitToAttack.y][unitToAttack.x]].defense;
		// Go through buildings to see if the unit is on one 
		for (var i=0; i<this.game.building.length; i++) {
			if (this.game.building[i].x == unitToAttack.x && this.game.building[i].y == unitToAttack.y) { 
				unitToAttackDefense = this.game.buildingTypes[this.game.building[i].type].defense;
				break; 
			}
		};
		
		var damage = this.baseDamage[unitToAttack.type] * (this.hitPoints/10) * (1-(unitToAttackDefense * unitToAttack.hitPoints/100));
		var destroyed = unitToAttack.damage(damage);
		// Counter attack
		if (distanceToTarget == 1 && unitToAttack.weaponMinRange == 1 && !destroyed) {
			unitToAttackDefense = this.game.mapTypes[this.game.mapArray[this.y][this.x]].defense;
			// Go through buildings to see if the unit is on one 
			for (var i=0; i<this.game.building.length; i++) {
				if (this.game.building[i].x == this.x && this.game.building[i].y == this.y) { 
					unitToAttackDefense = this.game.buildingTypes[this.game.building[i].type].defense;
					break; 
				}
			};
			damage = unitToAttack.baseDamage[this.type] * (unitToAttack.hitPoints/ 10) * (1-(unitToAttackDefense * this.hitPoints/100)); 
			this.damage(damage);
			this.displayUnitStatus();
		};
		this.setState(5); 
		this.destroyMask();
		this.exhaust();
	};
	
	this.displayUnitStatus = function() {
		var optionStr = '';
		var displayStr = '';
		var captureRequired = 0;
		var capturedSoFar = 0;
		this.game.selectedUnitDisplay.innerHTML = "";
		this.game.selectedUnitOptions.innerHTML = "";
		if (this.state == 1 || this.state == 3 || this.state == 5) {
			for (var j=0; j<this.game.building.length; j++) {
				if (this.canCapture && (!this.game.building[j].owned || this.game.building[j].owner != this.player) && this.game.building[j].x == this.x && this.game.building[j].y == this.y) { 
					optionStr += '<a href="javascript:'+this.game.name+'.elementAction(\'capture\');">Capture</a><br>';
					captureRequired = this.game.buildingTypes[this.game.building[j].type].captureCost;
					if (!this.hasMoved) capturedSoFar = this.captureLevel;
					break; 
				};
			};
		};
		if ( this.state > 0 && this.state < 7 && this.state != 2) { // Active, but not moving
			displayStr += this.typeName+'<br>';
			displayStr += 'Health: '+this.hitPoints+'<br>';
			if (captureRequired) displayStr += 'Capture: '+capturedSoFar+'/'+captureRequired;
			optionStr += '<a href="javascript:'+this.game.name+'.elementAction(\'wait\');">Wait</a><br>';
			optionStr += '<a href="javascript:'+this.game.name+'.elementAction(\'undo\');">Undo</a><br>';
		};
		this.game.selectedUnitDisplay.innerHTML = displayStr;
		this.game.selectedUnitOptions.innerHTML = optionStr;
	};
	
	this.capture = function() {
		for (var j=0; j<this.game.building.length; j++) {
			if (this.canCapture && (!this.game.building[j].owned || this.game.building[j].owner != this.player) && this.game.building[j].x == this.x && this.game.building[j].y == this.y) { 
				this.exhaust(); // Do this first so unit can move and capture
				this.captureLevel += this.hitPoints;
				if (this.captureLevel >= this.game.buildingTypes[this.game.building[j].type].captureCost) {
					this.game.building[j].setOwner(true, this.player);
					this.captureLevel = 0;
				};
				this.updateUnitDisplay(false);
				break; 
			}
		}
	};
	
	this.setPath = function( pathArray ) {
		this.path = this.path.concat(pathArray);
		this.backupPath = new Array();
		this.backupPath = this.backupPath.concat(pathArray);
	};
	this.animatePath = function() {
		this.setState(2); // Moving
		if (this.path.length > 0) {
			this.unitStyle.zIndex = 100;
			var direction = this.path.shift();
			this.setFacing(direction);
			if (direction == 0) { this.y--; };
			if (direction == 1) { this.x++; };
			if (direction == 2) { this.y++; }; 
			if (direction == 3) { this.x--; };
			unitToAnimate = this;
			unitAnimateMover = setInterval('unitMoveAnimate(1)', 10);
		} else {
			this.finishMove(true);
		}
	};
	this.finishMove = function(didMove) {
		if (this.mask) this.destroyMask();
		this.unitStyle.zIndex = 10;
		this.hasMoved = didMove;
		if((didMove && this.moveAndAttack) || !didMove) {
			this.setState(4);
			this.createAttackMask();
		} else {
			this.setState(3);
		}
	};
	
	this.rewindPath = function() {
		this.setState(2); // Moving
		if (this.backupPath.length > 0) {
			this.unitStyle.zIndex = 100;
			var direction = this.backupPath.pop();
			this.setFacing(direction);
			if (direction == 0) this.y++; 
			if (direction == 1) this.x--; 
			if (direction == 2) this.y--; 
			if (direction == 3) this.x++;
			unitToAnimate = this;
			unitAnimateMover = setInterval('unitMoveAnimate(2)', 10);
		} else {
			this.setState(1);
			this.hasMoved = false;
			this.createMoveMask();
		}
	}
};

var unitToAnimate; // Pointer to the moving unit.

function unitMoveAnimate(usePath) {
	var aUnit = unitToAnimate;
	if(parseInt(aUnit.unitStyle.left) < aUnit.x*32) { aUnit.unitStyle.left = (parseInt(aUnit.unitStyle.left)+1)+"px";  
	} else if(parseInt(aUnit.unitStyle.left) > aUnit.x*32) { aUnit.unitStyle.left = (parseInt(aUnit.unitStyle.left)-1)+"px"; };
	if(parseInt(aUnit.unitStyle.top) < aUnit.y*32) { aUnit.unitStyle.top = (parseInt(aUnit.unitStyle.top)+1)+"px";   
	} else if(parseInt(aUnit.unitStyle.top) > aUnit.y*32) { aUnit.unitStyle.top = (parseInt(aUnit.unitStyle.top)-1)+"px"; };
	if (parseInt(aUnit.unitStyle.left) == aUnit.x*32 && parseInt(aUnit.unitStyle.top) == aUnit.y*32) {
		clearInterval(unitAnimateMover);
		if (usePath == 1) {
			aUnit.animatePath();
		} else if (usePath == 2) {
			aUnit.rewindPath();
		} else {
			this.finishMove(true);
		}
	}
};

