Script system in application - c++

I'm developing a game and now I want to make script system for it.
Now I have abstract class Object which is inherited by all game objects. I have to write a lot of technical code, add new object type into enum, register parser function for each object (that function parses object's params from file).
I don't want to make such work. So the idea is to get some script system (boost.python for example, because I'm using boost in my project). Each object will be a simple python-script, at c++ side I just load and run all that scripts.
Python isn't hard -typed so I can register functions, build types dynamically without storing enum, etc. The only bad part is writing a lot of binding-code but It makes only once.
Are my ideas right?

Can you give us a rough idea of how large the game is going to be?
If you're not careful, you could give yourself a lot of extra work without much benefit, but with some planning it sounds like it might help. The important questions are "What parts of the program do I want to simplify?", "Do I need a scripting language to simplify them? and "Can the scripting language simplify them?".
You mentioned that you don't want to have to manually parse files. Python's pickle module could handle serialization for you, but so could .NET. If you're using Visual Studio, then you may find it easier to write the code in C# than in Python.
You should also look for ways to simplify your code without adding a new language. For example, you might be able to create a simple binary file format and store your data structures without much parsing. There are probably other things you can do, but that would require more detailed knowledge of the program.

Related

C++ and LuaJIT, Scoped script environment

I've been using LuaJIT for some times now. The tip of the iceberg was enought for my needs until now, but my recent project require me to dig a little deeper.
My actual knowledge of LuaJIT is making function available from C++ to Lua and from Lua to C++. That include passing parameters, tables and retrieving return values.
This is the model I am used to:
I tried to search around for "scoped environement luajit" and multiple variation of the query, but unfortunately I did not find anything relevant. I might not use the right words?
This is the model I want to achieve :
I want to make a "global script environment" that I will share the C++ functions with then make it available to the "scoped script environments".
//push arguments
luaScopedEnvironment1->call("doSomething");
I just want a starting point, help for the terminology and maybe some pointers to related documentation :)
Thanks you for taking time to read me.
I dont think Lua or LuaJIT supports such a thing but if I'm not mistaken, what you are after is called "sandboxing".
It creates a new environment with which you can strip out or add functionality to. Its handy for removing IO and OS functionality.

Is it possible to change the code in the program itself in c++?

About the last year I did Java(Android)-programming, and did C# the Year before that. About a month now I'm learning C++, and since I got over friends, inheritance and stuff, I got a few questions, since I haven't been working with it up until now:
Is there a way for a class to define friends later on, because they need to exchange information or something. e.g. is there a way to define a 'random' friend later on? what do you need for that? The function's name or the address of the class?
Or is there generally a way to change the code from the program itself, so that it won't be necessary to recompile? e.g. creating new functions, classes or so?
I'd be very happy about any answer about that.
What you want to do is not possible with C++. If you need that sort of dynamically changing the program, you are better advised using a more dynamic higher-level language like Lisp.
friends can only be added to a class by modifying its source code. This is a feature, not a bug.
There are two ways to extend functionality like that.
Use dynamically loaded modules with the extended functionality. These modules supply a specific interface, and can be compiled separately from the main program.
Add support for scripting - allow users to add write scripts, and run them from inside your program.
The first solution is easier, depending on how much control you want to give those scripts.

Returning an instance of a C++ object in Lua 5.2?

