/*<SCRIPT Language="JavaScript">*/

var CUBE_ROOT_OF_2 = 1.25992104989487316476721060727823;
var SQUARE_ROOT_OF_2 = 1.4142135623730950488016887242097;

var DAM_TYPE_Blunt	= 0;
var DAM_TYPE_Cut	= 1;
var DAM_TYPE_Imp	= 2;

var DAM_TYPE_NAMES	= new Array("Blunt", "Cutting", "Impailing");

var MovementArray = new Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                              0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
                              0, 0, 1, 0, 0, 0, 0, 1, 0, 0,
                              0, 1, 0, 0, 1, 0, 0, 0, 1, 0,
                              0, 1, 0, 1, 0, 0, 1, 0, 1, 0,
                              0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                              1, 0, 1, 0, 1, 1, 0, 1, 0, 1,
                              1, 0, 1, 1, 0, 1, 1, 1, 0, 1,
                              1, 1, 0, 1, 1, 1, 1, 0, 1, 1,
                              1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
                              1, 1, 1, 1, 1, 1, 1, 1, 1, 1);

var arEncumberance  = new Array("None", "Light", "Medium", "Heavy", "Overloaded");
var WalkingSpeed    = new Array(  0.15,    0.15,     0.10,    0.10,         0.05);
var JoggingSpeed    = new Array(  0.75,    0.60,     0.50,    0.40,         0.00);
var SprintingSpeed  = new Array(  1.00,    0.85,     0.75,    0.00,         0.00);
var JumpingModifier = new Array(  1.00,    0.80,     0.60,    0.40,         0.20);

var AttributeCost = new Array(-100, -75, -55, -35, -20, //  1, 2, 3, 4, 5
                              -10,   -5,   0,   5,  10, //  6, 7, 8, 9,10
                               15,   25,  40,  55,  75, // 11,12,13,14,15
                               100, 125, 150, 175, 200);// 16,17,18,19,20

var SkillCost = new Array(  0,  1,  3,//   +0,  +1,  +2
                            5,  8, 11,//   +3,  +4,  +5
                           15, 19, 24,//   +6,  +7,  +8
                           29, 35, 41,//   +9, +10, +11
                           48, 55, 63,//  +12, +13, +14
                           71, 80, 89,//  +15, +16, +17
                           99, 109);// +18, +19

function Round(number)
{
   return Math.round(number -.0000001);
}
function RoundTo1Percent(number, precission)
{
   var factor = 1;
   if (number < 0)
   {
      factor = -1;
      number *= -1;
   }
   minNum = 100;
   maxNum = 1000;
   if (precission != 0) {
      minNum = Math.pow(10, precission-1);
      maxNum = Math.pow(10, precission);
   }
   while (number < minNum)
   {
      factor *= 10;
      number *= 10;
   }
   while (number >= maxNum)
   {
      factor /= 10;
      number /= 10;
   }
   // number must now between 100 and 1000 (excluding 1000)
   number = Round(number) / factor;
   return number;
}

function CalcAttributeCost(AttributeLevel)
{
   return AttributeCost[AttributeLevel-1];
}
function getBaseAttributeLevel() 
{
   for (i=0 ; i<AttributeCost.length ; i++)
      if (AttributeCost[i] == 0)
         return i+1;
   return 10;
}
function getMaxAttributeLevel()
{
   return AttributeCost.length;
}
function getMinAttributeLevel()
{
   return 1;
}
function CalcSkillCost(SkillLevel)
{
   return SkillCost[SkillLevel];
}
function CalcScaleMultiplier(Size)
{
   return Math.pow(CUBE_ROOT_OF_2, Size);
}
function ComputeToHitModifierForSize(Size)
{
   return Round(Size/2);
}
function CalcScaledStr(Strength, Size)
{
   retVal = Strength * CalcScaleMultiplier(Size);
   return RoundTo1Percent(retVal, 3);
}
function GetMovementForRound(RoundNum, Speed) {
   Extra = 0;
   if (Speed > 10)
   {
      Extra = Math.floor(Speed / 10);
      Speed = Speed - 10*Extra;
   }
   retVal = Extra + MovementArray[Speed*10 + RoundNum-1];
   if (retVal == 0)
      return "-";
   return retVal;
}

