Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.
 Entire forum ➜ MUSHclient ➜ VBscript ➜ ReDim, UBound & LBound on World [array] Variables.

ReDim, UBound & LBound on World [array] Variables.

Posting of new messages is disabled at present.

Refresh page


Pages: 1 2  

Posted by Magnum   Canada  (580 posts)  Bio
Date Sat 22 Dec 2001 02:31 PM (UTC)
Message
I'm having problems learning the syntax required to work with global array variables in my script. For example:

Dim arrSpellsPointer(), arrSpells()

Sub Test
Dim x
For x = 0 to UBound(arrSpellsPointer)
World.Note "ArrSpellsPointer(" & CStr(x) & "): " & World.GetVariable("arrSpellsPointer(x)")
Next
World.Note "Done."
End Sub

Sub Reset_Spells (thename, theoutput, thewildcards)
ReDim arrSpellsPointer(4)
ReDim arrSpells(5, 4)
World.SetVariable "arrSpellsPointer(0)", 4
World.SetVariable "arrSpells(1, 1)", -1
End Sub

I am not sure any of the code will work the way I intend. They need to interact with the global variables "arrSpellsPointer" & "arrSpells". How do I do this in conjunction with ReDim?

When I type "rtest" (an alias which calls "Reset_Spells"), and then type "/test", I get the following output:

ArrSpellsPointer(0):
ArrSpellsPointer(1):
ArrSpellsPointer(2):
ArrSpellsPointer(3):
ArrSpellsPointer(4):
Done.

Note that arrSpellsPointer(0) should be "4". I haven't made the alias test the multidimension array, which is what I would do next. How will I use ReDim & UBound with it?

I plan to expand and contract the arrays. I would have prefered to expand/contract the "x" in this variable:

arrSpells(x, 5)

...but msdn.microsoft says you can only ReDim the last argument, so I am forced to flip the chart in my head on it's side and use:

arrSpells(5, x)

...so It grows sideways. If I can't work with multidimensional arrays in a World context, I may have to use 5 individual arrays instead, but I would still need them to be global arrays... and I would still like to work with variable-sized arrays.

Can you help me Nick (or anyone else)?

Magnum.

Get my plugins here: http://www.magnumsworld.com/muds/

Constantly proving I don't know what I am doing...
Magnum.
Top

Posted by Eejit   (2 posts)  Bio
Date Reply #1 on Sun 23 Dec 2001 01:50 PM (UTC)
Message
Magnum,

I tried to run your test script. When I checked to see what variables were loaded in the variable list, there weren't any.

World.SetVariable "arrSpellsPointer(0)", 4 did not set any varibles.

World.SetVariable "arrSpellsPointer" & 0, 4 did load 4 into arrSpellsPointer0.

As for World.SetVariable "arrSpells(1, 1)", -1, I couldn't think of any way to load a multi-dimension array.

I think the problem is the Parenthesis in the variable names.

Eejit


Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #2 on Tue 25 Dec 2001 11:54 PM (UTC)
Message
I agree with Eejit - variable names must be alphanumeric, plus the underscore character.

You can test the return code from SetVariable, it will show a number indicating a bad name, and thus the variable isn't set.

Try doing it slightly differently, eg.
"ArrSpellsPointer_0" - of course you will get lots of variables that way. Not that that matters, except that it might slow down world saving a bit.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Magnum   Canada  (580 posts)  Bio
Date Reply #3 on Wed 26 Dec 2001 12:30 PM (UTC)
Message
Hmm. I don't understand what the underscore signifies. Seems to me, you are trying to remove the array aspect out of the variable I am trying to declare.

Let me illustrate by example:

Sub TestRoutine (thename, theoutput, thewildcards)
World.Note "Wildcard 1 is: " & thewildcards(1)
World.Note "Wildcard 2 is: " & thewildcards(2)
World.Note "Wildcard 3 is: " & thewildcards(3)
End Sub

There is a common array that we see all the time. The different "slots" in the array are distinguished by the number in parenthasis.

Now, it most cases, we are GETting a value out of that array. ...But if you wanted to SET a value to one of the "slots" in the array, what syntax would you use? ...And if you want the array to be a global variable (NOT local to the subroutine), what syntax would you use for that?

