• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Turning melee ai into campaign ai

Level 4
Joined
Apr 14, 2021
Messages
59
The title is pretty straightforward. I took the melee human ai script and edited in high elven parts to adjust it for a custom map of mine. As far as my intuition goes, I'm in a dead end where I don't see a plausible solution, I'm not a programmer – the most I can do is set up peons, build sequences, attack sequences and then call it all in the main function. The idea of going through a very different programming style seems pretty arduous, at least to me. Really would appreciate it if anyone could check out my "work in progress" script and let me know what the script lacks, thanks.

If you're, by any chance, wondering what happens when I load the ai script, the peasants just go straight for the gold mine and play brain dead.
Also, does it matter if I send the AI command (0, 0) in the trigger editor if I don't put the WaitForSignal command in the script?

JASS:
//==================================================================================================
//  $Id: human.ai,v 1.15 2003/04/23 19:26:00 bfitch Exp $
//==================================================================================================
globals
    boolean basic_opening       = true

    boolean b_hero_done        = false
    boolean b_knights_ok        = false

    integer c_altar_done        = 0
    integer c_castle_done       = 0
    integer c_food_made         = 0
    integer c_food_used         = 0
    integer c_footman_done      = 0
    integer c_gold              = 0
    integer c_gold_owned        = 0
    integer c_hall              = 0
    integer c_hall_done         = 0
    integer c_hawk_done         = 0
    integer c_hero_done         = 0
    integer c_house             = 0
    integer c_house_done        = 0
    integer c_keep_done         = 0
    integer c_knight_done       = 0
    integer c_mill_done         = 0
    integer c_mines             = 0
    integer c_peasant_done      = 0
    integer c_priest_done       = 0
    integer c_archer_done       = 0
    integer c_sanctum_done      = 0
    integer c_smith_done        = 0
    integer c_sorceress_done    = 0
    integer c_skyfury           = 0
    integer c_skyfury_done      = 0
    integer c_earthfury         = 0
    integer c_earthfury_done    = 0
    integer c_zep               = 0
endglobals

//--------------------------------------------------------------------------------------------------
//  set_skills
//--------------------------------------------------------------------------------------------------
function set_skills takes nothing returns nothing

    set skill[ 1] = FLAMESTRIKE
    set skill[ 2] = BANISH
    set skill[ 3] = SIPHON_MANA
    set skill[ 4] = FLAMESTRIKE
    set skill[ 5] = SIPHON_MANA
    set skill[ 6] = SUMMON_PHOENIX
    set skill[ 7] = FLAMESTRIKE
    set skill[ 8] = SIPHON_MANA
    set skill[ 9] = BANISH
    set skill[10] = BANISH

    call SetSkillArray(1, 'Hkal')
    call SetSkillArray(2, 'Hkal')
    call SetSkillArray(3, 'Hkal')

endfunction

//--------------------------------------------------------------------------------------------------
//  setup_force
//--------------------------------------------------------------------------------------------------
function setup_force takes nothing returns nothing
    call AwaitMeleeHeroes()
    call InitMeleeGroup()

    call SetMeleeGroup( hero_id             )
    call SetMeleeGroup( 'hhes'              )
    call SetMeleeGroup( KNIGHT              )
    call SetMeleeGroup( 'nhea'              )
    call SetMeleeGroup( PRIEST              )
    call SetMeleeGroup( SORCERESS           )
    call SetMeleeGroup( 'nws1'              )

    call SetInitialWave(10)
endfunction

//--------------------------------------------------------------------------------------------------
//  force_level
//--------------------------------------------------------------------------------------------------
function force_level takes nothing returns integer
    local integer level = 4 // basic hero
    set level = level + 2 * (c_footman_done + c_priest_done + c_sorceress_done)
    set level = level + 3 * (c_archer_done + c_hawk_done)
    set level = level + 5 * (c_hero_done + c_knight_done)
    set level = level + 6 *  c_hero_done
    return level
endfunction

//--------------------------------------------------------------------------------------------------
//  attack_sequence
//--------------------------------------------------------------------------------------------------
function attack_sequence takes nothing returns nothing
    local boolean needs_exp
    local boolean air_units
    local integer level

    loop
        exitwhen c_hero_done > 0 and c_footman_done >= 2
        call Sleep(2)
    endloop

    if MeleeDifficulty() == MELEE_NEWBIE then
        call Sleep(240)
    endif

    call StaggerSleep(0,2)
    loop
        loop
            exitwhen not CaptainRetreating()
            call Sleep(2)
        endloop

        call setup_force()

        set level = force_level()
        set max_creeps = level * 4 / 5
        set min_creeps = max_creeps - 10
        if min_creeps < 0 then
            set min_creeps = 0
        endif

        set needs_exp        = take_exp and (level >= 9 or c_gold_owned < 2000)
        set air_units        = c_hawk_done > 0
        set allow_air_creeps = (c_archer_done + c_hawk_done) >= 3

        call SingleMeleeAttack(needs_exp,false,air_units)

        if MeleeDifficulty() == MELEE_NEWBIE then
            call Sleep(60)
        endif
    endloop
