HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Save / Load Code Help

10-09-2007, 11:24 PM#1
MrApples
...who would be able to help me fix my Save/Load. It's almost complete, and it actually appears to be working also.

There is an issue where one extra binary is being used for every value, and any value that is on the max is not saved correctly. and I just haven't the mental focus to fix it right now. Offering permanent credit, and the joy of bringing another save/load into this world

NOTE: This is actually a good one. Maybe even a best, not my decision. Really I think it's a confusion with 0 having to be 1(as values start at 1, not 0), but i'm just too confused.

Some more info on it - http://www.pollama.com/index.php?topic=4954.0

An explanation of how it works(supposed to)
The user specifies a value, min, max, name, and code for each save.

The Value is what your actually saving, the part that changes.
The Min is how long it can go.
The max is how high.
The name is used to get the save and reference to it.
And the code is for different save-loads.

Example Save: call SaveInteger( (Level of Hero), "level", 1, 100, "hero")
Example Load: set Integer = LoadInteger("level", "hero")

SO this is what it does.

Max is set to Max + (1 - min). If max = 6, and min = 3, new max is 4 (3, 4, 5, 6).

The space needed is determined for each max. Space needed is in binary, so we keep checking the powers of 2. a Max of 4 would need 2 binary (2^2 >= 4 )

Next we fill the binary string by checking if the value is greater than the powers in reverse order. If it is, add '1' and subtract, if not, add '0'. If the space were 6, and the value 37, th bin string would look like this.

010010

(0 + 4 + 0 + 0 + 32 + 0) + 1 = 37 (000000 would be 1, we start at 1)

111111 would be 127, which is 1 less than 2^7. 111000 would be 15 ( 2 + 4 + 8 + 0 + 0 + 0 ) + 1. All the bin strings are then tied together, and then are assigned a certain character according to their combination. a = 00000, b = 10000.. etc.

The BooStuffer takes care of everything which does not fit in exact maxes, including the charset, and the Flip Index takes care of encryption. These can be shut off.
Attached Files
File type: w3xApples SaveLoad B1b(2).w3x (53.4 KB)
10-10-2007, 11:24 AM#2
Belphegor666
You should rephrase your question. This is the point there ain't many geniuses around and the rest just won't look at your post. Also you haven't specified what kind of work is this.Trigger, JASS, modeling... I unfortunately do not have time nor knowledge to help you out on this, so I'm bumping it, a bit.
10-10-2007, 08:37 PM#3
MrApples
If you know what a save/load is, then you know it's JASS.

And yes, I think genius is a requirement... otherwise you would be getting in to it as much as I am and it's not worth it.

