THIS is how AI takes over the world! And some PROGRAMMER questions?

Science fiction has it all wrong… AI does not become self aware, some programmer makes two (self proclaimed) improvements to an existing AI and when they clash all humans die!

I made 2 functions I was proud of.

The FIRST finds AI enemy SOB groups with a battle cruiser that is all alone and sends out a small frigate support force to help protect and a collector to start repairing it.

The SECOND was a way to add a little harassment to the human player BEFORE I released the AI to do its own attacks. As the shipyard made units I could not figure out how to automatically add those made units to a SOBgroup that I could control. I know they are in the PlayerShips0 but I wanted just the few bombers that came out to be in their own group so I could send them on a scripted mission outside of the AI’s control. What I thought was an ingenious way to do it was to select all units within 5000 radius of the shipyard and place into their own SOB group and then send that to attack the human player’s carrier (in this mission that is = to their MotherShip).

I knew it would also get other ships near by but chalked that up to some randomness which was welcomed.

Well, in the mission map there is an on going battle between an Ally AI and the enemy AI that does not endanger the human player… so I thought.

The two functions just happen to cross paths with each other and the result was:
An AI enemy’s force just came out ahead of the Ally AI force(unbeknownst to me in a galaxy far far away) and had 1 Vaygr BC alive. Support function kicks in and the shipyard creates 4 frigates and a collector and adds to the AI enemy’s SOB Group(which is still invulnerable because the human player has not “discovered” it yet).

Then the Harass Player function makes 2 bombers and selects all units within 5000 radius… whoops the 4 invulnerable frigates get put into another SOBGroup that is scheduled to attack the human player.

60 seconds later 4 frigates show up and defeat 3 battle cruisers, 4 destroyers, and then kill the human player.

In my 100’s of play throughs I never ran into this because the BC that was all alone is close to me and I “discovered” it sooner than my player did which ran the function to turn it on… aka made it’s SOB Group vulnerable and ready for human combat.

This would have been a beast to find, but luckily my player was savvy enough to send me some screen shots and I found it quicker.

QUESTIONS for the Programmers out there:

  1. What is a good way to add newly created units to a special SOB group to control via script? I think I came up with another way just now but have not tested it. I believe if I wanted sequential waves of units I could just create in the LEVEL file 1 SOBGroup and make it deploy from the shipyard and do something and when it dies, reuse the same SOBGroup again… in lieu of actually telling the shipyard to make the units and trying to select them via proximity function.

  2. Is there a way in game to select an AI unit and log the SOBGROUPs it belongs to, to the log?

  3. In my limited knowledge of LUA I often use the “Rule_AddInterval ( “x”, 120 )” not only to repeat a function but ALSO as a sort of timer to run a function after a certain amount of seconds has past (120 seconds in the ex.above) and then I remove the function. Is this okay for HWRM? Or is it inefficiency in some way I am not aware?

  4. Also about the “Rule_AddInterval” function. There are times I need to run something periodically to check on things to see if I need to adjust. I do not necessarily need to do it at an interval but thought that maybe using the “AddInterval” versus “Rule_Add” might be more friendly to the processor so the function does not actually try to run as often. Is it? I know the AddInterval has to check itself as often but the code inside does not need to run was my thought.

  5. Lastly, Several times I got into a timing issue where one SobGroup_* function was not done running before the next line, another SobGroup_* function, was being processed and the next function ran before I was ready for it to. Is there some mechanism in LUA to make sure a line is finished before it runs another? I felt very inefficient constantly using AddInterval just to buy some time to make sure the next function ran 3-5 seconds later and then removing the AddIntercal function.

5 Likes
  1. Get newly created ships:

    function GetNewShips()
    SobGroup_Create(“NewShipsSOB”)
    SobGroup_Empty(“NewShipsSOB”)
    SobGroup_FillSubstract(“NewShipsSOB”, “Player_Ships0”, “TrackedShips”) – NewShipsSOB = Player_Ships0 - TrackedShips
    SobGroup_SobGroupAdd(“TrackedShips”, “NewShipsSOB”) – TrackedShips = TrackedShips + NewShipsSOB
    return SobGroup_Count(“NewShipsSOB”)
    end

