views:

204

answers:

3

Hello all,

I've written a handful of basic 2D shooter games, and they work great, as far as they go. To build upon my programming knowledge, I've decided that I would like to extend my game using a simple scripting language to control some objects. The purpose is more about the general process of design of writing a script parser / executer than the actual control of random objects.

So, my current line of thought is to make use of a container of lambda expressions (probably a map). As the parser reads each line, it will determine the type of expression. Then, once it has decided the type of instruction and discovered whatever values it has to work with, it will then open the map to the kind of expression and pass it any values it needs to work.

A more-or-less pseudo code example would be like this:

//We have determined somehow or another that this is an assignment operator
someContainerOfFunctions["assignment"](whatever_variable_we_want);

So, what do you guys think of a design like this?

+2  A: 

Not to discourage you, but I think you would get more out of embedding something like Squirrel or Lua into your project and learning to use the API and the language itself. The upside of this is that you'll have good performance without having to think about the implementation.

Implementing scripting languages (even basic ones) from scratch is quite a task, especially when you haven't done one before.

Nick Bedford
+1 for Squirrel; It's **awesome** and **fast**. Unless the OP *wants* the experience of giving birth to a new language, I'd say this is the way to go.
LiraNuna
Those are both good suggestions (I have some experience with Lua), but the purpose of this exercise is indeed to experience the pain and agony of implementing a scripting language. I'm hoping that it will be a good thinking exercise.
ZachS
Lua is a great scripting language. It's very flexible, fast, lightweight, and easy to use if you know C. Just look at the list of games written in Lua: http://en.wikipedia.org/wiki/Category:Lua-scripted_video_games
Matt Fichman
@ZachS yep, only thing is, I've been there before. It *was* interesting getting the basics going I admit, but ultimately I didn't even get to the bytecode-execution stage which was a bummer.
Nick Bedford
If you are still interested in the guts of embeddable scripting languages, I suggest you have a glance at http://www.lua.org/doc/jucs05.pdf.
Nick Bedford
A: 

You might find value in Greg Rosenblatt's series of articles of at GameDev.net on creating a scripting engine in C++ ( http://www.gamedev.net/reference/articles/article1633.asp ).

The approach he takes seems to err on the side of minimalism and thus may be either a close fit or a good source of implementation ideas.

lzcd
That is a good article, I believe, and some of his ideas were already a part of my mental framework. Just imagine a map of opcodes where the code is the key and the value is a function that takes care of that particular operation.
ZachS
+2  A: 

To be honest: I don't think it's a good idea as you described, but does have potential.

This limits you with an 'annoying' burden of C++'s static number of arguments, which is may or may not what you want in your language.

Imagine this - you want to represent a function:

VM::allFunctions["functionName"](variable1);

But that function takes two arguments! How do we define a dynamic-args function? With "..." - that means stdargs.h and va_list. unfortunately, va_list has disadvantages - you have to supply an extra variable that will somehow be of an information to you of how many variables are there, so we change our fictional function call to:

VM::allFunctions["functionName"](1, variable1);
VM::allFunctions["functionWithtwoArgs"](2, variable1, variable2);

That brings you to a new problem - During runtime, there is no way to pass multiple arguments! so we will have to combine those arguments into something that can be defined and used during runtime, let's define it (hypothetically) as

typedef std::vector<Variable* > VariableList;

And our call is now:

VM::allFunctions["functionName"](varList);
VM::allFunctions["functionWithtwoArgs"](varList);

Now we get into 'scopes' - You cannot 'execute' a function without a scope - especially in embedded scripting languages where you can have several virtual machines (sandboxing, etc...), so we'll have to have a Scope type, and that changes the hypothetical call to:

currentVM->allFunctions["functionName_twoArgs"].call(varList, currentVM->currentScope);

I could continue on and on, but I think you get the point of my answer - C++ doesn't like dynamic languages, and it would most likely not change to fit it, as it will most likely change the ABI as well.

Hopefully this will take you to the right direction.

LiraNuna