// gurpschar.js
// errorhandler
var msgArray;
var urlArray;
var lnoArray;
// -----------
// global vars
var myCharacter;
var gDebug;
var gShowMoney;
var gDualWeaponParry;
// vars: lookup tables
var vAttr;
var vSkills;
var vDam;
var vStatus;
var vWealth;
// vars: character xp (values set in character sheet, HTML)
var xpAttr;
var xpAdv;
var xpSkill;
var xpSpells;
var xpTotal;
var myArmor;
var myWeapons;
var myRangedWeapons;
var myGuns;
var myPouch;
var myPack;
var mySaddlebags;
var myPackhorse;
var myHome;
var myIncome;
var myStatus;
var myStartingStatus;
var myWealth;
// ------
// local vars
var valST;
var valDX;
var valIQ;
var valHT;
var mySkills;                           // an array of skill objects
var lbsArmor, lbsShield, lbsWeapons, lbsPack;
var nCombatReflexes;
var vWeapons;
var vRangedWeapons;
var vRangeSteps;
// guns.js
var nGunsName;
var nGunsSkill;
var nGunsCost;
var nGunsLbs;
var nGunsDam;
var nGunsSS;
var nGunsAcc;
var nGunsHalfDamRange;
var nGunsMaxRange;
var nGunsType;
var nGunsROF;
var nGunsShots;
var nGunsRecoil;
var nGunsStrength;
var nGunsTL;
var vGuns;
var bShowAllGuns;
// armor.js
var vArmor;
// spell.js
var nSpellName;
var nSpellDifficulty;
var nSpellClass;
var nSpellResistance;
var nSpellCollege;
var nSpellCastingTime;
var nSpellDuration;
var nSpellEnergy;
var nSpellPrerequisite;
var nSpellItemEnergyCost;
var nSpellItemValue;
var nSpellRank;
var vSpells;                            // big array
// Enchantments.js
var vAccuracy;
var vDeflect;
var vFortify;
var vLighten;
var vPenetratingBlade;
// KnightsTemplar.js
var vKnightsTemplar;
// Bard
var bBard;
//
var vLanguages;
var vPowerstone;

//============================================================================
// object: Character
//============================================================================
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function buildWeapons()
{
    for ( var i = 0; i < myWeapons.length; i++ )
    {
        this.weapons[i] = createWeaponObj( myWeapons[i] );
    }
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function findWeapon( name )
{
    for ( var jj = 0; jj < myWeapons.length; jj++ )
    {
        if ( this.weapons[jj].name == name )
        {
            return this.weapons[jj];
        }
    }
    return null;
}  // findWeapon

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function setAttr()
{
    for ( var i = 0; i < xpAttr.length; i++ )
    {
        switch( xpAttr[i][0] )
        {
            case "ST" : this.ST = parseInt(getAttr(xpAttr[i][1])); break;
            case "DX" : this.DX = parseInt(getAttr(xpAttr[i][1])); break;
            case "IQ" : this.IQ = parseInt(getAttr(xpAttr[i][1])); break;
            case "HT" : this.HT = parseInt(getAttr(xpAttr[i][1])); break;
        }
    }
    if ( this.ST <= 5 )
    {
        this.height = 64;
    }
    else
    {
        if ( this.ST <= 16 )
        {
            this.height += (this.ST - 10);
        }
        else
        {
            this.height = 76;
        }
    }
    this.setWt();
}  // setAttr

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function setWt()
{
    switch ( this.height )
    {
        case 64 : this.wt = 130; break;
        case 65 : this.wt = 135; break;
        case 66 : this.wt = 135; break;
        case 67 : this.wt = 140; break;
        case 68 : this.wt = 145; break;
        case 69 : this.wt = 150; break;
        case 70 : this.wt = 155; break;
        case 71 : this.wt = 160; break;
        case 72 : this.wt = 165; break;
        case 73 : this.wt = 170; break;
        case 74 : this.wt = 180; break;
        case 75 : this.wt = 190; break;
        default:
            if ( this.height < 64 )
            {
                this.wt = 130;
            }
            if ( this.height < 63 )
            {
                this.wt = 120;
            }
            if ( 75 < this.height )
            {
                this.wt = 190 + 10 * (this.height - 75);
            }
            break;
    }
}  // setWt

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getAppearance()
{
    var str = "";
    var feet = Math.floor(this.height / 12);
    var inches = this.height - 12 * feet;
    str += String(feet) + "'" + String(inches) + "\" " + String(this.wt) + "lbs.";
    return str;
}

//-----------------------------------------------------------------------------
function Character()
{
    this.ST = 10;
    this.DX = 10;
    this.IQ = 10;
    this.HT = 10;
    this.height = 69;                   // inches
    this.wt = 150;                      // lbs
    this.weapons = new Array();
    this.buildWeapons = buildWeapons;
    this.findWeapon = findWeapon;
    this.setAttr = setAttr;
    this.setWt = setWt;
    this.getAppearance = getAppearance;

}
//============================================================================

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function writeCharacter()
{
    //try
    {
        myCharacter = new Character();

        document.writeln ( "<table cellspacing=2s5><tr><td>" );
        document.writeln ( "<form name='frmHeader'>" );
        document.writeln ( "<input NAME='xpTotal' TYPE=Text readonly class=readonly-rightalign SIZE=3>:total XP" );
        document.writeln ( "</form>" );

        document.writeln ( "</table>" );

        document.writeln ( "<table BORDER=0 CELLSPACING=0 CELLPADDING=1><tr>" );
        //---- col: xp --------------------------------------------------------
        document.writeln ( "<td style='VERTICAL-ALIGN: top;'>" );
        document.writeln ( "<form name='frmMain'>" );
        document.writeln ( "<table BORDER=0 CELLSPACING=0 CELLPADDING=1>" );
        myCharacter.setAttr();
        writeAttr();
        writeAdv();
        setID( "idAppearance", myCharacter.getAppearance() );
        writeMySkill();
        document.writeln ( "</table>" );
        //document.frmHeader["xpTotal"].value = String(xpTotal);
        setFormValue( "frmHeader", "xpTotal", String(xpTotal) );

        // col: separator
        document.writeln ( "<td width=5%>" );

        // col: Calc Stats, Equipment, Attack/Defense
        document.writeln ( "<td style='VERTICAL-ALIGN: top'>" );

        //---- col: calculated stats ------------------------------------------
        document.writeln ( "<table BORDER=0 CELLSPACING=2 CELLPADDING=0>" );
        document.writeln ( "<tr>" );
        document.writeln ( "<th colspan=2>Calculated Stats" );
        if ( gShowMoney )
        {
            document.writeln ( "<th colspan=1>Wealth" );
        }
        document.writeln ( "<tr valign=top>" );
        document.writeln ( "<td style='VERTICAL-ALIGN: top'>" );

        // swing, thrust, speed
        document.writeln ( "<table BORDER=0 CELLSPACING=0 CELLPADDING=1>" );

        document.write ( "<tr><td align=right>Swing: <td class=inputcell >" )
        document.writeln ( "<input name='swing' readonly class=readonly-rightalign TYPE=Text SIZE=5>" );
        //document.frmMain["swing"].value = getDam( valST, "sw", 0 );
        setFormValue( "frmMain", "swing", getDam( valST, "sw", 0 ));

        document.writeln ( "<tr><td align=right>Thrust: <td class=inputcell >" );
        document.write ( "<input name='thrust' readonly class=readonly-rightalign TYPE=Text SIZE=5>" );
        //document.frmMain["thrust"].value = getDam( valST, "thr", 0 );
        setFormValue( "frmMain", "thrust", getDam( valST, "thr", 0 ) );

        speed = ( (valHT + valDX) / 4 );
        document.writeln ( "<tr><td align=right>Speed: <td class=inputcell >" );
        document.write ( "<input name='speed' readonly class=readonly-rightalign TYPE=Text SIZE=5>" );
        //document.frmMain["speed"].value = String(speed);
        setFormValue( "frmMain", "speed", String(speed) );

        running = Math.floor(speed + parseInt(getSkillObject( "Running" ).value) / 8);
        document.writeln ( "<tr><td align=right>(run): <td class=inputcell >" );
        document.write ( "<input name='run' readonly class=readonly-rightalign TYPE=Text SIZE=5>" );
        //document.frmMain["run"].value = String(running);
        setFormValue( "frmMain", "run", String(running) );

        for ( j = 0; j < xpAdv.length; j++ )
        {
            adv =  xpAdv[j][0].split("|");
            if ( "Flight" == adv[0] )
            {
                flight = Math.floor(speed * 2);
                document.writeln ( "<tr><td align=right>(flight): <td class=inputcell >" );
                document.write ( "<input name='flight' readonly class=readonly-rightalign TYPE=Text SIZE=5>" );
                document.frmMain["flight"].value = String(flight);
            }
        }
        document.writeln ( "</table>" );    // swing,thrust,speed,run,flight

        // encumbrance
        document.writeln ( "<td style='VERTICAL-ALIGN: top'>" );
        writeEncumbrance();

        if ( gShowMoney )
        {
            // wealth
            document.writeln ( "<td id='idWealth' style='VERTICAL-ALIGN: top'>" );
        }

        document.writeln ( "</table>" );

        document.writeln ( "</form>" ); // frmMain

        myCharacter.buildWeapons();
        writeEquipment();
        writeDefense();

        document.writeln ( "</table> <!-- big table (page columns) -->" );

        if ( xpSpells != null )
        {
            writeSpell();
        }

        document.writeln( "<table><tr>" );
        if ( gShowMoney )
        {
            if ( myIncome == null )
            {
                myIncome = new Array();
            }
            myIncome[myIncome.length] = [ "armor", 0-getFormValue("frmArmor","valCost"), 0 ];
            myIncome[myIncome.length] = [ "shield", 0-getFormValue("frmShield","valCost"), 0 ];
            myIncome[myIncome.length] = [ "weapons", 0-getFormValue("frmWeapons","valCost"), 0 ];
            if ( myRangedWeapons != null )
            {
                myIncome[myIncome.length] = [ "ranged weapons", 0-getFormValue("frmRangedWeapons","valCost"), 0 ];
            }
            if ( myGuns != null )
            {
                myIncome[myIncome.length] = [ "guns", 0-getFormValue("frmGuns","valCost"), 0 ];
            }
        }

        writeBag( myPouch, "on person", null, true );
        writeBag( myPack, "Pack", null, true );
        writeBag( mySaddlebags, "Saddlebags", null, true );
        writeBag( myPackhorse, "Packhorse", null, true );
        writeBag( myHome, "At Home", null, true );
        writeBag( myIncome, "Money", null, true );
        document.writeln( "</table>" );

        if ( gShowMoney )
        {
            if ( myStatus == null )
            {
                myStatus = 0;
            }
            setID( "idWealth", getWealthString() );
        }
    }
    /*catch ( e )
    {
        errorHandler(e.msg, e.url, e.lno);
        displayErrors();
    }*/

}  // writeCharacter

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function writeAttr()
{
    document.writeln ( "<tr>" );
    document.writeln ( "<th colspan=7>Attributes" );
    document.writeln ( "<tr>" );
    document.writeln ( "<th class=column align=right style='FONT-FAMILY: Arial'>xp" );
    document.writeln ( "<th class=column align=right style='FONT-FAMILY: Arial'>" );
    var xp = 0;
    for ( var i = 0; i < xpAttr.length; i++ )
    {
        xp += xpAttr[i][1];
    }
    document.writeln ( " (" + xp + ")" );
    document.writeln ( "<th class=column colspan=5>" );
    document.writeln ( "<span id='idAppearance'></span>" );
    for ( var i = 0; i < xpAttr.length; i++ )
    {
        attr = xpAttr[i][0];
        document.write ( "<tr>" );
        document.writeln ( "<td class=inputcell>" );
        document.write ( "<input NAME='xpAttr" + attr + "' readonly class=readonly-rightalign TYPE=Text SIZE=3'>" );
        document.frmMain["xpAttr" + attr].value = String(xpAttr[i][1]);

        document.writeln ( "<td class=inputcell>" );
        document.write ( "<input name='valAttr" + attr + "' readonly class=readonly-bold TYPE=Text SIZE=3>" );
        document.frmMain["valAttr" + attr].value = getAttr(xpAttr[i][1]);
        document.writeln ( "<td>" + xpAttr[i][0] );
        switch( xpAttr[i][0] )
        {
            case "ST" : valST = parseInt(getAttr(xpAttr[i][1])); break;
            case "DX" : valDX = parseInt(getAttr(xpAttr[i][1])); break;
            case "IQ" : valIQ = parseInt(getAttr(xpAttr[i][1])); break;
            case "HT" : valHT = parseInt(getAttr(xpAttr[i][1])); break;
        }
        xpTotal += parseInt(xpAttr[i][1]);
    }
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getAttr(xp)
{
    attr = 1;
    while( vAttr[attr] <= xp )
    {
        attr++;
    }
    return String(attr);
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function writeAdv()
{
    var i, xp, mod, adv;
    var xpA, xpD;
    nCombatReflexes = 0;

    document.writeln ( "<tr>" );
    document.writeln ( "<th colspan=7>Advantages/Disadvantages" );
    document.writeln ( "<tr>" );
    document.writeln ( "<th class=column align=right style='FONT-FAMILY: Arial'>xp" );
    document.writeln ( "<th class=column align=left colspan=6 style='FONT-FAMILY: Arial'>" );
    xpA = 0;
    xpD = 0;
    for ( i = 0; i < xpAdv.length; i++ )
    {
        if ( 0 < xpAdv[i][1] )
        {
            xpA += xpAdv[i][1];
        }
        else
        {
            xpD += xpAdv[i][1];
        }
    }
    document.writeln ( " (" + xpA + " / " + xpD + ")" );
    for ( i = 0; i < xpAdv.length; i++ )
    {
        document.write ( "<tr>" );
        document.writeln ( "<td class=inputcell style='VERTICAL-ALIGN: top'>" );
        document.write ( "<input NAME='xpAdv" + i + "' readonly class=readonly-rightalign TYPE=Text SIZE=3>" );
        document.frmMain["xpAdv" + i].value = xpAdv[i][1];

        adv = xpAdv[i][0].split("|");
        document.writeln ( "<td>" );
        if ( 0 < adv[0].length )
        {
            document.writeln ( "<td nowrap colspan=1 align=left style='VERTICAL-ALIGN: top'>" + adv[0] );
        }
        xp = parseInt(xpAdv[i][1]);
        switch ( adv[0] )
        {
            case "Acute Vision" :
                mod = Math.floor( xp / 2 );
                document.writeln ( "<td>" );
                document.write ( "<input NAME='valAcuteVision' readonly class=readonly-rightalign TYPE=Text SIZE=3>" );
                document.frmMain["valAcuteVision"].value = "+" + String( mod );
                document.writeln ( "<td colspan=3> to vision rolls" );
                break;
            case "Acute Hearing" :
                mod = Math.floor( xp / 2 );
                document.writeln ( "<td>" );
                document.write ( "<input NAME='valAcuteHearing' readonly class=readonly-rightalign TYPE=Text SIZE=3>" );
                document.frmMain["valAcuteHearing"].value = "+" + String( mod );
                document.writeln ( "<td colspan=3> to hearing rolls" );
                break;
            case "Acute Taste/Smell" :
                mod = Math.floor( xp / 2 );
                document.writeln ( "<td>" );
                document.write ( "<input NAME='valAcuteTasteSmell' readonly class=readonly-rightalign TYPE=Text SIZE=3>" );
                document.frmMain["valAcuteTasteSmell"].value = "+" + String( mod );
                document.writeln ( "<td colspan=3> to taste/smell rolls" );
                break;
            case "Albino" :
            case "Albinism" :
                document.writeln ( "<td colspan=4>1pt damage / 30 minutes direct sunlight" );
                document.writeln ( "<br>-2 vision and ranged attacks in direct sunlight" );
                break;
            case "Alertness" :
                mod = Math.floor( xp / 5 );
                document.writeln ( "<td>" );
                document.write ( "<input NAME='valAlertness' readonly class=readonly-rightalign TYPE=Text SIZE=3>" );
                document.frmMain["valAlertness"].value = "+" + String( mod );
                document.writeln ( "<td colspan=3> on all perception rolls" );
                break;
            case "Animal Empathy" :
                if ( 5 <= xp )
                {
                    document.writeln ( "<td colspan=4>" );
                    document.writeln ( "+2 reaction with wild animals" );
                    document.writeln ( "<br>+4 reaction with tame animals" );
                }
                break;
            case "Appearance" :
                if ( xp <= -20 )
                {
                    document.writeln ( "<td style='VERTICAL-ALIGN: top'>" );
                    document.write ( "<input NAME='valAppearance' readonly class=readonly-rightalign TYPE=Text SIZE=3>" );
                    document.frmMain["valAppearance"].value = "-" + String( 4 );
                    document.writeln ( "<td colspan=3>" );
                    document.writeln ( "on all reaction rolls" );
                    document.writeln( "<br> (Hideous)" );
                }
                if ( xp <= -10 )
                {
                    document.writeln ( "<td style='VERTICAL-ALIGN: top'>" );
                    document.write ( "<input NAME='valAppearance' readonly class=readonly-rightalign TYPE=Text SIZE=3>" );
                    document.frmMain["valAppearance"].value = "-" + String( 2 );
                    document.writeln ( "<td colspan=3>" );
                    document.writeln ( "on all reaction rolls" );
                    document.writeln( "<br> (Ugly)" );
                }
                if ( xp <= -5 )
                {
                    document.writeln ( "<td style='VERTICAL-ALIGN: top'>" );
                    document.write ( "<input NAME='valAppearance' readonly class=readonly-rightalign TYPE=Text SIZE=3>" );
                    document.frmMain["valAppearance"].value = "-" + String( 1 );
                    document.writeln ( "<td colspan=3>" );
                    document.writeln ( "on all reaction rolls" );
                    document.writeln( "<br> (Unattractive)" );
                }
                if ( 5 <= xp )
                {
                    document.writeln ( "<td style='VERTICAL-ALIGN: top'>" );
                    document.write ( "<input NAME='valAppearance' readonly class=readonly-rightalign TYPE=Text SIZE=3>" );
                    document.frmMain["valAppearance"].value = "+" + String( 1 );
                    document.writeln ( "<td colspan=3>" );
                    document.writeln ( "on all reaction rolls" );
                    document.writeln( "<br> (Attractive)" );
                }
                if ( 15 <= xp )
                {
                    document.writeln ( "<td style='VERTICAL-ALIGN: top'>" );
                    document.write ( "<input NAME='valAppearance' readonly class=readonly-rightalign TYPE=Text SIZE=3>" );
                    document.frmMain["valAlertness"].value = "+" + String( 2 );
                    document.writeln ( "<td colspan=4>" );
                    document.writeln ( " on all reaction rolls made by the same sex" );
                    document.writeln ( "<br>+4 by opposite sex" );
                    document.writeln( "<br> (Handsome / Beautiful)" );
                }
                if ( 15 <= xp )
                {
                    document.writeln ( "<td style='VERTICAL-ALIGN: top'>" );
                    document.write ( "<input NAME='valAppearance' readonly class=readonly-rightalign TYPE=Text SIZE=3>" );
                    document.frmMain["valAlertness"].value = "+" + String( 2 );
                    document.writeln ( "<td colspan=4>" );
                    document.writeln ( " on all reaction rolls made by the same sex" );
                    document.writeln ( "<br>+6 by opposite sex" );
                    document.writeln( "<br> (Very Handsome / Very Beautiful)" );
                }
                break;
            case "Charisma" :
                mod = Math.floor( xp / 5 );
                document.writeln ( "<td>" );
                document.write ( "<input NAME='valCharisma' readonly class=readonly-rightalign TYPE=Text SIZE=3>" );
                document.frmMain["valCharisma"].value = "+" + String( mod );
                document.writeln ( "<td colspan=3> to reaction " );
                break;
            case "Clerical Investment" :
                if ( vKnightsTemplar != null )
                {
                    document.writeln ( "<td colspan=5>" )
                    document.writeln ( getRankKnightTemplar( xp ));
                }
                break;
            case "Combat Reflexes" :
                if ( 15 <= xp )
                {
                    document.writeln ( "<td colspan=4>+2 on Fright Checks " );
                    document.writeln ( "<br>+6 to recover from surpise/mental stun " );
                    nCombatReflexes = 1;
                }
                break;
            case "Hard to Kill" :
                mod = Math.floor( xp / 4 );
                document.writeln ( "<td colspan=4>+" + String( mod ) + " to all HT rolls made for survival" );
                break;
            case "Increased ST" :
                if ( 30 <= xp )
                {
                    valST = valST * 2;
                    setFormValue( "frmMain", "valAttrST", valST );
                }
                break;
            case "Language Talent" :
                mod = Math.floor( xp / 4 );
                document.writeln ( "<td>" );
                document.write ( "<input NAME='valLanguageTalent' readonly class=readonly-rightalign TYPE=Text SIZE=3>" );
                document.frmMain["valLanguageTalent"].value = "+" + String( mod );
                document.writeln ( "<td colspan=3> to language skills" );
                break;
            case "Magery" :
                if ( 5 <= xp )
                {
                    mod = Math.floor((xp - 5) / 10);
                }
                else
                {
                    mod = 0;
                }
                document.writeln ( "<td>" );
                document.write ( "<input NAME='valMagery' readonly class=readonly-rightalign TYPE=Text SIZE=3>" );
                document.frmMain["valMagery"].value = "+" + String( mod );
                document.writeln ( "<td colspan=3>to spell skills" );
                break;
            case "Musical Ability" :
                mod = xp;
                document.writeln ( "<td>" );
                document.write ( "<input NAME='valMusicalAbility' readonly class=readonly-rightalign TYPE=Text SIZE=3>" );
                document.frmMain["valMusicalAbility"].value = "+" + String( mod );
                break;
            case "Musical Magery" :
                mod = 0;
                oMusicalAbility = document.frmMain["valMusicalAbility"];
                if ( oMusicalAbility != null )
                {
                    xp = parseInt(oMusicalAbility.value);
                    if ( 8 <= xp )
                    {
                        mod = 1;
                    }
                    if ( 13 <= xp )
                    {
                        mod = 2;
                    }
                    if ( 18 <= xp )
                    {
                        mod = 3;
                    }
                }
                document.writeln ( "<td>" );
                document.write ( "<input NAME='valMagery' readonly class=readonly-rightalign TYPE=Text SIZE=3>" );
                document.frmMain["valMagery"].value = "+" + String( mod );
                document.writeln ( "<td colspan=4>to musical spell skills. must play an instrument while casting" );
                break;
            case "Power Investiture" :
                mod = 0;
                if ( vKnightsTemplar != null )
                {
                    mod = getKnightTemplarPower( xp );
                }
                else
                {
                    mod = Math.floor( xp / 10 );
                }
                document.writeln ( "<td>" );
                document.write ( "<input NAME='valMagery' readonly class=readonly-rightalign TYPE=Text SIZE=3>" );
                document.frmMain["valMagery"].value = "+" + String( mod );
                break;
            case "Reputation" :
                mod = Math.floor( xp / 5 );
                document.writeln ( "<td colspan=2>" );
                if ( 0 < mod )
                {
                    document.writeln ( "+" + String( mod ) );
                }
                else
                {
                    document.writeln ( String( mod ) );
                }
                document.writeln ( " to reaction " );
                break;
            case "Status" :
                myStartingStatus = Math.floor( xp / 5 );
                if ( myStatus == null )
                {
                    myStatus = myStartingStatus;
                }
                document.writeln ( "<td>" );
                document.writeln ( "+" + String( myStartingStatus ) );
                if ( 1 == adv.length )
                {
                    var status = getStatusObj( myStartingStatus );
                    adv[1] = status.name;
                }
                break;
            case "Strong Will" :
                mod = Math.floor( xp / 4 );
                document.writeln ( "<td>" );
                document.write ( "<input NAME='valStrongWill' readonly class=readonly-rightalign TYPE=Text SIZE=3>" );
                document.frmMain["valStrongWill"].value = "+" + String( mod );
                document.writeln ( "<td colspan=3> to Will rolls " );
                break;
            case "Voice" :
                mod = ( xp <= 10 ) ? +2 : 0;
                document.writeln ( "<td>" );
                document.write ( "<input NAME='valVoice' readonly class=readonly-rightalign TYPE=Text SIZE=3>" );
                document.frmMain["valVoice"].value = "+" + String( mod );
                document.writeln ( "<td colspan=3> to reaction " );
                break;
            case "Wealth" :
                myWealth = Math.floor( xp / 5 );
                document.writeln ( "<td>" );
                document.writeln ( "+" + String( myWealth ) );
                break;
        }
        if ( 1 < adv.length )
        {
            document.writeln ( "<td colspan=5>" );
            for ( j = 1; j < adv.length; j++ )
            {
                if ( 1 < j )
                {
                    document.writeln ( ", " );
                }
                document.writeln ( adv[j] );
            }
        }
        xpTotal += parseInt(xpAdv[i][1]);

    }
}  // writeAdv

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function SkillAdv(b,n)
{
    this.bonus = b;
    this.note = n;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function SkillObject(skill,a)
{
    this.name = skill;
    this.ndx = -1;
    this.value = 1;
    this.xp = 0;
    this.attr = "none";
    this.mod = 0;
    this.adv = a;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function createSkillObject( skill, xp )
{
    var adv, obj, defGrp, sk;
    obj = {name:null,ndx:-1,value:-1,xp:0,difficulty:null,attr:"none",mod:0,bonus:0,maneuver:false};
    sk = skill.split("|");
    obj.name = sk[0];
    obj.note = "";
    if ( 1 < sk.length )
    {
        for ( var j = 1; j < sk.length; j++ )
        {
            obj.note += sk[j];
        }
    }
    obj.ndx = ndxOfSkill( obj.name );
    if ( -1 < obj.ndx )
    {
        obj.difficulty = vSkills[obj.ndx][1];
        obj.attr = vSkills[obj.ndx][2];
        obj.maneuver = (obj.attr == "maneuver");
        obj.derived = vSkills[obj.ndx][5];
        obj.xp = xp;

        // preset bonus from advantages
        if ( obj.name == "Bard"
          || obj.name == "Leadership" )
        {
            adv = document.frmMain["valCharisma"];
            if ( adv != null )
            {
                obj.bonus += parseInt(adv.value);
                if ( 0 < obj.note.length )
                {
                    obj.note += "<br>";
                }
                obj.note += " w/Charisma";
            }
        }

        if ( obj.name == "Bard"
          || obj.name == "Diplomacy"
          || obj.name == "Performance"
          || obj.name == "Politician"
          || obj.name == "Savoir-Faire"
          || obj.name == "Sex Appeal"
          || obj.name == "Singing" )
        {
            adv = document.frmMain["valVoice"];
            if ( adv != null )
            {
                obj.bonus += parseInt(adv.value);
                if ( 0 < obj.note.length )
                {
                    obj.note += "<br>";
                }
                obj.note += " w/Voice";
            }
        }
        if ( obj.name == "Fast-Draw" )
        {
            for ( var j = 0; j < xpAdv.length; j++ )
            {
                if ( "Combat Reflexes" == xpAdv[j][0] && 15 <= xpAdv[j][1] )
                {
                    obj.bonus += 1;
                    if ( 0 < obj.note.length )
                    {
                        obj.note += "<br>";
                    }
                    obj.note += "w/Combat Reflexes";
                    break;
                }
            }
        }
        if ( obj.name == "Animal Handling"
          || obj.name == "Falconry"
          || obj.name == "Teamster"
          || obj.name == "Veterinary"
          || obj.name == "Riding" )
        {
            for ( var j = 0; j < xpAdv.length; j++ )
            {
                if ( "Animal Empathy" == xpAdv[j][0] && 5 <= xpAdv[j][1] )
                {
                    obj.bonus += 4;
                    if ( 0 < obj.note.length )
                    {
                        obj.note += "<br>";
                    }
                    obj.note += " w/Animal Empathy";
                    break;
                }
            }
        }
        if ( obj.name == "Tracking" )
        {
            for ( var j = 0; j < xpAdv.length; j++ )
            {
                if ( "Animal Empathy" == xpAdv[j][0] && 5 <= xpAdv[j][1] )
                {
                    if ( 0 < obj.note.length )
                    {
                        obj.note += "<br>";
                    }
                    obj.note += " +3 when tracking game";
                    break;
                }
            }
        }
        if ( obj.name.substr(0,8) == "Language" )
        {
            adv = document.frmMain["valLanguageTalent"];
            if ( adv != null )
            {
                obj.bonus += parseInt(adv.value);
            }
            obj.note += "(" + getLanguageDescription(obj.xp + obj.bonus) + ")";
        }

        if ( 0 < obj.xp )
        {
            obj.mod = getSkillMod( obj.xp, obj.difficulty );
            switch ( obj.difficulty )
            {
                case "ME":
                case "MA":
                case "MH":
                case "MVH":
                    if ( obj.name.substr(0,8) != "Language" )
                    {
                        for ( j = 0; j < xpAdv.length; j++ )
                        {
                            if ( "Eidetic Memory" == xpAdv[j][0] )
                            {
                                obj.mod = getSkillMod( 2 * obj.xp, obj.difficulty );
                                break;
                            }
                        }
                    }
                    break;
            }
            obj.value = getSkillValue( obj.attr, obj.mod + obj.bonus );
            // debugging
            /*
            if ( obj.name == "Mounted Combat" )
            {
                window.status = obj.name
                    + ", attr=" + String(obj.attr)
                    + ", mod=" + String(obj.mod)
                    + ", bonus=" + String(obj.bonus)
                    + ", value=" + String(obj.value)
                    + ", note=" + String(obj.note);
            }
            */
        }
        else
        {
            // set default
            obj.note += "(default)";
            var attr, mod, value;
            if ( obj.name.substr(0,8) == "Language" && 2 < sk.length )
            {
                obj.note = sk[1];
                obj.value = 0;
                obj.attr = sk[2];
                obj.mod = -1;               // Easy
                if ( obj.name.substr(10,7) == "Average" )
                {
                    obj.mod = -2;
                }
                if ( obj.name.substr(10,4) == "Hard" )
                {
                    obj.mod = -3;
                }
                if ( 0 <= obj.mod + obj.bonus  )
                {
                    obj.mod = - obj.bonus - 1;
                }

                for ( var jj = 0; jj < mySkills.length; jj++ )
                {
                    if ( mySkills[jj] != null
                      && mySkills[jj].note.substr(0,sk[2].length) == sk[2]
                      && 0 < mySkills[jj].xp )
                    {
                        obj.value = mySkills[jj].value + obj.mod + obj.bonus;
                        var ndx;
                        ndx = parseInt(getLanguageNdx( parseInt(mySkills[jj].xp) ));
                        ndx += obj.mod + obj.bonus;
                        if ( ndx < 0 )
                        {
                            ndx = 0;
                        }
                        if ( vLanguages.length - 1 < ndx )
                        {
                            ndx = vLanguages.length - 1;
                        }
                        obj.note = sk[1] + "(" + vLanguages[ndx][1] + " " + vLanguages[ndx][2] + ")(default)[" + String(ndx) + "]";
                        break;
                    }
                }
            } // language
            else
            {
                defGrp = vSkills[obj.ndx][3];
                for ( j = 0; j < defGrp.length; j++ )
                {
                    value = -1;
                    attr = defGrp[j][0];
                    mod = defGrp[j][1];
                    switch( attr )
                    {
                        case "ST" :
                        case "DX" :
                        case "IQ" :
                        case "HT" :
                            value = getSkillValue( attr, mod + obj.bonus );
                            break;
                        default:
                            if ( 0 < parseInt(attr) )
                            {
                                value = getSkillValue( attr, mod + obj.bonus );
                            }
                            else
                            {
                                for ( var jj = 0; jj < mySkills.length; jj++ )
                                {
                                    if ( mySkills[jj] != null
                                    && mySkills[jj].name == attr
                                    && 0 < mySkills[jj].xp )
                                    {
                                        value = mySkills[jj].value + mod + obj.bonus;
                                        break;
                                    }
                                }
                            }
                            break;
                    }
                    if ( obj.value < value )
                    {
                        obj.value = value;
                        obj.attr = attr;
                        obj.mod = mod;
                    }
                }
            } // non-language
        }

    } // ndx
    return obj;
}  // createSkillObject

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getSkillMod(xp,type)
{
    mod = -6;
    switch( type )
    {
        case "PE":
        case "PA":
        case "PH":
            mod = -6;
            if( 0.5 <= xp ) { mod = -3; }
            if( 1 <= xp ) { mod = -2; }
            if( 2 <= xp ) { mod = -1; }
            if( 4 <= xp ) { mod = 0; }
            if( 4 <  xp ) { mod = Math.floor(xp / 8) + 0; }
            switch( type )
            {
                case "PE": mod += 2; break;
                case "PA": mod += 1; break;
                case "PH": mod += 0; break;
            }
            break;
        case "ME":
        case "MA":
        case "MH":
            mod = -4;
            if( 0.5 <= xp ) { mod = -1; }
            if( 1 <= xp ) { mod = 0; }
            if( 1 <  xp ) { mod = Math.floor(xp / 2) + 0; }
            switch( type )
            {
                case "ME": mod -= 0; break;
                case "MA": mod -= 1; break;
                case "MH": mod -= 2; break;
            }
            break;
        case "MVH":
            mod = -6;
            if( 0.5 <= xp ) { mod = -4; }
            if( 1 <= xp ) { mod = -3; }
            if( 2 <= xp ) { mod = -2; }
            if( 4 <= xp ) { mod = -1; }
            if( 4 <  xp ) { mod = Math.floor(xp / 4) - 1; }
            break;
        // maneuvers
        case "A":
            mod = 0;
            if( 0.5 <= xp ) { mod = +1; }
            if( 1 <= xp ) { mod = +2; }
            if( 2 <= xp ) { mod = +3; }
            if( 4 <= xp ) { mod = Math.floor(xp / 2) + 2; }
            break;
        case "H":
            mod = 0;
            if( 1 <= xp ) { mod = +1; }
            if( 2 <= xp ) { mod = Math.floor(xp / 2) + 1; }
            break;
    }
    return mod;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getSkillValue( attr, mod )
{
    skill = 0;
    switch( attr )
    {
        case "ST" : skill = parseInt(valST) + parseInt(mod); break;
        case "DX" : skill = parseInt(valDX) + parseInt(mod); break;
        case "IQ" : skill = parseInt(valIQ) + parseInt(mod); break;
        case "HT" : skill = parseInt(valHT) + parseInt(mod); break;
        default:
            skill = parseInt(attr) + parseInt(mod);
            break;
    }

    return skill;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function buildMySkills()
{
    var i, xp, obj;

    mySkills = new Array(xpSkill.length);

    // get skill with experience
    for ( i = 0; i < xpSkill.length; i++ )
    {
        xp = xpSkill[i][1];
        if ( 0 < xp )
        {
            mySkills[i] = createSkillObject( xpSkill[i][0], xp);
        }
    }

    // append those defaulting from above
    for ( i = 0; i < xpSkill.length; i++ )
    {
        xp = xpSkill[i][1];
        if ( 0 == xp )
        {
            mySkills[i] = createSkillObject( xpSkill[i][0], xp);
        }
    }
}  // buildMySkills

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function findSkill( skill )
{
    var sk;
    var skillname;
    var specialty;
    sk = skill.split( "|" );
    skillname = sk[0];
    if ( 1 < sk.length )
    {
        specialty = sk[1];
    }

    for ( jj = 0; jj < mySkills.length; jj++ )
    {
        if ( mySkills[jj] != null
          && mySkills[jj].name == skillname )
        {
            if ( 1 < sk.length )
            {
                if ( mySkills[jj].note.substr(0,specialty.length) == specialty )
                {
                    return mySkills[jj];
                }
            }
            else
            {
                return mySkills[jj];
            }
        }
    }
    return null;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getSkillObject( skill )
{
    var obj;
    obj = findSkill( skill );
    if ( obj == null )
    {
        obj = createSkillObject( skill, 0 );
    }
    return obj;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function writeMySkill()
{
    buildMySkills();

    var skill, lastSkill;
    lastSkill = "";
    document.writeln ( "<tr>" );
    document.writeln ( "<th colspan=7>Skills" );
    document.writeln ( "<tr>" );
    document.writeln ( "<th class=column align=right style='FONT-FAMILY: Arial'>xp" );
    document.writeln ( "<th class=column align=left colspan=6 style='FONT-FAMILY: Arial'>" );
    xp = 0;
    for ( i = 0; i < mySkills.length; i++ )
    {
        xp += mySkills[i].xp;
    }
    document.writeln ( " (" + xp + ")" );
    for ( i = 0; i < mySkills.length; i++ )
    {
        document.write ( "<tr>" );
        document.writeln ( "<td class=inputcell style='VERTICAL-ALIGN: top'>" );
        document.write ( "<input NAME='xpSkill" + i + "' readonly class=readonly-rightalign TYPE=Text SIZE=3>" );
        document.frmMain["xpSkill" + String(i)].value = mySkills[i].xp;
        if ( -1 < mySkills[i].ndx )
        {
            document.writeln ( "<td style='VERTICAL-ALIGN: top'>" + mySkills[i].difficulty );
            document.writeln ( "<td style='VERTICAL-ALIGN: top'>" + mySkills[i].name );
            if ( mySkills[i].maneuver )
            {
                document.writeln ( "<td style='VERTICAL-ALIGN: top'>" + lastSkill );
                document.writeln ( "<td style='VERTICAL-ALIGN: top'>" + ( 0 <= mySkills[i].mod ? "+" + String(mySkills[i].mod) : String(mySkills[i].mod)) );
                document.writeln ( "<td>" );
            }
            else
            {
                document.writeln ( "<td style='VERTICAL-ALIGN: top'>" + mySkills[i].attr );
                document.writeln ( "<td style='VERTICAL-ALIGN: top'>" + ( 0 <= mySkills[i].mod ? "+" + String(mySkills[i].mod) : String(mySkills[i].mod)) );
                document.writeln ( "<td class=inputcell style='VERTICAL-ALIGN: top'>" );
                document.write ( "<input NAME='valSkill" + i + "' readonly class=readonly-rightalign TYPE=Text SIZE=3>" );
                document.frmMain["valSkill" + String(i)].value = String( mySkills[i].value );
                if ( !mySkills[i].derived )
                {
                    lastSkill = mySkills[i].name;
                }
            }
            if ( mySkills[i].note != null )
            {
                document.writeln ( "<td style='VERTICAL-ALIGN: top'>" + mySkills[i].note);
            }
            if ( mySkills[i].name == "Diplomacy" && 20 <= mySkills[i].value )
            {
                document.writeln ( "<tr><td colspan=2><td colspan=4>+2 on ALL reaction rolls" );
            }
            xpTotal += mySkills[i].xp;
        }
        else
        {
            document.writeln ( "<td>" );
            document.writeln ( "<td colspan=4>" + mySkills[i].name + "(not found)" );
            document.writeln ( "<td nowrap>" + mySkills[i].note);
        }
    }
}  // writeMySkill

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getSpellLevel( spell )
{
    var level, ndx, i, xp, mod, magery;
    // set default
    level = -1;
    ndx = ndxOfSpell( spell );
    if ( -1 < ndx )
    {
        // find spell
        for ( i = 0; i < xpSpells.length; i++ )
        {
            if ( spell == xpSpells[i][0] )
            {
                xp = xpSpells[i][1];
                mod = getSkillMod( xp, vSpells[ndx][nSpellDifficulty] );
                break;
            }
        }
        magery = document.frmMain["valMagery"].value;
        if ( magery != null )
        {
            mod += parseInt(magery);
        }
        level = getSkillValue( "IQ", mod );
    }
    return level;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function writeManeuvers()
{
    document.writeln ( "<form name='frmSpells'>" );
    document.writeln ( "<table BORDER=0 CELLSPACING=0 CELLPADDING=2>" );
    document.writeln ( "<tr>" );
    document.writeln ( "<th colspan=21>Maneuvers" );

    document.writeln ( "</table>" );
    document.writeln ( "</form>" );
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function writeSpell()
{
    if ( vSpells == null || vSpells == undefined )
    {
        initSpells();
    }
    var ndx, mod, val, magery;
    var xpSum;
    xpSum = 0;
    for ( var i = 0; i < xpSpells.length; i++ )
    {
        xpSum += xpSpells[i][1];
    }
    document.writeln ( "<form name='frmSpells'>" );
    document.writeln ( "<table BORDER=0 CELLSPACING=0 CELLPADDING=0>" );
    document.writeln ( "<tr>" );
    document.writeln ( "<th colspan=21>Spells" );
    document.writeln ( "<tr>" );
    document.writeln ( "<th class=column align=right style='FONT-FAMILY: Arial'>xp (" + String(xpSum) + ")" );
    document.writeln ( "<th class=hiddencolumn>MMMM<th class=column>" );  // difficulty
    document.writeln ( "<th class=hiddencolumn>M" );  // spacer
    document.writeln ( "<th class=column colspan=3 align=center>skill" );
    document.writeln ( "<th class=hiddencolumn>M<th class=column>class" );
    document.writeln ( "<th class=hiddencolumn>M<th class=column>Resistance" );
    document.writeln ( "<th class=hiddencolumn>M<th class=column>College     " );
    document.writeln ( "<th class=hiddencolumn>M<th class=column>CastingTime " );
    document.writeln ( "<th class=hiddencolumn>M<th class=column>Duration    " );
    document.writeln ( "<th class=hiddencolumn>M<th class=column>Energy      " );
    if ( vKnightsTemplar != null )
    {
        document.writeln ( "<th class=hiddencolumn>M<th class=column>rank" );
    }
    else
    {
        document.writeln ( "<th class=hiddencolumn>M<th class=column>Prerequisite" );
    }

    for ( var i = 0; i < xpSpells.length; i++ )
    {
        document.write ( "<tr>" );
        document.writeln ( "<td class=inputcell >" );
        document.write ( "<input NAME='xpSpell" + i + "' readonly class=readonly-rightalign TYPE=Text SIZE=3>" );
        document.frmSpells["xpSpell" + i].value = xpSpells[i][1];

        spell = xpSpells[i][0].split("|");
        ndx = ndxOfSpell( spell[0] );
        if ( -1 < ndx && ndx < vSpells.length )
        {
            document.writeln ( "<td>" + vSpells[ndx][nSpellDifficulty] );
            document.writeln ( "<td>" + xpSpells[i][0] );
            document.writeln ( "<td>" );  // spacer
            document.writeln ( "<td>" + "IQ" );
            mod = getSkillMod( parseInt(xpSpells[i][1]), vSpells[ndx][nSpellDifficulty] );
            document.writeln ( "<td>" + ( 0 <= mod ? "+" + String(mod) : String(mod)) );
            document.writeln ( "<td class=inputcell >" );
            document.write ( "<input NAME='valSpell" + i + "' readonly class=readonly-rightalign TYPE=Text SIZE=3>" );
            val = getSkillValue("IQ", mod);
            magery = document.frmMain["valMagery"];
            if ( magery != null )
            {
                val += parseInt(magery.value);
            }
            document.frmSpells["valSpell" + String(i) ].value = String( val );

            document.writeln ( "<td><td nowrap>" + vSpells[ndx][nSpellClass         ] );  // nSpellClass
            document.writeln ( "<td><td nowrap>" + vSpells[ndx][nSpellResistance    ] );  // nSpellResistance
            document.writeln ( "<td><td nowrap>" + vSpells[ndx][nSpellCollege       ] );  // nSpellCollege
            document.writeln ( "<td><td nowrap>" + vSpells[ndx][nSpellCastingTime   ] );  // nSpellCastingTime
            document.writeln ( "<td><td nowrap>" + vSpells[ndx][nSpellDuration      ] );  // nSpellDuration
            document.writeln ( "<td><td nowrap>" + vSpells[ndx][nSpellEnergy        ] );  // nSpellEnergy
            if ( vKnightsTemplar != null )
            {
                document.writeln ( "<td><td nowrap>" + getNameKnightTemplar(vSpells[ndx][nSpellRank]) )
                document.writeln ( "(" + vSpells[ndx][nSpellRank] + ")");  // rank
            }
            else
            {
                document.writeln ( "<td><td nowrap>" + vSpells[ndx][nSpellPrerequisite  ] );  // nSpellPrerequisite
            }

            xpTotal += parseInt(xpSpells[i][1]);
        }
        else
        {
            document.writeln ( "<td><td bgcolor=yellow>" + xpSpells[i][0] + "(not found)" );
        }
    }
    document.frmHeader["xpTotal"].value = String(xpTotal);
    document.writeln ( "</table>" );
    document.writeln ( "</form>" );
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function writeEquipment()
{
    var span;
    span = gShowMoney ? 6 : 5;
    document.writeln ( "<table BORDER=0 CELLSPACING=0 CELLPADDING=0>" );
    document.writeln ( "<form name='frmWealth'>" );
    document.writeln ( "<tr>" );
    document.writeln ( "<th colspan=" + String(span) + " style='BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid; BORDER-RIGHT: black 1px solid'>Equipment" );
    document.writeln ( "</form>" );
    writeArmor();
    writeWeapons( "frmWeapons" );
    document.writeln ( "</table>" );
    if ( myRangedWeapons != null )
    {
        writeRangedWeapons();
    }
    if ( myGuns != null )
    {
        writeGuns();
    }
}  // writeEquipment

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function writeArmor()
{
    document.writeln ( "<tr>" );
    var span;
    span = gShowMoney ? 6 : 5;
    document.writeln ( "<th colspan=" + String(span) + " class=column style='BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid; BORDER-RIGHT: black 1px solid'><b>Armor</b>" );

    writeArmorType( "Armor" );
    writeArmorType( "Shield" );

}  // writeArmor

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function findMyArmor( type )
{
    var iii;
    for ( iii = 0; iii < myArmor.length; iii++ )
    {
        armor = myArmor[iii][0].split("|");
        ndx = ndxOfArmor( armor[0] );
        if ( -1 < ndx )
        {
            if ( type == vArmor[ndx][1] )
            {
                break;
            }
        }
    }
    if ( myArmor.length <= iii )
    {
        iii = -1;
    }
    return iii;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function writeArmorType( type )
{
    var iii, armor, ndx, cost, lbs;
    var nPD, nDR;
    var j, mod, enchantment;
    armor = [ "(no " + type + ")" ];
    lbs = 0;
    cost = 0;
    nPD = 0;
    nDR = 0;
    iii = findMyArmor( type );
    if ( -1 < iii )
    {
        armor = myArmor[iii][0].split("|");
        ndx = ndxOfArmor( armor[0] );
        if ( -1 < ndx )
        {
            lbs = vArmor[ndx][3];
            cost = vArmor[ndx][2];
            nPD = vArmor[ndx][4];
            nDR = vArmor[ndx][5];
        }
    }

    // form
    document.writeln ( "<form name='frm" + type + "'>" );

    // header
    document.writeln ( "<tr>" );
    document.writeln ( "<th class=column align=right style='BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid;'>&nbsp;" );
    if ( gShowMoney )
    {
        document.writeln ( "$<th class=column align=right style='BORDER-TOP: black 1px solid;'>" );
        document.writeln ( "<input NAME='valCost' readonly class=readonly-rightalign TYPE=Text SIZE=6 value='0'>" );
    }
    document.writeln ( "<th class=column colspan=2 align=center style='BORDER-TOP: black 1px solid;'>description" );
    document.writeln ( "<th class=column align=right style='BORDER-TOP: black 1px solid;'>PD" );
    if ( type == "Armor" )
    {
        document.writeln ( "<th class=column align=right style='BORDER-TOP: black 1px solid;'>DR" );
    }

    document.writeln ( "<tr>" );
    document.writeln ( "<td align=right style='BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid'>" );
    document.write ( "<input NAME='valLbs" + type + "' readonly class=readonly-rightalign TYPE=Text SIZE=5>" );
    setFormValue( ("frm"+type), ("valLbs"+type), String(lbs) );
    if ( gShowMoney )
    {
        document.writeln ( "<td align=right style='BORDER-TOP: black 1px solid'>$" + String(cost) );
        incFormValue( ("frm"+type), "valCost", cost );
    }
    document.writeln ( "<td colspan=2 style='VERTICAL-ALIGN: middle; BORDER-TOP: black 1px solid; padding-left: 2;'>" + armor[0] );
    document.writeln ( "<td align=right style='BORDER-TOP: black 1px solid'>" );
    document.write ( "<input NAME='valPD" + type + "' readonly class=readonly-rightalign TYPE=Text SIZE=3>" );
    setFormValue( ("frm"+type), ("valPD"+type), String(nPD) );
    if ( type == "Armor" )
    {
        document.writeln ( "<td align=right style='BORDER-TOP: black 1px solid'>" );
        document.write ( "<input NAME='valDR" + type + "' readonly class=readonly-rightalign TYPE=Text SIZE=3>" );
        setFormValue( ("frm"+type), ("valDR"+type), String(nDR) );
    }
    if ( -1 < iii )
    {
        if ( 1 < armor.length )
        {
            document.writeln ( "<td>" );
            for ( j = 1; j < armor.length; j++ )
            {
                document.writeln ( armor[j] );
            }
        }
        for ( j = 0; j < myArmor[iii][1].length; j++ )
        {
            document.writeln ( "<tr>" );
            mod = myArmor[iii][1][j][1];
            enchantment = myArmor[iii][1][j][0];
            cost = costOfEnchantment( enchantment, mod );
            document.writeln ( "<td align=right style='BORDER-LEFT: black 1px solid'>&nbsp;" );
            if ( gShowMoney )
            {
                document.writeln ( "<td align=right>$" + String(cost) );
                incFormValue( ("frm"+type), "valCost", cost );
            }
            document.writeln ( "<td nowrap align=right style='padding-left: 2;'>" + (0 <= mod ? "+" : "") + String(mod) );
            document.writeln ( "<td nowrap align=left>: " + enchantment );
            switch ( enchantment )
            {
                case "Lighten Armour":
                    lbs = lbs * (1 + mod);
                    setFormValue( ("frm"+type), ("valLbs"+type), String(lbs) );
                    break;
                case "Fortify":
                    nDR += mod;
                    setFormValue( ("frm"+type), ("valDR"+type), String(nDR) );
                    break;
                case "Deflect":
                    nPD += mod;
                    setFormValue( ("frm"+type), ("valPD"+type), String(nPD) );
                    break;
            }
        }
    }
    document.writeln ( "</form>" );
}  // writeArmorType

//============================================================================

function getModeString( cellstyle, nPlusDam )
{
    var str, sDam;
    str = "";
    str +=  "<td align=right style='VERTICAL-ALIGN: top; " + cellstyle + "'>" + this.attack_type;
    str +=  "<td style='VERTICAL-ALIGN: top; " + cellstyle + "'>";
    sDam = getDam( valST, this.attack_type, this.dam_plus + nPlusDam );
    str +=  "<input readonly class=readonly-rightalign TYPE=Text SIZE=5 value=" + String(sDam) + ">";
    str +=  "<td align=center style='VERTICAL-ALIGN: top; " + cellstyle + "'>" + this.dam_type;  // type
    str +=  "<td align=center style='VERTICAL-ALIGN: top; " + cellstyle + "'>" + this.reach;  // reach
    return str;
}

//----------------------------------------------------------------------------
function WeaponMode( aMode )
{
    this.dam_type = aMode[0];
    this.attack_type = aMode[1];
    this.dam_plus = aMode[2];
    this.reach = aMode[3];
    this.sDam = "";
    this.getModeString = getModeString;
}

//----------------------------------------------------------------------------
function EnchantmentObj( weapon, enchantment )
{
    // properties
    this.enchantmant = enchantment[0];
    this.mod = enchantment[1];
    this.cost = 0;
    this.enchantdetail = this.enchantmant.split("|");
    this.name = this.enchantdetail[0];

    // constructor
    switch ( this.name )
    {
        case "Cheap":
            this.cost = weapon.cost * (-0.5);
            break;
        case "Fine":
            this.cost = weapon.cost;
            if ( 1 == this.mod )
            {
                this.cost *= 3;
            }
            else
            {
                if ( 2 == this.mod )
                {
                    this.cost *= 19;
                }
            }
            break;
        default:
            this.cost = costOfEnchantment( this.name, this.mod );
    }

    switch ( this.name )
    {
        case "Cheap":
        case "Fine":
        case "Puissance":
            for ( var mm=0; mm < weapon.modes.length; mm++ )
            {
                weapon.modes[mm].dam_plus += this.mod;
            }
            break;
        case "Accuracy":
            weapon.nSkill += this.mod;
            break;
        case "Weightlessness":
            this.lbs = 0;
            break;
    }
}  // EnchantmentObj

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getWeaponHeader( sFormName )
{
    var str;
    str = "";
    str += "<form name='" + sFormName + "'>";
    str += "<tr>";
    str += "<th class=column align=right style='BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid'>lbs";
    if ( gShowMoney )
    {
        str += "<th class=column align=center style='BORDER-TOP: black 1px solid;'>$";
    }
    var span;
    span = gShowMoney ? 9 : 8;
    str += "<th class=column colspan=" + String(span) + " align=left style='BORDER-TOP: black 1px solid; BORDER-RIGHT: black 1px solid'><b>Weapons</b>";


    var wt, cost;
    wt = 0;
    cost = 0;
    for ( var www = 0; www < myCharacter.weapons.length; www++ )
    {
        wt += myCharacter.weapons[www].lbs;
        cost += myCharacter.weapons[www].getCost();
    }
    str += "<tr>";
    str += "<th class=column align=right style='BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid;'>";
    str += "<input NAME='valLbsTotal' readonly class=readonly-rightalign TYPE=Text SIZE=5 value='" + String(wt) + "'>";
    if ( gShowMoney )
    {
        str += "<th class=column align=right style='BORDER-TOP: black 1px solid;'>";
        str += "<input NAME='valCost' readonly class=readonly-rightalign TYPE=Text SIZE=6 value='" + String(cost) + "'>";
    }

    str += "<th class=column align=right style='BORDER-TOP: black 1px solid'>&nbsp;";
    str += "<th class=column colspan=2 align=left style='BORDER-TOP: black 1px solid'>description";
    str += "<th class=column align=right style='BORDER-TOP: black 1px solid'>skill";
    str += "<th class=column colspan=3 align=center style='BORDER-TOP: black 1px solid'>dam";
    str += "<th class=column colspan=1 align=center style='BORDER-TOP: black 1px solid'>reach";
    str += "<th class=column colspan=1 align=center style='BORDER-TOP: black 1px solid; BORDER-RIGHT: black 1px solid'>notes";
    return str;
}  // getWeaponHeader

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getWeaponString( sFormName )
{
    var str;
    str = "";

    var cellsyle;
    cellstyle = "BORDER-TOP: black 1px solid";

    str +=  "<tr>";
    str +=  "<td align=right style='VERTICAL-ALIGN: middle; BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid'>";
    str +=  "<input name='lbs" + this.name + "' readonly class=readonly-rightalign TYPE=Text SIZE=5 value=" + String(this.lbs) + ">";
    setFormValue( sFormName, "lbs" + this.name, String(this.lbs) );
    if ( gShowMoney )
    {
        str +=  "<td align=right style='BORDER-TOP: black 1px solid'>";
        str +=  "$" + String(this.cost);
    }
    str += "<td class=hiddencolumn style='" + cellstyle + "'>&nbsp;";
    str += "<td colspan=1 style='VERTICAL-ALIGN: middle; BORDER-TOP: black 1px solid'>" + this.name;

    // debug
    //str += ", oSkill[" + String(this.oSkill.name) + "]";
    //str += ", value[" + String(this.oSkill.value) + "]";

    str +=  "<td style='" + cellstyle + "'>";
    str +=  "<input name='skill" + this.oSkill.name + "' readonly class=readonly-rightalign TYPE=Text SIZE=5 value=" + String(this.nSkill) + ">";
    setFormValue( sFormName, "skill" + this.name, String(this.nSkill) );

    str += this.getAttackModes(0);

    // enchantments
    for ( var j = 0; j < this.enchantments.length; j++ )
    {
        str +=  "<tr>";
        str +=  "<td align=right style='BORDER-LEFT: black 1px solid; VERTICAL-ALIGN: top'>&nbsp;";  // lbs
        if ( gShowMoney )
        {
            str +=  "<td align=right>$" + String(this.enchantments[j].cost);
        }
        switch ( this.enchantments[j].name )
        {
            case "Special" :
                // do nothing
                break;
            case "Bane" :
                var bane, nBaneDam, nBaneSkill;
                bane = this.enchantments[j].enchantdetail[1];
                nBaneDam = 0;
                nBaneSkill = 0;
                str +=  "<td nowrap colspan=2 align=left style='VERTICAL-ALIGN: top; BORDER-TOP: black 1px solid'>Bane: <b>" + bane + "</b><br>";
                for ( var jj = j; jj < this.enchantments.length
                   && (bane == this.enchantments[jj].enchantdetail[1])
                   && ("Bane" == this.enchantments[jj].name); jj++ )
                {
                    switch ( this.enchantments[jj].enchantdetail[2] )
                    {
                        case "Puissance":
                            nBaneDam = this.enchantments[jj].mod;
                            break;
                        case "Accuracy":
                            nBaneSkill = this.enchantments[jj].mod;
                            break;
                    }
                }
                str +=  "<td nowrap colspan=1 align=right style='VERTICAL-ALIGN: top; BORDER-TOP: black 1px solid'>";
                str +=  "<input name='skill" + this.oSkill.name + "' readonly class=readonly-rightalign TYPE=Text SIZE=5 value=" + String(this.nSkill + nBaneSkill) + ">";
                str += this.getAttackModes(nBaneDam);
                while ( j < this.enchantments.length
                   && (bane == this.enchantments[j].enchantdetail[1])
                   && ("Bane" == this.enchantments[j].name) )
                {
                    str += "<tr>";
                    str +=  "<td nowrap colspan=2 align=right style='VERTICAL-ALIGN: top; BORDER-LEFT: black 1px solid'>";
                    str +=  (0 <= this.enchantments[j].mod ? "+" : "") + String(this.enchantments[j].mod);
                    str +=  "<td nowrap align=left style='VERTICAL-ALIGN: top'>: " + this.enchantments[j].enchantdetail[2];
                    j++;
                }
                break;
            default:
                str +=  "<td nowrap align=right style='VERTICAL-ALIGN: top'>";
                str +=  (0 <= this.enchantments[j].mod ? "+" : "") + String(this.enchantments[j].mod);
                str +=  "<td nowrap align=left style='VERTICAL-ALIGN: top'>: " + this.enchantments[j].name;
                break;
        }

        if ( j < this.enchantments.length && 1 < this.enchantments[j].enchantdetail.length )
        {
            str +=  "<td colspan=14 style='VERTICAL-ALIGN: top'>";
            for ( jj = 1; jj < this.enchantments[j].enchantdetail.length; jj++ )
            {
                str += this.enchantments[j].enchantdetail[jj];
            }
        }
    }

    return str;
}  // getWeaponString

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getAttackModes( nPlus )
{
    var str;
    str = "";
    var objMode;
    for ( var mm = 0; mm < this.modes.length; mm++ )
    {
        objMode = this.modes[mm];
        if ( mm == 0 )
        {
            cellstyle = "BORDER-TOP: black 1px solid";
        }
        else
        {
            cellstyle = "";
        }
        if ( 0 < mm )
        {
            str +=  "<tr>";
            str +=  "<td style='BORDER-LEFT: black 1px solid'>&nbsp;";
            if ( gShowMoney )
            {
                str +=  "<td>";
            }
            str +=  "<td colspan=2>";
            str +=  "<td>";
        }

        str += objMode.getModeString( cellstyle, nPlus );

        if ( 0 == mm )
        {
            str +=  "<td nowrap colspan=12 style='VERTICAL-ALIGN: top'>";
            str +=  this.notes;  // notes
        }
    }
    return str;
}  // getAttackModes

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getWeaponFooter()
{
    var str;
    str = "";
    str += "</form>";
    return str;
}  // getWeaponFooter

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getCost()
{
    var cost;
    cost = this.cost;
    for ( var ee=0; ee < this.enchantments.length; ee++ )
    {
        cost += this.enchantments[ee].cost;
    }
    return cost;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getParry()
{
    if ( this.oSkill == null )
    {
        throw {msg:"getParry() not called as a weapon method", url:"gurpschar.js", lno:-1 };
    }
    var nParry = this.nSkill;
    switch ( this.oSkill.name )     // skill for 'weapon'
    {
        case "Fencing":
        case "Main-Gauche" :
        case "Brawling":
        case "Staff":
            nParry = Math.floor((nParry * 2.0) / 3.0);
            break;
        default:
            nParry = Math.floor(nParry / 2);
    }
    if ( this.name == "Knife (Large)"
        || this.name == "Knife (Small)"
        || this.name == "Dagger" )
    {
        nParry--;
    }
    if ( "Main-Gauche" == this.name )
    {
        nParry++;               // PD from basket-hilt
    }
    nParry += nCombatReflexes;
    return nParry;
}

//----------------------------------------------------------------------------
function WeaponObj()
{
    // base attributes
    this.name = "none";
    this.oSkill = null;
    this.cost = 0;
    this.lbs = 0;
    this.minST = 0;
    this.modes = new Array();
    this.notes = "";
    // custom attributes
    this.ndx = -1;
    this.nSkill = 0;
    this.enchantments = new Array();
    // functions
    this.getWeaponHeader = getWeaponHeader;
    this.getWeaponString = getWeaponString;
    this.getMountedWeaponString = getMountedWeaponString;
    this.getMountedWeaponDetail = getMountedWeaponDetail;
    this.getWeaponFooter = getWeaponFooter;
    this.getCost = getCost;
    this.getParry = getParry;
    this.getAttackModes = getAttackModes;
}  // WeaponObj

//----------------------------------------------------------------------------
function createWeaponObj( aWeapon )
{
    var weapon;
    weapon = new WeaponObj();
    weapon.name = aWeapon[0];

    // code
    // lookup everything
    weapon.ndx = ndxOfWeapon( weapon.name );
    if ( -1 < weapon.ndx )
    {
        weapon.oSkill = getSkillObject(vWeapons[weapon.ndx][1]);
        if ( weapon.oSkill != null )
        {
            weapon.nSkill = weapon.oSkill.value;
            weapon.cost = vWeapons[weapon.ndx][2];
            weapon.lbs = vWeapons[weapon.ndx][3];
            weapon.minST = vWeapons[weapon.ndx][4];
            weapon.notes = vWeapons[weapon.ndx][6];
            if ( 0 < vWeapons[weapon.ndx][5].length )
            {
                for ( var mm=0; mm < vWeapons[weapon.ndx][5].length; mm++ )
                {
                    weapon.modes[mm] = new WeaponMode( vWeapons[weapon.ndx][5][mm] );
                    if ( "Brawling" == weapon.oSkill.name )
                    {
                        weapon.modes[mm].dam_plus += Math.floor(weapon.oSkill.value / 10);
                    }
                }
            }
            if ( 0 < aWeapon[1].length )
            {
                for ( var ee=0; ee < aWeapon[1].length; ee++ )
                {
                    weapon.enchantments[ee] = new EnchantmentObj( weapon, aWeapon[1][ee] );
                }
            }
            if ( myCharacter.ST < weapon.minST )
            {
                weapon.nSkill -= (weapon.minST - myCharacter.ST);
            }
        }
        else
        {
            weapon.oSkill = new SkillObject(vWeapons[weapon.ndx][1], null );
            weapon.oSkill.name = "skill [" + vWeapons[weapon.ndx][1] + "] not found";
        }
    }
    return weapon;
}  // getWeaponObj

//============================================================================
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function writeWeapons( sFormName )
{
    var weapon;
    weapon = new WeaponObj();
    document.writeln ( weapon.getWeaponHeader(sFormName) );
    for ( var www = 0; www < myCharacter.weapons.length; www++ )
    {
        document.writeln ( myCharacter.weapons[www].getWeaponString(sFormName) );
    }
    document.writeln ( weapon.getWeaponFooter() );
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function writeRangedWeapons()
{
    var wt = 0;
    document.writeln ( "<table BORDER=0 CELLSPACING=0 CELLPADDING=0>" );
    document.writeln ( "<form name='frmRangedWeapons'>" );
    document.writeln ( "<tr>" );
    var span = gShowMoney ? 2 : 1;
    document.writeln ( "<th class=column align=right style='BORDER-LEFT: black 1px solid; BORDER-TOP: black 1px solid; '>lbs" );
    if ( gShowMoney )
    {
        document.writeln ( "<th class=column align=center style='BORDER-TOP: black 1px solid;'>$" );
    }
    document.writeln ( "<th class=column colspan=19 align=left style='BORDER-TOP: black 1px solid; BORDER-RIGHT: black 1px solid;'><b>RangedWeapons</b>" );

    document.writeln ( "<tr>" );
    document.writeln ( "<th class=column align=right style='BORDER-LEFT: black 1px solid;'>" );
    document.writeln ( "<input NAME='valLbsTotal' readonly class=readonly-rightalign TYPE=Text SIZE=5 value='0'>" );
    if ( gShowMoney )
    {
        document.writeln ( "<th class=column align=right>" );
        document.writeln ( "<input NAME='valCost' readonly class=readonly-rightalign TYPE=Text SIZE=6 value='0'>" );
    }
    document.writeln ( "<th class=column align=left   style='PADDING-LEFT:2; PADDING-RIGHT:2;'>" );
    document.writeln ( "<th class=column align=right  style='PADDING-LEFT:2; PADDING-RIGHT:2;'>skill" );
    document.writeln ( "<th class=column align=center style='PADDING-LEFT:2; PADDING-RIGHT:2;'>SS" );
    document.writeln ( "<th class=column align=center style='PADDING-LEFT:2; PADDING-RIGHT:2;'>Acc" );
    document.writeln ( "<th class=column align=center style='PADDING-LEFT:2; PADDING-RIGHT:2;'>eST" );
    //document.writeln ( "<th class=column align=center style='PADDING-LEFT:2; PADDING-RIGHT:2;'>type" );
    //document.writeln ( "<th class=column align=left   style='PADDING-LEFT:2; PADDING-RIGHT:2;'>plus" );
    document.writeln ( "<th class=column align=right  style='PADDING-LEFT:2; PADDING-RIGHT:2;' colspan=2>damage" );
    //document.writeln ( "<th class=column align=center style='PADDING-LEFT:2; PADDING-RIGHT:2;'>type" );
    document.writeln ( "<th class=column align=center style='PADDING-LEFT:2; PADDING-RIGHT:2;'>Move" );
    document.writeln ( "<th class=column align=center style='PADDING-LEFT:2; PADDING-RIGHT:2;'>Range" );
    document.writeln ( "<th class=column align=left style='BORDER-RIGHT: black 1px solid'>notes" );
    for ( var i = 0; i < myRangedWeapons.length; i++ )
    {
        if ( myRangedWeapons[i].__proto__ == Bow.prototype )
        {
            document.writeln ( myRangedWeapons[i].getBowTableRow() );
            wt += myRangedWeapons[i].lbs;
            document.frmRangedWeapons["valLbsTotal"].value = formatfloat( wt, 1 );
        }
        else
        {
            var myBow = getRangedWeaponFromListItem( myRangedWeapons[i] )
            if ( myBow != null )
            {
                document.writeln ( myBow.getRangedWeaponTableRow() );
                wt += myBow.lbs;
                document.frmRangedWeapons["valLbsTotal"].value = formatfloat( wt, 1 );
            }
            else
            {
                document.writeln ( "<tr>" );
                document.writeln ( "<td class=widecolumn>" + myRangedWeapons[i][0] + " (not found)" );
            }
        }
    }
    document.writeln ( "</form>" );
    document.writeln ( "</table>" );
}  // writeRangedWeapons

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getRangedWeaponFromListItem( item )
{
    var myBow = findRangedWeapon( item[0] );
    if ( myBow != null )
    {
        myBow.skill = getSkillObject(myBow.skillname);
        myBow.enchantments = item[1];
        // enchantments
        if ( myBow.enchantments != null )
        {
            for ( var j = 0; j < myBow.enchantments.length; j++ )
            {
                mod = myBow.enchantments[j][1];
                enchantlist = myBow.enchantments[j][0].split("|");
                enchantment = enchantlist[0];
                switch ( enchantment )
                {
                    case "Fine":
                    case "Puissance":
                        myBow.plus += mod;
                        break;
                    case "Accuracy":
                        //myBow.skill.value += mod;
                        break;
                }
                switch ( enchantment )
                {
                    case "Fine":
                        myBow.cost *= ( 1 == mod ) ? 3 : ( 2 == mod ) ? 19 : 1;
                        break;
                    default:
                        myBow.cost += costOfEnchantment( enchantment, mod );
                }
            }
        }
    }
    return myBow;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function writeGuns()
{
    var gun, ndx, cost, lbs, wt;
    var nSkill;
    var i;
    wt = 0;
    document.writeln ( "<table BORDER=0 CELLSPACING=0 CELLPADDING=0>" );
    document.writeln ( "<form name='frmGuns'>" );
    document.writeln ( "<tr>" );
    var span;
    span = gShowMoney ? 2 : 1;
    document.writeln ( "<th class=column align=right style='BORDER-LEFT: black 1px solid; BORDER-TOP: black 1px solid; '>lbs" );
    if ( gShowMoney )
    {
        document.writeln ( "<th class=column align=center style='BORDER-TOP: black 1px solid;'>$" );
    }
    document.writeln ( "<th class=hiddencolumn style='BORDER-TOP: black 1px solid;'>M" );  // spacer
    document.writeln ( "<th class=column colspan=20 align=left style='BORDER-TOP: black 1px solid; BORDER-RIGHT: black 1px solid'><b>Guns</b>" );

    document.writeln ( "<tr>" );
    document.writeln ( "<th class=column align=right style='BORDER-LEFT: black 1px solid;'>" );
    document.write ( "<input NAME='valLbsTotal' readonly class=readonly-rightalign TYPE=Text SIZE=5 value='0'>" );
    if ( gShowMoney )
    {
        document.writeln ( "<th class=column align=right>" );
        document.writeln ( "<input NAME='valCost' readonly class=readonly-rightalign TYPE=Text SIZE=6 value='0'>" );
    }
    document.writeln ( "<th class=hiddencolumn>M" );  // spacer
    document.writeln ( "<th class=column align=left>description" );
    document.writeln ( "<th class=hiddencolumn>M" );  // spacer
    document.writeln ( "<th class=column align=right>skill" );
    document.writeln ( "<th class=hiddencolumn>M" );  // spacer
    document.writeln ( "<th class=column align=center>dam" );
    document.writeln ( "<th class=hiddencolumn>M" );  // spacer
    document.writeln ( "<th class=column align=center>type" );
    document.writeln ( "<th class=hiddencolumn>M" );  // spacer
    document.writeln ( "<th class=column align=center>SS" );
    document.writeln ( "<th class=hiddencolumn>M" );  // spacer
    document.writeln ( "<th class=column align=center>Acc" );
    document.writeln ( "<th class=hiddencolumn>M" );  // spacer
    document.writeln ( "<th class=column align=center>ROF" );
    document.writeln ( "<th class=hiddencolumn>M" );  // spacer
    document.writeln ( "<th class=column align=center>Shots" );
    document.writeln ( "<th class=hiddencolumn>M" );  // spacer
    document.writeln ( "<th class=column align=center>recoil" );
    document.writeln ( "<th class=hiddencolumn>M" );  // spacer
    document.writeln ( "<th class=column colspan=2 align=center style='BORDER-RIGHT: black 1px solid'>range" );
    for ( i = 0; i < myGuns.length; i++ )
    {

        gun = myGuns[i][0];
        ndx = ndxOfTable( gun, vGuns );
        if ( -1 < ndx )
        {
            cost = vGuns[ndx][nGunsCost];
            lbs = vGuns[ndx][nGunsLbs];

            document.writeln ( "<tr>" );
            document.writeln ( "<td align=right style='BORDER-LEFT: black 1px solid'>" );
            document.write ( "<input NAME='valLbsGun" + String(i) + "' readonly class=readonly-rightalign TYPE=Text SIZE=5>" );
            document.frmGuns["valLbsGun" + String(i)].value = String(lbs);
            if ( gShowMoney )
            {
                document.writeln ( "<td align=right>$" + String(cost) );
                incFormValue( "frmGuns", "valCost", cost );
            }
            document.writeln ( "<td>" );
            document.writeln ( "<td colspan=2>" + gun );
            document.writeln ( "<td>" );
            nSkill = getSkillObject(vGuns[ndx][nGunsSkill]).value;
            document.write ( "<input NAME='valGunSkill" + String(i) + "' readonly class=readonly-rightalign TYPE=Text SIZE=5>" );
            document.frmGuns["valGunSkill" + String(i)].value = String(nSkill);
            document.writeln ( "<td>" );
            document.writeln ( "<td align=center>" + vGuns[ndx][nGunsDam] );
            document.writeln ( "<td>" );
            document.writeln ( "<td align=center>" + vGuns[ndx][nGunsType] );
            document.writeln ( "<td>" );
            document.writeln ( "<td align=center>" + vGuns[ndx][nGunsSS] );
            document.writeln ( "<td>" );
            document.writeln ( "<td align=center>+" + vGuns[ndx][nGunsAcc] );
            document.writeln ( "<td>" );
            document.writeln ( "<td align=center>" + vGuns[ndx][nGunsROF] );
            document.writeln ( "<td>" );
            document.writeln ( "<td align=center>" + vGuns[ndx][nGunsShots] );
            document.writeln ( "<td>" );
            document.writeln ( "<td align=center>" + vGuns[ndx][nGunsRecoil] );
            document.writeln ( "<td>" );
            document.writeln ( "<td align=center style='BORDER-RIGHT: black 1px solid'>" + vGuns[ndx][nGunsHalfDamRange] + "-" + vGuns[ndx][nGunsMaxRange] );
            wt += lbs;
            document.frmGuns["valLbsTotal"].value = String( wt );
        }
        else
        {
            document.writeln ( "<tr>" );
            document.writeln ( "<td>" + myGuns[i][0] + " (not found)" );
        }
    }
    document.writeln ( "</form>" );
    document.writeln ( "</table>" );
}  // writeGuns

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getBagLbs( bag )
{
    var item;
    var wt;
    wt = 0;
    if ( bag != null )
    {
        for ( var i = 0; i < bag.length; i++ )
        {
            if ( bag[i].__proto__ == BagItem.prototype )
            {
                item = bag[i];
            }
            else
            {
                item = BagItemFromArray( bag[i] );
            }
            wt += item.lbs;
        }
    }
    return wt;
}  // getBagLbs

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getBagCost( bag )
{
    var item;
    var cost;
    cost = 0;
    if ( bag != null )
    {
        for ( var i = 0; i < bag.length; i++ )
        {
            if ( bag[i].__proto__ == BagItem.prototype )
            {
                item = bag[i];
            }
            else
            {
                item = BagItemFromArray( bag[i] );
            }
            cost += item.cost;
        }
    }
    return cost;
}  // getBagCost

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getBagExpenses( bag )
{
    var item;
    var cost;
    cost = 0;
    if ( bag != null )
    {
        for ( var i = 0; i < bag.length; i++ )
        {
            if ( bag[i].__proto__ == BagItem.prototype )
            {
                item = bag[i];
            }
            else
            {
                item = BagItemFromArray( bag[i] );
            }
            if ( item.cost < 0 )
            {
                cost += item.cost;
            }
        }
    }
    return 0 - cost;
}  // getBagExpenses

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function BagItem( name, cost, lbs, notes )
{
    this.name = name;
    this.cost = cost;
    this.lbs = lbs;
    this.notes = notes;
    this.getBagItemRowString = getBagItemRowString;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function BagItemFromArray( ary )
{
    var bag = new BagItem( ary[0], ary[1], ary[2] );
    if ( ary[3] != null && ary[3] != undefined )
    {
        bag.notes = ary[3];
    }
    return bag;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getBagItemRowString()
{
    var str = "";
    str += "<tr>";
    str += "<td align=right style='BORDER-LEFT: black 1px solid; VERTICAL-ALIGN: top'>";
    str += String(this.lbs);
    if ( gShowMoney )
    {
        str += "<td align=right style='padding-left: 5px;'>";
        if ( 0 == this.cost )
        {
            str += "~";
        }
        else
        {
            str += "$" + String(this.cost);
        }
        incFormValue( "frmWealth", "valCost", String(this.cost) );
    }
    str += "<td style='VERTICAL-ALIGN: top; BORDER-RIGHT: black 1px solid;  padding-left: 5px;'>" + this.name;
    if ( this.notes != null && this.notes != undefined )
    {
        str += "<td>" + this.notes;
    }
    return str;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function writeBag( bag, name, bShowSummary, bNewTD )
{
    /*
    if ( bag.name != null )
    {
        //name = bag.name;
    }
     */
    if ( bNewTD == true )
    {
        document.writeln ( "<td style='VERTICAL-ALIGN: top'>" );
    }
    document.writeln( getBagString( bag, name, bShowSummary ) );
}  // writeBag

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getBagString( bag, name, bShowSummary )
{
    var str;
    str = "";
    if ( bag != null && 0 < bag.length )
    {
        if ( bag != myIncome && myIncome != null && myIncome != undefined )
        {
            myIncome[myIncome.length] = [ name, 0-getBagCost(bag), 0 ];
        }

        var wt;
        wt = 0;
        var totalcost;
        totalcost = 0;
        str += "<table BORDER=0 CELLSPACING=0 CELLPADDING=1>";
        str += "<tr>";
        str += "<th class=column align=right style='BORDER-TOP: black 1px solid; BORDER-BOTTOM: black 1px solid; BORDER-LEFT: black 1px solid;'>lbs";
        if ( gShowMoney )
        {
            str += "<th class=column align=right style='BORDER-TOP: black 1px solid; BORDER-BOTTOM: black 1px solid;    '>cost";
        }
        var sTmp = (bag.name == null || bag.name == undefined ) ? name : bag.name;
        str += "<th class=column align=left style='BORDER-TOP: black 1px solid; BORDER-BOTTOM: black 1px solid; BORDER-RIGHT: black 1px solid; padding-left: 5px;'><b>" + sTmp + "</b>";
        var item;
        for ( var i = 0; i < bag.length; i++ )
        {
            if ( bag[i].__proto__ == BagItem.prototype )
            {
                item = bag[i];
            }
            else
            {
                item = BagItemFromArray( bag[i] );
            }
            str += item.getBagItemRowString();
            wt += item.lbs;
            totalcost += parseFloat(item.cost);
        }
        wt = Math.floor( wt * 100 ) / 100;
        if ( bShowSummary == null || bShowSummary == true )
        {
            str += "<tr>";
            str += "<th class=column align=right style='BORDER-TOP: black 1px solid; BORDER-BOTTOM: black 1px solid; BORDER-LEFT: black 1px solid;'>" + String(wt);
            if ( gShowMoney )
            {
                totalcost = Math.floor( totalcost * 100 ) / 100;
                str += "<th class=column align=right style='BORDER-TOP: black 1px solid; BORDER-BOTTOM: black 1px solid;'>$" + String(totalcost);
            }
            str += "<th class=column align=left style='BORDER-TOP: black 1px solid; BORDER-BOTTOM: black 1px solid; BORDER-RIGHT: black 1px solid; padding-left: 5px;'>total";
        }
        str += "</table>";
    }
    return str;
}  // getBagString

//----------------------------------------------------------------------------
function findInBag( stuff, bag )
{
    var found = false;
    if ( bag != null && 0 < bag.length )
    {
        var item;
        for ( var i = 0; i < bag.length; i++ )
        {
            if ( bag[i].__proto__ == BagItem.prototype )
            {
                item = bag[i];
            }
            else
            {
                item = BagItemFromArray( bag[i] );
            }
            if ( item.name == stuff )
            {
                found = true;
                break;
            }
        }
    }
    return found;
}

//============================================================================
// Horse Object
//============================================================================
var vHorses;
//============================================================================

//----------------------------------------------------------------------------
function initHorses()
{
    vHorses = new Array();
    vHorses[vHorses.length] = new Horse( "Man",            12, 12,10, 12, 12,  6,  100,  160, 0, 0 );
    vHorses[vHorses.length] = new Horse( "Dog",             8, 13, 5, 14, 10,  8,  100,   80, 0, 0 );
    vHorses[vHorses.length] = new Horse( "Donkey",         25, 10, 4, 13, 13,  8, 1000,  500, 1, 1 );
    vHorses[vHorses.length] = new Horse( "Small Mule",     30, 10, 4, 14, 14,  8, 1000,  800, 1, 1 );
    vHorses[vHorses.length] = new Horse( "Large Mule",     40, 10, 4, 14, 14,  9, 2000, 1400, 1, 1 );
    vHorses[vHorses.length] = new Horse( "Ox",             80,  8, 4, 17, 17,  8, 1500, 2500, 1, 1 );
    vHorses[vHorses.length] = new Horse( "Pony",           30, 10, 4, 13, 13, 13, 1500,  800, 1, 1 );
    vHorses[vHorses.length] = new Horse( "Racehorse",      32,  9, 4, 13, 13, 18, 4000, 1100, 1, 1 );
    vHorses[vHorses.length] = new Horse( "Saddle Horse",   35,  9, 4, 14, 14, 12, 1200, 1200, 1, 1 );
    vHorses[vHorses.length] = new Horse( "Cavalry Horse",  40,  9, 4, 15, 15, 16, 4000, 1400, 1, 1 );
    vHorses[vHorses.length] = new Horse( "Heavy Warhorse", 50,  9, 4, 16, 16, 15, 5000, 1900, 1, 1 );
    vHorses[vHorses.length] = new Horse( "Draft Horse",    60,  9, 4, 16, 16, 12, 2000, 2000, 1, 1 );
    vHorses[vHorses.length] = new Horse( "Onager",         25, 10, 4, 13, 13,  8, 1000,  500, 1, 1 );
    vHorses[vHorses.length] = new Horse( "Camel",          40,  9, 4, 15, 15, 10, 1500, 1400, 1, 1 );
}

//----------------------------------------------------------------------------
function createHorse( type )
{
    if ( vHorses == null || vHorses == undefined )
    {
        initHorses();
    }
    for ( var ndx = 0; ndx < vHorses.length; ndx++ )
    {
        if ( vHorses[ndx].name == type  )
        {
            return vHorses[ndx].CloneHorse();
            //return vHorses[ndx];
        }
    }
    return null;
}  // createHorse

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function Horse( name, st, dx, iq, ht, hits, move, cost, wt, pd, dr )
{
    this.name = name;
    this.ST = st;
    this.DX = dx;
    this.IQ = iq;
    this.HT = ht;
    this.hits = hits;
    this.move = move;
    this.cost = cost;
    this.wt = wt;
    this.PD = pd;
    this.DR = dr;
    this.training = 0;
    this.equipment = null;
    this.CloneHorse = CloneHorse;
    this.getHorseEncumbranceObject = getHorseEncumbranceObject;
    this.getHorseStr  = getHorseStr;
    this.getHorseAttrStr = getHorseAttrStr;
    this.getMountedAttack = getMountedAttack;
    this.addEquipment = addEquipment;
    this.setRidingEquipment = setRidingEquipment;
    this.getHorsesTableRow = getHorsesTableRow;
}  // Horse

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function CloneHorse()
{
    var horse = new Horse( this.name, this.ST, this.DX, this.IQ, this.HT, this.hits, this.move, this.cost, this.wt, this.PD, this.DR );
    horse.training = this.training;
    return horse;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getHorseEncumbranceObject( st, lbs )
{
    var encumbrance = {name:"none",mod:0,move:null};
    if ( (this.ST * 2) < lbs ) encumbrance = {name:"light",mod:2,move:null};
    if ( (this.ST * 6) < lbs ) encumbrance = {name:"medium",mod:4,move:null};
    if ( (this.ST * 10) < lbs ) encumbrance = {name:"heavy",mod:6,move:null};
    if ( (this.ST * 15) < lbs ) encumbrance = {name:"extra-heavy",mod:8,move:null};
    if ( (this.ST * 20) < lbs ) encumbrance = {name:"maximum",mod:null,move:1};
    if ( (this.ST * 30) < lbs ) encumbrance = {name:"won't move",mod:null,move:0};
    return encumbrance;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getHorseStr()
{
    var str;
    str = "";
    str += "<table>";
    str += "<tr><th colspan=4>" + this.name;
    str += "<tr>";

    str += "<td style='VERTICAL-ALIGN: top'>";
    str += this.getHorseAttrStr();

    str += "<td style='VERTICAL-ALIGN: top'>";
    str += getBagString( this.equipment, "equipment" );
    var lbs;
    lbs = getBagLbs( this.equipment );
    encumbrance = "none";
    if ( (this.ST * 2) < lbs ) encumbrance = "light";
    if ( (this.ST * 6) < lbs ) encumbrance = "medium";
    if ( (this.ST * 10) < lbs ) encumbrance = "heavy";
    str += "encumbrance: <b>" + encumbrance + "</b>";

    str += "<td style='VERTICAL-ALIGN: top'>";
    str += "<span id='iMountedAttacks'></span>";

    str += "</table>";
    return str;
}  // getHorseStr

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getHorseAttrStr()
{
    var str;
    str = "";
    str += "<table>";
    str += "<tr><td align=right>" + String(this.ST) + "<td>ST";
    str += "<tr><td align=right>" + String(this.DX) + "<td>DX";
    str += "<tr><td align=right>" + String(this.IQ) + "<td>IQ";
    str += "<tr><td align=right>" + String(this.HT) + "<td>HT";
    str += "</table>";

    str += "<table BORDER=0 CELLSPACING=0 CELLPADDING=0>";
    str += "<tr>";
    str += "<th class=column>Move";
    str += "<th class=column align=center>encumbrance";
    str += "<th class=column align=right>lbs";

    str += "<tr>";
    str += "<td align=right>" + String(this.move);
    str += "<td align=center>none";
    str += "<td align=right>0-" + String(this.ST * 2);

    str += "<tr>";
    str += "<td align=right>" + String(this.move - 2);
    str += "<td align=center>light";
    str += "<td align=right>" + String(this.ST * 2 - 1) + "-" + String(this.ST * 6);

    str += "<tr>";
    str += "<td align=right>" + String(this.move - 4);
    str += "<td align=center>medium";
    str += "<td align=right>" + String(this.ST * 6 - 1) + "-" + String(this.ST * 10);

    str += "</table>";
    if ( 0 < this.training )
    {
        str += "<p>";
        str += "training +" + String(this.training) + " to riding skill";
    }
    return str;
}  // getHorseAttrStr

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getMountedAttack( sFormName, weapon )
{
    var str;
    str = "";
    str += "<table BORDER=0 CELLSPACING=0 CELLPADDING=0>";
    str += "<tr style='vertical-align: bottom'>";
    str += "<th class=column>weapon";
    str += "<th class=hiddencolumn>M";
    str += "<th class=column>relative<br>move";
    //str += "<th class=hiddencolumn>M";
    str += "<th class=column align=right>skill";
    str += "<th class=hiddencolumn>M";
    str += "<th class=column colspan=5>dam";
    str += "<th class=hiddencolumn>M";
    str += "<th class=column>notes";

    if ( findInBag( "Lance", this.equipment ) )
    {
        //---- Lance -------------------------------------------------------------
        var cellstyle = "BORDER-TOP: black 1px solid";
        str += "<tr>";
        str += "<td rowspan=3 style='vertical-align=top; BORDER-TOP: black 1px solid;'>Lance";
        str += "<td rowspan=3 class=hiddencolumn style='BORDER-TOP: black 1px solid;'>M";

        var lance = createWeaponObj( ["Lance", [] ] );

        var riding, nSkill;
        riding = getSkillObject( "Riding", 0 );
        nSkill = ((riding.value + this.training) < lance.oSkill.value) ? (riding.value + this.training) : lance.oSkill.value;

        // move
        str += "<td style='BORDER-TOP: black 1px solid;'>&le;5";
        //str += "<td rowspan=3 class=hiddencolumn style='BORDER-TOP: black 1px solid;'>M";

        // skill
        str += "<td rowspan=3 style='TEXT-ALIGN:right; VERTICAL-ALIGN:top; BORDER-TOP: black 1px solid;'>";
        str += String(nSkill);
        str += "<td rowspan=3 class=hiddencolumn style='BORDER-TOP: black 1px solid;'>M";

        var objMode = lance.modes[0];
        str += "<td align=right style='" + cellstyle + "'>";
        str += objMode.attack_type;
        str += "<td class=hiddencolumn style='" + cellstyle + "'>M";

        str += "<td style='TEXT-ALIGN: right; " + cellstyle + "'>";
        nDam = getDam( Math.floor(this.ST / 4), objMode.attack_type, objMode.dam_plus );
        str += String(nDam);
        str += "<td class=hiddencolumn style='" + cellstyle + "'>M";
        str += "<td style='" + cellstyle + "'>" + objMode.dam_type;  // type
        str += "<td class=hiddencolumn style='" + cellstyle + "'>M";
        str += "<td nowrap colspan=12 style='VERTICAL-ALIGN: top; " + cellstyle + "'>";
        str += lance.notes;  // notes

        cellstyle = "";

        str += "<tr>";
        str += "<td>6-10";
        str += "<td colspan=2>";
        str += "<td style='TEXT-ALIGN: right;'>";
        nDam = getDam( Math.floor(this.ST / 2), objMode.attack_type, objMode.dam_plus );
        str += String(nDam);

        str += "<tr>";
        str += "<td>11+";
        str += "<td colspan=2>";
        str += "<td style='TEXT-ALIGN: right;'>";
        nDam = getDam( Math.floor(this.ST), objMode.attack_type, objMode.dam_plus );
        str += String(nDam);
    } // Lance

    // weapon
    if ( weapon != null )
    {
        str += weapon.getMountedWeaponString( this, sFormName )
    }

    str += "</table>";
    return str;
}  // getMountedAttack

//----------------------------------------------------------------------------
// WeaponObj.getMountedWeaponString
//----------------------------------------------------------------------------
function getMountedWeaponString( horse, sFormName )
{
    var str;
    str = "";
    str += this.getMountedWeaponDetail( horse, sFormName, this.name, 0, 0 );
    // bane
    if ( this.enchantments != null )
    {
        for ( var ee = 0; ee < this.enchantments.length; ee++ )
        {
            if ( this.enchantments[ee].name == "Bane" )
            {
                var bane, nBaneDam, nBaneSkill;
                bane = this.enchantments[ee].enchantdetail[1];
                nBaneDam = 0;
                nBaneSkill = 0;
                for ( var eeee = ee; eeee < this.enchantments.length
                   && (bane == this.enchantments[eeee].enchantdetail[1])
                   && ("Bane" == this.enchantments[eeee].name); eeee++ )
                {
                    switch ( this.enchantments[eeee].enchantdetail[2] )
                    {
                        case "Puissance":
                            nBaneDam = this.enchantments[eeee].mod;
                            break;
                        case "Accuracy":
                            nBaneSkill = this.enchantments[eeee].mod;
                            break;
                    }
                }
                str += this.getMountedWeaponDetail( horse, sFormName, bane, nBaneSkill, nBaneDam );
                break;
            } // if 'bane'
        }
    }

    return str;
}  // WeaponObj.getMountedWeaponString

//----------------------------------------------------------------------------
// WeaponObj.getMountedWeaponDetail
//----------------------------------------------------------------------------
function getMountedWeaponDetail( horse, sFormName, sTitle, nSkillMod, nPlusDam )
{
    var str;
    str = "";

    var cellsyle;
    cellstyle = "BORDER-TOP: black 1px solid";

    str +=  "<tr>";
    str += "<td rowspan=" + String(this.modes.length + 1) + " style='VERTICAL-ALIGN: top; BORDER-TOP: black 1px solid'>" + sTitle;
    str += "<td rowspan=" + String(this.modes.length + 1) + " class=hiddencolumn style='BORDER-TOP: black 1px solid;'>M";

    // slow movement
    // move
    str += "<td style='BORDER-TOP: black 1px solid;'>&le;5";

    // skill
    var nSkill = this.nSkill + nSkillMod;
    var riding = findSkill("Riding");
    var riding = getSkillObject( "Riding", 0 );
    nSkill = ((riding.value + horse.training) < nSkill) ? (riding.value + horse.training) : nSkill;

    str += "<td rowspan=" + String(this.modes.length) + " style='TEXT-ALIGN:right; VERTICAL-ALIGN:top; BORDER-TOP: black 1px solid;'>";
    str += String(nSkill);
    str += "<td rowspan=" + String(this.modes.length + 1) + " class=hiddencolumn style='BORDER-TOP: black 1px solid;'>M";

    var objMode, nDam;
    for ( var mm = 0; mm < this.modes.length; mm++ )
    {
        objMode = this.modes[mm];
        if ( mm == 0 )
        {
            cellstyle = "BORDER-TOP: black 1px solid";
        }
        else
        {
            cellstyle = "";
        }

        if ( 0 < mm )
        {
            str +=  "<tr>";
            str +=  "<td colspan=4 align=right style='" + cellstyle + "'>";
        }
        else
        {
            str +=  "<td align=right style='" + cellstyle + "'>";
        }
        str += objMode.attack_type;
        str += "<td class=hiddencolumn style='" + cellstyle + "'>M";

        str +=  "<td style='TEXT-ALIGN: right; " + cellstyle + "'>";
        nDam = getDam( valST, objMode.attack_type, objMode.dam_plus + nPlusDam );
        str += String(nDam);
        str += "<td class=hiddencolumn style='" + cellstyle + "'>M";
        str +=  "<td style='" + cellstyle + "'>" + objMode.dam_type;  // type
        if ( 0 == mm )
        {
            str += "<td class=hiddencolumn style='" + cellstyle + "'>M";
            str +=  "<td nowrap colspan=12 style='VERTICAL-ALIGN: top; " + cellstyle + "'>";
            str +=  this.notes;  // notes
        }
    }

    // horse move 6+
    str += "<tr>";
    str += "<td>6+";

    // skill
    nSkill -= 2;
    var sk = findSkill( "Mounted Combat|" + this.oSkill.name );
    if ( sk != null )
    {
        nSkill += sk.mod;
    }
    str += "<td style='TEXT-ALIGN:right; VERTICAL-ALIGN=top;'>";
    str += String(nSkill);

    for ( var mm = 0; mm < this.modes.length; mm++ )
    {
        objMode = this.modes[mm];
        if ( objMode.attack_type == "sw" )
        {
            str +=  "<td align=right style='" + cellstyle + "'>";
            str += objMode.attack_type;
            str += "<td class=hiddencolumn style='" + cellstyle + "'>M";
            str +=  "<td style='" + cellstyle + "'>";
            nDam = getDam( valST, objMode.attack_type, objMode.dam_plus + nPlusDam + 2 );
            str += String(nDam);
            str += "<td class=hiddencolumn style='" + cellstyle + "'>M";
            str +=  "<td style='" + cellstyle + "'>" + objMode.dam_type;
            str += "<td class=hiddencolumn style='" + cellstyle + "'>M";
        }
    }

    return str;
}  // getMountedWeaponDetail

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function addEquipment( item )
{
    if ( item != null )
    {
        if ( this.equipment == null )
        {
            this.equipment = new Array();
            this.equipment[0] = item;
        }
        else
        {
            this.equipment[this.equipment.length] = item;
        }
    }
    return item;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function setRidingEquipment()
{
    this.addEquipment( new BagItem(  this.name, this.cost, 0 ) );
    this.addEquipment( new BagItem(  "rider", 0, myCharacter.wt ) );
    this.addEquipment( new BagItem(  "Armor & Shield", 0, lbsArmor + lbsShield ) );
    this.addEquipment( new BagItem(  "weapons (includes pouch)", 0, lbsWeapons ) );
    this.addEquipment( new BagItem(  "Saddle, bit and bridle", 0, 20 ) );
    this.addEquipment( new BagItem(  "saddlebags", 0, 10 ) );
    this.addEquipment( new BagItem(  "stuff in saddlebags", 0, getBagLbs(mySaddlebags) ) );
    this.addEquipment( new BagItem(  "pack (in saddlebags)", 0, lbsPack ) );
}  // setRidingEquipment

//----------------------------------------------------------------------------
function getHorseTable()
{
    var str = "<table BORDER=1 CELLSPACING=0 CELLPADDING=2>";
    str += getHorsesHeaderRow();
    if ( vHorses == null || vHorses == undefined )
    {
        initHorses();
    }
    for ( var ndx = 0; ndx < vHorses.length; ndx++ )
    {
        str += vHorses[ndx].getHorsesTableRow();
    }
    str += "</table>";
    return str;
}

//----------------------------------------------------------------------------
function getHorsesHeaderRow()
{
    var str = "<tr>";
    str += "<th class=column>name";
    str += "<th class=column>ST";
    str += "<th class=column>DX";
    str += "<th class=column>IQ";
    str += "<th class=column>HT";
    str += "<th class=column>hits";
    str += "<th class=column>move";
    str += "<th class=column>cost";
    str += "<th class=column>wt (lbs)";
    str += "<th class=column>PD";
    str += "<th class=column>DR";
    return str;
}

//----------------------------------------------------------------------------
function getHorsesTableRow()
{
    var str = "<tr>";
    str += "<td style='TEXT-ALIGN:left;'>" + String(this.name);
    str += "<td style='TEXT-ALIGN:right;'>" + String(this.ST);
    str += "<td style='TEXT-ALIGN:right;'>" + String(this.DX);
    str += "<td style='TEXT-ALIGN:right;'>" + String(this.IQ);
    str += "<td style='TEXT-ALIGN:right;'>" + String(this.HT);
    str += "<td style='TEXT-ALIGN:right;'>" + String(this.hits);
    str += "<td style='TEXT-ALIGN:right;'>" + String(this.move);
    str += "<td style='TEXT-ALIGN:right;'>$" + String(this.cost);
    str += "<td style='TEXT-ALIGN:right;'>" + String(this.wt);
    str += "<td style='TEXT-ALIGN:right;'>" + String(this.PD);
    str += "<td style='TEXT-ALIGN:right;'>" + String(this.DR);
    return str;
}

//============================================================================
var vLandVehicles;
var nLbsPerCuFt;
var nIncline;
//============================================================================
function initLandVehicle()
{
    nLbsPerCuFt = 20.0;                    // typical cargo
    nIncline = 0;
    vLandVehicles = new Array();
    vLandVehicles[vLandVehicles.length] =  new LandVehicle("Dogsled"                ,   400,   305, 1,  0,  4, 14, "Dog",         2,   13,   6, 0.5, 30, 0, getHarness(0), getWheel(5), null);
    vLandVehicles[vLandVehicles.length] =  new LandVehicle("Battle Car"             ,   396,   406, 1,  1,  0,  4, "Donkey",      1,   19,   4, 0.5, 40, 1, getHarness(1), getWheel(2), null);
    vLandVehicles[vLandVehicles.length] =  new LandVehicle("Light Chariot"          ,   333,   181, 1,  1,  0,  2, "Pony",        1,   19,   9, 0.5, 30, 1, getHarness(1), getWheel(3), null);
    vLandVehicles[vLandVehicles.length] =  new LandVehicle("Heavy Chariot"          ,   356,   239, 1,  2,  0,  4, "Pony",        1,   23,   9, 0.5, 30, 1, getHarness(1), getWheel(3), null);
    vLandVehicles[vLandVehicles.length] =  new LandVehicle("Oxcart"                 ,   280,   560, 0,  0, 24,  2, "Ox",          1,   19,   2, 0.5, 10, 1, getHarness(1), getWheel(3), "an ox will only walk for a half day");
    vLandVehicles[vLandVehicles.length] =  new LandVehicle("Palanquin"              ,   160,    88, 0,  1,  0,  2, "Man",         1,    7,   2, 0.5, 20, 1, getHarness(3), getWheel(0), null);
    //vLandVehicles[vLandVehicles.length] =  new LandVehicle("Platform car"           ,   357,   263, 1,  0,  0,  2, "Onager",      1,   11,   2, 0.5, 20, 1, getHarness(1), getWheel(4), null);
    //vLandVehicles[vLandVehicles.length] =  new LandVehicle("Straddle car"           ,   275,   149, 1,  0,  3,  2, "Onager",      0,    5,   2, 0.5, 20, 1, getHarness(1), getWheel(4), null);
    vLandVehicles[vLandVehicles.length] =  new LandVehicle("Assyrian Battering Ram" ,  2000,  6220, 0,  0,  0, 10, "Man",         5,  188,   2, 0.5, 30, 2, getHarness(3), getWheel(0), null);
    vLandVehicles[vLandVehicles.length] =  new LandVehicle("Racing Chariot"         ,   644,   168, 1,  0,  0,  4, "Racehorse",   1,    4,  16, 0.5, 40, 2, getHarness(1), getWheel(3), null);
    vLandVehicles[vLandVehicles.length] =  new LandVehicle("Siege Tower"            , 24700, 18970, 0, 18,  3, 16, "Ox",         20, 1200,   4, 0.5, 15, 2, getHarness(1), getWheel(4), null);
    vLandVehicles[vLandVehicles.length] =  new LandVehicle("Farm Cart"              ,   500,   480, 1,  0, 24,  2, "Draft Horse", 2,   22,   8, 0.5, 30, 3, getHarness(2), getWheel(3), null);
    vLandVehicles[vLandVehicles.length] =  new LandVehicle("Farm Wagon"             ,   760,   680, 1,  0, 40,  2, "Draft Horse", 2,   22,   8, 0.5, 30, 3, getHarness(2), getWheel(4), "LT");
    vLandVehicles[vLandVehicles.length] =  new LandVehicle("Supply Wagon"           ,  1949,  3541, 1,  0, 80,  2, "Draft Horse", 2,   12,   8, 0.5, 30, 3, getHarness(2), getWheel(4), "GVD.Lon");
    //vLandVehicles[vLandVehicles.length] =  new LandVehicle("Hussite War Wagon"      , 10600, 21300, 2, 20,  0,  8, "Draft Horse",10,  760,   4, 0.5, 10, 3, getHarness(2), getWheel(4), null);
}

//----------------------------------------------------------------------------
function LandVehicle( name, cost, ew, crew, psgrs, cargo, draftno, drafttype, DR, HP, move, MR, distance, TL, harness, wheel, notes )
{
    this.name       = name;
    this.cost       = cost;
    this.ew         = ew;
    this.crew       = crew;
    this.psgrs      = psgrs;
    this.cargo      = cargo;
    this.draftno    = draftno;
    this.drafttype  = drafttype;
    this.DR         = DR;
    this.HP         = HP;
    this.move       = move;
    this.MR         = MR;
    this.distance   = distance;
    this.TL         = TL;
    this.harness    = harness;
    this.wheel      = wheel;
    this.notes      = notes;
    this.CloneLandVehicle = CloneLandVehicle;
    this.getLandVehicleTableRow = getLandVehicleTableRow;
    this.getActualWeight = getActualWeight;
    this.getEffectiveWeight = getEffectiveWeight;
    this.getTeamEffectiveST = getTeamEffectiveST;
}

//----------------------------------------------------------------------------
function CloneLandVehicle()
{
    return new LandVehicle( this.name, this.cost, this.ew, this.crew, this.psgrs, this.cargo, this.draftno, this.drafttype, this.DR, this.HP, this.move, this.MR, this.distance, this.TL, this.harness, this.wheel, this.notes );
}  // CloneLandVehicle

//----------------------------------------------------------------------------
function createLandVehicle( type )
{
    if ( vLandVehicles == null || vLandVehicles == undefined )
    {
        initLandVehicle();
    }
    for ( var ndx = 0; ndx < vLandVehicles.length; ndx++ )
    {
        if ( vLandVehicles[ndx].name == type )
        {
            return vLandVehicles[ndx].CloneLandVehicle();
        }
    }
    return null;
}  // createLandVehicle

//----------------------------------------------------------------------------
function printLandVehicleTable()
{
    //nLbsPerCuFt = 20;
    nIncline = 0;
    var str = "";
    str += "<form name='frmVehicleTable' id='land'>";
    str += "</form>";
    str += getVehicleLegend( true );
    document.writeln( str );
    setFormHtml( "frmVehicleTable", getLandVehicleTable() );
    //CargoTypeChange();
}

//----------------------------------------------------------------------------
function getLandVehicleTable()
{
    var str = "<table BORDER=1 CELLSPACING=0 CELLPADDING=2>";
    str += getLandVehicleHeaderRow();
    if ( vLandVehicles == null || nLbsPerCuFt == null || nIncline == null || vLandVehicles == undefined )
    {
        initLandVehicle();
    }
    for ( var ndx = 0; ndx < vLandVehicles.length; ndx++ )
    {
        str += vLandVehicles[ndx].getLandVehicleTableRow();
    }
    str += "</table>";
    return str;
}  // getLandVehicleTable

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getLandVehicleHeaderRow()
{
    var str = "<tr>";
    str += "<th rowspan=2 class=column>TL";
    str += "<th rowspan=2 class=column>name";
    str += "<th rowspan=2 class=column>cost";
    str += "<th rowspan=2 class=column>ew";
    str += "<th rowspan=2 class=column>crew";
    str += "<th rowspan=2 class=column>psgrs";
    str += "<th rowspan=2 class=column>cargo<br>(cf)";
    str += "<th rowspan=2 class=column>DR";
    str += "<th rowspan=2 class=column>HP";
    str += "<th rowspan=2 class=column>wheels";
    str += "<th colspan=4 class=column>draft animals";
    str += "<th colspan=3 class=column>incline " + String(nIncline) + "%";
    str += "<th rowspan=2 class=column>MR";
    str += "<th rowspan=2 class=column>notes";
    //str += "<th rowspan=2 class=column>distance";
    str += "<tr>";
    str += "<th class=column>harness";
    str += "<th class=column>no";
    str += "<th class=column>type";
    str += "<th class=column>ST";
    str += "<th  class=column>Cargo<br>";
    if ( nLbsPerCuFt == 50 )
    {
        str += "Bulk: 50lbs / cf";
    }
    else
    {
        str += "Typical: 20lbs / cf";
    }
    str += "<th class=column>move";
    //str += "<th class=column>[move]";
    str += "<th class=column>mph";
    str += "<tr>";
    return str;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getLandVehicleTableRow()
{
    var st = this.getTeamEffectiveST();
    var hvy = false;
    var lbs = this.getEffectiveWeight(true,99,nLbsPerCuFt,nIncline);
    var move = this.move;
    var step = move / 8;
    var animal = createHorse( this.drafttype );
    var encumbrance;
    var bgcolor = "";
    if ( animal != null )
    {
        if ( this.drafttype == "Man" )
        {
            // this uses a man's encumbrance progression: 2,4,6,12
            encumbrance = getEncumbranceObject( st, lbs );
        }
        else
        {
            // this uses a Horse's encumbrance progression: 2,6,20
            encumbrance = animal.getHorseEncumbranceObject( st, lbs );
        }

        move = animal.move;
        if ( this.drafttype == "Man" )
        {
            move -= encumbrance.mod;
            step = move / 4;
        }
        else
        {
            if ( encumbrance.move != null )
            {
                move = encumbrance.move;
                bgcolor = "BACKGROUND: pink; ";
            }
            else
            {
                move -= encumbrance.mod;
            }
            step = move / 8;
        }
    }

    var str = "<tr>";
    str += "<td style='TEXT-ALIGN:right'>" + String(this.TL);
    str += "<td style='TEXT-ALIGN:left'>" + String(this.name);
    str += "<td style='TEXT-ALIGN:right'>$" + String(this.cost);
    str += "<td style='TEXT-ALIGN:right'>" + String(this.ew);
    str += "<td style='TEXT-ALIGN:right'>" + String(this.crew);
    str += "<td style='TEXT-ALIGN:right'>" + String(this.psgrs);
    str += "<td style='TEXT-ALIGN:right'>" + String(this.cargo);
    str += "<td style='TEXT-ALIGN:right'>" + String(this.DR);
    str += "<td style='TEXT-ALIGN:right'>" + String(this.HP);
    str += "<td style='TEXT-ALIGN:right'>";
    if ( this.wheel != null )
    {
        str += String(this.wheel.getWheelString());
    }
    str += "<td style='TEXT-ALIGN:right'>";
    if ( this.harness != null )
    {
        str += String(this.harness.name);
    }
    str += "<td style='TEXT-ALIGN:right'>" + String(this.draftno);
    str += "<td style='TEXT-ALIGN:left'>" + String(this.drafttype);
    str += "<td style='TEXT-ALIGN:right'>" + String(st);
    str += "<td style='TEXT-ALIGN:right; " + bgcolor + "'>" + formatfloat(lbs,0);
    str += " (" + encumbrance.name + ")";
    str += "<td style='TEXT-ALIGN:right; " + bgcolor + "'>" + String(move);
    //str += "<td style='TEXT-ALIGN:right'>" + String(this.move);  // from LT
    str += "<td style='TEXT-ALIGN:right'>" + formatfloat(getMPH(step),1);
    str += "<td style='TEXT-ALIGN:right'>" + String(this.MR);

    str += "<td style=''>";
    if ( this.notes != null )
    {
        str += String(this.notes);
    }
    //str += "<td style='TEXT-ALIGN:right'>" + String(this.move);
    //str += "<td style='TEXT-ALIGN:right'>" + String(this.distance);

    return str;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getActualWeight( crew, passengers, lpcf )
{
    var lbs = this.ew;
    if ( crew )
    {
        lbs += this.crew * 200;         // 200 lbs per person
    }
    passengers = (this.psgrs < passengers) ? this.psgrs : passengers;
    lbs += passengers * 200;            // 200 lbs per person
    lbs += this.cargo * lpcf;           // cf * lbs / cu.ft.
    /*
    switch ( cargo )
    {
        case 1 : lbs += this.cargo * 20; break; // normal cargo
        case 2 : lbs += this.cargo * 50; break; // bulk cargo, e.g. grain
        case 0 :
        default:
            // none
    }
     */
    return lbs;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getEffectiveWeight( crew, passengers, lpcf, incline )
{
    var lbs = this.getActualWeight( crew, passengers, lpcf );
    if ( incline == null )
    {
        incline = 0;
    }
    var lift = (incline / 100) * lbs;
    lbs -= lift;
    if ( this.wheel != null )
    {
        lbs /= this.wheel.divisor;
    }
    //window.status = this.name + ": " + String(lbs) + "lbs, " + String(lift) + " lift";
    return lbs + lift;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getTeamEffectiveST()
{
    var strength = 0;
    var animal = createHorse( this.drafttype );
    if ( animal != null )
    {
        strength = animal.ST * this.draftno;
    }
    if ( this.harness != null )
    {
        strength *= this.harness.efficiency;
    }
    return strength;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getHarness( type )
{
    var harness = {name:"rope",efficiency:0.075};
    switch ( type )
    {
        case 1 : harness = {name:"yoke and pole",efficiency:0.100}; break;
        case 2 : harness = {name:"horse collar",efficiency:0.150}; break;
        case 3 : harness = {name:"lift",efficiency:1.0}; break;
        case 0 :;
        default:
            // rope
    }
    return harness;
}

//============================================================================
function Wheel( number, type, divisor )
{
    this.number = number;
    this.type = type;
    this.divisor = divisor;
    this.getWheelString = getWheelString;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getWheelString()
{
    var str = "";
    if ( 0 < this.number )
    {
        str = String(this.number) + " " + this.type;
    }
    else
    {
        str = "no wheels";
    }
    return str;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getWheel( type )
{
    var wheel = new Wheel(0,"none",1);
    switch ( type )
    {
        case 1 : wheel = new Wheel(2,"solid",5); break;
        case 2 : wheel = new Wheel(4,"solid",10); break;
        case 3 : wheel = new Wheel(2,"spoked",10); break;
        case 4 : wheel = new Wheel(4,"spoked",20); break;
        case 5 : wheel = new Wheel(2,"skis",15); break;
        case 0 :;
        default:
            // none
    }
    return wheel;
}

//----------------------------------------------------------------------------
function getMPH( step, minPerHr, terrain )
{
    if ( minPerHr == null || minPerHr == undefined )
    {
        minPerHr = 50.0;
    }
    var mph = step * 60.0 * minPerHr / 1760.0;
    return mph;
}

//----------------------------------------------------------------------------
function CargoTypeChange( density )
{
    if ( density != null )
    {
        nLbsPerCuFt = density;
    }
    if ( document.forms["frmVehicleTable"].id == "land" )
    {
        setFormHtml( "frmVehicleTable", getLandVehicleTable() );
    }
    else if ( document.forms["frmVehicleTable"].id == "water" )
    {
        setFormHtml( "frmVehicleTable", getWaterVehicleTable() );
    }
    return nLbsPerCuFt;
}

//----------------------------------------------------------------------------
function LandVehicleInclineChange()
{
    nIncline = parseInt(getFormValue("frmVehicleLegend", "txtIncline"));
    setFormHtml( "frmVehicleTable", getLandVehicleTable() );
}

//============================================================================
var vWaterVehicles;
//----------------------------------------------------------------------------
function initWaterVehicles()
{
    vWaterVehicles = new Array();
    vWaterVehicles[vWaterVehicles.length] = new  WaterVehicle( "Bark Canoe",                15,   270,   195,  2, 0,   20,   3120, 1,  14, 0.25, 2, 0, 0, "" );

    vWaterVehicles[vWaterVehicles.length] = new  WaterVehicle( "Egyptian Merchant Ship",    90, 17900, 20950, 36, 0, 4500, 323532, 2, 713, 0.02, 2, 5, 1, "" );
    vWaterVehicles[vWaterVehicles.length] = new  WaterVehicle( "Egyptian Riverboat",        35, 2537, 3560, 14, 0, 350, 31200, 1, 65, 0.1, 2, 6, 1, "" );
    vWaterVehicles[vWaterVehicles.length] = new  WaterVehicle( "Ancient Merchant Galley",   75, 9570, 11190, 35, 0, 1350, 162240, 2, 480, 0.02, 3, 6, 2, "" );
    vWaterVehicles[vWaterVehicles.length] = new  WaterVehicle( "Chinese River boat",         43, 6200, 9500, 18, 0, 800, 57408, 4, 480, 0.02, 3, null, 2, "" );
    vWaterVehicles[vWaterVehicles.length] = new  WaterVehicle( "Hellenistic Quinquereme",  120, 80800, 59200, 310, 27, 180, 253344, 10, 1350, 0.02, 6, 5, 2, "" );
    vWaterVehicles[vWaterVehicles.length] = new  WaterVehicle( "Karve",                     76, 8100, 10900, 32, 0, 400, 62073, 4, 476, 0.05, 3, 6, 2, "Viking longship, war" );
    vWaterVehicles[vWaterVehicles.length] = new  WaterVehicle( "Roman Quinquereme",        135, 135000, 81000, 286, 100, 1000, 544128, 10, 2125, 0.01, 5, 6, 2, "" );
    vWaterVehicles[vWaterVehicles.length] = new  WaterVehicle( "Trireme",                  120, 56700, 48000, 186, 14, 180, 202800, 10, 1178, 0.02, 5, 6, 2, "" );
    vWaterVehicles[vWaterVehicles.length] = new  WaterVehicle( "Caraval",                   80, 20500, 38500, 23, 0, 2240, 277056, 5, 1350, 0.05, null, 8, 3, "" );
    vWaterVehicles[vWaterVehicles.length] = new  WaterVehicle( "Carrack",                  128, 78700, 201500, 25, 0, 22400, 1479720, 10, 7450, 0.02, null, 5, 3, "");
    vWaterVehicles[vWaterVehicles.length] = new  WaterVehicle( "Cog",                       77, 22700, 50400, 18, 0, 5800, 501600, 5, 1950, 0.05, null, 4, 3, "" );
    vWaterVehicles[vWaterVehicles.length] = new  WaterVehicle( "Crusader Ship",            118, 106000, 190000, 72, 50, 50000, 3704316, 5, 7275, 0.02, 1, 5, 3, "" );
    vWaterVehicles[vWaterVehicles.length] = new  WaterVehicle( "Drakkar",                  150, 67200, 72230, 70, 70, 2000, 517920, 10, 2100, 0.05, 3, 5, 3, "Viking longship, war" );
    vWaterVehicles[vWaterVehicles.length] = new  WaterVehicle( "Knarr",                     82, 10850, 19300, 16, 16, 5400, 205656, 5, 1050, 0.05, 1, 4, 3, "Viking roundship, cargo" );
    vWaterVehicles[vWaterVehicles.length] = new  WaterVehicle( "Venetian Galley",          125, 67300, 81000, 190, 0, 6000, 617448, 10, 2325, 0.02, 3, 7, 3, "" );
}

//----------------------------------------------------------------------------
function WaterVehicle( name, length, cost, ew, crew, psgrs, cargo, flotation, DR, HP, MR, moverowed, movesail, TL, notes )
{
    this.name       = name;
    this.length     = length;
    this.cost       = cost;
    this.ew         = ew;
    this.crew       = crew;
    this.psgrs      = psgrs;
    this.cargo      = cargo;
    this.flotation  = flotation;
    this.DR         = DR;
    this.HP         = HP;
    this.MR         = MR;
    this.moverowed  = moverowed;
    this.movesail   = movesail;
    this.TL         = TL;
    this.notes      = notes;
    this.getWaterVehicleTableRow = getWaterVehicleTableRow;
    this.getActualWeight = getActualWeight;
}

//----------------------------------------------------------------------------
function makeWaterVehicle()
{
}

//----------------------------------------------------------------------------
function printWaterVehicleTable()
{
    nLbsPerCuFt = 20;
    nIncline = 0;
    var str = "";
    str += "<form name='frmVehicleTable' id='water'>";
    str += "</form>";
    str += getVehicleLegend();
    document.writeln( str );
    setFormHtml( "frmVehicleTable", getWaterVehicleTable() );
    //CargoTypeChange();
}

//----------------------------------------------------------------------------
function getVehicleLegend( land )
{
    nLbsPerCuFt = 20;
    var str = "";
    str += "<form name='frmVehicleLegend'>";
    str += "<p><b>Where:</b>";
    str += "<table wisth=100%><tr>";
    str += "<td style='VERTICAL-ALIGN:top'>";
    str += "<ul>";
    str += "<li><B>ew:</B> empty weight";
    str += "<li><B>crew:</B> # people to safely operate";
    if ( land == true )
    {
        str += "<li>incline = <input name='txtIncline' type=text size=3 value='" + String(nIncline) + "' class=rightalign onChange='LandVehicleInclineChange()'>%";
    }
    str += "<li>";
    str += "<b>cargo:</b> in cubic feet (cf)";
    str += "<br><input name='chkCargo' type='radio' onClick='CargoTypeChange(20)'";
    if ( nLbsPerCuFt == 20 )
    {
        str += " checked";
    }
    str += "> typical cargo is 20lbs/cf";
    str += "<br><input name='chkCargo' type='radio' onClick='CargoTypeChange(50)'";
    if ( nLbsPerCuFt == 50 )
    {
        str += " checked";
    }
    str += "> bulk cargo (such as grain) is 50lb/cf";
    str += "<li><B>floatation:</B> (lbs) A heavy load effects the Seamanship roll made during heavy weather (amount TBD).";
    str += "<li><b>DR:</b> Damage Resistance (same as for an individual)";
    str += "<li><b>HP:</b> Hit Points";
    str += "<li><B>MR:</b> is the number of G's the vehicle can withstand in a turn.  To find the turning radius, square the move and divide by 10 x MR.";
    if ( land != null && land == true )
    {
        str += "<li><b>no:</b> is the number of draft animals";
        str += "<li><b>type:</b> is the type of draft animal. See <A HREF='horses.html'>Horses</A>.";
        str += "<li><b>ST:</b> is the effective strength of the team of draft animals";
    }
    str += "<li><B>normal load:</b> includes a full crew, all passengers (200lb/person) and normal cargo (20lbs/cf).";
    if ( land != null && land == true )
    {
        str += "<li><B>move:</b> is the draft animals move reduced by the encumbrance of the normal load";
    }
    else
    {
        str += "<li><B>move:</b> is in hexes/sec with a normal load. Rowed move aasumes a complete crew and sailed move assumes a favorable wind.";
    }
    str += "<li><B>mph:</b> is the speed for long distance travel.  see <A HREF='LongDistance.html'>Long Distance</A>";
    str += "</ul>";
    if ( land == true )
    {
        str += "<td style='VERTICAL-ALIGN:top'>";
        str += "<ul>";
        str += "<li><b>Wheels</b> reduce the effective weight of the vehicle<br>";
        str += "<table border=1 cellspacing=0 cellpadding=1>";
        str += "<tr>";
        str += "<th class=column>type";
        str += "<th class=column>divisor";
        var wheel;
        for ( var type = 0; type <= 5; type++ )
        {
            wheel = getWheel( type );
            str += "<tr>";
            str += "<td>" + wheel.getWheelString();
            str += "<td align=right>" + formatfloat(wheel.divisor,1);
        }
        str += "</table>";
        str += "</ul>";
        str += "";
        str += "<td style='VERTICAL-ALIGN:top'>";
        str += "<ul>";
        str += "<li><b>Harness</b> defines the effective strength (ST) of the team of draft animals<br>";
        str += "<table border=1 cellspacing=0 cellpadding=1>";
        str += "<tr>";
        str += "<th class=column>type";
        str += "<th class=column>efficiency";
        var harness;
        for ( var type = 0; type <= 3; type++ )
        {
            harness = getHarness( type );
            str += "<tr>";
            str += "<td>" + harness.name;
            str += "<td align=right>" + formatfloat(harness.efficiency,1);
        }
        str += "</table>";
        str += "</ul>";
    }
    str += "</table>";
    str += "</form>";
    return str;
}

//----------------------------------------------------------------------------
function getWaterVehicleTable()
{
    var str = "<table BORDER=1 CELLSPACING=0 CELLPADDING=2>";
    str += getWaterVehicleHeaderRow();
    if ( vWaterVehicles == null || vWaterVehicles == undefined )
    {
        initWaterVehicles();
    }
    for ( var ndx = 0; ndx < vWaterVehicles.length; ndx++ )
    {
        str += vWaterVehicles[ndx].getWaterVehicleTableRow();
    }
    str += "</table>";
    return str;
}  // getWaterVehicleTable

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getWaterVehicleHeaderRow()
{
    var str = "<tr>";
    str += "<th rowspan=2 class=column>TL";
    str += "<th rowspan=2 class=column>name";
    str += "<th rowspan=2 class=column>cost";
    str += "<th rowspan=2 class=column>ew";
    str += "<th rowspan=2 class=column>crew";
    str += "<th rowspan=2 class=column>psgrs";
    str += "<th rowspan=2 class=column>cargo<br>(cf)<br>";
    str += "<th rowspan=2 class=column>floatation";
    str += "<th rowspan=2 class=column>DR";
    str += "<th rowspan=2 class=column>HP";
    str += "<th rowspan=2 class=column>MR";
    str += "<th colspan=2 class=column>move";
    str += "<th rowspan=2 class=column>load";
    str += "<th rowspan=2 class=column>notes";
    str += "<tr>";
    str += "<th class=column>rowed";
    str += "<th class=column>sail";
    return str;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getWaterVehicleTableRow()
{
    var hvy = false;
    var lbs = this.getActualWeight(true,99,nLbsPerCuFt);
    var move = this.move;

    var str = "<tr>";
    str += "<td style='TEXT-ALIGN:right'>" + String(this.TL);
    str += "<td style='TEXT-ALIGN:left'>" + String(this.name);
    str += "<td style='TEXT-ALIGN:right'>$" + String(this.cost);
    str += "<td style='TEXT-ALIGN:right'>" + String(this.ew);
    str += "<td style='TEXT-ALIGN:right'>" + String(this.crew);
    str += "<td style='TEXT-ALIGN:right'>" + String(this.psgrs);
    str += "<td style='TEXT-ALIGN:right'>" + String(this.cargo);
    str += "<td style='TEXT-ALIGN:right'>" + String(this.flotation);
    str += "<td style='TEXT-ALIGN:right'>" + String(this.DR);
    str += "<td style='TEXT-ALIGN:right'>" + String(this.HP);
    str += "<td style='TEXT-ALIGN:right'>" + String(this.MR);
    str += "<td style='TEXT-ALIGN:right'>";
    if ( this.moverowed != null )
    {
        str += String(this.moverowed);
    }
    str += "<td style='TEXT-ALIGN:right'>";
    if ( this.movesail != null )
    {
        str += String(this.movesail);
    }

    str += "<td style='TEXT-ALIGN:right'>";
    var pct = 100 * this.getActualWeight(true,999,nLbsPerCuFt) / this.flotation;
    str += formatfloat( pct, 0 ) + "%";

    str += "<td style=''>";
    if ( this.notes != null )
    {
        str += String(this.notes);
    }

    return str;
}

//============================================================================

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function writeHorseEquipment( vArray )
{
    var i;
    var item, cost, lbs, wt;
    wt = 0;
    for ( i = 0; i < vArray.length; i++ )
    {
        lbs = vArray[i][0];
        item = vArray[i][1];

        document.writeln ( "<tr valign=middle>" );
        document.writeln ( "<td align=right>" );  // lbs
        document.write ( "<input name='lbs" + item + "' readonly class=readonly-rightalign TYPE=Text SIZE=5>" );
        document.frmHorse["lbs"+item].value = lbs;
        document.writeln ( "<td>" );  // spacer
        document.writeln ( "<td colspan=4 style='VERTICAL-ALIGN: middle;'>" + item );
        wt += lbs;
    }
    return wt;
}  // writeHorseEquipment

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function writeDefense()
{
    var lbs;
    //var lbsArmor, lbsShield, lbsWeapons, lbsPack;
    var nPDArmor, nPDShield, nDRArmor;
    lbsArmor = 0;
    lbsShield = 0;
    lbsWeapons = 0;
    lbsPack = 0;
    lbsArmor = Math.floor( getFormValue( "frmArmor", "valLbsArmor" ) );
    lbsShield = Math.floor( getFormValue( "frmShield", "valLbsShield" ) );
    lbsWeapons = Math.floor( getBagLbs( myPouch ) * 100 ) / 100;
    lbsWeapons += Math.floor( getFormValue( "frmWeapons", "valLbsTotal" ) );
    lbsWeapons += Math.floor( getFormValue( "frmRangedWeapons", "valLbsTotal" ) );
    lbsWeapons += Math.floor( getFormValue( "frmGuns", "valLbsTotal" ) );
    lbsPack = Math.floor( getBagLbs( myPack ) * 100 ) / 100;
    nPDArmor = Math.floor(getFormValue("frmArmor","valPDArmor"));
    nPDShield = Math.floor(getFormValue("frmShield","valPDShield"));
    nDRArmor = Math.floor(getFormValue("frmArmor","valDRArmor"));

    document.writeln ( "<form name='frmDefense'>" );
    document.writeln ( "<table BORDER=0 CELLSPACING=0 CELLPADDING=0>" );
    document.writeln ( "<tr>" );
    document.writeln ( "<th colspan=6 style='BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid; BORDER-RIGHT: black 1px solid; '>Defense" );
    document.writeln ( "<tr valign=bottom>" );
    document.writeln ( "<th class=column align=right colspan=2 style='BORDER-LEFT: black 1px solid'>skill" );
    document.writeln ( "<th class=column align=right>w/<br>shield" );
    document.writeln ( "<th class=column align=right>w/<br>armor" );
    document.writeln ( "<th class=column align=right style='BORDER-RIGHT: black 1px solid'>w/<br>both" );
    if ( 0 < lbsPack )
    {
        document.writeln ( "<th class=column align=right style='BORDER-RIGHT: black 1px solid'>w/<br>pack" );
    }

    document.writeln ( "<tr>" );
    document.writeln ( "<th class=column align=left style='BORDER-LEFT: black 1px solid'>lbs" );
    document.writeln ( "<th class=column align=right>" + String(lbsWeapons) );
    document.writeln ( "<th class=column align=right>" + String(lbsWeapons + lbsShield) );
    document.writeln ( "<th class=column align=right>" + String(lbsWeapons + lbsArmor) );
    document.writeln ( "<th class=column align=right style='BORDER-RIGHT: black 1px solid'>" + String(lbsWeapons + lbsArmor + lbsShield) );
    if ( 0 < lbsPack )
    {
        lbs = Math.floor( (lbsWeapons + lbsArmor + lbsShield + lbsPack) * 100.0 ) / 100.0;
        document.writeln ( "<th class=column align=right style='BORDER-RIGHT: black 1px solid'>" + String(lbs) );
    }

    document.writeln ( "<tr>" );
    document.writeln ( "<th class=column align=left style='BORDER-LEFT: black 1px solid'>encumbrance" );
    document.writeln ( "<th class=column align=right>" + getEncumbrance(lbsWeapons) );
    document.writeln ( "<th class=column align=right>" + getEncumbrance(lbsWeapons + lbsShield) );
    document.writeln ( "<th class=column align=right>" + getEncumbrance(lbsWeapons + lbsArmor) );
    document.writeln ( "<th class=column align=right style='BORDER-RIGHT: black 1px solid'>" + getEncumbrance(lbsWeapons + lbsArmor + lbsShield) );
    if ( 0 < lbsPack )
    {
        document.writeln ( "<th class=column align=right style='BORDER-RIGHT: black 1px solid'>" + getEncumbrance(lbsWeapons + lbsArmor + lbsShield + lbsPack) );
    }

    var run, speed;
    run = parseInt(document.frmMain["run"].value );
    speed = parseInt(document.frmMain["speed"].value );
    document.writeln ( "<tr>" );
    document.writeln ( "<th class=column align=left  style='BORDER-LEFT: black 1px solid'>move" );
    document.writeln ( "<th class=column align=right>" );
    document.writeln ( "<input name='moveBase' readonly class=readonly-rightalign TYPE=Text SIZE=6>" );
    document.frmDefense["moveBase"].value = String( run - getEncumbrance(lbsWeapons) );

    document.writeln ( "<th class=column align=right>" );
    document.writeln ( "<input name='moveShield' readonly class=readonly-rightalign TYPE=Text SIZE=6>" );
    document.frmDefense["moveShield"].value = String( run - getEncumbrance(lbsWeapons + lbsShield) );

    document.writeln ( "<th class=column align=right>" );
    document.writeln ( "<input name='moveArmor' readonly class=readonly-rightalign TYPE=Text SIZE=6>" );
    document.frmDefense["moveArmor"].value = String( run - getEncumbrance(lbsWeapons + lbsArmor) );

    document.writeln ( "<th class=column align=right style='BORDER-RIGHT: black 1px solid'>" );
    document.writeln ( "<input name='moveArmorShield' readonly class=readonly-rightalign TYPE=Text SIZE=6>" );
    document.frmDefense["moveArmorShield"].value = String( run - getEncumbrance(lbsWeapons + lbsArmor + lbsShield) );

    if ( 0 < lbsPack )
    {
        document.writeln ( "<th class=column align=right style='BORDER-RIGHT: black 1px solid'>" );
        document.writeln ( "<input name='movePack' readonly class=readonly-rightalign TYPE=Text SIZE=6>" );
        document.frmDefense["movePack"].value = String( run - getEncumbrance(lbsWeapons + lbsArmor + lbsShield + lbsPack) );
    }

    // dodge
    document.writeln ( "<tr>" );
    document.writeln ( "<th class=column align=left  style='BORDER-LEFT: black 1px solid'><b>Dodge</b>" );
    document.writeln ( "<td align=right style='BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid'>" + String( speed - getEncumbrance(lbsWeapons) + nCombatReflexes) );
    document.writeln ( "<td align=right style='BORDER-TOP: black 1px solid;'>" + String( speed  - getEncumbrance(lbsWeapons + lbsShield) + nPDShield + nCombatReflexes) );
    document.writeln ( "<td align=right style='BORDER-TOP: black 1px solid;'>" + String( speed - getEncumbrance(lbsWeapons + lbsArmor) + nPDArmor + nCombatReflexes) );
    document.writeln ( "<td align=right style='BORDER-TOP: black 1px solid; BORDER-RIGHT: black 1px solid'>" + String( speed - getEncumbrance(lbsWeapons + lbsArmor + lbsShield) + nPDShield + nPDArmor + nCombatReflexes) );
    if ( 0 < lbsPack )
    {
        document.writeln ( "<td align=right style='BORDER-TOP: black 1px solid; BORDER-RIGHT: black 1px solid; BORDER-BOTTOM: black 1px solid'>" + String( speed - getEncumbrance(lbsWeapons + lbsArmor + lbsShield + lbsPack) + nPDShield + nPDArmor + nCombatReflexes) );
    }

    // block
    if ( -1 < findMyArmor( "Shield" ) )
    {
        var nBlock;
        nBlock = parseInt(getSkillObject( "Shield" ).value / 2) + nCombatReflexes;
        document.writeln ( "<tr>" );
        document.writeln ( "<th class=column align=left  style='BORDER-LEFT: black 1px solid'><b>Block</b>" );
        document.writeln ( "<td align=right style='BORDER-LEFT: black 1px solid'>" + String(nBlock) );
        document.writeln ( "<td align=right style=''>" + String( nBlock + nPDShield ) );
        document.writeln ( "<td align=right style=''>~"  );
        document.writeln ( "<td align=right style='BORDER-RIGHT: black 1px solid'>" + String( nBlock + nPDShield + nPDArmor) );
    }

    // parry
    var nParry;
    var ndx;
    var bbottom;
    for ( var i = 0; i < myCharacter.weapons.length; i++ )
    {
        if ( "Lance" == myCharacter.weapons[i].name )
        {
            continue;
        }
        nParry = myCharacter.weapons[i].getParry();
        if ( i == (myCharacter.weapons.length-1) )
        {
            bbottom = "BORDER-BOTTOM: black 1px solid;"
        }
        else
        {
            bbottom = "";
        }
        document.writeln ( "<tr>" );
        document.writeln ( "<th class=column align=left style='BORDER-LEFT: black 1px solid; " + bbottom + "'>" );
        document.writeln ( "<b>" + myCharacter.weapons[i].name + "</b>" );

        document.writeln ( "<td align=right style='BORDER-LEFT: black 1px solid; " + bbottom + "'>" );
        document.writeln ( String(nParry) );

        document.writeln ( "<td align=right style='" + bbottom + "'>" );
        document.writeln ( String( nParry + nPDShield ) );

        document.writeln ( "<td align=right style='" + bbottom + "'>" );
        document.writeln ( String( nParry + nPDArmor ) );

        document.writeln ( "<td align=right style='BORDER-RIGHT: black 1px solid; " + bbottom + "'>" );
        document.writeln ( String( nParry + nPDShield + nPDArmor) );
    }
    if ( gDualWeaponParry != null )
    {
        weapons = gDualWeaponParry.split("|");
        if ( 1 < weapons.length )
        {
            var primaryWeapon = myCharacter.findWeapon( weapons[0] );
            var secondaryWeapon = myCharacter.findWeapon( weapons[1] );
            if ( primaryWeapon != null && secondaryWeapon != null )
            {
                nParry = secondaryWeapon.getParry();
                if ( secondaryWeapon.name == "Main-Gauche" )
                {
                    nParry--;
                }
                nParry = Math.floor(nParry / 4);
                nParry += primaryWeapon.getParry();
                nParry -= 2;                        // default
                skill = findSkill( "Dual-Weapon Parry" );
                if ( skill != null )
                {
                    nParry += skill.mod;
                }
                if ( secondaryWeapon.name == "Main-Gauche" )
                {
                    nParry++;               // basket hilt
                }

                document.writeln ( "<tr>" );
                document.writeln ( "<th class=column align=left style='BORDER-LEFT: black 1px solid; BORDER-BOTTOM: black 1px solid;'>" );
                document.writeln ( "<b>" + primaryWeapon.name + " &amp; " + secondaryWeapon.name + "</b>" );

                document.writeln ( "<td align=right style='BORDER-LEFT: black 1px solid; BORDER-BOTTOM: black 1px solid;'>" );
                document.writeln ( String(nParry) );

                document.writeln ( "<td align=right style='BORDER-BOTTOM: black 1px solid;'>" );
                document.writeln ( String( nParry + nPDShield ) );

                document.writeln ( "<td align=right style='BORDER-BOTTOM: black 1px solid;'>" );
                document.writeln ( String( nParry + nPDArmor ) );

                document.writeln ( "<td align=right style='BORDER-RIGHT: black 1px solid; BORDER-BOTTOM: black 1px solid;'>" );
                document.writeln ( String( nParry + nPDShield + nPDArmor) );
            }
        }
    }

    document.writeln ( "</table>" );
    document.writeln ( "</form>" );
}  // writeDefense

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function setFormValue( frm, field, value )
{
    if ( document.forms[frm] != null )
    {
        if ( document.forms[frm][field] != null )
        {
            document.forms[frm][field].value = value;
        }
    }
    return value;
}  // setFormValue

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function incFormValue( frm, field, value )
{
    var val;
    var tmpForm = document.forms[frm];
    if ( tmpForm != undefined )
    {
        if ( tmpForm[field] != null )
        {
            val = parseFloat(tmpForm[field].value);
            val += value;
            tmpForm[field].value = val;
        }
    }
    return val;
}  // incFormValue

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getFormValue( frm, field )
{
    var value;
    value = 0;
    if ( document.forms[frm] != null )
    {
        if ( document.forms[frm][field] != null )
        {
            value = document.forms[frm][field].value;
        }
    }
    return value;
}  // getFormValue

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function writeEncumbrance()
{
    document.writeln ( "<table BORDER=0 CELLSPACING=0 CELLPADDING=0>" );
    document.writeln ( "<tr>" );
    document.writeln ( "<th colspan=3 style='BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid; BORDER-RIGHT: black 1px solid; '>Encumbrance" );
    document.writeln ( "<tr>" );
    document.writeln ( "<th class=column align=left style='BORDER-LEFT: black 1px solid; padding-left: 2;'>encumbrance" );
    document.writeln ( "<th class=column align=right style='BORDER-RIGHT: black 1px solid'>lbs" );
    writeEncumbranceLine( "none", 0, valST * 2, false );
    writeEncumbranceLine( "light", valST * 2 + 1, valST * 4, false );
    writeEncumbranceLine( "medium", valST * 4 + 1, valST * 6, false );
    writeEncumbranceLine( "heavy", valST * 6 + 1, valST * 12, false );
    writeEncumbranceLine( "extra-heavy", valST * 12 + 1, valST * 20, true );

    document.writeln ( "</table>" );
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function writeEncumbranceLine( name, min, max, bBottom )
{
    var sStyle;
    if ( bBottom )
    {
        sStyle = "BORDER-BOTTOM: black 1px solid;";
    }
    else
    {
        sStyle = "";
    }
    document.writeln ( "<tr>" );
    document.writeln ( "<th class=column align=left style='BORDER-LEFT: black 1px solid; padding-left: 2;" + sStyle + "'>" + name );
    document.writeln ( "<td align=right style='BORDER-RIGHT: black 1px solid;" + sStyle + "'>" + String(min) + "-" + String(max) );
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getEncumbrance( wt )
{
    return getEncumbranceObject( valST, wt ).mod;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getEncumbranceObject( st, lbs )
{
    var encumbrance = {name:"none",mod:0};
    if ( (st * 2) < lbs )
    {
        encumbrance = {name:"light",mod:1};
    }
    if ( (st * 4) < lbs )
    {
        encumbrance = {name:"medium",mod:2};
    }
    if ( (st * 6) < lbs )
    {
        encumbrance = {name:"heavy",mod:3};
    }
    if ( (st * 12) < lbs )
    {
        encumbrance = {name:"extra-heavy",mod:4};
    }
    return encumbrance;
}

//----------------------------------------------------------------------------
function getDam( st, type, plus )
{
    if ( vDam == null || vDam == undefined )
    {
        initDamageTable();
    }
    var sDam = "";
    var nDice = 0;
    var nPlus = 0;
    var ndx = st - 4;
    if ( ndx < 0 )
    {
        ndx = 0;
    }
    if ( vDam.length < ndx )
    {
        ndx = vDam.length;
    }
    switch( type )
    {
        case "thr"  : nDice = vDam[ndx][0][0]; nPlus = vDam[ndx][0][1]; break;
        case "sw"   : nDice = vDam[ndx][1][0]; nPlus = vDam[ndx][1][1]; break;
        case "bite" : nDice = vDam[ndx][2][0]; nPlus = vDam[ndx][2][1]; break;
    }
    nPlus += plus;
    while ( 3 <= nPlus )
    {
        nDice++;
        nPlus -= 4;
    }
    sDam = String(nDice) + "d";
    if ( 0 <= nPlus )
    {
        sDam += "+";
    }
    sDam += String(nPlus);
    return sDam;
}  // getDam

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function writeWeaponTable()
{
    var modes;
    var lastSkill;
    vWeapons.sort( cmpBySkill );
    lastSkill = "";

    document.writeln ( "<table BORDER=1 CELLSPACING=0 CELLPADDING=1>" );
    document.writeln ( "<tr>" );

    //document.writeln ( "<th>skill" );
    document.writeln ( "<th>weapon" );
    document.writeln ( "<th>cost" );
    document.writeln ( "<th>lbs" );
    document.writeln ( "<th>ST" );

    document.writeln ( "<th>type" );
    document.writeln ( "<th>dam" );
    document.writeln ( "<th>'+'" );
    document.writeln ( "<th>reach" );

    document.writeln ( "<th>notes" );

    for ( weapon = 0; weapon < vWeapons.length; weapon++ )
    {
        if ( lastSkill != vWeapons[weapon][1] )
        {
            document.writeln ( "<tr valign=top>" );
            document.writeln ( "<td colspan=9><b>" + vWeapons[weapon][1] + "</b>" );
            lastSkill = vWeapons[weapon][1];
        }
        document.writeln ( "<tr valign=top>" );
        modes = vWeapons[weapon][5].length;
        //document.writeln ( "<td rowspan=" + modes + ">" + vWeapons[weapon][1] );  // skill
        document.writeln ( "<td rowspan=" + modes + ">" + vWeapons[weapon][0] );  // weapon
        document.writeln ( "<td rowspan=" + modes + " align=right>$" + vWeapons[weapon][2] ); // cost
        document.writeln ( "<td rowspan=" + modes + " align=right>" + vWeapons[weapon][3] );  // lbs
        document.writeln ( "<td rowspan=" + modes + " align=right>" + vWeapons[weapon][4] );  // ST
        for ( mode = 0; mode < modes; mode++ )
        {
            if ( 0 < mode )
            {
                document.writeln ( "<tr>" );
                //document.writeln ( "<td colspan=5>" );
            }
            objMode = vWeapons[weapon][5];
            document.writeln ( "<td>" + objMode[mode][0] );  // type
            document.writeln ( "<td>" + objMode[mode][1] );  // dam
            plus = parseInt(objMode[mode][2]);
            if ( 0 <= plus )
            {
                document.writeln ( "<td>+" + plus );  // plus
            }
            else
            {
                document.writeln ( "<td>" + plus );  // plus
            }

            document.writeln ( "<td>" + objMode[mode][3] );  // reach
            if ( 0 == mode )
            {
                document.writeln ( "<td rowspan=" + modes + ">" + vWeapons[weapon][6] );
            }
        }

    }
    document.writeln ( "</table>" );
    document.writeln ( "* Must be <i>readied</i> for one turn to change from long to short grip or vice versa." );
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function writeGunTable()
{
    document.writeln( "<form name='frmGuns'>" );
    document.writeln( "<input Type=Checkbox Name='chkBySkill' onclick='setGunTable()' checked>Sort by weapon skill<br>" );
    document.writeln( "<input Type=Checkbox Name='chkShowAll' onclick='setGunTable();'>Show all guns<br>" );
    document.writeln( "</form>" );
    document.writeln( "<form name='frmGunTable'>gun table</form>" );
    setFormHtml('frmGunTable',getGunTable());
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function setGunTable()
{
    setFormHtml('frmGunTable',getGunTable());
    //window.status = "show " + (document.frmGuns["chkShowAll"].checked ? "all" : "known") + " guns";
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function setID( id, str )
{
    if ( id != null && id != undefined )
    {
        obj = document.getElementById(id);
        if ( obj != null )
        {
            obj.innerHTML = str;
        }
        else
        {
            window.status = "setID(): '" + id + "' not found";
        }
    }
    else
    {
        window.status = "setID():null id";
    }
}  // setID

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function setFormHtml( name, str )
{
    if ( document.forms[name] != null && document.forms[name] != undefined )
    {
        document.forms[name].innerHTML = str;
    }
    else
    {
        window.status = "setFormHtml(): '" + name + "' not found";
    }
}  // setFormHtml

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getGunTable()
{
    var str;
    str = "";

    var lastSkill;
    lastSkill = "";
    if ( document.forms["frmGuns"]["chkBySkill"].checked )
    {
        vGuns.sort( cmpBySkill );
    }
    else
    {
        vGuns.sort( cmpByName );
    }
    bShowAllGuns = document.forms["frmGuns"]["chkShowAll"].checked;

    str += "<table BORDER=1 CELLSPACING=0 CELLPADDING=1>";
    str += "<tr><th class=boldcolumn colspan=99 style='TEXT-ALIGN:left'>sorted by: " + ( document.forms["frmGuns"]["chkBySkill"].checked ? "skill" : "name" );
    str += "<tr><th class=boldcolumn colspan=99 style='TEXT-ALIGN:left'>show " + ( document.forms["frmGuns"]["chkShowAll"].checked ? "all" : "known" ) + " guns";

    str += "<tr>";
    str += "<th class=boldcolumn>Name";
    str += "<th class=boldcolumn>TL";
    if ( !document.forms["frmGuns"]["chkBySkill"].checked )
    {
        str += "<th class=boldcolumn>skill";
    }
    str += "<th class=boldcolumn>$";
    str += "<th class=boldcolumn>Lbs";
    str += "<th class=boldcolumn>Dam";
    str += "<th class=boldcolumn>Type";
    str += "<th class=boldcolumn>SS";
    str += "<th class=boldcolumn>Acc";
    str += "<th class=boldcolumn>ROF";
    str += "<th class=boldcolumn>Shots";
    str += "<th class=boldcolumn>Recoil";
    str += "<th class=boldcolumn>Min ST";
    str += "<th class=boldcolumn>Range";

    for ( gun = 0; gun < vGuns.length; gun++ )
    {
        if ( bShowAllGuns || 0 < vGuns[gun][nGunsCost]  )
        {
            if ( document.forms["frmGuns"]["chkBySkill"].checked && lastSkill != vGuns[gun][nGunsSkill] )
            {
                str += "<tr valign=top>";
                str += "<th class=column colspan=99 align=left><b>" + vGuns[gun][nGunsSkill] + "</b>";
                lastSkill = vGuns[gun][nGunsSkill];
            }
            str += "<tr valign=top>";
            str += "<td>" + vGuns[gun][nGunsName];
            str += "<td align=center>" + vGuns[gun][nGunsTL];
            if ( !document.forms["frmGuns"]["chkBySkill"].checked )
            {
                str += "<td>" + vGuns[gun][nGunsSkill];
            }
            str += "<td align=right>$" + vGuns[gun][nGunsCost];
            str += "<td align=center>" + vGuns[gun][nGunsLbs];
            str += "<td>" + vGuns[gun][nGunsDam];
            str += "<td>" + vGuns[gun][nGunsType];
            str += "<td align=right>" + vGuns[gun][nGunsSS];
            str += "<td align=right>" + vGuns[gun][nGunsAcc];
            str += "<td align=right>" + vGuns[gun][nGunsROF];
            str += "<td align=right>" + vGuns[gun][nGunsShots];
            str += "<td align=right>" + vGuns[gun][nGunsRecoil];
            str += "<td align=center>" + vGuns[gun][nGunsStrength];
            str += "<td align=center>" + vGuns[gun][nGunsHalfDamRange];
            str += "-" + vGuns[gun][nGunsMaxRange];
        }
    }
    str += "</table>";
    return str;
}  // writeGunTable

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function cmpByName( a, b )
{
    if ( a[0] == b[0] )
    {
        return 0;
    }
    else
    {
        if ( a[0] < b[0] )
        {
            return -1;
        }
        else
        {
            return +1;
        }
    }
    //return 0;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function cmpBySkill( a, b )
{
    if ( a[1] == b[1] )
    {
        return 0;
    }
    else
    {
        if ( a[1] < b[1] )
        {
            return -1;
        }
        else
        {
            return +1;
        }
    }
    //return 0;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function cmpByRank( a, b )              // vSpells for KnightsTemplar
{
    if ( a[nSpellRank] == b[nSpellRank] )
    {
        return 0;
    }
    else
    {
        if ( a[nSpellRank] < b[nSpellRank] )
        {
            return -1;
        }
        else
        {
            return +1;
        }
    }
    //return 0;
}

//----------------------------------------------------------------------------
function initWeapons()
{
    vWeapons = [
        // weapon               skill                 cost  lbs    minST                +    reach     notes
        //  0                   1                     2     3      4      5                            6
        //                                                                 0      1     2     3
        [ "Axe",               "Axe/Mace",            50,   4,     12, [[ "cut", "sw",  +2,  "1"] ],   "1 turn to ready." ],
        [ "Bastard Sword: 2H", "Two-Handed Sword",    750,  5,     10, [[ "cut", "sw",  +2,  "1,2"] ,
                                                                        [ "imp", "thr", +3,  "2" ] ],  "thrusting" ],
        [ "Bastard Sword",     "Broadsword",          750,  5,     11, [[ "cut", "sw",  +1,  "1,2"],
                                                                        [ "imp", "thr", +2,  "2"] ], "1 turn to ready, thrusting" ],
        [ "Baton",             "Shortsword",          20,   1,     7,  [[ "cr",  "sw",  +0,  "1"],
                                                                        [ "cr",  "thr", +0,  "1"] ], "" ],
        [ "Bite",              "Brawling",            0,    1,     0,  [[ "cut", "bite",+0,  "C"] ], "" ],
        [ "Broadsword",        "Broadsword",          500,  3,     10, [[ "cut", "sw",  +1,  "1"],
                                                                        [ "imp", "thr", +1,  "1"] ], "standard broadsword has a <i>blunt</i> point." ],
        [ "Broadsword, thrusting", "Broadsword",      600,  3,     10, [[ "cut", "sw",  +1,  "1"],
                                                                        [ "imp", "thr", +2,  "1"] ], "thrusting" ],
        [ "Claw",              "Brawling",            0,    1,     0,  [[ "cut", "sw",  -3,  "C,1"] ], "bear claw strapped to wrist" ],
        [ "Claws",             "Brawling",            0,    1,     0,  [[ "cut", "sw",  -3,  "C"] ], "natural attack" ],
        [ "Club",              "Broadsword",          10,   3,     11, [[ "cr",  "sw",  +1,  "1"] ], "" ],
        [ "Dagger",            "Knife",               20,   0.25,  3,  [[ "imp", "thr", -1,  "C"] ], "-1 to parry with" ],
        [ "Glaive",            "Polearm",             100,  8,     11, [[ "cut", "sw",  +3,  "2,3*"],
                                                                        [ "imp", "thr", +3,  "1-3*"] ], "2 turns to ready<br>1 turn to ready after thrust" ],
        [ "Great Axe",         "Two-Handed Axe/Mace", 100,  8,     13, [[ "cut", "sw",  +3,  "1,2"] ], "1 turn to ready." ],
        [ "Greatsword",        "Two-Handed Sword",    900,  7,     12, [[ "cut", "sw",  +3,  "1,2"],
                                                                        [ "imp", "thr", +3,  "2"] ], "" ],
        [ "Halberd",           "Polearm",             150,  12,    13, [[ "cut", "sw",  +5,  "2,3*"],
                                                                        [ "imp", "thr", +3,  "1-3*"],
                                                                        [ "imp", "sw",  +4,  "2,3"] ], "2 turns to ready after swing<br>2 turns to ready after swing. May get <i>stuck</i>.<br>1 turn to ready after thrust" ],
        [ "Hatchet",           "Axe/Mace",            40,   2,     7,  [[ "cut", "sw",  +0,  "1"] ], "1 turn to ready." ],
        [ "Javelin",           "Spear",               30,   2,     0,  [[ "imp", "thr", +1,  "1"] ], "" ],
        [ "Katana",            "Katana",              650,  5,     11, [[ "cut", "sw",  +1,  "1,2"],
                                                                        [ "imp", "thr", +1,  "1"] ], "+1 sw when used 2-Hands" ],
        [ "Knife (Large)",     "Knife",               40,   1,     0,  [[ "cut", "sw",  -2,  "C,1"],
                                                                        [ "imp", "thr", +0,  "C"] ], "-1 to parry with" ],
        [ "Knife (Small)",     "Knife",               30,   0.5,   0,  [[ "cut", "sw",  -3,  "C,1"],
                                                                        [ "imp", "thr", -1,  "C"] ], "-1 to parry with" ],
        [ "Lance",             "Lance",               60,   6,     12, [[ "imp", "thr", +3,  "4"] ], "to ready: miss=1sec, hit=2sec" ],
        [ "Mace",              "Axe/Mace",            50,   5,     12, [[ "cr",  "sw",  +3,  "1"] ], "1 turn to ready" ],
        [ "Main-Gauche",       "Main-Gauche",         50,   1.25,  0,  [[ "cut", "sw",  -3,  "C,1"],
                                                                        [ "imp", "thr", +0,  "C"] ], "" ],
        [ "Maul",              "Two-Handed Axe/Mace", 80,   12,    14, [[ "cr",  "sw",  +4,  "1,2"] ],  "1 turn to ready" ],
        [ "Pick",              "Axe/Mace",            70,   3,     11, [[ "imp", "sw",  +1,  "1"] ],    "1 turn to ready" ],
        [ "Poleaxe",           "Polearm",             120,  10,    12, [[ "cut", "sw",  +4,  "2,3*"]  ], "" ],
        [ "Punch",             "Brawling",            0,    0,     0,  [[ "cr",  "thr", -2,  "C"]    ], "" ],
        [ "Rapier",            "Fencing",             500,  1.5,   0,  [[ "imp", "thr", +1,  "1,2"]  ], "max dam: 1d+1" ],
        [ "Sabre",             "Fencing",             700,  2,     7,  [[ "imp", "thr", +1,  "1"],
                                                                        [ "cut", "sw",  +0,  "1"] ], "thust max dam: 1d+2" ],
        [ "Scythe",            "Two-Handed Axe/Mace", 15,   5,     12, [[ "cut", "sw",  +2,  "1"] ], ""  ],
        [ "Scythe (point)",    "Two-Handed Axe/Mace", 15,   5,     6,  [[ "imp", "sw",  +0,  "1"] ], "point"  ],
        [ "Shortsword",        "Shortsword",          400,  2,     7,  [[ "cut", "sw",  +0,  "1"],
                                                                        [ "imp", "thr", +0,  "1"] ], "" ],
        [ "Small Mace",        "Axe/Mace",            35,   3,     11, [[ "cr",  "sw",  +2,  "1"] ], "" ],
        [ "Smallsword",        "Fencing",             400,  1,     0,  [[ "imp", "thr", +1,  "1"]  ], "max dam: 1d+1" ],
        [ "Spear",             "Spear",               40,   4,     9,  [[ "imp", "thr", +2,  "1"] ], "one-handed, throwable" ],
        [ "Spear: 2H",         "Spear",               40,   4,     9,  [[ "imp", "thr", +3,  "1,2*"] ], "two-handed" ],
        [ "Staff",             "Staff",               10,   4,     6,  [[ "cr",  "sw",  +2,  "1,2"],
                                                                        [ "cr",  "thr", +2,  "1,2"] ], "" ],
        [ "Throwing Axe",      "Axe/Mace",            60,   4,     12, [[ "cut", "sw",  +2,  "1"] ], "" ],
        [ "Warhammer",         "Two-Handed Axe/Mace", 100,  7,     13, [[ "imp", "sw",  +3,  "1,2*"] ], "" ]
    ];
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getWeaponItem( weapon )
{
    var item;
    var ndx = ndxOfWeapon( weapon );
    if ( -1 < ndx )
    {
        item = new BagItem( weapon, vWeapons[ndx][2], vWeapons[ndx][3] );
    }
    return item;
}

//----------------------------------------------------------------------------
function initGuns()
{
    nGunsName = 0;
    nGunsSkill = 1;
    nGunsCost = 2;
    nGunsLbs = 3;
    nGunsDam = 4;
    nGunsSS = 5;
    nGunsAcc = 6;
    nGunsHalfDamRange = 7;
    nGunsMaxRange = 8;
    nGunsType = 9;
    nGunsROF = 10;
    nGunsShots = 11;
    nGunsRecoil = 12;
    nGunsStrength = 13;
    nGunsTL = 14;
    bShowAllGuns = true;

    vGuns = [
        // gun                                     skill                     $     lbs, dam        SS        Acc       1/2 dam    max      type         ROF        shots Rcl      ST   TL
        // 0                                       1                         2     3    4          5         6         7          8        9            10         11    12       13   14
        [ "10.1 mm Pinata Stick",                 "Guns: Rifle",             0,    0,  "10d",      12,       11,       980,       4700,    "Cr.",      "1",        19,  -4,       14,  6   ],
        [ "10g Double Barrel",                    "Guns: Shotgun",           0,    0,  "5d",       13,       5,        25,        120,     "Cr.",      "1/L",      2,   -4,       13,  6   ],
        [ "10g Double Barrel BP",                 "BPW: Shotgun",            0,    0,  "5d",       13,       5,        25,        120,     "Cr.",      "1/L",      2,   -4,       13,  4   ],
        [ "10g Single Barrel",                    "Guns: Shotgun",           0,    0,  "5d",       13,       5,        25,        120,     "Cr.",      "1/L",      1,   -4,       13,  6   ],
        [ "10g Single Barrel BP",                 "BPW: Shotgun",            0,    0,  "5d",       13,       5,        25,        120,     "Cr.",      "1/L",      1,   -4,       13,  4   ],
        [ "12g Double Barrel",                    "Guns: Shotgun",           0,    0,  "4d",       13,       5,        25,        120,     "Cr.",      "1/L",      2,   -3,       12,  6   ],
        [ "12g Double Barrel BP",                 "BPW: Shotgun",            0,    0,  "4d",       13,       5,        25,        120,     "Cr.",      "1/L",      2,   -3,       12,  4   ],
        [ "12g Single Barrel",                    "Guns: Shotgun",           0,    0,  "4d",       13,       5,        25,        120,     "Cr.",      "1/L",      1,   -3,       12,  6   ],
        [ "12g Single Barrel BP",                 "BPW: Shotgun",            0,    0,  "4d",       13,       5,        25,        120,     "Cr.",      "1/L",      1,   -3,       12,  4   ],
        [ "ACR, 7mm w/APS",                       "Guns: Rifle",             0,    0,  "6d+7(2)",  12,       10,       1100,      6000,    "Cr.",      "10*",      20,  -2,       10,  6   ],
        [ "ACR, 7mm w/Solid",                     "Guns: Rifle",             0,    0,  "6d+1",     12,       10,       740,       4000,    "Cr.",      "10*",      20,  -2,       10,  6   ],
        [ "ACR, 9mm w/APS",                       "Guns: Rifle",             0,    0,  "7d+6(2)",  12,       10,       840,       5100,    "Cr.",      "10*",      20,  -2,       11,  6   ],
        [ "ACR, 9mm w/HEC",                       "Guns: Rifle",             0,    0,  "1d+1",     12,       10,       540,       3400,    "Exp",      "10*",      20,  -2,       11,  6   ],
        [ "ACR, 9mm w/Solid",                     "Guns: Rifle",             0,    0,  "7d-1",     12,       10,       540,       3400,    "Cr.",      "10*",      20,  -2,       11,  6   ],
        [ "AK-47, 7.62X39mm",                     "Guns: Lt. Auto",          0,    0,  "5d+1",     12,       7,        400,       3011,    "Cr.",      "10*",      30,  -1,       10,  6   ],
        [ "AK-74, 5.45mm",                        "Guns: Lt. Auto",          0,    0,  "5d",       12,       7,        500,       3843,    "Cr.",      "12*",      30,  -1,        9,  6   ],
        [ "AMT Backup, 9X19mm",                   "Guns: Pistol",            0,    0,  "2d",       11,       0,        125,       1467,    "Cr.",      "0",        0,   0,         8,  6   ],
        [ "AUG, 5.56X45mm NATO",                  "Guns: Rifle",             0,    0,  "5d",       11,       10,       500,       3800,    "Cr.",      "11*",      30,  -1,        9,  6   ],
        [ "Adams 54 Bore",                        "Guns: CL Ptl",            0,    0,  "2d-2",     11,       2,        120,       1400,    "Cr.",      "3~",       6,   -2,       10,  6   ],
        [ "Assault Rifle, 5.5mm",                 "Guns: Rifle",             0,    0,  "5d",       12,       11,       500,       3843,    "Cr.",      "12*",      30,  -1,        9,  6   ],
        [ "Assault Rifle, 7.5mm",                 "Guns: Rifle",             0,    0,  "7d",       14,       11,       1000,      4655,    "Cr.",      "11*",      20,  -2,       11,  6   ],
        [ "Auto Pistol, 7mm",                     "Guns: Pistol",            0,    0,  "2d-1",     10,       2,        175,       1700,    "Cr.",      "3~",       7,   -1,       10,  6   ],
        [ "Auto Pistol, 9mm",                     "Guns: Pistol",            0,    0,  "2d+2",     10,       3,        150,       1867,    "Cr.",      "3~",       15,  -1,        9,  6   ],
        [ "Auto Snub Pistol, 10mm w/CHEM",        "Guns: Pistol",            0,    0,  "Sp.",      9,        2,        80,        1100,    "Sp.",      "3~",       20,  -1,        8,  6   ],
        [ "Auto Snub Pistol, 10mm w/HEAT",        "Guns: Pistol",            0,    0,  "2d(10)",   9,        2,        80,        1100,    "Exp",      "3~",       20,  -1,        8,  6   ],
        [ "Auto Snub Pistol, 10mm w/HEC",         "Guns: Pistol",            0,    0,  "1d",       9,        2,        80,        1100,    "Exp",      "3~",       20,  -1,        8,  6   ],
        [ "Auto-Shotgun",                         "Guns: Shotgun",           0,    0,  "4d",       12,       6,        27,        160,     "Cr.",      "10*",      10,  -2,       12,  6   ],
        [ "BAR, .30-06",                          "Guns: Lt. Auto",          0,    0,  "7d+1",     17,       11,       800,       4700,    "Cr.",      "6/10*",    20,  -2,       13,  6   ],
        [ "Baker, .625",                          "BPW: Rifle",              0,    0,  "4d",       15,       7,        300,       2500,    "Cr.",      "1/20",     1,   -3,        0,  4   ],
        [ "Barret Model 82, .50BMG",              "Guns: Rifle",             0,    0,  "13d",      20,       16,       2200,      7400,    "Cr.",      "2~",       11,  -4,       13,  6   ],
        [ "Beretta 92, 9X19mm",                   "Guns: Pistol",            0,    0,  "2d+2",     10,       3,        150,       1900,    "Cr.",      "3~",       15,  -1,        9,  6   ],
        [ "Beretta M1923, 9X19mm",                "Guns: Pistol",            0,    0,  "2d+1",     11,       3,        140,       1800,    "Cr.",      "3~",       10,  -1,        9,  6   ],
        [ "Beretta M318, .25ACP",                 "Guns: Pistol",            0,    0,  "1d+1",     11,       1,        75,        1200,    "Cr.",      "3~",       9,   -1,        8,  6   ],
        [ "Bergmann MP18, 9X19mm",                "Guns: Lt. Auto",          0,    0,  "3d-1",     11,       7,        160,       1900,    "Cr.",      "9*",       32,  -1,       10,  6   ],
        [ "Blaster",                              "Guns: Pistol",         2000,    2,  "6d",       10,       6,        0,         300,     "Imp.",     "3~",       20,  -1,        0,  9   ],
        [ "Blaster Rifle",                        "Guns: BW",             3000,   10,  "12d",      14,       13,       400,       800,     "Imp.",     "3~",       12,  -1,        0,  9   ],
        [ "Blunderbuss, 8G",                      "BPW: Rifle",              0,    0,  "5d",       14,       3,        15,        100,     "Cr.",      "1/15",     1,   -4,        0,  4   ],
        [ "Body Pistol, 5mm",                     "Guns: Pistol",            0,    0,  "2d-1",     10,       2,        100,       1467,    "Cr.",      "3~",       6,   -1,        8,  6   ],
        [ "Bren, .303 British",                   "Guns: Lt. Auto",          0,    0,  "6d+1",     17,       11,       1000,      3800,    "Cr.",      "8*",       30,  -1,        0,  6   ],
        [ "Broomhandle Mauser, 7.63X25mm",        "Guns: Pistol",            0,    0,  "2d+1",     11,       3,        140,       1800,    "Cr.",      "3~",       10,  -1,       10,  6   ],
        [ "Brown Bess, .75",                      "Guns: Rifle",             0,    0,  "3d",       15,       5,        100,       1500,    "Cr.",      "1/20",     1,   -2,        0,  6   ],
        [ "Browning Auto-5, 12g",                 "Guns: Shotgun",           0,    0,  "4d",       12,       5,        25,        150,     "Cr.",      "3~",       5,   -2,       12,  6   ],
        [ "Browning High Power, 9X19mm",          "Guns: Pistol",            0,    0,  "2d+2",     10,       3,        150,       1900,    "Cr.",      "3~",       13,  -3,        9,  6   ],
        [ "Browning Model 1906, .25ACP",          "Guns: Pistol",            0,    0,  "1d",       10,       0,        50,        1000,    "Cr.",      "3~",       6,   -1,        7,  6   ],
        [ "Cannon-lock, .90",                     "BPW: Rifle",              0,    0,  "2d",       20,       1,        100,       600,     "Cr.",      "1/60",     1,   -3,        0,  4   ],
        [ "Carbine, 7mm",                         "Guns: Rifle",             0,    0,  "5d+1",     14,       10,       500,       3200,    "Cr.",      "3~",       10,  -1,        9,  6   ],
        [ "Castor '94 Assault Carbine",           "Guns: Lt. Auto",          0,    0,  "6d",       12,       11,       1000,      4500,    "Cr.",      "10*",      30,  -1,        9,  6   ],
        [ "Chachat, 8X50mm Lebel",                "Guns: Lt. Auto",          0,    0,  "6d",       17,       9,        400,       3900,    "Cr.",      "4",        20,  -2,       13,  6   ],
        [ "Charter Arms, .38Sp",                  "Guns: Pistol",           20,    2,  "2d-1",     10,       2,        120,       1900,    "Cr.",      "3~",       6,   -1,        8,  6   ],
        [ "Chatellerault, 7.5X54mm",              "Guns: Lt. Auto",          0,    0,  "6d+1",     17,       10,       1000,      3900,    "20",       "9*",       25,  -2,       13,  6   ],
        [ "Colt 'New Service', .38Sp",            "Guns: Pistol",            0,    0,  "2d-1",     10,       2,        120,       1934,    "Cr.",      "3~",       6,   -1,        9,  6   ],
        [ "Colt 'Peace Maker', .45Colt",          "Guns: Pistol",            0,    0,  "2d+1",     11,       2,        150,       1700,    "Cr.",      "1",        5,   -2,       11,  6   ],
        [ "Colt 'Texas Patterson', .36",          "Guns: CL Ptl",            0,    0,  "2d-1",     10,       1,        100,       1100,    "Cr.",      "1",        5,   -1,       10,  6   ],
        [ "Colt Army, .44",                       "BPW: Pistol",             0,    0,  "2d",       12,       1,        130,       1500,    "Cr.",      "1",        6,   -2,       10,  4   ],
        [ "Colt Army, .44RF",                     "Guns: Pistol",            0,    0,  "2d",       12,       1,        130,       1500,    "Cr.",      "1",        6,   -2,       10,  6   ],
        [ "Colt Detective Special, .38Sp",        "Guns: Pistol",            0,    0,  "2d-1",     11,       1,        130,       1600,    "Cr.",      "3~",       6,   -1,        9,  6   ],
        [ "Colt Dragoon, .44",                    "BPW: Pistol",             0,    0,  "2d+1",     11,       2,        150,       1500,    "Cr.",      "1",        6,   -3,       11,  4   ],
        [ "Colt M1911, .45ACP",                   "Guns: Pistol",           30, 2.75,  "2d",       10,       2,        175,       1700,    "Cr.",      "3~",       7,   -2,       10,  6   ],
        [ "Colt Navy, .36",                       "BPW: Pistol",             0,    0,  "2d-1",     9,        2,        120,       1300,    "Cr.",      "1",        6,   -1,        9,  4   ],
        [ "Colt Navy, .36RF",                     "Guns: Pistol",            0,    0,  "2d-1",     9,        2,        120,       1300,    "Cr.",      "1",        6,   -1,        9,  6   ],
        [ "Colt Python, .357M",                   "Guns: Pistol",            0,    0,  "3d-1",     10,       3,        185,       2034,    "Cr.",      "3~",       6,   -2,       10,  6   ],
        [ "Colt Texas, .34",                      "Guns: Pistol",            0,    0,  "2d-1",     10,       1,        100,       1100,    "Cr.",      "1",        5,   -1,       10,  6   ],
        [ "Colt Walker, .44",                     "BPW: Pistol",             0,    0,  "2d+2",     12,       2,        150,       1500,    "Cr.",      "1",        6,   -3,       12,  4   ],
        [ "Degtyarev DP, 7.62X54mmR",             "Guns: Lt. Auto",          0,    0,  "7d",       18,       10,       800,       3900,    "Cr.",      "10",       47,  -1,       13,  6   ],
        [ "Disruptor",                            "Guns: BW",                0,    0,  "6d",       13,       10,       500,       1000,    "Imp.",     "3~",       20,  0,         0,  6   ],
        [ "Electrolaser",                         "Beam Weapons",            0,    0,  "4d",       8,        4,        78,        156,     "Spec",     "1",        25,  0,         0,  8   ],
        [ "Enfield 1853, .577",                   "BPW: Rifle",              0,    0,  "4d",       15,       8,        700,       2100,    "Cr.",      "1/15",     1,   -2,       10,  4   ],
        [ "FGMP-11",                              "Beam Weapons",            0,    0,  "6dX25",    17,       16,       1100,      3300,    "Imp.",     "1",        500, -4,       22,  8   ],
        [ "FGMP-12",                              "Beam Weapons",            0,    0,  "8dX20",    15,       12,       1100,      3300,    "Imp.",     "1",        80,  -4,       10,  8   ],
        [ "FN HP35, 9X19mm",                      "Guns: Pistol",            0,    0,  "2d",       10,       3,        150,       1867,    "Cr.",      "3~",       3,   -1,        9,  6   ],
        [ "FN HP35, 9X19mm",                      "Guns: Pistol",            0,    0,  "2d+2",     10,       3,        150,       1867,    "Cr.",      "3~",       13,  -1,        9,  6   ],
        [ "FN Mag, 7.62X51mm NATO",               "Guns: Lt. Auto",          0,    0,  "7d",       19,       10,       1000,      4700,    "Cr.",      "15",       100, -1,       13,  6   ],
        [ "FN Minimi, 5.56X45mm NATO",            "Guns: Lt. Auto",          0,    0,  "5d+1",     15,       10,       500,       2800,    "Cr.",      "13*",      200, -1,       12,  6   ],
        [ "FN-FAL, 7.62X51mm NATO",               "Guns: Asslt Rifle",       0,    0,  "7d",       14,       11,       1000,      4655,    "Cr.",      "11*",      20,  -2,       11,  6   ],
        [ "Ferguson, .60",                        "BPW: Rifle",              0,    0,  "4d",       14,       7,        400,       3700,    "Cr.",      "1/10",     1,   -2,        0,  4   ],
        [ "Flamethrower",                         "Guns: FlmTh",             0,    0,  "3d",       5,        8,        40,        56,      "Cr.",      "4",        12,  0,        12,  6   ],
        [ "Flammenwerfer",                        "Guns: FlmTh",             0,    0,  "3d/sec.",  0,        6,        0,         24,      "F ",       "1",        6,   -3,        0,  6   ],
        [ "Flintlock, .51",                       "BPW: Rifle",              0,    0,  "2d-1",     11,       1,        75,        467,     "Cr.",      "1/20",     1,   -1,        0,  4   ],
        [ "Force Rod",                            "Beam Weapons",            0,    0,  "4d+2",     10,       5,        20,        30,      "Spec.",    "!3",       30,  0,         0,  8   ],
        [ "Galil, 5.56X45mm NATO",                "Guns: Rifle",             0,    0,  "5d",       12,       7,        500,       3843,    "Cr.",      "12*",      30,  -1,        9,  6   ],
        [ "Gauss Needle Rifle",                   "Guns: Rifle",             0,    0,  "2d",       14,       11,       500,       1000,    "Imp.",     "20*",      100, -1,        0,  6   ],
        [ "Gauss Needler",                        "Guns: Pistol",            0,    0,  "1d+2",     10,       4,        100,       300,     "Cr.",      "12",       100, -1,        0,  6   ],
        [ "Gauss Pistol, 4mm",                    "Guns: Pistol",            0,    0,  "6d(2)",    10,       7,        500,       3200,    "Cr.",      "8*",       15,  -1,        8,  6   ],
        [ "Gauss Rifle, 4mm",                     "Guns: Rifle",             0,    0,  "8d+1(2)",  12,       12,       900,       4500,    "Cr.",      "20*",      40,  -1,        9,  6   ],
        [ "Glock 17, 9X19mm",                     "Guns: Pistol",          450,    2,  "2d+2",     10,       3,        150,       1900,    "Cr.",      "3~",       17,  -1,        9,  7   ],
        [ "H&H Double-Express, .600NE",           "Guns: Rifle",             0,    0,  "10d",      16,       7,        1500,      5063,    "Cr.",      "2",        2,   -6,       13,  6   ],
        [ "H&K CAWS, 12g",                        "Guns: Shotgun",           0,    0,  "5D",       10,       7,        50,        200,     "Cr.",      "3~",       10,  -2,       12,  6   ],
        [ "H&K G3, 7.62X51mm NATO",               "Guns: Asslt Rifle",       0,    0,  "7d",       14,       10,       1000,      4655,    "Cr.",      "10*",      20,  -2,       11,  6   ],
        [ "H&K MP5, 9X19mm",                      "Guns: Lt. Auto",          0,    0,  "3d-1",     10,       8,        160,       1900,    "Cr.",      "10*",      30,  -1,       10,  6   ],
        [ "H&K PSG1, 7.62X51mm NATO",             "Guns: Rifle",             0,    0,  "7d",       15,       13,       1200,      4700,    "Cr.",      "1/3",      1,   -2,       12,  6   ],
        [ "HK21A1, 7.62X51mm NATO",               "Guns: Lt. Auto",          0,    0,  "7d",       18,       11,       1000,      4700,    "Cr.",      "15*",      100, -1,       13,  6   ],
        [ "Heater",                               "Beam Weapons",            0,    0,  "4d",       0,        0,        0,         10,      "Acid",     "1",        0,   0,         0,  8   ],
        [ "Henry Rifle, .44RF",                   "Guns: Rifle",             0,    0,  "2d+1",     13,       6,        250,       1900,    "Cr.",      "1",        16,  -1,        0,  6   ],
        [ "Hotchkiss MkI, .303British",           "Guns: Lt. Auto",          0,    0,  "6d+1",     20,       14,       600,       3800,    "Cr.",      "8*",       30,  -1,       13,  6   ],
        [ "IMI Desert Eagle, .44M",               "Guns: Pistol",            0,    0,  "3d",       12,       3,        230,       2500,    "Cr.",      "3~",       9,   -3,       12,  6   ],
        [ "IMI Desert Eagle, .50AE",              "Guns: Pistol",            0,    0,  "3d+2",     12,       3,        230,       2500,    "Cr.",      "3~",       9,   -4,       12,  6   ],
        [ "IMI Uzi, 9X19mm",                      "Guns: Lt. Auto",          0,    0,  "3d-1",     10,       7,        160,       1900,    "Cr.",      "10*",      32,  -1,       10,  6   ],
        [ "Ithaca Hammerless Double, 10g",        "Guns: Shotgun",           0,    0,  "5d",       12,       5,        25,        150,     "Cr.",      "2~",       2,   -4,       13,  6   ],
        [ "Kentucky Rifle, .45",                  "Guns: Rifle",             0,    0,  "4d",       15,       7,        400,       3700,    "Cr.",      "1/20",     1,   -2,       10,  6   ],
        [ "LE Mk3#1, .303",                       "Guns: Rifle",           130, 10.2,  "6d+1",     14,       10,       1000,      3800,    "Cr.",      "1",        10,  -2,       12,  6   ],
        [ "LPO-50",                               "Guns: FlmTh",             0,    0,  "3d/sec.",  0,        7,        0,         24,      "F ",       "1",        9,   -3,        0,  6   ],
        [ "Laser Carbine-10",                     "Beam Weapons",            0,    0,  "2d+2(2)",  12,       19,       4000,      8000,    "Imp.",     "4~",       50,  0,         7,  8   ],
        [ "Laser Carbine-8",                      "Beam Weapons",            0,    0,  "2d+2",     12,       18,       2700,      5400,    "Imp.",     "4~",       50,  0,         7,  8   ],
        [ "Laser Pistol",                         "Guns: Pistol",         1000,    2,  "1d",       9,        7,        400,       500,     "Imp.",     "4*",       20,  0,         0,  8   ],
        [ "Laser Pistol-10",                      "Beam Weapons",            0,    0,  "2d(2)",    10,       11,       870,       1700,    "Imp.",     "4~",       50,  0,         7,  8   ],
        [ "Laser Pistol-9",                       "Beam Weapons",            0,    0,  "2d",       10,       10,       580,       1200,    "Imp.",     "4~",       50,  0,         7,  8   ],
        [ "Laser Rifle",                          "Guns: BW",             2000,    5,  "2d",       15,       13,       900,       1200,    "Imp.",     "3~",       12,  0,         0,  8   ],
        [ "Laser Rifle-10",                       "Beam Weapons",            0,    0,  "4d(2)",    12,       20,       4900,      9200,    "Imp.",     "4~",       100, 0,         8,  8   ],
        [ "Laser Rifle-9",                        "Beam Weapons",            0,    0,  "4d",       12,       19,       3300,      6600,    "Imp.",     "4~",       100, 0,         8,  8   ],
        [ "Lebel '86, 8mm",                       "Guns: Rifle",             0,    0,  "6d+1",     15,       10,       1000,      3900,    "Cr.",      "1/2",      8,   -3,        0,  6   ],
        [ "Lewis, .303British",                   "Guns: Lt. Auto",          0,    0,  "6d+1",     18,       10,       500,       3800,    "Cr.",      "9",        47,  -1,       13,  6   ],
        [ "Luger, 9mmX19mm",                      "Guns: Pistol",           25, 2.75,  "2d+2",     9,        4,        175,       1900,    "Cr.",      "3~",       8,   -1,        9,  6   ],
        [ "M1 Carbine, .30 Carbine",              "Guns: Rifle",             0,    0,  "2d+2",     12,       8,        300,       2100,    "Cr.",      "3~",       15,  -1,        9,  6   ],
        [ "M1 Garand, .30-06",                    "Guns: Rifle",           590,   10,  "7d+1",     14,       11,       1000,      3710,    "Cr.",      "3~",       8,   -3,       12,  6   ],
        [ "M14, 7.62X51mm NATO",                  "Guns: Asslt Rifle",       0,    0,  "7d",       14,       11,       1000,      4655,    "Cr.",      "11*",      20,  -2,       11,  6   ],
        [ "M16, 5.56x45mm NATO",                  "Guns: Rifle",             0,    0,  "5d",       12,       11,       500,       3843,    "Cr.",      "12*",      20,  -1,        9,  6   ],
        [ "M1903A1, .30-06",                      "Guns: Rifle",             0,    0,  "7d+1",     14,       11,       1000,      3710,    "Cr.",      "1/2",      5,   -3,       12,  6   ],
        [ "M2 Carbine, .30 Carbine",              "Guns: Rifle",             0,    0,  "2d+2",     12,       8,        300,       2100,    "Cr.",      "12*",      30,  -1,        9,  6   ],
        [ "M2A1-7",                               "Guns: FlmTh",             0,    0,  "3d/sec.",  0,        7,        0,         50,      "F ",       "1",        10,  -3,        0,  6   ],
        [ "M4 E-T Sniper Cannon",                 "Guns: Rifle",             0,    0,  "6dx3",     17,       12,       1200,      6500,    "Cr.",      "3~",       22,  -3,       16,  6   ],
        [ "MG34, 7.92X57mm",                      "Guns: Lt. Auto",          0,    0,  "7d",       19,       10,       1000,      3900,    "Cr.",      "15*",      50,  -1,        0,  6   ],
        [ "MG42, 7.92X57mm",                      "Guns: Lt. Auto",          0,    0,  "7d",       19,       10,       1000,      3900,    "Cr.",      "20",       50,  -2,        0,  6   ],
        [ "MP38, 9X19mm",                         "Guns: Lt. Auto",          0,    0,  "3d-1",     10,       6,        160,       1900,    "Cr.",      "8",        32,  -1,       10,  6   ],
        [ "MP40, 9X19mm",                         "Guns: Lt. Auto",          0,    0,  "3d-1",     10,       6,        160,       1900,    "Cr.",      "8",        32,  -1,       10,  6   ],
        [ "Mac 10, .45ACP",                       "Guns: MPtl",              0,    0,  "2d+1",     9,        6,        180,       1700,    "Cr.",      "12*",      20,  -2,       12,  6   ],
        [ "Madsen, 8X58mmR Krag",                 "Guns: Lt. Auto",          0,    0,  "6d",       18,       10,       1000,      3900,    "Cr.",      "6",        30,  -1,        0,  6   ],
        [ "Magnum Revolver, 9mm",                 "Guns: Pistol",            0,    0,  "3d-1",     10,       3,        185,       2034,    "Cr.",      "3~",       6,   -2,       10,  6   ],
        [ "Marting-Henry, .450",                  "Guns: Rifle",             0,    0,  "5d",       15,       7,        600,       2000,    "Cr.",      "1/4",      1,   -2,       11,  6   ],
        [ "Matchlock Musket, .80",                "BPW: Musket",             0,    0,  "?",        0,        0,        -1,        -1,      "Cr.",      "0",        0,   0,         0,  4   ],
        [ "Mauser '96, 7.63mm",                   "Guns: Pistol",            0,    1,  "2d+1",     11,       3,        140,       1800,    "Cr.",      "3~",       10,  -1,       10,  6   ],
        [ "Mauser '98, 7.92X57mm",                "Guns: Rifle",             0,    1,  "7d",       14,       11,       1000,      4600,    "Cr.",      "1/2",      5,   -3,       12,  6   ],
        [ "Maxim MG08/15, 7.92X57mm",             "Guns: Lt. Auto",          0,    0,  "7d+1",     19,       11,       800,       4000,    "Cr.",      "6",        50,  -1,       14,  6   ],
        [ "Military Laser Rifle",                 "Guns: BW",                0,    0,  "2d",       12,       15,       1500,      2000,    "Imp.",     "8*",       140, 0,         0,  6   ],
        [ "Nagant, 7.62 Nagant",                  "Guns: Pistol",            0,    0,  "2d-1",     11,       2,        150,       1900,    "Cr.",      "3~",       7,   -1,        8,  6   ],
        [ "Needle Rifle",                         "Guns: Rifle",             0,    0,  "2d",       13,       9,        300,       800,     "Imp.",     "3~",       100, -1,        0,  6   ],
        [ "Needler Pistol",                       "Guns: Pistol",            0,    0,  "1d+2",     9,        1,        100,       300,     "Imp",      "3~",       100, -1,        0,  6   ],
        [ "PGMP-10",                              "Beam Weapons",            0,    0,  "6dX8",     12,       14,       460,       920,     "Imp.",     "1",        46,  -3,       12,  8   ],
        [ "PGMP-10A",                             "Beam Weapons",            0,    0,  "6dX15",    17,       15,       740,       1500,    "Imp.",     "1",        450, -3,       19,  8   ],
        [ "PGMP-11",                              "Beam Weapons",            0,    0,  "6dX15",    17,       15,       740,       1500,    "Imp.",     "1",        750, -3,        9,  8   ],
        [ "PK, 7.62X54mm",                        "Guns: Lt. Auto",          0,    0,  "7d",       16,       10,       1000,      3900,    "Cr.",      "12",       100, -1,       13,  6   ],
        [ "PPSh41, 7.62X25mm",                    "Guns: Lt. Auto",          0,    0,  "3d-1",     10,       6,        160,       1900,    "Cr.",      "16",       71,  -1,       10,  6   ],
        [ "RPD, 7.62X39mm",                       "Guns: Lt. Auto",          0,    0,  "5d+1",     17,       6,        400,       3000,    "Cr.",      "11",       50,  -1,       12,  6   ],
        [ "Remington 870, 12g",                   "Guns: Shotgun",         235,    8,  "4d",       12,       5,        25,        150,     "Cr.",      "3~",       5,   -3,       12,  7   ],
        [ "Remington DD, .41",                    "Guns: Pistol",            0,    0,  "1d",       11,       1,        80,        650,     "Cr.",      "1/15",     1,   -2,        0,  6   ],
        [ "Remington N.M. Army, .44",             "BPW: Pistol",             0,    0,  "2d",       11,       2,        150,       1500,    "Cr.",      "1",        6,   -2,       10,  4   ],
        [ "Remington N.M. Army, .44RF",           "Guns: Pistol",            0,    0,  "2d",       11,       2,        150,       1500,    "Cr.",      "1",        6,   -2,       10,  6   ],
        [ "Remington, .45",                       "Guns: Rifle",             0,    0,  "4d",       15,       8,        700,       2100,    "Cr.",      "1/4",      1,   -2,       11,  6   ],
        [ "Revolver, 5mm",                        "Guns: Pistol",            0,    0,  "1d",       10,       2,        75,        1100,    "Cr.",      "3~",       6,   -1,        8,  6   ],
        [ "Revolver, 7mm",                        "Guns: Pistol",            0,    0,  "1d+2",     10,       3,        130,       1500,    "Cr.",      "3~",       6,   -1,        8,  6   ],
        [ "Revolver, 9mm",                        "Guns: Pistol",            0,    0,  "2d",       10,       4,        150,       1600,    "Cr.",      "3~",       6,   -1,        8,  6   ],
        [ "Rifle, 13mm",                          "Guns: Rifle",             0,    0,  "13d+1",    17,       15,       1200,      5400,    "Cr.",      "2~",       10,  -2,       14,  6   ],
        [ "Rifle, 7mm",                           "Guns: Rifle",             0,    0,  "7d",       14,       11,       1000,      4655,    "Cr.",      "3~",       20,  -2,       11,  6   ],
        [ "Rifle, 9mm",                           "Guns: Rifle",             0,    0,  "7d-1",     14,       10,       540,       3400,    "Cr.",      "3~",       10,  -2,       12,  6   ],
        [ "Ruger Standard Model, .22LR",          "Guns: Pistol",            0,    0,  "1d+1",     9,        4,        75,        1200,    "Cr.",      "3~",       9,   -1,        7,  6   ],
        [ "S&W American, .44",                    "Guns: Pistol",            0,    0,  "2d",       10,       3,        150,       1700,    "Cr.",      "1",        6,   -2,       11,  6   ],
        [ "S&W M10, .38Sp",                       "Guns: Pistol",            0,    0,  "2d-1",     10,       2,        120,       1934,    "Cr.",      "3~",       6,   -1,        9,  6   ],
        [ "S&W M27, .357M",                       "Guns: Pistol",            0,    0,  "3d-1",     10,       3,        185,       2034,    "Cr.",      "3~",       6,   -2,       10,  6   ],
        [ "S&W M29, .44M",                        "Guns: Pistol",          100, 3.25,  "3d",       10,       2,        200,       2500,    "Cr.",      "3~",       6,   -3,       11,  7   ],
        [ "S&W No. 1, .22RF",                     "Guns: Pistol",            0,    0,  "1d-1",     9,        3,        40,        900,     "Cr.",      "1",        7,   -1,        8,  6   ],
        [ "S&W No. 2, .32RF",                     "Guns: Pistol",            0,    0,  "1d+1",     10,       2,        120,       1200,    "Cr.",      "1",        6,   -1,        9,  6   ],
        [ "S&W Russian, .44R",                    "Guns: Pistol",            0,    0,  "2d",       10,       3,        150,       1700,    "Cr.",      "3~",       6,   -2,       11,  6   ],
        [ "S&W Safety Hammerless, .38",           "Guns: Pistol",            0,    0,  "2d-1",     11,       1,        130,       1600,    "Cr.",      "3~",       5,   -1,        9,  6   ],
        [ "SMG, 9mm",                             "Guns: SMG",               0,    0,  "3d-1",     10,       7,        160,       1900,    "Cr.",      "10*",      32,  -1,       10,  6   ],
        [ "SMLE, .303Br",                         "Guns: Rifle",             0,    0,  "6d+1",     14,       10,       1000,      3800,    "Cr.",      "1",        10,  -2,       12,  6   ],
        [ "SPAS 12, 12g",                         "Guns: Shotgun",           0,    0,  "4d",       12,       5,        25,        150,     "Cr.",      "2~",       7,   -2,       10,  6   ],
        [ "Sharps Big Fifty, .50 50-90",          "Guns: Rifle",             0,    0,  "6d",       15,       7,        600,       3300,    "Cr.",      "1/4",      1,   -3,       12,  6   ],
        [ "Sharps Carbine, .52",                  "Guns: Rifle",             0,    0,  "5d",       13,       7,        400,       2600,    "Cr.",      "1/4",      1,   -2,       12,  6   ],
        [ "Sharps Carbine, .52 cl",               "BPW: RIfle",              0,    0,  "5d",       13,       7,        400,       2600,    "Cr.",      "1/L",      1,   -2,       12,  4   ],
        [ "Sharps, .52",                          "Guns: Rifle",             0,    0,  "5d",       13,       7,        500,       3000,    "Cr.",      "1/4",      1,   -2,       12,  6   ],
        [ "Sharps, .52 cl",                       "BPW: Rifle",              0,    0,  "5d",       13,       7,        500,       3000,    "Cr.",      "1/L",      1,   -2,       12,  4   ],
        [ "Shotgun",                              "Guns: Shotgun",           0,    0,  "4d",       12,       5,        25,        150,     "Cr.",      "3~",       5,   -3,       12,  6   ],
        [ "Snub Revolver, 10mm w/CHEM",           "Guns: Pistol",            0,    0,  "Sp.",      9,        2,        80,        1100,    "Sp.",      "3~",       6,   -1,        8,  6   ],
        [ "Snub Revolver, 10mm w/HEAT",           "Guns: Pistol",            0,    0,  "2d(10)",   9,        2,        80,        1100,    "Exp",      "3~",       6,   -1,        8,  6   ],
        [ "Snub Revolver, 10mm w/HEC",            "Guns: Pistol",            0,    0,  "1d",       9,        2,        80,        1100,    "Exp",      "3~",       6,   -1,        8,  6   ],
        [ "Spencer, .56",                         "Guns: Rifle",             0,    0,  "4d",       13,       6,        300,       2100,    "Cr.",      "1",        7,   -3,       12,  6   ],
        [ "Springfield, .58",                     "BPW: Rifle",              0,    0,  "4d",       15,       7,        400,       1900,    "Cr.",      "1/40",     1,   -2,       11,  4   ],
        [ "Sten, 9X19mm",                         "Guns: Lt. Auto",          0,    0,  "3d-1",     11,       6,        160,       1900,    "Cr.",      "9*",       32,  -1,       10,  6   ],
        [ "Striker, 12g",                         "Guns: Shotgun",           0,    0,  "4d",       13,       5,        25,        150,     "Cr.",      "3",        12,  -2,       11,  6   ],
        [ "Stun Rifle",                           "Guns: Rifle",             0,    0,  "stun",     12,       10,       300,       1000,    "stun",     "3~",       20,  0,         0,  6   ],
        [ "Stunner",                              "Guns: Pistol",            0,    0,  "Sp.",      10,       3,        12,        20,      "stun",     "3~",       40,  0,         0,  6   ],
        [ "Thompson SMG, .45ACP",                 "Guns: Lt. Auto",          0,    0,  "2d+1",     11,       7,        190,       1750,    "Cr.",      "9*",       30,  -3,       11,  6   ],
        [ "Tommy Gun",                            "Guns: Lt. Auto",          0,    0,  "2d+1",     11,       7,        190,       1750,    "Cr.",      "20*",      30,  -3,       11,  6   ],
        [ "Trapdoor Springfield, .45 45-70",      "Guns: Rifle",             0,    0,  "5d",       15,       8,        700,       1200,    "Cr.",      "1/4",      1,   -2,       11,  6   ],
        [ "Type 96, 6.5X50mm Arisaka",            "Guns: Lt. Auto",          0,    0,  "5d+1",     19,       6,        600,       3000,    "Cr.",      "9",        30,  -1,        0,  6   ],
        [ "Walther PPK, .32ACP",                  "Guns: Pistol",           75, 1.25,  "2d-1",     10,       2,        100,       1467,    "Cr.",      "3~",       7,   -1,        8,  6   ],
        [ "Webley No1, .455W",                    "Guns: Pistol",            0,    0,  "2d",       11,       2,        160,       1600,    "Cr.",      "3~",       6,   -2,       11,  6   ],
        [ "Wheellock, .60",                       "BPW: Pistol",             0,    0,  "1d+1",     13,       1,        75,        400,     "Cr.",      "1/60",     1,   -1,       10,  4   ],
        [ "Winchester '73, .44-40",               "Guns: Rifle",            40,  7.1,  "3d",       13,       7,        300,       2200,    "Cr.",      "2~",       6,   -2,       10,  5   ],
        [ "Winchester '73",                       "Guns: Rifle",             0,    0,  "3d",       13,       7,        300,       2200,    "Cr.",      "~2",       17,  -2,       10,  6   ],
        [ "Winchester '73 Carbine",               "Guns: Rifle",             0,    0,  "3d",       13,       7,        300,       2200,    "Cr.",      "~2",       12,  -2,       10,  6   ],
        [ "Winchester '76, .45",                  "Guns: Rifle",             0,    0,  "4d",       14,       7,        500,       2500,    "Cr.",      "~2",       15,  -2,       10,  6   ],
        [ "Winchester '87, 10g",                  "Guns: Shotgun",           0,    0,  "5d",       13,       5,        25,        150,     "Cr.",      "2~",       4,   -4,       13,  6   ],
        [ "Winchester '94, .30-30",               "Guns: Rifle",           475,    7,  "5d",       13,       8,        450,       3011,    "Cr.",      "2~",       6,   -1,       10,  5   ],
        [ "Winchester '97, 12g",                  "Guns: Shotgun",           0,    0,  "4d",       11,       5,        25,        150,     "Cr.",      "3",        6,   -4,       13,  6   ],
        [ "Winchester 66, .44rf",                 "Guns: Rifle",             0,    0,  "2d+1",     13,       6,        250,       1900,    "Cr.",      "~2",       17,  -1,       10,  6   ],
        [ "Wogdon, .45",                          "BPW: Pistol",             0,    0,  "2d-1",     10,       3,        75,        467,     "Cr.",      "1/20",     1,   -1,        9,  4   ]
    ];
}  // initGuns

//----------------------------------------------------------------------------
function initRangedWeapons()
{
    vRangedWeapons = [
        //                        name              skill                   type   dam     plus SS   Acc RangeHalf RangeMax cost   lbs   minST  TL  notes
        new RangedWeaponsObject( "Boulder",        "Throwing",             "cr",  "thr",   +4,  14,  +0, "-5",   "-5",     0,      0,    0,     0,  "" ),
        new RangedWeaponsObject( "Bow, Composite", "Bow",                  "imp", "thr",   +3,  14,  +3, "*20",  "*25",    900,    4,    10,    3,  "max dam 1d+4" ),
        new RangedWeaponsObject( "Bow, Long",      "Bow",                  "imp", "thr",   +2,  15,  +3, "*15",  "*20",    200,    3,    11,    3,  "max dam 1d+4" ),
        new RangedWeaponsObject( "Bow, Reg.",      "Bow",                  "imp", "thr",   +1,  13,  +2, "*15",  "*20",    100,    2,    10,    3,  "max dam 1d+4" ),
        new RangedWeaponsObject( "Bow, Short",     "Bow",                  "imp", "thr",   +0,  12,  +1, "*10",  "*15",    50,     2,    7,     2,  "max dam 1d+3" ),
        new RangedWeaponsObject( "Bow, Welsh",     "Bow",                  "imp", "thr",   +4,  16,  +4, "*20",  "*25",    900,    3,    12,    3,  "max dam 1d+4" ),
        new RangedWeaponsObject( "Crossbow",       "Crossbow",             "imp", "thr",   +4,  12,  +4, "*20",  "*25",    150,    6,    7,     4,  "max dam 3d" ),
        new RangedWeaponsObject( "Dagger",         "Thrown Weapon|Knife",  "imp", "thr",   -1,  12,  +0, "-5",   "+0",     20,     0.25, 0,     2,  "max dam 1d" ),
        new RangedWeaponsObject( "Fireball",       "Spell Throwing",       "cr", "1d/e",   +0,  13,  +1, "=25",  "=50",    0,      0,    1,     0,  "" ),
        new RangedWeaponsObject( "Hatchet",        "Thrown Weapon|Axe",    "cut", "sw",    +0,  11,  +1, "*1.5", "*2.5",   40,     2,    7,     2,  "" ),
        new RangedWeaponsObject( "Javelin",        "Thrown Weapon|Spear",  "imp", "thr",   +1,  10,  +3, "*1.5", "*2.5",   30,     2,    7,     1,  "" ),
        new RangedWeaponsObject( "Knife (Large)",  "Thrown Weapon|Knife",  "imp", "thr",   +0,  12,  +0, "-2",   "+5",     40,     1,    0,     2,  "max dam 1d+2" ),
        new RangedWeaponsObject( "Knife (Small)",  "Thrown Weapon|Knife",  "imp", "thr",   -1,  11,  +0, "-5",   "+0",     30,     0.5,  0,     2,  "max dam 1d+1" ),
        new RangedWeaponsObject( "Rock",           "Throwing",             "cr",  "thr",   -1,  12,  +0, "*2",   "*3.5",   0,      1,    0,     0,  "" ),
        new RangedWeaponsObject( "Spear",          "Thrown Weapon|Spear",  "imp", "thr",   +3,  11,  +2, "+0",   "*1.5",   40,     4,    9,     1,  "" ),
        new RangedWeaponsObject( "Throwing Axe",   "Thrown Weapon|Axe",    "cut", "sw",    +2,  10,  +2, "+0",   "*1.5",   60,     4,    11,    2,  "" )
    ];

    vRangeSteps = [
       [  +8,        (2/3/12)  ], //  in
       [  +7,        (3/3/12)  ], //  in
       [  +6,        (6/3/12)  ], //  in
       [  +5,        (12/3/12) ], //  in
       [  +4,        (1.5/3)   ], //  ft
       [  +3,        (2/3)     ], //  ft
       [  +2,        1         ], //  hx
       [  +1,        1.5       ], //  hx
       [  +0,        2         ], //  hx
       [  -1,        3         ], //  hx
       [  -2,        4.5       ], //  hx
       [  -3,        7         ], //  hx
       [  -4,        10        ], //  hx
       [  -5,        15        ], //  hx
       [  -6,        20        ], //  hx
       [  -7,        30        ], //  hx
       [  -8,        45        ], //  hx
       [  -9,        70        ], //  hx
       [ -10,        100       ], //  hx
       [ -11,        150       ], //  hx
       [ -12,        200       ], //  hx
       [ -13,        300       ], //  hx
       [ -14,        450       ], //  hx
       [ -15,        700       ], //  hx
       [ -16,        1000      ], //  hx
       [ -17,        1500      ], //  hx
       [ -18,        2000      ], //  hx
       [ -19,        3000      ], //  hx
       [ -20,        4500      ], //  hx
       [ -21,        7000      ], //  hx
       [ -22,        10000     ]  //  hx
    ];
}  // initRangedWeapons

//----------------------------------------------------------------------------
function getRangeModForDistance( hex )
{
    if ( vRangeSteps == null || vRangeSteps == undefined )
    {
        initRangedWeapons();
    }
    var mod = vRangeSteps[0][0];
    for ( var ndx = 0; ndx < vRangeSteps.length; ndx++ )
    {
        mod = vRangeSteps[ndx][0];
        if ( hex <= vRangeSteps[ndx][1] )
        {
            break;
        }
    }
    return mod;
}

//----------------------------------------------------------------------------
function writeRangeSteps()
{
    if ( vRangeSteps == null || vRangeSteps == undefined )
    {
        initRangedWeapons();
    }
    var str = "";
    var step;
    var last = 0;

    str += "<table border=0 cellspacing=0 cellpadding=1>";
    str += "<tr>";
    str += "<th class=column style='text-align:center;'colspan=2>distance/size";
    str += "<th class=column style='text-align:center;'colspan=2>mod";
    str += "<tr>";
    str += "<th class=column style='text-align:center;'>from";
    str += "<th class=column style='text-align:center;'>to";
    str += "<th class=column style='text-align:center;'>distance";
    str += "<th class=column style='text-align:center;'>size";

    for ( var ndx = 0; ndx < vRangeSteps.length; ndx++ )
    {
        step = vRangeSteps[ndx];
        hx = step[1];
        units = "hx";
        if ( hx < 1 )
        {
            hx *= 3;
            units = "ft";
        }
        if ( hx < 1 )
        {
            hx *= 12;
            units = "in";
        }
        str += "<tr>";
        if ( 9 < ndx )
        {
            str += "<td align=right>" + formatfloat(vRangeSteps[ndx-1][1] + 1,0);
        }
        else
        {
            str += "<td align=right>&nbsp;";
        }
        str += "<td align=right>" + String(hx) + " " + units;
        str += "<td align=center>" + getSignedNumber(step[0]);
        str += "<td align=center>" + getSignedNumber(0 - step[0]);
    }
    str += "</table>";

    document.writeln( str );
    return str;
}

//============================================================================
// RangedWeaponsObject
//============================================================================
function RangedWeaponsObject( name, skillname, type, dam, plus, SS, Acc, RangeHalf, RangeMax, cost, lbs, minST, TL, notes )
{
    this.name      = name;
    this.skillname = skillname;
    this.type      = type;
    this.dam       = dam;
    this.plus      = plus;
    this.SS        = SS;
    this.Acc       = Acc;
    this.RangeHalf = RangeHalf;
    this.RangeMax  = RangeMax;
    this.cost      = cost;
    this.lbs       = lbs;
    this.minST     = minST;
    this.TL        = TL;
    this.notes     = notes;
    // derived values
    this.skill = null;
    this.enchantments = null;
    this.RangedWeaponToString = RangedWeaponToString;
    this.getRangedWeaponTableRow = getRangedWeaponTableRow;
}

//----------------------------------------------------------------------------
function RangedWeaponToString()
{
    var str = "RangedWeapon(";
    str += this.name + ",";
    str += this.skillname + ",";
    str += this.type + ",";
    str += this.dam + ",";
    str += String(this.plus) + ",";
    str += String(this.SS) + ",";
    str += String(this.Acc) + ",";
    str += this.RangeHalf + ",";
    str += this.RangeMax + ",";
    str += String(this.cost) + ",";
    str += String(this.lbs) + ",";
    str += String(this.minST) + ",";
    str += String(this.TL) + ",";
    str += this.notes;
    str += ")";
    return str;
}

//----------------------------------------------------------------------------
function getRangedWeaponTableRow()
{
    var str = "";
    str +=  "<tr>";
    str +=  "<td class=widecolumn align=right style='BORDER-LEFT: black 1px solid'>";
    str +=  String(this.lbs);
    if ( gShowMoney )
    {
        str +=  "<td class=widecolumn align=right>$" + String(this.cost);
        incFormValue( "frmRangedWeapons", "valCost", this.cost );
    }
    str +=  "<td class=widecolumn nowrap>" + this.name;
    str +=  "<td class=widecolumn nowrap align=center style='BACKGROUND:#eeddaa; PADDING-LEFT:4; PADDING-RIGHT: 4;'>";
    str += String(this.skill.value);
    str +=  "<td class=widecolumn align=center>" + this.SS;
    str +=  "<td class=widecolumn align=center>+" + this.Acc;
    str +=  "<td class=widecolumn align=center>" + myCharacter.ST;
    //str +=  "<td class=widecolumn align=center>" + this.dam;
    //str +=  "<td class=widecolumn align=left>+" + this.plus;
    var nDam = getDam( valST, this.dam, this.plus );
    str +=  "<td class=widecolumn align=center>";
    str +=  String(nDam);
    str +=  "<td class=widecolumn align=center>" + this.type;

    var move = valST * 2.5;
    if ( this.skillname == "Bow" || this.skillname == "Crossbow" )
    {
        move = valST * 5;
    }
    str +=  "<td class=widecolumn align=center>" + formatfloat(move,0);
    str +=  "<td class=widecolumn align=center nowrap>" + String(getDistance(this.RangeHalf)) + "-" + String(getDistance(this.RangeMax));
    str +=  "<td class=widecolumn nowrap align=left>" + this.notes;

    // enchantments
    if ( this.enchantments != null )
    {
        for ( j = 0; j < this.enchantments.length; j++ )
        {
            str +=  "<tr>";
            mod = this.enchantments[j][1];
            enchantlist = this.enchantments[j][0].split("|");
            enchantment = enchantlist[0];
            str +=  "<td class=widecolumn style='BORDER-LEFT: black 1px solid'>&nbsp;";
            if ( gShowMoney )
            {
                var cost = costOfEnchantment( enchantment, mod );
                str +=  "<td class=widecolumn align=right>";
                //str += "$" + String(cost);
                //incFormValue( "frmRangedWeapons", "valCost", cost );
            }
            if ( enchantment == "Special" )
            {
            }
            else
            {
                str +=  "<td class=widecolumn align=right>";
                str +=  enchantment + " :";
                str +=  "<td class=widecolumn colspan=11 align=left>";
                str +=  (0 <= mod ? "+" : "") + String(mod);
            }
            if ( 1 < enchantlist.length )
            {
                str +=  "<td class=widecolumn colspan=14 style='VERTICAL-ALIGN: top'>";
                for ( jj = 1; jj < enchantlist.length; jj++ )
                {
                    str +=  enchantlist[jj];
                }
            }
        }
    }
    return str;
}

//----------------------------------------------------------------------------
function findRangedWeapon( name )
{
    if ( vRangedWeapons == null || vRangedWeapons == undefined )
    {
        initRangedWeapons();
    }
    for ( var ndx = 0; ndx < vRangedWeapons.length; ndx++ )
    {
        if ( vRangedWeapons[ndx].name == name )
        {
            return new RangedWeaponsObject(
                        vRangedWeapons[ndx].name,
                        vRangedWeapons[ndx].skillname,
                        vRangedWeapons[ndx].type,
                        vRangedWeapons[ndx].dam,
                        vRangedWeapons[ndx].plus,
                        vRangedWeapons[ndx].SS,
                        vRangedWeapons[ndx].Acc,
                        vRangedWeapons[ndx].RangeHalf,
                        vRangedWeapons[ndx].RangeMax,
                        vRangedWeapons[ndx].cost,
                        vRangedWeapons[ndx].lbs,
                        vRangedWeapons[ndx].minST,
                        vRangedWeapons[ndx].TL,
                        vRangedWeapons[ndx].notes )
        }
    }
    return null;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getDistance( factor, st )
{
    if ( st == null ) st = valST;
    var nDistance;
    nDistance = -1;
    nHex = parseInt(factor.substr(1));
    switch ( factor.substr(0,1) )
    {
        case "=" :
            nDistance = nHex;
            break;
        case "+" :
            nDistance = st + nHex;
            break;
        case "-" :
            nDistance = st - nHex;
            break;
        case "*" :
            nDistance = Math.floor(st * nHex);
            break;
        case "/" :
            nDistance = Math.floor(st / nHex);
            break;
    }
    return nDistance;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function writeRangedWeaponTable()
{
    document.writeln ( getRangedWeaponTable() );
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getRangedWeaponTable()
{
    if ( vRangedWeapons == null || vRangedWeapons == undefined )
    {
        initRangedWeapons();
    }
    var str = "";
    str += "<table BORDER=1 CELLSPACING=0 CELLPADDING=1>";

    str += "<tr>";
    str += "<th colspan=99>Ranged Weapons";
    str += "<tr>";
    str += "<th class=column rowspan=2>Name";
    str += "<th class=column rowspan=2>Skill";
    str += "<th class=column rowspan=2>Type";
    str += "<th class=column rowspan=2>Dam";
    str += "<th class=column rowspan=2>Plus";
    str += "<th class=column rowspan=2>SS";
    str += "<th class=column rowspan=2>Acc";
    str += "<th class=column colspan=2>Range";
    str += "<th class=column rowspan=2>Cost";
    str += "<th class=column rowspan=2>Lbs";
    str += "<th class=column rowspan=2>Strength";
    str += "<th class=column rowspan=2>TL";
    str += "<th class=column rowspan=2>Notes";
    str += "<tr>";
    str += "<th class=column>HalfDam";
    str += "<th class=column>Max";

    for ( var ndx = 0; ndx < vRangedWeapons.length; ndx++ )
    {
        str += "<tr valign=top>";
        str += "<td align=left>" + vRangedWeapons[ndx].name;
        str += "<td align=left>" + vRangedWeapons[ndx].skillname;
        str += "<td align=center>" + vRangedWeapons[ndx].type;
        str += "<td align=center>" + vRangedWeapons[ndx].dam;
        str += "<td align=center>" + vRangedWeapons[ndx].plus;
        str += "<td align=center>" + vRangedWeapons[ndx].SS;
        str += "<td align=center>" + vRangedWeapons[ndx].Acc;
        str += "<td align=center>" + vRangedWeapons[ndx].RangeHalf;
        str += "<td align=center>" + vRangedWeapons[ndx].RangeMax;
        str += "<td align=right>$" + vRangedWeapons[ndx].cost;
        str += "<td align=center>" + vRangedWeapons[ndx].lbs;
        str += "<td align=center>" + vRangedWeapons[ndx].minST;
        str += "<td align=center>" + vRangedWeapons[ndx].TL;
        str += "<td>" + vRangedWeapons[ndx].notes;
    }
    str += "</table>";
    return str;
}  // writeRangedWeaponTable

//============================================================================
// BowObject from "The Complete Archer, by Thomas Barnes"
//============================================================================
var lastArrow;
var BowRecurveType;
var BowQualityType;

//----------------------------------------------------------------------------
function printBowsArrows()
{
    lastArrow = createArrow( "Broadhead" );
    BowRecurveType = "none";
    BowQualityType = "normal";
    document.writeln( getBowsArrows() );
    setArrowForBow( lastArrow.name );
}

//----------------------------------------------------------------------------
function getBowsArrows()
{
    var str = "";
    str += "<form name='frmBowsArrows'>";
    str += "<table width=100%>";
    str += "<tr>";
    str += "<td width=40% style='vertical-align: top'>";
    str += "<span id='idBowTable'>" + getBowTable() + "</span>";
    str += "<td style='vertical-align: top' nowrap>";
    str += "Recurve Type:<br>";
    str += "<input type=radio name='chkRecurve' value='none' checked onClick='chkRecurveChange(this)'> none (regular bow)<br>";
    str += "<input type=radio name='chkRecurve' value='Long'         onClick='chkRecurveChange(this)'> long (longbow +25% length)<br>";
    str += "<input type=radio name='chkRecurve' value='passive'      onClick='chkRecurveChange(this)'> passive (-25% length)<br>";
    str += "<input type=radio name='chkRecurve' value='active'       onClick='chkRecurveChange(this)'> active (-25% length, +1 ST)<br>";
    str += "<p>";
    str += "Quality:<br>";
    str += "<input type=radio name='chkQuality' value='fine'           onClick='chkQualityChange(this)'> Fine<br>";
    str += "<input type=radio name='chkQuality' value='normal' checked onClick='chkQualityChange(this)'> Normal<br>";
    str += "<input type=radio name='chkQuality' value='cheap'          onClick='chkQualityChange(this)'> Cheap<br>";
    str += "<td rowspan=2 style='vertical-align: top' align=right>";
    str += "<span id='idArrowTable'>" + getArrowTable(false) + "</span>";
    str += "<tr>";
    str += "<td style='vertical-align: top' colspan=2>";
    str += "where:<br><ul>";
    str += "<li><b>ST: </b>is the ST required to pull the bow";
    str += "<li><b>pull: </b>is the poundage of the bow, based on effective ST";
    str += "<li><b>min length: </b>from text above";
    str += "<li><b>damage: </b>based on effective ST and the arrow";
    str += "<li><b>type: </b>based on the arrow";
    str += "<li><b>SS: </b>+2 for length < 40\", +1 for length < 50\", -1 for length > 65\"";
    str += "<li><b>Acc: </b>-1 for length < 40\", +1 for length > 50\", +2 for length > 65\"";
    //str += "<li><b>Bow mod: </b>-1 for length < 50\", +1 for length > 65\". Also modified by arrow type.";
    str += "<li><b>range: </b>1st value is ½dam, 2nd value is max.  Based on arrow and effective ST.";
    str += "<li><b>move: </b>speed of the arrow in hexes.  The target gets a +1 Dodge for every ½sec that the target can see the arrow coming.";
    str += "<li><b>cost: </b>Base ST ^ 2. Cheap is 60%, Fine is *4.  Passive recurve is +50%, Active recurve is *4 (same as 'fine')";
    str += "<li><b>weight: </b>length / 30.";
    str += "</ul>";
    str += "each of these calculations uses the base length before recurving.";
    str += "<tr>";
    str += "<td id='idArrowNote' style='vertical-align: top' colspan=99>";
    str += "</table>";
    str += "</form>";
    return str;
}

//----------------------------------------------------------------------------
function getBowTable( arrow )
{
    if ( arrow == null ) arrow = createArrow( "Broadhead" );
    BowQualityType = (BowQualityType == null) ? "normal" : BowQualityType;
    var str = "";
    str += "<table border=1 cellspacing=0 cellpadding=0>";
    str += "<tr><th colspan=99>";
    if ( BowRecurveType != null )
    {
        if ( BowRecurveType == "none" )
        {
            str += "Regular Bows";
        }
        else if ( BowRecurveType == "Long" )
        {
            str += "LongBows";
        }
        else
        {
            str += BowRecurveType + " Recurve Bows";
        }
    }
    else
    {
        str += "Regular Bows";
    }
    str += " (" + BowQualityType + ")";
    str += "<tr><th class=column colspan=99>arrow: " + arrow.name;
    str += "<tr>";
    str += "<th class=column>ST";
    str += "<th class=column>pull<br>(lbs)";
    str += "<th class=column>min length<br>(inches)";
    str += "<th class=column>damage";
    str += "<th class=column>type";
    str += "<th class=column>SS";
    str += "<th class=column>Acc";
    str += "<th class=column>Bow<br>mod";
    str += "<th class=column>range<br>(yds)";
    str += "<th class=column>move";
    str += "<th class=column>cost";
    str += "<th class=column>weight<br>(lbs)";
    str += "<th class=column>notes";

    var maxST = 16;
    switch ( BowQualityType )
    {
        case "very fine" :  maxST = 18; break;
        case "fine" :       maxST = 16; break;
        case "cheap" :      maxST = 12; break;
        case "normal" :
        default:            maxST = 14; break;
    }

    for ( var st = 6; st <= maxST; st++ )
    {
        var bow = new Bow( st, BowRecurveType, BowQualityType );
        str += "<tr>";
        str += "<th class=column>" + String(bow.st);
        str += "<td align=center>" + String(bow.getBowPoundage());
        str += "<td align=center>" + String(bow.getBowLength());
        str += "<td align=center>" + String(bow.getBowDam(null,arrow));
        str += "<td align=center>" + String(arrow.type);
        str += "<td align=center>" + String(bow.getBowSS());     // SS
        str += "<td align=center>" + getSignedNumberOrTilda(bow.getBowAcc());     // Acc
        str += "<td align=center>" + getSignedNumberOrTilda(bow.getBowSkill(arrow));     // Bow skill mod
        str += "<td align=center nowrap>" + getDistance( arrow.rangehalf, bow.eST ) + "-" + getDistance( arrow.rangemax, bow.eST );     // range
        str += "<td align=center>" + String(bow.eST * 5);     // move
        str += "<td align=center>$" + formatfloat(bow.cost,0);     // $
        str += "<td align=center>" + formatfloat(bow.lbs,1);     // wt
    }

    str += "</table>";
    return str;
}  // getBowTable

//----------------------------------------------------------------------------
function getArrowTable( bShowNotes )
{
    if ( vArrows == null || vArrows == undefined )
    {
        initArrows();
    }
    bShowNotes = (bShowNotes == null) ? true : bShowNotes;
    var str = "";
    str += "<table BORDER=1 CELLSPACING=0 CELLPADDING=1>";
    str += "<tr><th colspan=99>Arrows";
    str += "<tr>";
    str += "<th rowspan=2 class=column colspan=2>name";
    str += "<th rowspan=2 class=column>penetration<br>(adj DR by...)";
    str += "<th rowspan=2 class=column>dam<br>bonus";
    str += "<th rowspan=2 class=column>type";
    str += "<th rowspan=2 class=column>Bow<br>mod";
    str += "<th colspan=2 class=column>range (STx...)";
    if ( bShowNotes )
    {
        str += "<th rowspan=2 class=column>notes";
    }
    str += "<tr>";
    str += "<th class=column>half";
    str += "<th class=column>max";

    for ( var ndx = 0; ndx < vArrows.length; ndx++ )
    {
        str += "<tr id='idRow" + vArrows[ndx].name + "'>";
        str += "<td>" + "<input name='chkArrow' type='radio' class=radio value='" + vArrows[ndx].name + "'";
        if ( lastArrow != null && lastArrow.name == vArrows[ndx].name )
        {
            str += " checked ";
        }
        str += " onClick='setArrowForBow(this.value)'>";
        if ( bShowNotes )
        {
            str += "<td align=left>" + vArrows[ndx].name;
        }
        else
        {
            str += "<td align=left";
            //str += " onmouseover='setArrowNote( \"" + vArrows[ndx].name + "\" );'";
            str += ">";
            str += vArrows[ndx].name;
        }
        str += "<td align=center>" + getSignedNumberOrTilda( vArrows[ndx].penetration );
        str += "<td align=center>" + getSignedNumberOrTilda( vArrows[ndx].dam );
        str += "<td align=center>" + vArrows[ndx].type;
        str += "<td align=center>" + getSignedNumberOrTilda( vArrows[ndx].skill );
        str += "<td align=center>" + vArrows[ndx].rangehalf;
        str += "<td align=center>" + vArrows[ndx].rangemax;
        if ( bShowNotes )
        {
            str += "<td align=center>" + vArrows[ndx].notes;
        }
    }
    str += "<tr><td colspan=99 style='text-align: left'>where:<ul>";
    str += "<li><b>name</b> - describes the tip or point";
    str += "<li><b>penetration</b> -<br>'-1' = reduce the DR by 1 (like 'Penetrating Blade')<br>'*2' = treat armor as double (DR*2).";
    str += "<li><b>dam bonus</b> - included in 'Bow Table'";
    str += "<li><b>type</b> - damage type";
    str += "<li><b>Bow mod</b> - adj to 'Bow' skill";
    str += "<li><b>Range.half</b> - yds at which arrows do half damage";
    str += "<li><b>Range.max</b> - max. yds. that you can hit something and do damage.";
    str += "</ul>";
    str += "</table>";
    return str;
}  // getArrowTable

//----------------------------------------------------------------------------
function setArrowForBow( name )
{
    if ( lastArrow != null )
    {
        this["idRow" + lastArrow.name]["style"]["background"] = "white";
    }
    var arrow = findArrow( name );
    lastArrow = arrow;
    if ( arrow != null )
    {
        var str = getBowTable( arrow );
        setID( "idBowTable", str );
        setArrowNote( arrow.name );
        this["idRow" + arrow.name]["style"]["background"] = "silver";
    }
}

//----------------------------------------------------------------------------
function chkRecurveChange( obj )
{
    BowRecurveType = obj.value;
    setID( "idBowTable", getBowTable( lastArrow ) );
}

//----------------------------------------------------------------------------
function chkQualityChange( obj )
{
    BowQualityType = obj.value;
    setID( "idBowTable", getBowTable( lastArrow ) );
}

//----------------------------------------------------------------------------
function setArrowNote( name )
{
    var arrow = findArrow( name );
    if ( arrow != null )
    {
        var str = "";
        str += "<b>" + arrow.name + "</b><p>";
        str += arrow.notes;
        setID( "idArrowNote", str );
    }
}

//============================================================================
function Bow( st, recurve, quality, length, enchantments, arrows )
{
    this.name = "longbow";
    this.st = st;
    this.eST = st;                      // effective Strength
    this.recurve = recurve;
    this.quality = quality;
    this.length = length;
    this.enchantments = enchantments;
    this.arrows = arrows;
    // derived values
    this.lbs = 0;
    this.cost = 1000;
    this.notes = "";
    this.skill = null;
    this.BowToString = BowToString;
    this.getBowPoundage = getBowPoundage;
    this.getBowLength = getBowLength;
    this.getBowDam = getBowDam;
    this.getBowSS = getBowSS;
    this.getBowAcc = getBowAcc;
    this.getBowSkill = getBowSkill;
    this.getBowTableRow = getBowTableRow;
    // effective ST
    if ( this.recurve == "active" )
    {
        this.eST++;
    }
    switch ( this.recurve )
    {
        case "active" :     this.name = "active recurve bow"; break;
        case "passive" :    this.name = "recurve bow"; break;
        case "none" :
        default:
    }
    switch ( this.quality )
    {
        case "very fine" :
            this.eST += 2;
            this.notes = this.quality;
            break;
        case "fine" :
            this.eST += 1;
            this.notes = this.quality;
            break;
        case "cheap" :
            this.eST -= 1;
            this.notes = this.quality;
            break;
    }
    if ( this.length == null )
    {
        // minimum length
        this.length = 36;
        if ( 8 <= this.st ) this.length = 48;
        //if ( 12 <= this.st ) this.length = 52;
        if ( 13 <= this.st ) this.length = 60;
        if ( 14 <= this.st ) this.length = 80;
    }
    this.notes += ", " + String(this.length) + "in.";
    this.lbs = this.length / 30.0;
    this.cost = this.st * this.st;
    switch ( this.recurve )
    {
        case "active" :
            this.cost *= 4;   // same as 'Fine' quality
            break;
        case "passive" :
            this.cost *= 1.5; // add 50%
            break;
        case "long" :
        case "Long" :
            this.cost *= 1.25; // add 25%
            break;
    }
    switch ( this.quality )
    {
        case "very fine" : this.cost *= 20;   break;
        case "fine" :      this.cost *= 4;    break;
        case "cheap" :     this.cost *= 0.60; break;
        case "normal" :
        default:
            break;
    }
    if ( this.enchantments != null )
    {
        for ( j = 0; j < this.enchantments.length; j++ )
        {
            mod = this.enchantments[j][1];
            enchantlist = this.enchantments[j][0].split("|");
            enchantment = enchantlist[0];
            this.cost += costOfEnchantment( enchantment, mod );
        }
    }
    if ( myCharacter != null )
    {
        this.skill = getSkillObject( "Bow" );
    }
}  // Bow

//----------------------------------------------------------------------------
function BowToString()
{
    var str = "";
    str += this.name
    str += ", " + this.quality
    str += ((this.recurve != null) ? (", " + this.recurve) : "")
    str += ", " + String(this.st)
    str += ", " + String(this.eST)
    str += ", " + String(this.length) + "in."
    str += ", " + formatfloat(this.lbs,1) + "#"
    str += ", $" + String(this.cost)
    str += ", " + this.notes
    str += ".";
    //str += ", " + this.arrows
    //str += ", " + this.skill
    //str += ", " + this.enchantments
    return str;
}

//----------------------------------------------------------------------------
function getBowPoundage()
{
    var lbs = 10;
    if (  6 <= this.eST ) lbs =  15;
    if (  7 <= this.eST ) lbs =  20;
    if (  8 <= this.eST ) lbs =  25;
    if (  9 <= this.eST ) lbs =  30;
    if ( 10 <= this.eST ) lbs =  40;
    if ( 11 <= this.eST ) lbs =  55;
    if ( 12 <= this.eST ) lbs =  70;
    if ( 13 <= this.eST ) lbs =  85;
    if ( 14 <= this.eST ) lbs = 110;
    if ( 15 <= this.eST ) lbs = 140;
    if ( 16 <= this.eST ) lbs = 165;
    if ( 17 <= this.eST ) lbs = 195;
    if ( 18 <= this.eST ) lbs = 225;
    if ( 19 <= this.eST ) lbs = 250;
    if ( 20 <= this.eST ) lbs = 275;
    return lbs;
}  // getBowPoundage


//----------------------------------------------------------------------------
function getBowLength()
{
    var length = this.length;
    switch ( this.recurve )
    {
        case "active" :
        case "passive" :
            length *= 0.75;
            break;
        case "long" :
        case "Long" :
            length *= 1.25;
            break;
        case "none" :
        default:
    }
    return length;
}  // getBowLength

//----------------------------------------------------------------------------
function getBowDam( st, arrow )
{
    var eST = this.eST;                 // the effective ST defaults to that of the bow
    if ( st != null )
    {
        if ( st < this.st )
        {
            // if the archers ST is less than that required to pull the bow,
            // then use the archers ST.
            eST = st;
        }
    }
    if ( arrow == null && this.arrows != null ) arrow = this.arrows[0];
    if ( arrow == null ) arrow = createArrow( "Broadhead" );
    var type = "thr";
    var plus = arrow.dam;
    var dam = getDam( eST, type, plus );
    return dam;
}  // getBowDam

//----------------------------------------------------------------------------
function getBowSS()
{
    //var SS = 13;
    var SS = 4;
    var length = this.getBowLength();
    if ( length < 40 ) SS--;
    if ( length < 50 ) SS--;
    if ( 65 < length ) SS++;
    if ( 75 < length ) SS++;
    return -SS;
}

//----------------------------------------------------------------------------
function getBowAcc()
{
    var Acc = 2;
    var length = this.length;
    if ( this.recurve == "long" || this.recurve == "Long" )
    {
        length = this.getBowLength();
    }
    if ( length < 40 ) Acc--;
    if ( 50 < length ) Acc++;
    if ( 65 < length ) Acc++;
    return Acc;
}

//----------------------------------------------------------------------------
function getBowSkill( arrow )
{
    if ( arrow == null && this.arrows != null ) arrow = this.arrows[0];
    if ( arrow == null ) arrow = createArrow( "Broadhead" );
    var skill = arrow.skill;
    //if ( this.length < 50 ) skill--;
    //if ( 65 < this.length ) skill++;
    if ( this.quality == "cheap" ) skill--;
    if ( this.enchantments != null )
    {
        for ( j = 0; j < this.enchantments.length; j++ )
        {
            mod = this.enchantments[j][1];
            enchantlist = this.enchantments[j][0].split("|");
            enchantment = enchantlist[0];
            if ( enchantment == "Accuracy" )
            {
                skill += mod;
            }
        }
    }
    return skill;
}

//----------------------------------------------------------------------------
function getBowTableRow( arrow )
{
    var broadhead = createArrow( "Broadhead" );
    var str = "";
    str +=  "<tr>";
    str +=  "<td class=widecolumn align=right style='BORDER-LEFT: black 1px solid; VERTICAL-ALIGN:top;'>" + formatfloat(this.lbs,1);
    if ( gShowMoney )
    {
        str +=  "<td class=widecolumn align=right style='VERTICAL-ALIGN:top;'>$" + String(this.cost);
        incFormValue( "frmRangedWeapons", "valCost", this.cost );
    }
    str +=  "<td class=widecolumn nowrap onmouseover='window.status=\"" + this.BowToString() + "\";'>";
    if ( arrow == null )
    {
        if ( this.arrows == null )
        {
            str += this.name + "/" + broadhead.name;
        }
        else
        {
            for ( var i = 0; i < this.arrows.length; i++ )
            {
                str += this.name + "/" + this.arrows[i].name + "<br>";
            }
        }
    }
    else
    {
        str += this.name + "/" + arrow.name;
    }
    str +=  "<td class=widecolumn nowrap align=center style='BACKGROUND:#eeddaa; PADDING-LEFT:4; PADDING-RIGHT: 4; VERTICAL-ALIGN:top;'>";
    if ( this.skill == null )
    {
        this.skill = getSkillObject( "Bow" );
    }

    if ( arrow == null )
    {
        if ( this.arrows == null )
        {
            str += String(this.skill.value + this.getBowSkill(broadhead));
        }
        else
        {
            for ( var i = 0; i < this.arrows.length; i++ )
            {
                str += String(this.skill.value + this.getBowSkill(this.arrows[i])) + "<br>";
            }
        }
    }
    else
    {
        str += String(this.skill.value + this.getBowSkill(arrow));
    }

    str +=  "<td class=widecolumn align=center style='VERTICAL-ALIGN:top;'>" + this.getBowSS();
    str +=  "<td class=widecolumn align=center style='VERTICAL-ALIGN:top;'>+" + this.getBowAcc();
    str +=  "<td class=widecolumn align=center style='VERTICAL-ALIGN:top;'>" + this.eST;

    if ( arrow == null )
    {
        if ( this.arrows == null )
        {
            str +=  "<td class=widecolumn align=center>" + String(this.getBowDam( valST, broadhead ));
            str +=  "<td class=widecolumn align=center>" + broadhead.type;
            str +=  "<td class=widecolumn align=center>" + formatfloat(this.eST * 5,0);
            str +=  "<td class=widecolumn align=center nowrap>" + String(getDistance(broadhead.rangehalf)) + "-" + String(getDistance(broadhead.rangemax));
        }
        else
        {
            str += "<td class=widecolumn align=center>";
            for ( var i = 0; i < this.arrows.length; i++ ) str += String(this.getBowDam( valST, this.arrows[i] )) + "<br>";
            str += "<td class=widecolumn align=center>";
            for ( var i = 0; i < this.arrows.length; i++ ) str += this.arrows[i].type + "<br>";
            str += "<td class=widecolumn align=center style='VERTICAL-ALIGN:top;'>" + formatfloat(this.eST * 5,0) + "<br>";
            str += "<td class=widecolumn align=center nowrap>";
            for ( var i = 0; i < this.arrows.length; i++ ) str += String(getDistance(this.arrows[i].rangehalf)) + "-" + String(getDistance(this.arrows[i].rangemax)) + "<br>";
        }
    }
    else
    {
        str +=  "<td class=widecolumn align=center>" + String(this.getBowDam( valST, arrow ));
        str +=  "<td class=widecolumn align=center>" + arrow.type;
        str +=  "<td class=widecolumn align=center>" + formatfloat(this.eST * 5,0);
        str +=  "<td class=widecolumn align=center nowrap>" + String(getDistance(arrow.rangehalf)) + "-" + String(getDistance(arrow.rangemax));
    }

    if ( this.notes != null )
    {
        str +=  "<td class=widecolumn nowrap align=left style='VERTICAL-ALIGN:top;'>" + this.notes;
    }

    // enchantments
    if ( this.enchantments != null )
    {
        for ( j = 0; j < this.enchantments.length; j++ )
        {
            mod = this.enchantments[j][1];
            enchantlist = this.enchantments[j][0].split("|");
            enchantment = enchantlist[0];
            if ( enchantment == "Special" )
            {
            }
            else
            {
                str += " " + enchantment + ":";
                str += (0 <= mod ? "+" : "") + String(mod);
            }
            if ( 1 < enchantlist.length )
            {
                for ( jj = 1; jj < enchantlist.length; jj++ )
                {
                    str += ", " + enchantlist[jj];
                }
            }
        }
    }
    return str;
}


//============================================================================
// ArrowObject
//============================================================================
var vArrows;
//============================================================================
function initArrows()
{
    vArrows = new Array();
    vArrows[vArrows.length] = new Arrow( "Blunt",       "0", -2, "cr", 0, "*15", "*20", "These arrows have blunt heads and are designed to hunt very small game such as birds or rabbits. When fired against any target larger than 20 lbs. they do -2 points of basic damage per die of damage. Against smaller targets they do normal damage." );
    vArrows[vArrows.length] = new Arrow( "Bodkin",     "-1", +1, "imp", 0, "*15", "*20", "These arrows are heavier than normal and have a hardened, barbless (or nearly barbless) head. They were used by medieval and ancient archers to pierce plate armor." );
    vArrows[vArrows.length] = new Arrow( "Broadhead",   "0", +2, "imp", -1, "*20", "*25", "This is a double-edged, barbed arrow with a triangular or leaf-shaped head. Variants of this design are found around the world. This is the standard combat and big-game arrow. A successful roll vs. First Aid or Surgery is required to remove the arrow without doing an additional 1d6-3 points of additional damage." );
    vArrows[vArrows.length] = new Arrow( "Cresent",     "0", 0, "cut", -1, "*10", "*15", "Some ancient Mediterranean cultures had arrows with heads that looked like a crescent moon. The points faced forward and the concave leading edge was sharpened. It is reported that these arrows were used to decapitate ostriches." );
    vArrows[vArrows.length] = new Arrow( "Flu-Flu",     "0", -2, "cr", 0, "*5", "*10", "A variant on the Blunt Head, these arrows have extremely large, long fletches which produce a large amount of drag, which stabilizes the arrow, but also makes it fly much more slowly and decreases range. For small game hunting in dense vegetation, the short range and large fletches make the arrow much easier to find, giving +4 to Vision rolls to retrieve arrows." );
    vArrows[vArrows.length] = new Arrow( "Forked",     "*2", +1, "imp", -1, "*15", "*20", "Forked arrows have heads that are trident or fork shaped. They were used by ancient archers as well as Feudal Japanese Samurai (who called them 'Bowel Rakers'). Variants of this design are also used to hunt fish. It is designed to do as much damage as possible to the enemy's vitals and its barbs keep it from being pulled out. They tend to be heavy and unbalanced, so they are at -1 to hit. DR of armor is doubled, but damage which gets through armor is doubled. It does +1 to basic damage. A successful roll vs. First Aid or Surgery is required to remove the arrow without doing an additional 1d3-1 points of additional damage." );
    vArrows[vArrows.length] = new Arrow( "Field",       "0", -1, "imp", +1, "*20", "*25", "Field points are designed for hunting small game and target archery." );
    vArrows[vArrows.length] = new Arrow( "Flying",      "0", -2, "imp", 0, "*20", "*35", "This sort of arrow is designed to be fired at extremely long ranges. It is very light and is designed to be areodynamic as possible. It is especially popular in Turkey and other Arabic countries where distance shooting was a popular sport.<p>It is virtually useless except as a sport arrow, but clever characters might use it for signalling or for carrying messages. Shafts are light and long and the heads are very small, so this arrow gives -2 to basic damage, but maximum damage is 1d6-3 points." );
    vArrows[vArrows.length] = new Arrow( "Frog Crotch", "0", -1, "cr", -1, "*15", "*20", "This is another Japanese arrow and was used to demonstrate the precision of the archer's aim. The head was a U-shaped cutting blade, suitable for slicing though a rope. On a good enough roll (depending on distance and size of the targ et), it could down a banner, sever a fan tied to a ship's mast, or cut lacings that held a samurai's helmet or armor. <p>Against ropes and similar objects it does normal Thrust/Cut damage." );
    vArrows[vArrows.length] = new Arrow( "Humming",     "0", -1, "cr", -1, "*15", "*20", "This sort of arrow has a bulb-shaped head with holes drilled through it so it whistles or 'screams' as it flies. It is also called a turnip-head arrow. It was used by Feudal Japanese Samurai and some Ancient cultures. In Japan, it was customary to begin a battle by firing these arrows over the heads of the enemies, but they could also be used for signalling. Sometimes fighters filled the turnip-head with black powder and lit it, creating a fire-arrow. This did no damage to an enemy but would set inflammable material on fire." );
    vArrows[vArrows.length] = new Arrow( "Incindiary",  "0", 0, "imp", -1, "*15", "*20", "Any sort of arrow can be turned into an incindiary by wrapping a wad of flammable material around the shaft and igniting it. It takes 1d6 turns to set an incindiary arrow on fire from a ready flame source. Incindiary arrows go out on a roll of 6 on 1d6. They do no extra damage, but will eventually set flammable materials on fire. The arrows are destroyed by the fire. Incindiary arrows do damage like their head type." );
    vArrows[vArrows.length] = new Arrow( "Judo",        "0", -2, "cr", 0, "*15", "*20", "Some blunts have a small wire 'framework' built around the tip to better hit small targets such as birds and are called 'Judo' tips. They are a modern invention, but there is no reason why they could not have been developed at a lower Tech Level. These give +1 to skill to hit any object less than 1 foot in diameter. Another benefit is that if they miss, they don't 'burrow' into the leaves and grass. This gives +4 to Vision rolls to retrieve Judo arrows." );
    vArrows[vArrows.length] = new Arrow( "Leaf-Head",   "0", +2, "imp", 0, "*20", "*25", "This is a leaf-shaped arrow used by a number of cultures. It does the same damage as a broad-head arrow but can be removed without doing extra damage." );
    vArrows[vArrows.length] = new Arrow( "Poison",      "0", -1, "imp", +1, "*20", "*25", "Any arrow which does impaling or cutting damage can be poisoned. However, arrows which are specially designed to be poisoned have long, thin points with multiple barbs to allow the poison to adhere better.  Treat a specially made poison arrow as a field point arrow but allow the poison to take effect normally. Other types of arrows which are poisoned give +1 to the victim's HT roll since they are smooth and the head is relatively small." );
    vArrows[vArrows.length] = new Arrow( "Pyrotechnic", "0", 0, "imp", 0, "*20", "*25", "Medieval ninja used arrows loaded with black powder and pyrotechnics; they do no damage, but are very distracting. A nighttime volley of such arrows (10 or more arrows shot at the same time) will create such a din of noise and light that all Alertness, Hearing and Vision rolls for the next minute are at -4, cumulative with poor lighting bonuses. Characters with the Night Vision advantage lose their immunity to darkness for 20-HT seconds (minimum of 1), as the flashes of light will dazzle them badly. Single arrows will create a Flash effect which will temporarily blind all viewers within 10 yards (all Vision rolls at -3 in addition to normal darkness penalties; characters with Night Vision will lose that advantage for 2d turns).<p>Pyrotechnic arrows can set things on fire like Incendiary arrows.<p>A pyrotechnic arrow can be made out of a normal arrow in about an hour if a successful Demolitions or Fireworks-2 skill is made. After the first arrow is made, if materials are at hand, subsequent arrows can be modified in about 30 minutes." );
    vArrows[vArrows.length] = new Arrow( "Target",      "0", -1, "imp", +1, "*15", "*25", "Target points are used for sport archery. They are the smallest and most areodynamically-shaped of the arrowhead types." );
}

//----------------------------------------------------------------------------
function Arrow( name, penetration, dam, type, skill, rangehalf, rangemax, notes )
{
    this.name        = name;
    this.penetration = penetration;
    this.dam         = dam;
    this.type        = type;
    this.skill       = skill;
    this.rangehalf   = rangehalf;
    this.rangemax    = rangemax;
    this.notes       = notes;
}

//----------------------------------------------------------------------------
function createArrow( name )
{
    var arrow = findArrow( name );
    if ( arrow != null )
    {
        return new Arrow( arrow.name,
                          arrow.penetration,
                          arrow.dam,
                          arrow.type,
                          arrow.skill,
                          arrow.rangehalf,
                          arrow.rangemax,
                          arrow.notes );
    }
    return null;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function findArrow( name )
{
    if ( vArrows == null || vArrows == undefined )
    {
        initArrows();
    }
    var arrow = null;
    for ( var ndx = 0; ndx < vArrows.length; ndx++ )
    {
        if ( vArrows[ndx].name == name )
        {
            return vArrows[ndx];
        }
    }
    return arrow;
}

//============================================================================
// Armor
//============================================================================
function writeArmorTable()
{

    document.writeln ( "<table BORDER=0 CELLSPACING=0 CELLPADDING=0>" );
    document.writeln ( "<tr>" );

    document.writeln ( "<th class=column>armor" );
    document.writeln ( "<th class=column>type" );
    document.writeln ( "<th class=column>cost" );
    document.writeln ( "<th class=column>lbs" );
    document.writeln ( "<th class=column>PD" );
    document.writeln ( "<th class=column>DR" );
    document.writeln ( "<th class=column>notes" );

    for ( armor = 0; armor < vArmor.length; armor++ )
    {
        document.writeln ( "<tr valign=top>" );
        document.writeln ( "<td>" + vArmor[armor][0] );  // armor
        document.writeln ( "<td>" + vArmor[armor][1] );  // type
        document.writeln ( "<td align=right>$" + vArmor[armor][2] );  // cost
        document.writeln ( "<td align=right>" + vArmor[armor][3] ); // lbs
        document.writeln ( "<td align=right>+" + vArmor[armor][4] );  // PD
        document.writeln ( "<td align=right>+" + vArmor[armor][5] );  // DR
        document.writeln ( "<td>" + vArmor[armor][6] );  // notes
    }
    document.writeln ( "</table>" );
}

//----------------------------------------------------------------------------
function initArmor()
{
    vArmor = [
            // armor                type     $     lbs  PD DR  notes
            // 0                    1        2      3   4  5   6
            ["Buckler",            "Shield", 25,   2,   1, 0, ""],
            ["Chainmail",          "Armor",  550,  45,  3, 4, "+1/+2 PD/DR vs. imp attacks"],
            ["Cloak",              "Armor",  0,    1,   1, 0, "back and side only"],
            ["Cloth armor",        "Armor",  180,  14,  1, 1, ""],
            ["Half Plate",         "Armor",  2000, 70,  4, 5, ""],
            ["Heavy Leather",      "Armor",  350,  20,  2, 2, ""],
            ["Heavy Plate",        "Armor",  6000, 110, 4, 7, ""],
            ["Hvy Dragon Leather", "Armor",  1400, 20,  3, 3, ""],
            ["Lg. Shield",         "Shield", 90,   25,  4, 0, ""],
            ["Light Leather",      "Armor",  210,  10,  1, 1, ""],
            ["Light Plate",        "Armor",  4000, 90,  4, 6, ""],
            ["Lt. Dragon Leather", "Armor",  840,  10,  2, 2, ""],
            ["Med. Shield",        "Shield", 60,   15,  3, 0, ""],
            ["Natural",            "Armor",  0,    0,   0, 0, "natural protection"],
            ["Robes",              "Armor",  20,   2,   0, 0, ""],
            ["Scalemail",          "Armor",  750,  50,  3, 4, ""],
            ["Sm. Shield",         "Shield", 40,   8,   2, 0, ""],
            ["Summer Clothing",    "Armor",  20,   2,   0, 0, ""],
            ["Winter Clothing",    "Armor",  60,   5,   0, 1, ""],
            ["none",               "Armor",  0,    0,   0, 0, ""]
        ];
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function ndxOfSkill( skill )
{
    return ndxOfTable( skill, vSkills );
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function ndxOfWeapon( weapon )
{
    return ndxOfTable( weapon, vWeapons );
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function ndxOfGun( gun )
{
    return ndxOfTable( gun, vGuns );
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function ndxOfArmor( armor )
{
    return ndxOfTable( armor, vArmor );
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function ndxOfSpell( spell )
{
    if ( vSpells == null || vSpells == undefined )
    {
        initSpells();
    }
    return ndxOfTable( spell, vSpells );
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function ndxOfTable( item, vTable )
{
    var ndx, ndxLo, ndxHi, ndxLast;
    if ( gDebug )
    {
        document.writeln( "ndxOfTable(" + item + ").start" );
        document.writeln( "vTable=" + vTable );
        document.writeln( "<br>" );
    }
    ndxLo = 0;
    ndxHi = vTable.length - 1;
    ndx = Math.floor((ndxHi - ndxLo) / 2 + ndxLo);

    while( item != vTable[ndx][0] )
    {
        if ( ndxLo == ndxHi )
        {
            ndx = -1;
            if ( gDebug )
            {
                document.writeln( "ndxOfTable(" + item + ") not found" );
                document.writeln( "<br>" );
            }
            break;
        }

        ndxLast = ndx;
        if( item < vTable[ndx][0] )
        {
            ndxHi = ndx;
            ndx = Math.floor((ndxHi - ndxLo) / 2 + ndxLo);
        }
        else
        {
            ndxLo = ndx;
            ndx = Math.floor((ndxHi - ndxLo) / 2 + ndxLo);
        }
        if ( ndx == ndxLast )
        {
            ndxLo++;
            ndx = Math.floor((ndxHi - ndxLo) / 2 + ndxLo);
            if ( gDebug )
            {
                document.writeln( "ndxOfTable(" + item + ") ndx++ = " + String(ndx));
                document.writeln( "<br>" );
            }
        }
    }
    if ( gDebug )
    {
        document.writeln( "ndxOfTable(" + item + ").done ndx=" + String(ndx) );
        document.writeln( "<br>" );
    }
    return ndx;
}

//----------------------------------------------------------------------------
function initSpells()
{
    initSpellColumns();
    vSpells = [
        // Spell,Difficulty,Class,Resistance,College,CastingTime,Duration,Energy,Prerequisite,ItemEnergyCost,ItemValue
        [ "Accuracy","MH","Enchantment","~","Enchantment","1s","Perm","var","Dexterity",-1,-1 ],
        [ "Activate Runes","MVH","Regular","~","Meta-Spells","1s","Instant","none","M, Rune-Lore 12+",-1,-1 ],
        [ "Age","MVH","Regular","HT","Necromatic","1m","Perm","5 to 50","Youth or 6 other Necro.",2000,50000 ],
        [ "Air Jet","MH","Regular","~","Air","1s","1s","1 to 3","Shape Air",200,1790 ],
        [ "Air-Golem","MH","Regular","~","Movement","10s","1h","4/2","M2, Apportation",400,10000 ],
        [ "Alarm","MH","Regular","~","Knowlege","1s","1w","1","Tell Time",60,60 ],
        [ "Alertness","MVH","Regular","~","Mind Control","1s","10m","var","Any 2 of keen eyes/ears/nose",300,7500 ],
        [ "Alter Body","MH","Regular","HT","Body Control","2m","1h","8/6","Alter Visage",4000,100000 ],
        [ "Alter Visage","MH","Regular","HT","Body Control","1m","1h","4/3","Shapeshifting or Perf Illusion",1000,25000 ],
        [ "Analyze Magic","MH","Information","Spell","Knowlege","1h","Instant","8","Identify Spell",1200,30000 ],
        [ "Ancient History","MH","Information","~","Knowlege","min=cost","Instant","var","History",-1,-1 ],
        [ "Animate Plant","MH","Regular","~","Plant","5s","1m","var","7 Plant Spells",150,505 ],
        [ "Animation","MVH","Regular","~","Necromatic","5s","1m","var","Summon Spirit",300,7500 ],
        [ "Apportation","MH","Regular","IQ","Movement","1s","1m","var","M",900,22500 ],
        [ "Armor","MH","Regular","~","Protection & Warning","1s","1m","2/DR+|same","Repair",-1,-1 ],
        [ "Astral Vision","MVH","Regular","~","Knowlege","1s","1m","4|2","Sense Spirit and See Invisible",900,22500 ],
        [ "Aura","MH","Information","~","Knowlege","1s","Instant","3","Detect Magic",100,100 ],
        [ "Avoid","MH","Area","~","Mind Control","1m","1h","3/3","Hide, Fear, Forgetfulness",300,7500 ],
        [ "Awaken","MH","Area","~","Healing","1s","Instant","1","Lend Health",300,7500 ],
        [ "Bane","MH","Enchantment","~","Enchantment","-","Perm","100","Enchant",-1,0 ],
        [ "Banish","MH","Special","ST+IQ","Necromatic","5s","Instant","special","M, 1 spell from ea. ten colleges",-1,-1 ],
        [ "Banquet","MH","Regular","~","Food","1s","1d","2/meal","M, Cook, Foolishness",600,15000 ],
        [ "Beast Link","MH","Regular","~","Animal","5s","special","3","Beast Summoning",500,12500 ],
        [ "Beast Possession","MH","Regular","IQ","Animal","5s","1m","6/2","Rider Within or Possesion",1500,37500 ],
        [ "Beast Seeker","MH","Information","~","Animal","1s","Instant","3","Beast Summoning, 2 seek or seeker",-1,-1 ],
        [ "Beast Speech","MH","Regular","~","Animal","1s","1m","4/2","Beast Summoning",1000,25000 ],
        [ "Beast Summoning","MH","Regular","~","Animal","1s","1m","3/2","Beast-Soother",400,10000 ],
        [ "Beast-Soother","MH","Regular","~","Animal","1s","Perm","1 to 3","Persuassion or Animal Empathy",600,15000 ],
        [ "Berserker","MH","Regular","IQ","Mind Control","4s","10m","3/2","Bravery",500,12500 ],
        [ "Bird Control","MH","Regular","IQ","Animal","1s","1m","4/2","Beast-Soother",400,10000 ],
        [ "Bless","MH","Regular","~","Meta-Spells","1m/e","10,50,500","until lost","M2, 2 spells each ten colleges",100,100 ],
        [ "Bless Plants","MH","Area","~","Plant","5m","1crop/season","1","Heal Plant",500,12500 ],
        [ "Blink","MH","Blocking","~","Movement","1s","Instant","2","Teleport",800,20000 ],
        [ "Block","MH","Blocking","~","Protection & Warning","~","Instant","1/PD","M",-1,-1 ],
        [ "Blur","MH","Regular","~","Light & Darkness","2s","1m","1 to 5|same","Darkness",100,100 ],
        [ "Body of Air","MH","Regular","HT","Air","5s","1m","4/1","Shape Air",800,20000 ],
        [ "Body of Stone","MVH","Regular","HT","Earth","5s","1m","10/hex","Stone To Flesh",1500,37500 ],
        [ "Body of Water","MH","Regular","HT","Water","5s","1m","5/hex","Shape Water",1200,30000 ],
        [ "Boost DX","MH","Blocking","~","Body Control","~","~","1/1 (max5)","Dexterity",-1,-1 ],
        [ "Boost HT","MH","Blocking","~","Body Control","~","~","1/1 (max5)","Vigor",-1,-1 ],
        [ "Boost ST","MH","Blocking","~","Body Control","~","~","1/1 (max5)","Might",-1,-1 ],
        [ "Borrow Language","MH","Regular","~","Communication","3s","1m","3/1","Lend Language",-1,-1 ],
        [ "Borrow Skill","MH","Regular","~","Communication","3s","1m","4/3","Lend Skill",-1,-1 ],
        [ "Bravery","MH","Area","IQ-1","Mind Control","1s","1h","2","Fear",500,12500 ],
        [ "Breathe Air","MH","Regular","~","Water","1s","1m","4|2","Create Water, Destroy Air",150,505 ],
        [ "Breathe Fire","MVH","Regular","~","Fire","2s","1s","1 to 4","M, Flame Jet, Resist Fire",1000,25000 ],
        [ "Breathe Water","MH","Regular","~","Air/Water","1s","1m","4|2","Create Air, Destroy Water",400,10000 ],
        [ "Catch Missile","MH","Blocking","~","Protection & Warning","~","~","2","Deflect Missile",300,7500 ],
        [ "Catch Spell","MVH","Blocking","~","Meta-Spells","~","~","3","M2, DX12+, Return Missle",-1,-1 ],
        [ "Charm","MH","Regular","IQ","Mind Control","3s","1m","6/3","M, Loyalty, 7 Mind Control",3000,75000 ],
        [ "Clean","MH","Area","~","Making & Breaking","1s","Perm","2","Restore",100,100 ],
        [ "Climbing","MH","Regular","~","Body Control","1s","1m","1 to 3|same","None",250,4510 ],
        [ "Clouds","MH","Area","~","Air","10s","10m","1/20|same","4 Water, 4 Air",300,7500 ],
        [ "Clumsiness","MH","Regular","IQ","Body Control","1s","1m","var","Spasm",800,20000 ],
        [ "Cold","MH","Regular","~","Fire","1m","1m","3/hex","Heat",400,10000 ],
        [ "Colors","MH","Regular","~","Light & Darkness","1s","1m","2|1","Light",-1,-1 ],
        [ "Compel Truth","MH","Information","IQ","Communication","1s","5m","4|2","M2, Truthsayer",600,15000 ],
        [ "Complex Illusion","MH","Area","~","Illusion & Creation","1s","1m","2|1","Sound, Simple Illusion",-1,-1 ],
        [ "Conceal Magic","MH","Regular","~","Meta-Spells","3s","10h","1 to 5 s","Detect Magic",100,100 ],
        [ "Consecrate","MH","Enchantment","~","Clerical","5m","Perm","10","~",-1,-1 ],
        [ "Continual Light","MH","Regular","~","Light & Darkness","1s","var","var","Light",400,10000 ],
        [ "Control Creation","MH","Regular","spell","Illusion & Creation","2s","Instant","1/hex","Create Animal or Create Servant",400,10000 ],
        [ "Control Elemental","MH","Special","~","4 Diff.","2s","1m","special","Summon Elemental",1000,25000 ],
        [ "Control Illusion","MH","Regular","spell","Illusion & Creation","2s","Perm","1/hex","Perfect Illusion",300,7500 ],
        [ "Control Person","MH","Regular","IQ","Communication","10s","1m","6/3","Soul Rider or Telepathy",1500,37500 ],
        [ "Control Zombie","MH","Regular","spell","Necromatic","1s","Perm","3","Zombie",500,12500 ],
        [ "Cook","MH","Regular","~","Food","5s","Instant","1/meal","Test Food, Create Fire",90,90 ],
        [ "Copy","MH","Regular","~","Making & Breaking","5s","Perm","2+1/copy","Literacy, Dye",-1,-1 ],
        [ "Cornucopia","MH","Enchantment","~","Enchantment","-","Perm","50x$ value","M2, 2 Weapon Enchantment",-1,-1 ],
        [ "Counterspell","MH","Regular","spell","Meta-Spells","5s","Instant","var","M",-1,-1 ],
        [ "Create Air","MH","Area","~","Air","1s","5s","1","Purify Air",200,1790 ],
        [ "Create Animal","MH","Regular","~","Illusion & Creation","sec=cost","1m","var","Create Water, Create Object, IQ 13+",-1,-1 ],
        [ "Create Earth","MH","Regular","~","Earth","1s","Perm","4/hex","Earth To Stone",500,12500 ],
        [ "Create Elemental","MH","Special","~","4 Diff.","special","Perm","special","M2, Control Elemental",-1,-1 ],
        [ "Create Fire","MH","Area","~","Fire","1s","1m","2/1","Ignite Fire",300,7500 ],
        [ "Create Food","MH","Regular","~","Food","30s","Perm","3/meal","Cook, Seek Food",200,1790 ],
        [ "Create Object","MVH","Regular","~","Illusion & Creation","sec=cost","Indef.","2/5lbs","M2, Create Earth, Perfect Illusion",-1,-1 ],
        [ "Create Plant","MH","Area","~","Plant","sec=cost","Perm","var","M, Plant Growth",1000,25000 ],
        [ "Create Servant","MH","Regular","~","Illusion & Creation","3s","1m","3/1","M3, IQ13+, Create Object",-1,-1 ],
        [ "Create Warrior","MH","Regular","~","Illusion & Creation","4s","1m","4/4","Create Servant",-1,-1 ],
        [ "Create Water","MH","Regular","~","Water","1s","Perm","2/gal","Purify Water",200,1790 ],
        [ "Crystal Ball","MH","Enchantment","~","Enchantment","-","Perm","1000","Divination (Crystal-gazing)",-1,-1 ],
        [ "Cure Disease","MH","Regular","~","Healing","10m","Instant","4","Sterilize, Major Healing",800,20000 ],
        [ "Current","MH","Area","~","Water","1m","1h","1/50 | same","8 water spells",300,7500 ],
        [ "Curse","MH","Regular","~","Meta-Spells","var","special","var","M2, 2 spells ea. From 10 colleges",-1,-1 ],
        [ "Curse-Missile","MH","Missile","~","Body Control","1sec+other","var","2","M2+other spell",600,15000 ],
        [ "Dancing Weapon","MH","Enchantment","~","Enchantment","-","Perm","1,000/lb","Air-Golem",-1,-1 ],
        [ "Dark Vision","MH","Enchantment","~","Light & Darkness","1s","1m","5|2","Night Vision or Infravision",-1,-1 ],
        [ "Darkness","MH","Area","~","Light & Darkness","1s","1m","2/1","Continual Light",120,235 ],
        [ "Daze","MH","Regular","HT","Mind Control","2s","1m","3/2","Foolishness",1000,25000 ],
        [ "Death Vision","MH","Regular","HT","Necromatic","3s","1s","2","M",600,15000 ],
        [ "Deathtouch","MH","Regular","~","Body Control","1s","Instant","1 to 3","Wither Limb",2500,62500 ],
        [ "Decay","MH","Regular","~","Food","1s","Perm","1/meal","Test Food",100,100 ],
        [ "Deflect","MH","Enchantment","~","Enchantment","-","Perm","var","Enchant",-1,-1 ],
        [ "Deflect Missile","MH","Blocking","~","Protection & Warning","~","Instant","1","Apportation",200,1790 ],
        [ "Dehydrate","MH","Regular","HT","Water","2s","Perm","1 to 3","5 Water Spells inc. Destroy Water",700,17500 ],
        [ "Delay","MH","Regular","~","Meta-Spells","10s","2h","3/3","M3, 15 Spells",-1,-1 ],
        [ "Delayed Message","MH","Area","~","Sound","4s","Indef.","3","M, Voices, Detect Life",-1,-1 ],
        [ "Destroy Air","MH","Area","~","Air","1s","Instant","2","Create Air",-1,-1 ],
        [ "Destroy Water","MH","Area","~","Water","1s","Perm","3","Create Water",300,7500 ],
        [ "Detect Magic","MH","Regular","~","Knowlege","5s","Instant","2","M",300,7500 ],
        [ "Dexterity","MH","Regular","~","Body Control","1s","1m","2/DX+|same","Clumsiness",2000,50000 ],
        [ "Disintegrate","MVH","Regular","~","Making & Breaking","1s","Perm","1 to 4","M2, Shatter, Ruin",1500,37500 ],
        [ "Dispel Creation","MH","Regular","spell","Illusion & Creation","1s","Instant","1/hex","Control Creation",500,12500 ],
        [ "Dispel Illusion","MH","Regular","spell","Illusion & Creation","1s","Instant","1/hex","Control Illusion",400,10000 ],
        [ "Dispel Magic","MH","Area","spell","Meta-Spells","sec=cost","Perm","3","Counterspell and 12 other spells",-1,-1 ],
        [ "Displace Spell","MH","Regular","spell","Meta-Spells","5s","concentrate","1/4 of spell being moved","Suspend Magic",-1,-1 ],
        [ "Distill","MH","Regular","~","Food","10s","Perm","1/quart","Ferment, Destroy Water",400,10000 ],
        [ "Divination","MH","Information","~","Knowlege","1h","Instant","10","History, Element Spells",-1,-1 ],
        [ "Drain Mana","MVH","Area","~","Meta-Spells","1h","Perm","10","Dispel Magic, 1 spell ea. From 10 colleges",-1,-1 ],
        [ "Drunkenness","MH","Regular","IQ","Mind Control","2s","1m","var","Foolishness, Clumsiness",800,20000 ],
        [ "Dye","MH","Regular","~","Making & Breaking","3s","2d days","var","Restore, Colors",-1,-1 ],
        [ "Earth To Air","MH","Regular","~","Air/Earth","2s","Perm","1/cu.ft","Create Air, Shape Earth",750,18750 ],
        [ "Earth To Stone","MH","Regular","~","Earth","1s","Perm","3(to 20lbs),5/hx","M, Shape Earth",300,7500 ],
        [ "Earth Vision","MH","Regular","~","Knowledge/Earth","1s","30s","2/10yds|same","Shape Earth",400,10000 ],
        [ "Earthquake","MH","Area","~","Earth","30s","1m","2/2","M2, 6 Earth Spells inc. Earth Vision",-1,-1 ],
        [ "Emotion Control","MH","Area","IQ","Mind Control","1s","1h","2","Loyalty",1000,25000 ],
        [ "Enchant","MVH","Enchantment","~","Enchantment","var","Perm","var","M2, 1 spell ea. From 10 colleges",-1,-1 ],
        [ "Enslave","MVH","Regular","IQ","Mind Control","1s","Perm","30","Charm, Telepathy",-1,-1 ],
        [ "Entombment","MH","Regular","HT","Earth","3s","Perm","10","M2, 5 Earth spells",1200,30000 ],
        [ "Essential Flame","MH","Area","~","Fire","3s","1m","3/2","6 Fire spells",800,20000 ],
        [ "Essential Water","MH","Regular","~","Water","1s","Perm","3/gal","6 Water spells",800,20000 ],
        [ "Ethereal Body","MVH","Regular","~","Movement","30s","10s","8/4","6 Movement spells or M3 + Body of Air",8000,200000 ],
        [ "Exchange Bodies","MVH","Regular","IQ","Communication","1h","Perm","120","Permanent Possession, Soul Jar",-1,-1 ],
        [ "Exorcism","MH","Regular","spell","Communication","10s","Instant","10","Soul Rider or Possession",300,7500 ],
        [ "Explosive Fireball","MH","Missile","~","Fire","1-3s","Instant","2 to 6","Fireball",1200,30000 ],
        [ "Extinguish Fire","MH","Regular","~","Fire","1s","Perm","3/hex","Ignite Fire",400,10000 ],
        [ "False Aura","MH","Regular","IQ","Meta-Spells","10s","10h","4/2","Conceal Magic, Aura",-1,-1 ],
        [ "False Memory","MH","Regular","IQ","Mind Control","5s","var","var","Forgetfulness, 6 other Mind Control",-1,-1 ],
        [ "Far-Hearing","MH","Information","~","Knowledge/Sound","3s","1m","4/2","M, not deaf, 4 other Sound",400,10000 ],
        [ "Fatigue","MH","Regular","HT","Body Control","1s","1m","1/ST-/h","none",900,22500 ],
        [ "Fear","MH","Area","IQ","Mind Control","1s","10m","1","Sense Emotion",300,7500 ],
        [ "Ferment","MH","Regular","~","Food","10s","1h","1/pt or loaf","Decay",50,50 ],
        [ "Final Rest","MH","Regular","~","Clerical","10m","Perm","20","~",-1,-1 ],
        [ "Find Direction","MH","Information","~","Knowlege","1s","Instant","2","M",250,4510 ],
        [ "Find Weakness","MH","Information","~","Making & Breaking","2s","Instant","1","1 spell of ea. Four elements",100,100 ],
        [ "Fireball","MH","Missile","~","Fire","1-3s","Instant","1 to 3","M, Create Fire, Shape Fire",800,20000 ],
        [ "Fireproof","MH","Area","~","Fire","5m","1d","3","Extinguish Fire",300,7500 ],
        [ "Fish Control","MH","Reg","IQ","Animal","1s","1m","3/2","Beast-Soother",400,10000 ],
        [ "Flame Jet","MH","Regular","~","Fire","1s","1s","1-3|same","Create Fire, Shape Fire",800,20000 ],
        [ "Flaming Missiles","MH","Regular","~","Fire","3s","1m","4/2","Flaming Weapon",1000,25000 ],
        [ "Flaming Weapon","MH","Regular","~","Fire","2s","1m","4/1","M2, Heat",750,18750 ],
        [ "Flash","MH","Regular","~","Light & Darkness","2s","Instant","4","Continual Light",-1,-1 ],
        [ "Flesh To Stone","MH","Regular","HT","Earth","2s","Perm","10/hex","Earth To Stone",1000,25000 ],
        [ "Flight","MVH","Regular","~","Movement","2s","1m","5/3","M2, Levitation",2500,62500 ],
        [ "Fog","MH","Area","~","Water","1s","1m","2/1","Shape Water",300,7500 ],
        [ "Foolishness","MH","Regular","IQ","Mind Control","1s","1m","1/IQ-/h","IQ12+",800,20000 ],
        [ "Force Dome","MH","Area","~","Protection & Warning","1s","10m","3/2","M, Weather Dome, Apportation",-1,-1 ],
        [ "Forest Warning","MH","Area","~","Plant","1s","10h","1/2|same","4 Plant",-1,-1 ],
        [ "Forgetfulness","MH","Regular","IQ or skill","Mind Control","10s","1h","3/3","M, Foolishness, IQ12+",500,12500 ],
        [ "Fortify","MH","Enchantment","~","Enchantment","-","Perm","var","Enchant",-1,-1 ],
        [ "Freeze","MH","Regular","~","Water","10s","var","6/hex","Shape Water",200,1790 ],
        [ "Frost","MH","Area","~","Water","1s","var","1","Create Water or Cold",200,1790 ],
        [ "Frostbite","MH","Regular","HT","Water","3s","Perm","1 to 3","5 other Water inc. Freeze, Frost",700,17500 ],
        [ "Geyser","MVH","Area","~","Water","5s","1s","5|2","6 Water and either 4 Earth or Fire",-1,-1 ],
        [ "Gift of Letters","MVH","Regular","~","Communication","1s","1m","4|2","Borrow Language, 3 lang.@10+",300,7500 ],
        [ "Gift of Tongues","MVH","Regular","~","Communication","1s","1m","4|2","Borrow Language, 3 lang.@10+",300,7500 ],
        [ "Glass Wall","MH","Regular","~","Knowlege","1s","1m","4|2","5 Knowledge or Earth Vision",600,15000 ],
        [ "Glow","MH","Area","~","Light & Darkness","1s/.5e","2d days","0.5,1,1.5,2","Continual Light",250,4510 ],
        [ "Glue","MH","Area","~","Movement","1s","10m","3/3","Haste",300,7500 ],
        [ "Golem","MVH","Enchantment","~","Enchantment","var","Perm","var","Shape Earth, Animation",-1,-1 ],
        [ "Great Geas","MVH","Regular","IQ","Mind Control","1m","Perm","30","M3, 15 Mind Control inc. Lesser Geas",4000,100000 ],
        [ "Great Haste","MVH","Regular","~","Movement","3s","10s","5","M, Haste, IQ12+",2000,50000 ],
        [ "Great Voice","MH","Regular","~","Sound","2s","1m","3|1","Voices, Thunderclap",200,1790 ],
        [ "Great Ward","MH","Block","spell","Meta-Spells","none","Instant","1/subject","M2, Ward",-1,-1 ],
        [ "Great Wish","MVH","Enchantment","~","Enchantment","-","-","2000","M3, Wish, (DX+IQ)30+",-1,-1 ],
        [ "Greater Shapeshifting","MVH","Special","~","Animal","5s","1m","8|4","Shapeshifting",-1,-1 ],
        [ "Hail","MH","Area","~","Water","1s","1m","1/5|same","Snow",500,12500 ],
        [ "Halt Aging","MVH","Regular","~","Healing","1s","5d days","20","M2, 6 Healing",10000,250000 ],
        [ "Hang Spell","MVH","Special","~","Meta-Spells","10s","1h","max(2,hung spell)","Delay",-1,-1 ],
        [ "Hardiness","MH","Blocking","~","Protection & Warning","~","Instant","1/DR","Stiffen",-1,-1 ],
        [ "Haste","MH","Regular","~","Movement","2s","1m","2|1","none",250,4510 ],
        [ "Hawk Flight","MVH","Regular","~","Movement","3s","1m","8|4","Flight",3000,75000 ],
        [ "Hawk Vision","MH","Regular","~","Light & Darkness","2s","1m","4|2","Keen Eyes or 5 Light",400,10000 ],
        [ "Heal Plant","MH","Area","~","Plant","1m","Perm","3","Identify Plant",400,10000 ],
        [ "Healing Slumber","MH","Regular","(auto)","Healing","30s","8hr","6,10","M2, Peacful Sleep, Minor Healing",-1,-1 ],
        [ "Heat","MH","Regular","~","Fire","1m","1m","3/hex","Create Fire, Shape Fire",400,10000 ],
        [ "Hex","MH","Enchantment","~","Enchantment","-","Perm","200","Enchant",-1,-1 ],
        [ "Hide","MH","Regular","~","Light & Darkness","5s","1h","1 to 5|same","Blur or Forgetfulness",1000,25000 ],
        [ "Hide Path","MH","Regular","~","Plant","1s","1m","2/1","Heal Plant",300,7500 ],
        [ "Hide Thoughts","MH","Regular","~","Communication","1s","10m","3/1","Truthsayer",400,10000 ],
        [ "Hideaway","MH","Enchantment","~","Enchantment","-","Perm","50","Create Object, Lighten",-1,-1 ],
        [ "Hinder","MH","Regular","~","Body Control","1s","1m","1 to 4|same","Haste or Clumsiness",600,15000 ],
        [ "History","MH","Information","~","Knowlege","sec=cost","Instant","var","Trace",-1,-1 ],
        [ "Hush","MH","Regular","IQ","Sound","2s","10s","2/1","Silence",200,1790 ],
        [ "Ice Dagger","MH","Missile","~","Water","1-3s","Instant","1 to 3","Ice Sphere or Water Jet",400,10000 ],
        [ "Ice Slick","MH","Area","~","Water","2s","var","3","Frost",100,100 ],
        [ "Ice Sphere","MH","Missile","~","Water","1-3s","Instant","1 to 3","Shape Water",400,10000 ],
        [ "Ice Vision","MH","Regular","~","Water/Knowledge","1s","30s","2/10yds","Shape Water",400,10000 ],
        [ "Icy Weapon","MH","Regular","~","Water","3s","1m","3/1","Create Water",750,18750 ],
        [ "Identify Plant","MH","Information","~","Plant","1s","Instant","2","Seek Plant",200,1790 ],
        [ "Identify Spell","MH","Information","~","Knowlege","1s","Instant","2","Detect Magic",1100,27500 ],
        [ "Ignite Fire","MH","Regular","~","Fire","1s","1s","1 to 4","none",100,100 ],
        [ "Illusion Disguise","MH","Regular","~","Illusion & Creation","1s","until disbelieved","3","Simple Illusiion",150,505 ],
        [ "Illusion Shell","MH","Regular","~","Illusion & Creation","1s","1m","2/hex","Simple Illusiion",200,1790 ],
        [ "Independence","MH","Area","~","Illusion & Creation","var","var","2","Simple Illusiion",-1,-1 ],
        [ "Infravision","MH","Regular","~","Light & Darkness","1s","1m","3/1","Keen Eyes or 5 Light",100,100 ],
        [ "Insect Control","MH","Regular","IQ","Animal","1s","1m","3/2","Beast-Soother",300,7500 ],
        [ "Instant Regeneration","MVH","Regular","~","Healing","special","Perm","80","M3, Regeneration",4000,100000 ],
        [ "Instant Restoration","MVH","Regular","~","Healing","special","Perm","50","M2, Restoration",2500,62500 ],
        [ "Invisibility","MH","Regular","~","Light & Darkness","3s","1m","5/3","6 Light inc. Blur",1200,30000 ],
        [ "Invisible Wizard Ear","MH","Regular","~","Sound","4s","1m","5/3","Wizard Ear, Invisibility",-1,-1 ],
        [ "Invisible Wizard Eye","MH","Regular","~","Knowlege","4s","1m","5/3","Wizard Eye, Invisibility",1600,40000 ],
        [ "Iron Arm","MH","Blocking","~","Protection & Warning","1s","Instant","1","Resist Pain, DX12+",600,15000 ],
        [ "Itch","MH","Regular","~","Body Control","1s","until scratched","2","none",100,100 ],
        [ "Keen Ears","MH","Regular","HT","Mind Control/Sound","1s","30m","1per+/h","none",150,505 ],
        [ "Keen Eyes","MH","Regular","~","Mind Control","1s","30m","1per+/h","none",150,505 ],
        [ "Keen Nose","MH","Regular","~","Mind Control","1s","30m","1per+/h","none",100,100 ],
        [ "Knots","MH","Regular","~","Making & Breaking","3s","Indef.","2","Stiffen",20,20 ],
        [ "Know Illusion","MH","Information","~","Illusion & Creation","1s","Instant","2","Simple Illusiion",-1,-1 ],
        [ "Lend Health","MH","Regular","~","Healing","1s","1h","1/HT loaned","Lend Strength",250,4510 ],
        [ "Lend Language","MH","Regular","~","Communication","3s","1m","3/1","Mind-Sending",-1,-1 ],
        [ "Lend Skill","MH","Regular","~","Communication","3s","1m","3/2","Mind-Sending, IQ12+",-1,-1 ],
        [ "Lend Spell","MH","Regular","~","Meta-Spells","3s","Perm","=maint of lent spell","M, Lend Skill, 6 colleges",-1,-1 ],
        [ "Lend Strength","MH","Regular","~","Healing","1s","Perm","var","M or Empathy adv.",100,100 ],
        [ "Lesser Geas","MVH","Regular","IQ","Mind Control","30s","Perm","12","M2, 10 Mind Control",2000,50000 ],
        [ "Lesser Wish","MVH","Enchantment","~","Enchantment","-","-","180","M, 1 ea. From 10 colleges",-1,-1 ],
        [ "Levitation","MH","Regular","IQ","Movement","2s","1m","1/80lbs/h","Apportation",700,17500 ],
        [ "Light","MH","Regular","~","Light & Darkness","1s","1m","1|1","none",100,100 ],
        [ "Light Jet","MH","Regular","~","Light & Darkness","1s","1m","2|1","Continual Light",200,1790 ],
        [ "Lighten","MH","Enchantment","~","Enchantment","-","Perm","var","Enchant",100,100 ],
        [ "Lighten Burden","MH","Regular","~","Movement","3s","10m","3 or 5/h","Apportation",-1,-1 ],
        [ "Lightning","MH","Missile","~","Air","1-3s","Instant","1 to 3","6 Air spells",800,20000 ],
        [ "Limit","MH","Enchantment","~","Enchantment","-","Perm","200","Enchant",-1,-1 ],
        [ "Link","MH","Area","~","Ench./Meta.","4h","Indef.","8","Delay",-1,-1 ],
        [ "Lockmaster","MH","Regular","Magelock","Movement","10s","Perm","3","Locksmith or Apportation and M2",2000,50000 ],
        [ "Locksmith","MH","Regular","~","Movement","1s","1m","2/2","Apportation",1000,25000 ],
        [ "Loyal Sword","MH","Enchantment","~","Enchantment","-","Perm","750/lb","Apportation",-1,-1 ],
        [ "Loyalty","MH","Regular","IQ","Mind Control","2s","1h","2/2","Bravery, 4 other Mind Control",2000,50000 ],
        [ "Madness","MH","Regular","IQ-2","Mind Control","2s","1m","4/2","Forgetfulness or Drunkenness",1000,25000 ],
        [ "Mage Sense","MH","Regular","IQ-2","Knowlege","2s","1m","4/2","Forgetfulness or Drunkenness",1200,30000 ],
        [ "Mage Sight","MH","Regular","~","Knowlege","1s","1m","3/2","Detect Magic",800,20000 ],
        [ "Magelock","MH","Regular","~","Protection & Warning","1s","1m","3/2","Detect Magic",200,1790 ],
        [ "Mage-Stealth","MH","Regular","~","Sound","3s","1m","3/2","Hush",500,12500 ],
        [ "Magic Resistance","MH","Regular","IQ+M","Meta-Spells","3s","1m","1 to 5|same","M, 1 ea. From 7 colleges",300,7500 ],
        [ "Major Healing","MVH","Regular","~","Healing","1s","Perm","1 to 4","M, Minor Healing",1500,37500 ],
        [ "Mammal Control","MH","Regular","IQ","Animal","1s","1m","5/3","Beast-Soother or Charm",600,15000 ],
        [ "Manipulate","MH","Regular","~","Movement","3s","1m","4/3","Locksmith",-1,-1 ],
        [ "Mass Daze","MH","Area","HT","Mind Control","sec=cost","Instant","2/1","Daze, IQ13+",-1,-1 ],
        [ "Mass Sleep","MH","Area","HT","Mind Control","sec=cost","Instant","3","Sleep, IQ13+",-1,-1 ],
        [ "Mass Suggestion","MH","Area","IQ","Mind Control","sec=cost","10m","4/2","Suggestion",1500,37500 ],
        [ "Master","MH","Regular/Block.","IQ","Animal","1s","Indef.","2","Beast-Soother",800,20000 ],
        [ "Measurement","MH","Area/Information","~","Knowlege","1s","Instant","1","none",50,50 ],
        [ "Melt Ice","MH","Area","~","Water","10s","Perm","1","Heat or Freeze",300,7500 ],
        [ "Mental Stun","MH","Regular","IQ","Mind Control","1s","Instant","2","Daze or Stun",-1,-1 ],
        [ "Message","MH","Regular","Sound","Sound","dura","15s","1fat. / 15secs","Great Voice, Seeker",1000,25000 ],
        [ "Might","MH","Regular","~","Body Control","1s","1m","2/ST+|same","Lend Strength",1500,37500 ],
        [ "Mind-Reading","MH","Regular","IQ","Communication","10s","1m","4|2","Truthsayer",1000,25000 ],
        [ "Mind-Search","MVH","Regular","IQ","Communication","1m","1m","6|3","Mind-Reading",1500,37500 ],
        [ "Mind-Sending","MH","Regular","~","Communication","4s","1m","4/4","Mind-Reading",1500,37500 ],
        [ "Mindlessness","MVH","Regular","IQ","Mind Control","5s","1m","8|4","M2, Forgetfulness",800,20000 ],
        [ "Minor Healing","MH","Regular","~","Healing","1s","Perm","1 to 3","Lend Health",600,15000 ],
        [ "Missile Shield","MH","Regular","~","Protection & Warning","1s","1m","5|2","Apportation or Shield",400,10000 ],
        [ "Mollusk Control","MH","Regular","IQ","Animal","1s","1m","3|2","Beast-Soother",400,10000 ],
        [ "Monk's Banquet","MH","Regular","~","Food","1s","24h","6","Banquet, Resist Pain",1000,25000 ],
        [ "Mystic Mist","MH","Area","~","Protection & Warning","5m","10h","1|1","M and Watchdog or Shield",-1,-1 ],
        [ "Name","MH","Enchantment","~","Enchantment","-","Perm","200 or 400","Enchant",-1,-1 ],
        [ "Neutralize Poison","MH","Regular","~","Healing","30s","Perm","5","Cure Disease or M3 and Test Food",400,10000 ],
        [ "Night Vision","MH","Regular","~","Light & Darkness","1s","1m","3|1","Keen Eyes or 5 Light",200,1790 ],
        [ "Nightingale","MH","Area","~","Protection & Warning","1s","10h","1/2|same","Sense Danger",100,100 ],
        [ "Nightmare","MH","Regular","IQ","Mind Control","1m","1h","6","M2, Death Vision, Fear, Sleep",800,20000 ],
        [ "No-Smell","MH","Regular","~","Air","1s","1h","2","Purify Air",150,505 ],
        [ "Noise","MH","Regular","~","Sound","1s","1h","2","Purify Air",100,100 ],
        [ "Odor","MH","Area","~","Air","1s","1h","1","No-Smell",40,40 ],
        [ "Pain","MH","Regular","HT","Body Control","2s","1s","2","Spasm",400,10000 ],
        [ "Panic","MH","Regular","IQ","Mind Control","1s","1m","4|2","Fear",-1,-1 ],
        [ "Paralyze Limb","MH","Regular","HT","Body Control","1s","1m","3","M, 5 Body Control inc. Pain",1000,25000 ],
        [ "Password","MH","Enchantment","~","Enchantment","-","Perm","400","Enchant",-1,-1 ],
        [ "Pathfinder","MH","Information","~","Knowlege","10s","Instant","4","M, IQ12+, 2 Seek",1000,25000 ],
        [ "Peaceful Sleep","MH","Regular","Special","Mind Control","30s","8h","4","Sleep, Silence",900,22500 ],
        [ "Pentagram","MH","Special","~","Meta-Spells","5s/hex","Perm","10/hex","Spell Shield",-1,-1 ],
        [ "Perfect Illusion","MH","Area","~","Illusion & Creation","1s","1m","3/h","M, Complex Illusion",-1,-1 ],
        [ "Permanent Beast Possesion","MVH","Regular","IQ","Animal","1m","perm","20","M2, Beast Possession",-1,-1 ],
        [ "Permanent Forgetfulness","MVH","Regular","IQ or skill","Mind Control","1h","Perm","15","M2, Forgetfulness, IQ13+",1000,25000 ],
        [ "Permanent Madness","MVH","Regular","IQ-2","Mind Control","10m","Perm","20","M2, Madness, IQ13+",-1,-1 ],
        [ "Permanent Possession","MVH","Regular","IQ","Communication","5m","Indef.","30","M3, Possession",3000,75000 ],
        [ "Persuasion","MH","Regular","IQ","Communication","1s","1m","2xbonus","Sense Emotion",1000,25000 ],
        [ "Pestilence","MH","Regular","~","Necromatic","30s","Perm","6","M, Steal Health, Decay",1000,25000 ],
        [ "Phantom","MH","Area","~","Illusion & Creation","1s","1m","9|4.5","M2, Perfect Illusion, Hinder, Apportation",300,7500 ],
        [ "Phantom Flame","MH","Area","~","Fire","1s","1m","1|1","Shape Fire or Simple Illusion",-1,-1 ],
        [ "Planar Summons","MH","Special","~","Necromatic","5m","var","20","M, 1 ea. From 10 Colleges",-1,-1 ],
        [ "Plant Form","MH","Special","~","Plant","1s","1h","5|2","M, 6 Plant",1200,30000 ],
        [ "Plant Growth","MH","Area","~","Plant","10s","1m","3|2","Heal Plant",300,7500 ],
        [ "Plant Sense","MH","Regular","Hide Path","Plant","1s","1m","3|2","Forest Warning, Hide Path",500,12500 ],
        [ "Poison Food","MH","Regular","~","Food","1s","Perm","3/meal","Purify Food, Decay",600,15000 ],
        [ "Poltergeist","MH","Missile","HT","Movement","1s","Instant","1 or 2","Apportation",1000,25000 ],
        [ "Possession","MVH","Regular","IQ","Communication","1m","1m","10/4","M and Control Person or Beast Possession",2500,62500 ],
        [ "Power","MH","Enchantment","~","Enchantment","-","Perm","var","Recover Strength",-1,-1 ],
        [ "Powerstone","MH","Enchantment","~","Enchantment","-","Perm","20/casting","Enchant",-1,-1 ],
        [ "Predict Weather","MH","Information","~","Air","5s","Instant","var","4 Air spells",-1,-1 ],
        [ "Preserve Food","MH","Regular","~","Food","1s","1w","special","Sterilize, Test Food",20,20 ],
        [ "Puissance","MH","Enchantment","~","Enchantment","-","Perm","var","5 Earth spells",250,4510 ],
        [ "Purify Air","MH","Area","~","Air","1s","Instant","1","none",50,50 ],
        [ "Purify Food","MH","Regular","~","Food","1s","Perm","1/lb","Preserve Food or Decay",400,10000 ],
        [ "Purify Water","MH","Special","~","Water","5-10s/gal","Perm","1/gal","Seek Water",50,50 ],
        [ "Quick March","MH","Regular","~","Movement","1m","1days march","4","M, Haste",-1,-1 ],
        [ "Quick-Draw","MH","Enchantment","~","Enchantment","-","Perm","300/lb","Apportation",300,7500 ],
        [ "Rain","MH","Area","~","Water/Air","1m","1h","1/10|same","Clouds",600,15000 ],
        [ "Rear Vision","MH","Regular","~","Mind Control","1s","1m ","3|1","Alertness",1000,25000 ],
        [ "Recover Strength","MH","Special","~","Healing","special","special","none","M, Lend Strength",1000,25000 ],
        [ "Reflect","MH","Block","spell","Meta-Spells","none","Instant","4 or 6","Ward",-1,-1 ],
        [ "Reflex","MH","Special","~","Meta-Spells","10s","1h","var","Delay, Ward",-1,-1 ],
        [ "Regeneration","MVH","Regular","~","Healing","special","Perm","20","M2, Restoration",3000,75000 ],
        [ "Rejoin","MH","Regular","~","Making & Breaking","4s/10lb","10m","1/10lbs/h","Weaken, Restore",-1,-1 ],
        [ "Remove Aura","MH","Regular","IQ","Meta-Spells","10s","Perm","5","Dispel Magic, Aura",-1,-1 ],
        [ "Remove Curse","MH","Regular","Spell","Meta-Spells","1h","Instant","20","M2, 1 ea. From 15 colleges",-1,-1 ],
        [ "Remove Enchantment","MH","Enchantment","~","Enchantment","var","Perm","100","Enchant",-1,-1 ],
        [ "Repair","MH","Regular","~","Making & Breaking","1s/lb","Perm","3/10lbs","M2, Rejoin",-1,-1 ],
        [ "Repair Arrow","MH","Regular","~","Making & Breaking","4s/arrow","Perm","2/arrow","Rejoin",-1,-1 ],
        [ "Repel Animal","MH","Area","HT","Animal","10s","1h","see (Animal) Control","(Animal) Control for type repelled",-1,-1 ],
        [ "Repel Spirits","MH","Area","IQ","Necromatic","10s","1h","4|2","Banish and Turn Spirit",1100,27500 ],
        [ "Reptile Control","MH","Regular","IQ","Animal","1s","1m","4|2","Beast-Soother",400,10000 ],
        [ "Reshape","MH","Regular","~","Making & Breaking","10s","1m","6|3","M, Weaken, Shape Earth or Shape Plant",500,12500 ],
        [ "Resist Cold","MH","Regular","~","Fire","1s","1m","2/hex","Create Fire, Heat",800,20000 ],
        [ "Resist Fire","MH","Regular","~","Fire","1s","1m","2/hex","Extinguish Fire, Cold",800,20000 ],
        [ "Resist Pain","MH","Regular","~","Body Control","1s","1m","4|2","M2, Pain",800,20000 ],
        [ "Restoration","MVH","Regular","~","Healing","1m","perm","15","Major Healing",2000,50000 ],
        [ "Restore","MH","Regular","~","Making & Breaking","3s","10m","2/hex/h","Weaken or Simple Illusion",-1,-1 ],
        [ "Restore Mana","MVH","Area","~","Meta-Spells","1h","Perm","10","Dispel Magic, 1 ea. From 10 colleges",-1,-1 ],
        [ "Resurrection","MVH","Regular","~","Necro/Healing","2h","Perm","300","Instant Regeneration, Summon Spirit",-1,-1 ],
        [ "Retch","MH","Regular","HT","Body Control","4s","~","3","Spasm, +2 body control",400,10000 ],
        [ "Return Missile","MH","Block","~","Protection & Warning","~","Instant","3","Catch Missle",400,10000 ],
        [ "Reverse Missiles","MH","Regular","~","Protection & Warning","1s","1m","7|3","Missile Shield or Force Dome",600,15000 ],
        [ "Rider","MH","Regular","~","Animal","1s","5m","2|1","1 Control spell",800,20000 ],
        [ "Rider Within","MH","Regular","~","Animal","3s","1m","4|1","2 Animal Control spells",1000,25000 ],
        [ "Rooted Feet","MH","Regular","ST","Body Control","1s","1m","3","Hinder",400,10000 ],
        [ "Roundabout","MH","Regular","HT","Body Control","1s","Instant","3","Tanglefoot",-1,-1 ],
        [ "Ruin","MH","Regular","~","Making & Breaking","5s/lb","1m","2/lb|same","M, Weaken, Decay",-1,-1 ],
        [ "Sand Jet","MH","Regular","~","Earth","1s","1s","1 to 3|same","Create Earth, Shape Earth",-1,-1 ],
        [ "Scribe","MH","Regular","~","Sound","1s","1m","3|1","Voices, Literacy, Air-Golem",250,4510 ],
        [ "Scroll","MH","Enchantment","~","Enchantment","days=cost","var","special","M, Literacy adv.",-1,-1 ],
        [ "Scryguard","MH","Regular","~","Meta-Spells","5s","10h","3|1","M",500,12500 ],
        [ "Scrywall","MH","Area","~","Meta-Spells","sec=cost","10h","3|2","Scryguard",300,7500 ],
        [ "See Invisible","MH","Regular","~","Light & Darkness","1s","1m","4|2","Invisibility or Dark Vision and Infravision",400,10000 ],
        [ "See Secrets","MH","Regular","~","Knowlege","5s","1m","5|2","Seeker, Aura",400,10000 ],
        [ "Seek Air","MH","Information","~","Air","1s","Instant","1","none",-1,-1 ],
        [ "Seek Earth","MH","Information","~","Earth","10s","Instant","3","none",50,50 ],
        [ "Seek Fire","MH","Information","~","Fire","1s","Instant","1","none",-1,-1 ],
        [ "Seek Food","MH","Information","~","Food","1s","Instant","2","none",300,7500 ],
        [ "Seek Plant","MH","Information","~","Plant","1s","Instant","2","none",50,50 ],
        [ "Seek Water","MH","Information","~","Water","1s","Instant","2","none",40,40 ],
        [ "Seeker","MH","Information","~","Knowlege","1s","Instant","3","M, IQ12+, 2 Seek",500,12500 ],
        [ "Sense Danger","MH","Information","~","Protection & Warning","1s","Instant","3","Sense Foes or Danger Sense adv.",400,10000 ],
        [ "Sense Emotion","MH","Regular","~","Communication","1s","Instant","2","Sense Foes",300,7500 ],
        [ "Sense Foes","MH","Information/Area","~","Communication","1s","Instant","1(min.2)","none",200,1790 ],
        [ "Sense Life","MH","Information/Area","~","Communication","1s","Instant","1/2(Min1)","none",80,80 ],
        [ "Sense Observation","MH","Area","~","Protection & Warning","5s","1hr","1 or 3 | .5 or 1.5","Sense Danger or Scryguard",-1,-1 ],
        [ "Sense Spirit","MH","Information/Area","~","Necromatic","1s","Instant","0.5","Death Vision or Sense Life and M",100,100 ],
        [ "Shape Air","MH","Regular","~","Air","1s","1m","1 to 10","Create Air",200,1790 ],
        [ "Shape Darkness","MH","Area","~","Light & Darkness","1s","1m","2|2","Darkness",200,1790 ],
        [ "Shape Earth","MH","Regular","~","Earth","1s","1m","2/hex/1/hex","Seek Earth",200,1790 ],
        [ "Shape Fire","MH","Area","~","Fire","1s","1m","2|1","Ignite Fire",400,10000 ],
        [ "Shape Plant","MH","Regular","~","Plant","10s","1m","3|1","Identify Plant",500,12500 ],
        [ "Shape Stone","MH","Regular","~","Earth","1s","1m","4/hex/2/hex","Shape Earth, 3 other Earth",500,12500 ],
        [ "Shape Water","MH","Regular","~","Water","2s","1m","1|1","Create Water",400,10000 ],
        [ "Shapeshift to Familiar Form","MH","Special","IQ","Animal","30s","1h","6|2","M2, 6 other spells (any college), familiar",1500,37500 ],
        [ "Shapeshift Others","MVH","Special","IQ","Animal","30s","1h","6|2","M2, Shapeshifting for that form",3000,75000 ],
        [ "Shapeshifting","MVH","Special","IQ","Animal","30s","1h","6|2","M2, 6 other spells (any college)",1500,37500 ],
        [ "Share Strength","MH","Regular","~","Healing","1s","special","var","Lend ST",-1,-1 ],
        [ "Sharpen","MH","Regular","~","Making & Breaking","4s","1m","special","Repair",-1,-1 ],
        [ "Shatter","MVH","Regular","~","Making & Breaking","1s","Instant","1 to 3","M, Weaken",500,12500 ],
        [ "Shatterproof","MH","Regular","~","Making & Breaking","1s","1h","3/3","Repair, Shatter",400,10000 ],
        [ "Shield","MH","Regular","~","Protection & Warning","1s","1m","2/PD+|same","M2",-1,-1 ],
        [ "Sickness","MH","Regular","HT","Mind/Body","4s","1m","3|3","Drunkenness or Pestilence",1500,37500 ],
        [ "Silence","MH","Area","~","Sound","1s","1m","2|1","Sound",80,80 ],
        [ "Simple Illusion","MH","Area","~","Illusion & Creation","1s","1m","1/h","not blind, IQ11+",-1,-1 ],
        [ "Skull-Spirit","MH","Regular","~","Necromatic","1s","24h","20","4 other Necromantic",40,40 ],
        [ "Sleep","MH","Regular","HT","Mind Control","3s","Instant","4","Daze",1200,30000 ],
        [ "Slow Fall","MH","Regular","~","Movement","1s","1m","1/50lbs/h","Apportation",1000,25000 ],
        [ "Snow","MH","Area","~","Water","1s","1h","1/15","Clouds, Frost",450,11250 ],
        [ "Snow Shoes","MH","Regular","~","Water","2s","1m","2|1","Shape Water",350,8750 ],
        [ "Soul Jar","MVH","Regular","~","Necromatic","1m","Perm","8","M, 6 Necro. Inc. Steal HT",-1,-1 ],
        [ "Soul Rider","MH","Regular","IQ","Communication","3s","1m","5/2","Mind-Reading",1000,25000 ],
        [ "Sound","MH","Regular","~","Sound","1s","var","var","none",50,50 ],
        [ "Sound Jet","MH","Regular","~","Sound","1s","1s","1 to 4|same","Great Voice",400,10000 ],
        [ "Sound Vision","MH","Regular","~","Sound","1s","1m","5/2","Acute Hearing",400,10000 ],
        [ "Spasm","MH","Regular","HT","Body Control","1s","a moment","2","Itch",300,7500 ],
        [ "Speed","MH","Regular","HT","Enchantment","1s","a moment","2","Itch",-1,-1 ],
        [ "Spell Shield","MH","Area","~","Meta-Spells","1s","1m","3|2","M2, Scryguard, Magic Resistance",400,10000 ],
        [ "Spell Wall","MH","Regular","spell","Meta-Spells","1s","1m","2|2","Spell Shield",-1,-1 ],
        [ "Spellguard","MVH","Regular","spell","Meta-Spells","1/e","10h","1-3|1-3","Dispel Magic",-1,-1 ],
        [ "Staff","MH","Enchantment","~","Enchantment","-","Perm","30","Enchant",-1,-1 ],
        [ "Steal Health","MH","Regular","~","Necromatic","1m/3HT","Perm","none","Steal Strength",1500,37500 ],
        [ "Steal Strength","MH","Regular","~","Necromatic","1m/3ST","Perm","none","Minor Healing",800,20000 ],
        [ "Steal Youth","MVH","Regular","HT","Necromatic","1h","Perm","10 to 30","Youth, Age, Steal Health",8000,200000 ],
        [ "Stench","MH","Area","~","Air","1s","5m","1","Purify Air",60,60 ],
        [ "Sterilize","MH","Area","~","Healing","var","Instant","3/hex","Decay or Insect Control",400,10000 ],
        [ "Stiffen","MH","Regular","Spec.","Making & Breaking","2s/lb","10m","1/lb/h","Rejoin",-1,-1 ],
        [ "Stone Missile","MH","Missile","~","Earth","1/energy pt","Instant","1 to 3","Create Earth",400,10000 ],
        [ "Stone To Earth","MH","Regular","~","Earth","1s","Perm","10/hex","Earth To Stone or any 4 Earth",400,10000 ],
        [ "Stone To Flesh","MH","Regular","~","Earth","5s","Perm","10/hex","M2, Stone To Earth, Flesh To Stone",1000,25000 ],
        [ "Stop Bleeding","MH","Regular","~","Healing","1s","Perm","1 or 10","Lend Health",-1,-1 ],
        [ "Storm","MH","Area","~","Air/Water","1m","1h","1/50 | same","Rain and Hail",1000,25000 ],
        [ "Strengthen Will","MH","Regular",,"Mind Control","1s","1m","1/+1","M and 6 Mind Control spells",-1,-1 ],
        [ "Strike Blind","MH","Regular","HT","Body Control","1s","10s","4/2","2 Light, Spasm",2000,50000 ],
        [ "Strike Deaf","MH","Regular","HT","Body Control","1s","10s","3/1","2 Sound, Spasm",1000,25000 ],
        [ "Strike Dumb","MH","Regular","HT","Body Control","1s","10s","3/1","Spasm",2500,62500 ],
        [ "Stun","MH","Regular","HT","Body Control","1s","Instant","2","Pain",-1,-1 ],
        [ "Suggestion","MH","Regular","IQ","Mind Control","10s","10m","4/3","Emotion Control, Forgetfulness",500,12500 ],
        [ "Summon Demon","MH","Special","~","Necromatic","5m","1h","20","M, 1 ea. From 10 colleges",-1,-1 ],
        [ "Summon Elemental","MH","Special","~","4 Diff.","30s","1h","4","M",800,20000 ],
        [ "Summon Shade","MVH","Information","IQ","Necromatic","10m","1m","50/20","Summon Spirit",800,20000 ],
        [ "Summon Spirit","MH","Information","IQ","Necromatic","5m","1m","20/10","Death Vision, M2",1000,25000 ],
        [ "Sunbolt","MH","Missile","~","Light & Darkness","1s/e","Instant","1,2,3","Sunlight + 5 other Light/Darkness spells",800,20000 ],
        [ "Sunlight","MH","Area","~","Light & Darkness","1s","1m","2|1","M, Glow, Colors",175,915 ],
        [ "Suspend Enchantment","MH","Enchantment","~","Enchantment","1s","1h","25","Enchant",-1,-1 ],
        [ "Suspend Magic","MH","Area","spell","Meta-Spells","1s/e","1m","3|2","Suspend Spell, 8 other spells",-1,-1 ],
        [ "Suspend Spell","MH","Regular","spell","Meta-Spells","1s","1m","1/10 cost of suspended spell","M",-1,-1 ],
        [ "Suspended Animation","MH","Regular","HT","Healing","30s","Indef.","6","Sleep, 4 Healing",2000,50000 ],
        [ "Swim","MH","Regular","~","Water/Movement","3s","1m","6/3","Shape Water, Levitation",1000,25000 ],
        [ "Tangle Growth","MH","Area","~","Plant","2s","1m","1 or 2/h","Plant Growth",20,20 ],
        [ "Tanglefoot","MH","Regular","DX","Body Control","1s","Instant","2","Clumsiness",600,15000 ],
        [ "Telecast","MVH","Special","~","Meta-Spells","1m","1m","var","M3, Teleport, Wizard Eye, +10 colleges",1900,47500 ],
        [ "Telepathy","MVH","Regular","~","Communication","4s","1m","4/4","Mind-Sending",2000,50000 ],
        [ "Teleport","MVH","Special","~","Movement","1s","Instant","var","Hawk Flight or IQ 15+",3000,75000 ],
        [ "Teleport Other","MVH","Regular","IQ+1","Movement","1s","Instant","var","M3, Teleport",3000,75000 ],
        [ "Teleport Shield","MH","Area","~","Protection & Warning","10s","1h","1/3|same","Watchdog, Spell Shield or Teleport",50,50 ],
        [ "Tell Time","MH","Information","~","Knowlege","1s","Instant","1","none",250,4510 ],
        [ "Terror","MH","Area","IQ","Mind Control","1s","Instant","4","Fear",-1,-1 ],
        [ "Test Food","MH","Information","~","Food","1s","Instant","1 to 3","none",100,100 ],
        [ "Throw Spell","MVH","Missile","~","Meta-Spells","1s","~","3","Delay, Catch Spell",-1,-1 ],
        [ "Thunderclap","MH","Regular","~","Sound","1s","Instant","2","Sound",-1,-1 ],
        [ "Total Paralysis","MH","Regular","HT","Body Control","1s","1m","5","Paralyze Limb",2000,50000 ],
        [ "Touch","MH","Regular","~","Body Control","1s","Instant","1","none",50,50 ],
        [ "Trace","MH","Regular","~","Knowlege","1m","1h","3/1","Seeker",-1,-1 ],
        [ "Truthsayer","MH","Information","IQ","Communication","1s","Instant","2","Sense Emotion",500,12500 ],
        [ "Turn Blade","MH","Block","DX","Protection & Warning","~","~","1","Apportation or Spasm",-1,-1 ],
        [ "Turn Spirit","MH","Regular","IQ","Necromatic","1s","10s","4|2","Fear and Sense Spirit",350,8750 ],
        [ "Turn Zombie","MH","Area","~","Necromatic","2s","1d","2","Zombie",600,15000 ],
        [ "Umbrella","MH","Regular","~","Water/Prot.","2s","10m","1/1","Shape Water or Shield",100,100 ],
        [ "Undo","MH","Regular","Spec.","Movement","1s","Instant","3 or 6","Locksmith",400,10000 ],
        [ "Utter Dome","MH","Area","~","Protection & Warning","1s","1m","6/4","M2, Force Dome, Spell Shield",-1,-1 ],
        [ "Vigor","MH","Regular","~","Body Control","1s","1m","2/HT+|same","Lend Health",1500,37500 ],
        [ "Voices","MH","Regular","~","Sound","1s","1m","3/2","Sound",20,20 ],
        [ "Volcano","MH","Regular","~","Earth","1h","1d","15/10","Earthquake, 6 Fire",-1,-1 ],
        [ "Walk on Air","MH","Regular","~","Air","1s","1m","3/2","Shape Air",500,12500 ],
        [ "Walk on Water","MH","Regular","~","Water","4s","1m","3/2","Shape Water",500,12500 ],
        [ "Walk Through Earth ","MH","Regular","~","Earth","1s","1s","4/3","Shape Stone",1200,30000 ],
        [ "Wall of Silence","MH","Area","~","Sound","1s","1m","2/1","Silence",100,100 ],
        [ "Wallwalker","MH","Regular","~","Movement","1s","1m","1/50lbs/h","Apportation",1000,25000 ],
        [ "Ward","MH","Block","spell","Meta-Spells","none","Instant","2 or 3","M",-1,-1 ],
        [ "Watchdog","MH","Area","~","Protection & Warning","10s","10h","1/1","Sense Danger",200,1790 ],
        [ "Water Jet","MH","Regular","~","Water","1s","1s","1 to 3","Shape Water",600,15000 ],
        [ "Water To Wine","MH","Regular","~","Food","10s","Perm","4/gal","Purify Water, Ferment",500,12500 ],
        [ "Water Vision","MH","Information","~","Water/Knowledge","1s","30s","1/1","Shape Water",200,1790 ],
        [ "Waves","MH","Area","~","Water","1m","1h","1/60 | same","Shape Water",300,7500 ],
        [ "Weaken","MH","Regular","~","Making & Breaking","5s","Perm","2","Find Weakeness",200,1790 ],
        [ "Weaken Will","MH","Regular","IQ","Mind Control","1s","1m","2/-1","M, Foolishness",-1,-1 ],
        [ "Weather Dome","MH","Area","~","Protection & Warning","1s","10h","3/2","2 ea. From 4 elements",-1,-1 ],
        [ "Whirlwind","MH","Area","~","Air","1s/radius","1m","4/2","Windstorm",-1,-1 ],
        [ "Wind","MH","Area","~","Air","1m","1h","1/50 | same","4 Water and 4 Air",300,7500 ],
        [ "Windstorm","MH","Area","~","Air","1s/radius","1m","2/1","Shape Air",-1,-1 ],
        [ "Winged Knife","MH","Missile","~","Movement","1s","Instant","1/lb","Poltergeist",300,7500 ],
        [ "Wisdom","MH","Regular","~","Mind Control","1s","1m","var","6 other Mind Control",2000,50000 ],
        [ "Wish","MVH","Enchantment","~","Enchantment","-","-","250","M2, Lesser Wish, 1 ea. From 15 colleges",-1,-1 ],
        [ "Wither Limb","MH","Regular","HT","Body Control","1s","Perm","5","M2, Paralyze Limb",2000,50000 ],
        [ "Wither Plant","MH","Area","HT","Plant","10s","Perm","2","Plant Growth",200,1790 ],
        [ "Wizard Ear","MH","Regular","~","Sound","2s","1m","4/3","Apportation, Far-Hearing, Sound Vision",450,11250 ],
        [ "Wizard Eye","MH","Regular","~","Knowlege","2s","1m","4/2","M, Apportation, Keen Eyes",1100,27500 ],
        [ "Youth","MVH","Regular","~","Healing","1s","special","100","M3, Halt Aging",-1,-1 ],
        [ "Zombie","MH","Regular","~","Necromatic","1m","Perm","8","Summon Spirit, Lend Health",-1,-1 ]
    ];
}  // initSpells

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function initSpellColumns()
{
    nSpellName =           0;
    nSpellDifficulty =     1;
    nSpellClass =          2;
    nSpellResistance =     3;
    nSpellCollege =        4;
    nSpellCastingTime =    5;
    nSpellDuration =       6;
    nSpellEnergy =         7;
    nSpellPrerequisite =   8;
    nSpellItemEnergyCost = 9;
    nSpellItemValue =      10;
    nSpellRank =           11;
    spellsortcolumn = nSpellName;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function writeSpellTable()
{
    document.writeln( "<form name='frmSpells'></form>" );
    setFormHtml( "frmSpells", getSpellTable() );
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getSpellTable()
{
    var str = "";
    var ndx;
    str += "<table BORDER=1 CELLSPACING=0 CELLPADDING=1>";
    str += getSpellTableHeader();
    for ( ndx = 0; ndx < vSpells.length; ndx++ )
    {
        str += getSpellTableRow( ndx );
    }
    str += "</table>";
    return str;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getSpellTableHeader()
{
    var str = "";
    str += "<tr>";
    str += "<th rowspan=2><a href='javascript:SortSpellsBy(nSpellName)'>Spell</a>";
    str += "<th rowspan=2><a href='javascript:SortSpellsBy(nSpellDifficulty)'>Difficulty</a>";
    str += "<th rowspan=2><a href='javascript:SortSpellsBy(nSpellClass)'>Class</a>";
    str += "<th rowspan=2><a href='javascript:SortSpellsBy(nSpellResistance)'>Resistance</a>";
    str += "<th rowspan=2><a href='javascript:SortSpellsBy(nSpellCollege)'>College</a>";
    str += "<th rowspan=2><a href='javascript:SortSpellsBy(nSpellCastingTime)'>Casting<br>Time</a>";
    str += "<th rowspan=2><a href='javascript:SortSpellsBy(nSpellDuration)'>Duration</a>";
    str += "<th rowspan=2><a href='javascript:SortSpellsBy(nSpellEnergy)'>Energy</a>";
    if ( vKnightsTemplar == null )
    {
        str += "<th rowspan=2><a href='javascript:SortSpellsBy(nSpellPrerequisite)'>Prerequisite</a>";
    }
    str += "<th colspan=2>Item";

    str += "<tr>";
    str += "<th><a href='javascript:SortSpellsBy(nSpellItemEnergyCost)'>Energy<br>Cost</a>";
    str += "<th><a href='javascript:SortSpellsBy(nSpellItemValue)'>Value</a>";
    return str;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getSpellTableRow( ndx )
{
    var str = "";
    str += "<tr valign=top>";
    str += "<td nowrap>" + vSpells[ndx][nSpellName          ];  // nSpellName
    str += "<td nowrap>" + vSpells[ndx][nSpellDifficulty    ];  // nSpellDifficulty
    str += "<td nowrap>" + vSpells[ndx][nSpellClass         ];  // nSpellClass
    str += "<td nowrap>" + vSpells[ndx][nSpellResistance    ];  // nSpellResistance
    str += "<td nowrap>" + vSpells[ndx][nSpellCollege       ];  // nSpellCollege
    str += "<td nowrap>" + vSpells[ndx][nSpellCastingTime   ];  // nSpellCastingTime
    str += "<td nowrap>" + vSpells[ndx][nSpellDuration      ];  // nSpellDuration
    str += "<td nowrap>" + vSpells[ndx][nSpellEnergy        ];  // nSpellEnergy
    if ( vKnightsTemplar == null )
    {
        str += "<td nowrap>" + vSpells[ndx][nSpellPrerequisite  ];  // nSpellPrerequisite
    }
    str += "<td nowrap align=right>" + vSpells[ndx][nSpellItemEnergyCost];  // nSpellItemEnergyCost
    str += "<td nowrap align=right>$" + vSpells[ndx][nSpellItemValue     ];  // nSpellItemValue
    return str;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function writeGrimoire( title, spells )
{
    var i, ndx;
    if ( vSpells == null || vSpells == undefined )
    {
        initSpells();
    }

    document.writeln ( "<table BORDER=1 CELLSPACING=0 CELLPADDING=1>" );
    document.writeln ( "<tr>" );
    document.writeln ( "<th colspan=20>" + title );
    document.writeln ( getSpellTableHeader() );
    for ( i = 0; i < spells.length; i++ )
    {
        ndx = ndxOfSpell( spells[i] );
        if ( -1 < ndx )
        {
            document.writeln ( getSpellTableRow( ndx ) );
        }
    }
    document.writeln ( "</table>" );
}  // writeGrimoire

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function writeKnightTemplar()
{
    if ( vKnightsTemplar == null || vKnightsTemplar == undefined )
    {
        initKnightsTemplar();
    }

    document.writeln ( "<table BORDER=0 CELLSPACING=0 CELLPADDING=1>" );
    document.writeln ( "<tr>" );

    document.writeln ( "<td style='vertical-align:top;'>" );
    document.writeln ( "<table BORDER=1 CELLSPACING=0 CELLPADDING=1>" );
    document.writeln ( "<tr>" );
    document.writeln ( "<th colspan=99>Clerical Investment" );
    document.writeln ( "<tr>" );
    document.writeln ( "<th>Rank" );
    document.writeln ( "<th>xp" );
    document.writeln ( "<th>Title" );
    for ( var ndx = 0; ndx < vKnightsTemplar.length; ndx++ )
    {
        document.writeln ( "<tr valign=top>" );
        document.writeln ( "<td nowrap align=center>" + String(ndx) );
        document.writeln ( "<td nowrap align=center>" + vKnightsTemplar[ndx][0] );
        document.writeln ( "<td nowrap>" + vKnightsTemplar[ndx][1] );
    }
    document.writeln ( "</table>" );

    document.writeln ( "<td style='vertical-align:top;'>" );
    document.writeln ( "<table BORDER=1 CELLSPACING=0 CELLPADDING=1>" );
    document.writeln ( "<tr>" );
    document.writeln ( "<th colspan=99>Power Investiture" );
    document.writeln ( "<tr>" );
    document.writeln ( "<th>Power" );
    document.writeln ( "<th>xp" );
    for ( var ndx = 0; ndx < vKnightsTemplarPowerInvestiture.length; ndx++ )
    {
        document.writeln ( "<tr valign=top>" );
        document.writeln ( "<td nowrap align=center>" + String(ndx+1) );
        document.writeln ( "<td nowrap align=center>" + vKnightsTemplarPowerInvestiture[ndx] );
    }
    document.writeln ( "</table>" );

    document.writeln ( "</table>" );

    vSpells.sort( cmpByRank );

    var lastRank = -1;
    document.writeln ( "<p>" );
    document.writeln ( "<table BORDER=1 CELLSPACING=0 CELLPADDING=1>" );
    document.writeln ( getSpellTableHeader() );
    for ( var ndx = 0; ndx < vSpells.length; ndx++ )
    {
        if ( lastRank != vSpells[ndx][nSpellRank] )
        {
            lastRank = vSpells[ndx][nSpellRank];
            document.writeln ( "<tr valign=top>" );
            document.writeln ( "<th class=column align=left colspan=20><b>" + String(lastRank) + ": " + getNameKnightTemplar( lastRank ) + "</b>" );
        }
        document.writeln ( getSpellTableRow( ndx ) );
    }
    document.writeln ( "</table>" );
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function SortSpellsBy( column )
{
    if ( nSpellName <= column && column <= nSpellItemValue )
    {
        spellsortcolumn = column;
        vSpells.sort( spellsorter );
        setFormHtml( "frmSpells", getSpellTable() );
    }
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
var spellsortcolumn;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function spellsorter( a, b )
{

    if ( a[spellsortcolumn] == b[spellsortcolumn] )
    {
        return 0;
    }
    else
    {
        if ( a[spellsortcolumn] < b[spellsortcolumn] )
        {
            return -1;
        }
        else
        {
            return +1;
        }
    }
    //return 0;
}

//----------------------------------------------------------------------------
function getSpellColumn( spell, column )
{
    var value;
    value = 0;
    var ndx;
    ndx = ndxOfSpell( spell );
    if ( -1 < ndx )
    {
        if ( nSpellName <= column && column <= nSpellItemValue )
        {
            value = vSpells[ndx][column];
        }
    }
    return value;
}  // getSpellColumn

//----------------------------------------------------------------------------
function getItemCost( spell )
{
    if ( vSpells == null || vSpells == undefined )
    {
        initSpells();
    }
    return getSpellColumn(spell,nSpellItemValue);
}


//----------------------------------------------------------------------------
function getSpellItem( spell, power )
{
    //return getSpellItem( spell, power, null );
    return new BagItem(spell, 0, 0, "notes");
}

//----------------------------------------------------------------------------
function getSpellItem( spell, power, notes )
{
    if ( vSpells == null || vSpells == undefined )
    {
        initSpells();
    }
    var item = new BagItem( "" + spell, getItemCost(spell) + getPowerstoneCost(power), 0, notes );
    if ( power != null && 0 < power )
    {
        item.notes = String(power);
        item.lbs = 0.1;
    }
    return item;
}

//----------------------------------------------------------------------------
function getGestureDescription( nPlus )
{

    var str = "no hand gestures or foot movement";
    if ( -6 < nPlus )
    {
        str = "no hand gestures or one hand and no foot movements";
    }
    if ( -4 < nPlus )
    {
        str = "no foot movement or gesturing with one hand";
    }
    if ( -2 < nPlus )
    {
        str = "gesturing with both hands and minimal foot movements";
    }
    if ( 0 < nPlus )
    {
        str = "huge exaggerated hand and foot movements";
    }
    return str;
}

//----------------------------------------------------------------------------
function getIncantationDescription( nPlus )
{
    var str = "no speech";
    if ( -4 < nPlus )
    {
        str = "soft speech";
    }
    if ( -2 < nPlus )
    {
        str = "firmly spoken voice";
    }
    if ( 0 < nPlus )
    {
        str = "shouting";
    }
    return str;
}

//----------------------------------------------------------------------------
function writeEnchantmentTables()
{
    document.writeln ( "<table>" );
    document.writeln ( "<tr>" );
    document.writeln ( "<td style='VERTICAL-ALIGN: top;'>" );       writeEnchantmentsTable( "Accuracy", vAccuracy );
    document.writeln ( "<td style='VERTICAL-ALIGN: top;'>" );       writeEnchantmentsTable( "Deflect", vDeflect );
    document.writeln ( "<td style='VERTICAL-ALIGN: top;'>" );       writeEnchantmentsTable( "Fortify", vFortify );
    document.writeln ( "<td style='VERTICAL-ALIGN: top;'>" );       writeEnchantmentsTable( "Lighten", vLighten );
    document.writeln ( "<td style='VERTICAL-ALIGN: top;'>" );       writeEnchantmentsTable( "Penetrating Blade", vPenetratingBlade );
    document.writeln ( "</table>" );
}

//----------------------------------------------------------------------------
function writeEnchantmentsTable( sName, vTable )
{
    document.writeln ( "<table BORDER=1 CELLSPACING=0 CELLPADDING=1>" );
    document.writeln ( "<tr>" );
    document.writeln ( "<th colspan=3>" + sName );

    document.writeln ( "<tr>" );
    document.writeln ( "<th class=column>mod" );
    document.writeln ( "<th class=column>mana" );
    document.writeln ( "<th class=column>cost" );

    var enchantment, mod;
    for ( enchantment = 0; enchantment < vTable.length; enchantment++ )
    {
        document.writeln ( "<tr valign=top>" );
        mod = vTable[enchantment][0];
        document.writeln ( "<td align=center>" + (0 <= mod ? "+" : "") + mod );  // mod
        document.writeln ( "<td align=right>" + vTable[enchantment][1] );  // mana
        document.writeln ( "<td align=right>$" + vTable[enchantment][2] ); // cost
    }
    document.writeln ( "</table>" );
    document.writeln ( "<p>" );
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function costOfEnchantment( enchantment, mod )
{
    var cost;
    var ndx;
    cost = 0;
    ndx = -1;
    switch ( enchantment )
    {
        case "Accuracy"          : ndx = ndxOfEnchantmentTable( mod, vAccuracy ); break;
        case "Puissance"         : ndx = ndxOfEnchantmentTable( mod, vAccuracy ); break;
        case "Deflect"           : ndx = ndxOfEnchantmentTable( mod, vDeflect ); break;
        case "Fortify"           : ndx = ndxOfEnchantmentTable( mod, vFortify ); break;
        case "Lighten Armour"    : ndx = ndxOfEnchantmentTable( mod, vLighten ); break;
        case "Penetrating Blade" : ndx = ndxOfEnchantmentTable( mod, vPenetratingBlade ); break;
    }
    if ( -1 < ndx )
    {
        switch ( enchantment )
        {
            case "Accuracy"          : cost = vAccuracy[ndx][2]; break;
            case "Puissance"         : cost = vAccuracy[ndx][2]; break;
            case "Deflect"           : cost = vDeflect[ndx][2]; break;
            case "Fortify"           : cost = vFortify[ndx][2]; break;
            case "Lighten Armour"    : cost = vLighten[ndx][2]; break;
            case "Penetrating Blade" : cost = vPenetratingBlade[ndx][2]; break;
        }
    }
    else
    {
        /*
        ndx = ndxOfSpell( enchantment );
        if ( -1 < ndx )
        {
            cost = vSpells[ndx][nSpellItemValue];
        }
         */
        cost = getItemCost( enchantment );
        window.status = enchantment + " costs $" + String(cost);
    }
    return cost;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function ndxOfEnchantment( enchantment, mod )
{
    switch ( enchantment )
    {
        case "Accuracy"         : return ndxOfEnchantmentTable( mod, vAccuracy );
        case "Puissance"        : return ndxOfEnchantmentTable( mod, vAccuracy );
        case "Deflect"          : return ndxOfEnchantmentTable( mod, vDeflect );
        case "Fortify"          : return ndxOfEnchantmentTable( mod, vFortify );
        case "Lighten Armour"   : return ndxOfEnchantmentTable( mod, vLighten );
        case "PenetratingBlade" : return ndxOfEnchantmentTable( mod, vPenetratingBlade );
    }
    return 0;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function ndxOfAccuracy( mod ) { return ndxOfEnchantmentTable( mod, vAccuracy ); }
function ndxOfDeflect( mod ) { return ndxOfEnchantmentTable( mod, vDeflect ); }
function ndxOfFortify( mod ) { return ndxOfEnchantmentTable( mod, vFortify ); }
function ndxOfLighten( mod ) { return ndxOfEnchantmentTable( mod, vLighten ); }
function ndxOfPenetratingBlade( mod ) { return ndxOfEnchantmentTable( mod, vPenetratingBlade ); }

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function ndxOfEnchantmentTable( mod, vTable )
{
    ndx = -1;
    var i;
    for( i = 0; i < vTable.length; i++  )
    {
        if ( mod == vTable[i][0] )
        {
            ndx = i;
            break;
        }
    }
    if ( vTable.length <= ndx )
    {
        ndx = -1;                       // not found
    }
    return ndx;
}

//----------------------------------------------------------------------------
function initEnchantments()
{
    //      mod,    mana,   cost($)
    vAccuracy = [
            [+0,    0,       0          ],
            [+1,    250,     4510       ],
            [+2,    1000,    25000      ],
            [+3,    5000,    125000     ],
            [+4,    20000,   500000     ],
            [+5,    80000,   2000000    ]
        ];
    vDeflect = [
            [+0,    0,       0          ],
            [+1,    100,     100        ],
            [+2,    500,     12500      ],
            [+3,    2000,    50000      ],
            [+4,    8000,    200000     ],
            [+5,    20000,   500000     ]
        ];
    vFortify = [
            [+0,    0,       0          ],
            [+1,    50,      50         ],
            [+2,    200,     1790       ],
            [+3,    800,     20000      ],
            [+4,    3000,    75000      ],
            [+5,    8000,    200000     ]
        ];
    vLighten = [
            [ -0.00,     0,     0 ],
            [ -0.25,   100,   100 ],
            [ -0.50,   500, 12500 ]
        ];
    vPenetratingBlade = [
            [+0,    0,       0          ],
            [-1,    150,     505        ],
            [-2,    600,     15000      ],
            [-3,    2400,    60000      ],
            [-4,    9000,    225000     ],
            [-5,    24000,   600000     ]
        ];
}

//----------------------------------------------------------------------------
function initKnightsTemplar()
{
    vKnightsTemplar = [
       // xp   title or rank (clerical investment)
        [  2, "Servant Brother (Freres de Metier)" ],  // 1
        [  4, "Rural Brother (Freres Casaliers)" ],    // 2
        [  6, "Esquire" ],                             // 3
        [  8, "Sergeant (Serving Brother)" ],          // 4
        [ 16, "Knight" ],                              // 5
        [ 32, "Counciler Or Master" ],                 // 6
        [ 64, "Grand Master" ]                         // 7
    ];

    vKnightsTemplarPowerInvestiture = [ 8, 14, 20 ];

    initSpellColumns();
    vSpells = [
        // Spell,Difficulty,Class,Resistance,College,CastingTime,Duration,Energy,Prerequisite,ItemEnergyCost,ItemValue
        [ "Armor","MH","Regular","~","Protection & Warning","10s","1m","2/DR+|same","Repair",-1,-1, 2 ],
        [ "Astral Vision","MVH","Regular","~","Knowlege","10s","10m","4|2","Sense Spirit and See Invisible",900,22500, 4 ],
        [ "Aura","MH","Information","~","Knowlege","1s","Instant","3","Detect Magic",100,100, 3 ],
        [ "Banish","MH","Special","ST+IQ","Necromatic","5s","Instant","special","M, 1 spell from ea. ten colleges",-1,-1, 4 ],
        [ "Bless: +1","MH","Regular","~","Meta-Spells","1m/e","10,50,500","until lost","M2, 2 spells each ten colleges",100,100, 3 ],
        [ "Bless: +2","MH","Regular","~","Meta-Spells","1m/e","10,50,500","until lost","M2, 2 spells each ten colleges",100,100, 4 ],
        [ "Bless: +3","MH","Regular","~","Meta-Spells","1m/e","10,50,500","until lost","M2, 2 spells each ten colleges",100,100, 5 ],
        [ "Block","MH","Blocking","~","Protection & Warning","~","Instant","1/PD","M",-1,-1, 1 ],
        [ "Bravery","MH","Area","IQ-1","Mind Control","10s","1h","2","Fear",500,12500, 1 ],
        [ "Compel Truth","MH","Information","IQ","Communication","1s","5m","4|2","M2, Truthsayer",600,15000, 5 ],
        [ "Consecrate","MH","Enchantment","~","Clerical","5m","Perm","10","~",-1,-1, 6 ],
        [ "Deflect Missile","MH","Blocking","~","Protection & Warning","~","Instant","1","Apportation",200,1790, 2 ],
        [ "Detect Magic","MH","Regular","~","Knowlege","5s","Instant","2","M",300,7500, 2 ],
        [ "Dexterity","MH","Regular","~","Body Control","10s","1m","2/DX+|same","Clumsiness",2000,50000, 3 ],
        [ "Dispel Magic","MH","Area","spell","Meta-Spells","sec=cost","Perm","3","Counterspell and 12 other spells",-1,-1, 5 ],
        [ "Final Rest","MH","Regular","~","Clerical","10m","Perm","20","~",-1,-1, 3 ],
        [ "Gift of Tongues","MVH","Regular","~","Communication","1s","1m","4|2","Borrow Language, 3 lang.@10+",300,7500, 1 ],
        [ "Great Voice","MH","Regular","~","Sound","20s","1m","3|1","Voices, Thunderclap",200,1790, 3 ],
        [ "Hardiness","MH","Blocking","~","Protection & Warning","~","Instant","1/DR","Stiffen",-1,-1, 1 ],
        [ "Healing Slumber","MH","Regular","(auto)","Healing","30s","8hr","6,10","M2, Peacful Sleep, Minor Healing",-1,-1, 3 ],
        [ "Lend Strength","MH","Regular","~","Healing","1s","Perm","var","M or Empathy adv.",100,100, 1 ],
        [ "Light","MH","Regular","~","Light & Darkness","10s","1m","1|1","none",100,100, 1 ],
        [ "Magic Resistance","MH","Regular","IQ+M","Meta-Spells","30s","1m","1 to 5|same","M, 1 ea. From 7 colleges",300,7500, 4 ],
        [ "Major Healing","MVH","Regular","~","Healing","10s","Perm","1 to 4","M, Minor Healing",1500,37500, 4 ],
        [ "Might","MH","Regular","~","Body Control","10s","1m","2/ST+|same","Lend Strength",1500,37500, 2 ],
        [ "Minor Healing","MH","Regular","~","Healing","10s","Perm","1 to 3","Lend Health",600,15000, 2 ],
        [ "Pentagram","MH","Special","~","Meta-Spells","50s/hex","Perm","10/hex","Spell Shield",-1,-1, 5 ],
        [ "Purify Air","MH","Area","~","Air","10s","Instant","1","none",50,50, 1 ],
        [ "Purify Food","MH","Regular","~","Food","10s","Perm","1/lb","Preserve Food or Decay",400,10000, 2 ],
        [ "Purify Water","MH","Special","~","Water","50-100s/gal","Perm","1/gal","Seek Water",50,50, 1 ],
        [ "Remove Curse","MH","Regular","Spell","Meta-Spells","1h","Instant","20","M2, 1 ea. From 15 colleges",-1,-1, 5 ],
        [ "Repair","MH","Regular","~","Making & Breaking","10s/lb","Perm","3/10lbs","M2, Rejoin",-1,-1, 4 ],
        [ "Repel Spirits","MH","Area","IQ","Necromatic","10s","1h","4|2","Banish and Turn Spirit",1100,27500, 5 ],
        [ "Scrywall","MH","Area","~","Meta-Spells","10s/e","10h","3|2","Scryguard",300,7500, 5 ],
        [ "Sense Danger","MH","Information","~","Protection & Warning","10s","Instant","3","Sense Foes or Danger Sense adv.",400,10000, 2 ],
        [ "Sense Foes","MH","Information/Area","~","Communication","10s","Instant","1(min.2)","none",200,1790, 1 ],
        [ "Sense Observation","MH","Area","~","Protection & Warning","50s","1hr","1 or 3 | .5 or 1.5","Sense Danger or Scryguard",-1,-1, 4 ],
        [ "Sense Spirit","MH","Information/Area","~","Necromatic","10s","Instant","0.5","Death Vision or Sense Life and M",100,100, 3 ],
        [ "Shatterproof","MH","Regular","~","Making & Breaking","1s","1h","3/3","Repair, Shatter",400,10000, 5 ],
        [ "Shield","MH","Regular","~","Protection & Warning","10s","1m","2/PD+|same","M2",-1,-1, 2 ],
        [ "Spell Shield","MH","Area","~","Meta-Spells","10s","1m","3|2","M2, Scryguard, Magic Resistance",400,10000, 5 ],
        [ "Stop Bleeding","MH","Regular","~","Healing","1s","Perm","1 or 10","Lend Health",-1,-1, 1 ],
        [ "Turn Spirit","MH","Regular","IQ","Necromatic","1s","10s","4|2","Fear and Sense Spirit",350,8750, 4 ],
        [ "Turn Zombie","MH","Area","~","Necromatic","2s","1d","2","Zombie",600,15000, 3 ],
        [ "Vigor","MH","Regular","~","Body Control","10s","1m","2/HT+|same","Lend Health",1500,37500, 1 ]
    ];
}  // initKnightsTemplar

//----------------------------------------------------------------------------
function getNameKnightTemplar( rank )
{
    var sVal;
    sVal = "none";
    if ( vKnightsTemplar != null )
    {
        rank--;
        if ( 0 <= rank && rank <= vKnightsTemplar.length )
        {
            sVal = vKnightsTemplar[rank][1];
        }
    }
    return sVal;
}

//----------------------------------------------------------------------------
function getRankKnightTemplar( xp )
{
    var sVal, rank;
    sVal = "none";
    if ( vKnightsTemplar != null )
    {
        for ( rank = 0; rank < vKnightsTemplar.length; rank++ )
        {
            if ( xp < vKnightsTemplar[rank][0] )
            {
                break;
            }
            sVal = vKnightsTemplar[rank][1];
        }
    }
    return sVal;
}

//----------------------------------------------------------------------------
function getKnightTemplarPower( xp )
{
    var power = 0;
    if ( vKnightsTemplar != null )
    {
        for ( power = 0; power < vKnightsTemplarPowerInvestiture.length; power++ )
        {
            if ( xp < vKnightsTemplarPowerInvestiture[power] )
            {
                break;
            }
        }
        /*
        if ( 8 <= xp )
        {
            power = 1;
        }
        if ( 14 <= xp )
        {
            power = 2;
        }
        if ( 20 <= xp )
        {
            power = 3;
        }
         */
    }
    return power;
}


//----------------------------------------------------------------------------
function initBard()
{
    bBard = true;
    initSpellColumns();
    vSpells = [
        // Spell,Difficulty,Class,Resistance,College,CastingTime,Duration,Energy,Prerequisite,ItemEnergyCost,ItemValue
        [ "Alter Visage","MH","Regular","HT","Body Control","1m","1h","4/3","Shapeshifting or Perf Illusion",1000,25000 ],
        [ "Analyze Magic","MH","Information","Spell","Knowlege","1h","Instant","8","Identify Spell",1200,30000 ],
        [ "Ancient History","MH","Information","~","Knowlege","min=cost","Instant","var","History",-1,-1 ],
        [ "Aura","MH","Information","~","Knowlege","10s","Instant","3","Detect Magic",100,100 ],
        [ "Borrow Language","MH","Regular","~","Communication","30s","1m","3/1","Lend Language",-1,-1 ],
        [ "Bravery","MH","Area","IQ-1","Mind Control","10s","1h","2","Fear",500,12500 ],
        [ "Charm","MH","Regular","IQ","Mind Control","30s","1m","6/3","M, Loyalty, 7 Mind Control",3000,75000 ],
        [ "Compel Truth","MH","Information","IQ","Communication","10s","5m","4|2","M2, Truthsayer",600,15000 ],
        [ "Complex Illusion","MH","Area","~","Illusion & Creation","10s","1m","2|1","Sound, Simple Illusion",-1,-1 ],
        [ "Control Creation","MH","Regular","spell","Illusion & Creation","20s","Instant","1/hex","Create Animal or Create Servant",400,10000 ],
        [ "Control Illusion","MH","Regular","spell","Illusion & Creation","20s","Perm","1/hex","Perfect Illusion",300,7500 ],
        [ "Create Animal","MH","Regular","~","Illusion & Creation","sec=cost*10","1m","var","Create Water, Create Object, IQ 13+",-1,-1 ],
        [ "Create Object","MVH","Regular","~","Illusion & Creation","sec=cost*10","Indef.","2/5lbs","M2, Create Earth, Perfect Illusion",-1,-1 ],
        [ "Create Servant","MH","Regular","~","Illusion & Creation","30s","1m","3/1","M3, IQ13+, Create Object",-1,-1 ],
        [ "Create Warrior","MH","Regular","~","Illusion & Creation","40s","1m","4/4","Create Servant",-1,-1 ],
        [ "Daze","MH","Regular","HT","Mind Control","20s","1m","3/2","Foolishness",1000,25000 ],
        [ "Delayed Message","MH","Area","~","Sound","40s","Indef.","3","M, Voices, Detect Life",-1,-1 ],
        [ "Detect Magic","MH","Regular","~","Knowlege","50s","Instant","2","M",300,7500 ],
        [ "Dispel Creation","MH","Regular","spell","Illusion & Creation","10s","Instant","1/hex","Control Creation",500,12500 ],
        [ "Dispel Illusion","MH","Regular","spell","Illusion & Creation","10s","Instant","1/hex","Control Illusion",400,10000 ],
        [ "Emotion Control","MH","Area","IQ","Mind Control","10s","1h","2","Loyalty",1000,25000 ],
        [ "Enslave","MVH","Regular","IQ","Mind Control","10s","Perm","30","Charm, Telepathy",-1,-1 ],
        [ "Fear","MH","Area","IQ","Mind Control","10s","10m","1","Sense Emotion",300,7500 ],
        [ "Foolishness","MH","Regular","IQ","Mind Control","10s","1m","1/IQ-/h","IQ12+",800,20000 ],
        [ "Forgetfulness","MH","Regular","IQ or skill","Mind Control","2m","1h","3/3","M, Foolishness, IQ12+",500,12500 ],
        [ "Gift of Tongues","MVH","Regular","~","Communication","10s","1m","4|2","Borrow Language, 3 lang.@10+",300,7500 ],
        [ "Great Geas","MVH","Regular","IQ","Mind Control","1m","Perm","30","M3, 15 Mind Control inc. Lesser Geas",4000,100000 ],
        [ "Great Voice","MH","Regular","~","Sound","20s","1m","3|1","Voices, Thunderclap",200,1790 ],
        [ "History","MH","Information","~","Knowlege","sec=cost*10","Instant","var","Trace",-1,-1 ],
        [ "Hush","MH","Regular","IQ","Sound","20s","10s","2/1","Silence",200,1790 ],
        [ "Illusion Disguise","MH","Regular","~","Illusion & Creation","10s","until disbelieved","3","Simple Illusiion",150,505 ],
        [ "Illusion Shell","MH","Regular","~","Illusion & Creation","10s","1m","2/hex","Simple Illusiion",200,1790 ],
        [ "Independence","MH","Area","~","Illusion & Creation","var","var","2","Simple Illusiion",-1,-1 ],
        [ "Know Illusion","MH","Information","~","Illusion & Creation","1s","Instant","2","Simple Illusiion",-1,-1 ],
        [ "Lesser Geas","MVH","Regular","IQ","Mind Control","30s","Perm","12","M2, 10 Mind Control",2000,50000 ],
        [ "Loyalty","MH","Regular","IQ","Mind Control","20s","1h","2/2","Bravery, 4 other Mind Control",2000,50000 ],
        [ "Madness","MH","Regular","IQ-2","Mind Control","20s","1m","4/2","Forgetfulness or Drunkenness",1000,25000 ],
        [ "Mass Daze","MH","Area","HT","Mind Control","sec=cost*10","Instant","2/1","Daze, IQ13+",-1,-1 ],
        [ "Mass Sleep","MH","Area","HT","Mind Control","sec=cost*10","Instant","3","Sleep, IQ13+",-1,-1 ],
        [ "Mass Suggestion","MH","Area","IQ","Mind Control","sec=cost*10","10m","4/2","Suggestion",1500,37500 ],
        [ "Message","MH","Regular","Sound","Sound","dura","15s","1fat. / 15secs","Great Voice, Seeker",1000,25000 ],
        [ "Mind-Reading","MH","Regular","IQ","Communication","10s","1m","4|2","Truthsayer",1000,25000 ],
        [ "Noise","MH","Regular","~","Sound","10s","1h","2","Purify Air",100,100 ],
        [ "Panic","MH","Regular","IQ","Mind Control","10s","1m","4|2","Fear",-1,-1 ],
        [ "Peaceful Sleep","MH","Regular","Special","Mind Control","1m","8h","4","Sleep, Silence",900,22500 ],
        [ "Perfect Illusion","MH","Area","~","Illusion & Creation","10s","1m","3/h","M, Complex Illusion",-1,-1 ],
        [ "Persuasion","MH","Regular","IQ","Communication","10s","1m","2xbonus","Sense Emotion",1000,25000 ],
        [ "Phantom","MH","Area","~","Illusion & Creation","10s","1m","9|4.5","M2, Perfect Illusion, Hinder, Apportation",300,7500 ],
        [ "Sense Danger","MH","Information","~","Protection & Warning","10s","Instant","3","Sense Foes or Danger Sense adv.",400,10000 ],
        [ "Sense Emotion","MH","Regular","~","Communication","10s","Instant","2","Sense Foes",300,7500 ],
        [ "Sense Foes","MH","Information/Area","~","Communication","10s","Instant","1(min.2)","none",200,1790 ],
        [ "Silence","MH","Area","~","Sound","10s","1m","2|1","Sound",80,80 ],
        [ "Simple Illusion","MH","Area","~","Illusion & Creation","10s","1m","1/h","not blind, IQ11+",-1,-1 ],
        [ "Sleep","MH","Regular","HT","Mind Control","30s","Instant","4","Daze",1200,30000 ],
        [ "Sound","MH","Regular","~","Sound","1s","var","var","none",50,50 ],
        [ "Strengthen Will","MH","Regular",,"Mind Control","10s","1m","1/+1","M and 6 Mind Control spells",-1,-1 ],
        [ "Suggestion","MH","Regular","IQ","Mind Control","1m","10m","4/3","Emotion Control, Forgetfulness",500,12500 ],
        [ "Terror","MH","Area","IQ","Mind Control","10s","Instant","4","Fear",-1,-1 ],
        [ "Thunderclap","MH","Regular","~","Sound","10s","Instant","2","Sound",-1,-1 ],
        [ "Truthsayer","MH","Information","IQ","Communication","10s","Instant","2","Sense Emotion",500,12500 ],
        [ "Voices","MH","Regular","~","Sound","10s","1m","3/2","Sound",20,20 ],
        [ "Wall of Silence","MH","Area","~","Sound","10s","1m","2/1","Silence",100,100 ],
        [ "Watchdog","MH","Area","~","Protection & Warning","1m","10h","1/1","Sense Danger",200,1790 ],
        [ "Weaken Will","MH","Regular","IQ","Mind Control","10s","1m","2/-1","M, Foolishness",-1,-1 ],
        [ "Wisdom","MH","Regular","~","Mind Control","10s","1m","var","6 other Mind Control",2000,50000 ]
    ];
}  // initBard

//----------------------------------------------------------------------------
function errorDetail(msg, url, lno)
{
    //document.writeln('<B>Error in file:</B> ' + url + '<BR>');
    //document.writeln('<B>Line number:</B> ' + lno + '<BR>');
    document.writeln('<B>Error(line:' + lno + '):</B>' + msg + '<P>')
    return false;
}

//----------------------------------------------------------------------------
function errorHandler(msg, url, lno)
{
    msgArray[msgArray.length] = msg;
    urlArray[urlArray.length] = url;
    lnoArray[lnoArray.length] = lno;
    return true;
}

//----------------------------------------------------------------------------
function displayErrors()
{
    win2=window.open('','window2','scrollbars=yes');
    win2.document.writeln('<B>Error Report</B><P>');
    for (var i=0; i < msgArray.length; i++)
    {
        win2.document.writeln('<B>Error in file:</B> ' + urlArray[i] + '<BR>');
        win2.document.writeln('<B>Line number:</B> ' + lnoArray[i] + '<BR>');
        win2.document.writeln('<B>Message:</B> ' + msgArray[i] + '<P>')
    }
    win2.document.close();
}

//----------------------------------------------------------------------------
// Sets cookie values. Expiration date is optional
function setCookie(name, value, expire)
{
    var today = new Date();
    var expires = new Date();
    expires.setTime(today.getTime() + 1000*60*60*24*365*10);  // 10 yrs from now
    document.cookie = name + "=" + escape(value) + ("; expires=" + expires.toGMTString());
}

//----------------------------------------------------------------------------
// get cookie set from above
function getCookie(Name)
{
    var search = Name + "=";
    if (document.cookie.length > 0)
    {
        // if there are any cookies
        offset = document.cookie.indexOf(search);
        if (offset != -1)
        {
            // if cookie exists
            offset += search.length;          // set index of beginning of value
            end = document.cookie.indexOf(";", offset);          // set index of end of cookie value
            if (end == -1) end = document.cookie.length;
            return unescape(document.cookie.substring(offset, end));
        }
    }
    return null;
}


//----------------------------------------------------------------------------
function init()
{
    //window.onerror = errorHandler;
    window.onerror = errorDetail;
    msgArray = new Array();
    urlArray = new Array();
    lnoArray = new Array();
    gDebug = false;
    gShowMoney = false;
    initSkills();
    initLanguages();
    initArmor();
    initWeapons();
    initRangedWeapons();
    initGuns();
    initEnchantments();
    initPowerstone();
    initStatus();
    myStartingStatus = 0;
    myWealth = 0;

    vAttr = [ -80, -70, -60, -50, -40, -30, -20, -15, -10, 0, 10, 20, 30, 45, 60, 80, 100, 125, 150, 175 ];
    //                    3,   4,   5,   6,   7,   8,   9,10, 11, 12, 13, 14, 15, 16,  17,  18,  19,  20
    xpTotal = 0;
}

//----------------------------------------------------------------------------
function initSkills()
{
    vSkills = [
        // skill                           difficukty  attr       default [attr:0,mod:1],            max, variant on last skill?
        // 0                                   1       2          3                                  4    5
        [ "Abacus",                           "MA",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Accounting",                       "MH",   "IQ",      [["IQ",       -10],
                                                                  ["Merchant", -5],
                                                                  ["Mathematics", -5]
                                                                 ], +99, false ],
        [ "Acrobatic Kick",                   "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Acrobatics",                       "PH",   "DX",      [["DX",                        -6 ]], +99, false ],
        [ "Acting",                           "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Administration",                   "MA",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Advanced Sexual Techniques",       "MH",   "IQ",      [["Intercourse", -6 ]              ], +99, false ],
        [ "Aggresive Parry",                  "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Aggressive Parrying Kick",         "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Agronomy",                         "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Airshipman",                       "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Alchemy",                          "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Animal Guise",                     "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Animal Handling",                  "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Anthropology",                     "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Appreciate Beauty",                "MVH",  "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Archaeology",                      "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Architecture",                     "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Area Knowledge",                   "ME",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Arm/Wrist Lock",                   "A",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Armoury",                          "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Artificial Intelligence",          "MH",   "IQ",      [["Computer Programming",      -3 ]], +99, false ],
        [ "Artist",                           "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Astrology",                        "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Astronomy",                        "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Augury",                           "MVH",  "IQ",      [["Theology",                  -4 ]], +99, false ],
        [ "Autohypnosis",                     "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Aviation",                         "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Axe Kick",                         "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Axe Throwing",                     "PE",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Axe/Mace",                         "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Back Kick",                        "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Ball Game",                        "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Bard",                             "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Bardic Lore",                      "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Bartender",                        "MA",   "IQ",      [["Carousing",                 -3 ]], +99, false ],
        [ "Baton",                            "PA",   "",        [[" ",                         +0 ]], +99, false ],
        [ "Battlesuit",                       "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Beam Weapons",                     "PE",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Being Ridden",                     "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Beverage-Making",                  "ME",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Bicycling",                        "PE",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Bind",                             "H",    "maneuver",[[ "skill",                    +0 ]], +3 , true  ],
        [ "Biochemistry",                     "MVH",  "IQ",      [["Chemistry",                 -5 ]], +99, false ],
        [ "Black Powder Weapons",             "PE",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Blackjack",                        "PE",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Blacksmith",                       "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Blind Fighting",                   "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Blinding Touch",                   "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Blowpipe (Fukiya)",                "PE",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Blowpipe",                         "PH",   "DX",      [["DX",                        -6 ]], +99, false ],
        [ "Board Games",                      "ME",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Boating",                          "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Body Control",                     "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Body Language",                    "MH",   "IQ",      [["Psychology",                -3 ]], +99, false ],
        [ "Body Sense",                       "PH",   "DX",      [["DX",                        -6 ]], +99, false ],
        [ "Boinger",                          "PA",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Bolas",                            "PA",   "DX",      [["none",                      +0 ]], +99, false ],
        [ "Botany",                           "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Bow",                              "PH",   "DX",      [["DX",                        -6 ]], +99, false ],
        [ "Bow and Palette",                  "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Boxing",                           "PA",   "DX",      [["none",                      +0 ]], +99, false ],
        [ "Brain Hacking",                    "MVH",  "IQ",      [["Will",                      -6 ]], +99, false ],
        [ "Brawling",                         "PE",   "DX",      [["DX",                        -6 ]], +99, false ],
        [ "Breakfall",                        "A",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Breaking Blow",                    "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Breath Control",                   "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Broadsword",                       "PA",   "DX",      [["DX", -5 ],
                                                                  ["Shortsword", -2 ]
                                                                 ], +99, false ],
        [ "Buckler",                          "PE",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Bulldancing",                      "PH",   "DX",      [["Acrobatics",                -5 ]], +99, false ],
        [ "Bullfighting",                     "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Bun Fu",                           "PH",   "DX",      [["none",                      +0 ]], +99, false ],
        [ "Calligraphy",                      "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Camouflage",                       "ME",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Carousing",                        "PA",   "HT",      [["HT",                        -4 ]], +99, false ],
        [ "Carpentry",                        "ME",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Cartography",                      "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Cat Stance",                       "A",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Ch'i Treatment",                   "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Change Control",                   "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Chemistry",                        "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Chess",                            "ME",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Choke Hold",                       "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Choreography",                     "MA",   "IQ",      [["Dancing",                   -2 ]], +99, false ],
        [ "Climbing",                         "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Cloak",                            "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Close Combat",                     "A",    "maneuver",[["skill",                     +0 ]], +2 , true  ],
        [ "Computer Hacking",                 "MVH",  "IQ",      [["Computer Programming",      -4 ]], +99, false ],
        [ "Computer Operation",               "ME",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Computer Programming",             "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Conducting",                       "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Conspiracy Theory",                "MVH",  "IQ",      [["History",                   -4 ]], +99, false ],
        [ "Cooking",                          "ME",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Cooperage",                        "ME",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Corps-à-Corps",                    "H",    "maneuver",[[ "skill",                    +0 ]], +2 , true  ],
        [ "Counterattack",                    "H",    "maneuver",[[ "skill",                    +0 ]], +5 , true  ],
        [ "Courtesan",                        "MA",   "IQ",      [["Savoir-Faire",              -5 ]], +99, false ],
        [ "Criminology",                      "MA",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Crossbow",                         "PE",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Cryptanalysis",                    "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Cryptography",                     "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Cryptology",                       "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Cyberaxe",                         "MH",   "IQ",      [["(similar instrument)",      -4 ]], +99, false ],
        [ "Cyberdeck Operation",              "MVH",  "IQ",      [["Computer Operation",        -8 ]], +99, false ],
        [ "Cyphering",                        "ME",   "IQ",      [["IQ",                        -2 ]], +99, false ],
        [ "Dancing",                          "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Darts",                            "PE",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Demolition",                       "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Detect Lies",                      "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Dexitroboping",                    "PH",   "DX",      [["none",                      +0 ]], +99, false ],
        [ "Diagnosis",                        "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Diplomacy",                        "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Directing",                        "MH",   "IQ",      [["Performance",               -5 ]], +99, false ],
        [ "Disarming",                        "H",    "maneuver",[[ "skill",                    +0 ]], +5 , true  ],
        [ "Disguise",                         "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Dislocating",                      "PH",   "DX",      [["none",                      +0 ]], +99, false ],
        [ "Distilling",                       "MA",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Dreaming",                         "MVH",  "IQ",      [["IQ",                        -10]], +99, false ],
        [ "Dreamlands Lore",                  "MH",   "IQ",      [["Dream Travel",              -5 ]], +99, false ],
        [ "Driving",                          "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Drop Kick",                        "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Drunken Fighting",                 "PH",   "DX",      [["none",                      +0 ]], +99, false ],
        [ "Dual-Weapon Attack",               "H",    "maneuver",[[ "skill",                    +0 ]], +4 , true  ],
        [ "Dual-Weapon Parry",                "H",    "maneuver",[[ "skill",                    +0 ]], +2 , true  ],
        [ "Dyeing",                           "MA",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Ear Clap",                         "A",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Ecology",                          "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Economics",                        "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Elbow Strike",                     "A",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Electronics Operation",            "MA",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Electronics",                      "MH",   "IQ",      [["(other electronics)",       -4 ]], +99, false ],
        [ "Emmfozing",                        "PH",   "DX",      [["DX",                        -6 ]], +99, false ],
        [ "Engineer",                         "MH",   "IQ",      [["Mechanic",                  -6 ]], +99, false ],
        [ "Enigmas",                          "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Enthrallment: Captivate",          "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Enthrallment: Persuade",           "MA",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Enthrallment: Suggest",            "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Enthrallment: Sway Emotions",      "MA",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Equestrian Acrobatics",            "PH",   "DX",      [["Riding",                    -3 ]], +99, false ],
        [ "Erotic Art",                       "PH",   "DX",      [["Acrobatics",                -5 ]], +99, false ],
        [ "Escape",                           "PH",   "DX",      [["DX",                        -6 ]], +99, false ],
        [ "Esquive",                          "H",    "maneuver",[[ "skill",                    +0 ]], +3 , true  ],
        [ "Exorcism",                         "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Exoskeleton",                      "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Explosive Ordnance Disposal",      "MH",   "IQ",      [["Demolition",                -4 ]], +99, false ],
        [ "Eye-Gouging",                      "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Face Attacks",                     "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Falconry",                         "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Fanning",                          "PE",   "DX",      [["DX",                        -6 ]], +99, false ],
        [ "Fast-Draw",                        "PE",   "DX",      [["none",                      +0 ]], +99, true  ],
        [ "Fast-Talk",                        "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Featherworking",                   "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Feint",                            "H",    "maneuver",[[ "skill",                    +0 ]], +4 , true  ],
        [ "Fencing",                          "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Fiber Crafts",                     "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Fight Choreography",               "MA",   "IQ",      [["Stage Combat",              -2 ]], +99, false ],
        [ "Fighting While Seated",            "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Finger Lock",                      "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Fire Eating",                      "PA",   "DX",      [["none",                      +0 ]], +99, false ],
        [ "Fire Walking",                     "ME",   "IQ",      [["Will",                      -5 ]], +99, false ],
        [ "Fire-Siphon",                      "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Fireworks",                        "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "First Aid",                        "ME",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Fishing",                          "ME",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Flail",                            "PH",   "DX",      [["DX",                        -6 ]], +99, false ],
        [ "Fleche",                           "A",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Flight",                           "PA",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Flint Sparking",                   "PE",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Floor Lunge",                      "H",    "maneuver",[[ "Fencing",                  +0 ]], +4 , true  ],
        [ "Flower Arranging",                 "ME",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Flying Fists",                     "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Flying Jump Kick",                 "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Flying Leap",                      "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Fnord",                            "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Force Shield",                     "PE",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Force Sword",                      "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Force Whip",                       "PA",   "DX",      [["Whip",                      -3 ]], +99, false ],
        [ "Forensics",                        "MH",   "IQ",      [["Criminology",               -4 ]], +99, false ],
        [ "Foreplay",                         "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Forgery",                          "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Fortune Telling",                  "MA",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Forward Observer",                 "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Free Fall",                        "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Freight Handling",                 "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Gambling",                         "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Games",                            "ME",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Gardening",                        "ME",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Garrote",                          "PE",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Genetics",                         "MVH",  "IQ",      [["Biochemistry",              -5 ]], +99, false ],
        [ "Geology",                          "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Gesture",                          "ME",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Glassblowing",                     "PH",   "DX",      [["DX",                        -6 ]], +99, false ],
        [ "Glide",                            "H",    "maneuver",[[ "skill",                    +0 ]], +4 , true  ],
        [ "Ground Fighting",                  "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Gunner",                           "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Guns: Pistol",                     "PE",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Guns: Rifle",                      "PE",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Guns: Shotgun",                    "PE",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Hand of Death",                    "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Hand-Clap Parry",                  "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Hard-Hat Diving",                  "MA",   "IQ",      [["Scuba",                     -2 ]], +99, false ],
        [ "Harpoon",                          "PH",   "DX",      [["Spear Throwing",            -2 ]], +99, false ],
        [ "Head Butt",                        "A",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Head Lock",                        "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Hedgewise",                        "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Heraldry",                         "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Herbalist",                        "MH",   "IQ",      [["Naturalist",                -6 ]], +99, false ],
        [ "Herbary",                          "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Hidden Lore(type)",                "MA",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Hiking",                           "PA",   "HT",      [["none",                      +0 ]], +99, false ],
        [ "History",                          "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "History:Esoteric",                 "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Hit Location",                     "H",    "maneuver",[[ "skill",                    +0 ]], +3 , true  ],
        [ "Holdout",                          "MA",   "IQ",      [["IQ", -5 ],
                                                                  ["Sleight of Hand", -3 ]
                                                                 ], +99, false ],
        [ "Hook Kick",                        "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Howl(type)",                       "PA",   "HT",      [["none",                      +0 ]], +99, false ],
        [ "Hyperborean Baton",                "PH",   "DX",      [["none",                      +0 ]], +99, false ],
        [ "Hyperspace Physics",               "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Hypnotic Hands",                   "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Hypnotism",                        "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Illumination",                     "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Illusion Art",                     "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Immovable Stance",                 "PH",   "DX",      [["none",                      +0 ]], +99, false ],
        [ "Initial Carving",                  "A",    "maneuver",[[ "skill",                    +0 ]], +4 , true  ],
        [ "Intelligence Analysis",            "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Intercourse",                      "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Intercourse, adv",                 "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Interrogation",                    "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Intimidation",                     "MA",   "IQ",      [["ST",                        -5 ]], +99, false ],
        [ "Invisiblity Art",                  "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Jab",                              "A",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Jeweler",                          "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Jitte/Sai",                        "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Judo",                             "PH",   "DX",      [["none",                      +0 ]], +99, false ],
        [ "Juggling",                         "PE",   "DX",      [["Sleight of Hand",           -3 ]], +99, false ],
        [ "Jump Kick",                        "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Jumping",                          "PE",   "DX",      [["none",                      +0 ]], +99, false ],
        [ "Karate",                           "PH",   "DX",      [["none",                      +0 ]], +99, false ],
        [ "Katana",                           "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Keneenk",                          "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Kiai",                             "PH",   "HT",      [["none",                      +0 ]], +99, false ],
        [ "Kicking",                          "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Kissing",                          "ME",   "IQ",      [                                  ], +99, false ],
        [ "Kite Flying",                      "PE",   "DX",      [["DX",                        -2 ]], +99, false ],
        [ "Knee Strike",                      "A",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Knife",                            "PE",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Knife Throwing",                   "PE",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Kosho",                            "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Kusari",                           "PH",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Lance",                            "PA",   "DX",      [["Spear",                     -2 ]], +99, false ],
        [ "Language, Average",                "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Language, Easy",                   "ME",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Language, Hard",                   "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Lasso",                            "PA",   "DX",      [["none",                      +0 ]], +99, false ],
        [ "Law",                              "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Leadership",                       "MA",   "IQ",      [["ST",                        -5 ]], +99, false ],
        [ "Leatherworking",                   "ME",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Lifting",                          "PH",   "ST",      [["none",                      +0 ]], +99, false ],
        [ "Light Walk",                       "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Linguistics",                      "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Lip Reading",                      "MA",   "IQ",      [["Vision",                    -10]], +99, false ],
        [ "Literature",                       "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Lockpicking",                      "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Low-G Flight",                     "PA",   "DX",      [["ST",                        -6 ]], +99, false ],
        [ "Lucid Dreaming",                   "ME",   "IQ",      [["Will",                      -4 ]], +99, false ],
        [ "Lunge",                            "A",    "maneuver",[[ "skill",                    +0 ]], +2 , true  ],
        [ "Magic Breath",                     "PE",   "DX",      [["DX",                        -2 ]], +99, false ],
        [ "Magic Jet",                        "PE",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Main-Gauche",                      "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Make-Up",                          "ME",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Masonry",                          "PE",   "DX",      [["IQ",                        -3 ]], +99, false ],
        [ "Masquerade",                       "PA",   "HT",      [["IQ",                        -4 ]], +99, false ],
        [ "Mathematics",                      "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Mechanic",                         "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Meditation",                       "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Mental Strength",                  "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Merchant",                         "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Metallurgy",                       "MH",   "IQ",      [["Blacksmith",                -8 ]], +99, false ],
        [ "Meteorology",                      "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Mimic Non-Rabbit",                 "PH",   "HT",      [["IQ",                        -6 ]], +99, false ],
        [ "Mimicry (Animal Sounds)",          "PH",   "HT",      [["IQ",                        -6 ]], +99, false ],
        [ "Mimicry (Bird Calls)",             "PH",   "HT",      [["IQ",                        -6 ]], +99, false ],
        [ "Mimicry (Human Speech)",           "PH",   "HT",      [["IQ",                        -6 ]], +99, false ],
        [ "Mind Block",                       "MA",   "IQ",      [["Will",                      -4 ]], +99, false ],
        [ "Monowire Whip",                    "PH",   "DX",      [["Whip",                      -6 ]], +99, false ],
        [ "Motorcycle",                       "PE",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Mounted Combat",                   "A",    "maneuver",[[ "skill",                    +0 ]], +2 , true  ],
        [ "Muscle Reading",                   "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Musical Composition",              "MH",   "IQ",      [["Musical Instrument",        -2 ]], +99, false ],
        [ "Musical Instrument",               "MH",   "IQ",      [["(similar instrument)",      -3 ]], +99, false ],
        [ "Mythos Lore",                      "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Mythos Magick Rituals",            "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "NBC Warfare",                      "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Native Language",                  "ME",   "IQ",      [["IQ",                        -2 ]], +99, false ],
        [ "Naturalist",                       "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Navigation",                       "MH",   "IQ",      [["Seamanship",                -5 ]], +99, false ],
        [ "Neck Snap",                        "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Needlecraft",                      "PA",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Nei Tan",                          "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Net",                              "PH",   "DX",      [["none",                      +0 ]], +99, false ],
        [ "Netmaking",                        "PE",   "DX",      [["DX",                        -6 ]], +99, false ],
        [ "Neurophon",                        "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "No-Landing Extraction",            "MA",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Nuclear Physics",                  "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Nuclear Powerplant Engineer",      "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Nuclear Weapons Engineer",         "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Occultism",                        "MA",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Occultism: Demonology",            "MA",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Occultism: Vampire",               "MA",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Off-Hand Weapon Training",         "H",    "maneuver",[[ "skill",                    +0 ]], +4 , true  ],
        [ "Open-Dress Diving",                "MA",   "IQ",      [["Scuba",                     -2 ]], +99, false ],
        [ "Orienteering",                     "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Origami",                          "ME",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Packing",                          "MA",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Paleontology",                     "MH",   "IQ",      [["var",                       +0 ]], +99, false ],
        [ "Panhandling",                      "ME",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Parachuting",                      "PE",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Paraphysics",                      "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Parry Missile Weapons",            "PH",   "DX",      [["none",                      +0 ]], +99, false ],
        [ "Pass",                             "A",    "maneuver",[[ "skill",                    +0 ]], +2 , true  ],
        [ "Patolli",                          "ME",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Performance",                      "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Performance/Ritual",               "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Pharmacy",                         "MH",   "IQ",      [["IQ",                        -7 ]], +99, false ],
        [ "Philosophy",                       "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Photography",                      "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Photonics",                        "MH",   "IQ",      [["(other Photonics)",         -4 ]], +99, false ],
        [ "Physician",                        "MH",   "IQ",      [["IQ",                        -7 ]], +99, false ],
        [ "Physics",                          "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Physiology (race)",                "MVH",  "IQ",      [["IQ",                        -7 ]], +99, false ],
        [ "Physiology",                       "MVH",  "IQ",      [["IQ",                        -7 ]], +99, false ],
        [ "Pickpocket",                       "PH",   "DX",      [["DX", -6 ],
                                                                  ["Sleight of Hand", -4]
                                                                 ], +99, false ],
        [ "Picture-Writing",                  "MH",   "IQ",      [["Picture Writing",           -3 ]], +99, false ],
        [ "Piledriver",                       "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Piloting",                         "PA",   "DX",      [["IQ",                        -6 ]], +99, false ],
        [ "Planetology",                      "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Poetry",                           "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Poisons",                          "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Polearm",                          "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Politics",                         "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Pottery",                          "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Power Blow",                       "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Powerboat",                        "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Precognitive Parry",               "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Pressure Points",                  "MH",   "IQ",      [["Yin/Yang Healing",          -4 ]], +99, false ],
        [ "Pressure Secrets",                 "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Probability Physics",              "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Professional Skill",               "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Prospecting",                      "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Psi Skill",                        "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Psionics",                         "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Psychology",                       "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Punning",                          "MA",   "IQ",      [["Bard",                      -3 ]], +99, false ],
        [ "Push",                             "PH",   "DX",      [["none",                      +0 ]], +99, false ],
        [ "Rabbit Punch",                     "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Read Wathan",                      "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Research",                         "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Retain Weapon",                    "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Riding",                           "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Riposte",                          "H",    "maneuver",[[ "skill",                    +0 ]], +4 , true  ],
        [ "Ritual Magic",                     "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Ritual Paths (Voodoo)",            "MVH",  "IQ",      [["Ritual Magic",              -6 ]], +99, false ],
        [ "Rituals and Ceremonies",           "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Roll with Blow",                   "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Roundhouse Punch",                 "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Rune-Lore",                        "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Running",                          "PH",   "HT",      [["none",                      +0 ]], +99, false ],
        [ "SIGINTCollection/Jamming",         "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Sacrifice",                        "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Sailor",                           "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Satire",                           "MVH",  "IQ",      [["Bard",                      -4 ]], +99, false ],
        [ "Savoir-Faire",                     "ME",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Savoir-Faire (Dojo)",              "ME",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Savoir-Faire (Galactic)",          "MA",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Savoir-Faire (Merchant Banquet)",  "ME",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Savoir-Faire (Military)",          "ME",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Scene Design",                     "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Science!",                         "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Scrounging",                       "ME",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Scuba",                            "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Sculpting",                        "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Seamanship",                       "ME",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Seduction",                        "MH",   "IQ",      [["Fast-Talk", -4 ],
                                                                  ["Flirting", -5 ]                 ], +99, false ],
        [ "Sensie Interface",                 "MH",   "IQ",      [["Cyberdeck",                 -3 ]], +99, false ],
        [ "Sensitivity",                      "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Sex Appeal",                       "MA",   "HT",      [["HT",                        -3 ]], +99, false ],
        [ "Sextant",                          "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Shadowing",                        "MA",   "IQ",      [["IQ", -6 ],
                                                                  ["Stealth", -4]
                                                                 ], +99, false ],
        [ "Shapeshifting",                    "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Shield",                           "PE",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Shin Kick",                        "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Shipbuilding",                     "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Shipbuilding (Starship)",          "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Shiphandling",                     "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Short Staff",                      "PH",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Shortsword",                       "PA",   "DX",      [["DX",-5 ],
                                                                  ["Broadsword", -2 ]
                                                                 ], +99, false ],
        [ "Shuriken",                         "PH",   "DX",      [["DX",                        -6 ]], +99, false ],
        [ "Shuto",                            "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Sign Language",                    "MA",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Singing",                          "PE",   "HT",      [["HT",                        -4 ]], +99, false ],
        [ "Skaldic Lore",                     "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Skating",                          "PH",   "DX",      [["DX",                        -6 ]], +99, false ],
        [ "Skiing",                           "PH",   "DX",      [["DX",                        -6 ]], +99, false ],
        [ "Sleight of Hand",                  "PH",   "DX",      [["none",                      +0 ]], +99, false ],
        [ "Sling",                            "PH",   "DX",      [["DX",                        -6 ]], +99, false ],
        [ "Slip",                             "H",    "maneuver",[[ "Boxing",                   +0 ]], +3 , true  ],
        [ "Slipping-the-Hammer",              "PE",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Snake Charming",                   "MA",   "IQ",      [["Animal Handling",           -4 ]], +99, false ],
        [ "Snap-Shot",                        "A",    "maneuver",[[ "skill",                    -4 ]], +0 , true  ],
        [ "Sonar Imaging",                    "MA",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Spear",                            "PA",   "DX",      [["DX", -5],
                                                                  ["Staff", -2 ]
                                                                 ], +99, false ],
        [ "Spear Thrower",                    "PA",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Spear Throwing",                   "PE",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Speed Reading",                    "MA",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Speed-Load",                       "PE",   "DX",      [["none",                      +0 ]], +99, false ],
        [ "Spell Throwing",                   "PE",   "DX",      [["DX",                        -3 ]], +99, false ],
        [ "Spin Kick",                        "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Spinning Punch",                   "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Sport",                            "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Sprining Attack",                  "A",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Staff",                            "PH",   "DX",      [["DX", -5],
                                                                  ["Spear", -2 ]
                                                                 ], +99, false ],
        [ "Stage Combat",                     "PA",   "DX",      [["Performance",               -3 ]], +99, false ],
        [ "Stamp Kick",                       "A",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Stealth",                          "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Sticking",                         "H",    "maneuver",[[ "Judo",                     -2 ]], +99, true  ],
        [ "Stone Knapping",                   "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Stop Hit",                         "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Strategy",                         "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Streetwise",                       "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Style Analysis",                   "MH",   "IQ",      [["Tactics",                   -6 ]], +99, false ],
        [ "Sumo Wrestling",                   "PA",   "DX",      [["none",                      +0 ]], +99, false ],
        [ "Surgery",                          "MVH",  "IQ",      [["Physician",                 -5 ]], +99, false ],
        [ "Surveying",                        "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Survival (Urban)",                 "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Survival",                         "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Sweeping Kick",                    "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Swimming",                         "PE",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Tactics",                          "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Talisman Creation",                "MVH",  "IQ",      [["Prime Sphere",              -3 ]], +99, false ],
        [ "Tanning",                          "PA",   "DX",      [["IQ",                        -4 ]], +99, false ],
        [ "Tattooing",                        "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Tea Ceremony",                     "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Teaching",                         "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Teamster",                         "MA",   "IQ",      [["Animal Handling",           -4 ]], +99, false ],
        [ "Telegraphy",                       "ME",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Temporal Electronics",             "MH",   "IQ",      [["Temporal Operation",        -6 ]], +99, false ],
        [ "Temporal Operation",               "MA",   "IQ",      [["Temporal Electronics",      -2 ]], +99, false ],
        [ "Temporal Physics",                 "MVH",  "IQ",      [["Temporal Electronics",      -6 ]], +99, false ],
        [ "Thanatology",                      "MH",   "IQ",      [["Psychology",                -5 ]], +99, false ],
        [ "Thaumatology",                     "MVH",  "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Theology",                         "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Throwing Art",                     "PH",   "DX",      [["none",                      +0 ]], +99, false ],
        [ "Throwing Stick",                   "PE",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Throwing",                         "PH",   "DX",      [["none",                      -3 ]], +99, false ],
        [ "Throwing, Rock-Dropping",          "PH",   "DX",      [["Throwing",                  -4 ]], +99, false ],
        [ "Thrown Weapon",                    "PE",   "DX",      [["DX",                        -4 ]], +99, true  ],
        [ "Tonfa",                            "PH",   "DX",      [["DX",                        -6 ]], +99, false ],
        [ "Tournament Law",                   "ME",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Tracking",                         "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Traffic Analysis",                 "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Traps",                            "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Two-Handed Axe/Mace",              "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Two-Handed Sword",                 "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Typing",                           "PE",   "DX",      [["DX",                        -4 ]], +99, false ],
        [ "Underwater Demolition",            "MA",   "IQ",      [["Demolition",                -2 ]], +99, false ],
        [ "Vacc Suit",                        "MA",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Vedodit Training",                 "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Ventriloquism",                    "MH",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Veterinary",                       "MH",   "IQ",      [["Animal Handling",           -5 ]], +99, false ],
        [ "Vever Drawing",                    "MH",   "IQ",      [["Ritual magic (Voodoo)",     -4 ]], +99, false ],
        [ "Video Production",                 "MA",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Vole Training",                    "MA",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Walker/Handler Operation",         "ME",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Weaving",                          "ME",   "IQ",      [["IQ",                        -4 ]], +99, false ],
        [ "Weird Magic",                      "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Weird Science",                    "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Whip",                             "PA",   "DX",      [["none",                      +0 ]], +99, false ],
        [ "Whirlwind Attack",                 "H",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Woodworking",                      "PA",   "DX",      [["DX",                        -5 ]], +99, false ],
        [ "Wrestling",                        "PA",   "DX",      [["none",                      +0 ]], +99, false ],
        [ "Writing",                          "MA",   "IQ",      [["IQ",                        -5 ]], +99, false ],
        [ "Xenobiology",                      "MA",   "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Xenology",                         "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Yawara",                           "A",    "maneuver",[[ "skill",                    +0 ]], +99, true  ],
        [ "Yin/Yang Healing",                 "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ],
        [ "Zen Archery",                      "MVH",  "IQ",      [["none",                      +0 ]], +99, false ],
        [ "Zoology",                          "MH",   "IQ",      [["IQ",                        -6 ]], +99, false ]
    ];
    initDamageTable();
}  // initSkills

//----------------------------------------------------------------------------
function initDamageTable()
{
    vDam = [
        // thr            sw             bite           ST
        [ [0, 0],        [0, 0],        [1,-5] ],   //  4
        [ [1,-5],        [1,-5],        [1,-4] ],   //  5
        [ [1,-4],        [1,-4],        [1,-3] ],   //  6
        [ [1,-3],        [1,-3],        [1,-3] ],   //  7
        [ [1,-3],        [1,-2],        [1,-3] ],   //  8
        [ [1,-2],        [1,-1],        [1,-2] ],   //  9
        [ [1,-2],        [1, 0],        [1,-2] ],   // 10
        [ [1,-1],        [1,+1],        [1,-2] ],   // 11
        [ [1,-1],        [1,+2],        [1,-1] ],   // 12
        [ [1, 0],        [2,-1],        [1,-1] ],   // 13
        [ [1, 0],        [2, 0],        [1,-1] ],   // 14
        [ [1,+1],        [2,+1],        [1,-1] ],   // 15
        [ [1,+1],        [2,+2],        [1, 0] ],   // 16
        [ [1,+2],        [3,-1],        [1, 0] ],   // 17
        [ [1,+2],        [3, 0],        [1, 0] ],   // 18
        [ [2,-1],        [3,+1],        [1, 0] ],   // 19
        [ [2,-1],        [3,+2],        [1, 0] ],   // 20
        [ [2, 0],        [4,-1],        [1,+1] ],   // 21
        [ [2, 0],        [4, 0],        [1,+1] ],   // 22
        [ [2,+1],        [4,+1],        [1,+1] ],   // 23
        [ [2,+1],        [4,+2],        [1,+1] ],   // 24
        [ [2,+2],        [5,-1],        [1,+1] ],   // 25
        [ [2,+2],        [5, 0],        [1,+2] ],   // 26
        [ [3,-1],        [5,+1],        [1,+2] ],   // 27
        [ [3,-1],        [5,+1],        [1,+2] ],   // 28
        [ [3, 0],        [5,+2],        [1,+2] ],   // 29
        [ [3, 0],        [5,+2],        [1,+2] ],   // 30
        [ [3,+1],        [6,-1],        [2,-1] ],   // 31
        [ [3,+1],        [6,-1],        [2,-1] ],   // 32
        [ [3,+2],        [6, 0],        [2,-1] ],   // 33
        [ [3,+2],        [6, 0],        [2,-1] ],   // 34
        [ [4,-1],        [6,+1],        [2,-1] ],   // 35
        [ [4,-1],        [6,+1],        [2, 0] ],   // 36
        [ [4, 0],        [6,+2],        [2, 0] ],   // 37
        [ [4, 0],        [6,+2],        [2, 0] ],   // 38
        [ [4,+1],        [7,-1],        [2, 0] ],   // 39
        [ [4,+1],        [7,-1],        [2, 0] ],   // 40
        [ [4,+2],        [7, 0],        [2,+1] ],   // 41
        [ [4,+2],        [7, 0],        [2,+1] ],   // 42
        [ [5,-1],        [7,+1],        [2,+1] ],   // 43
        [ [5,-1],        [7,+1],        [2,+1] ],   // 44
        [ [5, 0],        [7,+2],        [2,+1] ],   // 45
        [ [5, 0],        [7,+2],        [2,+2] ],   // 46
        [ [5,+1],        [8,-1],        [2,+2] ],   // 47
        [ [5,+1],        [8,-1],        [2,+2] ],   // 48
        [ [5,+2],        [8, 0],        [2,+2] ],   // 49
        [ [5,+2],        [8, 0],        [2,+2] ]    // 50
    ];
}  // initDamageTable

//----------------------------------------------------------------------------
function initLanguages()
{
    vLanguages = [
        [ 0.0,  "~",        "no idea",                      "you have no idea what they are saying." ],
        [ 0.5,  "A (4)",    "important words",              "Recognizes some important words."],
        [ 1.0,  "B (5-6)",  "simple sentences",             "Usually understands simple sentences, spoken slowly."],
        [ 2.0,  "C (7-8)",  "adequate, no idioms, thick accent", "Adequate reading and speaking vocabulary. Non-native speakers will have a thick accent, very amusing to natives."],
        [ 4.0,  "D (9-10)", "native, no idioms, accent",    "Command of the language equivalent to that of an average native speaker without idioms. Non-natives will retain a distinct foreign accent."],
        [ 6.0,  "E (11-12)", "educated, no idioms, slight accent", "Command of the language equivalent to that of an educated native without idioms. Non-natives will retain a slight foreign accent."],
        [ 8.0,  "F (13-14)",    "understand idioms, no accent", "Full mastery of the language, including idioms. No foreign accent. Can adopt regional accents if desired."],
        [ 10.0, "G (15+)",      "thinks in language",           "Absolute fluency. If non-native, can think in the language."]
    ];
}

//----------------------------------------------------------------------------
function writeLanguageTable()
{
    document.writeln ( "<table BORDER=1 CELLSPACING=0 CELLPADDING=1>" );

    document.writeln ( "<tr>" );
    document.writeln ( "<th colspan=5>Language Fluency levels" );
    document.writeln ( "<tr>" );
    document.writeln ( "<th class=column rowspan=2>xp" );
    document.writeln ( "<th class=column rowspan=2>fluency class" );
    document.writeln ( "<th class=column colspan=2>description" );
    document.writeln ( "<tr>" );
    document.writeln ( "<th class=column >short" );
    document.writeln ( "<th class=column >long" );

    for ( ndx = 0; ndx < vLanguages.length; ndx++ )
    {
        document.writeln ( "<tr valign=top>" );
        document.writeln ( "<td>" + vLanguages[ndx][0] ); // xp
        document.writeln ( "<td>" + vLanguages[ndx][1] ); // class
        document.writeln ( "<td>" + vLanguages[ndx][2] ); // short
        document.writeln ( "<td>" + vLanguages[ndx][3] ); // long
    }
    document.writeln ( "</table>" );
}

//----------------------------------------------------------------------------
function getLanguageDescription( xp )
{
    var ndx;
    ndx = getLanguageNdx( xp );
    return vLanguages[ndx][1] + " " + vLanguages[ndx][2];
}

//----------------------------------------------------------------------------
function getLanguageNdx( xp )
{
    for ( var ndx = 0; ndx < vLanguages.length && vLanguages[ndx][0] < xp; ndx++ )
    {
    }
    if ( vLanguages.length - 1 < ndx )
    {
        ndx = vLanguages.length - 1;
    }
    return ndx;
}  // getLanguageNdx

//----------------------------------------------------------------------------
function initPowerstone()
{
    vPowerstone = [
         70,
        160,
        270,
        400,
        550,
        720,
        910,
       1120,
       1350,
       1600,
       1870,
       2160,
       2470,
       2800,
       3150,
       3520,
       3910,
       4320,
       4750,
       5200,
       5670,
       6160,
       6670,
       7200,
       7750,
       8320,
       8910,
       9520,
      10150,
      10800,
      11470,
      12160,
      12870,
      13600,
      14350,
      15120,
      15910,
      16720,
      17550,
      18400,
      19270,
      20160,
      21070,
      22000,
      22950,
      23920,
      24910,
      25920,
      26950,
      28000,
      29070,
      30160,
      31270,
      32400,
      33550,
      34720,
      35910,
      37120,
      38350,
      39600,
      40870,
      42160,
      43470,
      44800,
      46150,
      47520,
      48910,
      50320,
      51750,
      53200,
      54670,
      56160,
      57670,
      59200,
      60750,
      62320,
      63910,
      65520,
      67150,
      68800
    ];
}  // initPowerstone

//----------------------------------------------------------------------------
function getPowerstoneCost( power )
{
    var cost;
    cost = 0;
    if ( vPowerstone == null || vPowerstone == undefined )
    {
        initPowerstone();
    }
    if ( 0 < power && power < vPowerstone.length )
    {
        cost = vPowerstone[power-1];
    }
    return cost;
}

//----------------------------------------------------------------------------
function initStatus()
{
    vStatus = [
        [ -4,     "serf, slave",                50     ],
        [ -3,     "street beggar",              50     ],
        [ -2,     "Outsider, underworld",       50     ],
        [ -1,     "Bondsman, servant",          100    ],
        [  0,     "Freeman",                    200    ],
        [  1,     "Squire, captain, merchant",  400    ],
        [  2,     "Knight",                     800    ],
        [  3,     "Lesser Lord",                1500   ],
        [  4,     "Landed Lord",                2500   ],
        [  5,     "Baron, Count",               5000   ],
        [  6,     "Prince, Duke",               10000  ]
    ];

    vWealth = [
        [ -3, "Dead Broke", 0.2 ],
        [ -2, "Poor", 1 ],
        [ -1, "Struggling", 2.5 ],
        [  0, "Average", 5 ],
        [  1, "Comfortable", 10 ],
        [  2, "Wealthy", 25 ],
        [  3, "Very Wealthy", 100 ],
        [  4, "Filthy Rich", 500 ],
        [  5, "Multimillionaire", 500 ]
    ];

}

//----------------------------------------------------------------------------
function getStatusObj( lvl )
{
    if ( vStatus == null || vStatus == undefined )
    {
        initStatus();
    }
    var obj = {level:-4,name:"serf",mcl:50};
    for ( var ndx = 0; ndx < vStatus.length; ndx++ )
    {
        if ( lvl < vStatus[ndx][0] )
        {
            break;
        }
        obj.level = vStatus[ndx][0];
        obj.name = vStatus[ndx][1];
        obj.mcl = vStatus[ndx][2];
    }
    return obj;
}

//----------------------------------------------------------------------------
function getWealthObj( lvl )
{
    var obj = {level:-3,name:"Dead Broke",multiplier:0.2};
    for ( var ndx = 0; ndx < vWealth.length; ndx++ )
    {
        if ( lvl < vWealth[ndx][0] )
        {
            break;
        }
        obj.level = vWealth[ndx][0];
        obj.name = vWealth[ndx][1];
        obj.multiplier = vWealth[ndx][2];
    }
    return obj;
}

//----------------------------------------------------------------------------
function getEffectiveWealth( status, money )
{
    var wealth = getWealthObj( vWealth[0][0] );
    for ( var ndx = 0; ndx < vWealth.length; ndx++ )
    {
        if ( money < (status.mcl * wealth.multiplier) )
        {
            break;
        }
        wealth.level = vWealth[ndx][0];
        wealth.name = vWealth[ndx][1];
        wealth.multiplier = vWealth[ndx][2];
    }
    return wealth;
}

//----------------------------------------------------------------------------
function getWealthString()
{
    var str;
    str = "";
    var xpStatus = getStatusObj( myStartingStatus );
    var status = getStatusObj( myStatus );
    var wealth = getWealthObj( myWealth );
    var money = getBagExpenses(myIncome);
    var eWealth = getEffectiveWealth( status, money );

    str += "<table border=0 cellspacing=0 cellpadding=0>";

    str += "<tr>";
    str += "<th>";                      // actual, effective
    str += "<th class=column style='padding-left:4'>status";
    str += "<th class=column style='padding-left:4'>wealth";
    str += "<th class=column align=right style='padding-left:4'>money";

    str += "<tr>";
    str += "<th class=column>thru xp";
    str += "<td style='padding-left:4'>" + xpStatus.name + "(" + getSignedNumber(xpStatus.level) + ")";
    str += "<td style='padding-left:4'>" + wealth.name + "(" + getSignedNumber(wealth.level) + ")";
    str += "<td align=right style='padding-left:4'>$" + String(xpStatus.mcl * wealth.multiplier);

    str += "<tr>";
    str += "<th class=column colspan=3>actual";
    str += "<td align=right style='padding-left:4'>$" + String(money);

    str += "<tr>";
    str += "<th class=column>effective";
    str += "<td style='padding-left:4'>" + status.name + "(" + getSignedNumber(status.level) + ")";
    str += "<td style='padding-left:4'>" + eWealth.name + "(" + getSignedNumber(eWealth.level) + ")";
    str += "<td align=right style='padding-left:4'>$" + String(status.mcl * eWealth.multiplier);

    return str;
}

//----------------------------------------------------------------------------
function getSignedNumber( num )
{
    var str = "";
    if ( 0 < num )
    {
        str += "+";
    }
    str += String(num);
    return str;
}

//----------------------------------------------------------------------------
function getSignedNumberOrTilda( num )
{
    var str = "";
    if ( 0 < num )
    {
        str += "+";
    }
    str += String(num);
    if ( num == 0  )
    {
        str = "~";
    }
    return str;
}

//----------------------------------------------------------------------------
function formatfloat( num, digits, zerochar )
{
    var str = String( Math.floor( num * Math.pow(10,digits)) / Math.pow(10,digits) );
    var ndx = str.indexOf( "." );
    if ( -1 < ndx )
    {
        var zeros = str.length - ndx - 1;
        for ( var i = zeros; i < digits; i++ )
        {
            str += "0";
        }
    }
    else
    {
        if ( 0 < digits )
        {
            str += ".";
            for ( var i = 0; i < digits; i++ )
            {
                str += "0";
            }
        }
    }
    if ( zerochar != null && str == "0" )
    {
        str = zerochar;
    }
    return str;
}

//----------------------------------------------------------------------------
function findArrayItem( name, array )
{
    var item;
    if ( array != null )
    {
        for ( var i = 0; i < array.length; i++ )
        {
            if ( name == array[i][0] )
            {
                return array[i];
            }
        }
    }
    return item;
}
