Refering to Variable Names with other Variables

BlitzMax Forums/BlitzMax Beginners Area/Refering to Variable Names with other Variables

Mordax_Praetorian(Posted 2006) [#1]
Hey, I'm currently trying the B-Max demo, and was wondering if it could do something I never found a way to do in B+

Often in my games engine (which I want to port over to B-Max), the engine needs to refer to a variable, the name of which is contained within another variable.

Right now, I have to have a huge long list such as:

Select Thing
   Case "Thing1"
      DrawImage Thing1, X, Y
   Case "Thing2"
      DrawImage Thing2, X, Y
   Case "Thing3"
      DrawImage Thing3, X, Y
End Select


There is one specific procedure where the lists like this are getting absurdly long, where I read a map for a room (Made of 4 letter codes) from a file and have the images for the tiles they refer to in variables of the same name.

Is there a command in BlitzMax that would allow me to do something like this

DrawImage VarName(Thing), X, Y

Where the VarName command would take the string contained in Thing and refer to the variable of that name


jhans0n(Posted 2006) [#2]
I know it's not exactly what you're looking for, but couldn't you drop all of your "Things" into an array, and read an integer from the map that corresponds with the element of the array that you want?

DrawImage Things(thingInt), X, Y


Mordax_Praetorian(Posted 2006) [#3]
Thats an interesting solution that I hadnt thought of

I'll experiment with this when I get to porting that part of the code (will be soon)

Thanks


N(Posted 2006) [#4]
Could use a hash table I should think.


Mordax_Praetorian(Posted 2006) [#5]
Whats a hash table?


Suco-X(Posted 2006) [#6]
Here is another solution for you.



Mfg Suco


N(Posted 2006) [#7]
This is a hash table (original written by Matt Laurenson [Defoc8], I added a lot of stuff to it):


This is hash.c:


This is how I use it in my engine:


As pointed out by Suco-X, a map would work as well, but I think in this case a hash table would be faster.


Mordax_Praetorian(Posted 2006) [#8]
Sorry Noel, but I'm afraid I dont understand any of that in the slightest

Suco, that method looks good, but it'll take some looking at before I undertand it completely, I'm very bad at understanding other peoples code, thanks for the help


N(Posted 2006) [#9]
Basically, RegisterObject registers an object in the global object table with the name specified by name$ and with the value obj:Object. It returns the key for this object (in the case that you wish to refer to it by key and not name).

You then use the key or name with either GetObjectByHandle or GetObjectByName to retrieve the object.

When you no longer want the object in the hash table, you unregister it with UnregisterObject and either pass the name string or specify the name as Null and pass the key to the second argument.

So if your type has a ToString method, you can use that as the name and retrieve whatever is stored with its name with GetObjectByName.

E.g., DrawImage( TImage(GetObjectByName( Thing.ToString( ) )), blahdee, blah, blah, fooblah )

Hopefully that made sense.

And I would recommend using the Indigo code (last codebox) since it's easier than having to know how to use the gHashTable type (not that it's hard, but having a simple public interface is nice).

The only 'problem', and this should be fairly obvious, is that your names must be unique. This is a trait shared by arrays as well. Two values can't share the same index, after all.


Picklesworth(Posted 2007) [#10]
First off, thanks to Noel for posting that!
I'm really surprised that this thread disappeared. It is a great example, and precisely what I was looking for :)

I am looking for which is faster (A hash table or a TMap?) for getting a variable:Object that is linked to a key:String.
Comparing strings is a pretty painful thing, but it seems that hash tables are doing some similarly painful math stuff. Is there a specific difference in how each should be used?
In my case there aren't too many variables bouncing around (20 at most, I'd wager).

What is the grand purpose of hash tables? Would it be misuse to be using a hash table simply to link strings to objects, or is that the reason why they exist?


Edit

This thread is also pretty helpful: http://www.blitzbasic.com/Community/posts.php?topic=51627


SculptureOfSoul(Posted 2007) [#11]
A hashtable should be faster than a TMap once the TMap gets to some size - although it's hard to really tell without doing some testing.

A proper hash algorithm is very very fast. Once the hash itself is generated, the hash table is essentially just looking up the data in an array. So hash tables are only marginally slower than arrays. My hashtable, for instance, only spends 141 millisecs performing 900,000 lookups (I managed to get it to be faster than Lua's hash table lookups - woot!) Actually, these aren't just 900,000 hashes - it's actually retrieving an entry for a specific key 900,000 times, and then making an assignment to that value. So yeah, it's fast.


In your case, I think the hash table will be faster than the TMap. Given that you know approximately how many key/value pairs you'll need, you won't even face the one slow operation of a hash table - resizing it.

Should I post my hash code, even though it's not fully tidied up yet?

It's based off of the core code above but with plenty more functions. For instance, you can store multiple values per key with the ability to sort those via overloading the Compare method of the objects (this was so I could build ordered lists of key/value pairs that shared the same key...I was building a sort of "dynamic function" hooking system and the hooks could either exist or not, but if they did exist they needed to be ordered in a specific manner.)

Of course you can also "GetMultipleValues", when you've got more than one key/value pair that share the same key - you can specify the initial size of the table, you can manually grow the table (I planned to make this growth configureable to be automatic based on some variables that you set but haven't got there yet and probably won't be adding it, although it should be a relatively trivial add)

I also dug up a hash algorithm that is MUCH more efficient at evenly spreading the entries throughout the hash table.


ImaginaryHuman(Posted 2007) [#12]
Function pointers


Picklesworth(Posted 2007) [#13]
141 millisecs performing 900,000 lookups

Holy... wow!
I keep forgetting how fast these computer things are :)

Thank you for the very in-depth information, SculptureOfSoul. It is very helpful!

(I'm also very glad to finally have some clue what those weird hash tables I keep hearing about actually do)


SculptureOfSoul(Posted 2007) [#14]
Well, I'm going to tidy up the code a bit and post it later. I'm not using it right now and if someone else finds some use for it all the better.

Regarding the speed: hehe, yeah, it's amazing what a computer can do. It's also amazing what kind of impact little optimizations can make. Hand-rolling a for loop instead of calling for-eachin shaved off ~200 or so millisecs from the above # of operations. While that's really rather trivial in the scheme of things, I was going to be doing tons of lookups per frame (every character in the MUD was a big hash-table of data, basically, so that I could add variables, add hooks to "logic modules", etc etc.) so I needed the utmost speed. I used Lua as a benchmark since it's fundamental variable type, the table, is based on hash tables and is highly optimized.

Hope to have the code up and in the archives within a few hours.


SculptureOfSoul(Posted 2007) [#15]
Dangit - I had a huge lengthy reply about the inner workings of a hash table and IE borked on me. Grrrrr.


SculptureOfSoul(Posted 2007) [#16]
Well, here's a link to the hashtable type I was talking about: http://www.blitzmax.com/codearcs/codearcs.php?code=1907

If you've got any questions, feel free to ask.