For example, in a subroutine, I may declare a variable which will be thrown out when the subroutine is complete:

Sub Example
Dim ExampleString
ExampleString = "Testing."
World.Note ExampleString
End Sub

If I were working with a global variable, it's a completely different syntax:

Dim ExampleString

Sub Example
World.SetVariable "ExampleString", "Testing."
World.Note World.GetVariable("ExampleString")
End Sub

World.GetVariable and World.SetVariable must be used. How do I use those two commands in conjunction with a variable that is an array?

I took a break from writing this posting to try some new test script. Here is a new test routine THAT WORKS:

Sub TestTwo
Dim arrSpellsPointer(), arrSpells()
Dim x, y
Dim TestString
ReDim arrSpellsPointer(4)
ReDim arrSpells(5, 4)
arrSpellsPointer(0) = 4
arrSpells(1, 1) = -1
For x = LBound(arrSpellsPointer) to UBound(arrSpellsPointer)
World.Note "arrSpellsPointer(" & CStr(x) & "): " & arrSpellsPointer(x)
Next
For x = LBound(arrSpells, 2) to UBound(arrSpells, 2)
TestString = Empty
For y = LBound(arrSpells, 1) to UBound(arrSpells, 1)
TestString = TestString & CStr(y) & "= " & CStr(arrSpells(y, x)) & " "
Next
World.Note "arrSpells(all, " & CStr(x) & "): " & TestString
Next
World.Note "Done."
End Sub

It works because all of the variables are local (to the subroutine). Now... My problem is, I need to make "arrSpellsPointer()" and "arrSpells()" global variables. E.I.: The Dim statements will be OUTSIDE the subroutine.

Once they are outside the subroutine (and global), I assume I will need to still use World.GetVariable and World.SetVariable to access the values. ...But what syntax should I use to do so?

Furthermore, and I suspect this may not be possible (yet), I would like to be able to use "LBound", "UBound" and most importantly, "ReDim" on these GLOBAL variables.

That last item would probably involve Nick creating new commands such as "World.LBound", "World.UBound" and "World.ReDim".

I have this sneaking suspicion that perhaps I should be doing things like:

World.GetVariable("arrSpellsPointer(" & CStr(x) & ")")

...because the "x" is being passed as a literal "x" and not the value of the variable named "x". I have not tested this theory yet. Even if that works, I don't see a way around the UBound, LBound, ReDim problem.

I hope you can follow all of that.

Get my plugins here: http://www.magnumsworld.com/muds/

Constantly proving I don't know what I am doing...
Magnum.
Top

Posted by Magnum   Canada  (580 posts)  Bio
Date Reply #4 on Wed 26 Dec 2001 01:05 PM (UTC)
Message
Getting back to my original test routines; I modified them slightly to test the theory I posted at the end of my last message. Unfortunately, this test still does NOT work:

Dim arrSpellsPointer(), arrSpells()

Sub Test
Dim x
Dim VariableName
For x = LBound(arrSpellsPointer) to UBound(arrSpellsPointer)
VariableName = "arrSpellsPointer(" & CStr(x) & ")"
World.Note VariableName & ": " & World.GetVariable(VariableName)
Next
World.Note "Done."
End Sub

Sub Reset_Spells (thename, theoutput, thewildcards)
ReDim arrSpellsPointer(4)
ReDim arrSpells(5, 4)
World.SetVariable "arrSpellsPointer(0)", 4
World.SetVariable "arrSpells(1, 1)", -1
World.Note "Initialized."
End Sub

Interestingly, the output (which is the same as my original posting), does offer some interesting insights:

ReDim might be working on the global arr.variables to some extent, since the array DOES get increased to 4. UBound and LBound also seem to function on the global arr.variables, as proven when the FOR - NEXT loop executes properly.

I tried using the following line:

ErrorCode = World.SetVariable "arrSpellsPointer(0)", 4

...but it didn't work. I don't know how to grab the errorcode.

Get my plugins here: http://www.magnumsworld.com/muds/

Constantly proving I don't know what I am doing...
Magnum.
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #5 on Wed 26 Dec 2001 09:47 PM (UTC)
Message
Quote:

If I were working with a global variable, it's a completely different syntax:

Dim ExampleString

Sub Example
World.SetVariable "ExampleString", "Testing."
World.Note World.GetVariable("ExampleString")
End Sub


First, I think you are getting confused between MUSHclient variables and VB variables. In this case, "ExampleString" is a MUSHclient variable (stored in the world file, if you ever save it) and thus the line:


Dim ExampleString


is not required.

You could use VB "global" variables (a different thing) in which case you would write:



Dim ExampleString

Sub Example
ExampleString = "Testing."
World.Note ExampleString
End Sub


Now, VB global variables can be arrays (and MUSHclient variables cannot) so you could say:


Dim ExampleString (2)

Sub Example
ExampleString (2) = "Testing."
World.Note ExampleString (2)
End Sub


However, you can simulate arrays using MUSHclient variables by appending a number, as I suggested in the earlier post, eg.


Sub Example
World.SetVariable "ExampleString_2", "Testing."
World.Note World.GetVariable("ExampleString_2")
End Sub


By appending "_2" to the name I create a new variable, but for purposes of working with a batch of them, I can now quickly iterate through them by making a loop that appends "_1", "_2" and so on, thus simulating an array. Now that you do that, you can simulate multi-dimensional arrays in a similar way (eg. append "_2_3").


Quote:

Once they are outside the subroutine (and global), I assume I will need to still use World.GetVariable and World.SetVariable to access the values. ...


No, see example above of a "dim" statement outside a sub, but using the standard VB syntax.

The major problem with "dim" variables is that they are lost when you close the world, or even if you reprocess the script, so if you are testing scripts, you may be frustrated that the global "dims" go back to empty every time.


- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Magnum   Canada  (580 posts)  Bio
Date Reply #6 on Thu 27 Dec 2001 07:37 AM (UTC)
Message
Ahh... Ok, I see the error of my ways. Looks like I can delete the mass of "Dim" statements at the beginning of my script file.

There is one thing though, and this is an assumption that I have been working on since I started scripting:

I've always thought of the mushclient script file as a library file. That is, subroutines are called, executed, and then forgotten (deleted from memory). There is no 'base' script program that is ALWAYS running, and thus, no 'global' variables that are ALWAYS stored in memory.

So... using the correct language, is it possible to even use global variables in a mushclient script? What would happen if I took my "World_Initialize" script, and removed the Sub and End Sub header/footer? Would it get executed once when I load mushclient (or re-process script)?

Assuming I want to maintain the spells in my spell queue across MushClient sessions:

Given this new information, it seems I would have to manage LBound and UBound myself... and the equivelent to 'ReDim' would be a series of "World.DeleteVariable" executions. It all seems feasible.

Get my plugins here: http://www.magnumsworld.com/muds/

Constantly proving I don't know what I am doing...
Magnum.
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #7 on Thu 27 Dec 2001 10:21 PM (UTC)
Message
If you take a look at the example vbscript file that comes with MUSHclient, there is a line right at the end ...



world.note "Scripting enabled - script file processed"


Because this line is outside a sub, it is executed when scripting is enabled (for that world), ie. when the world file is loaded. Thus you could use that to do some initialisation.

Yes, global variables will persist from call to call (ie. dims that are outside a sub), however you still have the problem that I mentioned that if you rerun scripting (eg. if you change the script file) then it is re-executed, and all global variables are lost (however the initialisation line is re-executed).

Thus, to make things persist, you would need to save them (eg. to MUSHclient variables) when you change them, and reload them when the script file is re-executed.

Given that, I tend to use MUSHclient variables all the time, as they persist even when you change the script file, and will persist forever if you remember to save the world file (the script can do that if you want).

