Tutorial tods, splits and joins

Sgqvur

FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
Reaction score
62
First thing first, what does TOD mean?
Well it means Time Of Day (Off Topic: also it's the nickname of the former professional Warcraft 3 TFT player Tod (aka 4K.Tod)
who I think is now a decent SC2 player as well =), so yeah go Tod!), which can be tweaked in Warcraft 3 as I think we all know.
There are two functions below that act as a wrappers for the natives, that I think work more "intuitively".
Well you might ask, what's so bad about the natives? Well say for example that you need/want to set the TOD to 01:30.
You can do that with [ljass]SetFloatGameState(GAME_STATE_TIME_OF_DAY, 1.5)[/ljass]. See the "problem"? The second argument 1.5
is what the wrappers try to "fix". Now say you want to set the TOD to 01:47? Not so "intuitive" eh? So what the wrapper allows you
is to just use 1.47 as an argument or in general x.y (0 <= x <= 23, 0 <= y <= 59).

The two wrappers:
JASS:

function settod takes real time returns nothing
    local integer whole_part = R2I(time)
    local real    real_part  = time - whole_part

    set real_part = real_part / 60 * 100
 
    call SetFloatGameState(GAME_STATE_TIME_OF_DAY, whole_part + real_part)
endfunction

function TriggerRegisterTODEvent takes trigger t, real time returns event
    local integer whole_part = R2I(time)
    local real    real_part  = time - whole_part
 
    set real_part = real_part / 60 * 100
      
    return TriggerRegisterGameStateEvent(t, GAME_STATE_TIME_OF_DAY, EQUAL, whole_part + real_part)
endfunction

// example usage:
// call settod(13.37)
// call TriggerRegisterTODEvent(t, 5.50)



The second things are the functions split and join. These functions work in the following way:
split:

The split function takes a "pattern" argument and a string to split and returns an array
containing the substrings, I think an example might help to clarify things:

[ljass]string array sa = split(":", "a:b:c:d")[/ljass]

the result of the above line (which is not a valid [v]Jass[2], nor I think anything else for that matter)
simply sets (it creates a new array) the first element of sa to a, the second to b, etc. So the sa will look like:

---- 0 1 2 3
sa: |a|b|c|d|

join:

The join function does the opposite, it takes an array and a string parameter and it "fuses/glues/concatenates" the elements of
the array in to a string, ex:

[ljass]string s = join(".", ["the", "helper", "net"])[/ljass]

the result would be that s == "the.helper.net" (again the above line is not a valid [v]Jass[2])


Okay, but the problem with [v]Jass[2] is that functions can't take nor return arrays. So does that mean
that the split and join can't be used? Of course not. The workaround is to make them use implicit arrays,
not explicitly accept arrays as arguments.


So the following is a textmacro that allows users to make their own split/join functions that work
on a implicit array specified also in the textmacro arguments:

JASS:


function index takes string source, string pattern, integer offset returns integer
    local integer source_len  = StringLength(source)
    local integer pattern_len = StringLength(pattern)
    local integer str_p       = 0

    if offset &lt; 0 then
        set str_p = source_len + offset
    else
        set str_p = str_p + offset
    endif

    loop
        exitwhen str_p &gt;= source_len - pattern_len  + 1
        
        if SubString(source, str_p, str_p + pattern_len) == pattern then
            return str_p
        endif

        set str_p = str_p + 1
    endloop

    return -1
endfunction

//! textmacro SPLIT_JOIN takes ARRAY_NAME, SPLIT_NAME, JOIN_NAME
globals
    string array $ARRAY_NAME$
    integer $ARRAY_NAME$_size = 0
endglobals

