Advertisement

Developing the ideal scripting language feature set

Started by May 16, 2004 06:23 AM
37 comments, last by Ravyne 20 years, 5 months ago
quote: Original post by Jotaf
Ok... If lisp is so great, I think you should tell us what''s so good about it (no I''m not being sarcastic) The topic of this thread is "what makes a good scripting language" after all!

Well, ''lisp'' is a little vague.

In general, the primary feature all LISPs have is the ability to treat data as code, and vice versa. This, in turn, leads to the ability to construct domain-specific ''sublanguages'', which can be used interchangeably.

(transform input-stream output-stream  (identifier ((/[A-Za-z0-9_]+/)))  (expression    ((identifier)     (get symbol-table identifier))    ((expression "." identifier)     (select val from fields where (and (== obj $1)                                        (== name $3))))    ((expression "+" expression))     (+ $1 $3)))) 


This little example shows part of a parser for a C-style interpreted language. The parser, which is not a builtin LISP feature, directly contains code that performs the interpretation, and an SQL select expression which itself contains LISP code for checking the field values.
quote:
Ok. So you can say that there''s a "longsword" class, and you can create an instance of that class that has all the default behaviour. Then you can add different functions to it so it becomes a "poisoned longsword". This is really simple and straightforward to implement and use. What aspects of OOP would be useful for a structure like this?

An obvious solution is multiple inheritance. However, that has two drawbacks. Firstly, since MI is the evil de jour in OOP theory, I''d get lynched by the code purity mob. Secondly, and notably more importantly, it''s effectively impossible to scale a naïve MI solution to a weapon which inflicts more than N status effects.

