HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

A few questions

05-29-2008, 06:32 AM#1
Beardo
Trying to make (this part of) my code more and more efficient. any help with the following questions would definitely be appreciated

Collapse JASS:
struct  hd
real array buffs[30]
integer bufftotal
integer playerid
...
endstruct

constant function OverTen takes integer n returns real
    if n == 0 then
    return 0
    elseif n == 1 then
    return .01
    elseif n == 2 then
    return .02
    elseif n == 3 then
    return .03
    elseif n == 4 then
    return .04
    elseif n == 5 then
    return .05
    elseif n == 6 then
    return .06
    elseif n == 7 then
    return .07
    elseif n == 8 then
    return .08
    elseif n == 9 then
    return .09
    elseif n == 10 then
    return .1
    elseif n == 11 then
    return .11
    elseif n == 12 then
    return .12
    endif
    return 0.0
    endfunction
Collapse JASS:
method addbuff takes real buffnum, integer playerid returns nothing
    local real name       
    local integer i         = 0
    
    set name = buffnum + OverTen(playerid)
    
    loop
    if .buffs[i] == 0 then
        set .buffs[i]   = name
        set .bufftotal  = .bufftotal + 1
        return
    elseif .buffs[i] != 0 then
        set i = i + 1
    elseif i > 30 then
    return
    endif
    endloop
    endmethod
    

    method searchbuffs takes real buffnum, integer playerid, boolean remove returns boolean
    local real name                 = 0             
    local integer i                   = 0
    local integer counted         = 0
    local boolean exit              = false
    
    set name = (buffnum + OverTen(playerid))

        loop
            exitwhen counted >= .bufftotal
            if .buffs[i] == name then
                if remove == true then
                    set .buffs[i] = 0
                    set .bufftotal  = .bufftotal - 1
                endif    
                return true
            elseif .buffs[i] != name and .buffs[i] != 0 then
                set i       = i + 1
                set counted = counted + 1
            elseif .buffs[i] != name and .buffs[i] == 0 then
                set i       = i + 1
            endif    
        endloop
        return false
    endmethod
A quick explaination:
This is currently my buff system. Each "buff" (Tornado Slow) ability has a number associated w/ it (that I keep track on an excel sheet). I use the above code to store: 1. What buffs are on the unit/hero 2. What player's spell that buff came from.

I.E "Power Word: Shield" (Buff Number 52) casted by played 1 (0) would be added into the units (real) buff array as: 52.0, player 1 52.01 etc.

The questions:
1. The Searching Loop: Currently I don't know any alternative to this. Any way around it? toadcop? :)
2. Mapping: Taking a bit from weeadars recursive tutorial (which I barely understood) I mapped the 11 #s (there's 11 players) that I'm going to divide by 10 in a constant function to increase code efficency. is it really effective?
05-29-2008, 10:54 AM#2
Themerion
I think your code would be more effecient if you just divided the number with 10.
05-29-2008, 04:39 PM#3
Silvenon
Collapse JASS:
constant function OverTen takes integer n returns real
    if n == 0 then
    return 0
    elseif n == 1 then
    return .01
    elseif n == 2 then
    return .02
    elseif n == 3 then
    return .03
    elseif n == 4 then
    return .04
    elseif n == 5 then
    return .05
    elseif n == 6 then
    return .06
    elseif n == 7 then
    return .07
    elseif n == 8 then
    return .08
    elseif n == 9 then
    return .09
    elseif n == 10 then
    return .1
    elseif n == 11 then
    return .11
    elseif n == 12 then
    return .12
    endif
    return 0.0
endfunction

Collapse JASS:
function OverTen takes integer n returns real
    return (I2R(n) / 100)
endfunction

Collapse JASS:
if remove == true then

Collapse JASS:
if remove then

That's all I see for now...
05-29-2008, 05:41 PM#4
Deaod
inline OverTen. Replace set name = buffnum + OverTen(playerid) with [ljass]set name = buffnum + (playerid/100)[ljass]

