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

[AI] Catch backrun commands

Status
Not open for further replies.
Level 6
Joined
Aug 22, 2008
Messages
123
Hello everyone

I already succeeded in customizing the buildorder and optimizing a lot of processes, but I'm slowly getting fed up with the ai's stupid moves like always keeping a bear back in base, not defending the expansion in several cases, not saving lowlife heros and so on.
Using TPs and simple commands are easy for me to do, but having that long list of automatically generated script code that somewhere contains points like running back after having done a creepspot or attack, I cannot find out how or at least where to modify it.

Thanks for reading, I need useful hints, basic spam is not wanted.
 
Level 6
Joined
Aug 22, 2008
Messages
123
Sorry, but that is far not what i requested.
I got that common.ai and use a lot of commands out of it and tracked the functions of automatically generated functioncalls in the ai script using Jasscraft, but i just cannot seperate the systems and functions that cause things like running back. My request is a short explanation about the basic system to know how to modify it. There are way too many different and stupidly named variables, that sometimes even do not appear anywhere except the common.ai.:wink:

//Edit:
To show you what I'm talking about:

JASS:
globals
    
    integer                 MaxWisps                    =13
    
    unit                    Main                        =null
    
    boolean                 T2Started                   =false
    boolean                 T3Started                   =false
    
    integer                 attackWave                 = 1
    integer                 nextDelay                  = 0
    integer                 awGold                     = 0
    integer                 awWood                     = 0
    
    // Conditions
    boolean                 gCond_Ready_to_Upgrade1    = false
    boolean                 gCond_Ready_to_Upgrade2    = false
    boolean                 gCond_SchwacheCamps        = false
    boolean                 gCond_MittelCamps          = false
    boolean                 gCond_T1_Damageup          = false
    boolean                 BuildingsT2T3              = false
    boolean                 gCond_ExeDefBauen          = false
    boolean                 gCond_Third_hero           = false
    boolean                 gCond_MittelCampsStaerker  = false
    boolean                 gCond_T1_DefenseUp         = false
    boolean                 gCond_ExeBauen             = false
    boolean                 gCond_Keine_Resourcen_Angriff = false
    boolean                 AOLsStehen                  =false
    boolean                 GegnerExe                   =false
    boolean                 Hunthall                    =false
    boolean                 T3Schritt2                  =false
    boolean                 T3                          = false
endglobals

.
.
.

//***************************************************************************
//*
//*  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 > 1) then
        return false
    endif
    
    // First Hero Only
    if (GetUnitCountDone(hero_id) < 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: Alle Einheiten
    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( 'earc' )
        call AddAttackUnit( all, all, 'earc' )
        set all = GetUnitCountDone( 'ebal' )
        call AddAttackUnit( all, all, 'ebal' )
        set all = GetUnitCountDone( 'echm' )
        call AddAttackUnit( all, all, 'echm' )
        set all = GetUnitCountDone( 'edoc' )
        call AddAttackUnit( all, all, 'edoc' )
        set all = GetUnitCountDone( 'edot' )
        call AddAttackUnit( all, all, 'edot' )
        set all = GetUnitCountDone( 'edry' )
        call AddAttackUnit( all, all, 'edry' )
        set all = GetUnitCountDone( 'efdr' )
        call AddAttackUnit( all, all, 'efdr' )
        set all = GetUnitCountDone( 'ehip' )
        call AddAttackUnit( all, all, 'ehip' )
        set all = GetUnitCountDone( 'ehpr' )
        call AddAttackUnit( all, all, 'ehpr' )
        set all = GetUnitCountDone( 'emtg' )
        call AddAttackUnit( all, all, 'emtg' )
        set all = GetUnitCountDone( 'esen' )
        call AddAttackUnit( all, all, 'esen' )
        
    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 )
    endif
endfunction

//===========================================================================
// Sleep delays for each attack wave
//===========================================================================
function AttackWaveDelay takes integer inWave returns nothing
    if (inWave < nextDelay) then
        return
    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 > 1) 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 (GegnerExe) then
        set target = GetEnemyExpansion()
    endif
    
    if (gCond_ExeBauen) then
        if (target == null) then
            set target = GetExpansionFoe()
            if (target != null) then
                set take_exp = false
            endif
        endif
        
        // Target Priority #5
    endif
    
    // Target Priority #8
    if (gCond_MittelCamps) then
        if (target == null) then
            set target = GetCreepCamp( 6, 14, false )
        endif
        
        // Target Priority #9
    endif
    
    
    // Target Priority #2
    if (gCond_Keine_Resourcen_Angriff) then
        if (target == null) then
            set target = GetAllianceTarget()
            if (target != null) then
                set setAlly = false
            endif
        endif
        
        // Target Priority #3
        if (target == null) then
            set target = GetMegaTarget()
        endif
        
        // Target Priority #4
    endif
    
    if (gCond_MittelCampsStaerker) then
        if (target == null) then
            set target = GetCreepCamp( 1, 16, false )
        endif
        
        // Target Priority #6
    endif
    
    if (target == null) then
        set target = GetAllianceTarget()
        if (target != null) then
            set setAlly = false
        endif
    endif
    // Target Priority #7
    if (target == null) then
        set target = GetMegaTarget()
    endif
    
    
    
    if (gCond_SchwacheCamps) then
        if (target == null) then
            set target = GetCreepCamp( 0, 11, false )
        endif
        
        // Target Priority #10
    endif
    if (target == null) then
        set target = GetCreepCamp( 14, 100, true )
    endif
    
    // Target Priority #11
    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
    
    // 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( 5 )
    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 RemoveInjuries(  )
        call ResetAttackUnits(  )
        call PrepareForces(  )
        call LaunchAttack(  )
    endloop