I have looked at multiple sources and I just do not understand them. Mostly all of them are either using a library like luaBind (Which I do not want to use because it relies on Boost) or they are not already instanced objects in C++ but rather created in Lua directly.
I have a Player class, which is wrapped in another class to handle Lua calling. I have created a std::vector list of both these objects in my initialization of the application.
So basically I do not want the Lua script to be creating these player objects I would just like to create a function getPlayer() which then returns the Lua wrapped object. I have no idea where to start with defining the Lua wrapped object for Lua to call nor do I know how to return an instance of the object to Lua so I can use calls from it.
Here's an example of what I would like my Lua script to look like:
player = getPlayer(1) -- Returns the Lua wrapped object from C++ where 1 is the object's index in the std::vector list
print("Player's name: ", player:name()) -- Print's the player's name
Could someone point me to a decent tutorial that explains how to do this. I am pretty sure that this isn't some sort of "Never been done and why would you want to" case so surely there must be at least one tutorial out there. I have been searching for about 2 days now with no positive results.
This isn't a Never been done task, but companies which they use Lua have been already done lots of changes and improvements on the raw source of Lua to make it fit in the place that they want. Since all of us programmers are not that cool to do such stuffs on third-parties sources, we have to use whatever exists out there. You think Crytek is using the exact same version of Lua which is resided on its website's repository? No sir.
You can make this happen by using userdata. Or you can use meta tables. There is also another piece of code named Luna which it helps you to achieve faster.
Otherwise, it's all Luabind, and believe me you're going to end up using it one way or another. Besides, its use of Boost is not that broad and there is going to be just 200kb added to the final executable. Check this address if you want to use Luabind sometime, it's really a good article on the web. http://blog.nuclex-games.com/tutorials/cxx/luabind-introduction/
If you're too bored with Lua, I may suggest you to use squirrel as an alternative to Lua. Personally, I prefer squirrel more than Lua because of its C like syntax and its abilities which they are the ones that we want. Besides, you can even declare constants and use real classes in its context which Lua is pretty failed at this. The funny thing about squirrel is that the designer is a guy that he has been working on FarCry on developing Lua for its engine.

What does embedding a language into another do?

This may be kind of basic but... here goes.
If I decide to embed some kind of scripting language like Lua or Ruby into a C++ program by linking it's interpreter what does that allow me to do in C++ then?
Would I be able to write Ruby or Lua code right into the cpp file or simply call scripts from the program?
If the latter is true, how would I do that?
Because they're scripting languages, the code is always going to be "interpreted." In reality, you aren't "calling" the script code inside your program, but rather when you reach that point, you're executing the interpreter in the context of that thread (the thread that reaches the scripting portion), which then reads the scripting language and executes the applicable machine code after interpreting it (JIT compiling kind of, but not really, there's no compiling involved).
Because of this, its basically the same thing as forking the interpreter and running the script, unless you want access to variables in your compiled program/in your script from the compiled program. To access values to/from, because you're using the thread that has your compiled program's context, you should be able to store script variables on the stack as well and access them when your thread stops running the interpreter (assuming you stored the variables on the stack).
Edit: response:
You would have to write it yourself. Think about it this way: if you want to use assembly in c++, you use the asm keyword. You then in the c++ compiler, need to parse the source file, get to the asm keyword, and then switch to the assembly compiler. Then the assembly compiler needs to go until the end bracket of the asm region and compile this code.
If you want to do this,it will be a bit different, since assembly gets compiled, not interpreted (which is what you want to do). What you'll need to do, is change the compiler you're using (lets say c++), so that it recognizes your own user defined keyword. Lets say this keyword is scriptX{}. You need to change the c++'s parser so that when it see's scriptX{}, it stores everything between the brackets in the readonly data section of your compiled program. You then need to add a hook in the compiled assembly file to switch the context of the thread to your script interpreter, and start the program counter at the beginning of your script section (which you put in read only data section of the object file).
Good luck with that...
A common reason to embed a scripting language into a program is to provide for the ability to control the program with scripts provided by the end user.
Probably the simplest example of such a script is a configuration file. Assume that your program has options, and needs to remember the options from run to run. You could write them out to a file as a binary image of your options structure, but that would be fragile, not easy to inspect or edit, and likely not portable across systems. Writing the options out in plain text with some sort of labels for which is which addresses most of those complaints, but now you need to parse that text and recover the options. Then some users want different options on Tuesdays, want to do simple arithmetic to compute one option from another, or to write one configuration file that they can use on both Windows and Linux, and pretty soon you find yourself inventing a little language to express all of those ideas and mechanisms with. At this point, there's a better way.
The languages Lua and TCL both grew out of essentially that scenario. Larger systems needed to be configured and controlled by end users. End users wanted to edit a simple text file and get immediate satisfaction, even (especially) when working with large systems that might have required hours to compile successfully.
One advantage here is that rather than inventing a programming language one feature at a time as user's needs change, you start with a complete language along with its documentation. The language designer has already made a number of tough decisions for you (how do I represent strings and numbers, what about lists, what about named values, what does if look like, etc.) and has generally also brought a carefully designed and debugged implementation to the table.
Lua is particularly easy to integrate. Reading a simple configuration file and extracting the settings from the Lua state can be done using a small subset of its C API. Once you have Lua available, it is attractive to use it for other purposes. In many cases, you will find that it is more productive to write only the innermost loops in C, and use Lua to glue those functions together and provide all the "business logic" of the application. This is how Adobe Lightroom is implemented, as well as many games on platforms ranging from simple set-top-boxes to iOS devices and even PCs.

