Thread: Reviving my old scripting language.

  1. #1
    Registered User
    Join Date
    Jan 2005
    Posts
    106

    Reviving my old scripting language.

    This probably won't make any sense. It's 4 AM, the day after graduation, I'm dehydrated, and I'm a bit out of it. Still, here it goes.

    Okay, this was something I was doing back in January. Wanted to devise a simple scripting language of my own because A) I was bored. B) I'm too autistic for LUA. C) I'm allergic to good ideas. Anyway, I worked on it for a bit and I got something that was sort of workable, although I didn't really have the interpretor set up to handle if statements sanely (or at all). Likewise, the only data types I had were strings and classless objects, so actually dealing with stuff is bizarre. Still, mostly a proof-of-concept thing, and at that I believe I succeeded admirably.

    OKay, so I figure that, as is, I can simply re-use a lot of the data manipulation stuff I wrote for the express purpose of reusing when I inevitably rewrote the thing (the functions I'm reusing are mostly tokenization functions and search functions. Nothing big), and then rewrite the interpretor itself (which is rather simple -- it's basically just external function calls. I'm not doing anything really elaborate or cool here). The only problem with this is that all of the object-oriented stuff still has to be handled in the C++ code. I want to at least design the scripting language to have some degree of its own object-oriented... stuff (primarily, because it's completely happy with completely maleable, classless objects. C++ obviously isn't. This sort of ... well, amorphousness seems useful for writing text adventure parsers and language bots). Anyway, while I guess an ultimate goal would be able to write a complete game in this system, that'd be incredibly dumb and I wouldn't do it.

    One of the test games people use to show-off their system's capabilities is this short text adventure called The Cloak of Darkness. when trying to write that in my scripting language, I noticed something I needed -- a better way of handling state control for objects (well, also some sort of set math, but that's not really hard to do). Specifically, in the game, you have a cloak. It can either be worn, in the players inventory, or on the coat hook. Worn is the initial state. Inventory is the state it needs to be in to either wear it or hang it up. Being hung up is the state it needs to be in to make this room not be dark (hence the name). One way to handle this, of course, is just with a lot of if statements. if cloak is in the inventory, and if player selects "wear,"etc etc. This, of course, is rather clunky. A more desirable method would be to have some sort of "reaction" code in certain objects that would, at some interval, check object A's 'state,' and update/alter some value, variable, or piece of code in object B.

    For example, if the cloak's state became 'worn,' if there's a function member in the cloack object that handles what happens when you try to wear it, normally I'd just have three or so if statements to figure out what state the cloak was in and then what do. I'd rather have it automatically... somehow, like, "switch" which member gets called whenever the state changes. I'd also rather have something inside the object so I have less loopy procedural coding stuff to deal with. If I have it automated and within the object, I can write THAT bit in C++. Just wondering if you guys had any thoughts on existing implementations or other ways to handle this.

    One thing I noticed is that, given how I'm setting the language up to work, I can very easily make it so object members can be accessed by, er...well, you can store the name of whatever member you want to access in a variable, and then just pass in the variable for the member-access-code. Same thing works with function calls. In this case, if there were, say, three member which were basically just function calls, I could potentially just have a state-change-reaction thing change some variable, and simply call that variable instead of an actual member.

    It's also worth mentioning that I've only written C++ stuff to interpret the scripts. Beyond this, I've yet to do any more direct interaction, which, if I'm going to be embedding these instead of just writing a discrete interpretor, would probably be a good idea.

  2. #2
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    The scripting language that Shakti and I devised is completely message-based. Variables are handled through specific functions which operate on variables or variable slot's - AKA elements in an array.

    Messages are then sent to the target object ID's ScriptProc function. The message is then handled (or not handled) by the object. The engine also has a ScriptProc function where it can respond to specific messages as well.

    The goal was to make the game completely controllable and modifiable from the script. It also supports user commands through set macros we've come up with. Overall it's very powerful but definitely not up to par with a major scripting language.

    Script->Script processor->Object->Action
    Script->Script processor->Engine->Action
    Script->Script processor->GUI->Action

    There are a few more details involved in order to get everyone working on the same page but overall it's quite simple.

    Everyone one of our script commands utilizes this structure:

    Code:
    struct ScriptFunc
    {
      DWORD dwMessage;
      DWORD dwParam1;
      DWORD dwParam2;
      DWORD dwParam3;
    }
    • dwMessage is the message ID
    • dwParam1 is the first param, usually the object being acted on
    • dwParam2 is the second param, usually the target object of the command (IE: aIDAttack (1,2) - object 1 attacks object 2
    • dwParam3 is the third param and it is rarely, if ever, used in our system. When used it usually acts as a modifier for the messageID. Say you wanted object 1 to move to object 2 at a speed of 4: aIDMoveToAtSpd(1,2,4)


    A simple script to make object 1 attack object 2 until it is dead.

    Code:
    //Check if object 2 is dead, if true, set variable 1 to 1
    if (aIDIsDead(2))
      aVarSET(1,1)
    endif
    
    //If variable 1 is 0, we know object 2 is still alive so attack it
    if (aVarEQ(1,0))
       //1 out of 100 times we will attack with special move 5
       if (Random(100))
          aIDAttackWithMove(1,2,5)
       else
          aIDAttack(1,2)
       endif
    endif
    There several ways to accomplish this in our script but I showed what I think is the easiest.

    User commands are added like this:
    Code:
    USER_COMMAND3 "uAttackObjectWith" 
      //Param1 - object 
      //Param2 - target
      //Param3 - weapon
    
      //Check if object doing action is alive, if target is alive, and
      //if action object even has the weapon
      if (aIDIsAlive(PARAM1) AND aIDIsAlive(PARAM2) AND 
          aIDHasWeapon(PARAM1,PARAM3))
      
          aIDAttackUsing(PARAM2,PARAM3))
      endif
    END_USER_COMMAND3
    
    //Object 1 attack object 2 with weapon 20
    
    if (Random(500))
     uAttackObjectWith(1,2,20)
    endif
    Params are determined by how the user passes them to the function. We cannot test to see whether the user is using their command correctly, but we can provide a mechanism so they can build up complicated commands and then execute them with one line of script. The number following the macros is an indicator the script how many params it requires. All standard script commands start with "a" and all user commands start with "u"

    Interesting to see how you approached your script. I'd like to see some samples of it.
    Last edited by VirtualAce; 06-06-2006 at 06:10 AM.

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    106
    "The scripting language that Shakti and I devised is completely message-based."

    That's mostly implementation. I was talking more about design.

    Anyway, I just had another bizarre idea. Instead of having embedded if statements within the code itsef, the more complex branches would... well, have their own sort of class. It'd e

    uh...

    I forgot what that e was going to do.

    Anyway, it would be sort of like those multi-step leaf identifcation charts. "If the leaf is red, go to 2. If the leaf is blue, do X and break."

    I'm not really sure why I thought this was a good idea, other than that I could potentially have generic branch objects, I guess. Effectively, it'd be like an intelligent switch statement. I dunno. Wouldn't be hard to make, at least. Would get me out of having to write genuinely meaningful code for handling jumps and gotos in the script XD So yeah, might play around with this. Leave it if it's cool. Kill it if it sucks.

  4. #4
    Registered User
    Join Date
    Jan 2005
    Posts
    106
    Also, bubba, I can't really remember if I asked you this or not, but when your interpretor program read scripts, how/where did you store the scripts? I think I mentioned this before, but as far as mine goes, the idea is just to load in all of the script-files (they're listed in an includ d file, right now), and then split the commands/member names off from their parameters, and just store them in two vectors with a 1:1 correlation. After that, it basically just sends commands and a related vector contain that commands arguments to a seperate function and past that point it's not too different conceptually from a messanging system.

    This works fine but it's just really bloody tedious (not hard. Not terribly long either. Just very. very. boring.) to write and I'm wondering if there's a faster/easier method for storing/reading from script files? Then again, I was working on a text-adventure engine, where reading in the scripts completely before hand would be more beneficial. I'm also considering working on a top-down, graphical RPG (Read: I need to re-learn how to make a tiling engine AND something that scrolls. Also a spriting engine, which sounds easy but ALSO very tedious), though, which will probably contain substantially smaller scripts (and more of them), so odds are those wont all be loaded in at once.

    (Obviously writing a compiler or partial-compiler for the scripts would probably make it a lot easier to read them in the program and would allow me to have a more elegant syntax, but as I said, I don't really want to write a compiler for these things).

  5. #5
    Registered User
    Join Date
    Aug 2003
    Posts
    1,218
    The way the script does it is this:
    Read in what functioncall is being made on the line. Read in the arguments to that functioncall (can be none, can be variables and static values). These arguments are stored in a vector, and the functioncall is stored in a std::string. After that I call a function that gives a messageid (DWORD) given the functionname. Then I call another function that takes the argumentsvector as argument and at the same time fills some pointers that will point to the actua memory-location where those variables/static values are stored. Last i store all this info in another structure and push it back to a vector.

    That is all done at loadtime, at run time i just iterate through the final vector, calling the messageproc for each index in the vector and I have instant access to the variables and stuff in question since I just do a pointer-lookup.
    STL Util a small headers-only library with various utility functions. Mainly for fun but feedback is welcome.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. What's the Difference Between a Programming Language and a Scripting Language?
    By Krak in forum A Brief History of Cprogramming.com
    Replies: 23
    Last Post: 07-15-2005, 04:46 PM
  2. Strange loop
    By D@rk_force in forum C++ Programming
    Replies: 22
    Last Post: 12-18-2004, 02:40 PM
  3. C Language And A Scripting Language
    By DarkSpy in forum C Programming
    Replies: 9
    Last Post: 06-26-2003, 08:05 AM
  4. How would I go about making a scripting language...
    By gcn_zelda in forum C++ Programming
    Replies: 1
    Last Post: 06-19-2003, 11:43 AM
  5. Creating my own Scripting language in C++ for CGI
    By stovellpaul in forum C Programming
    Replies: 0
    Last Post: 10-01-2002, 03:41 AM