• 🏆 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!

Help with AI

Status
Not open for further replies.
Level 2
Joined
Jun 5, 2012
Messages
19
Hey guys, consider this as my introductory thread or something. So, yay.

I've been creating an AI for my map, all is working, but I cant seem to figure out how to make certain things run on it. So, I would just like you guys to give me a sort of solution on how to accomplish the tasks about to be said. vJass, Jass or even plain GUI is fine. I can work my way on the three.

Ok, so here:

1. How do I create a certain point in a random range from 100 - 1200 and in a random angle/facing and check if that point is pathable or not. If yes, move to it. If no, loop again until a pathable point is made. (I know how to do this but not this) After, if the unit enters or goes to the said point, new one is created. This would be run until a target is acquired.

2. How do I make something like this: Every few seconds (or oven milliseconds) the computer finds the unit with the largest threat and attack the said unit. Every unit gets a threat and is a real. Also, if the unit is a hero, the threat increases by like 2x or 2.5x.

3. How do I do: When the unit's hp drops to say like 25%, they retreat to a point like offset by 1200 points. If the hp is like 10%, the unit flees to the nearest fountain.

4. How do I make the AI buy items? I can make this, but I need more solutions, since mine is terribly long.

5. Last, how do I make unit cast spells/use items depending on their own or enemies stats? Ex. if the AI has 20% hp and has potions, use the potions. If the enemy unit has 200 hp left and the AI has a spell which deals like 250 damage, spell casted.

Thanks a lot,
Verkas
 
Level 6
Joined
Feb 5, 2012
Messages
1,685
#4 SUGGESTION

event-a unit is attack
CONDITION- LIFE OF ATTACKED UNIT IS LESSER THAN 30%
OWNER OF ATTACKED UNIT IS COMPUTER PLAYER
THEN
IF
condition- ATTACKED UNIT HAS (THE POTION) = TRUE
then
set HERO RANGE= UNITS WITHIN 500 OF ATTACKED UNIT MATCHING ENEMY
IF
NUMBER OF UNITS IN HERO RANGE = 0
THEN
UNIT- ORDER ATTACKED TO USE POTION TO ATTACKED
 
Level 2
Joined
Jun 5, 2012
Messages
19
You mean number 5, right?

And lol, I haven't thought of said solution. Thanks anyways.
Also, use
  • tags. They dont hurt your brain when used.[/B][/COLOR][/SIZE][/FONT]
 
Level 2
Joined
Jun 5, 2012
Messages
19
Well, observing something would be hard since the code itself is not presented. Thanks again.
 
Level 2
Joined
Jun 5, 2012
Messages
19
aNYWAY there is a JASS AI on the tutorial section........just find it or ask others where to find it...it has AI BUY ITEM, AI USE ITEM, AI ATTACK AND USE SPELLS

From what I see, it is simply a melee-type of an AI, the only AI i've seen for a non-melee map in a tutorial is the GUI one, but it doesn't live up to my standards. I've played the maker of the tutorials map and I didn't really like the AI.
 

Cokemonkey11

Spell Reviewer
Level 30
Joined
May 9, 2006
Messages
3,547
AI is one of the last things you'll attempt/learn in scripting. There are people who write jass for years before they attempt proper AI handling.

Edit: A better way to put this is that there are entire university degrees dedicated to creating AI.

Look:

JASS:
scope ai initializer i
    private struct aiData
        unit hero
        integer itemType
        string itemClass
        integer itemLevel
        integer itemCost
        real depth
    endstruct
    
    globals
        private timer time=CreateTimer()
        private integer dbIndex=-1
        private aiData array aiDB
    endglobals
    
    private function newShip takes integer index returns unit
        local integer rand=GetRandomInt(0,9)
        local unit u
        local integer array ids
        set ids[0]='H001'   //Crusader
        set ids[1]='H000'   //Sailor
        set ids[2]='H009'   //Juggernaut
        set ids[3]='H008'   //Overlord
        set ids[4]='H003'   //Interceptor
        set ids[5]='H004'   //Sea Punisher
        set ids[6]='H00A'   //Beast
        set ids[7]='H00C'   //Lurker
        set ids[8]='H006'   //Dominator
        set ids[9]='H007'   //Destroyer
        if index<7 then
            set u=CreateUnit(Player(index),ids[rand],57,-6486,90)
        else
            set u=CreateUnit(Player(index),ids[rand],-1487,5780,270)
        endif
        return u
    endfunction
    
    private function aiOrderDeepestBack takes unit u returns location
        local unit favUnit=null
        local location start=GetUnitLoc(u)
        local group g=CreateGroup()
        local real multiplier
        local integer playerNum
        local boolean less=false
        if GetPlayerId(GetOwningPlayer(u))<7 then
            set multiplier=-1
            set playerNum=1
            set less=true
        else
            set multiplier=1
            set playerNum=0
            set less=false
        endif
        call GroupEnumUnitsOfPlayer(g,Player(playerNum),null)
        loop
            exitwhen FirstOfGroup(g)==null
            if favUnit==null then
                set favUnit=FirstOfGroup(g)
            endif
            if less then
                if GetUnitY(FirstOfGroup(g))<GetUnitY(favUnit) and GetWidgetLife(FirstOfGroup(g))>1 then
                    set favUnit=FirstOfGroup(g)
                endif
            else
                if GetUnitY(FirstOfGroup(g))>GetUnitY(favUnit) and GetWidgetLife(FirstOfGroup(g))>1 then
                    set favUnit=FirstOfGroup(g)
                endif
            endif
            call GroupRemoveUnit(g,FirstOfGroup(g))
        endloop
        call DestroyGroup(g)
        return Location(GetUnitX(favUnit),GetUnitY(favUnit)+multiplier*450)
    endfunction
    
    private function removeAllItems takes unit u returns nothing
        local integer index=0
        loop
            exitwhen index>5
            call RemoveItem(UnitItemInSlot(u,index))
            set index=index+1
        endloop
    endfunction
    
    private function getItemType takes string s, integer l returns integer
        local integer array rapidMidTypes
        set rapidMidTypes[0]='I000' //Arrow Cannon
        set rapidMidTypes[1]='I01B' //Bowmen
        set rapidMidTypes[2]='I005' //Cold-Arrows Cannon
        set rapidMidTypes[3]='I00I' //Fire-Arrow Cannon
        set rapidMidTypes[4]='I018' //Guard Tower Cannon
        set rapidMidTypes[5]='I01N' //Shadow Cannon
        set rapidMidTypes[6]='I01P' //Trickster Rockets
        set rapidMidTypes[7]='I00G' //Multi-Rockets
        if s=="rapidMid" then
            return rapidMidTypes[l]
        endif
        return 0
    endfunction
    
    private function getItemCost takes integer t returns integer
        local item i=CreateItem(t,0,0)
        local integer c=R2I(GetWidgetLife(i))
        call RemoveItem(i)
        return c
    endfunction

    private function p takes nothing returns nothing
        local integer index=0
        loop
            exitwhen index>dbIndex
            
            if GetPlayerId(GetOwningPlayer(aiDB[index].hero))<7 then
                if GetUnitY(aiDB[index].hero)<-5932 and GetPlayerState(GetOwningPlayer(aiDB[index].hero),PLAYER_STATE_RESOURCE_GOLD)>aiDB[index].itemCost then
                    if Units_hasInventorySlot(aiDB[index].hero) then
                        call UnitAddItemById(aiDB[index].hero,aiDB[index].itemType)
                        call SetPlayerState(GetOwningPlayer(aiDB[index].hero),PLAYER_STATE_RESOURCE_GOLD,GetPlayerState(GetOwningPlayer(aiDB[index].hero),PLAYER_STATE_RESOURCE_GOLD)-aiDB[index].itemCost)
                    elseif GetPlayerState(GetOwningPlayer(aiDB[index].hero),PLAYER_STATE_RESOURCE_GOLD)>aiDB[index].itemCost*10 then
                        call SetPlayerState(GetOwningPlayer(aiDB[index].hero),PLAYER_STATE_RESOURCE_GOLD,GetPlayerState(GetOwningPlayer(aiDB[index].hero),PLAYER_STATE_RESOURCE_GOLD)+aiDB[index].itemCost*3)
                        call removeAllItems(aiDB[index].hero)
                        set aiDB[index].itemLevel=aiDB[index].itemLevel+1
                        set aiDB[index].itemType=getItemType(aiDB[index].itemClass,aiDB[index].itemLevel)
                        set aiDB[index].itemCost=getItemCost(aiDB[index].itemType)
                    endif
                endif
                if GetUnitState(aiDB[index].hero,UNIT_STATE_LIFE)<1 then
                elseif GetUnitState(aiDB[index].hero,UNIT_STATE_LIFE)/GetUnitState(aiDB[index].hero,UNIT_STATE_MAX_LIFE)<.5 then
                    call IssuePointOrder(aiDB[index].hero,"move",-1152,-6443) //move to south repair
                elseif GetUnitState(aiDB[index].hero,UNIT_STATE_LIFE)/GetUnitState(aiDB[index].hero,UNIT_STATE_MAX_LIFE)>.5 then
                    call IssuePointOrderLoc(aiDB[index].hero,"move",aiOrderDeepestBack(aiDB[index].hero))
                endif
            else
                if GetUnitY(aiDB[index].hero)>5434 and Units_hasInventorySlot(aiDB[index].hero) then
                    call UnitAddItemById(aiDB[index].hero,'I000')
                endif
                if GetUnitState(aiDB[index].hero,UNIT_STATE_LIFE)<1 then
                elseif GetUnitState(aiDB[index].hero,UNIT_STATE_LIFE)/GetUnitState(aiDB[index].hero,UNIT_STATE_MAX_LIFE)<.5 then
                    call IssuePointOrder(aiDB[index].hero,"move",-2252,5458) //move to north repair
                elseif GetUnitState(aiDB[index].hero,UNIT_STATE_LIFE)/GetUnitState(aiDB[index].hero,UNIT_STATE_MAX_LIFE)>.5 then
                    call IssuePointOrderLoc(aiDB[index].hero,"move",aiOrderDeepestBack(aiDB[index].hero))
                endif
            endif
            
            set index=index+1
        endloop
    endfunction
    
    private function a takes nothing returns nothing
        local integer index=2
        loop
            exitwhen index>11
            if GetPlayerController(Player(index))==MAP_CONTROL_COMPUTER then
                call RemoveUnit(Units_playerBoat[index+1])
                set dbIndex=dbIndex+1
                set aiDB[dbIndex]=aiData.create()
                set Units_playerBoat[index+1]=aiDB[dbIndex].hero
                set aiDB[dbIndex].hero=newShip(index)
                set aiDB[dbIndex].itemClass="rapidMid"
                set aiDB[dbIndex].itemType='I000'   //Arrow Cannon
                set aiDB[dbIndex].itemCost=165
                set aiDB[dbIndex].depth=450
                set aiDB[dbIndex].itemLevel=0
                set Units_playerBoat[index+1]=aiDB[dbIndex].hero
            endif
            set index=index+1
        endloop
        if dbIndex!=-1 then
            call TimerStart(time,5,true,function p)
        endif
    endfunction
    
    private function i takes nothing returns nothing
        local trigger t=CreateTrigger()
        call TriggerRegisterTimerEvent(t,10,false)
        call TriggerAddAction(t,function a)
    endfunction
