vJASS & Zinc Documentation
For the latest documentation about how it works vJASS and Zinc language layers for Warcraft III, please follow these links:
Jasshelper documentation - Zinc documentation - WC3 Optimizer documentation

[AI] How AI work

Starquizer · 11861

0 Members and 1 Guest are viewing this topic.

[AI] How AI work
on: January 13, 2013, 03:27:08 PM

Hello, moyackx.

Now, I am hoping to discuss thing about AI. I really don't know why so many are not interested in it.

Anyways, you were saying something about building up some kind of table, does that mean I can't command the AI to build a certain building, lets say 2 Ancient of War then later increase them to 4 ? because I make something like that and it worked:

Code: jass
  1. function main takes nothing returns nothing
  2.     call CampaignAI( MOON_WELL, function hero_levels )
  3.     call SetWoodPeons(4)
  4.     //call AttackMoveXY(-6500,-6500) // Just a signal to detect if the AI is working or not
  5.         //call PurchaseZeppelin()
  6.    
  7.     call SetBuildUnitEx( 9, 9, 9, WISP         )
  8.     call SetBuildUnitEx( 1, 1, 1, TREE_LIFE    )
  9.  
  10.     call SetBuildUnitEx( 1, 1, 1, ANCIENT_WAR  )
  11.     call SetBuildUnitEx( 1, 1, 1, ELF_ALTAR    )
  12.     call SetBuildUnitEx( 1, 1, 1, HUNTERS_HALL )
  13.     call SetBuildUnitEx( 2, 2, 2, ANCIENT_WAR  )
  14.     call SetBuildUnitEx( 2, 2, 2, ELF_ALTAR    )
  15.     call SetBuildUnitEx( 2, 2, 2, HUNTERS_HALL )
  16.     call SetBuildUnitEx( 4, 4, 4, ANCIENT_WAR  )
  17. endfunction
  18.  




[AI] How AI work
Reply #1 on: January 13, 2013, 08:06:58 PM

That's right. If you check the code behind SetBuildUnitEx() you'll see the following:

Code: jass
  1. function SetBuildUnitEx takes integer easy, integer med, integer hard, integer unitid returns nothing
  2.     if difficulty == EASY then
  3.         call SetBuildAll(BUILD_UNIT,easy,unitid,-1)
  4.     elseif difficulty == NORMAL then
  5.         call SetBuildAll(BUILD_UNIT,med,unitid,-1)
  6.     else
  7.         call SetBuildAll(BUILD_UNIT,hard,unitid,-1)
  8.     endif
  9. endfunction

And SetBuildAll() does this:

Code: jass
  1. function SetBuildAll takes integer t, integer qty, integer unitid, integer town returns nothing
  2.     if qty > 0 then
  3.         set build_qty[build_length] = qty
  4.         set build_type[build_length] = t
  5.         set build_item[build_length] = unitid
  6.         set build_town[build_length] = town
  7.         set build_length = build_length + 1
  8.     endif
  9. endfunction

In conclusion these functions actually are not giving orders directly, instead they fill a table that the AI internally will be checking and following, the dynamic of this functions is seen in the fact that we add or remove priorities (orders) according to situations.

I've been trying to develop a super AI but the big issue has been this feature, if you change dramatically the table between every Sleep(), the AI will get unresponsive or arbitrary and it will fail.


[AI] How AI work
Reply #2 on: January 14, 2013, 06:38:33 AM

So that concludes that campaign AI are critically stable and fragile and special care should be taken when making one.

I have lots of question about AI but lets not put them in one post, most importantly, can I use common.ai defined globals in my triggers to track their values as it seems that the function I2S don't work in AI files.



[AI] How AI work
Reply #3 on: January 14, 2013, 08:16:41 AM

So that concludes that campaign AI are critically stable and fragile and special care should be taken when making one.
And not only campaign AI, melee AI is affected too because they use both procedures.

Quote
I have lots of question about AI but lets not put them in one post, most importantly, can I use common.ai defined globals in my triggers to track their values as it seems that the function I2S don't work in AI files.
Unfortunately not, because these globals are only valid per AI player. But you can get integers from triggers using the Commands functions.