Writing C++ "Scripts"

I am a solo developer on a large C++ library that I use for research (I'm a PhD student). Let's say the library has a bunch of classes that implement cool algorithms: Algorithm1, Algorithm2, etc. I then write a bunch of C-style functions that are stand-alone "scripts" that use the library to either test the recently added functionality or to run simulations that produce plots that I then include in wonderfully-brilliant (I'm in denial) journal publications. The design of the library follows good software engineering principles (to the best of my knowledge and ability), but the "scripts" that link the library from main.cpp do not follow any principle except: "get the job done".
I now have over 300 such "scripts" in a single file (20,000+ lines of code). I have no problem with it, I remain very productive, and that's really the ultimate goal. But I wonder if this approach has major weaknesses that I just have learned to live with.
// File: main.cpp
#include <cool_library/algorithm1.h>
#include <cool_library/algorithm2.h>
...
#include <cool_library/algorithmn.h>
void script1() {
// do stuff that uses some of the cool library's algorithms and data structures
// but none of the other scriptX() functions
}
void script2() {
// do stuff that uses some of the included algorithms and data structures
}
...
// Main function where I comment in the *one* script I want to run.
int main() {
// script1();
// script2();
// script3();
...
script271();
return 0;
}
Edit 1: There are several goals that I have in this process:
Minimize the time it takes to start a new script function.
Make all old script functions available at my finger tips for search. So I can then copy and paste bits of those scripts into a new one. Remember this is NOT supposed to be good design for use by others.
I don't care about the compilation time of the script file because it compiles in under a second as it is now with the 20,000 lines of code.
I use Emacs as my "IDE" by the way, in Linux, using the Autoconf/Automake/Libtool process for building the library and the scripts.
Edit 2: Based on the suggestions, I'm starting to wonder if part of the way to increase productivity in this scenario is not to restructure the code, but to customize/extend the functionality of the IDE (Emacs in my case).
If I were you, I would split that huge file into 300 smaller ones: each would have just one scriptNN() and main() calling just it.
Now, when you have it compiled, you will have 300 small scriptNN executables (you may need to create appropriate Makefile for this though).
What's nice about this - now you can use these script executables as building blocks to be put or called by other scripts, like bash, python, perl, etc.
EDIT Explanation how this design allows to address your goals.
Time to start new script function - simply copy one of existing files and tweak it a little.
Make all old script functions available at my finger tips for search - emacs can do multi-file search across all other script files you have.
I don't care about the compilation time of the script file - it does not matter then. But you will have all of them available to you at once, without editing one big main() and recompiling.
Your example may be a good use case of scripting language. To be more specific, you could all your script* C++ functions glued to some interpreter, like Lua, Python, Ocaml, Guile etc... and have your test cases be written in the scripting language.
All scripting languages enable you to glue your C (hence also C++) functions.
For Lua, see its Lua API chapter. For Python, see its Extending & Embedding Python section. For Ocaml, see Interfacing C with OCaml section. For Guile, see Programming in C chapter.
You may wish to embed the interpreter inside your main function, or you could extend the existing interpreter with your new C++ functions (hence using some main provided by the interpreter).
Notice that using some scripting language may have a profound impact on the design and architecture of your library and software
If you are comfortable with it, and it works for you, just stick with it. You said you are the only developer, then just do whatever you want. I always spend too much time thinking about things like this for my projects :P. I've learned to just focus on the important and productive things. Theoretical things only work in theory...
All the suggested answers are good and you can even combine them. Just to add my 5 cents: your execution flow fits exactly into Strategy and Command design patterns. You may want to look at their benefits, but it's a question of benefit vs. investment.