function ComputeMovementBase(Health, Dexterity) {
   return Round(Health + Dexterity + 10);
}

function GetMovementModifier(Encumberance, Gate)
{
   if (Gate == "Walking")   return WalkingSpeed[Encumberance];
   if (Gate == "Jogging")   return JoggingSpeed[Encumberance];
   if (Gate == "Sprinting") return SprintingSpeed[Encumberance];
   return "Error";
}

function FormatTableRowWithMovementHeaders()
{
   Width = 40;
   retVal = "<TR><TH width="+Width+"></TH>";
   for (round=1 ; round<11 ; round++)
   {
      retVal += "<TH width="+Width+">"+round+"</TH>";
   }
   retVal += "</TR>";
   return retVal;
}

function FormatTableRowWithMovement(Speed, bSpeedInParenthises, bInSeparateRow)
{
   Width = 10;
   if (bInSeparateRow)
      retVal = "<TR>";
   else
      retVal = "";
   
   if (bSpeedInParenthises)
       retVal += "<TD>(<B>"+Speed+"</B>)</TD>";
   else
       retVal += "<TH width="+Width+">"+Speed+"</TH>";

   for (round=1 ; round<11 ; round++)
      retVal += "<TD width="+Width+"><font face=fixed>"+GetMovementForRound(round, Speed)+"</font></TD>";
   if (bInSeparateRow)
      retVal += "</TR>";
   return retVal;
}

function ConvertToPercent(Num)
{
   if (Num == 0)
      return "--";
   return (""+Num*100+"%");
}

function ComputeRelativeScoreLevel(Roll, Skill)
{
   retVal = 20;
   Skill = 8*Skill;
   bZero = false;
   if (Roll == 0)    {
      bZero = true;
      Roll = 1;
   }
   
   while (true)    {
      if (Roll >= Skill)
         break;
      retVal--;
      Skill = Skill/SQUARE_ROOT_OF_2;
   }
   if (bZero)
      return retVal-2;
   return retVal;
}

