• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

AI Editor Not Recognozing Conditions

Status
Not open for further replies.
The Justify More Workers condition below is being ignored. It is also ignored if I use (Number of Mines Owned).

upload_2017-11-17_1-27-31.png
 
Level 12
Joined
Jun 15, 2016
Messages
472
Cuz AI editor suxx.

Seriously now, you'd have a much easier time debugging the script itself. You can export it from the AI editor, this will give you an .ai file you can open in any text editor. I think each condition is converted to a function with the same name in the script, so it should be easy to locate it and every time it is called.
Then, all you need to do is add a debugging function like this wherever you want:

call DisplayTextToPlayer (p,0,0,"t") // Where p is your player slot (if you're player one then type PlayerEx(1), if you're player 2 type PlayerEx (2) and so on) // And t is whatever message you want between "double quotes"

This way you can see if it is called and what it does.
 
Level 12
Joined
Jun 15, 2016
Messages
472
Try importing this script. I didn't test it (no object data and all), so it might do nothing if I made a mistake. In that case send it back (and the map will also really help).


JASS:
//===========================================================================
//
// Shellgan
//
//   Warcraft III AI script
//   Generated by the Warcraft III World Editor
//   Date: Fri Nov 17 01:16:57 2017
//
//===========================================================================

//***************************************************************************
//*
//*  Global Variables
//*
//***************************************************************************

globals
    integer                 attackWave                 = 1
    integer                 nextDelay                  = 0
    integer                 awGold                     = 0
    integer                 awWood                     = 0

    // Conditions
    boolean                 gCond_Food_A               = false
    boolean                 gCond_Food_B               = false
    boolean                 gCond_Food_C               = false
    boolean                 gCond_Food_D               = false
    boolean                 gCond_Food_E               = false
    boolean                 gCond_Food_F               = false
    boolean                 gCond_Food_G               = false
    boolean                 gCond_Justify_Expansion    = false
    boolean                 gCond_Justify_More_Workers = false
    boolean                 gCond_Hero_A               = false
   
    // Debug condition
    boolean                 gCond_Debug                = false
endglobals

//***************************************************************************
//*
//*  Debug Functions
//*
//***************************************************************************

//===========================================================================
function B2S takes boolean b returns string
    if b then
        return "true"
    else
        return "false"
    endif
endfunction

//===========================================================================
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

//===========================================================================
// Courtesy of AIAndy and Tommi. See source:
// http://www.hiveworkshop.com/threads/two-custom-campaign-ais-examples.8939/
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

//===========================================================================
function Msg takes string message returns nothing
    local integer slot = 0
   
    loop
        call DisplayTextToPlayer(Player(slot),0,0,message)
        set slot = slot + 1
        exitwhen slot >= 12
    endloop
endfunction

//***************************************************************************
//*
//*  Utility Functions
//*
//***************************************************************************

//===========================================================================
function CheckLastCommand takes boolean pop returns integer
    local integer cmd = GetLastCommand()
    if (pop) then
        call PopLastCommand(  )
    endif
    return cmd
endfunction

//===========================================================================
function CheckLastCommandData takes boolean pop returns integer
    local integer data = GetLastData()
    if (pop) then
        call PopLastCommand(  )
    endif
    return data
endfunction

//===========================================================================
function TotalFoodProduced takes nothing returns integer
    return GetPlayerState(ai_player,PLAYER_STATE_RESOURCE_FOOD_CAP)
endfunction

//===========================================================================
function ExpansionNeeded takes nothing returns boolean
    return take_exp
endfunction

//===========================================================================
function BuildExpansion takes integer hallID, integer mineID returns nothing
    if (HallsCompleted(hallID)) then
        call SetBuildExpa( TownCount(hallID) + 1, mineID )
    endif
endfunction

//===========================================================================
function CurrentAttackWave takes nothing returns integer
    return attackWave
endfunction

//===========================================================================
function ResetAttackUnits takes nothing returns nothing
    set awGold = 0
    set awWood = 0
    call InitAssaultGroup(  )
endfunction

//===========================================================================
function AddAttackUnit takes integer minQty, integer maxQty, integer unitID returns nothing
    // Track attacking gold workers
    if (unitID == 'ewsp') then
        set awGold = awGold + minQty
    endif

    // Track attacking wood workers
    if (unitID == 'ewsp') then
        set awWood = awWood + minQty
    endif

    call SetAssaultGroup( minQty, maxQty, unitID )
endfunction

//***************************************************************************
//*
//*  Basic Options
//*
//***************************************************************************

//===========================================================================
function InitOptions takes nothing returns nothing
    call SetMeleeAI(  )
    call SetDefendPlayer( true )
    call SetRandomPaths( true )
    call SetTargetHeroes( true )
    call SetPeonsRepair( true )
    call SetHeroesFlee( true )
    call SetHeroesBuyItems( true )
    call SetUnitsFlee( false )
    call SetGroupsFlee( true )
    call SetWatchMegaTargets( true )
    call SetIgnoreInjured( false )
    call SetHeroesTakeItems( true )
    call SetSlowChopping( false )
    call SetCaptainChanges( true )
    call SetSmartArtillery( true )
endfunction

//***************************************************************************
//*
//*  Conditions
//*
//***************************************************************************

//===========================================================================
// Updates the values of all preset conditions
//===========================================================================
function UpdateConditions takes nothing returns nothing
    set gCond_Food_A = ( FoodUsed(  ) >= 14 )
    set gCond_Food_B = ( FoodUsed(  ) >= 28 )
    set gCond_Food_C = ( FoodUsed(  ) >= 42 )
    set gCond_Food_D = ( FoodUsed(  ) >= 86 )
    set gCond_Food_E = ( FoodUsed(  ) >= 100 )
    set gCond_Food_F = ( FoodUsed(  ) >= 114 )
    set gCond_Food_G = ( FoodUsed(  ) >= 122 )
    set gCond_Justify_Expansion = ( GetMinesOwned(  ) == 1 )
    set gCond_Justify_More_Workers = ( GetUnitCount( 'egol' ) > 1 )
    set gCond_Hero_A = ( GetUnitCountDone( 'nnad' ) >= 1 )
   
    if gCond_Debug then
        call Msg("==========================")
        call Msg(("Justify more workers: " + B2S(gCond_Justify_More_Workers)))
        call Msg(("Number of mine units: " + Int2Str(GetUnitCount( 'egol' )) + " || Number of done mine units: " + Int2Str(GetUnitCountDone( 'egol' ))))
        call Msg("==========================")
    endif
endfunction

//***************************************************************************
//*
//*  Heroes
//*
//***************************************************************************

//===========================================================================
// Stores hero ID and skills
//===========================================================================
function SetHero takes integer order, integer heroid returns nothing
    if (order == 1) then
        set hero_id = heroid
        if (heroid == 'O009') then
            set skills1[ 1] = 'A033'
            set skills1[ 2] = 'A04V'
            set skills1[ 3] = 'A029'
            set skills1[ 4] = 'A033'
            set skills1[ 5] = 'A04V'
            set skills1[ 6] = 'A00S'
            set skills1[ 7] = 'A029'
            set skills1[ 8] = 'A033'
            set skills1[ 9] = 'A04V'
            set skills1[10] = 'A029'
        elseif (heroid == 'E006') then
            set skills1[ 1] = 'A04Z'
            set skills1[ 2] = 'A0A9'
            set skills1[ 3] = 'A09B'
            set skills1[ 4] = 'A04Z'
            set skills1[ 5] = 'A0A9'
            set skills1[ 6] = 'A09R'
            set skills1[ 7] = 'A09B'
            set skills1[ 8] = 'A04Z'
            set skills1[ 9] = 'A0A9'
            set skills1[10] = 'A09B'
        elseif (heroid == 'H00N') then
            set skills1[ 1] = 'A02V'
            set skills1[ 2] = 'A08K'
            set skills1[ 3] = 'A05B'
            set skills1[ 4] = 'A02V'
            set skills1[ 5] = 'A08K'
            set skills1[ 6] = 'A038'
            set skills1[ 7] = 'A05B'
            set skills1[ 8] = 'A02V'
            set skills1[ 9] = 'A08K'
            set skills1[10] = 'A05B'
        endif
    elseif (order == 2) then
        set hero_id2 = heroid
        if (heroid == 'O009') then
            set skills2[ 1] = 'A033'
            set skills2[ 2] = 'A04V'
            set skills2[ 3] = 'A029'
            set skills2[ 4] = 'A033'
            set skills2[ 5] = 'A04V'
            set skills2[ 6] = 'A00S'
            set skills2[ 7] = 'A029'
            set skills2[ 8] = 'A033'
            set skills2[ 9] = 'A04V'
            set skills2[10] = 'A029'
        elseif (heroid == 'E006') then
            set skills2[ 1] = 'A04Z'
            set skills2[ 2] = 'A0A9'
            set skills2[ 3] = 'A09B'
            set skills2[ 4] = 'A04Z'
            set skills2[ 5] = 'A0A9'
            set skills2[ 6] = 'A09R'
            set skills2[ 7] = 'A09B'
            set skills2[ 8] = 'A04Z'
            set skills2[ 9] = 'A0A9'
            set skills2[10] = 'A09B'
        elseif (heroid == 'H00N') then
            set skills2[ 1] = 'A02V'
            set skills2[ 2] = 'A08K'
            set skills2[ 3] = 'A05B'
            set skills2[ 4] = 'A02V'
            set skills2[ 5] = 'A08K'
            set skills2[ 6] = 'A038'
            set skills2[ 7] = 'A05B'
            set skills2[ 8] = 'A02V'
            set skills2[ 9] = 'A08K'
            set skills2[10] = 'A05B'
        endif
    elseif (order == 3) then
        set hero_id3 = heroid
        if (heroid == 'O009') then
            set skills3[ 1] = 'A033'
            set skills3[ 2] = 'A04V'
            set skills3[ 3] = 'A029'
            set skills3[ 4] = 'A033'
            set skills3[ 5] = 'A04V'
            set skills3[ 6] = 'A00S'
            set skills3[ 7] = 'A029'
            set skills3[ 8] = 'A033'
            set skills3[ 9] = 'A04V'
            set skills3[10] = 'A029'
        elseif (heroid == 'E006') then
            set skills3[ 1] = 'A04Z'
            set skills3[ 2] = 'A0A9'
            set skills3[ 3] = 'A09B'
            set skills3[ 4] = 'A04Z'
            set skills3[ 5] = 'A0A9'
            set skills3[ 6] = 'A09R'
            set skills3[ 7] = 'A09B'
            set skills3[ 8] = 'A04Z'
            set skills3[ 9] = 'A0A9'
            set skills3[10] = 'A09B'
        elseif (heroid == 'H00N') then
            set skills3[ 1] = 'A02V'
            set skills3[ 2] = 'A08K'
            set skills3[ 3] = 'A05B'
            set skills3[ 4] = 'A02V'
            set skills3[ 5] = 'A08K'
            set skills3[ 6] = 'A038'
            set skills3[ 7] = 'A05B'
            set skills3[ 8] = 'A02V'
            set skills3[ 9] = 'A08K'
            set skills3[10] = 'A05B'
        endif
    endif
