Page 1 of 2

Hello World Lua AI

Posted: 18 Dec 2012, 04:48
by zyxar
Hi,
I've been looking at some lua ai scripts and am having some trouble writing something that works. The ai page dedicated to lua ais is pretty sparse. I'm wondering if anyone can help me with figuring out what is necessary to have in order to write a lua ai, and an explanation of what each part does.

Thanks
Zyxar

Re: Hello World Lua AI

Posted: 18 Dec 2012, 04:51
by zwzsg
You make a synced gadget.
You use that to gather info and that to issue commands.

The trick is to stop looking for an "AI" interface and just write a regular gadget.



Edit: Oh wait, you're a new person? I confused you with a regular. Well, you'll have to learn the Lua language, and what is a Spring gadget I'm afraid. Say, have you read http://springrts.com/wiki/AI:Development:Lang:Lua ? Have you looked at Spring Tanks Lua AI, which is maybe the shortest? Though if you're new, first step would be to make a hello world gadget.

Re: Hello World Lua AI

Posted: 18 Dec 2012, 05:16
by zyxar
I've looked at the spring tanks ai some, but I don't have a whole lot of knowledge about that game. I started playing ota and recently found spring, so I mostly enjoy playing xta. I'm attempting to write a more agressive ai to supplement rai's strong base-building skills.

Anyway, what I understand is that the ai has to by synced between all players. I can tell that the spring tanks has a synced section of code, but I'm not sure what each of the individual functions contributes.

I'm new to lua and know a little java. I already had a look at the link to the spring lua ai page you posted.

A hello world gadget sounds helpful.

Edit: In order to write a hello world gadget do I need to put Spring.Echo("string") inside of a callin?

Thank you
Zyxar

Re: Hello World Lua AI

Posted: 18 Dec 2012, 07:55
by Beherith
Pretty much yes.
Just put the echo in gadget:GameFrame(n)
that will echo every frame.

Re: Hello World Lua AI

Posted: 18 Dec 2012, 15:35
by zyxar
Ok, so I have written a gadget that spams "Hello World!" every game frame. If I try to sync the code and run it in single player it fails. Is this because spring doesn't take into account that you're the only human in the game? If I were to run this in a two-player game with the synced code would it then work?

Thanks,
Zyxar

function gadget:GetInfo()
return {
name = "HelloWorld",
desc = "Prints Hello World! to the game screen each game frame",
author = "zyxar",
date = "12-17-12",
license = "Public Domain",
layer = 82,
enabled = true
}
end

function gadget:GameFrame(n)
Spring.Echo("Hello World!")
end

Re: Hello World Lua AI

Posted: 18 Dec 2012, 17:03
by zyxar
Now what I'm wrestling with is bridging the gap between that gadget and an ai gadget.
Do I just replace the Spring.Echo() with stuff like
Spring.GiveOrderToUnit()?

I came up with something like
some function that gets the ai's team ID
local myunits = Spring.GetTeamUnits(myteamid)
for i, o in pairs(myunits) do
local currentUnitDefID = Spring.GetUnitDefID(myunits)
if currentUnitDefID = some unit's ID then
do stuff
elseif currentUnitDefID = some other unit's ID then
do other stuff
...........................
end
end

Re: Hello World Lua AI

Posted: 18 Dec 2012, 17:25
by knorke
Now what I'm wrestling with is bridging the gap between that gadget and an ai gadget.
See http://springrts.com/wiki/AI:Developmen ... _AI_Gadget

Basically you need that file LuaAI.lua, so that the AI will show up in the "add bot player" menu in lobby. (But it will not show up in the add-bot menu of spring.exe, that is normal.)
The gadgetAI then has to use Spring.GetTeamLuaAI to decide which team(s) it is assigned to and which units it is allowed to control.
I came up with something like
some function that gets the ai's team ID
local myunits = Spring.GetTeamUnits(myteamid)
for i, o in pairs(myunits) do
local currentUnitDefID = Spring.GetUnitDefID(myunits)
if currentUnitDefID = some unit's ID then
do stuff
elseif currentUnitDefID = some other unit's ID then
do other stuff
...........................
end
end
yes, basically like that.
Keep in mind that there might be multiple botplayers using the same AI, but for start does not matter.