Not one view :(
10-10-2007, 08:48 PM#4
Captain Griffen
This is in the wrong forum. *wonders how he didn't notice that first time*

And I'll do you a favour and change the thread name.
10-10-2007, 11:43 PM#5
Ammorth
Seeing as how I finished my save-code recently, Ill take a look and see whats up.

Edit: I couldn't seem to generate any problems. Can you explain what you did, what happend, and what should have happend?
10-11-2007, 12:42 AM#6
MrApples
Well one binary is added on to each save, meaning it's about 2 characters longer then it should be, and if a value lands on the max it does not save correctly... or it might be that if a max is on a power of 2...

I really think the problem has something to do with me confusing myself on terms of 0 being 1. 000 would be 1.

My reason for putting this in projects with that name is that I don't expect help, but if a 'genius' happened to roll by... it's appreciated though Capt.
10-11-2007, 07:28 PM#7
SentryIII
Post the original code that you used to create the algorithms before converting it to JASS. It's so much easier to walkthrough and debug the code in an IDE like Visual Studio or Eclipse instead of constantly loading your map in WC3 just to see if anything improved.
10-11-2007, 07:51 PM#8
MrApples
I first wrote it out by hand in my notebook, and then I wrote it out in Notepad++(with the vJASS add-on). So really, it's always been in JASS. I'll attach the script in a txt document.

And if this will help; heres the oldest version of the SaveCode function I have. It doesn't work, but maybe it can give an idea on what it does.
Collapse JASS:
function Savec takes integer c returns string
    local integer xi = 0
    local integer xi2 = 0
    local integer xi3 = 0
    local integer a = 1
    local integer a2 = udg_Code_Saves[c]
    local integer b = 0
    local integer b2 = 0
    local string result = null
    local string xs = null
    local string xs2 = null
    if ( a2 <= 0 ) then
        // Nothing saved, end.
        set result = "cerror"
        return result
    endif
    loop
        // Let's get multi-demensional(for multiple codes)
        set xi3 = ( a + ( 1000 * (c - 1)))
        set xi = udg_Save_Val[xi3]
        set xi2 = udg_Save_Max[xi3]
        set b = 1
        loop
            // Find space needed. Powers are of 2, [1] being 2, [2] being 4. This was changed to start at 1 in later version.
            if ( xi2 < udg_SL_Powers[b] ) then
                exitwhen true
            endif
            set b = ( b + 1)
        endloop
        // Part of the BooStuffer before I named it. If a value is less than the excess amount of space (Power - Max), then
        // check if the the last binary added is '1'. If so, set value = value + max and remove the binary. If not, remove
        // the binary anyway.
        if ( xi2 <= ( udg_SL_Powers[b] - xi2 ) ) then
            if ( xs != null ) then
                if ( SubString( xs, 1, 1 ) == "1" ) then
                    set xi = ( xi + xi2 )
                endif
                set xs = SubString( xs, 2, StringLength(xs) )
            endif
        endif
        set b = ( b - 1 )
        loop
            // This converts a value into a binary string. 000 = 1, 100 = 2, 010 = 3, 001 = 5 (should, not in this v)
            if ( xi >= udg_SL_Powers[b] ) then
                set xi = ( xi - udg_SL_Powers[b] )
                set xs = ( "1" + xs )
            else
                set xs = ( "0" + xs )
            endif
            set b = ( b - 1 )
            // We've reached the lowest power, 2 (should be 1)
            if ( b == 0 ) then
                exitwhen true
            endif
        endloop
        loop
            // Before I made the BooStuffer work for characters too. The end length of the total bin string must be a factor
            // of 6, add extra 0's if not. This is because each character has a 6-long binary conterpart.
            if ( ModuloInteger( StringLength(xs), 6 ) != 0 ) then
                set xs = ( xs + "0" )
            else
                exitwhen false
            endif
        endloop
        set xi = StringLength(xs)
        set a = 1
        set a2 = 6
        set b = 1
        set b2 = 5
        loop
            set xs2 = SubString( xs, a, a2)
            // Do we want a 64 base or a 32 base. (Before BooStuffer)
            if ( udg_SL_Base == 32 ) then
                loop
                    // Get the character for next binary combination. BinSet desc. below.
                    if ( xs2 == SubString( udg_SL_BinSet, b, b2 ) ) then
                        set result = result + SubString( udg_SL_CharSet, b, b )
                        exitwhen true
                    endif
                    set b = ( b + 1 )
                    set b2 = ( b2 + 1 )
                endloop
            else
                loop
                    // Same as above, for 64base.
                    // Never found the 6 BinSe before this (code which contains all the combinations of 1' and 0's 6
                    // length, in only 69 characters). Gotta use the 32 one, so add a 1 if value is above 32. 0 if not.
                    if ( b <= 32 ) then
                        if ( xs2 == ( SubString( udg_SL_BinSet, b, b2 ) + "0" ) ) then
                            set result = result + SubString( udg_SL_CharSet, b, b )
                            exitwhen true
                        endif
                    else
                        if ( xs2 == ( SubString( udg_SL_BinSet, b, b2 ) + "1" ) ) then
                            set result = result + SubString( udg_SL_CharSet, b, b )
                            exitwhen true
                        endif
                    endif
                    set b = ( b + 1 )
                    set b2 = ( b2 + 1 )
                endloop
            endif
            if ( a2 == xi ) then
            exitwhen true
            endif
            set a = ( a + 6 )
            set a2 = ( a2 + 6 )
        endloop
    endloop
    return result
endfunction
[/jass]
Attached Files
File type: txtasl2.txt (30.7 KB)
10-11-2007, 08:34 PM#9
Viper5030
Quote:
Originally Posted by MrApples
If you know what a save/load is, then you know it's JASS.

You can save/loads with the GUI, too.

I just don't want people that only work with the GUI to feel so limited and discouraged, cuz too many people make incorrect assumptions about the limitations of the GUI. I'm currently working on a completely original map made of pure new abilities and concepts, and I haven't come across ANY limitations that could otherwise be solved with JASS, except for 1 line of custom code to implement individual multiboards.
10-11-2007, 08:47 PM#10
SentryIII
Okay... can you at least post a flowchart of the logic? It makes it easier to visually walkthrough the logic step by step.

Also, can you give some examples of the data, like what is being returned and what is supposed to be returned?
10-11-2007, 09:19 PM#11
Captain Griffen
You can do a GUI save / load code, but DON'T. It is far harder, even for someone very experienced at GUI (such as me), and I used JASS parts for turning strings into bits.
10-11-2007, 09:36 PM#12
MrApples
The first three attempts of this were actually in GUI, and so is my 'Risk Engine' and a bunch of things. A save/load of this complexity kinda has to be done in JASS though, but I can rephrase. "I mentioned JASS in my original post, and a custom function, so of course it must be JASS."
-----------------------
It returns a code, most of the time the code is longer then it should be, and sometimes it is incorrect.

When a value is saved, the function takes the value, min, max, name, and code. It checks if that value exists, if so it overwrites, and it sets the max to max - (min - 1). If the min were 3, and the max 6, the new max would be 4. If the min -2, and the max 7, the new max would be 10 (0 included). The values also go through all sorts of checks to make sure they're in-sync.

The save function ends up storing a value, max, and spaceneeded for each save into a global array.
-----------------------------'
The SaveCode("codename") function...
  • Finds the ID of the code(code is a string), and then gets the correct section of the array(multidemensional).
  • If overload is on, the "overload" function is constantly called throughout the system. This is built for larger codes/maps to prevent the system from crashing the game.
  • BooStuffer is run. If Value is less than ((Power[Space+1]-1) - Max) then we can stuff a Binary. If last saved binary is "1", add Max to Value, if not, do nothing. EX. Say value = 3, max=11, space would be 4(1, 2, 4, 8 can be used to get this value), so Power[Space+1]-1 = 15, 15-11(max) = 4, and 4 is > 3(val) so if the value is 3, that means a 0 has been removed, if the value is 14(val + max), that means a 1 has been removed.
  • Next we convert each value into binary. Each value takes Space amount of binary. 3, max11 would be 0100 (/1 + 2 + /4 + /8) + 1 (add 1 because values start at 1, not 0). 1100 would be 4 (1 + 2 + /4 + /8) + 1, 0011 would be 13 (/1 + /2 + 4 + 8) + 1.
  • This is done by lopping backwards checking if the value is greater than the current 'power' from the Powers variable. If it is, add "1" to string and subtract, otherwise, add "0" and do nothing.
  • Now the values go through the 'Flip Index', which is my way of encypting codes. It works off of 10 random numbers specified by the mapper, and it scrambles all the binary according to such.
  • *BooStuffer, Flip Index, and Overload are all on/off turnable. Thats how I know if they're causing it.
  • The bincode is looped through in groups of 5, BooStuffer is also run here except for the characters. The code looks for a binary match to each set of 5, and assigns a integer from 1 to 32(base5) according to the starting position of that combination in the BinSet.
  • When the remaining binstring is less than 5, add 0's to fill up the end. As it must be a factor of 5.
  • Stich together the code. If the Pimper is enabled, color codes are added. Return the code.

This is really tough to explain.
10-12-2007, 09:34 AM#13
SentryIII
I still don't get it.

If it's too much trouble to post the current JASS code, a flowchart of the logic, or even actual examples of the output, then you're better off on your own.

Convert the JASS algorithm to something like VB.NET or C#, then debug and walk through it to make sure each line is doing what it's supposed to be doing. Otherwise you'll just waste more time on this overly complex mess. The best way to solve this problem is to simpify it. Plain and simple.
10-13-2007, 01:45 AM#14
MrApples
I did post the current jass code, and a flowchart (maybe not a good one).

I'll emb it here.
Collapse JASS:
//______________//
// Core - Save  //
//______________//


function SaveCode takes string c returns string
    local integer xi = 0
    local integer xi2 = 0
    local integer xi3 = 0
    local integer ci = 1
    local integer a = 1
    local integer a2 = 0
    local integer b = 0
    local integer b2 = 0
    local string result = ""
    local string xs = ""
    local string xs2 = ""
    local integer array Flip_Use1
    local integer array Flip_Use2
    set c = StringCase( c, false)
    loop
        if ( udg_Code_Name[ci] == c ) then
            exitwhen true
        else
            if ( udg_Code_Name[ci] == null ) then
                // Create Error, Code Doesn't Exist.
                return "nocode"
            else
                set ci = ci + 1
            endif
        endif
        if ( udg_SL_Use_Overload == true ) then
            call Overload(1)
        endif
    endloop
    set a2 = udg_Code_Saves[ci]
    // Did they actually save anything?
    if ( a2 <= 0 ) then
        // No values saved for this code. Duh?
        set result = "nosaves"
        return result
    endif
    loop
        // Lets make it multi-demensional.
        set xi3 = ( a + ( udg_SL_MaxSaves * (ci - 1)))
        set xi = udg_Save_Val[xi3]
        set xi2 = udg_Save_Max[xi3]
        set b = udg_Save_Space[xi3]
        if ( udg_SL_Use_BooStuffer == true ) then
            // Start BooStuffer
            if ( xi2 <= ( udg_SL_Powers[b] - xi2 ) ) then
                if ( xs != "" ) then
                    if ( SubString( xs, 0, 1 ) == "1" ) then
                        set xi = ( xi + xi2 )
                    endif
                    set xs = SubString( xs, 1, StringLength(xs) )
                else
                    // Create opt error. xs = null.
                endif
            endif
            // End BooStuffer
        endif
        loop
            if ( xi >= udg_SL_Powers[b] ) then
                set xi = ( xi - udg_SL_Powers[b] )
                set xs = ( "1" + xs )
            else
                set xs = ( "0" + xs )
            endif
            exitwhen ( b <= 1 )
            set b = ( b - 1 )
        endloop
        exitwhen a == a2
        set a = ( a + 1 )
        if ( udg_SL_Use_Overload == true ) then
            call Overload(5)
        endif
    endloop
    call Switch()
    // Flip Index
        if ( udg_SL_Use_FlipIndex == true ) then
        set a = 1
        set xi = StringLength(xs)
        loop
            set Flip_Use1[a] = ( ModuloInteger(udg_SL_Flip_Index1[a], xi) + 1 )
            set Flip_Use2[a] = ( ModuloInteger(udg_SL_Flip_Index2[a], xi) + 1 )
            exitwhen a == udg_SL_Flip_Sum
            set a = a + 1
        if ( udg_SL_Use_Overload == true ) then
            call Overload(2)
        endif
        endloop
        set a = 1
        loop
            if ( SubString(xs, Flip_Use1[a]-1, Flip_Use1[a]) != SubString(xs, Flip_Use2[a]-1, Flip_Use2[a]) ) then
                if ( SubString(xs, Flip_Use1[a]-1, Flip_Use1[a]) == "0" ) then
                    set xs = ( SubString(xs, 0, Flip_Use1[a]-1) + ( "1" + SubString(xs, Flip_Use1[a], xi) ))
                    set xs = ( SubString(xs, 0, Flip_Use2[a]-1) + ( "0" + SubString(xs, Flip_Use2[a], xi) ))
                else
                    set xs = ( SubString(xs, 0, Flip_Use1[a]-1) + ( "0" + SubString(xs, Flip_Use1[a], xi) ))
                    set xs = ( SubString(xs, 0, Flip_Use2[a]-1) + ( "1" + SubString(xs, Flip_Use2[a], xi) ))
                endif
            endif
            exitwhen a == udg_SL_Flip_Sum
            set a = a + 1
            if ( udg_SL_Use_Overload == true ) then
                call Overload(4)
            endif
        endloop
    endif
    // End Flip Index
    set b = 1
    set xi3 = 0
    loop
        if ( StringLength(xs) < 5 ) then
            set xs2 = xs
            set xs = ""
            loop
                if ( StringLength(xs2) != 5 ) then
                    set xs2 = ( xs2 + "0" )
                    set xi3 = xi3 + 1
                else
                    exitwhen true
                endif
            endloop
        else
            set xs2 = SubString( xs, 0, 5)
            set xs = SubString( xs, 5, StringLength(xs) )        
        endif
        loop
            if ( xs2 == SubString( udg_SL_BinSet, b-1, (b+4)) ) then
                if ( udg_SL_Use_BooStuffer == true ) then
                    // Start BooStuffer
                    // If a value can be above 64, and is above 64, then extra is 1, else 0. Same goes for 32.
                    // Yes it makes sense, stop forgetting that.
                    if (b <= (udg_SL_Chars - udg_SL_Base)) then
                        if ( xs != "" ) then
                            if SubString( xs, 0, 1) == "1" then
                                set b = (b + udg_SL_Base)
                            endif
                            set xs = SubString( xs, 1, StringLength(xs))
                            if (b <= (udg_SL_Chars - udg_SL_Base2)) then
                                if ( xs != "" ) then
                                    if SubString( xs, 0, 1) == "1" then
                                        set b = (b + udg_SL_Base2)
                                    endif
                                    set xs = SubString( xs, 1, StringLength(xs))
                                else
                                    // Create Opt Error. xs was = null.
                                endif
                            endif
                        else
                            // Create Opt Error. xs was = null.
                        endif
                    endif
                    // End BooStuffer
                endif
                // Pimp My Code?
                if ( udg_SL_Use_Pimper == true ) then
                    set result = ( result + ( udg_SL_ColorChar[b] + ( SubString( udg_SL_CharSet, b-1, b ) + "|r" )) )
                else
                    set result = ( result + SubString( udg_SL_CharSet, b-1, b ) )                
                endif
                exitwhen true
            endif
            set b = ( b + 1 )
        if ( udg_SL_Use_Overload == true ) then
            call Overload(5)
        endif
        endloop
        exitwhen ( xs == "" )
        set b = 1
        set xs2 = ""
    endloop
    if ( xi3 > 0 ) then
        // Create Opt. Error. Extra space went unused.
    endif
    return result
endfunction


//_______________________//
//      End - Save       //
//_______________________//

Really this topic has helped me think more clearly about it, I may end up making a 5th attempt, but it's a shame the 20 hours I spent on this attempt alone are blown... suggestions are welcome.
10-13-2007, 02:14 AM#15
Ammorth
I would suggest you make seach step a sperate function so it is easier to view and understand what everything does. Once you have the entire systm working, start inlining everything, or just even leave is.