HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Advanced Return Bug Use...

01-08-2004, 01:08 AM#1
Cacodemon
I've made some experiments with return bug-based functions and here are results:

1. Not only handle anchestors have handles, but strings, reals and booleans also have! I could hardly believe my eyes...

2. Every new string declaration as well as string union operator causes memory leaks! This is example:
Code:
[color=skyblue]
function SomeFunc takes nothing returns nothing
 local string Str = [/color][color=limegreen]"Hello "[/color] + [color=limegreen]"World!"[/color][color=skyblue]
endfunction
[/color]

When being called, SomeFunc() allocates 3 strings and 3 handles corresponding to them in memory:

1. "Hello "
2. "World!"
3. "Hello World!"

Every "+" operator allocates handles for both operands and one handle for result! And every time string is declared or redeclared it leaks memory! For example:
Code:
[color=skyblue]
function MyFunc takes nothing returns nothing
 local function Str = [/color][color=limegreen]"AAAA"[/color][color=skyblue]
 set Str = [/color][color=limegreen]"BBBB"[/color][color=skyblue]
 set Str = [/color][color=limegreen]"CCCC"[/color][color=skyblue]
 set Str = [/color][color=limegreen]"DDDD"[/color][color=skyblue]
endfunction
[/color]
MyFunc() will allocate 4 different strings in memory, every next after previous. And these strings will not be removed from memory after MyFunc() returns. It's not good for performance, but I guess Blizzard had reasons to do this.

I have noticed one thing: If you declare string, but another string contains the same data was already declared, String2Handle() doesn't allocate additional handle. It returns handle to existing string. I guess Blizzard made this for saving memory.

3. Warcraft doesn't use direct memory handles. You know well it's too unsafe so Blizzard couldn't do that! Handles are allocated in "declaration order".

4. Reals have handles too! Try using R2H() and H2R() function to ensure. But real handles are very big numbers unlike string / unit handles. Is it possible to be not a handle but real data coded into integer? I haven't understood this yet.

RB open incredible coding abilities! Transferring and returnings arrays into / out ANY function is POSSIBLE. I'm translating short report about this... I'll post it tomorrow!


-------------------------------------------------


Here's example of C-styled Format function which takes 2 strings: one contains string to be displayed ("Data String") and another contains untypized handles array converted to string ("Handles Array"). Array contains handles can be created using Object2F() functions - I2F(), R2F(), S2F() and P2F() functions. This functions supports only several types of data:
  • %i - Being placed inside Data string, this symbols mean integer value to be substituted instead.
  • %r - Real value.
  • %p - Player's name.
  • %s - String.
  • % + any other symbol after is displayed "as is".

How to use this?

You have string like this: "Player %p has %i gold, %i lumber and his hero has %r% of health..."

So just call:
Code:
[color=skyblue]call Format(
  [color=limegreen]"Player %p has %i gold, %i lumber and his hero has %r% of health..."[/color],
  P2F(udg_Player) + I2F(udg_PlayerGold) + 
  I2F(udg_PlayerLumber) + R2F(udg_HealthPercent))
[/color]

So you get string like this:

"Player Cacodemon has 500 gold, 100 lumber and his hero has 75.00% of health..."

"Cacodemon", 500, 100, "75.00" are values stored in corresponding variables. If your Handle String have less handles than Data String, formatting symbols which don't have corresponding handles are displayed "as is". You can format strings contains as many handles of any type as you wish. Be sure that actual types of handles in Handle String are equal to handles types in Data string!

This is its code including standart RB-functions:

Code:
[color=skyblue]
function S2H takes string S returns integer
 return S
 return 0
endfunction

function H2S takes integer H returns string
 return H
 return ""
endfunction

function R2H takes real R returns integer
 return R
 return 0
endfunction

function H2R takes integer H returns real
 return H
 return 0.0
endfunction

function P2H takes player P returns integer
 return P
 return 0
endfunction

function H2P takes integer H returns player
 return H
 return null
endfunction

function I2F takes integer I returns string
 return I2S(I) + " "
endfunction

function R2F takes real R returns string
 return I2S(R2H(R)) + " "
endfunction

function S2F takes string S returns string
 return I2S(S2H(S)) + " "
endfunction

function P2F takes player P returns string
 return I2S(P2H(P)) + " "
endfunction

function Char takes string Str, integer Index returns string
 return SubString(Str, Index, Index + 1)
endfunction

function CPos takes string M, string Sub, integer Index returns integer
 loop
  exitwhen (Char(M,Index) == Sub) or (Char(M,Index) == "")
  set Index = Index + 1
 endloop
 return Index
endfunction