endfunction

//--------------------------------------------------------------------------------------------------
//  init_vars
//--------------------------------------------------------------------------------------------------
function init_vars takes nothing returns nothing

    set c_altar_done        = GetUnitCountDone(HUMAN_ALTAR)
    set c_castle_done       = TownCountDone(CASTLE)
    set c_food_made         = c_hall * GetFoodMade(TOWN_HALL) + c_house * GetFoodMade(ELF_FARM)
    set c_food_used         = FoodUsed()
    set c_footman_done      = GetUnitCountDone('hhes')
    set c_gold              = GetGold()
    set c_gold_owned        = GetGoldOwned()
    set c_hall              = TownCount(TOWN_HALL)
    set c_hall_done         = TownCountDone(TOWN_HALL)
    set c_hawk_done         = GetUnitCountDone('nws1')
    set c_hero_done         = GetUnitCountDone(hero_id)
    set c_house             = GetUnitCount(ELF_FARM)
    set c_house_done        = GetUnitCountDone(ELF_FARM)
    set c_keep_done         = TownCountDone(KEEP)
    set c_knight_done       = GetUnitCountDone(KNIGHT)
    set c_mill_done         = GetUnitCountDone(LUMBER_MILL)
    set c_mines             = GetMinesOwned()
    set c_peasant_done      = GetUnitCountDone(PEASANT)
    set c_priest_done       = GetUnitCountDone(PRIEST)
    set c_archer_done     = GetUnitCountDone('nhea')
    set c_sanctum_done      = GetUnitCountDone(SANCTUM)
    set c_smith_done        = GetUnitCountDone(BLACKSMITH)
    set c_sorceress_done    = GetUnitCountDone(SORCERESS)
    set c_skyfury           = TownCount(HIGH_SKY)
    set c_skyfury_done      = TownCountDone(HIGH_SKY)
    set c_earthfury         = TownCount(HIGH_EARTH)
    set c_earthfury_done    = TownCountDone(HIGH_EARTH)
    set c_zep               = GetUnitCount(ZEPPELIN)

    set b_hero_done        = GetUnitCountDone(hero_id) >= 1
    set b_knights_ok        = c_castle_done>=1 and c_mill_done>=1 and c_smith_done>=1

    if basic_opening and (b_hero_done or (MeleeDifficulty() == MELEE_NEWBIE and c_castle_done >= 1)) then
        set basic_opening = false
    endif
endfunction

//--------------------------------------------------------------------------------------------------
//  set_vars
//--------------------------------------------------------------------------------------------------
function set_vars takes nothing returns nothing
    loop
        call init_vars()
        call Sleep(1)
    endloop
endfunction

//--------------------------------------------------------------------------------------------------
//  do_upgrades
//--------------------------------------------------------------------------------------------------
function do_upgrades takes nothing returns nothing

    if c_keep_done >= 1 then

        call SetBuildUpgr( 1, UPG_WOOD )

        if c_castle_done >= 1 then
            call SetBuildUpgr( 2, UPG_WOOD )
        endif

        if b_knights_ok then
            call SetBuildUpgr( 1, UPG_BREEDING )
        endif
        if c_sanctum_done >= 1 then
            if c_priest_done >= 1 then
                call SetBuildUpgr( 1, UPG_PRAYING )
            endif
            if c_sorceress_done >= 1 then
                call SetBuildUpgr( 1, UPG_SORCERY )
            endif
        endif
        if c_castle_done >= 1 then

            call SetBuildUpgr( 2, UPG_WOOD )

            if c_sanctum_done >= 1 then
                if c_priest_done >= 1 then
                    call SetBuildUpgr( 2, UPG_PRAYING )
                endif
                if c_sorceress_done >= 1 then
                    call SetBuildUpgr( 2, UPG_SORCERY )
                endif
            endif
        endif
    endif

    call SetBuildUpgr( 1, UPG_DEFEND )

    if c_smith_done >= 1 then
        call SetBuildUpgr( 1, UPG_ARMOR     )
        call SetBuildUpgr( 1, UPG_MELEE     )
        call SetBuildUpgr( 1, UPG_MOON_ARMOR)
        call SetBuildUpgr( 1, UPG_STR_MOON  )

        if c_keep_done >= 1 then
            call SetBuildUpgr( 2, UPG_ARMOR     )
            call SetBuildUpgr( 2, UPG_MELEE     )
            call SetBuildUpgr( 2, UPG_MOON_ARMOR)
            call SetBuildUpgr( 2, UPG_STR_MOON  )

            if c_castle_done >= 1 then
                call SetBuildUpgr( 3, UPG_ARMOR     )
                call SetBuildUpgr( 3, UPG_MELEE     )
                call SetBuildUpgr( 3, UPG_MOON_ARMOR)
                call SetBuildUpgr( 3, UPG_STR_MOON  )
            endif
        endif
    endif

    if c_archer_done >= 1 and c_keep_done >= 1 then
        call SetBuildUpgr( 1, UPG_BOWS )
        if c_castle_done >= 1 then
            call SetBuildUpgr( 1, UPG_MARKSMAN )
        endif
    endif

    if c_mill_done >= 1 then
        call SetBuildUpgr( 1, UPG_MASONRY )
        if c_keep_done >= 1 then
            call SetBuildUpgr( 2, UPG_MASONRY )
        endif
    endif