endfunction
 
Level 6
Joined
Aug 22, 2008
Messages
123
*push*
Those are the functions that are being used as basics, but they do not contain the backrun command. Is that a basic command that cannot be edited?:hohum:


JASS:
function AttackMoveKillA takes unit target returns nothing
    if target == null then
        call SuicideSleep(3)
        return
    endif

    debug call Trace("AttackMoveKillA\n")
    call AttackMoveKill(target)
    call ReformUntilTargetDead(target)
    call SleepInCombat()
endfunction


function SleepInCombat takes nothing returns nothing
    local integer count = 0
    debug call Trace("SleepInCombat\n")
    loop
        loop
            exitwhen not CaptainInCombat(true)  // goal is cleared
            exitwhen CaptainIsEmpty()           // duh
            call SuicideSleep(1)
        endloop

        set count = count + 1
        exitwhen count >= 8

        //xxx this is what it should have been; do this for next patch?
        //call SuicideSleep(1)
    endloop
    debug call Trace("exit SleepInCombat\n")
endfunction

function ReformUntilTargetDead takes unit target returns nothing
    debug call Trace("ReformUntilTargetDead\n")
    call CommonSleepUntilTargetDead(target,true)
endfunction

function CommonSleepUntilTargetDead takes unit target, boolean reform returns nothing
    loop
        exitwhen CaptainRetreating()
        exitwhen CaptainReadinessHP() <= 40

        exitwhen not UnitAlive(target)
        exitwhen UnitInvis(target) and not IsUnitDetected(target,ai_player)

        if not TownThreatened() then
            call AttackMoveKill(target)
        endif

        call SuicideSleep(3)

        if reform and sleep_seconds < -40 then
            if CaptainInCombat(true) then
                set sleep_seconds = sleep_seconds + 5
            else
                set sleep_seconds = 0
                call FormGroup(1,false)
            endif
        endif
    endloop
endfunction
 
Level 6
Joined
Aug 22, 2008
Messages
123
Ok I'm slowly getting fed up with this... the question was "where can i find and modify the basic backrun command after battles". Do you really think that your MPQ datas got anything to do with that issue? No, they dont.
Please, start to give me serious hints, I got the impression that I'm the only advanced mapper on AI scripts. Has nobody ever scripted a meele ai before?:hohum:

//Edit: I already taught my AI to use the townportal when it's first hero is in trouble. It IS possible to work with the ai script...
 
Level 13
Joined
Apr 15, 2008
Messages
1,063
I got the impression that I'm the only advanced mapper on AI scripts.
You are propably right about this. It's a pity, since warcraft has one of the best AI editors I have seen (I was thinking about some AI tournament, I will suggest it as contest here, that might get someone iterested in AI)

To your issue, this function:
JASS:
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
you need to remove and not CaptainRetreating(), then he will attack several creep spots in a row.

By the way, I spent very long time getting some debug text off the AI (I gave up eventually). I noticed the Trace system, which is already implemented, but it gives no output, do you know how to get it to work?
 
Level 6
Joined
Aug 22, 2008
Messages
123
You are propably right about this. It's a pity, since warcraft has one of the best AI editors I have seen (I was thinking about some AI tournament, I will suggest it as contest here, that might get someone iterested in AI)

To your issue, this function:
JASS:
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
you need to remove and not CaptainRetreating(), then he will attack several creep spots in a row.

By the way, I spent very long time getting some debug text off the AI (I gave up eventually). I noticed the Trace system, which is already implemented, but it gives no output, do you know how to get it to work?

First of all, thank you for finding out the issue I was asking for. Downcasting all the basic functions, I found a lot, but nothing that could be directly modified.

An AI contest was started on Inwarcraft.de like 2 months ago but the ones organizing the tournament did not do well. My clan is currently doing a 2on2 AI tournament, having real rules and giving help to those that want to take part without any knowledge of the AI editor. I'm tuning one AI at the moment, but this one will not be used for the tournament since this would be unfair to those that do not own the knowledge of Jass.

The trace function is this one:
JASS:
function Trace takes string message returns nothing
    if trace_on then
        call DisplayText(GetAiPlayer(),message)
    endif
endfunction
It may work if you use
JASS:
set trace_on=true
at the start of your AI script, but somehow you may not see anything since the text is displayed to the AI player. Looks like this is having its functionality when being started with mods that are known by blizzard only.:wink:
 
Level 13
Joined
Apr 15, 2008
Messages
1,063
It's nice to know there are some AI tournaments, I would like to participate someday, but I can't even properly play the game, so I the AI's skills would be really limited by my skills :grin:

I knew how the trace looked like, I tried almost everything I could to get the string to display (I even tried setting the message as Player Name, so I could at least see it there), but nothing worked. Also I tried viewing replay (since the messages display only to the AI player, and in playback you can "be" the same player as IA), but replays don't work properly these days. I just wasn't able to get the debug text off the AI, no matter how hard I tried.
 
Status
Not open for further replies.
Top