Top Mud Sites Forum Return to TopMudSites.com
Go Back   Top Mud Sites Forum > Mud Development and Administration > MUD Coding
Click here to Register

Reply
 
Thread Tools
Old 03-13-2004, 09:31 AM   #1
Gakusei
New Member
 
Join Date: Nov 2003
Posts: 7
Gakusei is on a distinguished road
Hello,

Long time listener, first time caller.

I am in the process of developing a MUD server in C++, and I am looking for a way to allow builders to script objects with 'events'. That is to say if a character walks into a room it triggers a scripted method named say 'EnterRoom' on the room, other characters and any items that may be lying about, with said character as an argument to this method.

I am quite capable of creating a lexer/parser myself, but I am wondering if there is an existing scripting language I can embed that will do the work for me?

I have looked briefly at LUA and RUBY. It was not imediatly obvious how to achieve this in LUA, and I could not find that much information on embedding RUBY.

The requirements are:
* Each object (character/room/item etc.) needs to have its own script.
* The script needs to access and create variables that are either local to its object or global to the world.
* The script needs to be somehow 'aware' of the object it is scripting.
* The script needs to be able to manipulate other objects somehow.

Basically, much like a collection of method calls added on to the C++ object.

I did a quick search and found a lot of good advice. However, to clarify, I suppose I am asking for more specific advice on how to set up these languages to achieve what I want.

I strongly suspect someone before me has tried/achieved this. I look forward to your sage-like advice,

Thanks!
Gakusei is offline   Reply With Quote
Old 03-13-2004, 11:26 AM   #2
Blobule
New Member
 
Join Date: Jul 2002
Location: Canada
Posts: 17
Blobule is on a distinguished road
<shamelessPlug>
You mean something like this:

http://www.wocmud.org/Carnage/docume.../documentID/24
http://www.wocmud.org/Carnage/docume.../documentID/25
</shamelessPlug>

I'd say the joy was in writing it. And it's completely sandboxed and under
my control. Before I wrote it I considered embedding PHP but then I figured
that would be more of a hassle, and also I wanted my legacy easyact
scripts to be compatible... so I started from scratch. In retrospect now
that I've done it, there are things I can do I don't think would have been
easy to do with PHP since I can fully control a running context from
within a function (kill it, pause it, jump to an arbitrary code segment). As it
stands though, it sucks my time like a black hole.
Blobule is offline   Reply With Quote
Old 03-13-2004, 11:33 AM   #3
Yui Unifex
Senior Member
 
Join Date: Apr 2002
Location: Florida
Posts: 323
Yui Unifex is on a distinguished road
Send a message via ICQ to Yui Unifex Send a message via AIM to Yui Unifex
Question

My public domain codebase, Aetas, has embedded Ruby for scripting. It performs admirably for every purpose you list.

Embedding Ruby is not too hard. I'll respond to your requirements in turn with how I implemented it in Ruby.
Quote:
Originally Posted by
* Each object (character/room/item etc.) needs to have its own script.
This is more a function of your codebase than the language you are embedding. My objects keep a list of 'Triggers' that fire upon some event being emitted. The trigger simply contains the text of a Ruby script.

Quote:
Originally Posted by
* The script needs to access and create variables that are either local to its object or global to the world.
This, also, is more a function of your codebase then the language you use. I use a property list for pretty much all accessible values, e.g., player->get("name") will return the string name of the player, and player->set("hp", "10") will set their hitpoints to 10. It's very easy to wrap these properties in whatever scripting language you choose. I simply provide a 'rubyval' function that converts the value into a Ruby VALUE by using rb_str_new for strings, or INT2FIX for numbers.

I do not have variables that are global to the world; but if I did, I would be using the same system of properties. I'd merely implement them on the global 'Game' class instead of a specific object.