endfunction

//--------------------------------------------------------------------------------------------------
//  build_sequence
//--------------------------------------------------------------------------------------------------
function build_sequence takes nothing returns nothing
    local integer peasants

    call InitBuildArray()

    if basic_opening then

        call MeleeTownHall( 0, TOWN_HALL )
        call MeleeTownHall( 1, TOWN_HALL )

        call SetBuildUnit(  6, PEASANT      )
        call SetBuildUnit(  1, HUMAN_ALTAR  )
        call SetBuildUnit(  7, PEASANT      )
        call SetBuildUnit(  1, HOUSE        )
        call SetBuildUnit(  1, BARRACKS     )
        call SetBuildUnit(  9, PEASANT      )
        call SetBuildUnit(  2, ELF_FARM     )
        call SetBuildUnit(  1, hero_id      )
        call SetBuildUnit( 11, PEASANT      )
        call SetBuildUnit(  1, 'hhes'       )
        call SetBuildUnit(  3, ELF_FARM     )
        call SetBuildUnit( 12, PEASANT      )
        call SetBuildUnit(  2, 'hhes'       )
        call SetBuildUnit( 13, PEASANT      )
        call SetBuildUnit(  3, 'hhes'       )
        call SetBuildUnit( 14, PEASANT      )
        call SetBuildUnit(  4, ELF_FARM     )
        call SetBuildUnit( 15, PEASANT      )
        call SetBuildUnit(  4, 'hhes'       )
        call SetBuildUnit( 16, PEASANT      )
        call SetBuildUnit(  5, 'hhes'       )
        call SetBuildUnit(  1, BLACKSMITH   )
        call SetBuildUnit(  6, 'hhes'       )
        call SetBuildUnit(  5, ELF_FARM     )
        call SetBuildUnit(  8, 'hhes'       )
        call SetBuildUnit(  6, ELF_FARM     )
        call SetBuildUnit(  2, 'nhea'       )
        call SetBuildUnit(  7, ELF_FARM     )
        call SetBuildUnit(  3, 'nhea'       )
        call SetBuildUnit(  1, ARCANE_VAULT )

        call BasicExpansion( c_mines < 2, TOWN_HALL )

        call SetBuildUnit(  4, 'nhea'       )
        call SetBuildUnit(  1, LUMBER_MILL  )

        if MeleeDifficulty() != MELEE_NEWBIE then
            call GuardSecondary( 1, 2, HIGH_SKY  )
            if c_mill_done >= 1 then
                call GuardSecondary( 1, 2, HIGH_EARTH  )
            endif
        endif

        call SetBuildUnit(  1, KEEP         )
        call SetBuildUpgr(  1, UPG_DEFEND   )
        call SetBuildUpgr(  1, UPG_ARMOR    )
        call SetBuildUnit(  7, ELF_FARM     )
        call SetBuildUpgr(  1, UPG_MELEE    )

        if c_keep_done < 1 then
            return
        endif

        call SetBuildUnit(  1, CASTLE       )

        call GuardSecondary( 0, 2, HIGH_EARTH  )
        if c_earthfury_done >= 3 then
            call GuardSecondary( 0, 1, HIGH_SKY  )
        endif

        call SetBuildUpgr(  1, UPG_STR_MOON )
        call SetBuildUnit(  1, SANCTUM      )
        call SetBuildUpgr(  1, UPG_WOOD     )
        call SetBuildUpgr(  2, UPG_ARMOR    )
        call SetBuildUpgr(  2, UPG_WOOD     )
        return
    endif

    // need a peasant or nothing will get built
    //
    if c_hall_done >= 1 then
        set peasants = 6 - GetWood() / 200
        if peasants < 3 then
            set peasants = 3
        endif
        if c_mines < 2 then
            set peasants = peasants + 5
        else
            set peasants = peasants + 10
        endif
        if peasants > 15 then
            set peasants = 15
        endif
        call SetBuildNext( peasants, PEASANT )
    endif

    // need a hall or we can't resource and make more peasants
    //
    if c_hall < 1 and c_peasant_done >= 1 then
        call MeleeTownHall( 0, TOWN_HALL )
        call MeleeTownHall( 1, TOWN_HALL )
        call MeleeTownHall( 2, TOWN_HALL )
    endif

    if c_gold > 500 and GetWood() < 100 then
        call SetBuildNext( 20, PEASANT )
    endif

    // if we have low gold in our mines then we need to expand
    //
    if c_gold_owned < 2000 then
        call BasicExpansion( c_mines < 2, TOWN_HALL )
        if MeleeDifficulty() != MELEE_NEWBIE then
            call GuardSecondary( 2, 2, HIGH_SKY  )
            if c_earthfury >= 2 then
                call GuardSecondary( 2, 2, HIGH_EARTH  )
            endif
        endif
    endif

    // get enough burrows to handle current food demand
    //
    if c_food_used + 5 >= c_food_made then
        call SetBuildUnit(  c_house_done + 1, ELF_FARM )
    endif

    // always rebuild heroes for defense
    //
    if c_altar_done >= 1 then
        if b_hero_done and MeleeDifficulty() != MELEE_NEWBIE then
                if c_castle_done >= 1 then
                    call SetBuildUnit( 1, hero_id )
                endif
            else
        call SetBuildUnit( 1, HUMAN_ALTAR )
    endif

    // minimum melee defense
    //
    call SetBuildUnit( 1, ELF_HIGH_BARRACKS )
    if b_knights_ok then
        call SetBuildUnit( 2, KNIGHT        )
    else
        call SetBuildUnit( 4, 'hhes'        )
    endif

    // minimum ranged/air defense
    //
        call SetBuildUnit( 3, 'nws1'    )
    else
        call SetBuildUnit( 1, BLACKSMITH )
        if c_smith_done >= 1 or c_gold < 1000 then
            call SetBuildUnit( 4, 'nhea'   )
        endif
    endif

    // siege attackers
    //
    call SetBuildUnit( 1, KEEP      )

    call SetBuildUnit( c_earthfury_done - c_skyfury_done, HIGH_EARTH )
    
    // if we have a lot of gold then advance the tech tree
    //
    if c_gold > 1000 then
        call SetBuildUnit( 1, ARCANE_VAULT  )
        call SetBuildUnit( 1, BLACKSMITH    )
        call SetBuildUnit( 1, LUMBER_MILL   )
        call SetBuildUnit( 1, SANCTUM       )
        call SetBuildUnit( 1, CASTLE        )

        call do_upgrades()

        if c_gold > 2000 then
            call BuildFactory( ELF_HIGH_BARRACKS       )
            call BuildFactory( SANCTUM                 )
        endif

    elseif c_food_used >= UPKEEP_TIER1 then
        call do_upgrades()
    endif

    call BasicExpansion( c_mines < 2, TOWN_HALL )

    if c_food_used >= UPKEEP_TIER2-10 and c_gold < 2000 then
        return
    endif

    // full up with more troops in general
    //
    if b_knights_ok then
        call SetBuildNext( 4, KNIGHT )
    endif

    if c_sanctum_done >= 1 then
        call SetBuildNext( 2, PRIEST        )
        call SetBuildNext( 1, SORCERESS     )

        if c_aviary_done >= 1 then
            call SetBuildNext( 2, 'nws1' )
        endif

        call SetBuildNext( 2, SORCERESS     )
    endif

    if c_gold_owned < 10000 then
        call BasicExpansion( c_mines < 3, TOWN_HALL )
    endif

    if c_food_used >= 60 and c_zep < 3 then
        call GetZeppelin()
    endif