endfunction

//===========================================================================
// Selects hero IDs for three possible heroes
//===========================================================================
function SelectHeroes takes nothing returns nothing
    local integer roll = GetRandomInt(1,100)
    if (roll <= 17) then
        call SetHero( 1, 'O009' )
        call SetHero( 2, 'E006' )
        call SetHero( 3, 'H00N' )
    elseif (roll <= 34) then
        call SetHero( 1, 'O009' )
        call SetHero( 2, 'H00N' )
        call SetHero( 3, 'E006' )
    elseif (roll <= 50) then
        call SetHero( 1, 'E006' )
        call SetHero( 2, 'O009' )
        call SetHero( 3, 'H00N' )
    elseif (roll <= 67) then
        call SetHero( 1, 'E006' )
        call SetHero( 2, 'H00N' )
        call SetHero( 3, 'O009' )
    elseif (roll <= 84) then
        call SetHero( 1, 'H00N' )
        call SetHero( 2, 'O009' )
        call SetHero( 3, 'E006' )
    else
        call SetHero( 1, 'H00N' )
        call SetHero( 2, 'E006' )
        call SetHero( 3, 'O009' )
    endif
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 building priorities for workers
//===========================================================================
function BuildPriorities takes nothing returns nothing
    local integer mine = TownWithMine()
    if (gCond_Food_A) then
        call SetBuildAll( BUILD_UNIT, 1, 'nntg', -1 )
    endif
    if (gCond_Food_B) then
        call SetBuildAll( BUILD_UNIT, 2, 'nntg', -1 )
    endif
    if (gCond_Food_C) then
        call SetBuildAll( BUILD_UNIT, 3, 'nntg', -1 )
    endif
    if (gCond_Food_D) then
        call SetBuildAll( BUILD_UNIT, 4, 'nntg', -1 )
    endif
    if (gCond_Food_E) then
        call SetBuildAll( BUILD_UNIT, 5, 'nntg', -1 )
    endif
    if (gCond_Hero_A) then
        call SetBuildAll( BUILD_UNIT, 1, hero_id, -1 )
    endif
    call SetBuildAll( BUILD_UNIT, 1, 'etol', -1 )
    if (gCond_Justify_More_Workers) then
        call SetBuildAll( BUILD_UNIT, 1, 'ewsp', -1 )
        call SetBuildAll( BUILD_UNIT, 2, 'ewsp', -1 )
        call SetBuildAll( BUILD_UNIT, 3, 'ewsp', -1 )
        call SetBuildAll( BUILD_UNIT, 4, 'ewsp', -1 )
        call SetBuildAll( BUILD_UNIT, 5, 'ewsp', -1 )
        if gCond_Debug then
            call Msg("==========================")
            call Msg("Build loop: making extra workers.")
            call Msg("==========================")
        endif
    endif
    call SetBuildAll( BUILD_UNIT, 6, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 7, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 8, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 9, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 10, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'nnad', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'nnsg', -1 )
    call SetBuildAll( BUILD_UNIT, 11, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 12, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 13, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'n005', -1 )
    call SetBuildAll( BUILD_UNIT, 2, 'nnsg', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'Rnam', -1 )
    if (gCond_Food_C) then
        call SetBuildAll( BUILD_UNIT, 1, 'etoa', -1 )
    endif
    if (gCond_Justify_Expansion) then
        call BuildExpansion( 'etol', 'etol' )
    endif
    call SetBuildAll( BUILD_UPGRADE, 1, 'Rnat', -1 )
endfunction

//===========================================================================
// Specifies harvesting priorities for workers
//===========================================================================
function HarvestPriorities takes nothing returns nothing
    local integer mine = TownWithMine()
    local integer allGold = GetUnitCountDone('ewsp')
    local integer allWood = GetUnitCountDone('ewsp')
    local integer numWorkers
    set numWorkers = 5
    call HarvestGold( mine + 0, numWorkers )
    set numWorkers = 5
    call HarvestGold( mine + 1, numWorkers )
    set numWorkers = 5
    call HarvestGold( mine + 2, numWorkers )
    set numWorkers = 5
    call HarvestGold( mine + 3, numWorkers )
    set numWorkers = allWood - awWood
    if (numWorkers > 0) then
        call HarvestWood( mine, numWorkers )
    endif
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

//***************************************************************************
//*
//*  Attacking
//*
//***************************************************************************

//===========================================================================
// Returns true if the minimum forces for an attack exist
//===========================================================================
function HaveMinimumAttackers takes nothing returns boolean
    local integer count

    // Check for attack wave limit
    if (attackWave > 20) then
        return false
    endif

    // Attack Group: All Units
    // No specific minimums exist, checking for at least one unit
    set count = 0
    set count = count + GetUnitCountDone(hero_id)
    set count = count + GetUnitCountDone(hero_id2)
    set count = count + GetUnitCountDone(hero_id3)
    set count = count + GetUnitCountDone('efdr')
    set count = count + GetUnitCountDone('h00D')
    set count = count + GetUnitCountDone('nsnp')
    set count = count + GetUnitCountDone('n00Q')
    set count = count + GetUnitCountDone('nwgs')
    set count = count + GetUnitCountDone('n01E')
    set count = count + GetUnitCountDone('nmyr')
    set count = count + GetUnitCountDone('nnsw')
    set count = count + GetUnitCountDone('nhyc')
    set count = count + GetUnitCountDone('n00E')
    set count = count + GetUnitCountDone('n00T')
    set count = count + GetUnitCountDone('n01D')
    set count = count + GetUnitCountDone('n007')
    if (count < 1) then
        return false
    endif
    return true
endfunction

//===========================================================================
// Assigns units to attack based on the given attack group
//===========================================================================
function PrepareAttackGroup takes integer groupID returns nothing
    local integer all

    // Attack Group #1: All Units
    if (groupID == 1) then
        set all = GetUnitCountDone( hero_id )
        call AddAttackUnit( all, all, hero_id )
        set all = GetUnitCountDone( hero_id2 )
        call AddAttackUnit( all, all, hero_id2 )
        set all = GetUnitCountDone( hero_id3 )
        call AddAttackUnit( all, all, hero_id3 )
        set all = GetUnitCountDone( 'efdr' )
        call AddAttackUnit( all, all, 'efdr' )
        set all = GetUnitCountDone( 'h00D' )
        call AddAttackUnit( all, all, 'h00D' )
        set all = GetUnitCountDone( 'nsnp' )
        call AddAttackUnit( all, all, 'nsnp' )
        set all = GetUnitCountDone( 'n00Q' )
        call AddAttackUnit( all, all, 'n00Q' )
        set all = GetUnitCountDone( 'nwgs' )
        call AddAttackUnit( all, all, 'nwgs' )
        set all = GetUnitCountDone( 'n01E' )
        call AddAttackUnit( all, all, 'n01E' )
        set all = GetUnitCountDone( 'nmyr' )
        call AddAttackUnit( all, all, 'nmyr' )
        set all = GetUnitCountDone( 'nnsw' )
        call AddAttackUnit( all, all, 'nnsw' )
        set all = GetUnitCountDone( 'nhyc' )
        call AddAttackUnit( all, all, 'nhyc' )
        set all = GetUnitCountDone( 'n00E' )
        call AddAttackUnit( all, all, 'n00E' )
        set all = GetUnitCountDone( 'n00T' )
        call AddAttackUnit( all, all, 'n00T' )
        set all = GetUnitCountDone( 'n01D' )
        call AddAttackUnit( all, all, 'n01D' )
        set all = GetUnitCountDone( 'n007' )
        call AddAttackUnit( all, all, 'n007' )

    endif
endfunction

//===========================================================================
// Prepares an attack group based on the current attack wave
//===========================================================================
function PrepareForces takes nothing returns nothing
    if (attackWave == 1) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 2) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 3) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 4) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 5) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 6) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 7) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 8) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 9) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 10) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 11) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 12) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 13) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 14) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 15) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 16) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 17) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 18) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 19) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 20) then
        call PrepareAttackGroup( 1 )
    endif
