eronoobos / ShardSpringLua

gadget for Spring RTS that loads Shard AI as a Lua AI, see https://github.com/eronoobos/Shard
0 stars 1 forks source link

Evo doesn't use metal spots, so how can I tell the builders to spread out? #5

Closed ForbodingAngel closed 8 years ago

ForbodingAngel commented 8 years ago

This is my biggest issue. Shard engineers will sit in one spot just building stuff, many times not even leaving the build pad. That's not good at all :'(

Halp?

Got it working BTW. It was my customizations that were breaking it (you were right).

eronoobos commented 8 years ago

A couple of ideas 1) Add a new behaviour to the engineers that gets high priority temporarily when UnitIdle has been called enough times. When activated, the behaviour would move them randomly away from their current position. 2) Modify taskqueuebehaviour to move the engineers around at the end of every taskqueue loop.

I'm glad it's working!

ForbodingAngel commented 8 years ago

1) Honestly I don't know how to do that 2) Actually, after every completed task would do nicely, but once again, don't know how to do it. Do you have any examples?

Me too! :-D

Sidenote: I used to have the ability to insert waits (x number of frames/seconds/etc) before they progressed to the next item in the list but I don't have the line anywhere anymore. Do you happen to do anything similar in BA that I could use?

Thanks so much for making shard as a luaai a reality <3

Tbh I have a lot of issues with the taskqueue's repeating and no controls on how many of each building gets built. I will likely just make ai specific buildings and use unitrestricted to limit them. Crude, but it works :-)

eronoobos commented 8 years ago

about wait, it appears you would put something like this in the taskqueue: {action = "wait", frames = 30} see https://github.com/eronoobos/ShardSpringLua/blob/master/luarules/gadgets/ai/taskqueuebehaviour.lua#L112

Speaking of which, an action would probably be a good way to move your engineers around. I'll just expand the default taskqueuebehaviour to include a "move" action. You would then just insert something like this into your taskqueue: {action = "move", x = 100, y = 200, z = 300} While I'm at it, how about this also: {action = "moverelative", x = math.random(-100, 100), y = math.random(-100, 100), z = math.random(-100, 100)} i leave it up to you to give it a better random relative position

A BuildWithLimitedNumber function for taskqueues:

function BuildWithLimitedNumber(tmpUnitName, maxNumber)
    if tmpUnitName == DummyUnitName then return DummyUnitName end
    if maxNumber == 0 then return DummyUnitName end
    local myUnits = game:GetUnits()
    if myUnits then
        local count = 0
        for i = 1, #myUnits do
            local myUnit = myUnits[i]
            if myUnit:Name() == tmpUnitName then
                count = count + 1
                if count == maxNumber then
                    return DummyUnitName
                end
            end
        end
    end
    return tmpUnitName
end
eronoobos commented 8 years ago

actually, make that { action = "move", position = {x=1, y=2, z=3} } (or "moverelative") this is just for consistency with how Shard deals with positions

eronoobos commented 8 years ago

https://github.com/eronoobos/ShardSpringLua/commit/41fbd6d5b4c468c8e48f2f9b06d95ed3551e31d2

let me know how it goes

ForbodingAngel commented 8 years ago

Jesus, did you just pretty much solve all my issues? lol

I'll give it a shot, thanks :-D

tomjn commented 8 years ago

That's what the boot behaviour is for, to take control and wait for the unit to leave the factory. A variation may choose to instead wait for the idle order, then issue a move order, and relinquish control on the second idle so that it goes elsewhere

But I'd rather not conflate task queues and solving this problem, especially when the boot behaviour was built for this very reason

tomjn commented 8 years ago

Instead I believe a proper solution comes from the building algorithm.

Specifically, I would create a module that created a grid of points, and counted the units closest to each point to create a density map. Then, when building, the builder wouldn't search from its own location, it would first find the closest four points on the grid, and start the search from the highest density point, ignoring any that have more than a certain threshold to prevent overpopulation.

The result should be an expanding base that never gets too clogged, a natural upper limit on how far the building algorithm should search ( grid size/2 ), and a framework on which to hang weights and incentives, or other logic such as for defenses, etc

tomjn commented 8 years ago

Of note, the attack handler module already has similar code, that code could be extracted out into another module, and we'd get all the additional benefits, such as negatively weighting areas by enemy forces, which would also prevent Shard from sending constructors into these areas to build inane things. It also simplifies attacking into the new problem of flattening that map and increasing density ( where enemy areas are negative density )

eronoobos commented 8 years ago

That indeed is a much better solution. And curse you, I am tempted to write it.

Regarding a variation on boot behaviour: If boot behaviour was activated every time the unit went idle, wouldn't that prevent taskqueues from ever building anything?

tomjn commented 8 years ago

Boot behaviour is never meant to run once it's done it's job, which at the moment is to wait a number of frames to give the unit time to exit the factory, once it's ran it never runs again

eronoobos commented 8 years ago

Yes. I meant in the (unwritten) variation you suggested, which would activate when the unit is idle, and issue a move order away from itself.

eronoobos commented 8 years ago

Oh I see, every other idle.