' Deep Deadly Dungeons
' (C)2005 by Richard Clark rickclark58@yahoo.com
' Compiled using FB version .15b
'
' This program is free software; you can redistribute it and/or modify it
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
'
'This is the monster related routines.
'

Function GetMonBase As Integer
    Dim wbase As Integer
    If player.hasorbs.hascrown = True Then
        wbase = 100 + levels.lcount(levels.currlevel)
    Else
        wbase = (levels.currlevel * 4 ) + levels.lcount(levels.currlevel)
    End If
    Return wbase    
End Function

function GetMonsterName(id as integer) as string
    select case id
        case darkangel: return "Dark Angel"
        case giantbat: return "Giant Bat"
        Case giantscorpion: Return "Giant Scorpion"
        Case dragon
            If easteregg Then
                Return "Ryan the Dragon"
            Else
                Return "Dragon"
            End If
        case elfwarrior: return "Elf Warrior"
        Case wisp: Return "Wisp"
        case giant: return "Giant"
        case harpy: return "Harpy"
        case incubus: return "Incubus"
        case jadegolem: return "Jade Golem"
        case kraken: return "Kraken"
        case lamia: return "Lamia"
        case manticore: return "Manticore"
        case naga: return "Naga"
        case ogre: return "Ogre"
        Case phantomfungus
            If easteregg Then
                Return "Kyle the Phantom Fungus"
            Else
                Return "Phantom Fungus"
            End If
        Case quorn: Return "Quorn"
        case rockgolem: return "Rock Golem"
        case skeleton: return "Skeleton"
        Case troll
            If easteregg Then
                Return "Jocke the Troll"
            Else
                Return "Troll"
            End If
        case uruk: return "Uruk"
        case vampire: return "Vampire"
        Case wombat
            If easteregg Then
                Return "Rick the Wombat"
            Else
                Return "Wombat"
            End If
        case xerth: return "Xerth"
        case yeek: return "Yeek"
        case zombie: return "Zombie"
        Case flameangel
            If easteregg Then
                Return "Z!re the Flame Angel"
            Else
                Return "Flame Angel"
            End If
        case werebear: return "WereBear"
        case giantcentipede: return "Giant Centipede"
        case demonspawn: return "Demon Spawn"
        case elemental: return "Elemental"
        case flamegolem: return "Flame Golem"
        case golem: return "Golem"
        case hobgoblin: return "Hobgoblin"
        case interloper: return "Interloper"
        case rovingjelly: return "Roving Jelly"
        case kobold: return "Kobold"
        case lich: return "Lich"
        case mage: return "Mage"
        case nazgul: return "Nazgul"
        case orc: return "Orc"
        case pulsingeye: return "Pulsing Eye"
        Case twinhead: Return "Twin-Head"
        case rogue: return "Rogue"
        case shurik: return "Shurik"
        case gianttarantula: return "Giant Tarantula"
        Case giantbeetle: Return "Giant Beetle"
        case varghoul: return "Varghoul"
        case wraith: return "Wraith"
        case xorn: return "Xorn"
        Case yekki: Return "Yekki"
        Case griffon: Return "Griffon"
    end select
end function

Sub ClearMonster(mon As montype)
    Dim As Integer i, j
    
    with mon
        .id = 0
        .mmcoord.x = 0
        .mmcoord.y = 0
        .defense = 0
        .tohit = 0
        .mtohit = 0
        .mdamage = 0
        .attackrange = 0
        .moved  = False
        .isscanned = False
        .stealth = 0
        .psighted = False
        .ldir = 0
        .ismagic = 0
        .attr.strg = 0
        .attr.endu = 0
        .attr.dext = 0
        .attr.agl = 0
        .attr.intl = 0
        .attr.vision = 0
        .attr.maxhp = 0
        .attr.currhp = 0
        .attr.expr = 0
        .attr.totexp = 0
        .attr.modstrg = 0
        .attr.modendu = 0
        .attr.moddext = 0
        .attr.modagl = 0
        .attr.modintl = 0
        .attr.modvision = 0
        .lastploc.x = -1
        .lastploc.y = -1
        ClearInvItem .righthand
        ClearInvItem .lefthand
        ClearInvItem .marmor
        ClearInvItem .minv
        For i = 0 To dunw - 1
            For j = 0 To dunh - 1
                .mpath(i, j) = 0
            Next
        Next
    end with
end sub

sub ClearMonsterArray
    dim as integer i, j
        
    For i = 1 To monarray
        ClearMonster levels.monster(i)
    next i
end sub

Function GetMonsterIndex(x As Integer, y As Integer) As Integer
    Dim i As Integer
    Dim ret As Integer = 0
    
    For i = 1 To monarray
        With levels.monster(i)
            If levels.monster(i).id > 0 Then
                If .mmcoord.x = x And .mmcoord.y = y Then
                    ret = i
                    Exit For
                End If
            End If
        End With        
    Next i
    Return ret
End Function

Function IsMonsterLoc(x As Integer, y As Integer) As Integer
    Dim i As Integer
    Dim ret As Integer = False
    
    For i = 1 To monarray
        If levels.monster(i).id > 0 Then 
            With levels.monster(i)
                If .mmcoord.x = x And .mmcoord.y = y Then
                    ret = True
                    Exit For
                End If
            End With
        End If        
    Next i
    Return ret
End Function

Function OpenTile(x As Integer, y As Integer) As Integer
    Dim ret As Integer
    
	If not ((x > -1) And (y > -1) and (x < dunw) And (y < dunh)) Then
		return False
	end if

    If x = player.pcoord.x And y = player.pcoord.y Then
        ret = False
    ElseIf IsMonsterLoc(x, y) Then
        ret = False
    Else
        If levels.map(x, y) = doorew Then
            ret = False
        ElseIf levels.map(x, y) = doorns Then
            ret = False
        ElseIf levels.map(x, y) = wall Then
            ret = False
        ElseIf levels.map(x, y) = secretwall Then
            ret = False
        Else
            ret = True
        End If
    End If
    Return ret
end function

Sub GenMonArmor(inv As invtype)
    Dim adesc As String = "Uknown mon armor"
        
    With inv.armor
        'set the eval difficulty
        .dr = GetDR
        .eval = False
        .cursed = GetPercentage(levels.currlevel * 4)
        'is item magic
        If GetPercentage(levels.currlevel * 4) Then
            .defmod = GetRandom(1, 10)
            .defmagic = GetRandom(1, 10)
            .defmagicmod = GetRandom(1, 10)
        Else
            .defmod = 0
            .defmagic = 0
            .defmagicmod = 0
        End If
        select case .id
            Case mleatherarm
                .ac = 2
                .strg = 50
                .noise = 1
                adesc = "Leather Armor"
            Case mcuirboliarm
                .ac = 3
                .Strg = 80
                .noise = 2
                adesc = "Cuirboli Armor"
            Case mringarm
                .ac = 4
                .strg = 100
                .noise = 3
                adesc = "Ring Armor"
            Case mbrigantinearm
                .ac = 5
                .strg = 140
                .noise = 4
                adesc = "Brigantine Armor"
            Case mchainarm
                .ac = 6
                .strg = 160
                .noise = 5
                adesc = "Chain Armor"
            Case mscalearm
                .ac = 7
                .strg = 200
                .noise = 6
                adesc = "Scale Armor"
            Case mplatearm
                .ac = 8
                .strg = 250
                .noise = 7
                .ac = 8
                adesc = "Plate Armor"
            Case mhide
                .ac = 3
                adesc = "Hide Armor"
            Case mscales
                .ac = 4
                adesc = "Scales Armor"
            Case menergy
                .ac = 9
                adesc = "Energy Armor"
            Case mfur
                .ac = 1
                adesc = "Fur Armor"
            Case mfeathers
                .ac = 2
                adesc = "Feather Armor"
            Case mrock
                .ac = 10
                adesc = "Rock Armor"
        End Select
        If .cursed Then
            .ac *= -1
        End If
    End With
    inv.desc = adesc