endfunction

//===========================================================================
// Sleep delays for each attack wave
//===========================================================================
function AttackWaveDelay takes integer inWave returns nothing
    if (inWave < nextDelay) then
        return
    endif

    if (inWave == 0) then
        call Sleep( 200 )
    elseif (inWave == 1) then
        call Sleep( 80 )
    elseif (inWave == 2) then
        call Sleep( 80 )
    elseif (inWave == 3) then
        call Sleep( 80 )
    elseif (inWave == 4) then
        call Sleep( 80 )
    elseif (inWave == 5) then
        call Sleep( 80 )
    elseif (inWave == 6) then
        call Sleep( 80 )
    elseif (inWave == 7) then
        call Sleep( 80 )
    elseif (inWave == 8) then
        call Sleep( 80 )
    elseif (inWave == 9) then
        call Sleep( 80 )
    elseif (inWave == 10) then
        call Sleep( 80 )
    elseif (inWave == 11) then
        call Sleep( 80 )
    elseif (inWave == 12) then
        call Sleep( 80 )
    elseif (inWave == 13) then
        call Sleep( 80 )
    elseif (inWave == 14) then
        call Sleep( 80 )
    elseif (inWave == 15) then
        call Sleep( 80 )
    elseif (inWave == 16) then
        call Sleep( 80 )
    elseif (inWave == 17) then
        call Sleep( 80 )
    elseif (inWave == 18) then
        call Sleep( 80 )
    elseif (inWave == 19) then
        call Sleep( 80 )
    elseif (inWave == 20) then
        call Sleep( 80 )
    endif

    set nextDelay = inWave + 1
endfunction

//===========================================================================
// Advances attack wave counter
//===========================================================================
function AttackWaveUpdate takes nothing returns nothing
    call AttackWaveDelay( attackWave )
    set attackWave = attackWave + 1
    if (attackWave > 20) then
        set attackWave = 1
        set nextDelay = attackWave + 1
    endif
endfunction

//===========================================================================
// Basic attack functionality
//===========================================================================
function AttackTarget takes unit target, boolean addAlliance returns nothing
    if (target == null) then
        return
    endif
    if (addAlliance) then
        call SetAllianceTarget( target )
    endif
    call FormGroup( 3, true )
    call AttackMoveKillA( target )
    if (not addAlliance) then
        call SetAllianceTarget( null )
    endif
endfunction

//===========================================================================
// Initiates an attack based on target priorities
//===========================================================================
function LaunchAttack takes nothing returns nothing
    local unit target = null
    local boolean setAlly = true

    // Don't launch any attack while town is threatened
    if (TownThreatened()) then
        call Sleep( 2 )
        return
    endif

    // Target Priority #1
    if (target == null) then
        set target = GetAllianceTarget()
        if (target != null) then
            set setAlly = false
        endif
    endif

    // Target Priority #2
    if (gCond_Food_C) then
        if (target == null) then
            set target = GetExpansionFoe()
            if (target != null) then
                set take_exp = false
            endif
        endif

        // Target Priority #3
    endif
    if (target == null) then
        set target = GetMegaTarget()
    endif

    // Target Priority #4
    if (target == null) then
        set target = GetEnemyExpansion()
    endif

    // Target Priority #5
    if (target == null) then
        set target = GetEnemyExpansion()
        if (target == null) then
            call StartGetEnemyBase(  )
            loop
                exitwhen (not WaitGetEnemyBase())
                call SuicideSleep( 1 )
            endloop
            set target = GetEnemyBase()
        endif
    endif

    // Target Priority #6
    if (target == null) then
        set target = GetCreepCamp( 0, 9, false )
    endif

    // Target Priority #7
    if (gCond_Food_C) then
        if (target == null) then
            set target = GetCreepCamp( 10, 100, true )
        endif

    endif
    // Attack the target and increment attack wave
    if (target != null) then
        call AttackTarget( target, setAlly )
        call AttackWaveUpdate(  )
    else
        // If no target was found, sleep a bit before trying again
        call Sleep( 20 )
    endif
endfunction

//===========================================================================
// Determines all attacking assignments
//===========================================================================
function AttackAssignment takes nothing returns nothing
    call StaggerSleep( 0, 2 )
    if (attackWave == 1) then
        call AttackWaveDelay( 0 )
    endif
    loop
        loop
            call UpdateConditions(  )
            exitwhen (HaveMinimumAttackers() and not CaptainRetreating())
            call Sleep( 2 )
        endloop
        call ResetAttackUnits(  )
        call PrepareForces(  )
        call LaunchAttack(  )
    endloop
endfunction

//===========================================================================
// Debug loop
//===========================================================================

function DebugLoop takes nothing returns nothing
    loop
        call WaitForSignal()
        set gCond_Debug = not gCond_Debug
    endloop
endfunction

//***************************************************************************
//*
//*  Main Entry Point
//*
//***************************************************************************

//===========================================================================
function main takes nothing returns nothing
    call InitAI(  )
    call SetPlayerName( ai_player, "Shellgan" )
    call InitOptions(  )
    call SelectHeroes(  )
    call CreateCaptains(  )
    call SetHeroLevels( function ChooseHeroSkill )

    call Sleep( 0.1 )
    call StartThread( function WorkerAssignment )
    call StartThread( function AttackAssignment )
    call StartThread( function DebugLoop        )
    call PlayGame(  )
endfunction


Note: because the AI updates the conditions every 2 seconds or so, debugging can be a bitch. So you need to do the following:

1. Insert this trigger to your map (send the command to the computer player):

  • Debug command
    • Events
      • Player - Player 1 (Red) skips a cinematic sequence
    • Conditions
    • Actions
      • AI - Send Player 2 (Blue) the AI Command (0, 0)
2. Everytime the AI player should start building extra workers, press ESC to show debug messages. If you want to stop showing debug messages, press ESC again (and if you want to start showing debug again press ESC again... you get the idea...)

3. You should get two types of debug statements: one for each time the script updates it's conditions with how many mine buildings there are, etc. .And in case the condition does work and more workers should be built, you'll get this extra message: "Build loop: making extra workers".

This should help at least a bit.
 
I've attached the build order showing that it should only produce the extra five workers if the conditions are met.

The first screen shows the condition failing, yet it builds the five extra workers.

The second screen shows the condition passing but the workers have been made for some time.
 

Attachments

  • 2017-11-18 16_41_47-AI Editor - [X__..._Beyond the Throne_AI_BtT Naga Insane.wai].png
    2017-11-18 16_41_47-AI Editor - [X__..._Beyond the Throne_AI_BtT Naga Insane.wai].png
    23.5 KB · Views: 38
  • 2017-11-18 16_41_36-Microsoft Office 2010.png
    2017-11-18 16_41_36-Microsoft Office 2010.png
    2.7 MB · Views: 51
  • 2017-11-18 16_40_16-Warcraft III.png
    2017-11-18 16_40_16-Warcraft III.png
    673.7 KB · Views: 47
Level 12
Joined
Jun 15, 2016
Messages
472
Oh! If that's your build order all you need to do is switch around. Give the "Justify more workers" condition to slaves 6 through 10 and it should work as you want.

This is why I don't use the AI editor... It doesn't tell you what everything does and opens the door to these types of mistakes.
 
Level 12
Joined
Jun 15, 2016
Messages
472
Odd. Just to make sure, try running it with this AI:
(this also has the debug statements if you need them)


JASS:
//===========================================================================
//
// Shellgan
//
//   Warcraft III AI script
//   Generated by the Warcraft III World Editor
//   Date: Fri Nov 17 01:16:57 2017
//
//===========================================================================

//***************************************************************************
//*
//*  Global Variables
//*
//***************************************************************************

globals
    integer                 attackWave                 = 1
    integer                 nextDelay                  = 0
    integer                 awGold                     = 0
    integer                 awWood                     = 0

    // Conditions
    boolean                 gCond_Food_A               = false
    boolean                 gCond_Food_B               = false
    boolean                 gCond_Food_C               = false
    boolean                 gCond_Food_D               = false
    boolean                 gCond_Food_E               = false
    boolean                 gCond_Food_F               = false
    boolean                 gCond_Food_G               = false
    boolean                 gCond_Justify_Expansion    = false
    boolean                 gCond_Justify_More_Workers = false
    boolean                 gCond_Hero_A               = false
   
    // Debug condition
    boolean                 gCond_Debug                = false
endglobals

//***************************************************************************
//*
//*  Debug Functions
//*
//***************************************************************************

//===========================================================================
function B2S takes boolean b returns string
    if b then
        return "true"
    else
        return "false"
    endif
endfunction

//===========================================================================
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

//===========================================================================
// Courtesy of AIAndy and Tommi. See source:
// http://www.hiveworkshop.com/threads/two-custom-campaign-ais-examples.8939/
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

//===========================================================================
function Msg takes string message returns nothing
    local integer slot = 0
   
    loop
        call DisplayTextToPlayer(Player(slot),0,0,message)
        set slot = slot + 1
        exitwhen slot >= 12
    endloop
endfunction

//***************************************************************************
//*
//*  Utility Functions
//*
//***************************************************************************

//===========================================================================
function CheckLastCommand takes boolean pop returns integer
    local integer cmd = GetLastCommand()
    if (pop) then
        call PopLastCommand(  )
    endif
    return cmd
endfunction

//===========================================================================
function CheckLastCommandData takes boolean pop returns integer
    local integer data = GetLastData()
    if (pop) then
        call PopLastCommand(  )
    endif
    return data
endfunction