[AI] How AI work
Reply #4 on: January 14, 2013, 09:26:47 AM

But you can get integers from triggers using the Commands functions.

I made a trigger to send AI signal command to stop an attack when the enemy is destroyed to learn how to use commands and I did something like that but it doesn't work and I don't get the message.

Code: jass
  1. globals
  2.     player MyVictim = Player(2) // Player 3 (Teal)
  3. endglobals
  4.  
  5. function hero_levels takes nothing returns integer
  6.     local integer hero  = GetHeroId()
  7.     local integer level = GetHeroLevelAI()
  8.     local integer a = 0
  9.     if hero == DEMON_HUNTER then
  10.         if level == 1 or level == 3 or level == 5 then
  11.             set a = IMMOLATION
  12.         endif
  13.         if level == 2 or level == 4 or level == 7 then
  14.             set a = EVASION
  15.         endif
  16.         if level >= 8 then
  17.             set a = MANA_BURN
  18.         endif
  19.         if level == 6 then
  20.             set a = METAMORPHOSIS
  21.         endif
  22.     endif
  23.     if hero == MOON_CHICK then
  24.         if level == 1 or level == 3 or level == 5 then
  25.             set a = TRUESHOT
  26.         endif
  27.         if level == 2 or level == 4 or level == 7 then
  28.             set a = SEARING_ARROWS
  29.         endif
  30.         if level >= 8 then
  31.             set a = SCOUT
  32.         endif
  33.         if level == 6 then
  34.             set a = STARFALL
  35.         endif
  36.     endif
  37.     return a
  38. endfunction
  39.  
  40. function stopAttack takes nothing returns boolean
  41.     local integer cmd = GetLastCommand()
  42.     call PopLastCommand()
  43.     if cmd == 2 then
  44.         return true
  45.     endif
  46.     return false
  47. endfunction
  48.  
  49. function main takes nothing returns nothing
  50.     call CampaignAI( MOON_WELL, function hero_levels )
  51.     call DisplayTextToPlayer(Player(0),0,0,"AI Started")
  52.     call SetBuildUnitEx( 1, 1, 1, TREE_LIFE    )
  53.     call SetBuildUnitEx( 8, 8, 8, ANCIENT_WAR  )
  54.     call SetBuildUnitEx( 2, 2, 2, ELF_ALTAR    )
  55.     call SetBuildUnitEx( 1, 1, 1, HUNTERS_HALL )
  56.     //•••••••••••••••••••••••••••••••••••••••••
  57.     //•               DEFENDERS               •
  58.     //•••••••••••••••••••••••••••••••••••••••••
  59.     call CampaignDefenderEx( 1, 1, 1, MOON_CHICK )
  60.     call CampaignDefenderEx( 10, 10, 10, ARCHER     )
  61.     call CampaignDefenderEx( 10, 10, 10, HUNTRESS   )
  62.     //call Sleep(10)    
  63.     //•     WAVE #5+    •\\
  64.     loop
  65.         call InitAssaultGroup()
  66.         call CampaignAttackerEx(1,1,1,MOON_CHICK)
  67.         call CampaignAttackerEx(10,10,10,ARCHER)
  68.         call CampaignAttackerEx(10,10,10,HUNTRESS)
  69.         call CampaignAttackerEx(4,4,4,BALLISTA)
  70.         call SuicideOnPlayerEx(10,10,10,MyVictim)
  71.         exitwhen stopAttack()
  72.     endloop
  73.     call DisplayTextToPlayer(Player(0),0,0,"AI Ended")
  74. endfunction

and the trigger that send the command is like this:

Trigger: Test 39768970
   
           
  • Undead Destroyed AI Signal
  •     Events
  •         Time - Every 1.00 seconds of game time
  •     Conditions
  •     Actions
  •         If (All Conditions are True) then do (Then Actions) else do (Else Actions)
  •             If - Conditions
  •                 (All units of (Units in (Playable map area) owned by Player 3 (Teal)) are dead) Equal to True
  •             Then - Actions
  •                 Trigger - Turn off (This trigger)
  •                 Game - Display to (All players) the text: All Undead Destroye...
  •                 AI - Send Player 2 (Blue) the AI Command (2, 0)
  •             Else - Actions
           