End Sub

Sub GenMonWeapon(inv As invtype, mon As montype)
    Dim wdesc As String = "Unknown mon weapon"
    Dim wbase As Integer
    
    wbase = GetMonBase    
    With inv.weapon
        'set the eval difficulty
        .dr = GetDR
        .eval = False
        .cursed = GetPercentage(levels.currlevel * 4)
        'is this a magic item?
        If GetPercentage(wbase) Then
            .tohitmod = GetRandom(1, wbase) / 10
            .dammod = GetRandom(1, wbase) / 10
        Else
            .tohitmod = 0
            .dammod = 0
        End If
        'cursed items are also magic items
        If .cursed Then
            If .tohitmod = 0 Then
                .tohitmod = GetRandom(1, wbase) / 10
            End If
            .tohitmod *= -1
            If .dammod = 0 Then
                .dammod = GetRandom(1, wbase) / 10
            End If
            .dammod *= -1
        End If
        Select Case .id
            Case mclub      'melee, 1 hand
                .hands = 1
                .damage = 4
                .strg = 50
                .skill = wmelee
                .noise = 1
                wdesc = "Club"
            Case mwarclub   'melee comabt, 1 hand
                .hands = 1
                .damage = 8
                .strg = 65
                .skill = wmelee
                .noise = 1
                wdesc = "War Club"
            Case mcudgel    'melee combat, 1 hand
                .hands = 1
                .damage = 5
                .strg = 55
                .skill = wmelee
                .noise = 1
                wdesc = "Cudgel"
            Case mdagger    'melee combat, 1 hand
                .hands = 1
                .damage = 4
                .strg = 50
                .skill = wmelee
                .noise = 1
                wdesc = "Dagger"
            Case mlongknife 'melee combat, 1 hand
                .hands = 1
                .damage = 6
                .strg = 60
                .skill = wmelee
                .noise = 1
                wdesc = "Long Knife"
            Case msmallsword 'sword, 1 hand
                .hands = 1
                .damage = 4
                .strg = 50
                .skill = wsword
                .noise = 2
                wdesc = "Small Sword"
            Case mshortsword 'sword, 1 hand
                .hands = 1
                .damage = 6
                .strg = 65
                .skill = wsword
                .noise = 2
                wdesc = "Short Sword"
            Case mrapier     'sword, 1 hand
                .hands = 1
                .damage = 9
                .strg = 80
                .skill = wsword
                .noise = 3
                wdesc = "Rapier"
            Case mscimitar   'sword, 1 hand
                .hands = 1
                .damage = 10
                .strg = 90
                .skill = wsword
                .noise = 3
                wdesc = "Scimitar"
            Case mbroadsword 'sword, 1 hands
                .hands = 1
                .damage = 10
                .strg = 100
                .skill = wsword
                .noise = 4
                wdesc = "Broadsword"
            Case mkatana     'sword, 2 hands
                .hands = 2
                .damage = 12
                .strg = 120
                .skill = wsword
                .noise = 4
                wdesc = "Katana"
            Case mlongsword  'sword, 2 hands
                .hands = 2
                .damage = 14
                .strg = 140
                .skill = wsword
                .noise = 4
                wdesc = "Longsword"
            Case mclaymore   'sword, 2 hands
                .hands = 2
                .damage = 16
                .strg = 160
                .skill = wsword
                .noise = 5
                wdesc = "Claymore"
            Case mgreatsword 'sword, 2 hands
                .hands = 2
                .damage = 18
                .strg = 180
                .skill = wsword
                .noise = 5
                wdesc = "Greatsword"
            Case modinsword  'sword 2 hands
                .hands = 2
                .damage = 20
                .strg = 190
                .skill = wsword
                .noise = 6
                wdesc = "Odinsword"
            Case mhellguard  'sword, 2 hands
                .hands = 2
                .damage = 30
                .strg = 200
                .skill = wsword
                .noise = 6
                wdesc = "Hellguard"
            Case mquarterstaff 'spear, 1 hands
                .hands = 1
                .damage = 4
                .strg = 50
                .skill = wspear
                .noise = 1
                wdesc = "Quarter-staff"
            Case mlongstaff    'spear, 2 hands
                .hands = 2
                .damage = 6
                .strg = 60
                .skill = wspear
                .noise = 2
                wdesc = "Long Staff"
            Case mlightspear   'spear, 2 hands
                .hands = 2
                .damage = 7
                .strg = 70
                .skill = wspear
                .noise = 2
                wdesc = "Light Spear"
            Case mpolearm      'spear, 2 hands
                .hands = 2
                .damage = 8
                .strg = 80
                .skill = wspear
                .noise = 2
                wdesc = "Polearm"
            Case mheavyspear   'spear, 2 hands
                .hands = 2
                .damage = 9
                .strg = 90
                .skill = wspear
                .noise = 2
                wdesc = "Heavy Spear"
            Case mtrident      'spear, 2 hands
                .hands = 2
                .damage = 10
                .strg = 100
                .skill = wspear
                .noise = 3
                wdesc = "Trident"
            Case mglaive       'spear, 2 hands
                .hands = 2
                .damage = 12
                .strg = 110
                .skill = wspear
                .noise = 3
                wdesc = "Glaive"
            Case mhandaxe      'axe, 1 hand
                .hands = 1
                .damage = 6
                .strg = 50
                .skill = waxe
                .noise = 1
                wdesc = "Hand Axe"
            Case mbattleaxe    'axe, 1 hand
                .hands = 1
                .damage = 9
                .strg = 80
                .skill = waxe
                .noise = 2
                wdesc = "Battle Axe"
            Case mgothicbattleaxe 'axe, 2 hands
                .hands = 2
                .damage = 10
                .strg = 100
                .skill = waxe
                .noise = 3
                wdesc = "Gothic Battle Axe"
            Case mwaraxe          'axe, 2 hands
                .hands = 2
                .damage = 12
                .strg = 110
                .skill = waxe
                .noise = 3
                wdesc = "War Axe"
            Case mhalberd         'axe, 2 hands
                .hands = 2
                .damage = 14
                .strg = 120
                .skill = waxe
                .noise = 3
                wdesc = "Halberd"
            Case mpoleaxe        'axe, 2 hands
                .hands = 2
                .damage = 16
                .strg = 140
                .skill = waxe
                .noise = 3
                wdesc = "Poleaxe"
            Case msmallmace      'mace, 1 hand
                .hands = 1
                .damage = 5
                .strg = 50
                .skill = wmace
                .noise = 2
                wdesc = "Small Mace"
            Case mbattlemace     'mace, 1 hand
                .hands = 1
                .damage = 7
                .strg = 60
                .skill = wmace
                .noise = 2
                wdesc = "Battle Mace"
            Case mspikedmace     'mace, 1 hand
                .hands = 1
                .damage = 9
                .strg = 70
                .skill = wmace
                .noise = 3
                wdesc = "Spiked Mace"
            Case mdoubleballmace 'mace, 1 hand
                .hands = 1
                .damage = 10
                .strg = 80
                .skill = wmace
                .noise = 4
                wdesc = "Double-ball Mace"
            Case mwarhammer      'mace, 1 hand
                .hands = 1
                .damage = 12
                .strg = 100
                .skill = wmace
                .noise = 2
                wdesc = "War Hammer"
            Case mmaul           'mace, 2 hands
                .hands = 2                
                .damage = 14
                .strg = 140
                .skill = wmace
                .noise = 1
                wdesc = "Maul"
            Case mbullwhip       'flail, 1 hand
                .hands = 1
                .damage = 4
                .strg = 50
                .skill = wflail 
                .noise = 1
                wdesc = "Bull Whip"
            Case mballflail      'flail, 1 hand
                .hands = 1
                .damage = 6
                .strg = 60
                .skill = wflail
                .noise = 3
                wdesc = "Ball Flail"
            Case mspikedflail    'flail, 1 hand
                .hands = 1
                .damage = 10
                .strg = 80
                .skill = wflail 
                .noise = 4
                wdesc = "Spiked Flail"
            Case mmorningstar    'flail, 1 hand
                .hands = 1
                .damage = 12
                .strg = 90
                .skill = wflail 
                .noise = 4
                wdesc = "Morningstar"
            Case mbattleflail    'flail, 2 hand
                .hands = 2
                .damage = 14
                .strg = 120
                .skill = wflail 
                .noise = 4
                wdesc = "Battle Flail"
            Case mbishopsflail   'flail, 2 hand
                .hands = 2
                .damage = 16
                .strg = 140
                .skill = wflail 
                .noise = 5
                wdesc = "Bishop Flail"
            Case msling          'sling, 2 hand
                .hands = 2
                .damage = 4
                .strg = 50
                .skill = wbow
                .noise = 1
                wdesc = "Sling"
            Case mshortbow       'bow, 2 hands
                .hands = 2
                .damage = 8
                .strg = 80
                .skill = wbow
                .noise = 1
                wdesc = "Short Bow"
            Case mlongbow        'bow, 2 hands
                .hands = 2
                .damage = 10
                .strg = 120
                .noise = 2
                .skill = wbow
                wdesc = "Long Bow"
            Case mbonebow        'bow, 2 hands
                .hands = 2
                .damage = 12
                .strg = 70
                .noise = 3
                .skill = wbow
                wdesc = "Bone Bow"
            Case madaminebow     'bow, 2 hands
                .hands = 2
                .damage = 14
                .strg = 140
                .skill = wbow
                .noise = 4
                wdesc = "Adamine Bow"
            Case mlightcrossbow  'crossbow, 2 hands
                .hands = 2
                .damage = 11
                .strg = 100
                .skill = wcrossbow
                .noise = 2
                wdesc = "Light Crossbow"
            Case mheavycrossbow  'crossbow, 2 hands
                .hands = 2
                .damage = 14
                .strg = 160
                .skill = wcrossbow
                .noise = 4
                wdesc = "Heavy Crossbow"
            Case mbarrelcrossbow 'crossbow, 2 hands
                .hands = 2
                .damage = 16
                .strg = 180
                .skill = wcrossbow
                .noise = 6
                wdesc = "Barrel Crossbow"
            Case mbite
                .hands = 2
                .damage = GetRandom(1, 20)
                wdesc = "Bite"
            Case mclaw
                .hands = 2
                .damage = GetRandom(1, 10)
                wdesc = "Claw"
            Case mfist
                .hands = 2
                .damage = GetRandom(1, mon.attr.strg \ 4)
                wdesc = "Fist"
            Case mspore
                .hands = 2
                .damage = GetRandom(1, 5)
                wdesc = "Spore"
            Case mteeth
                .hands = 2
                .damage = GetRandom(1, 25)
                wdesc = "Teeth"
            Case msting
                .hands = 2
                .damage = GetRandom(1, 35)
                wdesc = "Sting"
            Case mflame
                .hands = 2
                .damage = GetRandom(1, 40)
                wdesc = "Flame"
            Case mmagic
                .hands = 2
                .damage = GetRandom(1, 50)
                wdesc = "Magic"
        End Select
    End With
    inv.desc = wdesc
