|
So the other day I was thinking about how I was going to design the schema for the Ulysses Agenda game's server-side database, and then I had a revalation! I wanted pizza! But after I had that revalation, something else dawned on me! I was trying to think of how to store all the data, such as the ship types, the star dock types, the resource/mineral types, etc.. Then I began to think that schemas are just so restrictive, what if people want to expand the functionality of the game? Then I thought... code is data...data is code... Ruby? hell yes.
Before I launch into a tyrade about how ridiculously cool Ruby is and how appropriate it is for what I want to do, I want to provide some background. Back in the good old days, when I was skipping class at University in order to write code for a MUD, I was writing in LPC. Basically what this meant was that the LPMud GameDriver was written in C and ran on a Unix box, and the core networking and File I/O structure was available in a functional API to code written in LPC, a C-like psuedo-object-oriented language that I have always loved. In LPC, you had .c files that represented your "object" hierarchy... so you started off with /std/object.c and derived into things like /std/mobile/player.c and /std/container.c which had child classes such as room.c and player.c since both room and player could have inventories. LPC supports multiple inheritance, and you might code a room that looks something like this:
#include "domain.h"
#include <stdproperties.h>
#include <room.h>
inherit BASE_ROOM;
object knight;
void create_room()
{
set_short("Room");
set_long("This is a room. It looks like there's a room to the north.\n");
add_exit("north", "north_room.c");
}
void reset_room()
{
if (!knight)
{
knight = clone_object(MYDOMAIN + "/npcs/knight.c");
knight->move(this_object());
knight->say("Bow before me, you pitiful creatures!");
}
}
void onenter(object player)
{
tell(player, "Welcome to my room, " + player->query_race());
}
I am taking some liberties here since it has been a LONG time since I've actually coded any LPC. This was all great and wonderful...but it was a long time ago, and things have come a long way. For example, we now have an object-oriented programming language that sports all the power and flexibility of a pure-functional language like Python or F# as well as full support for object-oriented patterns such as inheritance, polymorphism, encapsulation, etc.
What if, instead of creating this stuffy mySQL or SQL 2005 schema and forcing all of the data into rows and columns, the world itself was defined as an object model scripted in Ruby. This would not only allow for the power of inheritance and instantiation, but data could be stored and state maintained via serialization, and people who got the game could extend and modify the game using the low-barrier-to-entry language of Ruby instead of worrying about compiling with VS 2005 and learning C# and the ins and outs of WCF. What if, just what if, you could create a Star dock called Joe's StarBar and Grill using Ruby and still have the entire Peer-to-Peer networking engine managed using the CLR and Windows Communication Foundation, bridging the top-tier "world script" in Ruby to .NET using RubyCLR?
# Ruby... its solid beef, baby!
require 'ulyssescore'
require 'stardock'
require 'commerce'
class StarDockAlpha < UlyssesCore.StarDock
include Store
include LocalWiki
include RoomChat
def initialize
self.dockname = "Joe's StarDock and Grill"
# set profit margin by Store mix-in
self.profitmargin = .3
# set wiki post limit by LocalWiki mix-in
self.wikilimit = 12
# set room name for RoomChat mix-in
self.chatroomname = "joes_stardock_and_grill"
end
end
And then, out in space, say in Sector 12, you might have code to create an instance of this star dock and place it in the list of objects floating around in the sector:
dock = StarDockAlpha.new
@localobjects.Add(dock, SpaceCoordinate.new(3,0,4)) # at point (3,0,4) within this sector
If you are sitting there saying OMFG, the potential uses for running Ruby on top of the CLR to enable scripted access to lower-level concepts such as WCF peer-to-peer networking, then I hear ya brother. If not, then you've got no business reading this blog and go back to the stone age where you belong :)
Mix-ins take care of needing Multiple inheritance (which Ruby doesn't actually support) that I had available to me via the psuedo-OOP LPC language. Ruby itself takes care of the simplicity of coding up new content, I just create files in a directory and the main game engine takes care of spawning off all the right objects. The Ruby core would listen to WCF events and take appropriate action, and would also translate the appropriate Ruby methods like Player#tell or Game#broadcast and everything would be, in my opinion, on a level of kick-ass on which my code has never before existed.
Thoughts?
ok a few things, ruby hmm I prefer python I just wish they'd get with the
times, TG is nice but ROR is better.
Not done with the book...which is why its taking so bloody long to do all
my fun stuff. I like Ruby just from an aesthetic point of view - people
could argue that Python is as good or better for this purpose. Entity
Framework and LINQ only allow me to store _data_, they don't let the people
who use my game write their own custom code. For example, you can't use
LINQ to make it so that when Joe Admin gets my game, he wants to write a
quest that will reward the player with XP for picking up a famous dignitary
from planet Y and delivering them to planet Z. Thats what you can't do with
pure data, but you can do with Ruby.
My blog look and feel template is a stock one provided by my host - I don't
have control over its IE 7 visibility. Btw, IE7 in its current form screws
up all kinds of CSS that it shouldn't screw up by the time it RTMs.
ahh ok I see now, I didn't realise it was a script for the game I guess
thats what the title says too ;)