endfunction

//--------------------------------------------------------------------------------------------------
//  peon_assignment
//--------------------------------------------------------------------------------------------------
function peon_assignment takes nothing returns nothing
    local integer T
    loop
        call ClearHarvestAI()

        set T = TownWithMine()

        call HarvestGold(T,4)
        call HarvestWood(0,1)
        call HarvestGold(T,1)
        call HarvestWood(0,1)

        if c_hall_done > 1 and c_mines > 1 then
            call HarvestGold(T+1,5)
        endif

        call HarvestWood(0,15)

        call build_sequence()

        call Sleep(GetRandomInt(1,3))
    endloop
endfunction

//--------------------------------------------------------------------------------------------------
//    main
//--------------------------------------------------------------------------------------------------
function main takes nothing returns nothing
    call CampaignAI(ELF_FARM, null)
    call peon_assignment()
    call attack_sequence()
    call set_skills()
    call StartThread(function set_vars)
endfunction
 
What is the purpose of your script for the campaign mission? If you want just a basic attack and defence script like the AIs in the blizz campaign use then you'd be better taking those AIs and adapting them instead.

I've attached some of those scripts below. Let me know how these look to you and whether they make sense :)

EDIT: If the peasants are just mining gold then it means that there is an error in the script causing the whole thing to fail. This will usually be a syntax error such as missing variables, a typo etc.
 

Attachments

  • u03_light_blue.ai
    2.6 KB · Views: 2
  • u03_green.ai
    2.6 KB · Views: 2
  • u03_blue_reforged.ai
    4.2 KB · Views: 3
  • u03_blue.ai
    4.1 KB · Views: 2
Level 31
Joined
Aug 29, 2012
Messages
1,434
There are indeed errors in the script so it's all invalidated

1749150519685.png


For the 1st one, the variable is FLAME_STRIKE, that was close enough :p

SingleMeleeAttack takes 4 arguments (I think)
1749150651057.png


