• 🏆 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] Special AI Curiosities

Status
Not open for further replies.
Level 15
Joined
Sep 26, 2007
Messages
369
I have some questions about AI, since I'm good with the AI campaign scripts (Not made by the AI Editor), but some mysteries still haunt me...

Controlling units during battle against an enemy base
When units are being charmed or possessed by the attackers, the victims refuse to join the attacking team, because they've been set as defenders and they'll simply go to their new home base.

When units are being resurrected or reincarnated, they refuse to keep fighting, because they've been set as defenders and they'll simply retreat to their bases.

Is there a way to force the charmed, possessed, resurrected and reincarnated units/Heroes to keep going as attackers? I know a solution for the possessed and charmed units, but I want to know if there are better ones.

Transport Bug
I want the computer player to attack the enemies from one island to another. Yeah, I know it's done with Zeppelins, but I want with the Transport Ships.

I've noticed that Zeppelins are controlled thanks to the Fly move type, I've tried to set the Transport Ship as a "flying" unit and it worked. Now, how do I do this as an Amphibious move type? Just like the good old WC2's transport ships.

Shipyard Bug
I want the computer player to build a Shipyard, but the peon-type unit just wanders around, looking for a land to build where it's supposed to build at the shores. How do I force the peon-type unit to build a Shipyard at the shores?
 
Level 5
Joined
Oct 27, 2007
Messages
158
I have some questions about AI, since I'm good with the AI campaign scripts (Not made by the AI Editor), but some mysteries still haunt me...

Controlling units during battle against an enemy base
When units are being charmed or possessed by the attackers, the victims refuse to join the attacking team, because they've been set as defenders and they'll simply go to their new home base.

When units are being resurrected or reincarnated, they refuse to keep fighting, because they've been set as defenders and they'll simply retreat to their bases.

Is there a way to force the charmed, possessed, resurrected and reincarnated units/Heroes to keep going as attackers? I know a solution for the possessed and charmed units, but I want to know if there are better ones.

If I recall correctly you can use timed units, like summons, parasites, stuff like that in attack groups calling the function GroupTimedLife(true)
However in order to include possessions, charms, or other permanent units, you'd have to modify the forming of attack groups. This isn't hard to do, I've done it too because I didn't like the way Blizzard implemented campaign attacks. All you have to do here is rewrite the CampaignAttacker and SuicideOnPlayer functions. There's a function called FormGroup where the attack group called with CampaignAttacker is actually formed. The attackers are built in a seperate thread. This thread is called in CampaignBasicsA, which is started by CampaignAI. You need to write a function in your new formgroup function where you check for possessed, charmed, etc. units and add them to the assault group. If you don't like rewriting all functions, or are satisfied with the way attacks are setup, then just copy and paste all the stuff from Common.ai and write a new function in your custom FormGroup function.

Another solution without creating custom functions is creating a seperate thread and check for those unit types, and suicide them on the enemy player. This has some disadvantages though. Units will not be included in the attack group itself, and they will attack on their own without support. However you could send them after the attack party is sent. You can do this with the CaptainInCombat function, where you check wether the attack captain is already in combat or not. You could do this whenever the attack or defense captain is in combat with the enemy player.

Transport Bug
I want the computer player to attack the enemies from one island to another. Yeah, I know it's done with Zeppelins, but I want with the Transport Ships.

I've noticed that Zeppelins are controlled thanks to the Fly move type, I've tried to set the Transport Ship as a "flying" unit and it worked. Now, how do I do this as an Amphibious move type? Just like the good old WC2's transport ships.

I've tried this too and haven't come up with a solution for this. The AI is programmed to only use air transports. There're no functions available that deal with sea transports. You could simulate this with trigger code, but that would screw up the AI script, and this would make the AI entirely trigger driven. Controlling an AI only through triggers would be a pain to do. If only the AI script was able to communicate with the map script then this could be simulated without messing up the AI script execution flow.

Shipyard Bug
I want the computer player to build a Shipyard, but the peon-type unit just wanders around, looking for a land to build where it's supposed to build at the shores. How do I force the peon-type unit to build a Shipyard at the shores?

