HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

[Proofread] FindFuncs

09-03-2009, 03:06 PM#1
Michael Peppers
So, starting with the need of searching for nearest trees for a custom lumber harvesting system, I've come up with this code. Anyway, I'm kinda sure it can be improved, so I'll leave it to your expert eyes.
Info


For now it has got 10 functions, but more may be implemented:
function FindNearestTree takes real srcX, real srcY, real range returns destructable
function FindFarthestTree takes real srcX, real srcY, real range returns destructable
function FindNearestDestOfType takes real srcX, real srcY, real range, integer id returns destructable
function FindFarthestDestOfType takes real srcX, real srcY, real range, integer id returns destructable
function FindNearestDest takes real srcX, real srcY, real range returns destructable
function FindFarthestDest takes real srcX, real srcY, real range returns destructable
function FindNearestUnitOfType takes real srcX, real srcY, real range, integer id returns unit
function FindFarthestUnitOfType takes real srcX, real srcY, real range, integer id returns unit
function FindNearestUnit takes real srcX, real srcY, real range returns unit
function FindFarthestUnit takes real srcX, real srcY, real range returns unit



Collapse JASS:
library FindFuncs

globals
//t1-21 are all the integer ids of the trees...
    private constant integer t1 = 'FTtw'
    private constant integer t2 = 'YTft'
    private constant integer t3 = 'BTtw'
    private constant integer t4 = 'VTlt'
    private constant integer t5 = 'KTtw'
    private constant integer t6 = 'DTsh'
    private constant integer t7 = 'JTtw'
    private constant integer t8 = 'OTtw'
    private constant integer t9 = 'ATtr'
    private constant integer t10 = 'CTtr'
    private constant integer t11 = 'ITtw'
    private constant integer t12 = 'NTtw'
    private constant integer t13 = 'LTlt'
    private constant integer t14 = 'YTct'
    private constant integer t15 = 'ZTtw'
    private constant integer t16 = 'JTct'
    private constant integer t17 = 'WTtw'
    private constant integer t18 = 'YTwt'
    private constant integer t19 = 'WTst'
    private constant integer t20 = 'YTst'
    private constant integer t21 = 'GTsh'
    
    private integer Id = 0
    
    private destructable Dest = null
    private unit Unit = null
    private real Dist = -1
    private real unitX = 0
    private real unitY = 0
    private rect r = null
    private boolean nearest = true
    private boolexpr cond = null
endglobals

private function Trees takes nothing returns boolean
local integer id = GetDestructableTypeId(GetFilterDestructable())
return id == t1 or id == t2 or id == t3 or id == t4 or id == t5 or id == t6 or id == t7 or id == t8 or id == t9 or id == t10 or id == t11 or id == t12 or id == t13 or id == t14 or id == t15 or id == t16 or id == t17 or id == t18 or id == t19 or id == t20 or id == t21
endfunction

private function DestCheck takes nothing returns boolean
return GetDestructableTypeId(GetFilterDestructable()) == Id
endfunction

private function DestSearch takes nothing returns nothing
local destructable d = GetEnumDestructable()
local real dist
local real dx
local real dy
    set dx = unitX - GetDestructableX(d)
    set dy = unitY - GetDestructableY(d)
    set dist = (dx * dx + dy * dy)
    if nearest == true then
        if (Dist < 0) or (dist < Dist) then
            set Dest = d
            set Dist = dist
        endif
    else
        if (Dist < 0) or (dist > Dist) then
            set Dest = d
            set Dist = dist
        endif
    endif
endfunction

private function UnitSearch takes nothing returns boolean
local unit u = GetFilterUnit()
local real dist
local real dx
local real dy
    set dx = unitX - GetUnitX(u)
    set dy = unitY - GetUnitY(u)
    set dist = (dx * dx + dy * dy)
    if Id == 0 then
        if nearest == true then
            if (Dist < 0) or (dist < Dist) then
                set Unit = u
                set Dist = dist
            endif
        else
            if (Dist < 0) or (dist > Dist) then
                set Unit = u
                set Dist = dist
            endif
        endif
    elseif (GetUnitTypeId(GetFilterUnit())) == Id then
        if nearest == true then
            if (Dist < 0) or (dist < Dist) then
                set Unit = u
                set Dist = dist
            endif
        else
            if (Dist < 0) or (dist > Dist) then
                set Unit = u
                set Dist = dist
            endif
        endif
    endif