//===========================================================================
function TotalFoodProduced takes nothing returns integer
    return GetPlayerState(ai_player,PLAYER_STATE_RESOURCE_FOOD_CAP)
endfunction

//===========================================================================
function ExpansionNeeded takes nothing returns boolean
    return take_exp
endfunction

//===========================================================================
function BuildExpansion takes integer hallID, integer mineID returns nothing
    if (HallsCompleted(hallID)) then
        call SetBuildExpa( TownCount(hallID) + 1, mineID )
    endif
endfunction

//===========================================================================
function CurrentAttackWave takes nothing returns integer
    return attackWave
endfunction

//===========================================================================
function ResetAttackUnits takes nothing returns nothing
    set awGold = 0
    set awWood = 0
    call InitAssaultGroup(  )
endfunction

//===========================================================================
function AddAttackUnit takes integer minQty, integer maxQty, integer unitID returns nothing
    // Track attacking gold workers
    if (unitID == 'ewsp') then
        set awGold = awGold + minQty
    endif

    // Track attacking wood workers
    if (unitID == 'ewsp') then
        set awWood = awWood + minQty
    endif

    call SetAssaultGroup( minQty, maxQty, unitID )
endfunction

//***************************************************************************
//*
//*  Basic Options
//*
//***************************************************************************

//===========================================================================
function InitOptions takes nothing returns nothing
    call SetMeleeAI(  )
    call SetDefendPlayer( true )
    call SetRandomPaths( true )
    call SetTargetHeroes( true )
    call SetPeonsRepair( true )
    call SetHeroesFlee( true )
    call SetHeroesBuyItems( true )
    call SetUnitsFlee( false )
    call SetGroupsFlee( true )
    call SetWatchMegaTargets( true )
    call SetIgnoreInjured( false )
    call SetHeroesTakeItems( true )
    call SetSlowChopping( false )
    call SetCaptainChanges( true )
    call SetSmartArtillery( true )
endfunction

//***************************************************************************
//*
//*  Conditions
//*
//***************************************************************************

//===========================================================================
// Updates the values of all preset conditions
//===========================================================================
function UpdateConditions takes nothing returns nothing
    set gCond_Food_A = ( FoodUsed(  ) >= 14 )
    set gCond_Food_B = ( FoodUsed(  ) >= 28 )
    set gCond_Food_C = ( FoodUsed(  ) >= 42 )
    set gCond_Food_D = ( FoodUsed(  ) >= 86 )
    set gCond_Food_E = ( FoodUsed(  ) >= 100 )
    set gCond_Food_F = ( FoodUsed(  ) >= 114 )
    set gCond_Food_G = ( FoodUsed(  ) >= 122 )
    set gCond_Justify_Expansion = ( GetMinesOwned(  ) == 1 )
    set gCond_Justify_More_Workers = ( GetUnitCount( 'egol' ) > 1 )
    set gCond_Hero_A = ( GetUnitCountDone( 'nnad' ) >= 1 )
   
    if gCond_Debug then
        call Msg("==========================")
        call Msg(("Justify more workers: " + B2S(gCond_Justify_More_Workers)))
        call Msg(("Number of mine units: " + Int2Str(GetUnitCount( 'egol' )) + " || Number of done mine units: " + Int2Str(GetUnitCountDone( 'egol' ))))
        call Msg("==========================")
    endif
endfunction

//***************************************************************************
//*
//*  Heroes
//*
//***************************************************************************

//===========================================================================
// Stores hero ID and skills
//===========================================================================
function SetHero takes integer order, integer heroid returns nothing
    if (order == 1) then
        set hero_id = heroid
        if (heroid == 'O009') then
            set skills1[ 1] = 'A033'
            set skills1[ 2] = 'A04V'
            set skills1[ 3] = 'A029'
            set skills1[ 4] = 'A033'
            set skills1[ 5] = 'A04V'
            set skills1[ 6] = 'A00S'
            set skills1[ 7] = 'A029'
            set skills1[ 8] = 'A033'
            set skills1[ 9] = 'A04V'
            set skills1[10] = 'A029'
        elseif (heroid == 'E006') then
            set skills1[ 1] = 'A04Z'
            set skills1[ 2] = 'A0A9'
            set skills1[ 3] = 'A09B'
            set skills1[ 4] = 'A04Z'
            set skills1[ 5] = 'A0A9'
            set skills1[ 6] = 'A09R'
            set skills1[ 7] = 'A09B'
            set skills1[ 8] = 'A04Z'
            set skills1[ 9] = 'A0A9'
            set skills1[10] = 'A09B'
        elseif (heroid == 'H00N') then
            set skills1[ 1] = 'A02V'
            set skills1[ 2] = 'A08K'
            set skills1[ 3] = 'A05B'
            set skills1[ 4] = 'A02V'
            set skills1[ 5] = 'A08K'
            set skills1[ 6] = 'A038'
            set skills1[ 7] = 'A05B'
            set skills1[ 8] = 'A02V'
            set skills1[ 9] = 'A08K'
            set skills1[10] = 'A05B'
        endif
    elseif (order == 2) then
        set hero_id2 = heroid
        if (heroid == 'O009') then
            set skills2[ 1] = 'A033'
            set skills2[ 2] = 'A04V'
            set skills2[ 3] = 'A029'
            set skills2[ 4] = 'A033'
            set skills2[ 5] = 'A04V'
            set skills2[ 6] = 'A00S'
            set skills2[ 7] = 'A029'
            set skills2[ 8] = 'A033'
            set skills2[ 9] = 'A04V'
            set skills2[10] = 'A029'
        elseif (heroid == 'E006') then
            set skills2[ 1] = 'A04Z'
            set skills2[ 2] = 'A0A9'
            set skills2[ 3] = 'A09B'
            set skills2[ 4] = 'A04Z'
            set skills2[ 5] = 'A0A9'
            set skills2[ 6] = 'A09R'
            set skills2[ 7] = 'A09B'
            set skills2[ 8] = 'A04Z'
            set skills2[ 9] = 'A0A9'
            set skills2[10] = 'A09B'
        elseif (heroid == 'H00N') then
            set skills2[ 1] = 'A02V'
            set skills2[ 2] = 'A08K'
            set skills2[ 3] = 'A05B'
            set skills2[ 4] = 'A02V'
            set skills2[ 5] = 'A08K'
            set skills2[ 6] = 'A038'
            set skills2[ 7] = 'A05B'
            set skills2[ 8] = 'A02V'
            set skills2[ 9] = 'A08K'
            set skills2[10] = 'A05B'
        endif
    elseif (order == 3) then
        set hero_id3 = heroid
        if (heroid == 'O009') then
            set skills3[ 1] = 'A033'
            set skills3[ 2] = 'A04V'
            set skills3[ 3] = 'A029'
            set skills3[ 4] = 'A033'
            set skills3[ 5] = 'A04V'
            set skills3[ 6] = 'A00S'
            set skills3[ 7] = 'A029'
            set skills3[ 8] = 'A033'
            set skills3[ 9] = 'A04V'
            set skills3[10] = 'A029'
        elseif (heroid == 'E006') then
            set skills3[ 1] = 'A04Z'
            set skills3[ 2] = 'A0A9'
            set skills3[ 3] = 'A09B'
            set skills3[ 4] = 'A04Z'
            set skills3[ 5] = 'A0A9'
            set skills3[ 6] = 'A09R'
            set skills3[ 7] = 'A09B'
            set skills3[ 8] = 'A04Z'
            set skills3[ 9] = 'A0A9'
            set skills3[10] = 'A09B'
        elseif (heroid == 'H00N') then
            set skills3[ 1] = 'A02V'
            set skills3[ 2] = 'A08K'
            set skills3[ 3] = 'A05B'
            set skills3[ 4] = 'A02V'
            set skills3[ 5] = 'A08K'
            set skills3[ 6] = 'A038'
            set skills3[ 7] = 'A05B'
            set skills3[ 8] = 'A02V'
            set skills3[ 9] = 'A08K'
            set skills3[10] = 'A05B'
        endif
    endif
endfunction

