bookmark_borderScummC – Make your own SCUMM Adventure Game!

Back in the good ol’ days of DOS, I used to (and still do) like playing adventure games. Specifically, I thought those made by Lucasarts were the best, as they often had simple yet funny plots, and you could pretty much get around them easily. They all had (more or less) consistent interfaces – from Maniac Mansion to The Secret of Money Island, you could tell it was a Lucasart’s adventure game and that it was going to essentially work the same as the last Lucasart’s adventure game you played.

Maniac Mansion The Secret of Monkey Island

The consistency in part came from the game engine which they all shared in common: SCUMM (Script Creation Utility for Maniac Mansion). Each game implemented its own set of scripts and resources which could be run in any version of SCUMM, provided that they were targeted for the version(s) of SCUMM that particular runtime of the engine supported. In a way, it was like the equivalent of Java for adventure games.

Anyhow, part of the reason I got interested in software development in the first place was that I always wondered how these games were made. I thought it was great how it all fitted together – the characters, the animation, the scripting, the lot. Eventually I found various projects on the ‘net which were aiming to create development system’s for other adventure game engines (such as those made by Sierra), but nobody seemed interested in SCUMM.

Thankfully in 2004 Alban Bedel made his first release of ScummC – a tool to compile SCUMM scripts (using a C-like language) and assets, and link them together so you could play them in any SCUMM runtime that supported version 6 scripts. Although it wasn’t until late last year that I was confident to download it and try it out. Still, it brought great a great new insight into how these SCUMM games were made.

ScummC Example

By the time I tried ScummC out, Alban had already made a standalone demo SCUMM game which consisted of a single room and a player character. Surprisingly, it was all presented in a top-down view, which wasn’t quite what I expected from a SCUMM adventure. Still, I played around with it and was greatly impressed.

When I digged down into the demo code though, I was amazed at how much of the interface was powered by script. The action’s, the inventory, the hover text – you name it, it was powered by script. Considering almost every Lucasart’s adventure game I played had that same look and feel, I was really thinking a lot of it was going to be explicitly supported in the engine.

In any case, soon after I showed interest in the ScummC project, Alban updated his standalone demo with a second room. It was interesting to note that whilst it was incredibly easy to add room’s to script, it was difficult to create the graphics for the rooms as you had to leave space in the room palette for any actor’s which might be present in the scene. Nowadays you rarely see modern image editors with support for tailoring palettes in this way, so I was compelled to modify the palcat tool included with ScummC to support pre-appending palettes to images (which for some reason I forget, I needed).

Another thing which I tasked myself with was how to make a conversation. For this, I had to grab a copy of ScummVM and use the debugger to see which SCUMM functions were being called during a typical conversation in Day of the Tentacle. In the end, I concluded that once a conversation is entered, the following things happen:

  1. saveVerbs() is called to hide all the interface elements (normally known as “verbs”)
  2. All dialogue items are initialised
  3. setVerbOff() is called on all dialogue items so they don’t appear
  4. Exit conditions for the dialogue are checked
  5. Each option of dialogue is loaded to a corresponding dialog item (setVerbName()) and turned on (setVerbOn())
  6. The conversation script waits till a dialogue option is selected. If it is, the relevant action corresponding to the dialogue gets executed. If the conversation hasn’t ended, it loops back to 3. Otherwise it goes on to 7.
  7. All dialogue items are hidden / deleted
  8. restoreVerbs() is called to restore all the interface elements

Which safe to say wasn’t quite what I expected, which was some specific support in the engine for conversations. Which goes to show that SCUMM can be quite flexible.

Sadly there doesn’t seem to be a lot of people using ScummC. Though then again, its much more programmer oriented as there is no fancy graphical IDE to build games as there is in other adventure game engine’s such as Adventure Game Studio. Its more of a DIY toolset, which doesn’t quite work well in this age of easy to use graphical interfaces. I can’t quite see the typical user of one of those interfaces having to blindly type in the following (taken from the ScummC example) in order to define a room and some resources.

#include 
#include "common.sch" 

bit welcomed,lost,santaHello,santaPlace,santaReal;
actor santa;
#define SANTA_COLOR 14

// our room
room Road {
// first we define the room parameters
// the background picture
image = "road.bmp";
// the zplanes
zplane = { "road_mask1.bmp", "road_mask2.bmp" };

boxd = "road.box";
trans = 0;

//cycle testCycl = { 60, 0, 103, 111 };
cost santaCost = "santa.cost";

voice letsgothere = { "letsgothere.voc", 500 };
voice welcome = { "welcome.voc" };
voice tv = { "file.voc" };

object axe;
...

Still, I think it would be interesting to see where ScummC goes, as there is still a lot to be done with it. I would encourage anyone with some free time and who feels comfortable using lots of commandline tools to check it out.

bookmark_borderNumber Systems & Bases

A while back, I writ a program in which one could convert any number from any base to and from base 10. So for example, if I had the number “10” in base 3, it would churn out “3” in base 10, and vice versa.

Initially all I got it converting was base 62. However I was not just satisfied with base 62, I wanted it to convert any possible base, defined by any set of symbols. To top it all off, I also made it possible to use unicode symbols via UTF-8.

So for example if I could conjure up the following hideous system:

Symbol A B C
Value 0 1 2

…and start saying thing’s like “C + C = AB”.

For the final touch, I added the ability to specify numbers with numerals. Although I didn’t quite get the conversion algorithm from base10 to numerals right.

Safe to say, I ended up with this rather hideous looking app programmed in C. But on the plus side I could:

  • Feed in a file containing a sequential list of UTF-8 formatted symbols to make my own number base system.
  • Feed in a file containing a list of “SYMBOL=VALUE” pair’s ordered by value to make my own numeral system.
  • Convert the output of either the previous examples back to base10.

In any case, one can grab the code here. It’s not pretty, nor is it quite the next killer app – but I had some fun writing it.

bookmark_borderRailsCollab Demo

A while back Gary Vaughan suggested I host a demo of RailsCollab on my server. Sadly though, I didn’t have any quick & easy way of adding new demo users to the system, that is until I cooked up OpenID support.

Consequently, there is now an OpenID enabled service running on http://brew.cuppadev.co.uk. Provided you have an OpenID, you should be able to select the “Use OpenID” checkbox and type in your OpenID to login. This will automagically register you with the system, adding you to the “OpenID” company and the “RailsCollab” project. Afterwards if you want, you can set your password so you can login using a regular username & password, though personally I think typing in your OpenID is a better idea.

Note that your OpenID provider needs to support handing over identity fields in order for RailsCollab to correctly register you. MyOpenID is an example of a provider that supports this. Also note that if there is a user with a duplicate username or email in the system, registration will fail.

I invite anyone to try RailsCollab out.

UPDATE: The demo has since been taken down. If you wish to try out RailsCollab, you will need to download and install it yourself.

bookmark_borderOpenID in RailsCollab

As mentioned in my Cloning ActiveCollab post, I managed to make a reasonably good clone of ActiveCollab using the Ruby on Rails framework.

Recently after watching the rather interesting Google TechTalk on The implications of OpenID, I decided to see if I could add OpenID support to RailsCollab.

OpenID Logo

OpenID is a pretty nifty decentralised single sign-on system. The process of verifying a user’s identity is essentially outsourced to an OpenID identity provider, instead of being left to web developer’s to implement it themselves (and consequently doing a very poor job of it). As a user, I host my identity on any of the numerous OpenID identity providers, preferably one which I can trust. Or if i’m really paranoid, I can just make my own OpenID identity provider.

In relation to RailsCollab, it makes sense to have support for OpenID as a key feature is the ability for client’s to log-on to review progress on a project.

Without OpenID, you’d have to give each of your client’s a username and password, the latter of which you can almost guarantee that someone will forget. And then you need to muck about with setting up an email server so you can send out “Password reset” emails, unless you want to do it all yourself each time you need to reset it.

With OpenID, you’d just have to give each of your client’s a username and an associated OpenID. There’s no need to much about with password’s, as you’ve outsourced that burden to the OpenID provider. All they need to do to login is type in their OpenID, and their OpenID provider will handle the sign-on process.

Obligatory Screenshot

For anyone crazy enough to actually try RailsCollab with OpenID, you can grab a copy from the Subversion repository on RailsForge. Details are available on the project page.

bookmark_borderOpenLaszlo XML Workaround

As mentioned in my previous OpenLaszlo post, I had a problem whereby in SOLO mode my app would send the XML data to the server in urlencode format. This meant that my poor REST-based web service barfed up as this was in no way valid XML. Safe to say, I wasn’t best pleased.

Thankfully though, considering I am interfacing with my own web service, I can change how the server interacts with the request data all I want. So it’s pretty easy to work around this issue.

In the case of the Ruby on Rails framework I am using, the easiest way is to make a new mimetype handler which handles our standards hostile custom mimetype (which I promptly called “application/xml-urlencode”). Like so:

Mime::Type.register "application/xml-urlencode", :xml

ActionController::Base.param_parsers[Mime::Type.lookup(
'application/xml-urlencode')] = Proc.new do
|data|
decoded_data =  CGI::unescape(data) # Decode data
XmlSimple.xml_in(data, {'keeproot' => true,
'forcearray' => false}) # Parse decoded XML
end

And then all I have to do in my OpenLaszlo app is something along the lines of:

datasetForSending.setHeader("Content-Type", "application/xml-urlencode");

And hey presto, the data is now recognised!

bookmark_borderOpenLaszlo Version of the Previous Flex Example

As hinted in my Running into Flex Limitations post, I finally managed to make a version of the rather nifty REST-based project object editor.

After being told about the magical “lzpostbody” parameter by Henry Minsky, I was able to send my XML data in the content of my POST request (which causes the Rails app to create Project objects).

Sadly I needed to make a little concession on the “PUT” method (which would cause the Rails app to modify the specified object) as I couldn’t manage to find a way of passing in the “_method=POST” parameter in from the request as I could with Flex, like so:

private function sendProjectUpdate():void
{
  var projectUpdate:Object = new Object();

  projectUpdate['name'] = pname.text;
  projectUpdate['description'] = description.text;

  updateProject.url = "http://localhost:3000/projects/" +
    projs_dg.selectedItem.id + ".xml?_method=PUT";
  updateProject.send({project:projectUpdate});
}

Doing a similar thing in OpenLaszlo didn’t work (my Rails app doesn’t seem to pick up the overriding _method). I can only assume that Flex is using some extra hocus pocus behind the scenes to make my app happy enough to go ahead. Maybe i’ll have to dissect the HTTP requests to get to the bottom of it.

To replace the requirement of “PUT”, I just added in another route in my Rails app that goes straight to the update method on the projects controller, like so:

map.connect 'test/update/:id', :controller => 'projects', :action => 'update'
map.connect 'test/update/:id.:format', :controller => 'projects', :action => 'update'

In any case, I was happy enough that I could get an equivalent version of my Flex app working in OpenLaszlo. Whilst it doesn’t have all the glitz and glamour of Flex’s components, it mostly still works the same, with the exception of the extra “Refresh” button which I had to add as I couldn’t seem to reliably determine when my requests to the server ended, which meant that the projects list doesn’t always automagically update to reflect the result on the server.

For reference, the code is located here.

UPDATE: Whilst this code works fine in the default PROXY mode, it seems that in SOLO mode the XML is escaped (e.g. ”New Project (TEST)!!!!<”) when sending data, which more or less sucks.

bookmark_borderRunning into OpenLaszlo Limitations

One of the things that got me interested in OpenLaszlo was its pretty cool databinding features, which meant I could take in data from any standard XML document (be it a web page, xmlrpc, or even SOAP) and prototype a little interface around it very quickly, as I previously mentioned in my previous posts.

However, today I decided to take it a step further. I wanted to provide an interface to edit the data I obtain from a request and send back the results to the server. I also wanted to make use of the Ruby on Rails framework’s support for REST.

Being the naive person I am, I thought it was going to be a walk in the park. In OpenLaszlo, all you need to do to grab and display your data from the server is:

  • Make a dataset and point it to your data (e.g. “http://localhost:3000/projects/1.xml”)
  • Make a control with “datapath” set to an appropriate location in your dataset in XPath format (e.g. “dset:/project”)
  • Call “doRequest” on your dataset

The call to “doRequest” can be done like so:

dset.setQueryType('GET');
dset.doRequest();

So naturally, I thought in order to POST the data from the dataset back to the server, I could do:

dset.setQueryType('POST');
dset.doRequest();

Which of course was completely wrong. I assumed that the API would work both ways (i.e. sending the data when the querytype is ‘POST’), which of course it didn’t. The only slightly helpful thing I could do was set the query string. However, this wasn’t quite compatible with REST, so I couldn’t use it as a solution.

After searching about a bit though, I came up with another solution:

var dp = new LzDatapointer();
dp.setPointer(parent.datapath);

var xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.open('POST', url, true);
xmlHttpRequest.send(dp.serialize());

“Great!” I thought, “This should work!”. Sadly though, it didn’t. It seems that OpenLaszlo’s XMLHttpRequest doesn’t send any data in a POST. Great.

A short while later, I realised I should be using a ‘PUT’ request for updating my REST-ful object. The final nail hit the coffin when I got a nice error message from XHttpRequest – “method ‘PUT’ not supported, use GET or POST”. Aaaagh!!

Safe to say, OpenLaszlo’s data binding API is pretty one-sided when it comes to data. Grabbing data? fine. Sending data? welcome to hell. And not even XMLHttpRequest is of any use, unless you want to send a long long query string, or just stuff everything in the headers, both options which contradict REST.

In the future I think i’m going to take a look at Adobe’s Flex. I suspect it might handle REST requests a bit better.