And you got an unknown variable
 
Level 4
Joined
Apr 14, 2021
Messages
59
What is the purpose of your script for the campaign mission? If you want just a basic attack and defence script like the AIs in the blizz campaign use then you'd be better taking those AIs and adapting them instead.
I'm testing out using a little more complex ai behavior as opposed to the plain campaign ai – I'm adjusting it for Key of the Three Moons campaign mission.
I'm hoping that if I can get it to work, then perhaps I could integrate it for the undead ai as well.

There are indeed errors in the script so it's all invalidated
I got it to work, the peasants no longer just head for the gold mine, but I just hit another dead end. I don't know if it's reforged's clunky mechanics or if I am just stupid, but the ai is still brain dead, I waited for a good 5 minutes to see if time is a factor, but it still does absolutely nothing.
Also, how did you get the debug information? It would probably save me a lot of trouble knowing where I went wrong.

JASS:
//==================================================================================================
//  $Id: human.ai,v 1.15 2003/04/23 19:26:00 bfitch Exp $
//==================================================================================================
globals
    boolean basic_opening       = true

    boolean b_hero_done        = false
    boolean b_knights_ok        = false

    integer c_altar_done        = 0
    integer c_castle_done       = 0
    integer c_food_made         = 0
    integer c_food_used         = 0
    integer c_footman_done      = 0
    integer c_gold              = 0
    integer c_gold_owned        = 0
    integer c_hall              = 0
    integer c_hall_done         = 0
    integer c_hawk_done         = 0
    integer c_hero_done         = 0
    integer c_house             = 0
    integer c_house_done        = 0
    integer c_keep_done         = 0
    integer c_knight_done       = 0
    integer c_mill_done         = 0
    integer c_mines             = 0
    integer c_peasant_done      = 0
    integer c_priest_done       = 0
    integer c_archer_done       = 0
    integer c_sanctum_done      = 0
    integer c_smith_done        = 0
    integer c_sorceress_done    = 0
    integer c_skyfury           = 0
    integer c_skyfury_done      = 0
    integer c_earthfury         = 0
    integer c_earthfury_done    = 0
    integer c_zep               = 0
endglobals

//--------------------------------------------------------------------------------------------------
//  set_skills
//--------------------------------------------------------------------------------------------------
function set_skills takes nothing returns nothing

    set skill[ 1] = FLAME_STRIKE
    set skill[ 2] = BANISH
    set skill[ 3] = SIPHON_MANA
    set skill[ 4] = FLAME_STRIKE
    set skill[ 5] = SIPHON_MANA
    set skill[ 6] = SUMMON_PHOENIX
    set skill[ 7] = FLAME_STRIKE
    set skill[ 8] = SIPHON_MANA
    set skill[ 9] = BANISH
    set skill[10] = BANISH

    call SetSkillArray(1, 'Hkal')
    call SetSkillArray(2, 'Hkal')
    call SetSkillArray(3, 'Hkal')

endfunction

//--------------------------------------------------------------------------------------------------
//  setup_force
//--------------------------------------------------------------------------------------------------
function setup_force takes nothing returns nothing
    call AwaitMeleeHeroes()
    call InitMeleeGroup()

    call SetMeleeGroup( hero_id             )
    call SetMeleeGroup( 'hhes'              )
    call SetMeleeGroup( KNIGHT              )
    call SetMeleeGroup( 'nhea'              )
    call SetMeleeGroup( PRIEST              )
    call SetMeleeGroup( SORCERESS           )
    call SetMeleeGroup( 'nws1'              )

    call SetInitialWave(10)
endfunction

//--------------------------------------------------------------------------------------------------
//  force_level
//--------------------------------------------------------------------------------------------------
function force_level takes nothing returns integer
    local integer level = 4 // basic hero
    set level = level + 2 * (c_footman_done + c_priest_done + c_sorceress_done)
    set level = level + 3 * (c_archer_done + c_hawk_done)
    set level = level + 5 * (c_hero_done + c_knight_done)
    set level = level + 6 *  c_hero_done
    return level
endfunction

//--------------------------------------------------------------------------------------------------
//  attack_sequence
//--------------------------------------------------------------------------------------------------
function attack_sequence takes nothing returns nothing
    local boolean needs_exp
    local boolean has_siege
    local boolean air_units
    local integer level

    loop
        exitwhen c_hero_done > 0 and c_footman_done >= 2
        call Sleep(2)
    endloop

    if MeleeDifficulty() == MELEE_NEWBIE then
        call Sleep(240)
    endif

    call StaggerSleep(0,2)
    loop
        loop
            exitwhen not CaptainRetreating()
            call Sleep(2)
        endloop

        call setup_force()

        set level = force_level()
        set max_creeps = level * 4 / 5
        set min_creeps = max_creeps - 10
        if min_creeps < 0 then
            set min_creeps = 0
        endif

        set needs_exp        = take_exp and (level >= 9 or c_gold_owned < 2000)
        set has_siege        = level >= 40 or c_knight_done > 0
        set air_units        = c_hawk_done > 0
        set allow_air_creeps = (c_archer_done + c_hawk_done) >= 3

        call SingleMeleeAttack(needs_exp,has_siege,false,air_units)

        if MeleeDifficulty() == MELEE_NEWBIE then
            call Sleep(60)
        endif
    endloop