//===========================================================================
// Selects hero IDs for three possible heroes
//===========================================================================
function SelectHeroes takes nothing returns nothing
    local integer roll = GetRandomInt(1,100)
    if (roll <= 17) then
        call SetHero( 1, 'O009' )
        call SetHero( 2, 'E006' )
        call SetHero( 3, 'H00N' )
    elseif (roll <= 34) then
        call SetHero( 1, 'O009' )
        call SetHero( 2, 'H00N' )
        call SetHero( 3, 'E006' )
    elseif (roll <= 50) then
        call SetHero( 1, 'E006' )
        call SetHero( 2, 'O009' )
        call SetHero( 3, 'H00N' )
    elseif (roll <= 67) then
        call SetHero( 1, 'E006' )
        call SetHero( 2, 'H00N' )
        call SetHero( 3, 'O009' )
    elseif (roll <= 84) then
        call SetHero( 1, 'H00N' )
        call SetHero( 2, 'O009' )
        call SetHero( 3, 'E006' )
    else
        call SetHero( 1, 'H00N' )
        call SetHero( 2, 'E006' )
        call SetHero( 3, 'O009' )
    endif
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 building priorities for workers
//===========================================================================
function BuildPriorities takes nothing returns nothing
    local integer mine = TownWithMine()
    if (gCond_Food_A) then
        call SetBuildAll( BUILD_UNIT, 1, 'nntg', -1 )
    endif
    if (gCond_Food_B) then
        call SetBuildAll( BUILD_UNIT, 2, 'nntg', -1 )
    endif
    if (gCond_Food_C) then
        call SetBuildAll( BUILD_UNIT, 3, 'nntg', -1 )
    endif
    if (gCond_Food_D) then
        call SetBuildAll( BUILD_UNIT, 4, 'nntg', -1 )
    endif
    if (gCond_Food_E) then
        call SetBuildAll( BUILD_UNIT, 5, 'nntg', -1 )
    endif
    if (gCond_Hero_A) then
        call SetBuildAll( BUILD_UNIT, 1, hero_id, -1 )
    endif
    call SetBuildAll( BUILD_UNIT, 1, 'etol', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 2, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 3, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 4, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 5, 'ewsp', -1 )
    if (gCond_Justify_More_Workers) then
        call SetBuildAll( BUILD_UNIT, 6, 'ewsp', -1 )
        call SetBuildAll( BUILD_UNIT, 7, 'ewsp', -1 )
        call SetBuildAll( BUILD_UNIT, 8, 'ewsp', -1 )
        call SetBuildAll( BUILD_UNIT, 9, 'ewsp', -1 )
        call SetBuildAll( BUILD_UNIT, 10, 'ewsp', -1 )
        if gCond_Debug then
            call Msg("==========================")
            call Msg("Build loop: making extra workers.")
            call Msg("==========================")
        endif
    endif
    call SetBuildAll( BUILD_UNIT, 1, 'nnad', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'nnsg', -1 )
    call SetBuildAll( BUILD_UNIT, 11, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 12, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 13, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'n005', -1 )
    call SetBuildAll( BUILD_UNIT, 2, 'nnsg', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'Rnam', -1 )
    if (gCond_Food_C) then
        call SetBuildAll( BUILD_UNIT, 1, 'etoa', -1 )
    endif
    if (gCond_Justify_Expansion) then
        call BuildExpansion( 'etol', 'etol' )
    endif
    call SetBuildAll( BUILD_UPGRADE, 1, 'Rnat', -1 )
endfunction

//===========================================================================
// Specifies harvesting priorities for workers
//===========================================================================
function HarvestPriorities takes nothing returns nothing
    local integer mine = TownWithMine()
    local integer allGold = GetUnitCountDone('ewsp')
    local integer allWood = GetUnitCountDone('ewsp')
    local integer numWorkers
    set numWorkers = 5
    call HarvestGold( mine + 0, numWorkers )
    set numWorkers = 5
    call HarvestGold( mine + 1, numWorkers )
    set numWorkers = 5
    call HarvestGold( mine + 2, numWorkers )
    set numWorkers = 5
    call HarvestGold( mine + 3, numWorkers )
    set numWorkers = allWood - awWood
    if (numWorkers > 0) then
        call HarvestWood( mine, numWorkers )
    endif
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

//***************************************************************************
//*
//*  Attacking
//*
//***************************************************************************

//===========================================================================
// Returns true if the minimum forces for an attack exist
//===========================================================================
function HaveMinimumAttackers takes nothing returns boolean
    local integer count

    // Check for attack wave limit
    if (attackWave > 20) then
        return false
    endif

    // Attack Group: All Units
    // No specific minimums exist, checking for at least one unit
    set count = 0
    set count = count + GetUnitCountDone(hero_id)
    set count = count + GetUnitCountDone(hero_id2)
    set count = count + GetUnitCountDone(hero_id3)
    set count = count + GetUnitCountDone('efdr')
    set count = count + GetUnitCountDone('h00D')
    set count = count + GetUnitCountDone('nsnp')
    set count = count + GetUnitCountDone('n00Q')
    set count = count + GetUnitCountDone('nwgs')
    set count = count + GetUnitCountDone('n01E')
    set count = count + GetUnitCountDone('nmyr')
    set count = count + GetUnitCountDone('nnsw')
    set count = count + GetUnitCountDone('nhyc')
    set count = count + GetUnitCountDone('n00E')
    set count = count + GetUnitCountDone('n00T')
    set count = count + GetUnitCountDone('n01D')
    set count = count + GetUnitCountDone('n007')
    if (count < 1) then
        return false
    endif
    return true
endfunction

//===========================================================================
// Assigns units to attack based on the given attack group
//===========================================================================
function PrepareAttackGroup takes integer groupID returns nothing
    local integer all

    // Attack Group #1: All Units
    if (groupID == 1) then
        set all = GetUnitCountDone( hero_id )
        call AddAttackUnit( all, all, hero_id )
        set all = GetUnitCountDone( hero_id2 )
        call AddAttackUnit( all, all, hero_id2 )
        set all = GetUnitCountDone( hero_id3 )
        call AddAttackUnit( all, all, hero_id3 )
        set all = GetUnitCountDone( 'efdr' )
        call AddAttackUnit( all, all, 'efdr' )
        set all = GetUnitCountDone( 'h00D' )
        call AddAttackUnit( all, all, 'h00D' )
        set all = GetUnitCountDone( 'nsnp' )
        call AddAttackUnit( all, all, 'nsnp' )
        set all = GetUnitCountDone( 'n00Q' )
        call AddAttackUnit( all, all, 'n00Q' )
        set all = GetUnitCountDone( 'nwgs' )
        call AddAttackUnit( all, all, 'nwgs' )
        set all = GetUnitCountDone( 'n01E' )
        call AddAttackUnit( all, all, 'n01E' )
        set all = GetUnitCountDone( 'nmyr' )
        call AddAttackUnit( all, all, 'nmyr' )
        set all = GetUnitCountDone( 'nnsw' )
        call AddAttackUnit( all, all, 'nnsw' )
        set all = GetUnitCountDone( 'nhyc' )
        call AddAttackUnit( all, all, 'nhyc' )
        set all = GetUnitCountDone( 'n00E' )
        call AddAttackUnit( all, all, 'n00E' )
        set all = GetUnitCountDone( 'n00T' )
        call AddAttackUnit( all, all, 'n00T' )
        set all = GetUnitCountDone( 'n01D' )
        call AddAttackUnit( all, all, 'n01D' )
        set all = GetUnitCountDone( 'n007' )
        call AddAttackUnit( all, all, 'n007' )

    endif
endfunction

//===========================================================================
// Prepares an attack group based on the current attack wave
//===========================================================================
function PrepareForces takes nothing returns nothing
    if (attackWave == 1) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 2) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 3) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 4) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 5) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 6) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 7) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 8) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 9) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 10) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 11) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 12) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 13) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 14) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 15) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 16) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 17) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 18) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 19) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 20) then
        call PrepareAttackGroup( 1 )
    endif
endfunction

//===========================================================================
// Sleep delays for each attack wave
//===========================================================================
function AttackWaveDelay takes integer inWave returns nothing
    if (inWave < nextDelay) then
        return
    endif

    if (inWave == 0) then
        call Sleep( 200 )
    elseif (inWave == 1) then
        call Sleep( 80 )
    elseif (inWave == 2) then
        call Sleep( 80 )
    elseif (inWave == 3) then
        call Sleep( 80 )
    elseif (inWave == 4) then
        call Sleep( 80 )
    elseif (inWave == 5) then
        call Sleep( 80 )
    elseif (inWave == 6) then
        call Sleep( 80 )
    elseif (inWave == 7) then
        call Sleep( 80 )
    elseif (inWave == 8) then
        call Sleep( 80 )
    elseif (inWave == 9) then
        call Sleep( 80 )
    elseif (inWave == 10) then
        call Sleep( 80 )
    elseif (inWave == 11) then
        call Sleep( 80 )
    elseif (inWave == 12) then
        call Sleep( 80 )
    elseif (inWave == 13) then
        call Sleep( 80 )
    elseif (inWave == 14) then
        call Sleep( 80 )
    elseif (inWave == 15) then
        call Sleep( 80 )
    elseif (inWave == 16) then
        call Sleep( 80 )
    elseif (inWave == 17) then
        call Sleep( 80 )
    elseif (inWave == 18) then
        call Sleep( 80 )
    elseif (inWave == 19) then
        call Sleep( 80 )
    elseif (inWave == 20) then
        call Sleep( 80 )
    endif

    set nextDelay = inWave + 1
endfunction

//===========================================================================
// Advances attack wave counter
//===========================================================================
function AttackWaveUpdate takes nothing returns nothing
    call AttackWaveDelay( attackWave )
    set attackWave = attackWave + 1
    if (attackWave > 20) then
        set attackWave = 1
        set nextDelay = attackWave + 1
    endif
endfunction

//===========================================================================
// Basic attack functionality
//===========================================================================
function AttackTarget takes unit target, boolean addAlliance returns nothing
    if (target == null) then
        return
    endif
    if (addAlliance) then
        call SetAllianceTarget( target )
    endif
    call FormGroup( 3, true )
    call AttackMoveKillA( target )
    if (not addAlliance) then
        call SetAllianceTarget( null )
    endif
endfunction