However for complex things like arrays, you have to fiddle a bit to put arrays into variables. One technique, other than the one I described earlier, is to use a special character (eg. tab) to delimit occurrences of an array (when putting into a variable) and then using an "explode" function (I don't remember its exact name) to get them back from the variable into an array.

I think there are examples on the forum.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Shadowfyr   USA  (1,788 posts)  Bio
Date Reply #8 on Fri 28 Dec 2001 09:12 AM (UTC)
Message
You can probably look at it this way, scripts act like programs without the main() declared. Anything not specifically defined as a sub is simply run. QBASIC did the same thing, allowing you to create optional subroutines that could be called by name, instead of using gosub 1000, or such. Everything in the main part of the script runs first, including global variable declarations, but like with QBASIC, loading or reloading the script causes it to be treated as a new program, and you lose all the previous settings. With QBASIC there was a variable saving command, that could be used to get around this, I think (may be confusing it with the old Apple BASIC). But since vbscript wasn't really designed to run long term, just when needed by a web page, it wasn't provided with any such command that I know of.

However... Assuming you have certain programs installed, you may be able to use SQL commands to call/create a database, then plug the values into that database file and retrieve them the same way. Only, I am not sure what the minimum needed for you to do this is. I have seen some hints that indicate MS Excel and even Word can be remote called in some cases, but not exactly how it works or what can actually be done with them. On the other hand, installing MYSQL or something like it would provide the 'server' needed to send/recieve database requests. The data could thus be stored, saved and later retrieved from the database, without worrying about the script getting reloaded, since it would exist independant of the script itself. The only draw back is you have to make sure that the ORB driver (server for SQL) is running before calling the script, otherwise it obviously isn't going to work. ;)

Sadly due to the security issues involved with the way vbscript was designed, there is no other way to do this, unless there is some way to generate a cookie file, like used in browsers. However, that may be a function of the client architecture the script runs in, not the language, so mushclient may not make such a method possible. Best bet though would be the database. Ironic that MS thought to supply a set of ODBC drivers with all versions of windows, but doesn't provide even a very simple server app to access them. :p You can use the control panel for ODBC to create one of any type for which the file structures are installed, just not access any of them. :p
Top

Posted by Magnum   Canada  (580 posts)  Bio
Date Reply #9 on Fri 28 Dec 2001 11:40 AM (UTC)
Message
Shadowfyr (Who's AoD alias I still can't figure out):

Although I did programming in BASIC and PASCAL over 10 years ago, I haven't done any since... until now. A lot of programming fundamentals are hazy to me.

I seem to recall, in PASCAL, that a main program could inherit variables from any libraries that it called.

I have to assume that Mushclient runs the equivelant of it's own mainline internally, and then calls the script file. The internal program must never terminate, otherwise all variables inherited by the script 'library' would be lost.

My previous assumption was that there was no internal main program, so whenever script subroutines were called, they would be loaded, run, and then unloaded (deleted).

...but however the internal programming works, what's important is that I now understand it. With my large script, which keeps growing, I should be able to eliminate some of the mushclient variables and replace them with VB Global variables. (The ones where I don't care if they get tossed when Mushclient is closed, or the script reinitialized).

Anyway, enough of that, and on with the project!

I've developed some new script routines for emulating an array using mushclient variables. I will post the newest script in a new thread, so that anyone borrowing from my work will not have to read through all learning steps I had to take along the way.

Get my plugins here: http://www.magnumsworld.com/muds/

Constantly proving I don't know what I am doing...
Magnum.
Top

Posted by Krenath   USA  (76 posts)  Bio
Date Reply #10 on Tue 01 Jan 2002 05:26 PM (UTC)

Amended on Tue 01 Jan 2002 05:29 PM (UTC) by Krenath

Message
VBscript supports the functions JOIN() and SPLIT().

JOIN takes an array and a delimiter (such as ",") and returns a delimited string which can be crammed into a MUSHclient variable with little problem

SPLIT takes a string and a delimiter and chops the string apart wherever it finds the delimiter, returning an array.

You could easily do the following:
Quote:

Dim aArray
aArray=Array("Foo","Bar","Baz","Gleep")

World.SetVariable "ArrayTest",Join(aArray,":")

'ArrayTest now contains "Foo:Bar:Baz:Gleep"
'I don't have to use a colon. I normally use a comma,
'but all the commas makes my example harder to read.
'You could choose a space, a tilde, the string " and ",
'or whatever you want to use to separate your array
'elements. You don't have to rigidly stick to the
'example.