function $SPLIT_NAME$ takes string pattern, string source returns nothing
    local integer a = 0
    local integer b = 0

    set $ARRAY_NAME$_size = 0

    if pattern != &quot;&quot; and pattern != null then
        set b = index(source, pattern, a)
        loop
            exitwhen b &lt; 0
        
            set $ARRAY_NAME$[$ARRAY_NAME$_size] = SubString(source, a, b)
            set $ARRAY_NAME$_size = $ARRAY_NAME$_size + 1

            set a = b + 1
            set b = index(source, pattern, a)
        endloop
        set $ARRAY_NAME$[$ARRAY_NAME$_size] = SubString(source, a, StringLength(source))
        set $ARRAY_NAME$_size = $ARRAY_NAME$_size + 1
    else
        loop
            exitwhen $ARRAY_NAME$_size &gt;= StringLength(source)
            set $ARRAY_NAME$[$ARRAY_NAME$_size] = SubString(source, $ARRAY_NAME$_size, $ARRAY_NAME$_size + 1)
            set $ARRAY_NAME$_size = $ARRAY_NAME$_size + 1
        endloop
    endif
endfunction

function $JOIN_NAME$ takes string glue returns string
    local string  result      = &quot;&quot;
    local integer split_index = 0

    loop
        exitwhen split_index == $ARRAY_NAME$_size - 1
         
        set result = result + $ARRAY_NAME$[split_index] + glue
        rpu
        set split_index = split_index + 1
    endloop
    set result = result + $ARRAY_NAME$[split_index]

    return result
endfunction   
//! endtextmacro


An example usage might be:

[ljass]//! runtextmacro SPLIT_JOIN("S", "split", "join")[/ljass]
[ljass]//! runtextmacro SPLIT_JOIN("S1", "split1", "join1")[/ljass]

I recommend short names for both the functions (you can call them whatever you like,
not just split/join) and the implicit array, which will make both using them easier and some folks
think scripts will run faster, which is rather curious (but it can reduce readability of course).

So what good are the split/join combo in the realm of [v]Jass[2]?
Well as you can find out in the attached map, they can be really, really helpful for handling commands by the player(s)/"learning" purposes.

I will try to give here an arguable senseless example that uses two splits.
Say you have a save/load code in your map, that uses the format [ljass][str:agi:int x:y:z i1:i2:i3:i4:i5:i6][/ljass],

and you want to "load/init" your hero struct with those values.

Lets assume we have 2 split functions called split (uses S[] as implicit array) and split1 (uses S1[] as implicit array)

if we call split(" ", player_inputed_string) then
S[0] will be "str:agi:int"

now if we split1(":", S[0]) we will have

S1[0] = "str"
S1[1] = "agi"
S1[2] = "int"

and we can now easily set those values to our struct.

The same goes for S[1] which is "x:y:z" and S[2] which is "i1:i2:...:i6"

So I think this demonstrates how useful splits can be.

But what about join(s)? Well join can be useful as well, but I really can't think of an even
arguably good example (other than just printing the contents of the implicit array) for it in [v]Jass[2],
this doesn't mean that some more creative folks won't find it useful of course.


And of course if more split(s) and join(s) are required then simply run another textmacro =)!

PS: the split function is just like the StringExploader(I might be wrong about the name) that Romek (I might be wrong again =))
had uploaded a while back, but I think it's name was Php inspired, and split/join are borrowed from Perl =)
(which are names that probably many other programming languages use [no, not that many other languages are called Perl but
functions with same/similar functionality are called the same [split/join] =)).
 

Attachments

  • tods_splits_joins.w3m
    16.5 KB · Views: 369

Dirac

22710180
Reaction score
147
Straight to graveyard resource. Is there even a resource here?

Nestharus already made a system that handles strings in a better way (and i've never thought i would say this, but's also more understandable than this), why on earth are you using textmacros instead of struct allocation for arrays???
 

UndeadDragon

Super Moderator
Reaction score
447
Is this supposed to have a tutorial prefix?
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +2
  • V-SNES V-SNES:
    Happy Friday!
    +1
  • The Helper The Helper:
    New recipe is another summer dessert Berry and Peach Cheesecake - https://www.thehelper.net/threads/recipe-berry-and-peach-cheesecake.194169/

      The Helper Discord

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top