//===========================================================================
// Initiates an attack based on target priorities
//===========================================================================
function LaunchAttack takes nothing returns nothing
    local unit target = null
    local boolean setAlly = true

    // Don't launch any attack while town is threatened
    if (TownThreatened()) then
        call Sleep( 2 )
        return
    endif

    // Target Priority #1
    if (target == null) then
        set target = GetAllianceTarget()
        if (target != null) then
            set setAlly = false
        endif
    endif

    // Target Priority #2
    if (gCond_Food_C) then
        if (target == null) then
            set target = GetExpansionFoe()
            if (target != null) then
                set take_exp = false
            endif
        endif

        // Target Priority #3
    endif
    if (target == null) then
        set target = GetMegaTarget()
    endif

    // Target Priority #4
    if (target == null) then
        set target = GetEnemyExpansion()
    endif

    // Target Priority #5
    if (target == null) then
        set target = GetEnemyExpansion()
        if (target == null) then
            call StartGetEnemyBase(  )
            loop
                exitwhen (not WaitGetEnemyBase())
                call SuicideSleep( 1 )
            endloop
            set target = GetEnemyBase()
        endif
    endif

    // Target Priority #6
    if (target == null) then
        set target = GetCreepCamp( 0, 9, false )
    endif

    // Target Priority #7
    if (gCond_Food_C) then
        if (target == null) then
            set target = GetCreepCamp( 10, 100, true )
        endif

    endif
    // Attack the target and increment attack wave
    if (target != null) then
        call AttackTarget( target, setAlly )
        call AttackWaveUpdate(  )
    else
        // If no target was found, sleep a bit before trying again
        call Sleep( 20 )
    endif
endfunction

//===========================================================================
// Determines all attacking assignments
//===========================================================================
function AttackAssignment takes nothing returns nothing
    call StaggerSleep( 0, 2 )
    if (attackWave == 1) then
        call AttackWaveDelay( 0 )
    endif
    loop
        loop
            call UpdateConditions(  )
            exitwhen (HaveMinimumAttackers() and not CaptainRetreating())
            call Sleep( 2 )
        endloop
        call ResetAttackUnits(  )
        call PrepareForces(  )
        call LaunchAttack(  )
    endloop
endfunction

//===========================================================================
// Debug loop
//===========================================================================

function DebugLoop takes nothing returns nothing
    loop
        call WaitForSignal()
        set gCond_Debug = not gCond_Debug
    endloop
endfunction

//***************************************************************************
//*
//*  Main Entry Point
//*
//***************************************************************************

//===========================================================================
function main takes nothing returns nothing
    call InitAI(  )
    call SetPlayerName( ai_player, "Shellgan" )
    call InitOptions(  )
    call SelectHeroes(  )
    call CreateCaptains(  )
    call SetHeroLevels( function ChooseHeroSkill )

    call Sleep( 0.1 )
    call StartThread( function WorkerAssignment )
    call StartThread( function AttackAssignment )
    call StartThread( function DebugLoop        )
    call PlayGame(  )
endfunction
 
Level 12
Joined
Jun 15, 2016
Messages
472
That is because you create your eleventh through thirteenth slave with no condition later. I only caught it now. Basically what you tell the AI is to build 10 slaves if you have 2 expansions, then tell it to build 13 no matter what. This one really should work.


JASS:
//===========================================================================
//
// Shellgan
//
//   Warcraft III AI script
//   Generated by the Warcraft III World Editor
//   Date: Fri Nov 17 01:16:57 2017
//
//===========================================================================

//***************************************************************************
//*
//*  Global Variables
//*
//***************************************************************************

globals
    integer                 attackWave                 = 1
    integer                 nextDelay                  = 0
    integer                 awGold                     = 0
    integer                 awWood                     = 0

    // Conditions
    boolean                 gCond_Food_A               = false
    boolean                 gCond_Food_B               = false
    boolean                 gCond_Food_C               = false
    boolean                 gCond_Food_D               = false
    boolean                 gCond_Food_E               = false
    boolean                 gCond_Food_F               = false
    boolean                 gCond_Food_G               = false
    boolean                 gCond_Justify_Expansion    = false
    boolean                 gCond_Justify_More_Workers = false
    boolean                 gCond_Hero_A               = false
   
    // Debug condition
    boolean                 gCond_Debug                = false
endglobals

//***************************************************************************
//*
//*  Debug Functions
//*
//***************************************************************************

//===========================================================================
function B2S takes boolean b returns string
    if b then
        return "true"
    else
        return "false"
    endif
endfunction

//===========================================================================
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

//===========================================================================
// Courtesy of AIAndy and Tommi. See source:
// http://www.hiveworkshop.com/threads/two-custom-campaign-ais-examples.8939/
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

//===========================================================================
function Msg takes string message returns nothing
    local integer slot = 0
   
    loop
        call DisplayTextToPlayer(Player(slot),0,0,message)
        set slot = slot + 1
        exitwhen slot >= 12
    endloop
endfunction

//***************************************************************************
//*
//*  Utility Functions
//*
//***************************************************************************

//===========================================================================
function CheckLastCommand takes boolean pop returns integer
    local integer cmd = GetLastCommand()
    if (pop) then
        call PopLastCommand(  )
    endif
    return cmd
endfunction

//===========================================================================
function CheckLastCommandData takes boolean pop returns integer
    local integer data = GetLastData()
    if (pop) then
        call PopLastCommand(  )
    endif
    return data
endfunction

//===========================================================================
function TotalFoodProduced takes nothing returns integer
    return GetPlayerState(ai_player,PLAYER_STATE_RESOURCE_FOOD_CAP)
endfunction

//===========================================================================
function ExpansionNeeded takes nothing returns boolean
    return take_exp
endfunction

//===========================================================================
function BuildExpansion takes integer hallID, integer mineID returns nothing
    if (HallsCompleted(hallID)) then
        call SetBuildExpa( TownCount(hallID) + 1, mineID )
    endif
endfunction

//===========================================================================
function CurrentAttackWave takes nothing returns integer
    return attackWave
endfunction

//===========================================================================
function ResetAttackUnits takes nothing returns nothing
    set awGold = 0
    set awWood = 0
    call InitAssaultGroup(  )
endfunction

//===========================================================================
function AddAttackUnit takes integer minQty, integer maxQty, integer unitID returns nothing
    // Track attacking gold workers
    if (unitID == 'ewsp') then
        set awGold = awGold + minQty
    endif

    // Track attacking wood workers
    if (unitID == 'ewsp') then
        set awWood = awWood + minQty
    endif

    call SetAssaultGroup( minQty, maxQty, unitID )
endfunction

//***************************************************************************
//*
//*  Basic Options
//*
//***************************************************************************

//===========================================================================
function InitOptions takes nothing returns nothing
    call SetMeleeAI(  )
    call SetDefendPlayer( true )
    call SetRandomPaths( true )
    call SetTargetHeroes( true )
    call SetPeonsRepair( true )
    call SetHeroesFlee( true )
    call SetHeroesBuyItems( true )
    call SetUnitsFlee( false )
    call SetGroupsFlee( true )
    call SetWatchMegaTargets( true )
    call SetIgnoreInjured( false )
    call SetHeroesTakeItems( true )
    call SetSlowChopping( false )
    call SetCaptainChanges( true )
    call SetSmartArtillery( true )
endfunction

//***************************************************************************
//*
//*  Conditions
//*
//***************************************************************************

//===========================================================================
// Updates the values of all preset conditions
//===========================================================================
function UpdateConditions takes nothing returns nothing
    set gCond_Food_A = ( FoodUsed(  ) >= 14 )
    set gCond_Food_B = ( FoodUsed(  ) >= 28 )
    set gCond_Food_C = ( FoodUsed(  ) >= 42 )
    set gCond_Food_D = ( FoodUsed(  ) >= 86 )
    set gCond_Food_E = ( FoodUsed(  ) >= 100 )
    set gCond_Food_F = ( FoodUsed(  ) >= 114 )
    set gCond_Food_G = ( FoodUsed(  ) >= 122 )
    set gCond_Justify_Expansion = ( GetMinesOwned(  ) == 1 )
    set gCond_Justify_More_Workers = ( GetUnitCount( 'egol' ) > 1 )
    set gCond_Hero_A = ( GetUnitCountDone( 'nnad' ) >= 1 )
   
    if gCond_Debug then
        call Msg("==========================")
        call Msg(("Justify more workers: " + B2S(gCond_Justify_More_Workers)))
        call Msg(("Number of mine units: " + Int2Str(GetUnitCount( 'egol' )) + " || Number of done mine units: " + Int2Str(GetUnitCountDone( 'egol' ))))
        call Msg("==========================")
    endif
endfunction

//***************************************************************************
//*
//*  Heroes
//*
//***************************************************************************