Collapse JASS:
    method addbuff takes real buffnum, integer playerid returns nothing
    local real name       
    local integer i         = 0
    
        set name = buffnum + OverTen(playerid)
    
        loop
            if .buffs[i] == 0 then
                set .buffs[i]   = name
                set .bufftotal  = .bufftotal + 1
                return
            elseif .buffs[i] != 0 then
                set i = i + 1
            elseif i > 30 then
                return
            endif
        endloop
    endmethod
Youre assigning the buffs inefficiently., use this instead:
Collapse JASS:
    method addbuff takes real buffnum, integer playerid returns boolean
    
        if .bufftotal>30 then // btw: why did you insert that limitation?
            // insert some fancy DebugMsg here, if you want
            return false // let the user know allocation failed
        endif

        set .buffs[.bufftotal]=buffnum + (playerid/100)
        set .bufftotal=.bufftotal+1
    
        return true
    endmethod
this now allocate the "buffs" linearly, so you might want to write a removebuff function, which keeps all buffs in order, so you dont overwrite a buff.
05-29-2008, 10:43 PM#5
Beardo
The real reason I did the overten function was because I got really strange results when I divided a real by 10. Sometimes it wouldnt register for some reason. I switched to multiplying by .1 and that worked fine, but I feel safer going this way.

I was just curious if it was more efficient to map the results versus having to make the computer do a predictable calculation.

I chose 30 cause since you have to specify a size for arrays in structs, and no hero is going to be able to have nearly that many buffs @ once in my map

@ Deaod: the problem with that is that it's sort of a hassle to make a removal function that will resort all of the buffs so that it doesnt look like:
Collapse JASS:
.buffs[0] = 51.2
.buffs[1] = 0
.buffs[2] = 51.2
.buffs[3] = 55.5
.buffs[4] = 50.2

if the above senario ever happened, then (like you said), .buffs[4] would get overwritten the next time a buff is allocated in the array. Is this a possible inline/removal function?
Collapse JASS:
local integer i  = 0
local integer i2 = 0
    loop
        exitwhen i > 30
            if .buffs[i] == name then
            debug call BJDebugMsg(GetUnitName(.hero)+ " has " + R2S(name) + " on it.")
                if remove then
                    set .buffs[i]   = 0
                    set .bufftotal  = .bufftotal - 1
                    debug call BJDebugMsg(GetUnitName(.hero)+ " had " + R2S(name) + " removed.")
                        //INLINE THE MOTHERFUCKER
                        loop
                        exitwhen i2 == (30 - i)
                        if .buffs[i + i2] == 0 and .buffs[i+i2+1] != 0 then
                            set .buffs[i+i2]   = .buffs[i+i2+1]
                            set .buffs[i+i2+1] = 0           
                        endif
                        set i2 = i2 + 1
                        endloop
                endif    
                    return true
            else
            set i = i + 1
            endif
        endloop
        return false
The only thing I don't like about it is that it will always goto 30 regardless, I don't see anyway around that. AND if there's ever somehow two 0s back to back then it screws everything up.

EDIT: Better removal/inline function.
05-30-2008, 12:42 PM#6
Deaod
Collapse JASS:
method RemoveBuff takes integer buffnum, integer playerid returns boolean
local real name=buffnum+(playerid*0.01)
local integer i=0
local boolean b=false
    
    loop
    exitwhen i => .bufftotal
        if .buffs[i] == name then
            set b = true
            debug call BJDebugMsg(GetUnitName(.hero)+ " has " + R2S(name) + " on it.")
            set .bufftotal = .bufftotal - 1
            if i < .bufftotal then
                set buffs[i] = .buffs[.bufftotal]
            endif
            set .buffs[.bufftotal] = 0
            debug call BJDebugMsg(GetUnitName(.hero)+ " had " + R2S(name) + " removed.")
        endif
    set i = i + 1
    endloop

    return b
endmethod
this method still works, if there are two buffs of the same type on the same hero.

Btw: Youre attaching things to heroes (units) here. There are better (read: safer) ways of working with units than attaching things to them (eg. theres PUI).
05-31-2008, 02:12 AM#7
Beardo
All the hero structs are stored in a global integer array. The mobs have their structs attached via UnitUserData

your removal functions pretty clever.kudos