Use the ShiftTownSpot(x, y) function. Set a point in shallow water where you'd like the shipyard to be built. What this function does is shift the town location build spot to the point you specify on the map. Be sure to shift the spot back inside your town after a peasant has started the shipyard, otherwise you end up with an AI building everything near the water.
 
Level 15
Joined
Sep 26, 2007
Messages
369
If I recall correctly you can use timed units, like summons, parasites, stuff like that in attack groups calling the function GroupTimedLife(true)
However in order to include possessions, charms, or other permanent units, you'd have to modify the forming of attack groups. This isn't hard to do, I've done it too because I didn't like the way Blizzard implemented campaign attacks. All you have to do here is rewrite the CampaignAttacker and SuicideOnPlayer functions. There's a function called FormGroup where the attack group called with CampaignAttacker is actually formed. The attackers are built in a seperate thread. This thread is called in CampaignBasicsA, which is started by CampaignAI. You need to write a function in your new formgroup function where you check for possessed, charmed, etc. units and add them to the assault group. If you don't like rewriting all functions, or are satisfied with the way attacks are setup, then just copy and paste all the stuff from Common.ai and write a new function in your custom FormGroup function.

Another solution without creating custom functions is creating a seperate thread and check for those unit types, and suicide them on the enemy player. This has some disadvantages though. Units will not be included in the attack group itself, and they will attack on their own without support. However you could send them after the attack party is sent. You can do this with the CaptainInCombat function, where you check wether the attack captain is already in combat or not. You could do this whenever the attack or defense captain is in combat with the enemy player.
No problem, I already have modified my own Common.ai file to fix some things. I might as well try rewriting those codes you've said.

As for my AI scripts, the possessed units are easy to control thanks to a separate function that, each second of the function loop, uses the AddAssaultUnit and include that unitID type which is not Undead. The problem is, when units are being resurrected or reincarnated, the AI can't gain control of them, since the AI picks on random units of the same UnitIDs, which is so unlike the triggers in WE Trigger Editor that allow us to pick on specific units. But still, I'll give it a try, and see what happens.

As for the GroupTimedLife, I never use it, because rarely, or sometimes, the AI ends up screwing around with their attack waves, and their attack timings rarely get messed up.

I've tried this too and haven't come up with a solution for this. The AI is programmed to only use air transports. There're no functions available that deal with sea transports. You could simulate this with trigger code, but that would screw up the AI script, and this would make the AI entirely trigger driven. Controlling an AI only through triggers would be a pain to do. If only the AI script was able to communicate with the map script then this could be simulated without messing up the AI script execution flow.
Just as I thought, only for air transports. Well, I'll stick with the zeppelins and the sky barges then. And yes, I could try simulating a sea attack with two players of the same team, one with AI, and the other without AI.

Use the ShiftTownSpot(x, y) function. Set a point in shallow water where you'd like the shipyard to be built. What this function does is shift the town location build spot to the point you specify on the map. Be sure to shift the spot back inside your town after a peasant has started the shipyard, otherwise you end up with an AI building everything near the water.
Okay, I'll give it a try then.
 
Level 5
Joined
Oct 27, 2007
Messages
158
As for my AI scripts, the possessed units are easy to control thanks to a separate function that, each second of the function loop, uses the AddAssaultUnit and include that unitID type which is not Undead. The problem is, when units are being resurrected or reincarnated, the AI can't gain control of them, since the AI picks on random units of the same UnitIDs, which is so unlike the triggers in WE Trigger Editor that allow us to pick on specific units. But still, I'll give it a try, and see what happens.

Well I looked into this matter a little bit further and have come up with a
solution for timed, possessed, charmed and resurrected units :wgrin: The real problem like you found out lies within resurrected units. You have no event from which you can detect resurrected units. You can however for Heroes but that isn't useful for detecting unit resurrection from an ability like Resurrection. The following is the code I used to do it. It's a combination of triggers and AI script code. It shows why the combined power of trigger code and AI script code makes the AI so much more flexible.

