Home » Community » Forums » » Creating a Scripting System in C++ Part II: Data Manipulation
  Intel sponsors gamedev.net search:   
[Control Panel] [Register] [Bookmarks] [Who's Online] [Active Topics] [Stats] [FAQ] [Search]

Add Forum to Favorites |  Send Topic To a Friend | View Forum FAQ | Track this topic

Page:   1 2 »»

 Last Thread Next Thread 
 Creating a Scripting System in C++ Part II: Data Manipulation
Post Reply 
Yaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaay ! At Last !

However...
I've just compiled the source (I haven't had the time to read the article yet but I wanted to see the source in action) and I get an assertion error at the third talkInstrList.push_back. I tried commenting the second talkInstrList.push_back out and that did the trick but then i get the same thing on the second varInstrList.push_back. Am I being dumb or is something wrong ?

Cheers

Tony

Edited by - TonyFish on February 2, 2002 6:52:55 PM

 User Rating: 1017   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Simply uncomment the line that says #include <assert.h> (at the top of virtualmachine.h) and it should compile fine.

If it doesn't, let me know again.

"Don't be afraid to dream, for out of such fragile things come miracles."

 User Rating: 1079   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

...unless of course you mean it compiled, and an assertion failed? When I ran it myself, none of the assertions failed, so this should not be the case.

"Don't be afraid to dream, for out of such fragile things come miracles."

 User Rating: 1079   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

So as to avoid confusion, please note this pseudo script:
set 0, 7
set 1, 7
set 2, 7
inc 1
dec 2
add 3, 1, 2

The last instruction should actually read:
add 3, 0, 2

Thanks to Charles Gibson for finding this mistake so fast. The source code is still correct, however.

"Don't be afraid to dream, for out of such fragile things come miracles."

 User Rating: 1079   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

It compiles fine and fails as previously described.
I'm using VC++6 by the way.

[EDIT]
Aha ! I'm using VC++6 in NT. Are you running Win98 ? That might explain it. Remember that the family versions of windows (Win95,Win98) let you do potentialy dangerous things whereas NT/2000 won't let you access memory in a dangerous way. After messing around I've noticed that the error seems to occur just after an instruction with 3 arguments (like op_print) is pushed.
I'm looking into it but if you have any ideas please post.
[/EDIT]

[EDIT2]
OK, I've isolated the problem. The assertion failure occurs whenever an instruction created using 3 arguments, is removed. For some reason VC doesn't like the "delete[] _data;" call in the destructor. If I comment it out the program seems to run fine but that would leak memory wouldn't it. Ugh char *'s are nasty.
[/EDIT2]

Cheers

Tony

Edited by - TonyFish on February 1, 2002 2:33:46 PM

Edited by - TonyFish on February 1, 2002 2:52:00 PM

 User Rating: 1017   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Yes, I am using Win98... uh oh.
Let me check it out a bit, and see if I can figure out what NT has against my code.

"Don't be afraid to dream, for out of such fragile things come miracles."

 User Rating: 1079   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Alright, I'm pretty sure I know what it's complaining about, and it is a problem on my behalf. What I find interesting is how it knows to complain.

The Instruction class needs either a deep-copy constructor (you would need to store the data size in each instruction), or at least a copy constructor that will take ownership of the data away from the original. Otherwise, when the temporary Instruction object created on the stack, while being pushed onto the vector, will delete the data as it leaves scope.

I offer this new Instruction class as a possible fix. Please tell me if it works for you.

    
// the basic instruction

class Instruction
{
public:
    Instruction(opcode code) : _code(code), _datsize(0), _data(0) {}
    Instruction(opcode code, const char* data, size_t dataSize)
        : _code(code), _datsize(dataSize), _data(new char[dataSize])
    { memcpy(_data, data, dataSize); }	// we must store our own internal copy

    Instruction(const Instruction& instr)
        : _code(instr._code), _datsize(instr._datsize), _data(new char[_datsize])
    { memcpy(_data, instr._data, _datsize); }
    ~Instruction()  { delete[] _data; }	// and we must then clean up after it


    opcode Code() const         { return _code; }
    const char* Data() const    { return _data; }
private:
    opcode  _code;
    size_t  _datsize;
    char*   _data;  // additional data

};
    


The new thing here is the copy constructor, which will perform the deep copy I mentioned.

Edit: a little reformatting
"Don't be afraid to dream, for out of such fragile things come miracles."

Edited by - Redleaf on February 1, 2002 3:04:58 PM

 User Rating: 1079   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

It may know how to complain but the complaint itself was pretty damn obscure !
Anyway it works fine now.
Maybe it's time for me to actually read the article now !
Thanks

Tony

 User Rating: 1017   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I was having the same problems with it. Then I spent an hour debugging when I remembered push_back making copies. Long story short I just finished all my modifications and was about to post it when I saw your last post.

Good tutorial though.

 User Rating: 1158   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I'm sorry to have put you through that. I know how terrible debugging of this nature can be. And what a silly mistake...

"Don't be afraid to dream, for out of such fragile things come miracles."

 User Rating: 1079   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Horrible, horrible article!

J/K, F'ing awesome article (ok, lame attempt at humor, so what?)