class weapon (inventory) {  def base_damage = 0;  def last_damage;  def deal_damage (victim, bonus, multiplier) {    last_damage = base_damage * multiplier + bonus;    victim.hp -= last_damage;  }};modifier poisoned (weapon) {  // after the method is called,  after deal_damage (victim, ...) {    // if the victim fails a fortitude check,    if (!victim.fortitudeCheck(18)) {      // apply the poisoned status to the victim.      victim.status |= Status.POISONED;    }  }};modifier vampiric (weapon) {  after deal_damage(victim, ...) {    this.owner.hp += last_damage;  }}class longsword (weapon) {  def icon = ''icons/weapons/longsword'';  // Special syntax for dice rolls.  def base_damage = 2d6;}; 


With this code, you could do poisoned longsword, vampiric longsword, or, without any extra coding, a vampiric poisoned longsword.
CoV
Hmm so I guess my system already supports that

I'll explain its structure in detail:

object_class { //Like the weapon type "longsword"  script* default_behaviour[] //The default scripts}object_instance { //Like a specific longsword in the game  object_class* base_class //This object is of type "longsword"  var* variables //Variables specific to the default behaviour:    //damage, condition, could also be hit points for a character  buff* attached_buffs[] //See below}buff_class { //Commonly known in games as a "buff", this is like    //the condition type "poisoned" or "vampiric"  script* scripts[] //Behaviour specific to this buff type}buff_instance { //The specific "poisoned" instance attached to a    //sword for example; this can be seen as the "poison" object    //inside the sword  var* variables //Variables specific to an instance: recharge    //time, strenght (like if you put more poison in a weapon)...}


I can't see nothing wrong with it... it supports everything you can throw at it. Beat this ;p (don't take me wrong I really wanna see this critiqued =)

[edited by - Jotaf on May 27, 2004 12:01:19 PM]
Advertisement
quote: Original post by Jotaf
Hmm so I guess my system already supports that

I''ll explain its structure in detail:

object_class { //Like the weapon type "longsword"  script* default_behaviour[] //The default scripts}object_instance { //Like a specific longsword in the game  object_class* base_class //This object is of type "longsword"  var* variables //Variables specific to the default behaviour:    //damage, condition, could also be hit points for a character  buff* attached_buffs[] //See below}buff_class { //Commonly known in games as a "buff", this is like    //the condition type "poisoned" or "vampiric"  script* scripts[] //Behaviour specific to this buff type}buff_instance { //The specific "poisoned" instance attached to a    //sword for example; this can be seen as the "poison" object    //inside the sword  var* variables //Variables specific to an instance: recharge    //time, strenght (like if you put more poison in a weapon)...}


I can''t see nothing wrong with it... it supports everything you can throw at it. Beat this ;p (don''t take me wrong I really wanna see this critiqued =)

Firstly, a snippet of code for actually associating a ''buff'' with a special instance would be handy.

Secondly, whilst my example works on any class, your example requires that the class which it to have a modifier attached to it is planned with modifiers in mind. Effectively, you need to put ''buff* attached_buffs[]'' in almost every class, just to be sure. And if you need to put it in almost every class, I figure it might as well be put in automatically by the compiler.

Thirdly, I don''t like your inheritance by composition.

Fourthly, I don''t know the ''buffs'' are activated. Does the ''base class'' have to explicitly activate all interested buffs when something interesting happens to it? My version automatically triggers the modifiers.

In short, it seems to me that my version allows modifiers to be attached to a class without that class having to be designed for modifiers in the first place, or being editted to include modifer support. I think that is superior because it keeps unneccesary complexity out of classes, and encourages class stability by not requiring you to edit already made classes.
CoV
I don''t like your arrogance. It makes me think that you''re just another OOP-nazi who likes to brag about how he knows all of the latest buzzwords. Frankly I don''t like to waste my time with people like this. Just for your information, "your" version adds nothing to what I already have. It''s absolutely worthless to make statements like "I just don''t like your whatever" and making assumptions about parts of the system that you don''t know about.
Ohh, don''t start Yet Another "my stuff is better than yours" flamewar.
--Slashstone - www.slashstone.comNerveBreak free scripting system.
quote: Original post by Jotaf
I don''t like your arrogance.

I apologise for having offended you. But, with respect, don''t ask for critiques if you aren''t prepared to get negative responses.
quote:
It makes me think that you''re just another OOP-nazi who likes to brag about how he knows all of the latest buzzwords.

Which would be wrong.

I''m happy not to use OOP when it''s appropriate not to use OOP. I just happen to believe that OOP is almost always the most appropriate paradigm to use to describe the data model of a game.
quote:
Frankly I don''t like to waste my time with people like this.

That''s your choice.
quote:
Just for your information, "your" version adds nothing to what I already have.

That seems arrogant to me. I only said I preferred my solution, and I thought it was superior.

And, just for your information, I disagree. I believe my "classful" version offers more flexibility and extensibility than your "classless" version, when comparing equal times programming it.

However, as I said in my post, I don''t know details of your system. It looks like you must be explicit about everything in your version, whilst my version does a lot of things implicitly.

Instead of snapping out at me because I hurt your feelings, it would do you well to explain what I had wrong about your version.
quote:
It''s absolutely worthless to make statements like "I just don''t like your whatever"

Unless you ask me why I don''t like it.

I prefer explicit inheritance to composition. I think that explicit inheritance almost always makes things easier to understand and code.

For example, it is unclear to me if the base_class member of object_instance is automatically searched for members.

If there is something magical about base_class that means it is, then that''s okay, although not ideal since you then can''t use the name base_class for any other purpose.

On the other hand, if object_instance would have to manually ''pass on'' messages that it doesn''t understand to the base class, then I can''t think that''s ever okay.
quote:
and making assumptions about parts of the system that you don''t know about.

And if you correct my assumptions, I''ll be happy to recant my conclusions drawn from faulty premises.
CoV
Advertisement
Honestly, I know this sounds absolutely insane, but I think moving away from scripting language altogether is the best approach. I mean, most of the stuff being done in teh scripting language is just "this event calls that event handle on that object with these parameters" which is really just wiring shit together, or "I''m defining this class, based on that class, but with these new parameters".

Unless you''re making a super-general-purpose engine like Unreal, an intelligently generalised non-scripted structure could be extraordinarily powerful. Consider how much strange stuff could be done with Doom hacking tools like DeHackEd, which only set flags and rearranged the frame order.

Alternately, there''s the modern approach seen in LabView and VirTools of using wired boxes as a programming structure. Variables become temporary paths from one logical block to the next, and threading becomes second nature to the language.

But of course, I love Python. Its slow, and the "batteries included" mentality means that any gamedev basing on it needs to tear out piles upon piles of hazardous OS bindings and built-in modules, but its a wonderful language for embedding. Defining new objects in C and exposing them in Python is a joyous process.

The only real caveat with a scripting language is this: if you ever write any kind of "do this as often as possible" or polling functions in the scripting language, then you''ve screwed up your architecture and should just write in C.

In short the best "feature" of a scripting language would be avoiding using it.

That, and being a stripped down version of Python with slightly more sensible syntax. Oh, and closures rule.
-- Single player is masturbation.
quote: Original post by Pxtl
Unless you''re making a super-general-purpose engine like Unreal, an intelligently generalised non-scripted structure could be extraordinarily powerful. Consider how much strange stuff could be done with Doom hacking tools like DeHackEd, which only set flags and rearranged the frame order.

Well, you get that just editing a configuration file. I don''t think that''s scripting, per se.
quote:
Alternately, there''s the modern approach seen in LabView and VirTools of using wired boxes as a programming structure. Variables become temporary paths from one logical block to the next, and threading becomes second nature to the language.

The problem with graphical programming ''languages'' is that people cannot use whatever development environment they want to edit it. Whilst with text programming languages, they can. For example, I use Visual Studio for editing Unreal scripts.

I note that VirTools includes a scripting language.

Information about how VirTools actually works appears to be scarse. LabView is a little more open about it, and it reminds me somewhat of the "aRts Builder", a KDE program for graphically building synthesizer effects from modules written in C++.
quote:
But of course, I love Python. Its slow, and the "batteries included" mentality means that any gamedev basing on it needs to tear out piles upon piles of hazardous OS bindings and built-in modules, but its a wonderful language for embedding. Defining new objects in C and exposing them in Python is a joyous process.

You''re an odd chap. I''d prefer to define an object in standard C++, compile it into a library, and then load it in Python. The difference being that I don''t want to have to infect my C++ program with logic for interacting with Python. That should be handled with a seperate adapter that somebody else writes. This makes things a lot easier if I want to change to another scripting language later.
quote:
The only real caveat with a scripting language is this: if you ever write any kind of "do this as often as possible" or polling functions in the scripting language, then you''ve screwed up your architecture and should just write in C.

Hmm. I''m not quite sure what you''re saying here. A script that needs to loop is inherently wrong, and proof that you shouldn''t be using a script? If so, I disagree wholeheartedly.
quote:
In short the best "feature" of a scripting language would be avoiding using it.

I''m not convinced that scripting languages are evil and should be avoided at all costs. Having an alternative to scripting languages, when it''s appropriate, is fine.

For example, if you want to define relationships between objects in a map, doing so graphically in the map is almost certainly the best way to do it. Of course, you should be able to give these relationships unique identifiers so you can talk about them in scripts.
quote:
That, and being a stripped down version of Python with slightly more sensible syntax. Oh, and closures rule.

What parts of the Python''s syntax are not sensible?
CoV
You''re right, sorry Mayrel, it''s not like you hurt my feelings or anything but it seemed at the time like you were just being an arse and I usually don''t tolerate that, now that I re-read your post I see that although you DID sound a bit arrogant it was certainly not intentional. Just like my reply to your post

I wanted to see this critiqued but I also wanted some reasons for why it''s not good. And you have some good points but I already thought about all of that and I think that I have a pretty good defence ;P You see, I was going to use an approach like you''re saying but then I thought "hey, maybe if I make it a bit more simple it will be much much easier to code and it will still come out right". Anyways I don''t have much time right now to explain the rest of the system. Yes you''re right, the system does make some assumptions that are probably not very obvious to a programmer used to OOP, but this was made with programmers and non-programmers in mind, so I think I can explain it easily to a non-programmer, while at the same time it shouldn''t be hard for a programmer to learn the new rules (I tried to keep them as sensible as possible). I''ll post back later.

This topic is closed to new replies.

Advertisement