JASS:
function Trig_CheckPossession_Conditions takes nothing returns boolean
    local integer ability_id = GetSpellAbilityId()

    return ability_id == 'ANch' or ability_id == 'ACch' or ability_id == 'Apos' or ability_id == 'ACps'
endfunction

function Trig_CheckPossession_Actions takes nothing returns nothing
    local unit caster_unit = GetSpellAbilityUnit()
    local unit target_unit = GetSpellTargetUnit()

    call DisplayTextToPlayer(udg_user, 0, 0, "Caster is: " + GetUnitName(caster_unit))
    if target_unit != null then
        call DisplayTextToPlayer(udg_user, 0, 0, "Target is: " + GetUnitName(target_unit))
        set udg_last_caster_unit = caster_unit
        set udg_last_target_unit = target_unit
    else
        call DisplayTextToPlayer(udg_user, 0, 0, "Invalid target!")
    endif
    set caster_unit = null
    set target_unit = null
endfunction

//===========================================================================
function InitTrig_CheckPossession takes nothing returns nothing
    set gg_trg_CheckPossession = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_CheckPossession, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition( gg_trg_CheckPossession, Condition( function Trig_CheckPossession_Conditions ) )
    call TriggerAddAction( gg_trg_CheckPossession, function Trig_CheckPossession_Actions )
endfunction
CheckPossession: This trigger I used to catch possession and charm casters, and the target. It still needs an unit changed owner event because there is no way to be sure the unit is actually possessed or charmed. The caster could die or select a unit which is already being charmed, possessed by another caster.

JASS:
function Trig_CheckOwnerState_Actions takes nothing returns nothing
    local unit changing_unit = GetChangingUnit()
    local integer unit_id = GetUnitTypeId(changing_unit)
    local player prev_owner = GetChangingUnitPrevOwner()
    local player new_owner = GetOwningPlayer(changing_unit)

    if udg_last_target_unit != null then
        if changing_unit == udg_last_target_unit then
            //call RemoveGuardPosition(changing_unit)
            //call RecycleGuardPosition(changing_unit)
            //call DisplayTextToPlayer(udg_user, 0, 0, "Removed AI guard position from unit.")
            call DisplayTextToPlayer(udg_user, 0, 0, "Possession succesfull.")
            call DisplayTextToPlayer(udg_user, 0, 0, "Previous unit owner was " + GetPlayerName(prev_owner))
            if prev_owner != udg_user then
                call CommandAI(prev_owner, 9, unit_id)
            endif
            if new_owner != udg_user then
                call CommandAI(new_owner, 8, unit_id)
            endif
            set udg_last_caster_unit = null
            set udg_last_target_unit = null
        endif
    endif
    set changing_unit = null
    set prev_owner = null
    set new_owner = null
endfunction

//===========================================================================
function InitTrig_CheckOwnerState takes nothing returns nothing
    set gg_trg_CheckOwnerState = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_CheckOwnerState, EVENT_PLAYER_UNIT_CHANGE_OWNER )
    call TriggerAddAction( gg_trg_CheckOwnerState, function Trig_CheckOwnerState_Actions )
endfunction
CheckOwnerState: This trigger is used to actually check if the target unit was possessed successfully. This isn't a foolproof system, however. I don't know what happens if two target units get possessed by two different casters at the exact same time. But this happening is very unlikely. Even when this happens it won't mess up things. The worst scenario being that a possessed unit isn't tracked. However during tests I didn't encounter any problems. I've actually seen possessions occurring at the same time, however we can't distinguish events in micro seconds or less, so for a human it seems like it's occurring at the same moment.

It sends an AI command with the unit id of the unit that's possessed. The AI script stores that unit in a possessions array. I'll explain that later.

JASS:
function Trig_PossessionDies_Actions takes nothing returns nothing
    local unit u = GetDyingUnit()
    local player owner = GetOwningPlayer(u)

    if u == udg_last_caster_unit then
        call DisplayTextToPlayer(udg_user, 0, 0, "Caster unit died before finishing possession!")
        set udg_last_caster_unit = null
        set udg_last_target_unit = null
    endif
    if owner != udg_user then
        call CommandAI(owner, 9, GetUnitTypeId(u))
        set udg_dead_units[udg_index] = u
        set udg_index = udg_index + 1
        if udg_index > 256 then
            set udg_index = 0
        endif
    endif
    set u = null
    set owner = null
endfunction

//===========================================================================
function InitTrig_PossessionDies takes nothing returns nothing
    set gg_trg_PossessionDies = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_PossessionDies, EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddAction( gg_trg_PossessionDies, function Trig_PossessionDies_Actions )
endfunction
PossessionDies: Here it checks if the caster unit died before completing the ability. If the caster dies the AI shouldn't be informed of a new unit. When a unit dies a command is sent to the AI player owner of the dying unit. This is needed so the AI script can check if the unit type is present in the possessions array. This won't track the exact unit object. This isn't necessary because there aren't any natives in common.ai that can send a specific unit to attack a player. You could send a unit object through though abusing the return bug and sending an integer pointer to the AI script. However this isn't very usefull in this case. The main purpose is to be sure the AI maintains the same amount of a unit type it has for defending the base. This can occur in Undead vs Undead scenarios.

This also keeps track of AI units dying. This system I used to track resurrected units. I keep an array of 256 unit handles to unit objects of units that died. The next trigger shows why.

JASS:
function Trig_CheckResurrections_Actions takes nothing returns nothing
    local integer index = 0
    local unit u

    loop
        exitwhen index == udg_index
        set u = udg_dead_units[index]
        if u != null and GetUnitState(u, UNIT_STATE_LIFE) > 0 then
            if IsUnitType(u, UNIT_TYPE_HERO) then
                call DisplayTextToPlayer(udg_user, 0, 0, "Hero is resurrected!")
                call SetUnitState(u, UNIT_STATE_MANA, GetUnitState(u, UNIT_STATE_MAX_MANA))
            else
                call DisplayTextToPlayer(udg_user, 0, 0, "Unit is resurrected!")
                call CommandAI(GetOwningPlayer(u), 10, GetUnitTypeId(u))
            endif
            set udg_dead_units[index] = null
        endif
        set index = index + 1
    endloop
    set u = null
endfunction

//===========================================================================
function InitTrig_CheckResurrections takes nothing returns nothing
    set gg_trg_CheckResurrections = CreateTrigger(  )
    call TriggerRegisterTimerEvent(gg_trg_CheckResurrections, 0.50, true)
    call TriggerAddAction( gg_trg_CheckResurrections, function Trig_CheckResurrections_Actions )
endfunction
CheckResurrections: This trigger checks if the units that died are resurrected. The hero part I used for debugging purposes. I used it to fill mana so the hero can use his resurrect ability. If a unit is resurrected it normally tries to go back to his main base and stay there as a defender. With this periodic timer you can now check for resurrected units and command the AI to do something with those units.

Code:
function SuicideUnitOnBattlefield takes integer unit_id returns nothing
    if CaptainInCombat(true) and not CaptainIsHome() then
        call DisplayTextToPlayer(dbg, 0, 0, "Sending unit to the battlefield.")
        call SuicideUnitEx(1, unit_id, pid)
    else
        call DisplayTextToPlayer(dbg, 0, 0, "Captain isn't in combat on the battlefield.")
    endif
endfunction
SuicideUnitOnBattlefield is a function from my AI script. Whenever the AI received a command that a unit was possessed, charmed or resurrected it calls this function. This is where you get the difference between suicide loops and triggered suicides. When you use suicide loops the AI tries to suicide more than one unit of the unit type. What's nice about this, is that it will check the nearest unused unit near the combat zone to send out on an attack. It won't pull units from his base, in case of Undead vs Undead where possessions etc. can be of the same unit type of the race the AI plays. That's why I've included a check for attack captain in combat and if the captain is currently in his main base. If he's in his main base and in combat then don't suicide. In that case you include the possessed etc. in the next attack wave, and that's the reason why you keep track of the possessed etc. units in the possessions array.

Code:
function SetPossessedUnit takes boolean add_unit, integer unit_id returns nothing
    local integer index = 0

    loop
        exitwhen possessions[index] == -1 or possessions[index] == unit_id
        set index = index + 2
    endloop
    if add_unit then
        if possessions[index] == -1 then
            set possessions[index] = unit_id
            set possessions[index + 1] = 1
            set possessions[index + 2] = -1
            call DisplayTextToPlayer(dbg, 0, 0, "Added new possessed unit type.")
        else
            set possessions[index + 1] = possessions[index + 1] + 1
            call DisplayTextToPlayer(dbg, 0, 0, "Updated existing possessed unit type count.")
        endif
        call SuicideUnitOnBattlefield(unit_id)
    elseif possessions[index] == unit_id then
        if possessions[index + 1] > 0 then
            set possessions[index + 1] = possessions[index + 1] - 1
            call DisplayTextToPlayer(dbg, 0, 0, "Removed one possessed unit.")
        endif
    endif
endfunction
SetPossessedUnit is another function the AI script uses. It stores the possessed and charmed units. It won't store resurrected units, because they're from the AI anyways. I don't find that necessary.

Code:
function FormAssaultGroup takes real seconds, boolean check_hp, integer hp_perc returns boolean
    local integer index
    local integer count
    local integer unit_id
    local boolean captain_ready

    if wave_prep_time < seconds or seconds <= 0 then
        call DisplayTextToPlayer(dbg, 0, 0, "Group forming wait time is too high!")
        set seconds = wave_prep_time
    endif
    if not check_hp then
        set hp_perc = 0
    endif
    loop
        set index = 0
        set wave_prep_time = wave_prep_time - seconds
        call Wait(seconds)
        call InitAssault()
        loop
            exitwhen index == attack_count
            set unit_id = attack_units[index]
            set count = attack_units[index + 1]
            call AddAssault(count, unit_id)
            set index = index + 2
        endloop
        set index = 0
        loop
            exitwhen not do_possessions
            exitwhen possessions[index] == -1
            set unit_id = possessions[index]
            set count = TownCountDone(unit_id)
            if count > 0 and possessions[index + 1] > 0 then
                if count > possessions[index + 1] then
                    set count = possessions[index + 1]
                endif
                call AddAssault(count, unit_id)
            endif
            set index = index + 2
        endloop
        call DisplayTextToPlayer(dbg, 0, 0, "Captain ready check...")
        set captain_ready = CaptainIsFull() and CaptainReadiness() >= hp_perc
        exitwhen captain_ready or wave_prep_time <= 0
        call DisplayTextToPlayer(dbg, 0, 0, "Captain in combat check, or form group timeout...")
        exitwhen abort
    endloop
    return captain_ready
endfunction
FormAssaultGroup is the custom function I use to create attack groups. It also includes the possessions that are stored in the possessions array that're not sent into combat yet. This happens for example when possessions occur when the attack captain isn't in combat on the battlefield. Most of the time this is caused by the defense captain combating attackers.

As for the GroupTimedLife, I never use it, because rarely, or sometimes, the AI ends up screwing around with their attack waves, and their attack timings rarely get messed up.
Well it's actually quite useful to set GroupTimedLife during the setup of your AI script. It ensures that the AI always includes timed units, like summons and parasites and such in attack waves. If you don't set this the AI doesn't make proper use of those units. For example if you have an attack wave with Meat wagons and Necromancers. The Necromancers raise skeletons from the corpses in the Meat wagons. This happens when the attack party is in combat. However when those skeletons are raised too far from the combat area they do nothing. If you set GroupTimedLife they will be included in the attack party and will automatically move into the combat zone. The same goes for summons from other races.

I just had to come up with something for this lol.. :razz:
I don't know why, I just can't stand it when faced with a problem and a solution isn't available yet.
 
Last edited:
Level 15
Joined
Sep 26, 2007
Messages
369
Interesting codes, and flexible indeed. I'll try them, as soon as I get some free time.