endfunction

//--------------------------------------------------------------------------------------------------
//  init_vars
//--------------------------------------------------------------------------------------------------
function init_vars takes nothing returns nothing

    set c_altar_done        = GetUnitCountDone(HUMAN_ALTAR)
    set c_castle_done       = TownCountDone(CASTLE)
    set c_food_made         = c_hall * GetFoodMade(TOWN_HALL) + c_house * GetFoodMade(ELF_FARM)
    set c_food_used         = FoodUsed()
    set c_footman_done      = GetUnitCountDone('hhes')
    set c_gold              = GetGold()
    set c_gold_owned        = GetGoldOwned()
    set c_hall              = TownCount(TOWN_HALL)
    set c_hall_done         = TownCountDone(TOWN_HALL)
    set c_hawk_done         = GetUnitCountDone('nws1')
    set c_hero_done         = GetUnitCountDone(hero_id)
    set c_house             = GetUnitCount(ELF_FARM)
    set c_house_done        = GetUnitCountDone(ELF_FARM)
    set c_keep_done         = TownCountDone(KEEP)
    set c_knight_done       = GetUnitCountDone(KNIGHT)
    set c_mill_done         = GetUnitCountDone(LUMBER_MILL)
    set c_mines             = GetMinesOwned()
    set c_peasant_done      = GetUnitCountDone(PEASANT)
    set c_priest_done       = GetUnitCountDone(PRIEST)
    set c_archer_done     = GetUnitCountDone('nhea')
    set c_sanctum_done      = GetUnitCountDone(SANCTUM)
    set c_smith_done        = GetUnitCountDone(BLACKSMITH)
    set c_sorceress_done    = GetUnitCountDone(SORCERESS)
    set c_skyfury           = TownCount(HIGH_SKY)
    set c_skyfury_done      = TownCountDone(HIGH_SKY)
    set c_earthfury         = TownCount(HIGH_EARTH)
    set c_earthfury_done    = TownCountDone(HIGH_EARTH)
    set c_zep               = GetUnitCount(ZEPPELIN)

    set b_hero_done        = GetUnitCountDone(hero_id) >= 1
    set b_knights_ok        = c_castle_done>=1 and c_mill_done>=1 and c_smith_done>=1

    if basic_opening and (b_hero_done or (MeleeDifficulty() == MELEE_NEWBIE and c_castle_done >= 1)) then
        set basic_opening = false
    endif
endfunction

//--------------------------------------------------------------------------------------------------
//  set_vars
//--------------------------------------------------------------------------------------------------
function set_vars takes nothing returns nothing
    loop
        call init_vars()
        call Sleep(1)
    endloop
endfunction

//--------------------------------------------------------------------------------------------------
//  do_upgrades
//--------------------------------------------------------------------------------------------------
function do_upgrades takes nothing returns nothing

    if c_keep_done >= 1 then

        call SetBuildUpgr( 1, UPG_WOOD )

        if c_castle_done >= 1 then
            call SetBuildUpgr( 2, UPG_WOOD )
        endif

        if b_knights_ok then
            call SetBuildUpgr( 1, UPG_BREEDING )
        endif
        if c_sanctum_done >= 1 then
            if c_priest_done >= 1 then
                call SetBuildUpgr( 1, UPG_PRAYING )
            endif
            if c_sorceress_done >= 1 then
                call SetBuildUpgr( 1, UPG_SORCERY )
            endif
        endif
        if c_castle_done >= 1 then

            call SetBuildUpgr( 2, UPG_WOOD )

            if c_sanctum_done >= 1 then
                if c_priest_done >= 1 then
                    call SetBuildUpgr( 2, UPG_PRAYING )
                endif
                if c_sorceress_done >= 1 then
                    call SetBuildUpgr( 2, UPG_SORCERY )
                endif
            endif
        endif
    endif

    call SetBuildUpgr( 1, UPG_DEFEND )

    if c_smith_done >= 1 then
        call SetBuildUpgr( 1, UPG_ARMOR     )
        call SetBuildUpgr( 1, UPG_MELEE     )
        call SetBuildUpgr( 1, UPG_MOON_ARMOR)
        call SetBuildUpgr( 1, UPG_STR_MOON  )

        if c_keep_done >= 1 then
            call SetBuildUpgr( 2, UPG_ARMOR     )
            call SetBuildUpgr( 2, UPG_MELEE     )
            call SetBuildUpgr( 2, UPG_MOON_ARMOR)
            call SetBuildUpgr( 2, UPG_STR_MOON  )

            if c_castle_done >= 1 then
                call SetBuildUpgr( 3, UPG_ARMOR     )
                call SetBuildUpgr( 3, UPG_MELEE     )
                call SetBuildUpgr( 3, UPG_MOON_ARMOR)
                call SetBuildUpgr( 3, UPG_STR_MOON  )
            endif
        endif
    endif

    if c_archer_done >= 1 and c_keep_done >= 1 then
        call SetBuildUpgr( 1, UPG_BOWS )
        if c_castle_done >= 1 then
            call SetBuildUpgr( 1, UPG_MARKSMAN )
        endif
    endif

    if c_mill_done >= 1 then
        call SetBuildUpgr( 1, UPG_MASONRY )
        if c_keep_done >= 1 then
            call SetBuildUpgr( 2, UPG_MASONRY )
        endif
    endif