endscope

AI is not so simple as "if the unit's health is less than 50%, run away!" You have to consider how you'll handle your units, what exactly needs to be controlled by the AI, how many, how accurate should it be, how random, etc.
 
Level 2
Joined
Jun 5, 2012
Messages
19
Well, i'm not going for something terribly accurate, but simple and functional enough. I am fully aware that there are courses at the university dedicated to this certain topic, but I don't want it to go that deep, a simple one would be good for me.

The only trouble i've had is with #2, since I cant somehow store these real values into a unit.

EDIT

I found a way for all 5. The moderator can close this thread now.
 
Level 2
Joined
Jun 5, 2012
Messages
19
Its rather simple. I know most are not the best way, but I go for the simplest way.

1. Is done by creating a region and making the unit move to it. Add the enters region event to a trigger and then move the region. Sort of a loop. What Drunken_Jackal suggested.

2. I am using Bribe's Unit Indexer, so I just array the threat value to the units custom value. The custom value is the array value, so its like ThreatValue[UnitsCustomValue]. This is just a theory though, not entirely sure.

3. Similar to neo_sluf's method, but it just moves the unit.

4. Detect if the player enters the safety range of a shop, then check if the gold is enough, create item, dedeuct gold and done.

5. Neo_sluf explained it. Its basically creating a unit group for each hero and checking if there are units in it. If there are, cast spell. If none, use potion if hp is below a certain percent.

Thanks guys, rep to all of yers.
 
Status
Not open for further replies.
Top