Well it's actually quite useful to set GroupTimedLife during the setup of your AI script. It ensures that the AI always includes timed units, like summons and parasites and such in attack waves. If you don't set this the AI doesn't make proper use of those units. For example if you have an attack wave with Meat wagons and Necromancers. The Necromancers raise skeletons from the corpses in the Meat wagons. This happens when the attack party is in combat. However when those skeletons are raised too far from the combat area they do nothing. If you set GroupTimedLife they will be included in the attack party and will automatically move into the combat zone. The same goes for summons from other races.
Yeah, I know the GroupTimedLife sounds useful, because I used it once before. Used until I spotted a terrible part, when they summon a unit in their main base and gets attacked, the already launched army (for having traveled so far) noticed that issue, and they've interrupted their traveling progress just to intercept to where the summoned unit was taking damage. That's why I have to disable the GroupTimedLife, sorry.

I just had to come up with something for this lol.. :razz:
I don't know why, I just can't stand it when faced with a problem and a solution isn't available yet.
Yeah, me too. Like I've said, some mysteries still haunt me. I think the questions that I've asked may have been a little bit too much.

But the need is not so urgent. If this problem gets way too complicated, let's forget it, it's not really important. So don't worry about it :wink:.
 
Level 15
Joined
Sep 26, 2007
Messages
369
I bet that most of us have already tried that so many times. But unfortunately, that "secret" code is not visible in any of the JASS scripts we know. Where could it be hidden? Perhaps in some encrypted data in the deep core of the game?

What would the creator of the AMAI scripts do about the transport ships? Since he's too good with the AI scripts. Perhaps someone who's registered to WC3Campaigns.net should ask him...

I think the Blizzard Team should have programed that before releasing the TFT version. Should we beg the Blizzard Team to release a 1.22 patch which includes the fix? And also fixing the Firelord's Volcano ability (Because I don't see him casting that spell by the CPU players!), and the Alchemist's Chemical Rage ability (The CPU players should use that each time he attacks, not rarely!).
 
Level 5
Joined
Oct 27, 2007
Messages
158
Yeah, I know the GroupTimedLife sounds useful, because I used it once before. Used until I spotted a terrible part, when they summon a unit in their main base and gets attacked, the already launched army (for having traveled so far) noticed that issue, and they've interrupted their traveling progress just to intercept to where the summoned unit was taking damage. That's why I have to disable the GroupTimedLife, sorry.

Yeah I can imagine that in some scenarios this is undesired behaviour. The same technique I used can be done for summons.

Yeah, me too. Like I've said, some mysteries still haunt me. I think the questions that I've asked may have been a little bit too much.

But the need is not so urgent. If this problem gets way too complicated, let's forget it, it's not really important. So don't worry about it :wink:.

I'm not worrying :wgrin: I have the spare time to do it, so why not try spending it doing something constructive.
 
Level 5
Joined
Oct 27, 2007
Messages
158
I bet that most of us have already tried that so many times. But unfortunately, that "secret" code is not visible in any of the JASS scripts we know. Where could it be hidden? Perhaps in some encrypted data in the deep core of the game?

What would the creator of the AMAI scripts do about the transport ships? Since he's too good with the AI scripts. Perhaps someone who's registered to WC3Campaigns.net should ask him...

I think the Blizzard Team should have programed that before releasing the TFT version. Should we beg the Blizzard Team to release a 1.22 patch which includes the fix? And also fixing the Firelord's Volcano ability (Because I don't see him casting that spell by the CPU players!), and the Alchemist's Chemical Rage ability (The CPU players should use that each time he attacks, not rarely!).


I think when pigs're going to fly... or should I say sheeps. :thumbs_up:
 
Level 15
Joined
Sep 26, 2007
Messages
369
I'm not worrying :wgrin: I have the spare time to do it, so why not try spending it doing something constructive.
I'm already doing it, I kinda like toying around with the JASS scripts from time to time. But sometimes I get real busy and rarely got free time...

I think when pigs're going to fly... or should I say sheeps. :thumbs_up:
Heh heh heh... You're right about that. As for the sheep, just how many of those poor cute fluffy woolly critters got tortured by Blizzard's hands?
 