Quote:
Originally Posted by
* The script needs to be somehow 'aware' of the object it is scripting.
Every object that I use for scripting has a Ruby class defined for it. You can use Data_Wrap_Struct to wrap a pointer into a Ruby class so that 'self' refers to it. In this way you write your Ruby pretty much the same way that you write your C++. For example:
[code] class Element
...
def cmdSay (args)
return if args.empty?

msg = "<#{name}> #{args}\n"
room.broadcast(msg)
room.sendevent(EVENT_TEXT, self, args, args)
end
...[/quote]
Since the 'say' command executes within the context of 'Element' (my toplevel entity), the 'room' in this method refers to the room in which the Element resides. So it functions rather naturally.

Although this sorta feels like an advertisement, my codebase implements exactly what you're asking, so feel free to check it out and post any questions you might have.
Yui Unifex is offline   Reply With Quote
Old 03-13-2004, 11:46 AM   #4
Yui Unifex
Senior Member
 
Join Date: Apr 2002
Location: Florida
Posts: 323
Yui Unifex is on a distinguished road
Send a message via ICQ to Yui Unifex Send a message via AIM to Yui Unifex
Question

I was just chastised for leaving out an essential part of our say command. Behold the power of Ruby!
[code] class Element
def dumbass (msg, &code)
if get("dumbass") then
send(msg)
dumbasses = get("dumbass").to_s
dumbasses.split(",").each { |dname|
person = Game.find_player dname
person.send(msg) if person
}
else
yield
end
end

def cmdSay (args)
return if args.empty?

msg = "<#{name}> #{args}\n"
dumbass(msg) {
room.broadcast(msg)
room.sendevent(EVENT_TEXT, self, args, args)
}
end[/quote]
Had some players getting too annoying, so we implemented a property for making messages they send only send to themselves or their little friends =). All without a reboot, btw.
Yui Unifex is offline   Reply With Quote
Old 03-13-2004, 12:06 PM   #5
Blobule
New Member
 
Join Date: Jul 2002
Location: Canada
Posts: 17
Blobule is on a distinguished road
Heheh we create objects for dumbass players where we override (we can create also) a command
or in the case of the following snippet all communication commands... this is also loadable at run
time, but prevents having exception handling in the command itself (which can also be scripted):

[code]
custom_command_act
parameters; whisper talk say tell reply gtell yell commune ooc ask emote ' " ; ,

protect
{
if( !%eqpdObj( @actor, @this ) )
{
#%runCommand( @actor, @command ' ' @arguments )
return
}
endif

#@action = 1d20
if( @action == 1 )
{
echoto char @actor You pull at your hair frantically.
echoto notc @actor %getName( @actor ) pulls at
\ %sexPossess( @actor ) hair frantically.
}
elseif( @action == 2 )
{
echoto char @actor
\ A loud gratuitous burp expounds from your stomach.
echoto notc @actor
\ A loud gratuitous burp expounds from %getName( @actor )'s stomach.
}
else
{
echoto char @actor
\ An overwhelming feeling of stoopidity takes grasp of your being.
}
endif
}
endprotect
[/quote]

Behold the power of BlobbieScript
Blobule is offline   Reply With Quote
Old 03-13-2004, 01:19 PM   #6
Gakusei
New Member
 
Join Date: Nov 2003
Posts: 7
Gakusei is on a distinguished road
Thankyou very much! I took a quick look and both of those systems look like they could be extremely helpful. I'll take a closer look over the course of the next week or so.

Here's another poser, related to my first question:

Another approach I am considering is writing the server entirely in an interpreted language like perl or ruby. I was wondering if anyone knows if it is possible to create an instance of a class which has basic functionality, then loading a script into that particular instance. What would be even more helpful is if it would override existing methods.

In more detail:

-> A class 'room' is defined.
-> The class definition contains a method 'DropItem' which defines the default behaviour for dropping an item into that room.
-> An instance of a room is created.
-> A script is loaded into this instance that redefines 'DropItem' for this room and this room only.

I don't know if this is possible, but I had a look through some documentation and perl's 'eval' looks interesting. I should note that I am not concerned about security at this point.