End Sub

Sub GenMonShield(inv As invtype)
    Dim cursed As Integer
    
    cursed = GetPercentage(10) 
    GenShield inv, cursed
    With inv.shield
        If GetPercentage(levels.currlevel * 4) Then
            .defmod = GetRandom(1, 10)
            .defmagic = GetRandom(1, 10)
            .defmagicmod = GetRandom(1, 10)
        Else
            .defmod = 0
            .defmagic = 0
            .defmagicmod = 0
        End If
    End With
End Sub

Sub GenMonInv(idx As Integer)
    With levels.monster(idx)
        ClearInvItem .minv
        If .righthand.weapon.id = msling Then
            .minv.typeid = ammos
            .minv.ammo.id = pebbles
            GenAmmo .minv
            .attackrange = 2
        ElseIf .righthand.weapon.id = mshortbow Then
            .minv.typeid = ammos
            .minv.ammo.id = arrows
            GenAmmo .minv
            .attackrange = 4
        ElseIf .righthand.weapon.id = mlongbow Then
            .minv.typeid = ammos
            .minv.ammo.id = arrows
            GenAmmo .minv
            .attackrange = 6
        ElseIf .righthand.weapon.id = mbonebow Then
            .minv.typeid = ammos
            .minv.ammo.id = arrows
            GenAmmo .minv
            .attackrange = 8
        ElseIf .righthand.weapon.id = madaminebow Then
            .minv.typeid = ammos
            .minv.ammo.id = arrows
            GenAmmo .minv
            .attackrange = 10
        ElseIf .righthand.weapon.id = mlightcrossbow Then
            .minv.typeid = ammos
            .minv.ammo.id = bolts
            GenAmmo .minv
            .attackrange = 4
        ElseIf .righthand.weapon.id = mheavycrossbow Then
            .minv.typeid = ammos
            .minv.ammo.id = bolts
            GenAmmo .minv
            .attackrange = 6
        ElseIf .righthand.weapon.id = mbarrelcrossbow Then
            .minv.typeid = ammos
            .minv.ammo.id = bolts
            GenAmmo .minv
            .attackrange = 8
        Else
            .minv.typeid = supplies
            .minv.supply.id = GetRandom(minsupply, maxsupply)
            GenSupply .minv
            .attackrange = 1
        End If
    End With
End Sub