Level 15
Joined
Feb 15, 2006
Messages
851
I bet that most of us have already tried that so many times. But unfortunately, that "secret" code is not visible in any of the JASS scripts we know. Where could it be hidden? Perhaps in some encrypted data in the deep core of the game?

What would the creator of the AMAI scripts do about the transport ships? Since he's too good with the AI scripts. Perhaps someone who's registered to WC3Campaigns.net should ask him...

I think the Blizzard Team should have programed that before releasing the TFT version. Should we beg the Blizzard Team to release a 1.22 patch which includes the fix? And also fixing the Firelord's Volcano ability (Because I don't see him casting that spell by the CPU players!), and the Alchemist's Chemical Rage ability (The CPU players should use that each time he attacks, not rarely!).
Transport issues are soooo complicated that even Strategy Master hasn't been able to "fix" them. If you analyze how the transport works in the standard AI, you will notice that improving this (or just trying to implement on transport ships) is really complicated, because it's completely hardcoded. Just to give an idea: the AI has a lame system that detects if a unit is stuck, if it's true, then the AI "paralyze" that unit, and order the Zeppelin to pick it up, then the AI has to find a better place to unload it so that unit can move properly... pretty difficult I must say.

Besides, in AMAI the flying transport is not used to move units from one place to other, in fact, Strategy Master developed one common strategy for all the races that use the Zeppelins to protect units with low health.

About a patch that fixes the AI behavior... I doubt seriously it will become into reality, it seems that it's the less important thing for Blizzard. Anyways, AMAI fills that gap in the best way possible IMO.

I've worked too much with this, and I think the best solution is to develop a full scripted AI system, now that vJASS has been implemented. We could create a system which offers a set of textmacros which we can use to manipulate an AI and, eventually, create "easy scripts". This, of course, implies a hard work implementing those macros and some functions that replace the functions GetUnitGoldCost, GetUnitLumberCost, etc...

If I'd have time, I will work with this, seriously.
 
Level 15
Joined
Sep 26, 2007
Messages
369
Transport issues are soooo complicated that even Strategy Master hasn't been able to "fix" them. If you analyze how the transport works in the standard AI, you will notice that improving this (or just trying to implement on transport ships) is really complicated, because it's completely hardcoded. Just to give an idea: the AI has a lame system that detects if a unit is stuck, if it's true, then the AI "paralyze" that unit, and order the Zeppelin to pick it up, then the AI has to find a better place to unload it so that unit can move properly... pretty difficult I must say.

Besides, in AMAI the flying transport is not used to move units from one place to other, in fact, Strategy Master developed one common strategy for all the races that use the Zeppelins to protect units with low health.
I used to play many melee maps (with the AMAI scripts) for long time ago. And I still play sometimes because it's fun. When I tried to learn how he created those scripts, I quited learning, too confusing for my brains. And again, he's really good with the AI Scripts.

But when I mentioned him, I was just wondering if he knew about a solution for the naval transports. That's all.

And you're right, the transport issues are indeed soooo complicated...

About a patch that fixes the AI behavior... I doubt seriously it will become into reality, it seems that it's the less important thing for Blizzard. Anyways, AMAI fills that gap in the best way possible IMO.
I know the Blizzard Team are too busy with the WoW to mind about updating WC3. But those spells AI are just minor problems, I use the fake Death and Decay spell to simulate the Volcano spell, while I use triggers to trigger the Alchemist's Chemical Rage. But still, I'm up for that alternative solution.

I've worked too much with this, and I think the best solution is to develop a full scripted AI system, now that vJASS has been implemented. We could create a system which offers a set of textmacros which we can use to manipulate an AI and, eventually, create "easy scripts". This, of course, implies a hard work implementing those macros and some functions that replace the functions GetUnitGoldCost, GetUnitLumberCost, etc...

If I'd have time, I will work with this, seriously.
Uoh :eek:! You don't have to work so hard because of this problem! Sorry, but I'd rather stick with the JASS only, it's the only programing language that I understand, sorry again.



Thanks for the replies, guys. Now, I think I have nothing else to ask about the AI, for now. So I'll be off for some time...
 
Last edited:
Status
Not open for further replies.
Top