return false
endfunction

function FindNearestTree takes real srcX, real srcY, real range returns destructable
    set unitX = srcX
    set unitY = srcY
    set Dist = -1
    set Dest = null
    set nearest = true
    set cond = Condition(function Trees)
    call SetRect(r, unitX - range, unitY - range, unitX + range, unitY + range)
    call EnumDestructablesInRect(r, cond, function DestSearch)
call DestroyBoolExpr(cond)
return Dest
endfunction

function FindFarthestTree takes real srcX, real srcY, real range returns destructable
    set unitX = srcX
    set unitY = srcY
    set Dist = -1
    set Dest = null
    set nearest = false
    set cond = Condition(function Trees)
    call SetRect(r, unitX - range, unitY - range, unitX + range, unitY + range)
    call EnumDestructablesInRect(r, cond, function DestSearch)
call DestroyBoolExpr(cond)
return Dest
endfunction

function FindNearestDestOfType takes real srcX, real srcY, real range, integer id returns destructable
    set Id = id
    set unitX = srcX
    set unitY = srcY
    set Dist = -1
    set Dest = null
    set nearest = true
    set cond = Condition(function DestCheck)
    call SetRect(r, unitX - range, unitY - range, unitX + range, unitY + range)
    call EnumDestructablesInRect(r, cond, function DestSearch)
call DestroyBoolExpr(cond)
return Dest
endfunction

function FindFarthestDestOfType takes real srcX, real srcY, real range, integer id returns destructable
    set Id = id
    set unitX = srcX
    set unitY = srcY
    set Dist = -1
    set Dest = null  
    set nearest = false
    set cond = Condition(function DestCheck)
    call SetRect(r, unitX - range, unitY - range, unitX + range, unitY + range)
    call EnumDestructablesInRect(r, cond, function DestSearch)
call DestroyBoolExpr(cond)
return Dest
endfunction

function FindNearestDest takes real srcX, real srcY, real range returns destructable
    set unitX = srcX
    set unitY = srcY
    set Dist = -1
    set Dest = null
    set nearest = true
    call SetRect(r, unitX - range, unitY - range, unitX + range, unitY + range)
    call EnumDestructablesInRect(r, null, function DestSearch)
return Dest
endfunction

function FindFarthestDest takes real srcX, real srcY, real range returns destructable
    set unitX = srcX
    set unitY = srcY
    set Dist = -1
    set Dest = null  
    set nearest = false
    call SetRect(r, unitX - range, unitY - range, unitX + range, unitY + range)
    call EnumDestructablesInRect(r, null, function DestSearch)
return Dest
endfunction

function FindNearestUnitOfType takes real srcX, real srcY, real range, integer id returns unit
local group g = CreateGroup()
    set Id = id
    set unitX = srcX
    set unitY = srcY
    set Dist = -1
    set Unit = null
    set nearest = true
    set cond = Condition(function UnitSearch)
    call GroupEnumUnitsInRange(g, unitX, unitY, range, cond)
call DestroyBoolExpr(cond)
call DestroyGroup(g)
return Unit
endfunction

function FindFarthestUnitOfType takes real srcX, real srcY, real range, integer id returns unit
local group g = CreateGroup()
    set Id = id
    set unitX = srcX
    set unitY = srcY
    set Dist = -1
    set Unit = null
    set nearest = false
    set cond = Condition(function UnitSearch)
    call GroupEnumUnitsInRange(g, unitX, unitY, range, cond)
call DestroyBoolExpr(cond)
call DestroyGroup(g)
return Unit
endfunction

function FindNearestUnit takes real srcX, real srcY, real range returns unit
local group g = CreateGroup()
    set Id = 0
    set unitX = srcX
    set unitY = srcY
    set Dist = -1
    set Unit = null
    set nearest = true
    set cond = Condition(function UnitSearch)
    call GroupEnumUnitsInRange(g, unitX, unitY, range, cond)
call DestroyBoolExpr(cond)
call DestroyGroup(g)
return Unit
endfunction

function FindFarthestUnit takes real srcX, real srcY, real range returns unit
local group g = CreateGroup()
    set Id = 0
    set unitX = srcX
    set unitY = srcY
    set Dist = -1
    set Unit = null
    set nearest = false
    set cond = Condition(function UnitSearch)
    call GroupEnumUnitsInRange(g, unitX, unitY, range, cond)