endfunction

//--------------------------------------------------------------------------------------------------
//  build_sequence
//--------------------------------------------------------------------------------------------------
function build_sequence takes nothing returns nothing
    local integer peasants

    call InitBuildArray()

    if basic_opening then

        call MeleeTownHall( 0, TOWN_HALL )
        call MeleeTownHall( 1, TOWN_HALL )

        call SetBuildUnit(  6, PEASANT      )
        call SetBuildUnit(  1, HUMAN_ALTAR  )
        call SetBuildUnit(  7, PEASANT      )
        call SetBuildUnit(  1, HOUSE        )
        call SetBuildUnit(  1, BARRACKS     )
        call SetBuildUnit(  9, PEASANT      )
        call SetBuildUnit(  2, ELF_FARM     )
        call SetBuildUnit(  1, hero_id      )
        call SetBuildUnit( 11, PEASANT      )
        call SetBuildUnit(  1, 'hhes'       )
        call SetBuildUnit(  3, ELF_FARM     )
        call SetBuildUnit( 12, PEASANT      )
        call SetBuildUnit(  2, 'hhes'       )
        call SetBuildUnit( 13, PEASANT      )
        call SetBuildUnit(  3, 'hhes'       )
        call SetBuildUnit( 14, PEASANT      )
        call SetBuildUnit(  4, ELF_FARM     )
        call SetBuildUnit( 15, PEASANT      )
        call SetBuildUnit(  4, 'hhes'       )
        call SetBuildUnit( 16, PEASANT      )
        call SetBuildUnit(  5, 'hhes'       )
        call SetBuildUnit(  1, BLACKSMITH   )
        call SetBuildUnit(  6, 'hhes'       )
        call SetBuildUnit(  5, ELF_FARM     )
        call SetBuildUnit(  8, 'hhes'       )
        call SetBuildUnit(  6, ELF_FARM     )
        call SetBuildUnit(  2, 'nhea'       )
        call SetBuildUnit(  7, ELF_FARM     )
        call SetBuildUnit(  3, 'nhea'       )
        call SetBuildUnit(  1, ARCANE_VAULT )

        call BasicExpansion( c_mines < 2, TOWN_HALL )

        call SetBuildUnit(  4, 'nhea'       )
        call SetBuildUnit(  1, LUMBER_MILL  )

        if MeleeDifficulty() != MELEE_NEWBIE then
            call GuardSecondary( 1, 2, HIGH_SKY  )
            if c_mill_done >= 1 then
                call GuardSecondary( 1, 2, HIGH_EARTH  )
            endif
        endif

        call SetBuildUnit(  1, KEEP         )
        call SetBuildUpgr(  1, UPG_DEFEND   )
        call SetBuildUpgr(  1, UPG_ARMOR    )
        call SetBuildUnit(  7, ELF_FARM     )
        call SetBuildUpgr(  1, UPG_MELEE    )

        if c_keep_done < 1 then
            return
        endif

        call SetBuildUnit(  1, CASTLE       )

        call GuardSecondary( 0, 2, HIGH_EARTH  )
        if c_earthfury_done >= 3 then
            call GuardSecondary( 0, 1, HIGH_SKY  )
        endif

        call SetBuildUpgr(  1, UPG_STR_MOON )
        call SetBuildUnit(  1, SANCTUM      )
        call SetBuildUpgr(  1, UPG_WOOD     )
        call SetBuildUpgr(  2, UPG_ARMOR    )
        call SetBuildUpgr(  2, UPG_WOOD     )
        return
    endif

    // need a peasant or nothing will get built
    //
    if c_hall_done >= 1 then
        set peasants = 6 - GetWood() / 200
        if peasants < 3 then
            set peasants = 3
        endif
        if c_mines < 2 then
            set peasants = peasants + 5
        else
            set peasants = peasants + 10
        endif
        if peasants > 15 then
            set peasants = 15
        endif
        call SetBuildNext( peasants, PEASANT )
    endif

    // need a hall or we can't resource and make more peasants
    //
    if c_hall < 1 and c_peasant_done >= 1 then
        call MeleeTownHall( 0, TOWN_HALL )
        call MeleeTownHall( 1, TOWN_HALL )
        call MeleeTownHall( 2, TOWN_HALL )
    endif

    if c_gold > 500 and GetWood() < 100 then
        call SetBuildNext( 20, PEASANT )
    endif

    // if we have low gold in our mines then we need to expand
    //
    if c_gold_owned < 2000 then
        call BasicExpansion( c_mines < 2, TOWN_HALL )
        if MeleeDifficulty() != MELEE_NEWBIE then
            call GuardSecondary( 2, 2, HIGH_SKY  )
            if c_earthfury >= 2 then
                call GuardSecondary( 2, 2, HIGH_EARTH  )
            endif
        endif
    endif

    // get enough burrows to handle current food demand
    //
    if c_food_used + 5 >= c_food_made then
        call SetBuildUnit(  c_house_done + 1, ELF_FARM )
    endif

    // always rebuild heroes for defense
    //
    if c_altar_done >= 1 then
        if b_hero_done and MeleeDifficulty() != MELEE_NEWBIE then
                if c_castle_done >= 1 then
                    call SetBuildUnit( 1, hero_id )
                endif
            else
        call SetBuildUnit( 1, HUMAN_ALTAR )
    endif

    // minimum melee defense
    //
    call SetBuildUnit( 1, ELF_HIGH_BARRACKS )
    if b_knights_ok then
        call SetBuildUnit( 2, KNIGHT        )
    else
        call SetBuildUnit( 4, 'hhes'        )
    endif

    // minimum ranged/air defense
    //
        call SetBuildUnit( 3, 'nws1'    )
    else
        call SetBuildUnit( 1, BLACKSMITH )
        if c_smith_done >= 1 or c_gold < 1000 then
            call SetBuildUnit( 4, 'nhea'   )
        endif
    endif

    // siege attackers
    //
    call SetBuildUnit( 1, KEEP      )

    call SetBuildUnit( c_earthfury_done - c_skyfury_done, HIGH_EARTH )
    
    // if we have a lot of gold then advance the tech tree
    //
    if c_gold > 1000 then
        call SetBuildUnit( 1, ARCANE_VAULT  )
        call SetBuildUnit( 1, BLACKSMITH    )
        call SetBuildUnit( 1, LUMBER_MILL   )
        call SetBuildUnit( 1, SANCTUM       )
        call SetBuildUnit( 1, CASTLE        )

        call do_upgrades()

        if c_gold > 2000 then
            call BuildFactory( ELF_HIGH_BARRACKS       )
            call BuildFactory( SANCTUM                 )
        endif

    elseif c_food_used >= UPKEEP_TIER1 then
        call do_upgrades()
    endif

    call BasicExpansion( c_mines < 2, TOWN_HALL )

    if c_food_used >= UPKEEP_TIER2-10 and c_gold < 2000 then
        return
    endif

    // full up with more troops in general
    //
    if b_knights_ok then
        call SetBuildNext( 4, KNIGHT )
    endif

    if c_sanctum_done >= 1 then
        call SetBuildNext( 2, PRIEST        )
        call SetBuildNext( 1, SORCERESS     )

        call SetBuildNext( 2, 'nws1' )

        call SetBuildNext( 2, SORCERESS     )
    endif

    if c_gold_owned < 10000 then
        call BasicExpansion( c_mines < 3, TOWN_HALL )
    endif

    if c_food_used >= 60 and c_zep < 3 then
        call GetZeppelin()
    endif
