Central Build AI as lua widget!
Moderator: Moderators
Re: Central Build AI as lua script?
Well, I bypassed all the gl.whatever and Spring still crashes after a while. Where/how should I submit the infolog?
Edit: Commented out several sections and managed to narrow down the crash to the part of the code that assigns one builder to assist another. Possibly the problem lies with spGiveOrderToUnit(unitID, CMD_REPAIR, { busyX, busyY, busyZ }, { "" }) and I'm feeding it invalid map coordinates, or I'm assigning it to repair something that isn't there yet, etc. More testing on my next day off.
Edit: Commented out several sections and managed to narrow down the crash to the part of the code that assigns one builder to assist another. Possibly the problem lies with spGiveOrderToUnit(unitID, CMD_REPAIR, { busyX, busyY, busyZ }, { "" }) and I'm feeding it invalid map coordinates, or I'm assigning it to repair something that isn't there yet, etc. More testing on my next day off.
Re: Central Build AI as lua widget!
best place would be manits (http://spring.clan-sy.com/mantis/), bonus points for providing a translated stacktrace.
Re: Central Build AI as lua widget!
Okay, I've stashed back a copy of the infolog.txt and a snapshot of the widget at the time of the crash and will attempt that translate thing again first chance I get.
Edit: Finally got a chance to report to Mantis.
I eventually decided the problem is that CMD.REPAIR expects either a unitID (1 parameter) or a map position plus a radius (x,y,z,r or 4 parameters). I'd misread the wiki and was only giving it a mappos (x,y,z or 3 parameters). Crazy thing is that it worked most of the time, only crashing occasionally. I'm pretty sure I've messed up parameters other times and gotten a simple Lua error message instead of a crash. Oh, well. It's in the hands of the developers now.
Edit: Now reported as resolved!
Edit: Finally got a chance to report to Mantis.
I eventually decided the problem is that CMD.REPAIR expects either a unitID (1 parameter) or a map position plus a radius (x,y,z,r or 4 parameters). I'd misread the wiki and was only giving it a mappos (x,y,z or 3 parameters). Crazy thing is that it worked most of the time, only crashing occasionally. I'm pretty sure I've messed up parameters other times and gotten a simple Lua error message instead of a crash. Oh, well. It's in the hands of the developers now.
Edit: Now reported as resolved!
Last edited by troycheek on 16 Jul 2009, 08:51, edited 2 times in total.
Re: Central Build AI as lua widget!
I've now managed to play three whole XTA games without my Central Build AI widget getting stuck or crashing. Now to download a few mods and see what happens.
For those playing at home, if issuing a CMD.REPAIR order to a unit, you should 1) make sure it has repair capability, 2) give it either a unit number OR a map position and a radius, and 3) check to see if there's something there to be repaired. I think it was #2 which was causing most of my crashes. I'd somehow gotten the idea that just the map position would work without a radius. Crazy thing is that it would work sometimes.
For those playing at home, if issuing a CMD.REPAIR order to a unit, you should 1) make sure it has repair capability, 2) give it either a unit number OR a map position and a radius, and 3) check to see if there's something there to be repaired. I think it was #2 which was causing most of my crashes. I'd somehow gotten the idea that just the map position would work without a radius. Crazy thing is that it would work sometimes.
Re: Central Build AI as lua widget!
Things went a little quicker than I expected so here's my first more or less working attempt at a replacement for the old Central Build Group AI. I didn't hardcode any unit names so it should work with any mod/game that uses mobile builders (isBuilder and canMove). I've tested it quite a bit with XTA and a little with CA and BA.
Still to do (in no particular order):
1) Replace simple distance check between builder and build order with an actual path check. (Can anybody give me some hints about the Spring pathfinder? A simple "can't get there from here" function would be lovely.)
2) Add a way to specify a Central Build group other than 1 while within the game, rather than by changing a line in the lua file.
3) Add a way to specify multiple Central Build groups, each with their build queue.
4) Monitor Central Builder health and order idle Builders to repair damaged coworkers.
5) Come up with some way to recognize build orders intended for the Central Build queue without using the Wait command as a bookmark.
I'd really like to hear back from any more experienced coders who can point out the more obvious mistakes I've made, and also from anyone who remembers the Central Build Group AI general "look and feel" who can tell me how close I got to replicating it.
Edit: Changed the file description below. Realized that I'd labelled it v0.1 when I'd actually uploaded v0.3. No change in the file itself, so don't re-download if you already have it.
Edit again: Removed and replaced with a newer version. See first post for download.
Still to do (in no particular order):
1) Replace simple distance check between builder and build order with an actual path check. (Can anybody give me some hints about the Spring pathfinder? A simple "can't get there from here" function would be lovely.)
2) Add a way to specify a Central Build group other than 1 while within the game, rather than by changing a line in the lua file.
3) Add a way to specify multiple Central Build groups, each with their build queue.
4) Monitor Central Builder health and order idle Builders to repair damaged coworkers.
5) Come up with some way to recognize build orders intended for the Central Build queue without using the Wait command as a bookmark.
I'd really like to hear back from any more experienced coders who can point out the more obvious mistakes I've made, and also from anyone who remembers the Central Build Group AI general "look and feel" who can tell me how close I got to replicating it.
Edit: Changed the file description below. Realized that I'd labelled it v0.1 when I'd actually uploaded v0.3. No change in the file itself, so don't re-download if you already have it.
Edit again: Removed and replaced with a newer version. See first post for download.
Last edited by troycheek on 04 Jul 2009, 07:19, edited 3 times in total.
-
- Posts: 823
- Joined: 21 Oct 2008, 02:54
Re: Central Build AI as lua widget!
The AI works great with BA. Here are some of my requests.
I want to define an area for the builders to build in, so that it can automatically build a building without me putting the location of the building. It will helps me lots in BA intense micro battles. :)
I want to define an area for the builders to build in, so that it can automatically build a building without me putting the location of the building. It will helps me lots in BA intense micro battles. :)
Re: Central Build AI as lua widget!
1) -
2) widget:TextCommand(command), this gets called when user types '/luaui <command>', this would be a nice way to change the group ingame (i.e. /luaui cbgroup 5), unless you want to make a button or some such (a lot of work for such a small thing)
3) Fairly easy isn't it? You would just need to loop for all groups marked as cb groups, running the same code you have now
4) widget:UnitDamaged(unitID, unitDefID, unitTeam, damage, paralyzer), then check what group the unit is in
5) widget:CommandNotify(cmdID, cmdParams, cmdOpts), follow with a getSelectedUnits call, loop through to see if any are central build and can execute order.
local bookmark = 99999 -- what is MAX_INT in Lua?
-- Use math.huge
I would also take a look at these callins:
widget:UnitIdle(unitID, unitDefID, teamID)
widget:UnitCmdDone(unitID, unitDefID, unitTeam, cmdID, cmdTag)
widget:UnitFinished(unitID, unitDefID, teamID)
(Look at http://springrts.com/wiki/LuaCallinReturn, and http://springrts.com/wiki/Lua_Scripting if you havn't)
Ideally you would have the entire widget 'event' based, i.e. no widget:Update() polling. I would also use internal groups, rather than springs groups, just make some simple things like meta+0-9 = adds to group (Label these units) and c+0-9 selects the group.
2) widget:TextCommand(command), this gets called when user types '/luaui <command>', this would be a nice way to change the group ingame (i.e. /luaui cbgroup 5), unless you want to make a button or some such (a lot of work for such a small thing)
3) Fairly easy isn't it? You would just need to loop for all groups marked as cb groups, running the same code you have now
4) widget:UnitDamaged(unitID, unitDefID, unitTeam, damage, paralyzer), then check what group the unit is in
5) widget:CommandNotify(cmdID, cmdParams, cmdOpts), follow with a getSelectedUnits call, loop through to see if any are central build and can execute order.
local bookmark = 99999 -- what is MAX_INT in Lua?
-- Use math.huge
I would also take a look at these callins:
widget:UnitIdle(unitID, unitDefID, teamID)
widget:UnitCmdDone(unitID, unitDefID, unitTeam, cmdID, cmdTag)
widget:UnitFinished(unitID, unitDefID, teamID)
(Look at http://springrts.com/wiki/LuaCallinReturn, and http://springrts.com/wiki/Lua_Scripting if you havn't)
Ideally you would have the entire widget 'event' based, i.e. no widget:Update() polling. I would also use internal groups, rather than springs groups, just make some simple things like meta+0-9 = adds to group (Label these units) and c+0-9 selects the group.
Re: Central Build AI as lua widget!
You want to be able to say Here's my build area, now give me a T1 vehicle factory. That's heading away from Centralized Building and into the area of Automated Building. For the moment, I'm trying to mostly emulate the capabilities and behavior of the old Group AI. I'll put this down as a possibility in version 2.0. (Currently at version 0.3 and about to start again from scratch thanks to Niobium.)Super Mario wrote:I want to define an area for the builders to build in, so that it can automatically build a building without me putting the location of the building. It will helps me lots in BA intense micro battles. :)
Re: Central Build AI as lua widget!
Ideally, I'd understand Lua and the Spring API before I even started writing something this complex. It's been a learning experience all around.Niobium wrote:Ideally you would have the entire widget 'event' based, i.e. no widget:Update() polling.
I used the existing Spring groups primarily because I assumed players were already familiar with them and I had noticed the GroupChanged() call-in in some other widget. I know the old Group AIs used group numbers 10 and up, but didn't know how to implement that. I'm not that familiar with the meta key concept, so I'll just have to download some widgets that use it. (This is my primary method of learning Lua.)Niobium wrote:I would also use internal groups, rather than springs groups, just make some simple things like meta+0-9 = adds to group (Label these units) and c+0-9 selects the group.
Thanks for the advice.
Last edited by troycheek on 03 Jul 2009, 02:50, edited 1 time in total.
-
- Posts: 823
- Joined: 21 Oct 2008, 02:54
Re: Central Build AI as lua widget!
I hope your learning experiences goes well.
Re: Central Build AI as lua widget!
If nothing else, I've had some fun and have given the AI coders and Spring developers an idea or two.Super Mario wrote:I hope your learning experiences goes well.
I'm about halfway through v0.4 now. Using some of the information from Niobium, I've made it a lot more event-driven. It's a lot snapper and responsive now. Idle builders are now recognized and re-assigned almost immediately. I may go back in and add some kind of delay. There were fewer traffic jams when the builders were dispatched a second or so apart.
Re: Central Build AI as lua widget!
Central Build AI v0.5 is now available for download. See first post for the link.
What's new:
1) Almost everything is rewritten and most actions are event-driven (thanks to suggestions by Niobium). No more Wait commands. Much more responsive.
2) Added code to remove widget in Spectator mode. Not sure it would cause a problem in Spectator mode, but I had the code.
3) Idle units now Guard active units just like in the original, whereas before I was faking it by sending Repair orders.
4) Removed the console spam.
I think I've now pretty much replicated the behavior of the original Central Build Group AI, including an annoying habit of assigning a distant build to the slowest unit in the group, then assigning all the faster units to guard the slowest.
Still to do:
a) Ability to assign a different unit group to Central Build, or create a custom group separate from Spring's normal groups.
b) Ability to create multiple Central Build groups. Low priority for me as I don't remember ever using more than one, anyway.
c) Add some intelligence to the job assignment. Currently, idle units are just assigned to the closest job they can do. I would like to factor in travel time, build speed, resource levels, and other stuff that a human player would do without thinking.
d) Add footprint outlines to the ghosted queued build orders. I keep stacking things on top of each other because I forget how far out a solar collector unfolds.
What's new:
1) Almost everything is rewritten and most actions are event-driven (thanks to suggestions by Niobium). No more Wait commands. Much more responsive.
2) Added code to remove widget in Spectator mode. Not sure it would cause a problem in Spectator mode, but I had the code.
3) Idle units now Guard active units just like in the original, whereas before I was faking it by sending Repair orders.
4) Removed the console spam.
I think I've now pretty much replicated the behavior of the original Central Build Group AI, including an annoying habit of assigning a distant build to the slowest unit in the group, then assigning all the faster units to guard the slowest.