function Format takes string DStr, string HStr returns string
 local string  Result = "" 
 local integer DSize = CPos(DStr, "", 0)
 local integer HSize = CPos(HStr, "", 0)
 local integer PrevH = 0
 local integer NextH = -1
 local integer DType = 0
 local integer Ref = 0
 local string Token
 if HStr == "" then
  return DStr
 endif
 loop
  exitwhen Ref >= DSize
  if Char(DStr, Ref) == "%" then
   set DType = CPos("iprs", Char(DStr, Ref + 1), 0)
   if (DType < 4) then 
    set Ref = Ref + 1 
    set PrevH = NextH + 1
    if PrevH < HSize then
     set NextH = CPos(HStr, " ", PrevH)
     set PrevH = S2I(SubString(HStr, PrevH, NextH + 1))
     if DType == 3 then
      set Token = H2S(PrevH)
     elseif DType == 2 then
      set Token = R2S(H2R(PrevH))
     elseif DType == 1 then
      set Token = GetPlayerName(H2P(PrevH))
     else
      set Token = I2S(PrevH)
     endif
    else
     set Token = SubString(DStr, Ref - 1, Ref + 2)
    endif
   else
    set Token = Char(DStr, Ref)
   endif
  else
   set Token = Char(DStr, Ref)
  endif
  set Result = Result + Token
  set Ref = Ref + 1
 endloop
 return Result
endfunction
[/color]

You can add additional handle types to this function, for example:
  • Formatted real - %f[x,y]
  • Order - %o
  • Unit-type - %u
    And so on...

I guess it's very, very useful...


Starcraftfreak: Can you add this function to your UMSWE?

---------------------------------

How to transfer arrays into functions... (No actual arrays but strings contains several handles)

Just convert all handles to string, handles can be divided by space. You can place every handle's type before it:

For example,

"I100 S26 R1237464 U13434 I343 "

Means:
  • Integer, value == 100
  • String, handle == 26
  • Real, handle == 1237464
  • Unit, handle == 13434
  • Integer, value == 343

Handle values can be got using I2S(Object2H(Object)) + " " functions. See example (S2F(), R2F() etc, but they don't add data type before handle)

You function should take string argument and process this string inside it. Algorythm is very simple (see previous example). You can process "arrays" contain several data types.

Your function can return this "handle string" as well...

I know this method is really stupid but only it allows you to transfer "arrays"...
01-08-2004, 02:17 AM#2
Cacodemon
This is Format() example... Type "Info" just in game... Every 5 seconds amount of resources is random-changed so you can see the difference in displayed values...
01-08-2004, 09:14 AM#3
jmoritz
Again I feel obliged to caution everyone NOT to use the return bug. There is always a good alternative solution. ALWAYS.

I don't really see why you need the return bug to create the format function. In particular, this function seems useless:
Code:
function R2F takes real R returns string
 return I2S(R2H(R)) + " "
endfunction

function R2F takes real R returns string
  return R2S(r) + " "
endfunction

Just use the above function and then don't decode the real in the format function. Same for other values. Why pass the player handle using return bug, when you can just put the player name in the string? Granted, you'll probably have to use a different delimiter instead of a single space, but that's not the point :)

Also, I'm not sure if reals are handles. Might be they are just 4 byte floats. Same for booleans. Try converting a real big real (lots of digits: 20+) to an integer and back again. If it fails, reals are probably stored as doubles (8 bytes). If not, probably floats (4 bytes, same as ints).

Try changing the integer you get from the return bug by increasing it by one and see what happens to the result. It should be a real still, just a different number. If war3 crashes or something, they might be hanldes after all.
01-08-2004, 12:19 PM#4
Cacodemon
Format() is not so good example of RB use. You can convert your data to string, not using return bug then process that string. But I've tried to show how "handle strings" can be used to process "array imitations" into function. Sometimes it can be useful.

As for reals, their precision depends on value:

0.12345678 is stored without precision loss, but
100000000000.12234 will be truncated to: 100000000000.0.
emote_sweat
01-08-2004, 01:06 PM#5
KaTTaNa
I like your idea about converting an array to a string to pass it as a parameter. It's a really interesting idea.
01-08-2004, 01:57 PM#6
AIAndy
I think using the heap is a better mechanism for passing arrays to functions than using a string. Especially it is more efficient.

Reals are stored as x*(2^y) . Thats why the precision behaves in the way you described.
01-08-2004, 03:17 PM#7
Cacodemon
AIAndy: Please write your "heap algorythm" here... I don't understand what you're talking about...

P.S. Thank you for Real storage method.
01-08-2004, 03:48 PM#8
AIAndy
http://www.wc3campaigns.com/forums/s...threadid=38216
The heap that was developed in the last JASS Challenge. Look at the end of the thread for instructions on how to use it.
The heap provides a way to retrieve memory and return it again once it is not needed any more. The memory is accessed by pointers which can be passed to any function (and returned of course too) as they are simple integers.
01-08-2004, 08:28 PM#9
PitzerMike
Still you did a good job finding all that out Cacodemon:D
01-09-2004, 02:28 AM#10
weaaddar
Right earlier versions of my DT4:A use to pass strings of information (using the return bug and mostly ints). WhicH I converted to arrays. However, as the code for each item became more and more complex I found an easier implementation to be multiple strings per item. I figured the database system was much easier for the end user as well. Return bug of strings working is nice though.
01-09-2004, 10:05 AM#11
Cacodemon
I think new heap system can be created using RB features. For example, you can store heap data as string and process heaps using their string handles. This method independs on global variables. There's only one problem - string handle is changed after every heap modification so it's better to store these handles in integer array and use cell index as heap.
01-11-2004, 01:29 AM#12
alastor_ac
is there any way you could develop / post a new heap system with the method you described in ur post above, i think it would be more memory-efficient and easier to implement than the other 2 uses.
01-11-2004, 03:34 PM#13
Cacodemon
If Warcraft modding community really needs this I can try a bit later...