endfunction

//--------------------------------------------------------------------------------------------------
//  peon_assignment
//--------------------------------------------------------------------------------------------------
function peon_assignment takes nothing returns nothing
    local integer T
    loop
        call ClearHarvestAI()

        set T = TownWithMine()

        call HarvestGold(T,4)
        call HarvestWood(0,1)
        call HarvestGold(T,1)
        call HarvestWood(0,1)

        if c_hall_done > 1 and c_mines > 1 then
            call HarvestGold(T+1,5)
        endif

        call HarvestWood(0,15)

        call build_sequence()

        call Sleep(GetRandomInt(1,3))
    endloop
endfunction

//--------------------------------------------------------------------------------------------------
//    main
//--------------------------------------------------------------------------------------------------
function main takes nothing returns nothing
    call CampaignAI(ELF_FARM, null)
    call peon_assignment()
    call attack_sequence()
    call set_skills()
    call StartThread(function set_vars)
endfunction
 
Level 4
Joined
Apr 14, 2021
Messages
59
Haha, all is fine. Even if I ultimately fail in getting this to work, I wouldn't sweat it as this is also beyond me, I'm just tinkering around to see if I can at least "upgrade" it, if anything. Thank you for the syntax thing, too.
 
I'm testing out using a little more complex ai behavior as opposed to the plain campaign ai – I'm adjusting it for Key of the Three Moons campaign mission.
I'm hoping that if I can get it to work, then perhaps I could integrate it for the undead ai as well.
Complex in what way? Imo starting from a melee AI and trying to convert it is not the best way to go. Instead you would be better taking one of the Campaign AIs and adding whatever more complex behaviour you want to it. Melee and Key of the Three Moons are quite different in how they work so I don't think a melee AI is the way to go.
 
Top