Openbracket

6Jun/107

Zork/MUD-like basic item structure

So at work the other day I was explaining Lantern to a buddy (@shamuspeveril) and we somehow got onto the topic of how well nodejs would work for a zork like game or a mud. Well, sure enough, with the idea stuck in my head I sat down today and tried to think through. Luckily I think this concept will apply well to what I hope to do with the Lantern server, so I don't feel like I deviated too much from my path.

In case you are not sure what a MUD is, this is a brief description grabbed from wiki :

MUDs combine elements of role-playing games, hack and slash, interactive fiction, and online chat. Players can read or view depictions of rooms, objects, other players, non-player characters, and actions performed in the virtual world. Players typically interact with each other and the world by typing commands that resemble a natural language.

And if you don't know what Zork is... Leave. Just go.

Anyways, making the basic nodejs server to handle limited verbs was pretty simple. Ex:
Server:

[code]
var http = require("http");
var url = require("url");
var fs = require("fs");
var sys = require("sys");
var qs = require("querystring");
var send404 = function(res){
res.writeHead(404);
res.write('404');
res.end();
}

var server = http.createServer(function(req,res)
{
var path = url.parse(req.url).pathname;
sys.puts(path);
switch (path)
{
case "/":
fs.readFile('mud/index.html', 'utf8', function(err, data)
{
if(err) {
res.writeHead(500, {});
res.end();
throw err;
}

res.writeHead(200, {
'Content-Length': data.length
, 'Content-Type': 'text/html'
});
res.write(data);
res.end();
});
break;

case "/command":
var commands = qs.parse(url.parse(req.url).query).commands;
handleCommands(commands);
break;
default:
if (/\.(js|html|swf)$/.test(path)){
try {
var swf = path.substr(-4) == '.swf';
res.writeHead(200, {'Content-Type': swf ? 'application/x-shockwave-flash' : ('text/' + (path.substr(-3) == '.js' ? 'javascript' : 'html'))});
res.write(fs.readFileSync(__dirname + path, swf ? 'binary' : 'utf8'), swf ? 'binary' : 'utf8');
res.end();
} catch(e){
send404(res);
}
break;
}

send404(res);
break;
}
});

server.listen(8000);

function handleCommands(commands)
{
var commandArr = commands.split(" ");
verbs(commandArr[0]);
}

function verbs(v)
{
switch(v)
{
case "n":
case "north":
sys.puts("Moving north");
break;
case "s":
case "south":
sys.puts("Moving south");
break;
}
}
[/code]

Client :

[code]
$(function(){
var commandObj = {
commands: document.getElementById('commands').value
}

$.get("http://localhost:8000/command", commandObj,
function(data)
{

}
, "json");
});
[/code]

So that just handles north/n and south/s but you can see how it would progress. Which should lead you to the problem I hit when I added the "south" command block - That is going to be one massive switch statement. So instead of continuing forward with my massive switch I decided to think about it yesterday and I think I came up with a solution that I will use also in Lantern for my crafting system.

The system relies on the item know what is can do and containing all the information that would make it able to control itself instead of a large switch/case on my part. And this whole set up is made 100 times easier because I'm going to be using mongodb.  Here's some pseudo code to give you an idea of what I'm talking about:

[code]

{
type:"Room",
exits:
{
north:{desc:"You see an exit to the north",room:3242},
south:{desc:"There's a small door that seems to be locked",room:123}
},
description: "You're in a big room with two doors.",
items:"123,63,7456,34,99,4563,215789,45"

commands:
{
look:{desc:"The room you are in is stupidly large with only two tiny doors, one to the north and a seemingly locked one to the south."};
yell:{desc:"You shout at the top of your lungs and you just hear your voice echoing mockingly off the walls."}
}
}

{
type:"Item",
id:123,
description: "The rock is small and perfectly circular.",
commands:
{
take:{desc:"You take the rock and put it in your backpack.",callback:"addToInventory"};
}
}

{
type:"Item",
id:99,
description: "A small glass bottle filled with an unknown liquid."
commands:
{
combine:{desc:"Blah blah", callback:combineWith, ingredients:4345, creates:8456}
}
}

[/code]

As you can see with a system like this, each item is responsible for knowing everything about it and the other items it interacts with. While this make be more difficult to create up front, I feel that once the system is in place I could easily use this in Lantern, a MUD or really any game going forward.

Or maybe I'm brutally over thinking the problem. Is there a better way to handle item relations and verbs?  Would a massive switch/case with all the different verbs I want be the way to go?  Even if I got that path, I need a similar structure to above just for the content. And then added a simple onetime use command like "lick" or something would require new code instead of just text.

Let me know what you think. I will be starting on code like this soonish for Lantern and would like to have a method pinned out. Right after I figure out the mapping issues I'm having ^^

5May/101

Random Encounters

Progress on Random Encounters, a mini-game of sorts that I am using as a test bed for some of my Lantern concepts, is slowly trucking along.  The game engine along with it's content creation tools are almost complete. Skinning hasn't been thought about yet, but the game itself is close.  Something that I need to do and haven't yet is find a *cheap* host that will allow me to install mongo and nodejs.  Emphasis on cheap as I am broke.

Random Encounters for me is a test for mongo, some simple js. though the initial build won't have it and some gameplay concepts that aren't nessicairly related to lantern but ones I am playing with.

The game will constantly be in beta and will be my playground for new idea's and tests.  After the current road map I have in mind is complete, which I will write down and post later, I will likely publish all the code for people to use if they have the urge to host a crappy game.

Anyways, here's a little snippet of code for mongo to get a random record that took me a while to get working.

[code]

$numOfCreatures = $collection->count();
$ranCreatureId = floor(rand(0,$numOfCreatures-1));
$ranCreateObj = $collection->find()->limit(-1)->skip($ranCreatureId)->getNext();

[/code]

27Apr/100

Lantern Update

In my last post I was discussing Lantern's combat and party system. These two features are very closely related to the map, which is going to be the main area of action in Lantern, so I have been thinking a lot about how to approach this map. I think from some discussions I have had with people in the #bbg irc room and with a few coworkers, I'm going to try to use nodejs for handling the communication and npc logic. From my understanding of nodejs (which is very limited so please correct me if I'm wrong) I can use it to push data to players that need it and create objects at run time on the server and run based on a timer. What I'm looking to do with this functionality is to run the npc's logic independant of players input.  I'm pretty sure nodejs will allow me to do this. All I need to do is set up linux on a virtual machine and get everything all playing nicely together so I can continue to develop on my local machine.

But as I work on Lantern and think about, the need to a test bed is becoming more apparent to me. So to fix this need I'm going to take a quick break from Lantern to make myself a small game that I can use to test different parts of Lantern. This will range from Mongo scripts to game tools (for creating quests/items/etc). The scope of the test bed currently is very limited to the mongo scripts and the game tools. If I can think of a way to test nodejs in this that would be great, but for now, just testing some idea's around those other elements would be enough. This small game test bed will be call Random Encounters. The game is exactly what it sounds like. You click a button and you encounter things. The game will suck, but it's purpose is testing.  This small game will hopefully be online in the next few weeks. Work has be pretty busy of late, so I haven't been able to look at anything lately.

So that's where I am. If anyone can confirm or deny my thoughts on nodejs that would be great.