And to use:

if (GetNewShips() > 0) then
    -- do code
end

Also, this assumes that TrackedShips has been created at the start of the match/mission/etc.

SobGroup_Create("TrackedShips")
SobGroup_Empty("TrackedShips")
  1. No.

  2. For functions that happen at a specific time, yes, that is okay.

  3. Rule_Add runs every 1/10 second regardless. Rule_AddInterval checks if it needs to run every 1/10 second (as far as I know?), and then runs if it’s timer is expired.

  4. That shouldn’t be happening, unless you’re calling a function out of order.

1 Like

I have had just a few of the in game SobGroup functions do that… usually destroying a ship or despawning and spawning, if I try to interact with the SobGroup after one of those it is as if it has not happened yet if the line is directly following. But if I run it a second or two later the next function works well.

I will try to find a specific example to see if it is not user error (me not understanding how the function works).

Thanks much for the rest… I did not know TrackedShips was a thing… i can change my logic to be more efficient now.

TrackedShips is not a “special” sobgroup (like Player_Ships0 is, for example). It’s just a way to find the difference in existing ships between two runs of the code (because TrackedShips will always already contain ships from the previous run).
That’s why SobGroup_Create(“TrackedShips”) and SobGroup_Empty(“TrackedShips”) are important at the beginning of the mission.

Okay so it is still possible to get mixed units in(from around the map) it then if I have multi carriers(from around the map) making units…

I might need to stay with the proximity if I want to make sure only the units near one of 5 carriers is going to be assigned to the new group for a special mission.

Speaking of that… this is one of those situations were I usually do a delay. If a Carrier is making 6 bombers… i need to wait X seconds to give the units to be made before I can check to try to group them. In that time another carrier across the map may have made 3 frigates as well. I do not want the frigates from across the map to be grouped with the bombers at the carrier that is about to send them on a mission… does this make sense?

I may try the idea I posted earlier, make a SOBGroup in the LEVEL file with 4 bombers. Call it when I need it to me made from the carrier. When the bombers all die (SOBGroup is empty) just make the same SOBGroup again to have 4 more bombers. I will just have to code all the checks to make the AI act “as if it is not cheating”.

I suppose it’s only for the AI, no ?
If so, how do you create your new ship ?
With SobGroup_CreateShip(“Carrier1”, “yournewlycreatedship”) ?

You could perhaps :

  • use SobGroup_SetAutoLaunch(“Carrier1”, ShipHoldStayDockedAlways) to temporarily stop newly created ships from undocking from the carrier
  • use SobGroup_CreateShip(“Carrier1”, “yournewlycreatedship”) to create your new ship
  • use SobGroup_IsDockedSobGroup(“yournewlycreatedship”, “Carrier1”) to check if it’s in this specific carrier (run through all your known carriers if necessary)
  • add “yournewlycreatedship” to a specific sobgroup dedicated to ships belonging to Carrier1 if the condition above is true
  • use SobGroup_SetAutoLaunch(“Carrier1”, ShipHoldLaunch) to launch your new ship which now virtually belongs to Carrier1
1 Like

I love it! I had not played with auto-launch yet so the idea had never popped. Pretty clean, thanks much!

You’re welcome ^^

I remembered using this method in the past. Tell us if it works for your needs :slight_smile:

Even better, SobGroup_CreateShip returns a runtime SobGroup containing the ship created.

Usage:

local CreatedShipSOB = SobGroup_CreateShip("CarrierSOB", "Vgr_Bomber")
SobGroup_SobGroupAdd("CarrierAttackGroup", CreatedShipSOB)
SobGroup_AttackPlayer("CarrierAttackGroup", 0)
2 Likes

Yeah, I totally forgot about that ! That’s even better ! No need to use the dock “trick” at all ! :smiley:

Whoops, I just realized I used the wrong function. Instead of SobGroup_FillUnion it should be SobGroup_SobGroupAdd. I’ve edited my answers above.

1 Like

I have family in for holidays but as soon as I have time I am going to revamp my Patrol AI code with these… far more efficient than my method.