Re: Hello World Lua AI

Posted: 18 Dec 2012, 20:44
by zwzsg
zyxar wrote:Anyway, what I understand is that the ai has to by synced between all players.
It doesn't have to. It would even probably be a bit better if it was in unsynced. But it is way more easier to have it in the synced part of the gadget.

Re: Hello World Lua AI

Posted: 18 Dec 2012, 21:31
by zyxar
Ok,
So I've made the ai (if it can be called that at this point) print different messages at different frames.
Now I am having trouble getting the commander to actually DO something. I have had a look at the spring tanks ai and tried to simplify it, but I'm not getting anywhere with it.

thanks for the help

Re: Hello World Lua AI

Posted: 19 Dec 2012, 01:47
by knorke
myteamid = Spring.GetMyTeamId()
hm no. See my post and wiki example how AI can get the teamIDs it is controlling.
GetMyTeamId() gets the team of the local player, but in synced "local player" does not make sense.

beside that it should work i think...

hm and this:
if currentunitdefid = 94 then
Replace the 94 with something like
local coreCommanderID = UnitDefNames["corcom"].id
("corcom" being the unitname)

Re: Hello World Lua AI

Posted: 19 Dec 2012, 02:04
by zyxar
Ok, so

Code: Select all

Spring.GetMyTeamID()
returns the ID of the player, then what does

Code: Select all

Spring.GetTeamLuaAI()
return?
I read the lua synced read page and it says that the output is
Spring.GetTeamLuaAI

( number teamID ) -> string "luaAI"
This doesn't seem right to me.

Re: Hello World Lua AI

Posted: 19 Dec 2012, 02:56
by knorke
Spring.GetMyTeamID() returns the ID of the player
It is only for unsynced (widgets), it returns the ID of the team that the local player is in. But for gadget does not know who the "local player" is, for gadget (synced) all players are equal.

Spring.GetTeamLuaAI(teamID)
Returns string containing name of AI defined in file LuaAI.lua as name="<AI name>".
So it returns "MyAwesomeAI" or "KillerBot" or nil (nothing) and gadget can check that to see if it should care about this team.

Not sure how to better explain it so I took one of my AIs and trimmed it down to only the initializing part and added some comments.
Not tested if I messed up some details but in principle it works like that:

Code: Select all

local myTeams = {}	--stores which teams the AI controls

function gadget:Initialize()
	--figure out which teams the gadget will control	
	for _,teamID in ipairs(Spring.GetTeamList()) do		--loop through all teams
        local _,_,_,ai,_ = Spring.GetTeamInfo(teamID)	--is an AI team?
        if ai and Spring.GetTeamLuaAI(t) == "HorstAI" then	--is it the LuaAI from THIS gadget?
			myTeams[teamID] = true	--save this as one of "our" teams
			Spring.Echo ("Horst AI will play for team  " .. teamID)
		end
    end
	if (myTeams == nil) then	--no entries? Means this game no bot uses this AI
		Spring.Echo ("Horst AI: not used, byebye.")
		gadgetHandler:RemoveGadget()	--disable gadget
	end
end


function gadget:GameFrame (frame)
	if (frame % 60 ~=0) then return end	--every 2 seconds 
	
	for _,teamID in pairs(myTeams) do	--loop over all our teams
		Spring.Echo ("now ordering teamID " .. teamID)
		local units = Spring.GetTeamUnits (teamID)	--
		for i,unitID in pairs(units) do
			------AI LOGIC GOES HERE-----
			Spring.Echo ("now ordering unit " .. unitID .. " of team " .. teamID)
			--move somewhere random
			local x = math.random(Game.mapSizeX)
			local z = math.random(Game.mapSizeZ)
			local y = Spring.GetGroundHeight (x,z)
			Spring.GiveOrderToUnit(unitID, CMD.MOVE , {x,y,z  }, {})
		end
	end