function ComputeSpeedModifierForStrength(strength) {
   return (4.0/strength +.5);
}
function ComputeSpeedModifierForSkill(skill) {
   return Math.min((5.0/skill +.5), 1);
}
function ComputeSpeedModifierForSize(size) {
   return Math.pow(1.05, size);
}
function ComputeAttackModifierForSize(size) {
   return round(size/2);
}
function ComputeJumpingHeight(skill, encumberance) {
   return JumpingModifier[encumberance]*skill/4;
}
function ComputeJumpingDistance(Movement, Height) {
   return (Movement * Math.pow(Height,.5) / 6);
}
function ComputeSizeAdjustedChanceMissile(baseChance, targetSize) {
   return (baseChance * CalcScaleMultiplier(targetSize));
}
function ComputeDistanceAdjustedChanceMissile(baseChance, dist) {
   return (baseChance * Math.pow((50/dist), 2));
}
function ComputeNetHitChanceMissile(skill, targetSize, distance) {
   return ComputeDistanceAdjustedChanceMissile(ComputeSizeAdjustedChanceMissile(skill, targetSize), distance);
}
function ComputeDamage(weaponDamage, defendersLevel, attackersLevel) {
   return Round(weaponDamage * (defendersLevel - attackersLevel) / 8);
}
function ComputeCriticalHitMissModifier(levelDifference) {
   return ((levelDifference - 10)/5 + 1)
}
function ComputeSwingDamage(strength) {
   return strength;
}
function ComputeThrustDamage(strength) {
   return Round(Math.pow(strength, .5)*5)/10; // round to nearest tenth
}
function ComputeMovementModifierForSize(baseMovement, size) {
   return (baseMovement * Math.pow(1.2,size));
}
function ComputeParry(Skill) {
   return Round(Skill/2);
}
function ComputeBlock(Skill) {
   return Round(Skill/2);
}
function ComputeDodge(MovementBase) {
   return Round(MovementBase/5);
}
function ComputeParrySpeed(WeaponSpeed) {
	return Round((WeaponSpeed+1)/2);
}
function ComputeBlockSpeed(ShieldSpeed) {
	return Round((ShieldSpeed+1)/2);
}
function ComputeDefaultSkillLevel(primaryAttributeLevel, skillDifficulty) {
   return ComputeBaseSkillLevel(primaryAttributeLevel, skillDifficulty) - 2;
}
function ComputeBaseSkillLevel(primaryAttributeLevel, SkillDifficulty) {
   adjAttLevel = primaryAttributeLevel;
   if (SkillDifficulty == "Easy")      adjAttLevel += 3;
   //else if (SkillDifficulty == "Average") 
   else if (SkillDifficulty == "Hard")      adjAttLevel -= 3;
   else if (SkillDifficulty == "Very Hard") adjAttLevel -= 6;
   return Round(adjAttLevel / 2);
}
function ComputeSkillLevel(primaryAttributeLevel, levelsBought, skillDifficulty) {
   if (levelsBought == 0)
      return ComputeDefaultSkillLevel(primaryAttributeLevel, skillDifficulty);
   return levelsBought*1 + ComputeBaseSkillLevel(primaryAttributeLevel, skillDifficulty);
}
function ComputeMinimumWeightForSize(size) {
   return RoundTo1Percent(Math.pow(2,(size/2))*128, 3);
}
function ComputeAverageWeightForSize(size) {
   return RoundTo1Percent(Math.pow(2,((size+.5)/2))*128, 3);
}
function ComputeMaximumWeightForSize(size) {
   minWieght = ComputeMinimumWeightForSize(size+1);
   if (minWieght > 100) {
      return (minWieght - 1);
   }
   for (i=-10 ; i<10 ; i++) {
      j = Math.pow(10, i);
      roundedWeight = RoundTo1Percent(minWieght - j, 3);
      if (roundedWeight < minWieght) {
         return roundedWeight;
      }
   }
   return minWieght;
}
function ComputeSizeForWeight(Weight) {
   retVal = 0;
   while (Weight>180)
   {
      Weight = Weight /SQUARE_ROOT_OF_2;
      retVal++;
   }
   while (Weight<180/SQUARE_ROOT_OF_2)
   {
      Weight = Weight *SQUARE_ROOT_OF_2;
      retVal--;
   }
   return retVal;
}  
function ComputeMaxWeightForEncumbrance(Encumberance, ScaledStr)
{
   if (Encumberance == arEncumberance[0]) return RoundTo1Percent(2*ScaledStr,3);
   if (Encumberance == arEncumberance[1]) return RoundTo1Percent(5*ScaledStr,3);
   if (Encumberance == arEncumberance[2]) return RoundTo1Percent(10*ScaledStr,3);
   if (Encumberance == arEncumberance[3]) return RoundTo1Percent(20*ScaledStr,3);
   if (Encumberance == arEncumberance[4]) return RoundTo1Percent(40*ScaledStr,3);
}
function ComputeCostOfSize(SizeDifference)
{
   SizeDifference = SizeDifference*1 + 3;
   SizeCostArray = new Array(-60, -35, -20, 0, 20, 50, 100);
   if ((SizeDifference >= 0) && (SizeDifference < SizeCostArray.length))
      return SizeCostArray[SizeDifference];

   alert("error in ComputeCostOfSize!  SizeDiff = "+SizeDifference);
   return error;
}