Later in your script, you can get your array back like so:

Quote:

Dim aArray,i
aArray=Split(World.GetVariable("ArrayTest"),":")

For i = lbound(aArray) to Ubound(aArray)
World.Note "element " & i & " contains " & aArray(i)
next


Using JOIN and SPLIT to turn your arrays into strings and back means you don't have to *simulate* using arrays. You really can use actual arrays. You simply use MUSHclient variables to store the contents, and load them into arrays when you want to work with them.

If you work with multidimensional arrays, you'll have to use JOIN and SPLIT inside loops or something, and you'll use a different delimiter for each dimension. A two-dimensional array rendered as a string might look like this:

foo1,bar1,baz1,gleep1:foo2,bar2,baz2,gleep2:foo3,bar3,baz3,gleep3

Split the string on : to get substrings. Split the substrings on , to get individual elements. Store the results in a two-dimensional array.

- Krenath from
bDv TrekMUSH
ATS TrekMUSH
TNG TrekMUSE
TOS TrekMUSE
Top

Posted by Norbert   USA  (61 posts)  Bio
Date Reply #11 on Mon 23 Jun 2003 01:00 PM (UTC)
Message
This sort of fits into this subject, but I was wondering if VB has a function that searches a array for a certain value then return that position?

Norbert

-Do you know what it's like to fall in the mud and get kicked... in the head... with an iron boot?
Of course you don't, no one does. It never happens
It's a dumb question... skip it.
Top

Posted by Shadowfyr   USA  (1,788 posts)  Bio
Date Reply #12 on Mon 23 Jun 2003 05:45 PM (UTC)
Message
Umm. I don't think so Norbert. I don't know of any language that does have such a command. Generally arrays require that you provide the search methods, since there are any number of ways you could do it, some more efficient than others with certain types of data. For instance, a sorted array is easiest to find something in using something like a bninary search, which cuts the total size of the section of the array being checked in half until it either can't divide it up to smaller bits any more or finds the value. Example:

array = {a b c d e f g h}
Find = "i"
Start = 1 (a)
End = 8 (h)
Test = int(End - Start)/2 + Start = 3 (c)
c < Find : Start = 3 (c)
Test = int(End - Start)/2 + Start = 5 (e)
e < Find : Start = 5 (e)
Test = int(End - Start)/2 + Start = 6 (f)
f < Find : Start = 6 (f)
Test = int(End - Start)/2 + Start = 7 (g)
g < Find : Start = 7 (g)
int(End - Start)/2 < 1 : Test = 8 (h)
h < Find : Start = 8 (h)
Start = End : Nothing was found.

This means you look at far fewer value, in this case 5 instead of all 8). This is misleading though, since the 'jump' gets bigger the more values you have. For 10,000 you would only check 14 values to figure out that it wasn't in the array. However, this will only work on information you can actually sort, so any other method will tend to require that you search the entire thing from start to end to make sure the value is not there. This is necessary when you 'have to' keep all the stuff in the original order you entered it.

Note.. It is possible to adapt the above method to find the best place for a new value to be inserted into a sorted array. Useful when you can manage to get it working right. ;)
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #13 on Mon 23 Jun 2003 09:33 PM (UTC)
Message
I don't suppose you mean "search a string" - you can use instr for that.

If you are talking about arrays, the easiest is probably to use "for each" and then test each array item for a match.

Certain other languages allow you to set up indexed items, known by various names, for instance "map" or "collection". In these cases, if set up properly, you can do something like this:

i = experience ["nick"]

That is, get the experience from an array indexed by a name, not a number.

Indeed Visual Basic has something similar called a collection, however VBscript does not have collections, I checked.

Shadowfyr's suggestion is correct, a linear search would be slow for a large list, and would be better off turned into a binary search. For small lists the overhead might not be noticeable.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #14 on Mon 23 Jun 2003 09:35 PM (UTC)
Message
Another approach is simply to use a database (SQL) and get data directly from that. That would allow very large collections, and be fairly flexible. There are examples of doing that in the plugins section.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


69,841 views.

This is page 1, subject is 2 pages long: 1 2  [Next page]

Posting of new messages is disabled at present.

Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.