This approach interests me for a few reasons: Less work, regular expressions (which I presume would come in handy in a text enviroment) and learning a new language (I am not familiar with perl/ruby/etc.).
Gakusei is offline   Reply With Quote
Old 03-13-2004, 01:50 PM   #7
Blobule
New Member
 
Join Date: Jul 2002
Location: Canada
Posts: 17
Blobule is on a distinguished road
Quote:
Originally Posted by
I should note that I am not concerned about security at this point.
If security is not a concern then Perl, PHP, or I'd wager any scripting language with
eval support, could do what you propose. For instance let's take the following (PHP
style since I never bothered getting very acquainted with Perl

class Room
{
function doDrop( $params )
{
if( !is_null( $this->overrides['doDrop'] ) )
{
return eval( $this->overrides['doDrop'] )
}

// Do normal doDrop processing.
...
}
}

As you can see by declaring an override script which is assigned to the specific
instance of the room then you can essentially override normal processing for an
individual room.

Cheers,
Blobule.
Blobule is offline   Reply With Quote
Old 03-13-2004, 04:22 PM   #8
Yui Unifex
Senior Member
 
Join Date: Apr 2002
Location: Florida
Posts: 323
Yui Unifex is on a distinguished road
Send a message via ICQ to Yui Unifex Send a message via AIM to Yui Unifex
Question

Quote:
Originally Posted by (Gakusei @ Mar. 13 2004,13:19)
Another approach I am considering is writing the server entirely in an interpreted language like perl or ruby. I was wondering if anyone knows if it is possible to create an instance of a class which has basic functionality, then loading a script into that particular instance. What would be even more helpful is if it would override existing methods.

In more detail:

-> A class 'room' is defined.
-> The class definition contains a method 'DropItem' which defines the default behaviour for dropping an item into that room.
-> An instance of a room is created.
-> A script is loaded into this instance that redefines 'DropItem' for this room and this room only.
Any scripting language can do this easily. If you were writing a server entirely in the scripting language, then a better idea would be to use polymorphism to provide your overriding. We call this 'subclassing' =).
Yui Unifex is offline   Reply With Quote
Old 03-13-2004, 05:04 PM   #9
Gakusei
New Member
 
Join Date: Nov 2003
Posts: 7
Gakusei is on a distinguished road
Thanks again.

I guess I am too used to more static languages. I found a function in Ruby that does exactly what I asked for (class_eval).

I am extremely tempted to write the entire server in Ruby now. No more fiddling with templated lists... Easy scripting... No garbage collection to code... Not too far from C++...

More besides.

The pull is strong.
Gakusei is offline   Reply With Quote
Old 03-14-2004, 08:39 AM   #10
Gakusei
New Member
 
Join Date: Nov 2003
Posts: 7
Gakusei is on a distinguished road
OK... I'm thinking about something like this:

[code]
class Room

def DropItem(item)
blah
end

end

...

eval "class ScriptedRoom_#{@room_id} < Room #{@roomscript} end"
eval "a = ScriptedRoom_#{@room_id}.new"

....
[/quote]

If I put the script in a database, I could potentially redefine the behaviour of any object through a website. Dangerous perhaps, but fun!
Gakusei is offline   Reply With Quote
Reply


Thread Tools


Which scripting language? - Similar Threads
Thread Thread Starter Forum Replies Last Post
What language? Aeran MUD Coding 9 04-27-2007 04:11 PM
Scripting gutterzombie MUD Builders and Areas 6 01-28-2004 01:30 PM
Internal Scripting Languages xanes Advanced MUD Concepts 10 05-19-2003 05:12 PM
Embedding scripting languages Artovil Advanced MUD Concepts 6 09-13-2002 02:01 AM
shell scripting Emit MUD Coding 3 05-26-2002 02:48 PM

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off

All times are GMT -4. The time now is 02:02 AM.


Powered by vBulletin® Version 3.6.7
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Style based on a design by Essilor
Copyright Top Mud Sites.com 2014