//===========================================================================
// Stores hero ID and skills
//===========================================================================
function SetHero takes integer order, integer heroid returns nothing
    if (order == 1) then
        set hero_id = heroid
        if (heroid == 'O009') then
            set skills1[ 1] = 'A033'
            set skills1[ 2] = 'A04V'
            set skills1[ 3] = 'A029'
            set skills1[ 4] = 'A033'
            set skills1[ 5] = 'A04V'
            set skills1[ 6] = 'A00S'
            set skills1[ 7] = 'A029'
            set skills1[ 8] = 'A033'
            set skills1[ 9] = 'A04V'
            set skills1[10] = 'A029'
        elseif (heroid == 'E006') then
            set skills1[ 1] = 'A04Z'
            set skills1[ 2] = 'A0A9'
            set skills1[ 3] = 'A09B'
            set skills1[ 4] = 'A04Z'
            set skills1[ 5] = 'A0A9'
            set skills1[ 6] = 'A09R'
            set skills1[ 7] = 'A09B'
            set skills1[ 8] = 'A04Z'
            set skills1[ 9] = 'A0A9'
            set skills1[10] = 'A09B'
        elseif (heroid == 'H00N') then
            set skills1[ 1] = 'A02V'
            set skills1[ 2] = 'A08K'
            set skills1[ 3] = 'A05B'
            set skills1[ 4] = 'A02V'
            set skills1[ 5] = 'A08K'
            set skills1[ 6] = 'A038'
            set skills1[ 7] = 'A05B'
            set skills1[ 8] = 'A02V'
            set skills1[ 9] = 'A08K'
            set skills1[10] = 'A05B'
        endif
    elseif (order == 2) then
        set hero_id2 = heroid
        if (heroid == 'O009') then
            set skills2[ 1] = 'A033'
            set skills2[ 2] = 'A04V'
            set skills2[ 3] = 'A029'
            set skills2[ 4] = 'A033'
            set skills2[ 5] = 'A04V'
            set skills2[ 6] = 'A00S'
            set skills2[ 7] = 'A029'
            set skills2[ 8] = 'A033'
            set skills2[ 9] = 'A04V'
            set skills2[10] = 'A029'
        elseif (heroid == 'E006') then
            set skills2[ 1] = 'A04Z'
            set skills2[ 2] = 'A0A9'
            set skills2[ 3] = 'A09B'
            set skills2[ 4] = 'A04Z'
            set skills2[ 5] = 'A0A9'
            set skills2[ 6] = 'A09R'
            set skills2[ 7] = 'A09B'
            set skills2[ 8] = 'A04Z'
            set skills2[ 9] = 'A0A9'
            set skills2[10] = 'A09B'
        elseif (heroid == 'H00N') then
            set skills2[ 1] = 'A02V'
            set skills2[ 2] = 'A08K'
            set skills2[ 3] = 'A05B'
            set skills2[ 4] = 'A02V'
            set skills2[ 5] = 'A08K'
            set skills2[ 6] = 'A038'
            set skills2[ 7] = 'A05B'
            set skills2[ 8] = 'A02V'
            set skills2[ 9] = 'A08K'
            set skills2[10] = 'A05B'
        endif
    elseif (order == 3) then
        set hero_id3 = heroid
        if (heroid == 'O009') then
            set skills3[ 1] = 'A033'
            set skills3[ 2] = 'A04V'
            set skills3[ 3] = 'A029'
            set skills3[ 4] = 'A033'
            set skills3[ 5] = 'A04V'
            set skills3[ 6] = 'A00S'
            set skills3[ 7] = 'A029'
            set skills3[ 8] = 'A033'
            set skills3[ 9] = 'A04V'
            set skills3[10] = 'A029'
        elseif (heroid == 'E006') then
            set skills3[ 1] = 'A04Z'
            set skills3[ 2] = 'A0A9'
            set skills3[ 3] = 'A09B'
            set skills3[ 4] = 'A04Z'
            set skills3[ 5] = 'A0A9'
            set skills3[ 6] = 'A09R'
            set skills3[ 7] = 'A09B'
            set skills3[ 8] = 'A04Z'
            set skills3[ 9] = 'A0A9'
            set skills3[10] = 'A09B'
        elseif (heroid == 'H00N') then
            set skills3[ 1] = 'A02V'
            set skills3[ 2] = 'A08K'
            set skills3[ 3] = 'A05B'
            set skills3[ 4] = 'A02V'
            set skills3[ 5] = 'A08K'
            set skills3[ 6] = 'A038'
            set skills3[ 7] = 'A05B'
            set skills3[ 8] = 'A02V'
            set skills3[ 9] = 'A08K'
            set skills3[10] = 'A05B'
        endif
    endif
endfunction

//===========================================================================
// Selects hero IDs for three possible heroes
//===========================================================================
function SelectHeroes takes nothing returns nothing
    local integer roll = GetRandomInt(1,100)
    if (roll <= 17) then
        call SetHero( 1, 'O009' )
        call SetHero( 2, 'E006' )
        call SetHero( 3, 'H00N' )
    elseif (roll <= 34) then
        call SetHero( 1, 'O009' )
        call SetHero( 2, 'H00N' )
        call SetHero( 3, 'E006' )
    elseif (roll <= 50) then
        call SetHero( 1, 'E006' )
        call SetHero( 2, 'O009' )
        call SetHero( 3, 'H00N' )
    elseif (roll <= 67) then
        call SetHero( 1, 'E006' )
        call SetHero( 2, 'H00N' )
        call SetHero( 3, 'O009' )
    elseif (roll <= 84) then
        call SetHero( 1, 'H00N' )
        call SetHero( 2, 'O009' )
        call SetHero( 3, 'E006' )
    else
        call SetHero( 1, 'H00N' )
        call SetHero( 2, 'E006' )
        call SetHero( 3, 'O009' )
    endif
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 building priorities for workers
//===========================================================================
function BuildPriorities takes nothing returns nothing
    local integer mine = TownWithMine()
    if (gCond_Food_A) then
        call SetBuildAll( BUILD_UNIT, 1, 'nntg', -1 )
    endif
    if (gCond_Food_B) then
        call SetBuildAll( BUILD_UNIT, 2, 'nntg', -1 )
    endif
    if (gCond_Food_C) then
        call SetBuildAll( BUILD_UNIT, 3, 'nntg', -1 )
    endif
    if (gCond_Food_D) then
        call SetBuildAll( BUILD_UNIT, 4, 'nntg', -1 )
    endif
    if (gCond_Food_E) then
        call SetBuildAll( BUILD_UNIT, 5, 'nntg', -1 )
    endif
    if (gCond_Hero_A) then
        call SetBuildAll( BUILD_UNIT, 1, hero_id, -1 )
    endif
    call SetBuildAll( BUILD_UNIT, 1, 'etol', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 2, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 3, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 4, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 5, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 6, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 7, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 8, 'ewsp', -1 )
    if (gCond_Justify_More_Workers) then
        call SetBuildAll( BUILD_UNIT, 9, 'ewsp', -1 )
        call SetBuildAll( BUILD_UNIT, 10, 'ewsp', -1 )
        call SetBuildAll( BUILD_UNIT, 11, 'ewsp', -1 )
        call SetBuildAll( BUILD_UNIT, 12, 'ewsp', -1 )
        call SetBuildAll( BUILD_UNIT, 13, 'ewsp', -1 )
        if gCond_Debug then
            call Msg("==========================")
            call Msg("Build loop: making extra workers.")
            call Msg("==========================")
        endif
    endif
    call SetBuildAll( BUILD_UNIT, 1, 'nnad', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'nnsg', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'n005', -1 )
    call SetBuildAll( BUILD_UNIT, 2, 'nnsg', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'Rnam', -1 )
    if (gCond_Food_C) then
        call SetBuildAll( BUILD_UNIT, 1, 'etoa', -1 )
    endif
    if (gCond_Justify_Expansion) then
        call BuildExpansion( 'etol', 'etol' )
    endif
    call SetBuildAll( BUILD_UPGRADE, 1, 'Rnat', -1 )
endfunction

//===========================================================================
// Specifies harvesting priorities for workers
//===========================================================================
function HarvestPriorities takes nothing returns nothing
    local integer mine = TownWithMine()
    local integer allGold = GetUnitCountDone('ewsp')
    local integer allWood = GetUnitCountDone('ewsp')
    local integer numWorkers
    set numWorkers = 5
    call HarvestGold( mine + 0, numWorkers )
    set numWorkers = 5
    call HarvestGold( mine + 1, numWorkers )
    set numWorkers = 5
    call HarvestGold( mine + 2, numWorkers )
    set numWorkers = 5
    call HarvestGold( mine + 3, numWorkers )
    set numWorkers = allWood - awWood
    if (numWorkers > 0) then
        call HarvestWood( mine, numWorkers )
    endif
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

//***************************************************************************
//*
//*  Attacking
//*
//***************************************************************************

//===========================================================================
// Returns true if the minimum forces for an attack exist
//===========================================================================
function HaveMinimumAttackers takes nothing returns boolean
    local integer count

    // Check for attack wave limit
    if (attackWave > 20) then
        return false
    endif

    // Attack Group: All Units
    // No specific minimums exist, checking for at least one unit
    set count = 0
    set count = count + GetUnitCountDone(hero_id)
    set count = count + GetUnitCountDone(hero_id2)
    set count = count + GetUnitCountDone(hero_id3)
    set count = count + GetUnitCountDone('efdr')
    set count = count + GetUnitCountDone('h00D')
    set count = count + GetUnitCountDone('nsnp')
    set count = count + GetUnitCountDone('n00Q')
    set count = count + GetUnitCountDone('nwgs')
    set count = count + GetUnitCountDone('n01E')
    set count = count + GetUnitCountDone('nmyr')
    set count = count + GetUnitCountDone('nnsw')
    set count = count + GetUnitCountDone('nhyc')
    set count = count + GetUnitCountDone('n00E')
    set count = count + GetUnitCountDone('n00T')
    set count = count + GetUnitCountDone('n01D')
    set count = count + GetUnitCountDone('n007')
    if (count < 1) then
        return false
    endif
    return true
endfunction