Definitally want script loading from file in the next installment.

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Why do you use char* buffers and manually allocated memory? This is exactly what std::string does for you automatically and would make your code cleaner.

 User Rating: 1015    Report this Post to a Moderator | Link

Maybe because more people are used to using char* than std::string?


Just an thought anyway...

 User Rating: 1035   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Well I was actually going to ask that. Why not use std::string ? Does it present any major drawbacks (in this context) as opposed to the char * approach ? (Remember I'm new to all this plus my c++ lecturer clearly didn't do a good job as he never taught us about issues like deep-copying which, now that I know about it, is common sense + simplicity. grr)

Cheers me'dears

Tony

 User Rating: 1017   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Sure, it would make the code cleaner at the moment. When you actually begin treating it as something other than a string however, and more like serial data, it begins to be a bit unnatural to use.

On top of that, a string is a bit larger than a single pointer, and with many instructions, it can add up. However, if you'd like the copy-on-write functionality, you would need something in addition to the pointer anyway.

I'd say the best alternative, if you really want to separate the copy-on-write functionality from the instruction class, (and it would be reasonable to do so, for the reason you give) would be to make a very simple copy-on-write buffer class, and simply include that in the Instruction. It would also be smaller than a full-blown string as far as memory is concerned.

A solution for simplifying this problem will definitely be available in the next article, either way. The solution I gave here was merely in the interest of time, to correct my mistake, and to allow TonyFish and others to use the code now, rather than after a commitee meeting.

Good point though.

"Don't be afraid to dream, for out of such fragile things come miracles."

 User Rating: 1079   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Fantastic article. I'm looking forward to when you start getting into language syntax.

Regards,


Dire Wolf
www.digitalfiends.com

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I think most script has something to do with objects (or actor). My question is how to communicate between that Script VM (or Engine) to the executed object?
... or how to communciate with the executor (objects that contain the script).

I'm looking for a good design on doing these...


-dienw-

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Dienw, you have to create some form of interface between separate components for them to be able to communicate, and the same is true when dealing with scripts and objects, and anything else you could use them for.

Such an interface could consist of functions, perhaps some data, and in some cases, specialized mediating classes.

The simplest way would simply be to expose object functionality through a layer of functions that a VM has access to, and can call by certain script instructions.

I'll definitely be covering this in a future article.

"Don't be afraid to dream, for out of such fragile things come miracles."

 User Rating: 1079   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Well since we're on the subject:

quote:
Original post by Redleaf


Such an interface could consist of functions, perhaps some data, and in some cases, specialized mediating classes.

The simplest way would simply be to expose object functionality through a layer of functions that a VM has access to, and can call by certain script instructions.

I'll definitely be covering this in a future article.


I'm slowly writing a scripting system to tie in with a game that I'm working on, but going about it somewhat differently -
I'm using C and just writing functions which I load into a small callback array ...

Now that I have the basic VM down and working, I'm beginning to think about interfacing with the host program, and implementing a sort of message passing scheme. The vm will request basic information from the game engine, like "can I see anybody?" and the game engine will, of it's own accord, tell the scripted actor things like "someone just became visible in front of you" or "you just got hit."

And, of course the other thing I'm thinking about is scaling the interface to deal with multiple units. Is the best way to do it to have one big "game script" or is it better to have a core game script which will load/store other scripts when necessary - that way each script has a unique interface to a single object in the game ... it's all very interesting to think about, but still somewhat into the future for me.

I would like some feedback on my ideas though - maybe I'll set some of my code up on a webpage somewhere so everyone else can see what I have going on and critique everything.

Feel free to give me any ideas, or mail them to me (should be an email link above!)

Kendall

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

There are games which use both of the techniques you describe, actually.

The ones which are comparable to the "one big game script" are essentially games written entirely in the scripting language, with only the engine it runs on being programmed natively in a language like C or C++.

Then there are some which have particular game components which run their own scripts. The scripts then dynamically define the behavior of these hard-coded components in the game.

I happen to think the second category is the most interesting, personally. The first category works well, however. Tribes is a pretty good example of the first category, as far as I know.

I'd be glad to check out where you're headed with your code. The callback system you describe is a nice simple approach which should be easy enough to impliment.

"Don't be afraid to dream, for out of such fragile things come miracles."

 User Rating: 1079   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

redleaf: you might want to get dave to update the code. i've just downloaded the lastest version (GDServer time 4:52:29PM on feb 9th) and it doesnt have the instruction fix.

strange - compiling the old version in relase mode worked fine until i hit the enter key when it moaned once, while the debug would err before the script was actually executed. nice to see the Win2K can still perform some dodgy memory ops

 User Rating: 1168   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

woo, page 2

sorry :D

 User Rating: 1168   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

Good call.

"Don't be afraid to dream, for out of such fragile things come miracles."

 User Rating: 1079   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

The downloadable code should now contain the fix.

"Don't be afraid to dream, for out of such fragile things come miracles."

 User Rating: 1079   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link
Page:   1 2 »»
All times are ET (US)

Post Reply
 Last Thread Next Thread 
Forum Rules:
You may not post new threads
You may post replies
You may not edit your posts
You may not use HTML in your posts
Jump To:
Administrative Options: