• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

[AI] AI build infinite burrows

Status
Not open for further replies.
Level 4
Joined
Nov 23, 2007
Messages
113
I'm using the AI editor and have it to the point of expanding. I've only set the AI to build 4 burrows in any base, and 1 burrow in the expansion (along with the other buildings).

Eventually, at some point (I think when the first gold mine dies, but not sure) the peons start building an infinite number of burrows - and I mean it gets beyond 40 of them, at the expansion. Sometimes at the main base as well.

Any idea why this might be happening?

After testing a bit more it seems there is no transparent factor as to the cause of this. It doesn't matter what map the AI is tested on, they eventually start making an infinite number of orc burrows.

I've attached the WAI file if someone could have a look and see what might be causing this.

Has no one run into this issue before? :s

Well, I guess my next question is... has anyone managed to get the AI editor to work correctly (or watched long enough to see if they start building infinite burrows)? If so, could you please post your WAI file?

Because I tested the GruntMaster.wai that comes with WC along with the maps that come with WC and the results are the same. Any AI created with the AI editor simply causes the AI to create infinite burrows at some point in the game. I've exported the AI file and see nothing out of place so something appears to be going on elsewhere.

I've reinstalled and made sure there were no ai or other file remnants within the WC folders and I"m at a loss as to why this would be happening other than a serious bug in the AI when the game is set to Melee.


Edit: I've since discovered that this only happens if the computer is instructed to build an expansion. The "bug" does not occur otherwise. Why, I have no idea.

I apologize to the mods for adding yet another post to this thread but I feel it may be important to post my observations so that it acts as a resource for others.

After repeated testing, I believe I have found the cause of the issue (and I'd certainly classify it as a "bug").

If you instruct the AI to build a building at a non-existent town/expansion (including a town/exp with a town hall not yet completed), it will build an infinite amount of them, one after the other.

To resolve this, if you want to build a burrow at an expansion, you can still put it right after the Expansion Town entry but use "(Total number of Great Hall units in Town #n(completed only: True) equal to 1" as the build condition. This way when it builds the burrow, you can be sure the town/expansion has been determined and you are referencing a valid "town".


Additionally, if you instruct the AI to build a fighting unit at a town that does not yet exist (or completed), it will build it at any other currently available location, but will erroneously keep building them until it reaches the available food cap. In addition, the next build order in the list will not be processed.
 

Attachments

  • OrcCreepMaster-tier1.zip
    1.2 KB · Views: 55
Last edited by a moderator:
Level 4
Joined
Nov 23, 2007
Messages
113
Everything is fine until you specify in the AI editor that they build the building/unit in a specific place (like Mine2, or Exp1 etc) and the AI doesn't own the mine yet (or rather, doesn't define it as an owned town).

The only way to prevent it (that I have discovered) is to use a condition that the town has a town hall unit (completed). Odd thing is, they still sometimes build more than exists in the build list (although not infinitely like when using no condition).

You definately have to check every build order for any possible error or condition because if you don't, the last valid build command in the list will be repeated infinitely because it cannot execute the following command. Not the most gracefully handling of an error, I must say.
 

Attachments

  • AI Builds infinite burrows.jpg
    AI Builds infinite burrows.jpg
    125.2 KB · Views: 388
Level 4
Joined
Nov 23, 2007
Messages
113
preventing it from happening is not really the issue but rather trying to resolve the bug and catch it at the source is another issue. I could simply include a condition in each burrow build limiting the number of burrows to 10. However, it would always build 10 burrows even if only 2 are needed.