Still to do:
a) Ability to assign a different unit group to Central Build, or create a custom group separate from Spring's normal groups.
b) Ability to create multiple Central Build groups. Low priority for me as I don't remember ever using more than one, anyway.
c) Add some intelligence to the job assignment. Currently, idle units are just assigned to the closest job they can do. I would like to factor in travel time, build speed, resource levels, and other stuff that a human player would do without thinking.
d) Add footprint outlines to the ghosted queued build orders. I keep stacking things on top of each other because I forget how far out a solar collector unfolds.
Re: Central Build AI as lua widget!
Looks good.
Replace widget:Update() with widget:GameFrame(n), where n is current gameframe.
Move UpdateOneGroupsDetails into GroupChanged and remove from update(). (There is only one place where groupHasChanged is modified, so I don't know why you are polling it in update)
widget:UnitCmdDone() and widget:UnitIdle() should cover all cases where a unit becomes idle, in which case you can move idle checking from update() into those callins. Though you'll have to test that. If this is the case then you no longer need Update().
You should also use widget:UnitDestroyed() and widget:UnitTaken() to remove builders as they die/are given to another team, can help solve some weird errors in advance (What would happen if you gave a central builder to a teammate? Your widget would detect it as alive, as well as being able to get its command queue, but all orders issued would not go through)
Also, you need to include spec checking as the game is running, i.e. you were a player and then you died and are now a spec. Most widgets just do a check every second / 30 gameframes, which is good enough. Nothing will go wrong if you try and issue orders as a spec, but it's good form to remove it.
Replace widget:Update() with widget:GameFrame(n), where n is current gameframe.
Move UpdateOneGroupsDetails into GroupChanged and remove from update(). (There is only one place where groupHasChanged is modified, so I don't know why you are polling it in update)
widget:UnitCmdDone() and widget:UnitIdle() should cover all cases where a unit becomes idle, in which case you can move idle checking from update() into those callins. Though you'll have to test that. If this is the case then you no longer need Update().
You should also use widget:UnitDestroyed() and widget:UnitTaken() to remove builders as they die/are given to another team, can help solve some weird errors in advance (What would happen if you gave a central builder to a teammate? Your widget would detect it as alive, as well as being able to get its command queue, but all orders issued would not go through)
Also, you need to include spec checking as the game is running, i.e. you were a player and then you died and are now a spec. Most widgets just do a check every second / 30 gameframes, which is good enough. Nothing will go wrong if you try and issue orders as a spec, but it's good form to remove it.
Re: Central Build AI as lua widget!
Another item I'd seen but had no idea what it meant. Is there a manual somewhere that I haven't found? All I can find in the wiki are lists which, if I'm lucky, tell me what parameters are used.Niobium wrote:Replace widget:Update() with widget:GameFrame(n), where n is current gameframe.
By the way, what's Update() supposed to be used for?
I did it that way originally because that's the way gunblob did it in his Unit Groups widget. My first inclination was also to move all the code into widget:GroupChanged(). However, when I did so, I found that Spring.GetGroupUnits() was returning an empty unit list or what appeared to be the unit list from before the change. Only by waiting a frame or two could I get an accurate current list of units in the group.Niobium wrote:Move UpdateOneGroupsDetails into GroupChanged and remove from update(). (There is only one place where groupHasChanged is modified, so I don't know why you are polling it in update)
It covers all the cases where a unit becomes idle, but if there's no work in the queue to assign it at that time, doesn't it stay idle? I'd still have to cycle through my units and look for idle ones at some point. Although I could put the idle check in widget:CommandNotify(), since that's the only time new orders would enter the queue. I'll look into that. But I'm still considering a delay to allow the idle units to stack up a bit so I can decide on new orders as a group instead of individually.Niobium wrote:widget:UnitCmdDone() and widget:UnitIdle() should cover all cases where a unit becomes idle
I was hoping that widget:GroupChanged() would catch all those situations. A unit that's dead or captured or whatever shouldn't be in my unit group anymore, which would trigger GroupChanged, which would trigger UpdateOneGroupsDetails, which would update my list of central builders.Niobium wrote:You should also use widget:UnitDestroyed() and widget:UnitTaken() to remove builders as they die/are given to another team, can help solve some weird errors in advance
I did use those call-ins in my Metal Maker and Retreat widgets. I'd just hoped I could avoid some of the housekeeping by using widget:GroupChanged().
Thanks again for the help.
Re: Central Build AI as lua widget!
http://springrts.com/wiki/LuaCallinReturn
Which is linked to from http://springrts.com/wiki/Lua_Scripting
Update() just gets called constantly no matter what. GameFrame() gets called when a gameframe has passed, so its affected by game speed, paused/unpaused, game having started, etc. Update() will just fire all the time. Afaik anyway.
Which is linked to from http://springrts.com/wiki/Lua_Scripting
Update() just gets called constantly no matter what. GameFrame() gets called when a gameframe has passed, so its affected by game speed, paused/unpaused, game having started, etc. Update() will just fire all the time. Afaik anyway.
Re: Central Build AI as lua widget!
Those are the pages I've been checking. Usually, I have to wait for someone to point out a particular call-in or variable or command or whatever before I realize what it does. For example, I would have never guessed what CommandNotify() does if you hadn't suggested it for a specific purpose. Mostly, I'm just grabbing code from widgets that do something I think I need to do.
I'll switch to GameFrame() for the next version. I found a bug I want to squash in UnitCmdDone() anyway. It's stopping guard orders that it shouldn't, and I just realized why.
I'll switch to GameFrame() for the next version. I found a bug I want to squash in UnitCmdDone() anyway. It's stopping guard orders that it shouldn't, and I just realized why.
Re: Central Build AI as lua widget!
Seems you might not have seen this:
http://springrts.com/phpbb/download/file.php?id=773 ?!
Has been (rightly) referred to as the "Lua Bible" :).
Don't know if it's the most current version though.
Regards
Sean
http://springrts.com/phpbb/download/file.php?id=773 ?!
Has been (rightly) referred to as the "Lua Bible" :).
Don't know if it's the most current version though.
Regards
Sean
Re: Central Build AI as lua widget!
That's the same version I have. (I'll have to re-read it in depth now that I've got a little better understanding of the subject.) While it does list a lot of call-ins, very few are actually described, much like the wiki. If everyone else can read a list of call-ins and intuitively understand exactly when they're triggered and what they'd be useful for, then I apologize for being slow. But as I said, it took someone suggesting CommandNotify() for a specific purpose before I realized what it did, then pure luck stumbling upon a post in another thread to understand how to get it to do what I wanted.
widget:CommandNotify(cmdID, cmdParams, cmdOptions) where cmdID = id code of the command issued (negative numbers indicate a build order), cmdParams = parameters of the command (map location, unitID, or whatever appropriate for that command), and cmdOptions = (need help here). This function is triggered once after each command issued by the player to a unit, but before the unit actually receives the command. Useful if the programmer wishes to modify or redirect commands. When functions exits, the command will be passed on to the unit unless function returns TRUE indicating that it has already handled the command.
I'm not even sure that's all correct, but it's my best guess after messing around with the thing for a few days. Not that exploration and experimentation in and of themselves aren't fun and educational, it's just that it gets a little frustrating sometimes when you bang out revision after revision trying to get something tuned just right only to realize that there was a call-in that detected exactly what you were looking for, you just didn't know about it.
Oh, it looks like it's time to upload a new version of the Central Build AI widget. New to v0.6:
1) have replaced Update() with GameFrame().
2) moved spectator check out of Update/GameFrame loop and now have a check in Initialize() and another in PlayerChanged(). (Thanks to SeanHeron for reminding me to check the Lua Bible again.)
3) fixed a bug where Central Builders would get nonCB orders canceled.
4) hopefully CBAI is now a bit smarter job assignments. Now taking all idle builders into account before sending them out on jobs.
5) slightly more likely to choose construction aircraft and hovercraft (canFly and canHover) as primary builders under the assumption that they can reach a project site more quickly than a ground vehicle.
There are still problems when the assigned builder can't reach the build location, but that will have to wait until I understand pathfinding better (possibly never). This was also a problem with the original Group AI.
widget:CommandNotify(cmdID, cmdParams, cmdOptions) where cmdID = id code of the command issued (negative numbers indicate a build order), cmdParams = parameters of the command (map location, unitID, or whatever appropriate for that command), and cmdOptions = (need help here). This function is triggered once after each command issued by the player to a unit, but before the unit actually receives the command. Useful if the programmer wishes to modify or redirect commands. When functions exits, the command will be passed on to the unit unless function returns TRUE indicating that it has already handled the command.
I'm not even sure that's all correct, but it's my best guess after messing around with the thing for a few days. Not that exploration and experimentation in and of themselves aren't fun and educational, it's just that it gets a little frustrating sometimes when you bang out revision after revision trying to get something tuned just right only to realize that there was a call-in that detected exactly what you were looking for, you just didn't know about it.
Oh, it looks like it's time to upload a new version of the Central Build AI widget. New to v0.6:
1) have replaced Update() with GameFrame().
2) moved spectator check out of Update/GameFrame loop and now have a check in Initialize() and another in PlayerChanged(). (Thanks to SeanHeron for reminding me to check the Lua Bible again.)
3) fixed a bug where Central Builders would get nonCB orders canceled.
4) hopefully CBAI is now a bit smarter job assignments. Now taking all idle builders into account before sending them out on jobs.
5) slightly more likely to choose construction aircraft and hovercraft (canFly and canHover) as primary builders under the assumption that they can reach a project site more quickly than a ground vehicle.
There are still problems when the assigned builder can't reach the build location, but that will have to wait until I understand pathfinding better (possibly never). This was also a problem with the original Group AI.
Re: Central Build AI as lua widget!
Everything you said about CommandNotify is correct.
cmdOptions is alt/shift/control/meta modifiers. (i.e. cmdOptions.shift). There is also cmdOptions.coded for the functions which require options in that form.
cmdOptions is alt/shift/control/meta modifiers. (i.e. cmdOptions.shift). There is also cmdOptions.coded for the functions which require options in that form.
Re: Central Build AI as lua widget!
Well, sorry if it wasn't that much help - but I must say I'm quite impressed with what you've put together, seeing you've started from scratch! (I tried my hand at a Lua AI, and god, was progress slow...).
I was under the assumption you didn't know the "bible", cause you hadn't used the "GameFrame" call in, and that is one of the ones that is described - though to be honest I wouldn't know why to choose that over "Update" either
. And same as you, after working for a bit I appreciated looking through the big daunting document again more than first time round!
I know SpliFF has the Coding Guide on his SVN, I'll have to ask/ check if anythings changed - and of course, we should probably look for a way that the stuff that you found out can be added in the relevant section! (After all that's the way SpliFF put it together)
Sean
I was under the assumption you didn't know the "bible", cause you hadn't used the "GameFrame" call in, and that is one of the ones that is described - though to be honest I wouldn't know why to choose that over "Update" either

I know SpliFF has the Coding Guide on his SVN, I'll have to ask/ check if anythings changed - and of course, we should probably look for a way that the stuff that you found out can be added in the relevant section! (After all that's the way SpliFF put it together)
Sean