|
|
View previous topic - View next topic |
Author |
Message |
I am Har har har Slightly Deformed Faerie Princess
Joined: 08 Jan 2004 Posts: 33 Location: America.
|
Posted: Tue Mar 23, 2004 1:58 pm Post subject: Question: String accessing variables |
[quote] |
|
I have a problem. I want to be able to modify game variables with my scripting engine. The problem is that I have to reference the variable by its name from a string variable. An example would be something like this:
Avariable% = 5
RefString$ = "Avariable%"
RefString$ = RefString$ + 1
Now, I know that this code won't work, but I want to make a way to access a variable through its identifier. Anyone that knows anything about this that could help would be greatly appreciated.
-ImHhh _________________ I do what I like. Do you have a problem with that?
|
|
Back to top |
|
|
white_door Icemonkey
Joined: 30 May 2002 Posts: 243 Location: New Zealand
|
Posted: Tue Mar 23, 2004 8:43 pm Post subject: |
[quote] |
|
You will not be able to do it the way you are thinking, referencing a variable by a string name is not possible in most languages.. However you have several options about other ways of doing it, here are a few:
1. have a massive if then construction, checking if the string is equal to the name of a variable then setting it.
2. Use a big array for all your variables then access it with numbers from the scripting engine. "1%=4" in the script might references script_vars%(1)=4 or however you do it in basic
3. You could have a array of strings and use a loop to compare the name of a variable in a script to each in the array.. then access a second array with the same element.
4. Similar to the idea from 3 but faster, you could hash the variable name (convert the name into a number using math) and use number to reference a variable in a big array
|
|
Back to top |
|
|
valderman Mage
Joined: 29 Aug 2002 Posts: 334 Location: Gothenburg, Sweden
|
Posted: Tue Mar 23, 2004 8:53 pm Post subject: |
[quote] |
|
I made a tree for the purpose. Basically, you use the first char as an index into an array, then the second, etc. until you reach \0.
It eats a lot of memory, and my implementation isn't the best (supporting ASCII chars 0 through 256, using recursion, etc.), but I believe it would be the fastest way, at least if you have a lot of variables. _________________ http://www.weeaboo.se
|
|
Back to top |
|
|
LeoDraco Demon Hunter
Joined: 24 Jun 2003 Posts: 584 Location: Riverside, South Cali
|
Posted: Tue Mar 23, 2004 10:14 pm Post subject: |
[quote] |
|
In a good language, this is what a symbol table is used for. A symbol table can be anything, really, from a simple list or stack, to something semi-complex, like a map. What you would want to do is associate an offset in memory, in which you store whatever value you're playing with in your scripting language, with the identifier you are using in your scripting language.
In C++, you could use something simple, like an STL map (a heap or a hash-table would also work; maps are often stored internally via either of these constructs) to store your symbol table. The key for the map would simply be strings (which would match your identifier), and the associated value would be the value you wanted to store in you scripting language. Course, there are some problems that come into play: if you want different levels of scope, you'll more than likely have to rename variables by some scheme, so that you do not loose anything. Also, if you want to store all forms of variables in your engine in one convenient map, then you would have to store values as a super-class and such. But, these are all minor problems.
And alternative method would be to have an Identifier class, which stores inside of it a string, representing its textual reference, and its value; you could then store these in a list or a stack, and easily access them that way. A lot of this is simple applications of compiler concepts.
Course, all of this is, relatively speaking, moot, as you are, apparently, using a BASIC flavor. So, you have options: stop using BASIC, and pick up a real language; create an object pattern in BASIC that can be used to create the objects mentioned above (which would be a headache, as you would have to fake memory addressing to do anything useful); or create a few simple structures that can fake the above concepts.
Now, my BASIC syntax is a bit rusty, as I haven't touched the language in several years, but what I would do is create a Record structure, which stored three pieces of data: the string name of variable you wish to create in your scripting language, a bit flag that represents what type of variable you are creating, and a LUT offset variable, that would keep track of which offset in a global array this record is referencing. You could then have a global array for each of the types you wished to support, as well as a Record array, which would store a reference to each variable you create in your scripting engine. This isn't terribly efficient, but it would work, and is a rather nice abstraction.
I had a professor whom was fond of quoting, "There is no problem in systems design that cannot be solved by adding another layer of abstraction." So yeah: put a few layers of abstraction on that, and you should be okay. _________________ "...LeoDraco is a pompus git..." -- Mandrake
|
|
Back to top |
|
|
janus Mage
Joined: 29 Jun 2002 Posts: 464 Location: Issaquah, WA
|
Posted: Tue Mar 23, 2004 11:17 pm Post subject: |
[quote] |
|
If you use VB, you can just use CallByName to access methods and properties in your classes. But I assume that you're using QB, so no luck there.
|
|
Back to top |
|
|
I am Har har har Slightly Deformed Faerie Princess
Joined: 08 Jan 2004 Posts: 33 Location: America.
|
Posted: Wed Mar 24, 2004 9:17 pm Post subject: |
[quote] |
|
1. Yes, I am using QB.
2. Thanks for your advice. Soon after I posted this, however, I found a way that might work. Using Varseg and Varptr, I can find the location of the variable in memory. Then, I output the variable names and their locations to a file. Then, I set up a sub like this:
SUB MODVAR(SEG%, OFFS%, VAL1%, VAL2%)
INPUT #FILE%, SEG%, OFFS%, VAL%
DEF SEG = SEG%
POKE OFFS%, VAL1%
POKE OFFS% + 1, VAL2%
END SUB
Or, If I wanted to add or subtract:
ADDITION:
POKE OFFS%, PEEK(OFFS%) + VAL1% 'VAL1 >= 1
SUBTRACTION:
POKE OFFS%, PEEK(OFFS%) + VAL1% 'VAL1 <= -1
Please tell me if this code will not work, but from all of the tests I've run, the program stores the variable in the same segment/offset every time it runs.
Thank you for your time _________________ I do what I like. Do you have a problem with that?
|
|
Back to top |
|
|
LeoDraco Demon Hunter
Joined: 24 Jun 2003 Posts: 584 Location: Riverside, South Cali
|
Posted: Wed Mar 24, 2004 11:18 pm Post subject: |
[quote] |
|
Again, my QB syntax/semantics/logic is a bit fuzzy, as I haven't used it in a long time. (Let that stand as a standard disclaimer.) It's never a good idea to assume a location in memory, for anything really, as it might be something the interpreter is doing that is specific to your box. Place an executable on somebody elses, and you don't know what will happen.
That said, this would more than likely work, as you are hopefully dumping the memory locations at runtime into a file. I say hopefully because in this way, you are technically not assuming locations.
Here's a different idea: since your modvar sub accepts parameters anyway, why not send it directly the segment and offset of the variable? That way, you're avoiding the necessity of having to preform a write and read from a file, which can be a slow process. And, you wouldn't have to be assuming locations for variables (if you are). It would be something to mess around with. _________________ "...LeoDraco is a pompus git..." -- Mandrake
|
|
Back to top |
|
|
DrunkenCoder Demon Hunter
Joined: 29 May 2002 Posts: 559
|
Posted: Thu Mar 25, 2004 5:08 pm Post subject: |
[quote] |
|
why not go the compiler route and build a proper symboltable?
If you use hashing or some other sane technique performance shouldn't be too bad, maybe some sort of tree would suite
you better since youre using QB I haven't used the langauge
myself.
Oh, and about CallByName... that can quite easily be simulated in C/C++ on windows as long as you know what properties and functions you want to expose. _________________ If there's life after death there is no death, if there's no death we never live. | ENTP
|
|
Back to top |
|
|
MadQB I wanna be a ballerina!
Joined: 31 May 2002 Posts: 24
|
Posted: Fri Mar 26, 2004 2:22 pm Post subject: |
[quote] |
|
First, I use a system similar to white_door's #2, it goes like this:
'******In the script file********
FLAG 001,04
IF 001,04,27
'****
that sets flag # 001 to a value of 04 then later on i check to see if flag # 001 has a value of 04, if it does, GOTO line label 27 in the script.
this is what my code looks like:
'*******QB Program (script parser)******
ScriptFlags(001)=04
IF ScriptFlags(001)=04 THEN &&&&&&
'***************************
Substitute &&&&&& with code for finding a line label in the script. This works good, but after you get 10 or fifteen number defined variables things get confusing.
So to answer your question, take a look at the following snippets:
'**********Script suggestion***********
MAKEVAR PlayerX INT
MAKEVAR PlayerName STRING
PlayerX=5
PlayerName=John Doe
'**********
That would tell the parser to make an integer variable called 'PlayerX' and a string variable and call it 'PlayerName'. Then Set PlayerX to 5 and PlayerName to 'John Doe'.
'********QB Code************
TYPE ScriptINTS
IntName as STRING * 12
IntValue as INTEGER
END TYPE
TYPE ScriptSTRINGS
StrName as STRING * 12
StrValue as STRING * 30
END TYPE
DIM SHARED ScriptIntVars(100) as ScriptINTS
DIM SHARED ScriptStrVars(100) as ScriptSTRINGS
'Parser Code
'Add a variable
'IntName$="nameofintvar"
'IntVal%=Value
'StrName$="nameofstrvar"
'StrVal$=string
IF ScriptIntVars(I).IntName="" THEN
ScriptIntVars(I).IntName=IntName$
ScriptIntVars(I).IntValue=IntVal%
END IF
IF ScriptStrVars(I).IntName="" THEN
ScriptStrVars(I).StrName=StrName$
ScriptStrVars(I).StrValue=StrVal%
END IF
'**********************
Then to check or change a value you just check the name of ScriptStrVars(I).StrName or ScriptIntVars(I).IntName and see if it is consistent with your variable's name, if so change the value, if not go to I+1 and do it again. Hope that helps!
EDIT: Now of course the above code would only allow 100 ints and 100 strings, so if you needed more you would have to change the DIM ScriptStrVars(100) to 150 or 200 or whatever you wanted. I would think that if you had too many you would want to store them in extended memory to save stack space, but maybe there is enough room. _________________ yep...
|
|
Back to top |
|
|
valderman Mage
Joined: 29 Aug 2002 Posts: 334 Location: Gothenburg, Sweden
|
Posted: Fri Mar 26, 2004 3:18 pm Post subject: |
[quote] |
|
I think it'd be mighty slow if you had to compare 100 strings everytime you wanted to use the last variable. _________________ http://www.weeaboo.se
|
|
Back to top |
|
|
MadQB I wanna be a ballerina!
Joined: 31 May 2002 Posts: 24
|
Posted: Fri Mar 26, 2004 6:57 pm Post subject: |
[quote] |
|
Quote: | I think it'd be mighty slow if you had to compare 100 strings everytime you wanted to use the last variable. |
Actually in QB it's not that slow since the compiler does all the comparing for you. And it was just a suggestion anyway, in the user defined typedef, it could store a memory address instead of using a string. That would be quicker and he could just POKE any new values into memory, and PEEK it every time he needed the current value. _________________ yep...
|
|
Back to top |
|
|
LeoDraco Demon Hunter
Joined: 24 Jun 2003 Posts: 584 Location: Riverside, South Cali
|
Posted: Sat Mar 27, 2004 12:00 am Post subject: |
[quote] |
|
Valderman wrote: | I think it'd be mighty slow if you had to compare 100 strings everytime you wanted to use the last variable. |
This is where having a stack of activation records lying around would be handy. Rather than having to, more often than not, fruitlessly search several different arrays for the appropriate storage container, you'd just have to search the activation record array. _________________ "...LeoDraco is a pompus git..." -- Mandrake
|
|
Back to top |
|
|
therabidwombat Sick of Being A Fairy Princess Yet?
Joined: 08 Mar 2004 Posts: 14 Location: Canada
|
Posted: Tue Mar 30, 2004 2:26 pm Post subject: |
[quote] |
|
If you were using GameMaker, then there's actually a function to refer to a variable by a string the same as the variables name. I can't remember exactly what it's called. If it can be done in GameMaker, I'm sure you can do it. _________________ How much crap would a wombat bat if a wombat could bat crap?
---------
Head Programmer on Worlds Beyond; Possibly entire EAA saga
Progress: ~40% done engine
|
|
Back to top |
|
|
js71 Wandering DJ
Joined: 22 Nov 2002 Posts: 815
|
Posted: Tue Mar 30, 2004 6:14 pm Post subject: |
[quote] |
|
Well, Game Maker code is pretty much stripped down C++. Emphasizing the 'stripped down' here... True, there's a function to do that in Game Maker, but plain C++ doesn't have a lot of the premade things game maker does-- You have to do a lot yourself.
|
|
Back to top |
|
|
|
Page 1 of 1 |
All times are GMT
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|