//===========================================================================
// Assigns units to attack based on the given attack group
//===========================================================================
function PrepareAttackGroup takes integer groupID returns nothing
    local integer all

    // Attack Group #1: All Units
    if (groupID == 1) then
        set all = GetUnitCountDone( hero_id )
        call AddAttackUnit( all, all, hero_id )
        set all = GetUnitCountDone( hero_id2 )
        call AddAttackUnit( all, all, hero_id2 )
        set all = GetUnitCountDone( hero_id3 )
        call AddAttackUnit( all, all, hero_id3 )
        set all = GetUnitCountDone( 'efdr' )
        call AddAttackUnit( all, all, 'efdr' )
        set all = GetUnitCountDone( 'h00D' )
        call AddAttackUnit( all, all, 'h00D' )
        set all = GetUnitCountDone( 'nsnp' )
        call AddAttackUnit( all, all, 'nsnp' )
        set all = GetUnitCountDone( 'n00Q' )
        call AddAttackUnit( all, all, 'n00Q' )
        set all = GetUnitCountDone( 'nwgs' )
        call AddAttackUnit( all, all, 'nwgs' )
        set all = GetUnitCountDone( 'n01E' )
        call AddAttackUnit( all, all, 'n01E' )
        set all = GetUnitCountDone( 'nmyr' )
        call AddAttackUnit( all, all, 'nmyr' )
        set all = GetUnitCountDone( 'nnsw' )
        call AddAttackUnit( all, all, 'nnsw' )
        set all = GetUnitCountDone( 'nhyc' )
        call AddAttackUnit( all, all, 'nhyc' )
        set all = GetUnitCountDone( 'n00E' )
        call AddAttackUnit( all, all, 'n00E' )
        set all = GetUnitCountDone( 'n00T' )
        call AddAttackUnit( all, all, 'n00T' )
        set all = GetUnitCountDone( 'n01D' )
        call AddAttackUnit( all, all, 'n01D' )
        set all = GetUnitCountDone( 'n007' )
        call AddAttackUnit( all, all, 'n007' )

    endif
endfunction

//===========================================================================
// Prepares an attack group based on the current attack wave
//===========================================================================
function PrepareForces takes nothing returns nothing
    if (attackWave == 1) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 2) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 3) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 4) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 5) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 6) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 7) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 8) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 9) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 10) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 11) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 12) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 13) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 14) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 15) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 16) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 17) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 18) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 19) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 20) then
        call PrepareAttackGroup( 1 )
    endif
endfunction

//===========================================================================
// Sleep delays for each attack wave
//===========================================================================
function AttackWaveDelay takes integer inWave returns nothing
    if (inWave < nextDelay) then
        return
    endif

    if (inWave == 0) then
        call Sleep( 200 )
    elseif (inWave == 1) then
        call Sleep( 80 )
    elseif (inWave == 2) then
        call Sleep( 80 )
    elseif (inWave == 3) then
        call Sleep( 80 )
    elseif (inWave == 4) then
        call Sleep( 80 )
    elseif (inWave == 5) then
        call Sleep( 80 )
    elseif (inWave == 6) then
        call Sleep( 80 )
    elseif (inWave == 7) then
        call Sleep( 80 )
    elseif (inWave == 8) then
        call Sleep( 80 )
    elseif (inWave == 9) then
        call Sleep( 80 )
    elseif (inWave == 10) then
        call Sleep( 80 )
    elseif (inWave == 11) then
        call Sleep( 80 )
    elseif (inWave == 12) then
        call Sleep( 80 )
    elseif (inWave == 13) then
        call Sleep( 80 )
    elseif (inWave == 14) then
        call Sleep( 80 )
    elseif (inWave == 15) then
        call Sleep( 80 )
    elseif (inWave == 16) then
        call Sleep( 80 )
    elseif (inWave == 17) then
        call Sleep( 80 )
    elseif (inWave == 18) then
        call Sleep( 80 )
    elseif (inWave == 19) then
        call Sleep( 80 )
    elseif (inWave == 20) then
        call Sleep( 80 )
    endif

    set nextDelay = inWave + 1
endfunction

//===========================================================================
// Advances attack wave counter
//===========================================================================
function AttackWaveUpdate takes nothing returns nothing
    call AttackWaveDelay( attackWave )
    set attackWave = attackWave + 1
    if (attackWave > 20) then
        set attackWave = 1
        set nextDelay = attackWave + 1
    endif
endfunction

//===========================================================================
// Basic attack functionality
//===========================================================================
function AttackTarget takes unit target, boolean addAlliance returns nothing
    if (target == null) then
        return
    endif
    if (addAlliance) then
        call SetAllianceTarget( target )
    endif
    call FormGroup( 3, true )
    call AttackMoveKillA( target )
    if (not addAlliance) then
        call SetAllianceTarget( null )
    endif
endfunction

//===========================================================================
// Initiates an attack based on target priorities
//===========================================================================
function LaunchAttack takes nothing returns nothing
    local unit target = null
    local boolean setAlly = true

    // Don't launch any attack while town is threatened
    if (TownThreatened()) then
        call Sleep( 2 )
        return
    endif

    // Target Priority #1
    if (target == null) then
        set target = GetAllianceTarget()
        if (target != null) then
            set setAlly = false
        endif
    endif

    // Target Priority #2
    if (gCond_Food_C) then
        if (target == null) then
            set target = GetExpansionFoe()
            if (target != null) then
                set take_exp = false
            endif
        endif

        // Target Priority #3
    endif
    if (target == null) then
        set target = GetMegaTarget()
    endif

    // Target Priority #4
    if (target == null) then
        set target = GetEnemyExpansion()
    endif

    // Target Priority #5
    if (target == null) then
        set target = GetEnemyExpansion()
        if (target == null) then
            call StartGetEnemyBase(  )
            loop
                exitwhen (not WaitGetEnemyBase())
                call SuicideSleep( 1 )
            endloop
            set target = GetEnemyBase()
        endif
    endif

    // Target Priority #6
    if (target == null) then
        set target = GetCreepCamp( 0, 9, false )
    endif

    // Target Priority #7
    if (gCond_Food_C) then
        if (target == null) then
            set target = GetCreepCamp( 10, 100, true )
        endif

    endif
    // Attack the target and increment attack wave
    if (target != null) then
        call AttackTarget( target, setAlly )
        call AttackWaveUpdate(  )
    else
        // If no target was found, sleep a bit before trying again
        call Sleep( 20 )
    endif
endfunction

//===========================================================================
// Determines all attacking assignments
//===========================================================================
function AttackAssignment takes nothing returns nothing
    call StaggerSleep( 0, 2 )
    if (attackWave == 1) then
        call AttackWaveDelay( 0 )
    endif
    loop
        loop
            call UpdateConditions(  )
            exitwhen (HaveMinimumAttackers() and not CaptainRetreating())
            call Sleep( 2 )
        endloop
        call ResetAttackUnits(  )
        call PrepareForces(  )
        call LaunchAttack(  )
    endloop
endfunction

//===========================================================================
// Debug loop
//===========================================================================

function DebugLoop takes nothing returns nothing
    loop
        call WaitForSignal()
        set gCond_Debug = not gCond_Debug
    endloop
endfunction

//***************************************************************************
//*
//*  Main Entry Point
//*
//***************************************************************************

//===========================================================================
function main takes nothing returns nothing
    call InitAI(  )
    call SetPlayerName( ai_player, "Shellgan" )
    call InitOptions(  )
    call SelectHeroes(  )
    call CreateCaptains(  )
    call SetHeroLevels( function ChooseHeroSkill )

    call Sleep( 0.1 )
    call StartThread( function WorkerAssignment )
    call StartThread( function AttackAssignment )
    call StartThread( function DebugLoop        )
    call PlayGame(  )
endfunction
 
Nowow is right, but if you wanted to preserve the build order so that the altar and spawning grounds would still be built prior to the 6-8th worker, you could create a local variable like this:

JASS:
function BuildPriorities takes nothing returns nothing
    local integer mine = TownWithMine()
    local integer workersCount = 0
    if (gCond_Food_A) then
        call SetBuildAll( BUILD_UNIT, 1, 'nntg', -1 )
    endif
    if (gCond_Food_B) then
        call SetBuildAll( BUILD_UNIT, 2, 'nntg', -1 )
    endif
    if (gCond_Food_C) then
        call SetBuildAll( BUILD_UNIT, 3, 'nntg', -1 )
    endif
    if (gCond_Food_D) then
        call SetBuildAll( BUILD_UNIT, 4, 'nntg', -1 )
    endif
    if (gCond_Food_E) then
        call SetBuildAll( BUILD_UNIT, 5, 'nntg', -1 )
    endif
    if (gCond_Hero_A) then
        call SetBuildAll( BUILD_UNIT, 1, hero_id, -1 )
    endif
    call SetBuildAll( BUILD_UNIT, 1, 'etol', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 2, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 3, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 4, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 5, 'ewsp', -1 )
    set workersCount = 5
    if (gCond_Justify_More_Workers) then
        call SetBuildAll( BUILD_UNIT, 6, 'ewsp', -1 )
        call SetBuildAll( BUILD_UNIT, 7, 'ewsp', -1 )
        call SetBuildAll( BUILD_UNIT, 8, 'ewsp', -1 )
        call SetBuildAll( BUILD_UNIT, 9, 'ewsp', -1 )
        call SetBuildAll( BUILD_UNIT, 10, 'ewsp', -1 )
        set workersCount = 10
    endif
    call SetBuildAll( BUILD_UNIT, 1, 'nnad', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'nnsg', -1 )
    // set the number of works to build equal to 6, or 11,
    //conditionally based on the previous value of workersCount
    set workersCount = workersCount + 1
    call SetBuildAll( BUILD_UNIT, workersCount, 'ewsp', -1 )
    set workersCount = workersCount + 1
    call SetBuildAll( BUILD_UNIT, workersCount, 'ewsp', -1 )
    set workersCount = workersCount + 1
    call SetBuildAll( BUILD_UNIT, workersCount, 'ewsp', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'n005', -1 )
    call SetBuildAll( BUILD_UNIT, 2, 'nnsg', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'Rnam', -1 )
    if (gCond_Food_C) then
        call SetBuildAll( BUILD_UNIT, 1, 'etoa', -1 )
    endif
    if (gCond_Justify_Expansion) then
        call BuildExpansion( 'etol', 'etol' )
    endif
    call SetBuildAll( BUILD_UPGRADE, 1, 'Rnat', -1 )
endfunction
 
Status
Not open for further replies.
Top