Sub GenDarkAngel(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = GetRandom(minmonarmor, maxmonarmor)
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = GetRandom(minmonweapon, maxmonweapon)
        GenMonWeapon .righthand, levels.monster(idx) 
        If .righthand.weapon.hands = 1 Then
            .lefthand.typeid = shields
            .lefthand.shield.id = GetRandom(minshield, maxshield)
            GenMonShield .lefthand
        End If
        GenMonInv idx
        .ismagic = True
    End With
End Sub


Sub GenGiantBat(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = mfur
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = mbite
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
    End With
End Sub

Sub GenGiantScoprion(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = mscales
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = msting
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
    End With
End Sub

Sub GenDragon(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = mscales
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = mflame
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
        .ismagic = True
    End With
End Sub

Sub GenElfWarrior(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = GetRandom(minmonarmor, maxmonarmor)
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = GetRandom(minmonweapon, maxmonweapon)
        GenMonWeapon .righthand, levels.monster(idx) 
        If .righthand.weapon.hands = 1 Then
            .lefthand.typeid = shields
            .lefthand.shield.id = GetRandom(minshield, maxshield)
            GenMonShield .lefthand
        End If
        GenMonInv idx
    End With
End Sub

Sub GenWisp(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = menergy
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = mmagic
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
        .attackrange = 6
        .ismagic = True
    End With
End Sub

Sub GenGiant(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id =  GetRandom(minmonarmor, maxmonarmor)
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = GetRandom(minmonweapon, maxmonweapon)
        GenMonWeapon .righthand, levels.monster(idx) 
        If .righthand.weapon.hands = 1 Then
            .lefthand.typeid = shields
            .lefthand.shield.id = GetRandom(minshield, maxshield)
            GenMonShield .lefthand
        End If
        GenMonInv idx
    End With
End Sub

Sub GenHarpy(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = mhide
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = mclaw
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
    End With
End Sub

Sub GenIncubus(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = menergy
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = GetRandom(minmonweapon, maxmonweapon)
        GenMonWeapon .righthand, levels.monster(idx) 
        If .righthand.weapon.hands = 1 Then
            .lefthand.typeid = shields
            .lefthand.shield.id = GetRandom(minshield, maxshield)
            GenMonShield .lefthand
        End If
        GenMonInv idx
    End With
End Sub

Sub GenJadeGolem(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = mrock
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = mfist
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
    End With
End Sub

Sub GenKraken(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = mhide
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = mclaw
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
    End With
End Sub

Sub GenLamia(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = mfur
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = mbite
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
    End With
End Sub

Sub GenManticore(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = mscales
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = msting
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
    End With
End Sub

Sub GenNaga(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id =  GetRandom(minmonarmor, maxmonarmor)
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = GetRandom(minmonweapon, maxmonweapon)
        GenMonWeapon .righthand, levels.monster(idx) 
        If .righthand.weapon.hands = 1 Then
            .lefthand.typeid = shields
            .lefthand.shield.id = GetRandom(minshield, maxshield)
            GenMonShield .lefthand
        End If
        GenMonInv idx
    End With
End Sub

Sub GenOgre(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id =  GetRandom(minmonarmor, maxmonarmor)
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = GetRandom(minmonweapon, maxmonweapon)
        GenMonWeapon .righthand, levels.monster(idx) 
        If .righthand.weapon.hands = 1 Then
            .lefthand.typeid = shields
            .lefthand.shield.id = GetRandom(minshield, maxshield)
            GenMonShield .lefthand
        End If
        GenMonInv idx
    End With
End Sub

Sub GenPhantomFungus(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = mfur
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = mspore
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
    End With
End Sub

Sub GenQuorn(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = mfeathers
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = mmagic
        .ismagic = True
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
        .attackrange = 4
    End With
End Sub

Sub GenRockGolem(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = mrock
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = mfist
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
    End With
End Sub

Sub GenSkeleton(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id =  GetRandom(minmonarmor, maxmonarmor)
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = GetRandom(minmonweapon, maxmonweapon)
        GenMonWeapon .righthand, levels.monster(idx) 
        If .righthand.weapon.hands = 1 Then
            .lefthand.typeid = shields
            .lefthand.shield.id = GetRandom(minshield, maxshield)
            GenMonShield .lefthand
        End If
        GenMonInv idx
    End With
End Sub

Sub GenTroll(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = GetRandom(minmonarmor, maxmonarmor)
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = GetRandom(minmonweapon, maxmonweapon)
        GenMonWeapon .righthand, levels.monster(idx) 
        If .righthand.weapon.hands = 1 Then
            .lefthand.typeid = shields
            .lefthand.shield.id = GetRandom(minshield, maxshield)
            GenMonShield .lefthand
        End If
        GenMonInv idx
    End With
End Sub

Sub GenUrik(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id =  GetRandom(minmonarmor, maxmonarmor)
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = GetRandom(minmonweapon, maxmonweapon)
        GenMonWeapon .righthand, levels.monster(idx) 
        If .righthand.weapon.hands = 1 Then
            .lefthand.typeid = shields
            .lefthand.shield.id = GetRandom(minshield, maxshield)
            GenMonShield .lefthand
        End If
        GenMonInv idx
    End With
End Sub

Sub GenVampire(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = menergy
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = mbite
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
        .ismagic = True
    End With
End Sub

Sub GenWombat(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = mfur
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = mclaw
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
    End With
End Sub

Sub GenXerth(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = GetRandom(minmonarmor, maxmonarmor)
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = GetRandom(minmonweapon, maxmonweapon)
        GenMonWeapon .righthand, levels.monster(idx) 
        If .righthand.weapon.hands = 1 Then
            .lefthand.typeid = shields
            .lefthand.shield.id = GetRandom(minshield, maxshield)
            GenMonShield .lefthand
        End If
        GenMonInv idx
    End With
End Sub

Sub GenYeek(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = mfur
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = mbite
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
    End With
End Sub

Sub GenZombie(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = GetRandom(minmonarmor, maxmonarmor)
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = GetRandom(minmonweapon, maxmonweapon)
        GenMonWeapon .righthand, levels.monster(idx) 
        If .righthand.weapon.hands = 1 Then
            .lefthand.typeid = shields
            .lefthand.shield.id = GetRandom(minshield, maxshield)
            GenMonShield .lefthand
        End If
        GenMonInv idx
        .ismagic = True
    End With
End Sub

Sub GenFlameAngel(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = menergy
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = GetRandom(minmonweapon, maxmonweapon)
        GenMonWeapon .righthand, levels.monster(idx) 
        If .righthand.weapon.hands = 1 Then
            .lefthand.typeid = shields
            .lefthand.shield.id = GetRandom(minshield, maxshield)
            GenMonShield .lefthand
        End If
        GenMonInv idx
        .ismagic = True
    End With
End Sub

Sub GenWereBear(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = mhide
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = mbite
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
        .ismagic = True
    End With
End Sub

Sub GenGiantCentipede(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = mscales
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = msting
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
    End With
End Sub

Sub GenDemonSpawn(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = GetRandom(minmonarmor, maxmonarmor)
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = GetRandom(minmonweapon, maxmonweapon)
        GenMonWeapon .righthand, levels.monster(idx) 
        If .righthand.weapon.hands = 1 Then
            .lefthand.typeid = shields
            .lefthand.shield.id = GetRandom(minshield, maxshield)
            GenMonShield .lefthand
        End If
        GenMonInv idx
        .ismagic = True
    End With
End Sub

Sub GenElemental(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = menergy
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = mmagic
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
        .attackrange = 8
        .ismagic = True
    End With
End Sub

Sub GenFlameGolem(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = mrock
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = mflame
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
        .attackrange = 10
        .ismagic = True
    End With
End Sub

Sub GenGolem(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = GetRandom(minmonarmor, maxmonarmor)
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = GetRandom(minmonweapon, maxmonweapon)
        GenMonWeapon .righthand, levels.monster(idx) 
        If .righthand.weapon.hands = 1 Then
            .lefthand.typeid = shields
            .lefthand.shield.id = GetRandom(minshield, maxshield)
            GenMonShield .lefthand
        End If
        GenMonInv idx
    End With
End Sub

Sub GenHobgoblin(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = GetRandom(minmonarmor, maxmonarmor)
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = GetRandom(minmonweapon, maxmonweapon)
        GenMonWeapon .righthand, levels.monster(idx) 
        If .righthand.weapon.hands = 1 Then
            .lefthand.typeid = shields
            .lefthand.shield.id = GetRandom(minshield, maxshield)
            GenMonShield .lefthand
        End If
        GenMonInv idx
    End With
End Sub

Sub GenInterloper(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = GetRandom(minmonarmor, maxmonarmor)
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = GetRandom(minmonweapon, maxmonweapon)
        GenMonWeapon .righthand, levels.monster(idx) 
        If .righthand.weapon.hands = 1 Then
            .lefthand.typeid = shields
            .lefthand.shield.id = GetRandom(minshield, maxshield)
            GenMonShield .lefthand
        End If
        GenMonInv idx
    End With
End Sub

Sub GenRovingJelly(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = mfur
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = mspore
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
        .attackrange = 4
    End With
End Sub

Sub GenKobold(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = GetRandom(minmonarmor, maxmonarmor)
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = GetRandom(minmonweapon, maxmonweapon)
        GenMonWeapon .righthand, levels.monster(idx) 
        If .righthand.weapon.hands = 1 Then
            .lefthand.typeid = shields
            .lefthand.shield.id = GetRandom(minshield, maxshield)
            GenMonShield .lefthand
        End If
        GenMonInv idx
    End With
End Sub

Sub GenLich(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = GetRandom(minmonarmor, maxmonarmor)
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = GetRandom(minmonweapon, maxmonweapon)
        GenMonWeapon .righthand, levels.monster(idx) 
        If .righthand.weapon.hands = 1 Then
            .lefthand.typeid = shields
            .lefthand.shield.id = GetRandom(minshield, maxshield)
            GenMonShield .lefthand
        End If
        GenMonInv idx
    End With
End Sub

Sub GenMage(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = menergy
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = mmagic
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
        .attackrange = 10
        .ismagic = True
    End With
End Sub

Sub GenNazgul(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = GetRandom(minmonarmor, maxmonarmor)
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = GetRandom(minmonweapon, maxmonweapon)
        GenMonWeapon .righthand, levels.monster(idx) 
        If .righthand.weapon.hands = 1 Then
            .lefthand.typeid = shields
            .lefthand.shield.id = GetRandom(minshield, maxshield)
            GenMonShield .lefthand
        End If
        GenMonInv idx
        .ismagic = True
    End With
End Sub

Sub GenOrc(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = GetRandom(minmonarmor, maxmonarmor)
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = GetRandom(minmonweapon, maxmonweapon)
        GenMonWeapon .righthand, levels.monster(idx) 
        If .righthand.weapon.hands = 1 Then
            .lefthand.typeid = shields
            .lefthand.shield.id = GetRandom(minshield, maxshield)
            GenMonShield .lefthand
        End If
        GenMonInv idx
    End With
End Sub

Sub GenPulsingEye(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = mscales
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = mflame
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
        .attackrange = 6
    End With
End Sub

Sub GenTwinHead(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = GetRandom(minmonarmor, maxmonarmor)
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = GetRandom(minmonweapon, maxmonweapon)
        GenMonWeapon .righthand, levels.monster(idx) 
        If .righthand.weapon.hands = 1 Then
            .lefthand.typeid = shields
            .lefthand.shield.id = GetRandom(minshield, maxshield)
            GenMonShield .lefthand
        End If
        GenMonInv idx
    End With
End Sub

Sub GenRogue(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = GetRandom(minmonarmor, maxmonarmor)
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = GetRandom(minmonweapon, maxmonweapon)
        GenMonWeapon .righthand, levels.monster(idx) 
        If .righthand.weapon.hands = 1 Then
            .lefthand.typeid = shields
            .lefthand.shield.id = GetRandom(minshield, maxshield)
            GenMonShield .lefthand
        End If
        GenMonInv idx
    End With
End Sub

Sub GenShurik(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = GetRandom(minmonarmor, maxmonarmor)
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = GetRandom(minmonweapon, maxmonweapon)
        GenMonWeapon .righthand, levels.monster(idx) 
        If .righthand.weapon.hands = 1 Then
            .lefthand.typeid = shields
            .lefthand.shield.id = GetRandom(minshield, maxshield)
            GenMonShield .lefthand
        End If
        GenMonInv idx
    End With
End Sub

Sub GenGiantTarantula(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = mhide
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = msting
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
    End With
End Sub

Sub GenGiantBeetle(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = mscales
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = mbite
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
    End With
End Sub

Sub GenVarghoul(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = GetRandom(minmonarmor, maxmonarmor)
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = GetRandom(minmonweapon, maxmonweapon)
        GenMonWeapon .righthand, levels.monster(idx) 
        If .righthand.weapon.hands = 1 Then
            .lefthand.typeid = shields
            .lefthand.shield.id = GetRandom(minshield, maxshield)
            GenMonShield .lefthand
        End If
        GenMonInv idx
        .ismagic = True
    End With
End Sub

Sub GenWraith(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = menergy
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = mmagic
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
        .attackrange = 10
        .ismagic = True
    End With
End Sub

Sub GenXorn(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = mfeathers
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = GetRandom(minmonweapon, maxmonweapon)
        GenMonWeapon .righthand, levels.monster(idx) 
        If .righthand.weapon.hands = 1 Then
            .lefthand.typeid = shields
            .lefthand.shield.id = GetRandom(minshield, maxshield)
            GenMonShield .lefthand
        End If
        GenMonInv idx
    End With
End Sub

Sub GenYekki(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = mfur
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = mclaw
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
    End With
End Sub

Sub GenGriffon(idx As Integer)
    With levels.monster(idx) 
        .marmor.typeid = armors
        .marmor.armor.id = mfeathers
        GenMonArmor .marmor
        .righthand.typeid = weapons
        .righthand.weapon.id = mbite
        GenMonWeapon .righthand, levels.monster(idx) 
        GenMonInv idx
    End With
End Sub

Sub AddAMonster(idx As Integer)
  Dim As Integer x, y, wbase
  
    wbase = GetMonBase
    Do
        x = GetRandom(1, dunw - 2)
        y = GetRandom(1, dunh - 2)
    Loop Until OpenTile(x, y)
    
    With levels.monster(idx)
        .flee = GetRandom(1, 100)
        .heal = GetRandom(1, 100)
        .ismagic = False
        .mtohit = 0
        .mdamage = 0
        .ldir = GetRandom(north, seast)
        .mmcoord.x = x
        .mmcoord.y = y
        .id = GetRandom(minmonster, maxmonster)
        .attr.strg = GetRandom(1, player.attr.strg \ 2) + (GetRandom(1, wbase) / 10)
        .attr.endu = GetRandom(1, player.attr.endu \ 2) + (GetRandom(1, wbase) / 10)
        .attr.dext = GetRandom(1, player.attr.dext \ 2) + (GetRandom(1, wbase) / 10)
        .attr.agl = GetRandom(1, player.attr.agl \ 2) + (GetRandom(1, wbase) / 10)
        .attr.intl = GetRandom(1, player.attr.intl \ 2) + (GetRandom(1, wbase) / 10)
        .attr.vision = GetRandom(1, vh)
        .stealth = GetRandom(1, 100)
        .attr.expr = 0
        .attr.totexp = 0
        .attr.modstrg = 0
        .attr.modendu = 0
        .attr.moddext = 0
        .attr.modagl = 0
        .attr.modintl = 0
        .attr.modvision = 0
        Select Case .id
            Case darkangel: GenDarkAngel idx
            Case giantbat: GenGiantBat idx
            Case giantscorpion: GenGiantScoprion idx
            Case dragon: GenDragon idx
            Case elfwarrior: GenElfWarrior idx
            Case wisp: GenWisp idx
            Case giant: GenGiant idx
            Case harpy: GenHarpy idx
            Case incubus: GenIncubus idx
            Case jadegolem: GenJadeGolem idx
            Case kraken: GenKraken idx
            Case lamia: GenLamia idx
            Case manticore: GenManticore idx
            Case naga: GenNaga idx
            Case ogre: GenOgre idx
            Case phantomfungus: GenPhantomFungus idx
            Case quorn: GenQuorn idx
            Case rockgolem: GenRockGolem idx
            Case skeleton: GenSkeleton idx
            Case troll: GenTroll idx
            Case uruk: GenUrik idx
            Case vampire: GenVampire idx
            Case wombat: GenWombat idx
            Case xerth: GenXerth idx
            Case yeek: GenYeek idx
            Case zombie: GenZombie idx
            Case flameangel: GenFlameAngel idx
            Case werebear: GenWereBear idx
            Case giantcentipede: GenGiantCentipede idx
            Case demonspawn: GenDemonSpawn idx
            Case elemental: GenElemental idx
            Case flamegolem: GenFlameGolem idx
            Case golem: GenGolem idx
            Case hobgoblin: GenHobgoblin idx
            Case interloper: GenInterloper idx
            Case rovingjelly: GenRovingJelly idx
            Case kobold: GenKobold idx
            Case lich: GenLich idx
            Case mage: GenMage idx
            Case nazgul: GenNazgul idx
            Case orc: GenOrc idx
            Case pulsingeye: GenPulsingEye idx
            Case twinhead: GenTwinHead idx
            Case rogue: GenRogue idx
            Case shurik: GenShurik idx
            Case gianttarantula: GenGiantTarantula idx
            Case giantbeetle: GenGiantBeetle idx
            Case varghoul: GenVarghoul idx
            Case wraith: GenWraith idx
            Case xorn: GenXorn idx
            Case yekki: GenYekki idx
            Case griffon: GenGriffon idx
        End Select
        If GetPercentage(wbase) Then
            .defense = GetRandom(1, wbase) / 10
            .tohit = GetRandom(1, wbase) / 10
            .attr.modstrg = GetRandom(1, wbase) / 10
            .attr.modendu = GetRandom(1, wbase) / 10
            .attr.moddext = GetRandom(1, wbase) / 10
            .attr.modagl = GetRandom(1, wbase) / 10
            .attr.modintl = GetRandom(1, wbase) / 10
            .attr.modvision = GetRandom(1, wbase) / 10
            If .ismagic Then
                .mtohit = GetRandom(1, wbase) / 10
                .mdamage = GetRandom(1, wbase) / 10
            End If
        End If
        .attr.maxhp = .attr.strg + .attr.endu + .attr.modstrg + .attr.modendu
        .attr.currhp = .attr.strg + .attr.endu + .attr.modstrg + .attr.modendu
    End With

End Sub

sub GenLevelMonsters
  Dim As Integer k
   
    ClearMonsterArray  
    For k = 1 To monarray
        AddAMonster k
    next k
end sub

Function MonsterAttack(mon As montype, tohit As Integer, damage As Integer) As Integer
    Dim As Integer didhit, mdef, roll, wbase
    
    wbase = GetMonBase
    If damage < 1 Then
        damage = GetRandom(1, wbase)
    End If
    'get the monster defense factor
    mdef = GetPlayerDefense(mon.ismagic)
    'see if monster hits
    roll = GetRandom(1, mdef)
    #IfDef tweak
    PrintMessage "M tohit: " + Str$(tohit)
    PrintMessage "M Roll: " + Str$(roll)
    PrintMessage "Player def: " + Str$(mdef)
    #endif
    If tohit >= roll Then
        'report successful hit
        PrintMessage "The " + GetMonsterName(mon.id) + " hits for " + Str$(damage) + " pts damage."
        'reduce player hp
        player.attr.currhp -= damage
        didhit = True
    Else
        PrintMessage "The " + GetMonsterName(mon.id) + " missed."
        didhit = False
    End If
    Return didhit
End Function

Sub DoMonsterAttackPlayer(mon As montype)
    Dim As Integer tohit, damage, didhit
    Dim As Integer dist
    Dim sndid As Integer = 0
    
    dist = CalcDist(mon.mmcoord.x, player.pcoord.x, mon.mmcoord.y, player.pcoord.y)
    If dist > 1 Then
        AnimateProjectile mon.mmcoord.x, mon.mmcoord.y, player.pcoord.x, player.pcoord.y 
        sndid = sndfbll
    End If
    With mon
        'get the to hit modifiers
        tohit = (.attr.dext / 10) + .attr.moddext + .tohit
        If .righthand.typeid = weapons Then
            tohit += Abs(.righthand.weapon.tohitmod)
            damage = .righthand.weapon.damage + Abs(.righthand.weapon.dammod) + (mon.attr.strg / 10) + mon.attr.modstrg
        End If
        If .lefthand.typeid = weapons Then
            tohit += Abs(.lefthand.weapon.tohitmod)
            damage = .lefthand.weapon.damage + Abs(.lefthand.weapon.dammod)  + (mon.attr.strg / 10) + mon.attr.modstrg
        End If
        If .ismagic Then
            tohit += .mtohit
            damage += .mdamage
        End If
        didhit = MonsterAttack(mon, tohit, damage)
        If didhit Then
            If sndid = 0 Then
                sndid = sndpunc
            End If
            CheckForDead
        Else
            If sndid = 0 Then
                sndid = sndmiss 
            End If
        End If
        #IfNDef cnosound
        PlayWavSound sndid
        #endif
    End With
End Sub

Sub ClearPath(idx As Integer)
    Dim As Integer i, j
    
    For i = 0 To dunw - 1
        For j = 0 To dunh - 1 
            levels.monster(idx).mpath(i, j) = 0
        Next j
    Next i

End Sub

Sub BuildPath(x1 As Integer, x2 As Integer, y1 As Integer, y2 As Integer, idx As Integer)
    Dim As Integer i, deltax, deltay, numtiles
    Dim As Integer d, dinc1, dinc2
    Dim As Integer x, xinc1, xinc2
    Dim As Integer y, yinc1, yinc2
    Dim isseen As Integer = True
    
    ClearPath idx
    deltax = Abs(x2 - x1)
    deltay = Abs(y2 - y1)

    If deltax >= deltay Then
        numtiles = deltax + 1
        d = (2 * deltay) - deltax
        dinc1 = deltay Shl 1
        dinc2 = (deltay - deltax) Shl 1
        xinc1 = 1
        xinc2 = 1
        yinc1 = 0
        yinc2 = 1
    Else
        numtiles = deltay + 1
        d = (2 * deltax) - deltay
        dinc1 = deltax Shl 1
        dinc2 = (deltax - deltay) Shl 1
        xinc1 = 0
        xinc2 = 1
        yinc1 = 1
        yinc2 = 1
    End If

    If x1 > x2 Then
        xinc1 = - xinc1
        xinc2 = - xinc2
    End If
    
    If y1 > y2 Then
        yinc1 = - yinc1
        yinc2 = - yinc2
    End If

    x = x1
    y = y1
    
    For i = 2 To numtiles
        levels.monster(idx).mpath(x, y) = i
        If d < 0 Then
            d = d + dinc1
            x = x + xinc1
            y = y + yinc1
        Else
            d = d + dinc2
            x = x + xinc2
            y = y + yinc2
        End If
    Next

End Sub

Function GetNextPath(m As mcoord, idx As Integer) As mcoord
    Dim As mcoord rcoord, tcoord
    Dim As Integer i, cvalue
    
    rcoord.x = -1
    rcoord.y = -1
    For i = north To seast
        tcoord = GetCoord(i, m)
        cvalue = levels.monster(idx).mpath(tcoord.x, tcoord.y)
        If cvalue > 0 And OpenTile(tcoord.x, tcoord.y) Then
            rcoord = tcoord
            levels.monster(idx).mpath(tcoord.x, tcoord.y) = 0
        End If
    Next
    Return rcoord
End Function

Function GetListenCoord(m As mcoord) As mcoord
    Dim As mcoord rcoord, tcoord
    Dim As Integer i, sndval
    
    
    rcoord.x = -1
    rcoord.y = -1
    sndval = 0
    
    'check all adjacent tiles
    For i = north To seast
        tcoord = GetCoord(i, m)
	If (tcoord.x > -1) And (tcoord.y > -1) and (tcoord.x < dunw) And (tcoord.y < dunh) Then
		If levels.soundmap(tcoord.x, tcoord.y) > 0 Then
			If levels.soundmap(tcoord.x, tcoord.y) > sndval And OpenTile(tcoord.x, tcoord.y) Then
				sndval = levels.soundmap(tcoord.x, tcoord.y)
				rcoord = tcoord
			End If
		End If
	end if
    Next
    
    Return rcoord
End Function

Sub DoMonsterHeal(idx As Integer)
    Dim heal As Integer
    
    If GetPercentage(levels.monster(idx).heal) Then
        heal = GetRandom(1, 10)
        levels.monster(idx).attr.currhp += heal
        If levels.monster(idx).attr.currhp > levels.monster(idx).attr.maxhp Then
            levels.monster(idx).attr.currhp = levels.monster(idx).attr.maxhp
        End If 
    End If
End Sub

Function CheckMonsterHP(idx As Integer) As Integer
    Dim As Integer chp
    
    chp = (levels.monster(idx).attr.currhp / levels.monster(idx).attr.maxhp) * 100
    If chp <= 25 Then
        Return True
    Else
        Return False
    End If
End Function

Sub RoamMonsters
    Dim As Integer i, j, dist, dist2
    Dim As mcoord tcoord, ttcoord, tmpcoord
    
    For i = 1 To monarray
        If levels.monster(i).id > 0 Then
            With levels.monster(i)
                'clear the sighted flag
                .psighted = False
                'is player in line of sight
                dist = CalcDist(player.pcoord.x, .mmcoord.x, player.pcoord.y, .mmcoord.y)
                If LineOfSight(player.pcoord.x, .mmcoord.x, player.pcoord.y, .mmcoord.y) And (dist <= .attr.vision) Then
                    'set sighted flag
                    .psighted = True
                    'save the last player position
                    .lastploc.x = player.pcoord.x
                    .lastploc.y = player.pcoord.y
                    BuildPath .lastploc.x, .mmcoord.x, .lastploc.y, .mmcoord.y, i
                End If
                'player in line of sight, move toward player
                If .psighted Then
                    'if hp less than 25 percent, runaway
                    If CheckMonsterHP(i) And GetPercentage(.flee) Then
                        dist = CalcDist(player.pcoord.x, .mmcoord.x, player.pcoord.y, .mmcoord.y)
                        For j = 1 To 8
                            .ldir += 1
                            If .ldir > seast Then .ldir = north
                            ttcoord = GetCoord(.ldir, .mmcoord)
                            If OpenTile(ttcoord.x, ttcoord.y) Then
                                dist2 = CalcDist(player.pcoord.x, ttcoord.x, player.pcoord.y, ttcoord.y)
                                If dist2 >= dist Then
                                    tmpcoord = ttcoord
                                    dist = dist2
                                End If
                            End If
                        Next
                        If OpenTile(tmpcoord.x, tmpcoord.y) Then
                            'move monster to new space
                            .mmcoord = tmpcoord
                            .isscanned = False
                            DoMonsterHeal i
                        End If
                    Else
                        'is the player in range
                        dist = CalcDist(player.pcoord.x, .mmcoord.x, player.pcoord.y, .mmcoord.y)
                        If dist < .attackrange Then
                            If GetPercentage(.attr.intl) Then
                                For j = 1 To 8
                                    .ldir += 1
                                    If .ldir > seast Then .ldir = north
                                    ttcoord = GetCoord(.ldir, .mmcoord)
                                    If OpenTile(ttcoord.x, ttcoord.y) Then
                                        dist2 = CalcDist(player.pcoord.x, ttcoord.x, player.pcoord.y, ttcoord.y)
                                        If dist2 >= dist Then
                                            tmpcoord = ttcoord
                                            dist = dist2
                                        End If
                                    End If
                                Next
                                If OpenTile(tmpcoord.x, tmpcoord.y) Then
                                    'move monster to new space
                                    .mmcoord = tmpcoord
                                    .isscanned = False
                                End If
                            End If
                            'attack player
                            DoMonsterAttackPlayer levels.monster(i)
                            DrawMap
                        ElseIf dist = .attackrange Then
                            'attack player
                            DoMonsterAttackPlayer levels.monster(i)
                            DrawMap
                        Else
                            ttcoord = GetNextPath(.mmcoord, i)
                            If ttcoord.x > -1 And ttcoord.y > -1 Then
                                'move monster to new space
                                .mmcoord = ttcoord
                                .isscanned = False
                                DoMonsterHeal i
                            Else
                                'reset the player loc
                                .lastploc.x = -1
                                .lastploc.y = -1
                            End If
                        End If
                    End If
                Else
                    'lost sight of player can we hear him
                    ttcoord = GetListenCoord(.mmcoord)
                    If ttcoord.x > -1 And ttcoord.y > -1 Then
                        .mmcoord = ttcoord
                        .isscanned = False
                        DoMonsterHeal i
                    Else
                       'cant hear so go to last location
                       If .lastploc.x > -1 And .lastploc.y > -1 Then
                           ttcoord = GetNextPath(.mmcoord, i)
                           If ttcoord.x > -1 And ttcoord.y > -1 Then
                               .mmcoord = ttcoord
                               .isscanned = False
                               DoMonsterHeal i
                           Else
                                'reset the player loc
                                .lastploc.x = -1
                                .lastploc.y = -1
                           End If
                       Else
                            'no idea on location
                            ttcoord = GetCoord(.ldir, .mmcoord)
                            'if open tile move there
                            If OpenTile(ttcoord.x, ttcoord.y) Then
                                .mmcoord = ttcoord
                                .isscanned = False
                                DoMonsterHeal i
                            Else
                                For j = 1 To 8
                                    .ldir += 1
                                    If .ldir > seast Then .ldir = north
                                    ttcoord = GetCoord(.ldir, .mmcoord)
                                    If OpenTile(ttcoord.x, ttcoord.y) Then
                                        .mmcoord = ttcoord
                                        .isscanned = False
                                        DoMonsterHeal i
                                        Exit For
                                    End If
                                Next
                            End If 
                       End If        
                    End If
                End If        
            End With
        End If            
    Next
    DrawMap
End Sub

Function GetMonsterDefense(idx As Integer, mattack As Integer = False) As Integer
    Dim def As Integer
    
    With levels.monster(idx)
        def = .defense
        def += (.attr.agl / 10) + .attr.modagl
        def += .marmor.armor.ac + .marmor.armor.defmod
        If mattack Then
            def += .marmor.armor.defmagic + .marmor.armor.defmagicmod
        End If
        If .righthand.typeid = shields Then
            def += Abs(.righthand.shield.ac) + .righthand.shield.defmod
            If mattack Then
                def += .righthand.shield.defmagic + .righthand.shield.defmagicmod
            End If
        End If
        If .lefthand.typeid = shields Then
            def += Abs(.lefthand.shield.ac) + .lefthand.shield.defmod
            If mattack Then
                def += .lefthand.shield.defmagic + .lefthand.shield.defmagicmod
            End If
        End If
    End With
    Return def
End Function

Function ConvertWeaponId(id As Integer) As Integer
    Select Case id
        Case mclub: Return club      
        Case mwarclub: Return warclub
        Case mcudgel: Return cudgel
        Case mdagger: Return dagger
        Case mlongknife: Return longknife
        Case msmallsword: Return smallsword
        Case mshortsword: Return shortsword
        Case mrapier: Return rapier
        Case mbroadsword: Return broadsword
        Case mscimitar: Return scimitar
        Case mkatana: Return katana
        Case mlongsword: Return longsword
        Case mclaymore: Return claymore
        Case mgreatsword: Return greatsword
        Case modinsword: Return odinsword
        Case mhellguard: Return hellguard
        Case mquarterstaff: Return quarterstaff
        Case mlongstaff: Return longstaff
        Case mpolearm: Return polearm
        Case mlightspear: Return lightspear
        Case mheavyspear: Return heavyspear
        Case mtrident: Return trident
        Case mglaive: Return glaive
        Case mhandaxe: Return handaxe
        Case mbattleaxe: Return battleaxe
        Case mgothicbattleaxe: Return gothicbattleaxe
        Case mwaraxe: Return waraxe
        Case mhalberd: Return halberd
        Case mpoleaxe: Return poleaxe
        Case msmallmace: Return smallmace
        Case mbattlemace: Return battlemace
        Case mspikedmace: Return spikedmace
        Case mdoubleballmace: Return doubleballmace
        Case mwarhammer: Return warhammer
        Case mmaul: Return maul
        Case mballflail: Return ballflail
        Case mspikedflail: Return spikedflail
        Case mmorningstar: Return morningstar
        Case mbullwhip: Return bullwhip
        Case mbattleflail: Return battleflail
        Case mbishopsflail: Return bishopsflail
        Case msling: Return sling
        Case mshortbow: Return shortbow
        Case mlongbow: Return longbow
        Case mbonebow: Return bonebow
        Case madaminebow: Return adaminebow
        Case mlightcrossbow: Return lightcrossbow
        Case mheavycrossbow: Return heavycrossbow
        Case mbarrelcrossbow: Return barrelcrossbow
        Case Else: Return 0
    End Select         
End Function

Function ConvertArmorId(id As Integer) As Integer
    Select Case id
        Case mleatherarm: Return leatherarm
        Case mcuirboliarm: Return cuirboliarm
        Case mringarm: Return ringarm
        Case mbrigantinearm: Return brigantinearm
        Case mchainarm: Return chainarm
        Case mscalearm: Return scalearm
        Case mplatearm: Return platearm
        Case Else: Return 0
    End Select
End Function

Sub MonsterDropItem(idx As Integer)
    Dim As Integer id, iitem
    
    With levels.monster(idx)
        If .righthand.typeid = weapons Then
            id = ConvertWeaponId(.righthand.weapon.id)
            If id > 0 Then
                .righthand.weapon.id = id
                DropItem .righthand, .mmcoord.x, .mmcoord.y, False
            End If
        End If
        If .lefthand.typeid = shields Then
           DropItem .lefthand, .mmcoord.x, .mmcoord.y, False
        End If
        If .marmor.typeid = armors Then
            id = ConvertArmorId(.marmor.armor.id)
            If id > 0 Then
                .marmor.armor.id = id
                DropItem .marmor, .mmcoord.x, .mmcoord.y, False
            End If
        End If
        DropItem .minv, .mmcoord.x, .mmcoord.y, False
        ClearInvItem .righthand
        ClearInvItem .lefthand
        ClearInvItem .marmor
        ClearInvItem .minv
    End With
End Sub

Sub KillAllMonsters
    Dim As Integer i
    
    For i = 1 To monarray
        levels.monster(i).id = 0
    Next    
End Sub

Function GetFreeMonsterIndex As Integer
    Dim i As Integer
    Dim ret As Integer = -1
    
    For i = 1 To monarray
        If levels.monster(i).id = 0 Then
            ret = i
            Exit For            
        End If
    Next
    Return ret
End Function

Sub ClearMonsterScan
    Dim i As Integer
    
    For i = 1 To monarray
        levels.monster(i).isscanned = False
    Next
End Sub
