- Joined
- Jun 16, 2004
- Messages
- 237
I made two custom campaign AIs for a new version of Defenders of Dwarvenkind (not yet released).
Lich King's Chosen AI
This AI does not build units. It waits until a unit owned by player 1 is in a specified region and then attacks it with all its units. The AI includes a set of functions for determining all units of the AI player and thus you don't need to know them beforehand, nor make changes if you add more preplaced units to the AI player. If you added more units to the AI player through triggers during the game, you would need to move call PrepareAssaultGroup() in function AttackAssignment before call AttackMoveKill(u).
Undead Wave AI
The AI builds building, upgrades, and units. The AI sends them to attack two targets (the Dwarven Gate and the Vault of the Dwarven Kings) in queue after receiving Attack Order 1 through the trigger action "AI - Send AI Command." The attack waves vary; they are defined in SetWave function.
The undead army includes three heros: Doomlord (custom hero), Death Knight, and Lich. Their skill order is defined in function SelectHeroes.
Cheers!
Lich King's Chosen AI
This AI does not build units. It waits until a unit owned by player 1 is in a specified region and then attacks it with all its units. The AI includes a set of functions for determining all units of the AI player and thus you don't need to know them beforehand, nor make changes if you add more preplaced units to the AI player. If you added more units to the AI player through triggers during the game, you would need to move call PrepareAssaultGroup() in function AttackAssignment before call AttackMoveKill(u).
Code:
//===========================================================================
//
// Lich King's Chosen AI
// Defenders of Dwarvenkind
//
// By Tommi Gustafsson
//
//===========================================================================
globals
integer array CountedID
integer array CountedNumber
integer array Command
integer array Data
integer FirstFree = 0
endglobals
//===========================================================================
// CountUnit, ClearCount, and AddCountedToAssault functions
//===========================================================================
function CountUnit takes integer unitid returns nothing
local integer i = 0
loop
if i == FirstFree then
set CountedID[i] = unitid
set CountedNumber[i] = 1
set FirstFree = FirstFree + 1
return
endif
if CountedID[i] == unitid then
set CountedNumber[i] = CountedNumber[i] + 1
return
endif
set i = i + 1
endloop
endfunction
function ClearCount takes nothing returns nothing
set FirstFree = 0
endfunction
function AddCountedToAssault takes nothing returns nothing
local integer i = 0
loop
exitwhen i == FirstFree
call AddAssault(CountedNumber[i],CountedID[i])
set i = i + 1
endloop
endfunction
//===========================================================================
// Basic Options
//===========================================================================
function InitOptions takes nothing returns nothing
call SetCampaignAI( )
call SetDefendPlayer( false )
call SetRandomPaths( false )
call SetTargetHeroes( false )
call SetPeonsRepair( true )
call SetHeroesFlee( false )
call SetHeroesBuyItems( true )
call SetUnitsFlee( false )
call SetGroupsFlee( false )
call SetWatchMegaTargets( false )
call SetIgnoreInjured( false )
call SetHeroesTakeItems( true )
call SetSlowChopping( false )
call SetCaptainChanges( true )
call SetSmartArtillery( true )
endfunction
//===========================================================================
// Prepares an assault group
//===========================================================================
function PrepareAssault takes nothing returns nothing
local group g = CreateGroup()
local unit u = null
local integer id
call ClearCount()
call GroupEnumUnitsOfPlayer(g, ai_player, null)
set u = FirstOfGroup(g)
loop
exitwhen u == null
set id = GetUnitTypeId(u)
//If the unit is not hidden, building, or worker, assign it to the attack group
if (not IsUnitType(u, UNIT_TYPE_STRUCTURE) and not IsUnitType(u, UNIT_TYPE_PEON) and not IsUnitHidden(u) and GetUnitState(u, UNIT_STATE_LIFE) > 0) then
call CountUnit(id)
endif
call GroupRemoveUnit(g, u)
set u = FirstOfGroup(g)
endloop
call DestroyGroup(g)
call AddCountedToAssault()
endfunction
//===========================================================================
// Determines all attacking assignments
//===========================================================================
function AttackAssignment takes nothing returns nothing
local group g = CreateGroup()
local rect r = Rect(-2700.0,-13100.0,5700.0,-7900.0)
local unit u = null
local boolean targetfound = false
call StaggerSleep( 0, 2 )
call PrepareAssault()
loop
call GroupEnumUnitsInRect(g, r, null)
set u = FirstOfGroup(g)
loop
exitwhen u == null
if (GetOwningPlayer(u) == Player(0) and GetUnitState(u, UNIT_STATE_LIFE) > 0) then
set targetfound = true
endif
exitwhen targetfound == true
call GroupRemoveUnit(g, u)
set u = FirstOfGroup(g)
endloop
if targetfound == true then
//call DisplayTimedTextToPlayer(Player(0),0,0,5,"Target Found\n")
set targetfound = false
call AttackMoveKill(u)
elseif not CaptainIsHome() then
//call DisplayTimedTextToPlayer(Player(0),0,0,5,"Returning Home\n")
call AttackMoveXY(-1150, -10000)
endif
call Sleep(2)
endloop
endfunction
//***************************************************************************
//* Main Entry Point
//***************************************************************************
function main takes nothing returns nothing
call InitAI( )
call InitOptions( )
call CreateCaptains( )
call SetCaptainHome(BOTH_CAPTAINS, -1150.0, -10000.0)
call Sleep( 0.1 )
call StartThread( function AttackAssignment )
call PlayGame( )
endfunction
Undead Wave AI
The AI builds building, upgrades, and units. The AI sends them to attack two targets (the Dwarven Gate and the Vault of the Dwarven Kings) in queue after receiving Attack Order 1 through the trigger action "AI - Send AI Command." The attack waves vary; they are defined in SetWave function.
The undead army includes three heros: Doomlord (custom hero), Death Knight, and Lich. Their skill order is defined in function SelectHeroes.
Code:
//===========================================================================
//
// Custom WarCraft III Undead AI Script
// Defenders of Dwarvenkind
// Dwarf Campaign - Chapter 1
//
// By Tommi Gustafsson
//
//===========================================================================
//***************************************************************************
//*
//* Global Variables
//*
//***************************************************************************
globals
unit array TargetQueue
integer array WaveUnit
integer array WaveQuantity
integer WaveUnits = 0
integer CurrentWave = 1
integer Difficulty = 1
integer AttackOrder = 0
integer harvestingghouls = 5
endglobals
//============================================================================
// Utility Functions
// Dig2Str and Int2Str
// By AIAndy
//============================================================================
function Dig2Str takes integer i returns string
if i == 1 then
return "1"
elseif i == 2 then
return "2"
elseif i == 3 then
return "3"
elseif i == 4 then
return "4"
elseif i == 5 then
return "5"
elseif i == 6 then
return "6"
elseif i == 7 then
return "7"
elseif i == 8 then
return "8"
elseif i == 9 then
return "9"
else
return "0"
endif
endfunction
function Int2Str takes integer ic returns string
local string s = ""
local integer i = ic
local integer ialt = 0
local boolean neg = false
if i == 0 then
return "0"
endif
if i < 0 then
set neg = true
set i = (-1)*i
endif
loop
exitwhen i == 0
set ialt = i
set i = i / 10
set s = Dig2Str( ialt - 10*i ) + s
endloop
if neg then
set s = "-"+s
endif
return s
endfunction
//===========================================================================
// Initializes TargetQueue
//===========================================================================
function SetTargetUnits takes nothing returns nothing
local group g = CreateGroup()
local unit u = null
local integer id
call GroupEnumUnitsOfPlayer(g, Player(0), null)
set u = FirstOfGroup(g)
loop
exitwhen u == null
set id = GetUnitTypeId(u)
if(id == 'h000') then
set TargetQueue[0] = u
elseif(id == 'nmgv') then
set TargetQueue[1] = u
endif
call GroupRemoveUnit(g, u)
set u = FirstOfGroup(g)
endloop
call DestroyGroup(g)
set TargetQueue[2] = null
endfunction
//===========================================================================
// SuicideOnQueue
//
// Description: Attacks units on a queue, prioritizing earlier targets on the
// queue over later ones. Will reattack the targets, if they are revived.
//
// Returns true when all units on the queue are destroyed or hidden
// Returns false when the attack group is destroyed
//===========================================================================
function SuicideOnQueue takes nothing returns boolean
local unit target = null
local integer i = 0
loop
//looks for a valid target, beginning from the start of the queue every 2 seconds
set target = null
set i = 0
loop
set target = TargetQueue[i]
//Exit when all targets have been destroyed
if target == null then
return true
endif
//Exit when a target that is alive and not hidden is found
exitwhen (UnitAlive(target) and not IsUnitHidden(target))
set i = i + 1
endloop
//exit if the attack group has been destroyed
if CaptainIsEmpty() then
return false
endif
//call DisplayTimedTextToPlayer(Player(0),0,0,5,"CaptainReadiness: "+Int2Str(CaptainReadiness())+"\n")
if CaptainReadiness() < 10 then
call CaptainGoHome()
return false
endif
//Attack the target
call AttackMoveKill(target)
//Sleep for 2 seconds before performing any other actions
call Sleep(2)
endloop
//Necessary to add because of the return check
return false
endfunction
//===========================================================================
// Basic Options
//===========================================================================
function InitOptions takes nothing returns nothing
call SetMeleeAI( )
call SetDefendPlayer( false )
call SetRandomPaths( false )
call SetTargetHeroes( false )
call SetPeonsRepair( true )
call SetHeroesFlee( false )
call SetHeroesBuyItems( true )
call SetUnitsFlee( false )
call SetGroupsFlee( false )
call SetWatchMegaTargets( true )
call SetIgnoreInjured( false )
call SetHeroesTakeItems( true )
call SetSlowChopping( false )
call SetCaptainChanges( true )
call SetSmartArtillery( true )
endfunction
//===========================================================================
// Updates AttackOrder and Difficulty
//===========================================================================
function UpdateConditions takes nothing returns nothing
if CommandsWaiting() != 0 then
set AttackOrder = GetLastCommand()
set Difficulty = GetLastData()
call PopLastCommand()
endif
endfunction
//===========================================================================
// Stores hero ID and skills
//===========================================================================
function SelectHeroes takes nothing returns nothing
//First Hero = Doomlord
set hero_id = 'U000'
set skills1[ 1] = 'AHfs'
set skills1[ 2] = 'AEmb'
set skills1[ 3] = 'AUav'
set skills1[ 4] = 'AHfs'
set skills1[ 5] = 'AUav'
set skills1[ 6] = 'ANdo'
set skills1[ 7] = 'AHfs'
set skills1[ 8] = 'AUav'
set skills1[ 9] = 'AEmb'
set skills1[10] = 'AEmb'
//Second Hero = Death Knight
set hero_id2 = 'Udea'
set skills2[ 1] = 'AUdc'
set skills2[ 2] = 'AUau'
set skills2[ 3] = 'AUdc'
set skills2[ 4] = 'AUau'
set skills2[ 5] = 'AUdc'
set skills2[ 6] = 'AUan'
set skills2[ 7] = 'AUau'
set skills2[ 8] = 'AUdp'
set skills2[ 9] = 'AUdp'
set skills2[10] = 'AUdp'
//Third Hero = Lich
set hero_id3 = 'Ulic'
set skills3[ 1] = 'AUfn'
set skills3[ 2] = 'AUdr'
set skills3[ 3] = 'AUfn'
set skills3[ 4] = 'AUdr'
set skills3[ 5] = 'AUfn'
set skills3[ 6] = 'AUdd'
set skills3[ 7] = 'AUdr'
set skills3[ 8] = 'AUfa'
set skills3[ 9] = 'AUfa'
set skills3[10] = 'AUfa'
endfunction
//===========================================================================
// Returns the hero skill for the given hero and level
//===========================================================================
function ChooseHeroSkill takes nothing returns integer
local integer curHero = GetHeroId()
local integer level = GetHeroLevelAI()
if (level > max_hero_level) then
set max_hero_level = level
endif
if (curHero == hero_id) then
return skills1[level]
elseif (curHero == hero_id2) then
return skills2[level]
elseif (curHero == hero_id3) then
return skills3[level]
endif
return 0
endfunction
//***************************************************************************
//*
//* Building and Harvesting
//*
//***************************************************************************
//===========================================================================
// Specifies AttackWaves
//===========================================================================
function SetWave takes integer wave returns nothing
if wave == 1 then
set WaveUnits = 2
set WaveUnit[0] = 'ugho'
set WaveQuantity[0] = 18
set WaveUnit[1] = hero_id
set WaveQuantity[1] = 1
elseif wave == 2 then
set WaveUnits = 2
set WaveUnit[0] = 'ucry'
set WaveQuantity[0] = 13
set WaveUnit[1] = hero_id2
set WaveQuantity[1] = 1
elseif wave == 3 then
set WaveUnits = 2
set WaveUnit[0] = 'umtw'
set WaveQuantity[0] = 11
set WaveUnit[1] = hero_id3
set WaveQuantity[1] = 1
elseif wave == 4 then
set WaveUnits = 2
set WaveUnit[0] = 'uabo'
set WaveQuantity[0] = 12
set WaveUnit[1] = hero_id
set WaveQuantity[1] = 1
elseif wave == 5 then
set WaveUnits = 4
set WaveUnit[0] = 'ugho'
set WaveQuantity[0] = 16
set WaveUnit[1] = 'unec'
set WaveQuantity[1] = 8
set WaveUnit[2] = hero_id
set WaveQuantity[2] = 1
set WaveUnit[3] = hero_id3
set WaveQuantity[3] = 1
elseif wave == 6 then
set WaveUnits = 4
set WaveUnit[0] = 'uabo'
set WaveQuantity[0] = 7
set WaveUnit[1] = 'ucry'
set WaveQuantity[1] = 8
set WaveUnit[2] = hero_id
set WaveQuantity[2] = 1
set WaveUnit[3] = hero_id2
set WaveQuantity[3] = 1
elseif wave == 7 then
set WaveUnits = 4
set WaveUnit[0] = 'ugho'
set WaveQuantity[0] = 16
set WaveUnit[1] = 'umtw'
set WaveQuantity[1] = 6
set WaveUnit[2] = hero_id
set WaveQuantity[2] = 1
set WaveUnit[3] = hero_id2
set WaveQuantity[3] = 1
elseif wave == 8 then
set WaveUnits = 4
set WaveUnit[0] = 'uabo'
set WaveQuantity[0] = 12
set WaveUnit[1] = 'unec'
set WaveQuantity[1] = 6
set WaveUnit[2] = hero_id
set WaveQuantity[2] = 1
set WaveUnit[3] = hero_id3
set WaveQuantity[3] = 1
elseif wave == 9 then
set WaveUnits = 6
set WaveUnit[0] = 'ugho'
set WaveQuantity[0] = 12
set WaveUnit[1] = 'unec'
set WaveQuantity[1] = 6
set WaveUnit[2] = 'umtw'
set WaveQuantity[2] = 6
set WaveUnit[3] = hero_id
set WaveQuantity[3] = 1
set WaveUnit[4] = hero_id2
set WaveQuantity[4] = 1
set WaveUnit[5] = hero_id3
set WaveQuantity[5] = 1
elseif wave == 10 then
set WaveUnits = 6
set WaveUnit[0] = 'uabo'
set WaveQuantity[0] = 7
set WaveUnit[1] = 'ucry'
set WaveQuantity[1] = 8
set WaveUnit[2] = 'unec'
set WaveQuantity[2] = 6
set WaveUnit[3] = hero_id
set WaveQuantity[3] = 1
set WaveUnit[4] = hero_id2
set WaveQuantity[4] = 1
set WaveUnit[5] = hero_id3
set WaveQuantity[5] = 1
elseif wave == 11 or wave == 13 or wave == 15 then
set WaveUnits = 6
set WaveUnit[0] = 'ugho'
set WaveQuantity[0] = 12
set WaveUnit[1] = 'unec'
set WaveQuantity[1] = 6
set WaveUnit[2] = 'umtw'
set WaveQuantity[2] = 8
set WaveUnit[3] = hero_id
set WaveQuantity[3] = 1
set WaveUnit[4] = hero_id2
set WaveQuantity[4] = 1
set WaveUnit[5] = hero_id3
set WaveQuantity[5] = 1
else
set WaveUnits = 6
set WaveUnit[0] = 'uabo'
set WaveQuantity[0] = 7
set WaveUnit[1] = 'ucry'
set WaveQuantity[1] = 8
set WaveUnit[2] = 'unec'
set WaveQuantity[2] = 8
set WaveUnit[3] = hero_id
set WaveQuantity[3] = 1
set WaveUnit[4] = hero_id2
set WaveQuantity[4] = 1
set WaveUnit[5] = hero_id3
set WaveQuantity[5] = 1
endif
endfunction
//===========================================================================
// Specifies building priorities
//===========================================================================
//Builds necropolis, first workers and goldmine
function BuildBasics takes nothing returns nothing
//Necropolis, 0/10
call SetBuildAll( BUILD_UNIT, 1, 'unpl', -1 )
//2 Gold Mines
call SetBuildAll( BUILD_UNIT, 2, 'ugol', -1 )
//5 Acolytes, 5/10
call SetBuildAll( BUILD_UNIT, 5, 'uaco', -1 )
//Crypt
call SetBuildAll( BUILD_UNIT, 1, 'usep', -1 )
//Altar
call SetBuildAll( BUILD_UNIT, 1, 'uaod', -1 )
//3 ziggurats, 5/40
call SetBuildAll( BUILD_UNIT, 3, 'uzig', -1 )
//Graveyard
call SetBuildAll( BUILD_UNIT, 1, 'ugrv', -1 )
//5 acolytes, 10/40
call SetBuildAll( BUILD_UNIT, 10, 'uaco', -1 )
// Hero 15/40
call SetBuildAll( BUILD_UNIT, 1, hero_id, -1 )
//5 lumber ghouls, 25/30
call SetBuildAll( BUILD_UNIT, 5, 'ugho', -1 )
endfunction
function BuildBuildings takes nothing returns nothing
local integer i = 0
// build to 9 ziggurats
call SetBuildAll( BUILD_UNIT, 9, 'uzig', -1 )
//Halls of the Dead
call SetBuildAll( BUILD_UNIT, 1, 'unp1', -1 )
//Tomb of Relics
call SetBuildAll( BUILD_UNIT, 1, 'utom', -1 )
//2nd crypt
call SetBuildAll( BUILD_UNIT, 2, 'usep', -1 )
//2 Temples of the Damned
call SetBuildAll( BUILD_UNIT, 2, 'utod', -1 )
//Upgrade to Black Citadel
call SetBuildAll( BUILD_UNIT, 1, 'unp2', -1 )
//Build 3 Slaughterhouses
call SetBuildAll( BUILD_UNIT, 3, 'uslh', -1 )
//Altar 2
call SetBuildAll( BUILD_UNIT, 2, 'uaod', -1 )
endfunction
//Builds heroes 2 and 3
function BuildExtraHeroes takes nothing returns nothing
call SetBuildAll( BUILD_UNIT, 1, hero_id2, -1 )
call SetBuildAll( BUILD_UNIT, 1, hero_id3, -1 )
endfunction
//Builds upgrades
function BuildUpgrades takes nothing returns nothing
local integer i = 0
//1/1 upgrades, if Experienced
if (Difficulty>=2) then
call SetBuildAll( BUILD_UPGRADE, 1, 'Rume', -1 )
call SetBuildAll( BUILD_UPGRADE, 1, 'Ruar', -1 )
call SetBuildAll( BUILD_UPGRADE, 1, 'Rura', -1 )
call SetBuildAll( BUILD_UPGRADE, 1, 'Rucr', -1 )
endif
//Necro upgrades
call SetBuildAll( BUILD_UPGRADE, 1, 'Rune', -1 )
call SetBuildAll( BUILD_UPGRADE, 2, 'Rune', -1 )
call SetBuildAll( BUILD_UPGRADE, 1, 'Rusm', -1 )
call SetBuildAll( BUILD_UPGRADE, 1, 'Rusl', -1 )
//2/2 upgrades, if Professional
if (Difficulty>=3) then
call SetBuildAll( BUILD_UPGRADE, 2, 'Rume', -1 )
call SetBuildAll( BUILD_UPGRADE, 2, 'Ruar', -1 )
call SetBuildAll( BUILD_UPGRADE, 2, 'Rura', -1 )
call SetBuildAll( BUILD_UPGRADE, 2, 'Rucr', -1 )
endif
//Exhume & Disease cloud
call SetBuildAll( BUILD_UPGRADE, 1, 'Ruex', -1 )
call SetBuildAll( BUILD_UPGRADE, 1, 'Rupc', -1 )
//3/3 if Champion (not available)
if (Difficulty>=4) then
call SetBuildAll( BUILD_UPGRADE, 3, 'Rume', -1 )
call SetBuildAll( BUILD_UPGRADE, 3, 'Ruar', -1 )
call SetBuildAll( BUILD_UPGRADE, 3, 'Rura', -1 )
call SetBuildAll( BUILD_UPGRADE, 3, 'Rucr', -1 )
endif
call SetBuildAll( BUILD_UNIT, 8, 'uzg1', -1 )
call SetBuildAll( BUILD_UNIT, 1, 'uzg2', -1 )
endfunction
//Builds the appropriate Attack Wave
function BuildWave takes nothing returns nothing
local boolean unitsbuilt = false
local integer i = 0
local integer qty = 1
loop
if WaveQuantity[i] >= qty then
if WaveUnit[i] == 'ugho' then
call SetBuildAll( BUILD_UNIT, qty + harvestingghouls, WaveUnit[i], -1 )
else
call SetBuildAll( BUILD_UNIT, qty, WaveUnit[i], -1 )
endif
set unitsbuilt=true
endif
set i = i + 1
exitwhen (i == WaveUnits and unitsbuilt == false)
if i == WaveUnits then
set i = 0
set unitsbuilt = false
set qty = qty + 1
endif
endloop
endfunction
//Calls all building functions
function BuildPriorities takes nothing returns nothing
call BuildBasics()
call BuildBuildings()
call BuildExtraHeroes()
call BuildUpgrades()
call BuildWave()
endfunction
//===========================================================================
// Specifies harvesting priorities for workers
//===========================================================================
function HarvestPriorities takes nothing returns nothing
local integer mine = TownWithMine()
local integer allGold = GetUnitCountDone('uaco')
local integer allWood = GetUnitCountDone('ugho')
local integer goldacos1 = 0
local integer goldacos2 = 0
local integer lumberghouls = 0
if allGold < 5 then
set goldacos1 = allGold
set goldacos2 = 0
elseif allGold < 10 then
set goldacos1 = 5
set goldacos2 = allGold - 5
else
set goldacos1 = 5
set goldacos2 = 5
endif
if allWood < harvestingghouls then
set lumberghouls = allWood
else
set lumberghouls = harvestingghouls
endif
call HarvestGold( mine + 0, goldacos1 )
call HarvestGold( mine + 1, goldacos2 )
call HarvestWood( 0, lumberghouls )
endfunction
//===========================================================================
// Determines all building and harvesting assignments for workers
//===========================================================================
function WorkerAssignment takes nothing returns nothing
loop
call UpdateConditions( )
// Harvesting
call ClearHarvestAI( )
call HarvestPriorities( )
// Building
call InitBuildArray( )
call BuildPriorities( )
call Sleep( 2 )
endloop
endfunction
//===========================================================================
// Returns true if the minimum forces for an attack exist
//===========================================================================
function HaveMinimumAttackers takes nothing returns boolean
local integer i = 0
local integer tempqty = 0
if (GetUnitCountDone( hero_id ) < 1 or GetUnitCountDone( hero_id2 ) < 1 or GetUnitCountDone( hero_id3 ) < 1) then
return false
endif
loop
exitwhen i == WaveUnits
if WaveUnit[i] == 'ugho' then
set tempqty = WaveQuantity[i] + harvestingghouls
else
set tempqty = WaveQuantity[i]
endif
if GetUnitCountDone(WaveUnit[i]) < tempqty then
return false
endif
set i = i + 1
endloop
return true
endfunction
//===========================================================================
// Assigns units to attack
//===========================================================================
function PrepareAttackGroup takes nothing returns nothing
local integer i = 0
loop
exitwhen i == WaveUnits
call SetAssaultGroup(WaveQuantity[i], WaveQuantity[i], WaveUnit[i] )
set i = i + 1
endloop
endfunction
//===========================================================================
// Determines all attacking assignments
//===========================================================================
function AttackAssignment takes nothing returns nothing
local boolean AttackSuccess = false
call StaggerSleep( 0, 2 )
loop
loop
call UpdateConditions( )
exitwhen ( AttackOrder > 0 and HaveMinimumAttackers() and not CaptainRetreating() and not CaptainInCombat(true) and not TownThreatened())
call Sleep( 3 )
endloop
//Launch Attack
call InitAssaultGroup( )
call PrepareAttackGroup( )
//Immediately begin to construct the next attack wave
set CurrentWave = CurrentWave + 1
call SetWave(CurrentWave)
//Form the attack group
call FormGroup( 3, true )
//Attack Units on the Queue; the return value is not used here
set AttackSuccess = SuicideOnQueue()
call Sleep(3)
endloop
endfunction
//***************************************************************************
//*
//* Main Entry Point
//*
//***************************************************************************
//===========================================================================
function main takes nothing returns nothing
call InitAI( )
call InitOptions( )
call SelectHeroes( )
call CreateCaptains( )
call SetHeroLevels( function ChooseHeroSkill )
// Define Target Units (Gate & Vault)
call SetTargetUnits()
// Define the first attack wave
call SetWave(CurrentWave)
call Sleep( 0.1 )
call StartThread( function WorkerAssignment )
call StartThread( function AttackAssignment )
call PlayGame( )
endfunction
Cheers!