Help with Mining AI

Help with Mining AI

Discuss Lua based Spring scripts (LuaUI widgets, mission scripts, gaia scripts, mod-rules scripts, scripted keybindings, etc...)

Moderator: Moderators

Post Reply
User avatar
SanadaUjiosan
Conflict Terra Developer
Posts: 907
Joined: 21 Jan 2010, 06:21

Help with Mining AI

Post by SanadaUjiosan »

I need to amend knorke's amazing, magical, awesome tp_mining gadget to accommodate mobile drop-off units.

Currently, when a miner is filled up and wants to return to a drop-off unit, it will go to the nearest one. It seems it checks for that location as soon as it is "ready".

If when the miner gets there, the drop-off unit has moved (by morphing or because it's simply another mobile unit), the miner will then return to a rock to mine, mine it for a split second before realizing it is indeed still full, do the search again, and go to the next nearest drop-off unit. If the travel between the rock and the drop-off is long enough, it's not that hard to have a miner perpetually search for the drop-off and never find it.

The most obvious remedy to me is to make the miner redo the search when it reaches the drop-off coordinates, if it still has the "cargo" of course, and then proceed to the nearest drop-off location again, instead of heading back to the rock.

Of course, the mobile-drop off unit would be slow so it's easy to catch up :-)

I think this is the piece controlling the "return to drop-off" AI for units (line 319):

Code: Select all

function return_to_dropoff (unitID)
    local x, y, z = Spring.GetUnitPosition(unitID)
    local tx, ty, tz = nearest_dropoff_position_from_miner (unitID)
    if (tx ~= nil) then
--      Spring.GiveOrderToUnit(unitID, CMD.FIRE_STATE , { 0 }, {}) 
--      Spring.GiveOrderToUnit(unitID, CMD.MOVE_STATE, { 0 }, {})
        Spring.GiveOrderToUnit(unitID, CMD.MOVE , {tx, ty, tz  }, {})
        miners[unitID].status = "to_hq"
        if (debug) then Spring.Echo ("returning to base with cargo:" .. miners[unitID].cargo) end
    end
end
And I think this is the piece controlling the drop-off search (line 190):

Code: Select all

function nearest_dropoff_position_from_miner (minerID)
    local minerteam = Spring.GetUnitTeam (minerID)
    local nearest_distance = 9999999999
    local nearest_dropoffID = nil
    for i in pairs (dropoffs) do
        local dropoffteam = Spring.GetUnitTeam (i)  
        if (minerteam == dropoffteam) then 
            local d = Spring.GetUnitSeparation (minerID, i)
            if (d < nearest_distance) then
                nearest_distance = d
                nearest_dropoffID = i
            end
        end
    end
    if (nearest_dropoffID ~= nil) then
        return Spring.GetUnitPosition (nearest_dropoffID)
    else
        return nil
    end
end
Ideas/examples/input on how to achieve this?

Link to the whole gadget:
tp_mining
gajop
Moderator
Posts: 3051
Joined: 05 Aug 2009, 20:42

Re: Help with Mining AI

Post by gajop »

1. To solve the problem of the drop-offs mobility: Have the miner's move command be on the drop off unit, instead of its current location.

2. To solve the problem of something happening with the drop-off unit that would make it unusable:
2.1. Create a mapping "dropoff unit id" -> "array of currently returning miner ids", and update it accordingly
2.2. Watch for events that would make the drop off unit unusable, most notably UnitDestroyed and whatever else you use for morphing. Once those events happen, initiate the search again for the currently returning miners and reassign their destination.
User avatar
SanadaUjiosan
Conflict Terra Developer
Posts: 907
Joined: 21 Jan 2010, 06:21

Re: Help with Mining AI

Post by SanadaUjiosan »

How would I do #1?

I didn't even think of #2 but it's a good idea. Sounds way harder though, so I'm going to prioritize #1 for now.

Example please :-)
gajop
Moderator
Posts: 3051
Joined: 05 Aug 2009, 20:42

Re: Help with Mining AI

Post by gajop »

I'm surprised to see that #1 isn't supported directly (or I'm missing something). You can optionally use the GUARD command or whatever bombers use when rearming.

Anyone else have an idea how to make a move command to a unit?

Anyhow here's the example code (hasn't been tested), which does #1 and #2, you will need to modify it to fit your code:

Code: Select all

local minerDropOffMap = {}
local dropOffMinerMap = {}

--TODO: use the AssignMiner function in your code and fix it appropriately
function AssignMiner(minerID)
	 -- FIXME: you need to use your own search function
	local dropOffID = SearchForDropOff(minerID)
	if dropOffID then
		-- FIXME: guard command isn't really suitable, and seems move command can't be used for units
		Spring.GiveOrderToUnit(minerID, CMD.GUARD, { dropOffID }, {})
		minerDropOffMap[minerID] = dropOffID
		table.insert(dropOffMinerMap, dropOffID)
	end
end

function RemoveMiner(minerID)
	minerDropOffMap[minerID] = nil
	local dropOffID = minerDropOffMap[minerID]
	if dropOffID then		
		table.remove(dropOffMinerMap[dropOffID], minerID)
	end	
end

function RemoveDropOff(dropOffID)
	dropOffMinerMap[dropOffID] = nil
	local miners = dropOffMinerMap[dropOffID]
	for _, minerID in pairs(miners) do
		minerDropOffMap[minerID] = nil
		AssignMiner(minerID)
	end
end

function gadget:UnitDestroyed(unitID, unitDefID, teamID, attackerID, attackerDefID, attackerTeamID)
	if isMiner(unitDefID) then
		RemoveMiner(unitID)
	elif isDropOff(unitDefID) then
		RemoveDropOff(unitID)
	end
end
User avatar
FLOZi
MC: Legacy & Spring 1944 Developer
Posts: 6240
Joined: 29 Apr 2005, 01:14

Re: Help with Mining AI

Post by FLOZi »

Correct way would be to use

Code: Select all

Spring.SetUnitMoveGoal
 ( number unitID, number x, number y, number z,
   [, number radius = 0 [, number speed = unit->maxSpeed * 2 ] ] ) -> nil
"used by default commands to get in build-,attackrange etc. "

That's how Guard works presumably.

Example here (though this is v.s. static units):

https://sourceforge.net/p/spring1944/co ... eClear.lua
Difference would be to reset the move goal to current target position each time in CommandFallback.
Post Reply

Return to “Lua Scripts”