Sean Middleditch » 2004 » July
I really don’t like Scriptix. The design sucks, the API sucks, the language sucks. Pretty much all around, it sucks.
I’ve been contemplating dumping Scriptix in AweMUD for an alternative for some time now. The two big choices, as I see it, are Mono and Lua. Mono is a very powerful framework; we’d get JITd scripts, multiple languages, a very complete standard library, and Boehm GC compatibility. However, Mono has a couple problems; it’s very big and complex, might not keep that Boehm GC compatibility for much longer, and could be a security problem without some of the Mono 1.2/2.0 planned features (sandboxing stuff, mostly).
Lua is a beautiful framework. The API is beautiful, the language is elegant, and the runtime is very lite and fairly quick. Truth be told, for anyone looking for an embedded scripting language, I’d have to call you an idiot for using anything other than Lua these days without having a very good reason. Unfortunately, I think I have a couple good reasons. First, it has no compatibility with the Boehm GC; it implements its own. It’s a C API that requires a lot of wrapping to be used by C++. It’s quick, but not super fast, being a very dynamic language. And the syntax, while great for developers, leaves a little to be desired for mere mortals. If AweMUD were a fresh project designed with Lua in mind from the start, it would be a no brainer, but I need something that’ll easily and painlessly slide in where Scriptix currently is.
So, what is the answer? Scriptix2.
Yes, that’s right. Idiot me has started *another* project, yet another scripting language.
This one, however, fucking rocks.
I’m using the Lemon parser generator and a very simple but quite speedy and usable custom tokenizer. The language syntax is somewhat BASIC-ish; no curly brackets, no semi-colons, and using a lot of English keywords. I’m only really so far as having some of the grammar down and having the basic tree analyzer in place, but it’s coming along quite nicely.
The planned features include static typing, a unique OO syntax, high performance (much better than current Scriptix, which itself is usually much better than Python, Lua, or Perl), easy to read syntax, a full set of user-oriented language features designed for embedded languages, lots of error detection and warnings, and a very, very easy to use API.
Syntax looks something like:
begin main ()
int x := 1
int y := x ** 2
if x < y then
print "hi"
end
end
Not too wild or anything. Like current Scriptix, you'll be able to declare functions as public, and also be able to declare global variables public. There will _not_ be the capability to create custom types inside a script; I just don't personally see the point, in most cases you can do without.
The big thing that's fairly different between Scriptix2 and Scriptix (and C++/Java/C#/etc.) is the OO model. Technically speaking, everything is an object, although internally ints, float, strings, arrays, bools, and any other core data types I come up with will all be special cased. The way OO works is entirely with global functions and overloading.
For example, say you have an object and you want a method to get the object's name. In Scriptix now, you'd do something like:
name = object.get_name();
object.set_name("foo");
In Scriptix2, however, we don’t have the method syntax. We do, however, have over-loaded global functions. So you can just make a function called name() that takes a single Object as an argument and returns a string. Make another that takes an Entity and returns the name. etc. So you have:
string name1 = name(object)
string name2 = name(other)
Now, when you want to set the name of an object, we could do one of three things. First, we could make a set_name() function for each object type. Second, we just call it name(), but make it take two arguments - the object and the new name. Scriptix2 solution, however, is to make a new kind of function call; an assignment call. Basically, just assign to the function call; a special function name is looked up (basically the given name with a = appended) and the expr used in the assignment is passed in as the additional args.
So you’d have a function definiton (declared in C++ code most likely) like so: string name=(Object, string)
You’d call it like this:
name(object) = "new name"
speed(bus) = 45
I read it as “name of object is ‘new name’” or “speed of bus is 45″. It feels a lot clearer to me than the object.method(value) syntax, which doesn’t read very well. I also think the new syntax is a lot easier to grasp. If the expression “name(object)” results in the object’s name, assigning to it should change the name, right? Just Makes Sense(tm).
Because the language is statically typed, I’m hoping the API to be a lot easier. You’ll be able to push _any_ object into the engine; the only real limitation will be that if you want to have the object’s memory managed, it better be allocated in Boehm GC managed heap. There will still be a necessary glue layer, althogh it _would_ be possible to hack in something like libffi to make the script function calls directly invoke C functions and C++ methods. The glue layer should be quite easy, however, since the values will be native C types packed into a chunk of memory; the glue generator can just make magic structs for each functions return types and argument lists. The glue code might look something like:
//
// Function foo()
// Arguments: string name, int value
// Returns: Object, bool
struct _do_foo_args { char* name; int value; };
struct _do_foo_return { Object* ret1; bool ret2; }
#define return(ret1val,ret2val) do{ _return.ret1 = (ret1val); _return.ret2 = (ret2val); }while(false)
void
_do_foo (_do_foo_args& arg, _do_foo_return& _return) {
//
#line 23
do_something_with(arg.name);
do_somethign_with(arg.value);
return(get_object(), true);
//
}
#undef return
//
That isn’t exactly how it’d look; mainly, the datatypes for args and return values will all have to be 32 bits (or 64 bits and 64-bit platforms) so that they align properly and can just be copied into and out of the stack.
Another big change over current Scriptix is how I plan on handling the compilation model. Currently in AweMUD we have this silly sorting hack for scripts to ensure one gets loaded before another to handle resolution of public functions and such. And even then we don’t allow two scripts to refer to functions in each other. With Scriptix2, the compiler will allow you to load multiple source files in. As each is loaded, the file is read and parsed, but the compiler goes no further than that. Then, once you’ve loaded all the files you want, you tell the compiler to go through the compilation stage. Thus, it has access to all the functions and whatnot in all source files at once, so there is no “dependency” resolution step that the developer has to handle. Just load up all the scripts in your scripts/ folder at once and let the compiler do the rest.
One thing that Scriptix has weak support for now but Scriptix2 will have from the start is a permission system. Basically, each source file can have access bits set, which are then compiled into each function defined in that source file. Additionally, whenever the application invokes a script, it may specify a set of access bits. As the engine runs, it keeps the set of current access bits. Initially this will be those specified by the application when it invoked the script. Each function that is called, however, will have its bits bitwise-and’d with the current bits. Functions can limit the current bits, but not increase them.
With this, say you have some script source from a potentially dangerous place. Say, you game allows servers to send mods to clients. You want your local scripts to have file access and such, since its needed for the game to work, but not the untrusted remote scripts. As you read the scripts from the mod, you compile them without the file access bit. Now, your application invokes a script in response to an event. It has no idea if its a local script or one over-rided by the remote server, so it just grants all access bits during the invocation. Run the script is invoked, however, the access bits not given during compilation are dropped (due to the bitwise and operation), preventing the script from doing anything malicious. The script can’t even take advantage of a buggy local script; even tho the local script was compiled with access bit for file access, if its invoked by the remote script it will not be able to _add_ the file access bits; they’re already gone since the code path when through the remote script.
The work on Scriptix2 isn’t going as fast as it could be, as I’m still working on the game ruleset and other AweMUD stuff. The fact that I’m so far along with Scriptix2 already given that lack of time, however, proves how clean and simple the design is. The vast majority of my time, in fact, was spent on learning how to use Lemon; not that that’s out of the way, the code stuff should be easy to finish off in a couple weeks.
The lack of PDF printing support in Windows or its applications has resulted in need for a bit of a hack. Basically, what we’ve had to do, is create another pseudo-printer on one of the (increasingly overloaded) Linux servers. The printer “filter” gets the job, extracts the user, job title, and postscript document, uses ps2pdf to convert the document to PDF, and mails the PDF back to the user.
Incredibly simple to setup on the server, but it’s a complete pain that this kind of crap is necessary. Even if Windows apps don’t have a built-in Export to PDF feature (hi OpenOffice.org!), the Windows printing subsystem should bloody well have it built-in (hi gnome-print!).
Seems the 0.22 release of AweMUD did manage to have a few bugs, including a crasher. ::sigh:: Still debating whether I should roll a 0.22b release or not. I wanted to have a rock solid release. 0.22 is a lot better than some previous releases, but it’s not perfect, and I rather like perfection, myself. ;-)
Either way, 0.23 might be a longish release cycle. The things I want to get done with the 0.23 release are things that will take a lot of time and effort to get right, which doesn’t help release cycle lengths at all.
One thing is the body description system, so that we can have varied body types (humanoid, centaur, etc.) and, eventually, body part damage tracking. Also with this comes the possibility of more intricate equipment usage, like arm bracers that only go on one arm instead of both, so player characters can have a less symmetrical appearance. (A lot of anime outfits tend to be asymmetrical, and look pretty sharp, so it seems like a good thing to support in a MUD.)
Another thing is character creation in C++. It’s currently in Scriptix, which isn’t that bad, but… Scriptix really isn’t a full scal programming language. It’s a scripting language. And not even the best around, because it tries too hard to look and act like C++/Java, which -are- full scale programming language. JavaScript would probably have been a better language to use than Scriptix. Still possible to fix Scriptix, but it would take a lot of effort, and iin the end, it’s probably better to just replace Scriptix than put that much more effort into trying to get it to work ideally.
Yet another thing on the list of stuff to is the pending action system. Basically, right now, each action (command) immediately calls a function to carry out its task, and then set a round time on the character. The round time just serves as a way to state that the character is “busy” and cannot take any action for a few seconds. This system has some flaws, though.
First, the action completes immediately, and then the wait begins. For a long action, like removing armor, the armor shouldn’t immediately be removed. The armor should be slowly removed over the time period. Among other things, the descriptive messages should look a little more realistic, and the character’s defense should slowly drop as more and more pieces of the armor are removed.
Second, the current system makes it impossible to have a queue of actions or actions that automatically repeat. Say combat. You want to auto-attack as quickly as possible. but you want to intersperse the auto-attacks with other commands without stopping the auto-attacks. As is now, any commands you type would be denied because you have round time, and as soon as the round time is up you’d auto-attack again. With a pending action system, you’d just queue up the actions. So if there are no more actions on the queue, the attack would fire again. Otherwise, it would process the other commands, and then when those are done the attack command would re-fire.
I’ve been working on a custom table-top RPG rule set. Mainly, I’m rather dissatisified with Dungeons and Dragons - the rules just don’t work that well, are still too complex, the power levels are completely unbalanced and unmanageable… it’s just not that much fun to me anymore.
My new system is code named B&L - Basements and Lizards. ;-) One design goal of the new rules is to make them fairly easily adaptable to a computer system, so we’ll have a system finally to use in AweMUD. Which will be most good.
Also been looking over BESM d20 (Anime hack on the D&D rules), which are rather interesting. Still looks like there will be massive power balancing problems, but then, anime tends to be like that. ^_^
Had a lot of reunions lately. My awesomely nifty friend from Seattle is back in town. I took her out to KANAR last weekend, and she’s attending the August 6th weekend game as well. I haven’t seen her in 7 months; I honestly can’t describe how much I’ve missed her or how glad I am she’s around for the next month. I only wish she wasn’t just going to leave again. :(
Also saw a couple of other friends I haven’t seen in ages. We had dinner, talked through a potion of the night, caught up on old times. Definitely cool people, shame they’re not around more often either.
Finally, I ran into my last ex. We haven’t really spoken in some 2 years, but for some reason after we saw each other last week she decided it’s time to start talking to me again. Must be my good looks. ;-) I’m still rather not too sure about this, we really did have a pretty bad breakup (entirely my fault, I will freely admit), but ah well.
In any event, I’ve seen more old friends this week than I’ve seen in the last two years.
Got x-rays of the lower back. Spine is in great condition; better than the average person. Yay!
Bones in the hip area (I forget the names of the exact bones; S-something-er-other) are rather crooked, which could be causing the pain in they’re pinching anything. Also a high liklihood of sprained back muscles, since not much else could explain the pain. After work on the lower back, I feel a lot better, but still pretty sore - further evidence that it’s a muscle problem and not a bone/nerve problem.
Chiropractor also took some x-rays of my neck (my usual problem area), so he has a more up-to-date idea of what work needs to be done there, and started away. Neck already feels a lot better.
As Robert Love was saying, roberts would not indeed have extra-sensory information over-laid onto their visual display for processing. They’d just “know.” As humans would do with other senses.
I think that, however, the problem isn’t that the movie producers or viewers have that hard of a time realizing that the robot wouldn’t see the information, as Mr. Love points out. Instead, it’s just visualization intended for the viewers themselves. Seeing the Terminator’s physique comparisons when looking for a new set of clothes isn’t meant to imply that that is how the Terminator receives that information to his AI, but is instead meant to display to the viewers what capabilities the Terminator has.
Without showing these features visually (or auditorily), the viewers wouldn’t even think of it. They mightn’t realize why the Terminator ignores some targets and goes for others on his third time through the bar in the buff, looking for clothes, unless the movie shows them that he is looking for a match in terms of physical build.
This is similar to how in a lot of action movies, the bad guy always spills the plot. It’s not because the bad guy is dumb. It’s not because the hero is incapable of fulfilling his role without hearing the plot spilt. It’s simply so that the information can get back to the viewer with as little break in suspension of disbelief as possible.
Another example of how nonsense is required for viewers are stages in plays. Notice how the audience always has the best viewpoint on the action? How everything seems to unfold in a fairly two dimensional fashion? The stage can’t move around to give you different view points on the fly, like cameras in a movie can. So the stage, actors, and props are laid out in a fairly “stupid” way (in terms of how we would do things in reality) merely because of the presence of the viewers.
I’ve managed to slaughter my lower back. Combination of the 10-day KANAR event and 30 minutes on a brand new jetski have resulted in my being in near-constant pain. Yay me!
Hopefully this isn’t anything permanent. Knowing my luck I’ve shattered a disc or something else that’s completely unfixable. :(
For anyone who’s wondering why I haven’t been doing anything useful with AweMUD or whatnot, this is why. I’ve been doing a lot of laying around, reading, and playing games.