In-game scripting system?
by Jacob Wagner · in Torque Game Builder · 02/17/2006 (1:12 am) · 11 replies
Hi. I am coding a robot programming game with torque 2d, and I've got to the point where I need to implement some kind of in-game scripting system so the player can program the robots.
Does anyone have an idea of how to accomplish this? I assume I would need to use some c++, so I am currently learning the language. After that I guess I will look at some open source scripting language projects.
Is there an easier way to do this in torquescript, even though I may not have all the functionality I need?(like checking the user's script code for errors). If so I'll continue programming in torquescript and add the c++ modifications later.
Does anyone have an idea of how to accomplish this? I assume I would need to use some c++, so I am currently learning the language. After that I guess I will look at some open source scripting language projects.
Is there an easier way to do this in torquescript, even though I may not have all the functionality I need?(like checking the user's script code for errors). If so I'll continue programming in torquescript and add the c++ modifications later.
#2
I guess if there was some way to limit what was being passed to exec that would work. I guess I could check the string that was being sent to exec and make sure it didnt call any functions other than the functions that that particular robot had available. I'll try that. If anyone else has any advice, thanks in advance.
02/17/2006 (3:11 am)
I could use that solution, but it would give the user too much power. I don't want them to be able to effectively reprogram the entire game, I just want them to be able to program the in-game robots. I guess these robots would have predefined functions to get them to interact with the world like 'moveForward()', grab(), etc, but the player would also need to be able to store variables and arrays and stuff, and create their own functions, etc.I guess if there was some way to limit what was being passed to exec that would work. I guess I could check the string that was being sent to exec and make sure it didnt call any functions other than the functions that that particular robot had available. I'll try that. If anyone else has any advice, thanks in advance.
#3
02/17/2006 (3:14 am)
@Jacob, there is also a variable passed into exec() that disables the ability to call engine functions. I havent used it before, but that's what it's for.
#4
I guess if there was some way to limit what was being passed to exec that would work. I guess I could check the string that was being sent to exec and make sure it didnt call any functions other than the functions that that particular robot had available. I'll try that. If anyone else has any advice, thanks in advance.
02/17/2006 (3:22 am)
I could use that solution, but it would give the user too much power. I don't want them to be able to effectively reprogram the entire game, I just want them to be able to program the in-game robots. I guess these robots would have predefined functions to get them to interact with the world like 'moveForward()', grab(), etc, but the player would also need to be able to store variables and arrays and stuff, and create their own functions, etc.I guess if there was some way to limit what was being passed to exec that would work. I guess I could check the string that was being sent to exec and make sure it didnt call any functions other than the functions that that particular robot had available. I'll try that. If anyone else has any advice, thanks in advance.
#5
02/17/2006 (3:23 am)
Sorry for the double post, i will look into the c++ source now to find that variable. Thanks for all the help
#6
It seems that the function eval() is what i need, not exec() (though I could be wrong)
If anyone can help me figure out what I need to pass to eval so that it disables the ability to call engine
functions please let me know. The relevant code seems to be here:
also the evaluate function seems to be defined here:
engine\source\console\console.cc
02/17/2006 (3:50 am)
Well, I'm not having much success figuring this out from the c++ source. It seems that the function eval() is what i need, not exec() (though I could be wrong)
If anyone can help me figure out what I need to pass to eval so that it disables the ability to call engine
functions please let me know. The relevant code seems to be here:
ConsoleFunction(eval, const char *, 2, 2, "eval(consoleString)")
{
argc;
return Con::evaluate(argv[1], false, NULL);
}also the evaluate function seems to be defined here:
engine\source\console\console.cc
const char *evaluate(const char* string, bool echo, const char *fileName)
{
if (echo)
Con::printf("%s%s", getVariable( "$Con::Prompt" ), string);
if(fileName)
fileName = StringTable->insert(fileName);
CodeBlock *newCodeBlock = new CodeBlock();
return newCodeBlock->compileExec(fileName, string, false, fileName ? -1 : 0);
}
#7
exec("t2d/gameScripts/script.cs", 1);
now I just have to figure out how to save a string to a file, which shouldn't take me too long to find out:)
There is also a 'journalScript' option to exec that I don't understand, but it seems pretty useful, if you do
a search for 'journalscript' on this site there is alink to a TGE only forum post, I'd sure like to know what the
rest of that post says :P It looks like it's something that allows you to record all function calls made or
something like that, sounds like it could be useful.
02/17/2006 (4:51 am)
I guess you were right about exec(), there is a nocalls boolean that can be called like this:exec("t2d/gameScripts/script.cs", 1);
now I just have to figure out how to save a string to a file, which shouldn't take me too long to find out:)
There is also a 'journalScript' option to exec that I don't understand, but it seems pretty useful, if you do
a search for 'journalscript' on this site there is alink to a TGE only forum post, I'd sure like to know what the
rest of that post says :P It looks like it's something that allows you to record all function calls made or
something like that, sounds like it could be useful.
#8
02/17/2006 (10:45 pm)
Check out the strategy tutorial, in it, an action function is created, which accepts actions that you define in script, you could then allow the user to use these actions by creating some type of drop down list that adds them in, and the robots follow the actions. I'm using something similar to this idea for building enemy behavior in a level editor using pre-defined actions that all enemies have access to.
#9
or, go checkout whatever tutorial EzraHW is mentioning :)
02/18/2006 (12:50 am)
@Jacob: instead of saving the string to file, make a copy of the exec function, and in your copy instead pass in your string to execute as an input parameter.or, go checkout whatever tutorial EzraHW is mentioning :)
#10
I'm not sure exactly how what EzraHW is mentioning works, but I assume it won't because I have particular needs: I need the player to be able to write in a program, but ONLY functions from the robot scriptobject he is programming would be allowed to be called when that program is executed.
However, I have a solution in mind: I'll go through the program code looking for "()", and then append a "robot1." in front of it (or whichever particular robot is being programmed. That way, if the player tried to call a console function, it would not work cuz it would come out as robot1.consoleFunction(), and if he just typed something like "rotate()", it would add "robot1.rotate()" to the code so i could send it to exec.
The only thing I am worried about is the user will be able to change global variables, so I guess I'll either have to have a weird naming system for my globals, or stop using them.
02/19/2006 (7:44 am)
Actually the exec method didn't work out exactly like I hoped, it seems if you pass the noCalls flag to exec then no function calls will be allowed at all, (whereas i thought it would only block console function calls)I'm not sure exactly how what EzraHW is mentioning works, but I assume it won't because I have particular needs: I need the player to be able to write in a program, but ONLY functions from the robot scriptobject he is programming would be allowed to be called when that program is executed.
However, I have a solution in mind: I'll go through the program code looking for "()", and then append a "robot1." in front of it (or whichever particular robot is being programmed. That way, if the player tried to call a console function, it would not work cuz it would come out as robot1.consoleFunction(), and if he just typed something like "rotate()", it would add "robot1.rotate()" to the code so i could send it to exec.
The only thing I am worried about is the user will be able to change global variables, so I guess I'll either have to have a weird naming system for my globals, or stop using them.
#11
So I was thinking you could make an Action funtion, which acts as a filter for the gui text box, basically when the user clicks the button to submit his code, it would look for the .action functions (or any others, like .var() .logic() .math() etc), and the action function would decide if it is a valid action inside the quotes and then fire off the proper t2d function (or any custom functions you made) on the robot currently selected when the button was pressed.
This way the user only uses action() and just supplies a type of action and variables for it, you could even make it a drop-down list which can fill in the action() function with default variables and stuff.
02/23/2006 (1:25 am)
I might be a bit confused with what you're doing, but in the strategy tutorial there was a section about creating scripted actions/behaviors, and it resulted in being able to do stuff like this: robot1.action("rotate",180);So I was thinking you could make an Action funtion, which acts as a filter for the gui text box, basically when the user clicks the button to submit his code, it would look for the .action functions (or any others, like .var() .logic() .math() etc), and the action function would decide if it is a valid action inside the quotes and then fire off the proper t2d function (or any custom functions you made) on the robot currently selected when the button was pressed.
This way the user only uses action() and just supplies a type of action and variables for it, you could even make it a drop-down list which can fill in the action() function with default variables and stuff.
Torque Owner Jason Swearingen
i am not a torquescript user in general, so what i'm telling you is very rough psudocode, you will have to figure out the exact calls yourself.
1) allow user input into some gui text box.
2a) have your game take the input, and pass it to the exec() function
2b) note: i dont think it's the exec function, but the function inside exec() that recieves the contents of a '.cs' file.. you'll have to look at the c++ code, but it's pretty obvious if you step through a debugger.
that's it! sorry i cant be more percise.. i know 100% sure that this route works, because i did something like this for my own purposes. There may be a better way, if that's true i hope someone else will post info.
and sorry i dont give you the exact info... all my code is on some backup harddrives right now in "long term storage" :)
-Jason