The group is created don't worry about that and I get "All Undead Destroyed." but I don't get "AI Ended" which mean that we are still in the loop.

So what's wrong with my code ?
« Last Edit: January 14, 2013, 09:40:38 AM by moyack »



[AI] How AI work
Reply #5 on: January 14, 2013, 04:23:51 PM

While you where away I messed alot with AI function until I made a strange script,

Code: jass
  1. globals
  2.     player MyVictim = Player(2) // Player 3 (Teal)
  3. endglobals
  4.  
  5. function hero_levels takes nothing returns integer
  6.     local integer hero  = GetHeroId()
  7.     local integer level = GetHeroLevelAI()
  8.     local integer a = 0
  9.     if hero == DEMON_HUNTER then
  10.         if level == 1 or level == 3 or level == 5 then
  11.             set a = IMMOLATION
  12.         endif
  13.         if level == 2 or level == 4 or level == 7 then
  14.             set a = EVASION
  15.         endif
  16.         if level >= 8 then
  17.             set a = MANA_BURN
  18.         endif
  19.         if level == 6 then
  20.             set a = METAMORPHOSIS
  21.         endif
  22.     endif
  23.     if hero == MOON_CHICK then
  24.         if level == 1 or level == 3 or level == 5 then
  25.             set a = TRUESHOT
  26.         endif
  27.         if level == 2 or level == 4 or level == 7 then
  28.             set a = SEARING_ARROWS
  29.         endif
  30.         if level >= 8 then
  31.             set a = SCOUT
  32.         endif
  33.         if level == 6 then
  34.             set a = STARFALL
  35.         endif
  36.     endif
  37.     return a
  38. endfunction
  39.  
  40. function stopAttack takes nothing returns nothing
  41.     local integer cmd
  42.     //loop
  43.     call DisplayTextToPlayer(Player(0),0,0,"Waiting for Signal")
  44.         set cmd = WaitForSignal()
  45.         call DisplayTextToPlayer(Player(0),0,0,"Signal Reieved")
  46.         if cmd == 2 then
  47.             call DisplayTextToPlayer(Player(0),0,0,"Stop the attack")
  48.             set allow_signal_abort = TRUE
  49.             set sleep_seconds = -300
  50.         endif
  51.     //endloop
  52. endfunction
  53.  
  54. function main takes nothing returns nothing
  55.     call CampaignAI( MOON_WELL, function hero_levels )
  56.     call DisplayTextToPlayer(Player(0),0,0,"AI Started")
  57.     debug call Trace("DEBUG MODE")
  58.     call SetBuildUnitEx( 1, 1, 1, TREE_LIFE    )
  59.     call SetBuildUnitEx( 1, 1, 1, TREE_AGES    )
  60.     call SetBuildUnitEx( 1, 1, 1, TREE_ETERNITY)
  61.     call SetBuildUnitEx( 8, 8, 8, ANCIENT_WAR  )
  62.     call SetBuildUnitEx( 2, 2, 2, ELF_ALTAR    )
  63.     call SetBuildUnitEx( 2, 2, 2, HUNTERS_HALL )
  64.     //•••••••••••••••••••••••••••••••••••••••••
  65.     //•               DEFENDERS               •
  66.     //•••••••••••••••••••••••••••••••••••••••••
  67.     call CampaignDefenderEx( 1, 1, 1, MOON_CHICK )
  68.     call CampaignDefenderEx( 10, 10, 10, ARCHER     )
  69.     call CampaignDefenderEx( 10, 10, 10, HUNTRESS   )    
  70.     call StartThread(function stopAttack)
  71.     //call stopAttack()
  72.    
  73.     //•     WAVE #5+    •\\
  74.     loop
  75.         call DisplayTextToPlayer(Player(0),0,0,"Prepairing an attack wave")
  76.         //call InitAssaultGroup()
  77.         set harass_length = 0
  78.         call CampaignAttackerEx(1,1,1,MOON_CHICK)
  79.         call CampaignAttackerEx(10,10,10,ARCHER)
  80.         call CampaignAttackerEx(10,10,10,HUNTRESS)
  81.         call CampaignAttackerEx(4,4,4,BALLISTA)
  82.         call SuicideOnPlayerEx(10,10,10,MyVictim)
  83.         exitwhen allow_signal_abort
  84.     endloop
  85.     call DisplayTextToPlayer(Player(0),0,0,"AI Ended")
  86. endfunction

The AI ended with the destruction of the enemy but I am not sure of the method as I am using a function to start another thread (line 70); is this function is ok to use more than one time (as it is already used by the function CampaignAI) because with it I could run more than loop at a time but it may bug another AIs if used so is it safe to use it.



[AI] How AI work
Reply #6 on: January 15, 2013, 05:31:11 AM

The trick is not using too much the function StartThread(), it puts too much load to the system. AIs don't exceed from 3 threads at the same time.


[AI] How AI work
Reply #7 on: January 15, 2013, 08:42:08 AM

The trick is not using too much the function StartThread(), it puts too much load to the system. AIs don't exceed from 3 threads at the same time.

I have been busy all yesterday running lots of tests and found something very useful, which is the global variable: allow_signal_abort, it is somehow similar to the way you use bj_wantDestroyGroup.

I have modified the script so that I no longer use another thread.

Code: jass
  1. globals
  2.     player MyVictim = Player(2) // Player 3 (Teal)
  3. endglobals
  4.  
  5. function hero_levels takes nothing returns integer
  6.     local integer hero  = GetHeroId()
  7.     local integer level = GetHeroLevelAI()
  8.     local integer a = 0
  9.     if hero == DEMON_HUNTER then
  10.         if level == 1 or level == 3 or level == 5 then
  11.             set a = IMMOLATION
  12.         endif
  13.         if level == 2 or level == 4 or level == 7 then
  14.             set a = EVASION
  15.         endif
  16.         if level >= 8 then
  17.             set a = MANA_BURN
  18.         endif
  19.         if level == 6 then
  20.             set a = METAMORPHOSIS
  21.         endif
  22.     endif
  23.     if hero == MOON_CHICK then
  24.         if level == 1 or level == 3 or level == 5 then
  25.             set a = TRUESHOT
  26.         endif
  27.         if level == 2 or level == 4 or level == 7 then
  28.             set a = SEARING_ARROWS
  29.         endif
  30.         if level >= 8 then
  31.             set a = SCOUT
  32.         endif
  33.         if level == 6 then
  34.             set a = STARFALL
  35.         endif
  36.     endif
  37.     return a
  38. endfunction
  39.  
  40. function main takes nothing returns nothing
  41.     call CampaignAI( MOON_WELL, function hero_levels )
  42.     call DisplayTextToPlayer(Player(0),0,0,"AI Started")
  43.     call SetBuildUnitEx( 1, 1, 1, TREE_LIFE    )
  44.     call SetBuildUnitEx( 1, 1, 1, TREE_AGES    )
  45.     call SetBuildUnitEx( 1, 1, 1, TREE_ETERNITY)
  46.     call SetBuildUnitEx( 8, 8, 8, ANCIENT_WAR  )
  47.     call SetBuildUnitEx( 2, 2, 2, ELF_ALTAR    )
  48.     call SetBuildUnitEx( 2, 2, 2, HUNTERS_HALL )
  49.     //•••••••••••••••••••••••••••••••••••••••••
  50.     //•               DEFENDERS               •
  51.     //•••••••••••••••••••••••••••••••••••••••••
  52.     call CampaignDefenderEx( 1, 1, 1, MOON_CHICK )
  53.     call CampaignDefenderEx( 10, 10, 10, ARCHER     )
  54.     call CampaignDefenderEx( 10, 10, 10, HUNTRESS   )    
  55.  
  56.     //•     WAVE #5+    •\\
  57.     set allow_signal_abort=true
  58.     loop
  59.         call DisplayTextToPlayer(Player(0),0,0,"Prepairing an attack wave")
  60.         call InitAssaultGroup()
  61.         call CampaignAttackerEx(1,1,1,MOON_CHICK)
  62.         call CampaignAttackerEx(10,10,10,ARCHER)
  63.         call CampaignAttackerEx(10,10,10,HUNTRESS)
  64.         call CampaignAttackerEx(4,4,4,BALLISTA)
  65.         call SuicideOnPlayerEx(10,10,10,MyVictim)
  66.         exitwhen CommandsWaiting() != 0
  67.     endloop
  68.     call PopLastCommand()
  69.     set allow_signal_abort = false
  70.     call DisplayTextToPlayer(Player(0),0,0,"AI Ended")
  71. endfunction

Now I no longer need another thread, just send the signal and the AI stop. And also with this boolean you could exit most of the sleep functions.

Now, I am planning to make an AI manual to describe what each native do and if it work or not but that will take lots of work and time but I think with your aid things might go a bit faster.



[AI] How AI work
Reply #8 on: January 16, 2013, 06:34:45 PM

Ok, I have been testing the functions for 2 day now and everything that is weird is becoming even weirder. So far I unlocked 10 natives and how to use them and their uses.



[AI] How AI work
Reply #9 on: January 16, 2013, 07:16:32 PM

Hey!!! that's awesome!!! I'm feeling like extending the jass highlighthing to common.si natives and functions, so we can develop a documentation about them.

From my part, I'm working in a risky enterprise :P : I'm deleoping a kind of "AI system" where you can easily define a strategy. You just have to Define the unit requirements and you just have to writ something like this:

First, you define the unit requirements at code init:
Code: jass
  1. call CreateUnitDef( 'nwgs', 2, 'nnsa', 0     , 0, 0) // COUALT
  2.     call CreateUnitDef( 'nnmg', 1, T[1]  , 0     , 0, 0) // MURGUL REAVER
  3.     call CreateUnitDef( 'nnsw', 2, 'nnsa', 0     , 0, 0) // NAGA SIREN
  4.     call CreateUnitDef( 'nsnp', 1, 'nnsg', 0     , 0, 0) // SNAP DRAGON
  5.     call CreateUnitDef( 'nmyr', 3, 'nnsg', 0     , 0, 0) // NAGA MYRMIDON
  6.     call CreateUnitDef( 'nhyc', 2, 'nnsg', 0     , 0, 0) // DRAGON TURTLE
  7.     call CreateUnitDef( WORK  , 1, T[1],   0     , 0, 0) // MURGUL SLAVE
  8.     call CreateUnitDef( 'n00L', 3, 'n01B', 'n000', 0, 0) // NAGA HYDRA
  9.     call CreateUnitDef( 'n00K', 2, 'nnsa', 0     , 0, 0) // MURGUL WIZARD
  10.     call CreateUnitDef( 'n002', 1, 'n01B', 0     , 0, 0) // NAGA ARTIFACTER
  11.     call CreateUnitDef( 'n00J', 2, 'n01B', 0     , 0, 0) // TRANSPORT TURTLE
  12.     call CreateUnitDef( hero_id, 1, 'nnad', 0    , 0, 0) // HERO 1
  13.     call CreateUnitDef( hero_id2, 2, 'nnad', 0   , 0, 0) // HERO 2
  14.     call CreateUnitDef( hero_id3, 3, 'nnad', 0   , 0, 0) // HERO 3
  15.     //NAGA BUILDINGS
  16.     call CreateUnitDef( 'nnad', 1, 0, 0, 0, 0) // ALTAR OF DEPTHS
  17.     call CreateUnitDef( FARM  , 1, 0, 0, 0, 0) // CORAL BED
  18.     call CreateUnitDef( 'nnsa', 2, 0, 0, 0, 0) // SHRINE OF AZSHARA
  19.     call CreateUnitDef( 'nnsg', 1, 0, 0, 0, 0) // SPAWNING GROUNDS
  20.     call CreateUnitDef( T[1], 1, 0, 0, 0, 0) // TEMPLE OF TIDES
  21.     call CreateUnitDef( 'nntg', 1, 'n000', 0, 0, 0) // TIDAL GUARDIAN
  22.     call CreateUnitDef( 'n000', 1, 0, 0, 0, 0) // RUINS OF RELICS
  23.     call CreateUnitDef( T[2], 2, T[1], 0, 0, 0) // HIGH TEMPLE OF TIDES
  24.     call CreateUnitDef( 'n01B', 1, 'n000', 0, 0, 0) // REPTILIAN
  25.     call CreateUnitDef( T[3], 3, T[2], 0, 0, 0) // SUPREME TEMPLE OF TIDES