end


function gadget:UnitDestroyed(unitID, unitDefID, teamID, attackerID)
	Spring.Echo ("a unit died!")	
	if (myTeams[teamID]) then	--is this teamID one of ours?
		Spring.Echo ("it was from one of our teams!")
	else
		Spring.Echo ("was not from one of our teams")
	end
end
Unless there was some fuckup you could try to use it like that and put your logic where it says:
------AI LOGIC GOES HERE-----

As zwzsg sugggested that is not the only way to do it.
It can be better to have an AI with unsynced parts.
Or use some OO design for the multiple teams.

This is an AI that can only control one team at once:
http://code.google.com/p/conflictterra/ ... p_KTAI.lua
because here myTeam is a variable instead of array and can only store one value (team)
Here is a video of what it does, maybe helpful when looking at the gadget:
http://www.youtube.com/watch?v=aOtnOEOtVTM

I would really like to continue with the AIs because it is so funny and maybe even make tutorial but all the lobbies that have "add bot" button suck and do not work on my computer. So I can not add botplayers. Isnt that fascinating?

Re: Hello World Lua AI

Posted: 19 Dec 2012, 03:07
by zyxar
Wow, thanks a lot. This will probably keep me busy for a while. Thanks for the time you put into explaining this to me.

Re: Hello World Lua AI

Posted: 20 Dec 2012, 17:22
by zyxar
Ok, I've gotten the ai to move finally taking small steps from printing hello world. I noticed that The "attack" option was missing from the UI, so I tested a pristine mod and it worked like normal. It appears that whatever I did in this gadget for the ai removed the ability to attack from the game. I checked the error log and found this referencing my gadget. I'm not really sure what to do with it.

[f=0000000] Error: Lua LoadCode pcall error = 0, LuaRules/main.lua, error = 2, LuaGadgets/gadgets.lua, [string "LuaRules/Gadgets/myluaai.lua"]:19: Bad teamID type in GetTeamLuaAI()

I assume bad teamID means that I messed up the array or the loop for the team stuff, but I'm not sure what to do to fix it, and I'm also not sure what this has to do with the attack option being removed.

thanks for any help
zyxar

here's the code I was running

Re: Hello World Lua AI

Posted: 20 Dec 2012, 20:47
by knorke
local _,_,_,ai,side = Spring.GetTeamInfo(t)
if Spring.GetTeamLuaAI(t) == gadget:GetInfo().name then

try changing to

if ai and Spring.GetTeamLuaAI(t) == ...

Re: Hello World Lua AI

Posted: 20 Dec 2012, 21:05
by zyxar
Ok, that fixed the error, but it still won't let me attack the ai's commander. Do you have any idea why this is?

Thanks
Zyxar

Re: Hello World Lua AI

Posted: 20 Dec 2012, 21:19
by knorke
what game?
maybe the attackbutton is just hidden, try a-hotkey

Re: Hello World Lua AI

Posted: 20 Dec 2012, 21:41
by zyxar
It's an xta mutation
maybe I should try putting into the mod?
The attack hotkey just causes them to walk to the unit they're supposed to attack.

Re: Hello World Lua AI

Posted: 20 Dec 2012, 21:48
by zyxar
Ok, yes it appears to be the mutation, because it works if I just put it into the mod the usual way

Re: Hello World Lua AI

Posted: 05 Jan 2013, 06:48
by Google_Frog
Have my LuaAI for reference. It is probably not that useful because it is a bit monolithic but that link points out the initialization step.

http://code.google.com/p/zero-k/source/ ... I.lua#3834

I suggest at least starting out with a synced luaAI because it is easier to get your head around. The AI can then read and change almost everything. This is because AIs are just normal spring gadgets which handle teams which were created as a LuaAI.