I was hoping someone had come across this before and discovered the section of code that causes the issue and perhaps came up with a condition that worked within the buggy section to sort of bypass the actual internal error. So far, the only thing that seems to work is to only build the burrow at an expansion once the townhall has been completed (or specify that it can be built in "any" town but then chances are you won't have a burrow at the expansion).
 
Level 5
Joined
Oct 27, 2007
Messages
158
I've been looking at this and found out the problem has to do with how the AI script manages mines. I can't show you the problem without using Jass, so bear with me.

JASS:
//***************************************************************************
//*
//*  Building and Harvesting
//*
//***************************************************************************

//===========================================================================
// Specifies building priorities for workers
//===========================================================================
function BuildPriorities takes nothing returns nothing
    local integer mine = TownWithMine()
    call SetBuildAll( BUILD_UNIT, 1, 'ogre', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'opeo', -1 )
    call SetBuildAll( BUILD_UNIT, 2, 'opeo', -1 )
    call SetBuildAll( BUILD_UNIT, 3, 'opeo', -1 )
    call SetBuildAll( BUILD_UNIT, 4, 'opeo', -1 )
    call SetBuildAll( BUILD_UNIT, 5, 'opeo', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'otrb', -1 )
    call SetBuildAll( BUILD_UNIT, 6, 'opeo', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'obar', -1 )
    call SetBuildAll( BUILD_UNIT, 7, 'opeo', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'oalt', -1 )
    call SetBuildAll( BUILD_UNIT, 8, 'opeo', -1 )
    call SetBuildAll( BUILD_UNIT, 9, 'opeo', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'ogru', -1 )
    call SetBuildAll( BUILD_UNIT, 1, hero_id, -1 )
    call SetBuildAll( BUILD_UNIT, 2, 'otrb', -1 )
    call SetBuildAll( BUILD_UNIT, 2, 'ogru', -1 )
    call SetBuildAll( BUILD_UNIT, 10, 'opeo', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'ofor', -1 )
    call SetBuildAll( BUILD_UNIT, 3, 'ogru', -1 )
    call SetBuildAll( BUILD_UNIT, 3, 'otrb', -1 )
    call SetBuildAll( BUILD_UNIT, 4, 'ogru', -1 )
    call SetBuildAll( BUILD_UNIT, 11, 'opeo', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'ovln', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'ohun', -1 )
    call SetBuildAll( BUILD_UNIT, 2, 'ohun', -1 )
    call SetBuildAll( BUILD_UNIT, 3, 'ohun', -1 )
    call SetBuildAll( BUILD_UNIT, 4, 'ohun', -1 )
    call SetBuildAll( BUILD_UNIT, 12, 'opeo', -1 )
    call SetBuildAll( BUILD_UNIT, 4, 'otrb', -1 )
    call SetBuildAll( BUILD_UNIT, 13, 'opeo', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'Roar', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'Rome', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'Rora', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'Rosp', -1 )
    call SetBuildAll( BUILD_UNIT, 14, 'opeo', -1 )
    call SetBuildAll( BUILD_UNIT, 15, 'opeo', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'ostr', -1 )
    if (gCond_Need_Exp1) then
        call BuildExpansion( 'ogre', 'ogre' )
    endif
    if (gCond_More_peons) then
        call SetBuildAll( BUILD_UNIT, 1, 'opeo', mine + 1 ) // Using mine + 1 is bad
        call SetBuildAll( BUILD_UNIT, 2, 'opeo', mine + 1 ) // Mine + 1 can point to a town that doesn't exist.
        call SetBuildAll( BUILD_UNIT, 3, 'opeo', mine + 1 )
        call SetBuildAll( BUILD_UNIT, 4, 'opeo', mine + 1 )
        call SetBuildAll( BUILD_UNIT, 5, 'opeo', mine + 1 )
    endif
    call SetBuildAll( BUILD_UNIT, 1, 'otrb', mine + 1 )
    call SetBuildAll( BUILD_UNIT, 1, 'owtw', mine + 1 )
    call SetBuildAll( BUILD_UNIT, 2, 'owtw', mine + 1 )
    call SetBuildAll( BUILD_UNIT, 5, 'ogru', -1 )
    call SetBuildAll( BUILD_UNIT, 6, 'ogru', -1 )
    call SetBuildAll( BUILD_UNIT, 7, 'ogru', -1 )
    call SetBuildAll( BUILD_UNIT, 8, 'ogru', -1 )
endfunction
The mine + 1 I think will cause problems when for example your main town goldmine runs out. TownWithMine will then return your first expansion town. That means the expansion you just made. However, it adds one to that mine, which will point to a non existing 2nd expansion, which is bad. The AI in this case doesn't know where to build. The AI editor is very crappy when it comes to dealing with exceptions. The code that Blizzard uses for managing towns is very sloppy. So unfortunately every AI script made with the editor is flawed with it.

There are ways to deal with this with some natives.
TownHasHall(mine + 1) // Returns true when mine + 1 has hall
TownHasMine(mine + 1) // Returns true when mine + 1 has mine

GetNextExpansion() //Returns the next possible expansion spot
So if the number is 3, you have 3 towns already.
0 = main base
1 = first expansion
2 = 2nd expansion

This way you know exactly how many expansions you have. Together with the two other natives (TownHashall, TownHasMine) you can check if its ok to build there.

ps. The snippet of code is the building strategy of your AI script. I strongly recommend coding AI scripts in Jass so you can prevent things like this happening.

As to why the AI script builds infinite amounts of stuff when such exceptions occur. Well it tries to build a fixed amount what you specified in that specific town (mine + 1). However if the exception occured I told you about then there will never be the amount of units in that town because that town doesn't exist. It can never have x amount of burrows in a town which doesn't exist. That's why it will keep building and building until it runs out of resources or is destroyed. All this can be fixed with simple exception checking which Blizzard forgot to do.

I found out by trial and error that this is one of the better ways to manage towns. The GetNextExpansion native isn't a reliable way to retrieve towns, so its better not to use it. The example below doesn't try to build in towns that don't exist, and builds one burrow and two watchtowers at every expansion. It also manages workers in a better way than the AI editor does. Lumber peons are more spread out over towns which have mines. If you want better AI town managent then the AI editor isn't going to cut it.

JASS:
//***************************************************************************
//*
//*  Building and Harvesting
//*
//***************************************************************************

//===========================================================================
// Specifies building priorities for workers
//===========================================================================
function BuildPriorities takes nothing returns nothing
    local integer mines_owned = GetMinesOwned()
    local integer mines_found = 0
    local integer town_id = 0
    local integer peons = 5 * mines_owned

    call SetBuildAll( BUILD_UNIT, 1, 'ogre', -1 )
    call SetBuildAll( BUILD_UNIT, peons, 'opeo', -1) // Build 5 peons for every gold mine owned.
    call SetBuildAll( BUILD_UNIT, 1, 'otrb', -1 )
    call SetBuildAll( BUILD_UNIT, peons + 1, 'opeo', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'obar', -1 )
    call SetBuildAll( BUILD_UNIT, peons + 2, 'opeo', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'oalt', -1 )
    call SetBuildAll( BUILD_UNIT, peons + 3, 'opeo', -1 )
    call SetBuildAll( BUILD_UNIT, peons + 4, 'opeo', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'ogru', -1 )
    call SetBuildAll( BUILD_UNIT, 1, hero_id, -1 )        
    call SetBuildAll( BUILD_UNIT, 2, 'otrb', -1 )
    call SetBuildAll( BUILD_UNIT, 2, 'ogru', -1 )
    call SetBuildAll( BUILD_UNIT, peons + 10, 'opeo', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'ofor', -1 )
    loop
        exitwhen mines_found == mines_owned
        if TownHasMine(town_id) then
            if town_id > 0 and TownHasHall(town_id) then // Only rebuild when it's an active town, to prevent AI from wasting resources
                call SetBuildAll( BUILD_UNIT, 1, 'otrb', town_id) // Build one burrow in every expansions
                call SetBuildAll( BUILD_UNIT, 2, 'owtw', town_id) // Build two watchtowers in every expansion
            endif
            set mines_found = mines_found + 1
        endif
        set town_id = town_id + 1
    endloop
    call SetBuildAll( BUILD_UNIT, 3, 'ogru', -1 )
    call SetBuildAll( BUILD_UNIT, 3, 'otrb', -1 )
    call SetBuildAll( BUILD_UNIT, 4, 'ogru', -1 )
    call SetBuildAll( BUILD_UNIT, 11, 'opeo', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'ovln', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'ohun', -1 )
    call SetBuildAll( BUILD_UNIT, 2, 'ohun', -1 )
    call SetBuildAll( BUILD_UNIT, 3, 'ohun', -1 )
    call SetBuildAll( BUILD_UNIT, 4, 'ohun', -1 )
    call SetBuildAll( BUILD_UNIT, 12, 'opeo', -1 )
    call SetBuildAll( BUILD_UNIT, 4, 'otrb', -1 )
    call SetBuildAll( BUILD_UNIT, 13, 'opeo', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'Roar', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'Rome', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'Rora', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'Rosp', -1 )
    call SetBuildAll( BUILD_UNIT, 14, 'opeo', -1 )
    call SetBuildAll( BUILD_UNIT, 15, 'opeo', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'ostr', -1 )
    if gCond_Need_Exp1 then
        call BuildExpansion('ogre', 'ogre')
    endif
    call SetBuildAll( BUILD_UNIT, 5, 'ogru', -1 )
    call SetBuildAll( BUILD_UNIT, 6, 'ogru', -1 )
    call SetBuildAll( BUILD_UNIT, 7, 'ogru', -1 )
    call SetBuildAll( BUILD_UNIT, 8, 'ogru', -1 )
endfunction

//===========================================================================
// Specifies harvesting priorities for workers
//===========================================================================
function HarvestPriorities takes nothing returns nothing
    local integer mines_owned = GetMinesOwned()
    local integer mines_found = 0
    local integer town_id = 0
    local integer peons_total = GetUnitCountDone('opeo')
    local integer gold_peons = 5 * mines_owned
    local integer wood_peons = 10
    local integer on_gold = 5
    local integer on_wood = 0

    if gold_peons > peons_total then
        set gold_peons = peons_total
    endif
    set wood_peons = peons_total - gold_peons
    if wood_peons > 0 and mines_owned > 0 then
        set on_wood = wood_peons / mines_owned
        set on_wood = on_wood + wood_peons - (on_wood * mines_owned)
    endif
    loop
        exitwhen mines_found == mines_owned
        if TownHasMine(town_id) then
            if gCond_Wood_Low then
                set on_gold = on_gold - 2
                set on_wood = on_wood + 2
            elseif gCond_Wood_Medium then
                set on_gold = on_gold - 1
                set on_wood = on_wood + 1
            endif
            call HarvestGold(town_id, on_gold)
            call HarvestWood(town_id, on_wood)
            set mines_found = mines_found + 1
        endif
        set town_id = town_id + 1
    endloop
endfunction
 
Last edited:
Level 4
Joined
Nov 23, 2007
Messages
113
Drone, I apologize for not responding sooner. Don't want you to think your post was ignored. I thought I was subscribed to this thread and when I never received any more emails that there were replies to this thread, I stopped checking.

Much appreciated for you taking the time to go over it and work out some of the logic. Thanks

+rep
 
Status
Not open for further replies.
Top