call DestroyBoolExpr(cond)
call DestroyGroup(g)
return Unit
endfunction

endlibrary
09-03-2009, 03:50 PM#2
Zerzax
I'm pretty sure you can get rid of the squareroot usage in your functions. Instead compare all squares of distances to find the shortest one, i.e. set dist = dx*dx + dy*dy and Dist = Dist*Dist. The rationale is that if the square of one distance is less than the square of another distance, the actual distance of the first is less than the second.

I also noticed that you are creating rects, enumerating, and then not destroying them, as well as constantly destroying a separate boolexpr from the one you are using. Use a global rect and use MoveRectTo or SetRect to enumerate. A global boolexpr is also recommended so you only need one.

In your Trees function, set a local integer equal to the destructable Id to save some cost. You could spread the function into a column of
Collapse JASS:
local boolean b = first condition
set b = b and second condition
set b = b and third condition....

but that's just fugly with all of those tree conditions. Stick to the one line, it doesn't matter much.
09-03-2009, 04:11 PM#3
Michael Peppers
Thanks for the help, I'll work on it right away

EDIT: Done
09-03-2009, 07:17 PM#4
azlier
Collapse JASS:
private function Trees takes nothing returns boolean
local integer id = GetDestructableTypeId(GetFilterDestructable())
return id == t1 or id == t2 or id == t3 or id == t4 or id == t5 or id == t6 or id == t7 or id == t8 or id == t9 or id == t10 or id == t11 or id == t12 or id == t13 or id == t14 or id == t15 or id == t16 or id == t17 or id == t18 or id == t19 or id == t20 or id == t21
endfunction
Sweet Jesus. Why not attach some boolean to all those ID's via Table? That would give you some speed. O(n) where it is totally unneeded isn't the best idea.

Collapse JASS:
set cond = Condition(function Trees)
    call SetRect(r, unitX - range, unitY - range, unitX + range, unitY + range)
    call EnumDestructablesInRect(r, cond, function DestSearch)
call DestroyBoolExpr(cond) //Wrong.

Collapse JASS:
local destructable d = GetEnumDestructable()
local unit u = GetFilterUnit()
//You never seem to null these?
09-03-2009, 07:27 PM#5
Bobo_The_Kodo
1) Don't need to destroy boolexprs
2) Use grouputils
3) There is a "IsTree" cond somewhere in database using "ghoul harvest" ability to check
09-03-2009, 07:54 PM#6
moyack
Pitzo tree detector function:

Collapse JASS:
function IsDestructableTree takes destructable d returns boolean
  local boolean i = IsDestructableInvulnerable(d)
  local unit u = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), <invisible caster>,GetWidgetX(d), GetWidgetY(d), 0)
  local boolean result = false
  call UnitAddAbility(u, 'Ahrl')
  if i then
    call SetDestructableInvulnerable(d, false)
  endif
  set result = IssueTargetOrder(u, "harvest", d)
  call RemoveUnit(u)
  if i then
    call SetDestructableInvulnerable(d, true)
  endif
  return result
endfunction
09-03-2009, 08:02 PM#7
Bobo_The_Kodo
Should update it to use a single dummy though
09-03-2009, 08:25 PM#8
Michael Peppers
Quote:
Originally Posted by moyack
Pitzo tree detector function:

Collapse JASS:
function IsDestructableTree takes destructable d returns boolean
  local boolean i = IsDestructableInvulnerable(d)
  local unit u = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), <invisible caster>,GetWidgetX(d), GetWidgetY(d), 0)
  local boolean result = false
  call UnitAddAbility(u, 'Ahrl')
  if i then
    call SetDestructableInvulnerable(d, false)
  endif
  set result = IssueTargetOrder(u, "harvest", d)
  call RemoveUnit(u)
  if i then
    call SetDestructableInvulnerable(d, true)
  endif
  return result
endfunction

Wait, wait... wouldn't this be slower than my obnoxiously long check?
09-03-2009, 08:27 PM#9
Rising_Dusk
Please use the one in the database.
09-03-2009, 08:31 PM#10
Michael Peppers
Okie, thanks everyone, I'll remove all of my noob-ish errors soon :P