Then you define the training order like this:
Code: jass
  1.     call BuildUnit(1, 'nmpe', -1 )
  2.     call BuildUnit(2, 'nmpe', -1 )
  3.     call BuildUnit(3, 'nmpe', -1 )
  4.     call BuildUnit(4, 'nmpe', -1 )
  5.     call BuildUnit(5, 'nmpe', -1 )
  6.     call BuildUnit(1, hero_id, -1 )
  7.     call BuildUnit(6, 'nmpe', -1 )
  8.     call BuildUnit(7, 'nmpe', -1 )
  9.     call BuildUnit(1, 'nnmg', -1 )
  10.     call BuildUnit(8, 'nmpe', -1 )
  11.     call BuildUnit(2, 'nnmg', -1 )
  12.     call BuildUnit(1, 'nsnp', -1 )
  13.     call BuildUnit(9, 'nmpe', -1 )
  14.     call BuildUnit(3, 'nnmg', -1 )
  15.     call BuildUnit(4, 'nnmg', -1 )
  16.     call BuildUnit(10, 'nmpe', -1 )
  17.     call BuildUnit(1, 'n002', -1 )
  18.     call BuildUnit(2, 'nsnp', -1 )
  19.     call BuildUnit(2, 'n002', -1 )
  20.     call BuildUnit(3, 'nsnp', -1 )

As you can see you only worry for setting the units, and the code will build all that it needs. Unfortunately I'm still having bad issues.


[AI] How AI work
Reply #10 on: January 18, 2013, 11:28:06 AM

Do you know how town system work (-1: main town, 0: ??, 1: first expansion, 2:second, etc)

Also I don't know why this function is always returning zero, GetTownUnitCount ?
Code: jass
  1. globals
  2.     integer n = 0
  3. endglobals
  4.  
  5. function main takes nothing returns nothing
  6.     call DisplayTextToPlayer(Player(0),0,0,"start"+I2S(1))
  7.     call CampaignAI(MOON_WELL,null)
  8.     call Sleep(1)
  9.     set n = GetTownUnitCount( ARCHER , 1 , true )
  10.     call Sleep(0.1)
  11.     if n == 0 then
  12.         call DisplayTextToPlayer(Player(0),0,0,"0")
  13.     elseif n == 1 then
  14.         call DisplayTextToPlayer(Player(0),0,0,"1")
  15.     elseif n == 2 then
  16.         call DisplayTextToPlayer(Player(0),0,0,"2")
  17.     elseif n == 3 then
  18.         call DisplayTextToPlayer(Player(0),0,0,"3")
  19.     elseif n == 4 then
  20.         call DisplayTextToPlayer(Player(0),0,0,"4")
  21.     else
  22.         call DisplayTextToPlayer(Player(0),0,0,"5+")
  23.     endif
  24.  
  25. endfunction



[AI] How AI work
Reply #11 on: January 20, 2013, 08:38:25 AM

AS far as I understood, main is -1, next is 0, second is 1, etc... so  in theory you're asking with this function how many archers are in town 2, I think the issue is that this function is valid with buildings only.


 

Chaos Realm - The world of Game modders and wc3 addicts     WC3JASS.com - The JASS Vault   Jetcraft - A Starcraft II mod