speeding up a script, any ideas?

Started by eduran, December 11, 2013, 08:02:27 AM

Previous topic - Next topic

eduran

I'd like to speed up the code below. It's getting called fairly regularly and every time it runs I get a very noteable frame drop.

What I am trying to do:
AccessibleCellsX/Y are two lists created once at the beginning of the map. They contain about 2100 items each (~20% of the cells on a 120x90 map). These cells can be accessed by a custom unit. Now I want to pick a random accessible cell that is in range of either a relay or a collector as a target for said unit. The fastest way I can think of looks like this:

:UpdateTargetCells
# reset lists
CreateList ->TargetCellsX
CreateList ->TargetCellsY
do(<-nOfAccessibleCells 0)  # nOfAccessibleCells > 2000
# for each cell on AccessibleCells, check if a collector/relay is in range
GetListElement(<-AccessibleCellsX i) ->x
GetListElement(<-AccessibleCellsY i) ->y
do(GetUnitsInRange(<-x <-y <-range) 0)
GetUnitType ->type
if(<-type eq("COLLECTOR") or(<-type eq("RELAY")))
# found one, append cell to TargetCells
AppendToList(<-TargetCellsX <-x)
AppendToList(<-TargetCellsY <-y)
# abort the inner loop to save time and clear leftover uids from stack
ClearStack
break
endif
loop
loop
GetListCount(<-TargetCellsX) ->nOfTargetCells

:PickTargetCell
# pick a random cell as target
RandInt(0 <-nOfTargetCells) ->index
GetListElement(<-TargetCellsX <-index) ->tarCellX
GetListElement(<-TargetCellsY <-index) ->tarCellY


The script works, but includes ~2100 GetUnitsInRange calls, which I figure are causing the framedrop. Can anyone think of a better/faster way to pick a target cell?


Clean0nion

Not sure of this would work, but you could try sticking a GetUnitsInRange at the beginning of the command, then add all the UIDs to a new list. Then instead of using another GetUnitsInRange, just use that list.

Grayzzur

Since you're going for a random target, you don't necessarily need the target list to be 100% accurate.

Instead of clearing and reloading the entire target list, update it in segments. You might do a quick scan of the existing target list, make sure all the unitID still exist (and are collectors or relays -- might be possible for one to be destroyed and another new unit takes over the unitID, since I don't know how the game assigns unitID's internally), and remove from the list any that are gone. The existing target list should be small enough that you can run through it quickly. Then run through a small subset of your accessible cells, 50 or 100 or whatever seems to work, and add targets to your target list that aren't already in it. Do a subset of accessible cells every couple of updates, and your list will be refreshed frequently.

If the new update is being called every frame, or at least before PickTargetCell (so that the invalid target cleanup is performed), then it should be fine -- otherwise PickTargetCell would need a little extra code to validate that the random target is still in existence and valid, and if not remove from the list and try again.
"Fate. It protects fools, little children, and ships named 'Enterprise.'" -William T. Riker