Thursday, April 25, 2013

"You can go"? We can do!

So, Robb Sherwin's game, Necrotic Drift, was recently available in a games bundle. One of the perks of buying the "deluxe" version that was included was the original game source. I picked up a copy myself, and lately, I've been updating ND to use Roodylib and attempting personal challenges like tweaking the window sizes to work better with multiple displays.

Necrotic Drift uses Cardinal Teulbach's can_go.h extension. I've already forgotten if I had specific gripes, but I've long thought that we could improve on its design. A couple days ago, I decided to finally do something about it.

I had some ideas for things that'd improve can_go, but my plan quickly morphed into something I'd have to write myself. I never liked how YouCanGo (the routine that prints the "You can go" message) does all of the exit-figuring calculations every time it is called, and I liked it less now that I have personally run into problems from writing to too many array slots between turns.

I decided to implement a system where, on the entrance to a room, I'd move around some objects to save the configuration of available exits, so then, every time I want to print the exits, the printing routine can just go look at the relevant objects.

Here is the new can_go.

I also did a version that is an update to Teulbach's can_go. While I changed the behavior of how the preposition property is handled, the new version should be mostly compatible with games written for the old system. Besides adding some feature, I optimized the code a bit here and there to cut down on unnecessary loops.

Here is the update to the old can_go.

I originally forgot to put door support into my new design. In adding it, I discovered an existing problem in Roodylib's DoGo's handling of non-door items with door_to properties. See, &object.door_to refers to door_to property routines while object.door_to refers to simple properties. It is important to check for both in your code.

Anyhow, Roodylib on bitbucket has already been updated, and the fix will show up in the next official upload to HbE (it'll be version 3.2).

Thursday, April 4, 2013

using what I've learned

First off, hey, this is the 70th post of this blog. Not bad for something less than a year old, I think. Just goes to show how geeky I can be about taking apart an IF language!

Anyhow, I had been thinking that of all of my extensions, my NPC  pathfinding extension "findpath.h" probably had the most bad code, memory-wise, as it assigns every room two additional properties, which it clears between uses. That is not unlike my array-clearing code that caused that huge headache in Roodylib.

It's always interesting to look at code you wrote a year ago, as I found several parts of "findpath.h" useless. Among the changes:
  • Previously, before writing the directions to be taken to the applicable character's script, I stored it in a property for that character (something that I was replacing the whole character class to give each character enough open slots). Since the code only sets up one path at a time, I figured I could just store the steps in a regular array that all characters would use. I think I wrote the original code at a time that I was especially fond of property arrays.
  • The code used an included routine called PropertyCount that went through the given property array and counted how many elements had values. Now, this might still be useful somewhere, but the way my code used it, I found I could easily replace it with better usage of local variables. I also clipped some of my determining-which-exit-is-best code by using local variables better.
  • Instead of clearing the room properties, I now determine whether or not a room has been counted yet by using the already_listed attribute. I can't say for certain, but I thought there was a chance that using an attribute might leave a smaller memory footprint.
  • I replaced this finding-the-other-side-of-this-door-object code:
            if InList(a.d, between, a ) = 1
                a = (a.d).between #2
            else
                a = (a.d).between
    With this code:
            a = ((a.d).between #((a = a.d.between # 1) + 1))  
     Anyhow, that second thing, which I got off of CharMove or somewhere, might take a bit longer to read, but it does the same thing without having to call InList. Now, I don't know if calling InList really uses that much more processing power or memory or anything, but at least, when you are using the debugger, you won't have to step through those extra lines.

    So, all in all, findpath.h is a leaner, meaner machine now. It still has some of the same hang-ups. Like, it doesn't have awesome code for dealing with locked doors or anything, but even with that, I think I put it in a much more stable place (now, if there is no available path to the "prize", the code should shut down without printing anything embarrassing).

    So yeah, there's that. If you are curious about the two versions, the old version is http://roody.gerynarsabode.org/hbe/findpathold.h and the new version is http://roody.gerynarsabode.org/hbe/findpath.zip.

    Happy pathfinding!

Tuesday, April 2, 2013

new_desc

In one of my WIPs, I did some hacky things to my code so that in any given room, objects with short_descs are grouped together into one paragraph. Since I've been adding DescribePlace-related stuff to Roodylib lately, I thought, hey, let's see if I can make this an official option in there!

In my WIP, I defined my short_descs like this:
    short_desc
    {
        "A giant spoon lies on the ground, as if discarded by some humongous
        spoon musician.";
    }

With Roodylib, I didn't want to task the author to add the semi-colon each time, and DescribePlace and ShortDescribe really expect short_desc to be a property routine (and not just a regular property). I found that it's pretty much impossible to get the code to play nicely with both.

In the end, I had to create an optional new property and new DescribePlace helper routines to  Roodylib (luckily, I had already designed a DescribePlace that'd allow easy inclusion of such). A game compiled with NEW_DESC set would allow the following and give it proper spacing:

    new_desc "A giant spoon lies on the ground, as if discarded by some
    humongous spoon musician."

Anyhow, this is a feature that will probably only be used by me, but I thought I'd announce it just the same.

Monday, April 1, 2013

more roodylib updates

I added a lot to Roodylib today. The biggest chunk of code was probably my new (optional)  DescribePlace system. All in all, Roodylib went from 160 KB to 181 KB.

I also "released" my port of Cardinal Teulbach's SceptreQuest, which I uploaded to http://roody.gerynarsabode.org/games/squest.hex (I use quotes because I don't intend to announce the game any where besides here and my twitter account, as the copyright on the game doesn't technically allow re-release like this). Writing that inspired several Roodylib updates today. We'll get to that in a bit.

First off, I added an AMERICAN_ENGLISH flag to Roodylib. It really doesn't change as much as you'd think. All it really does is move quotation mark placement for statements such as "I don't understand the word 'blah.'"

As mentioned I also added that DescribePlace stuff. When I ported SceptreQuest, I also coded its odd color handling. I found that this involved changing color at places that forced me to replace whole hugolib routines, so among other things, I added calls to RLibMessages to handle different printed tasks for DescribePlace (such as the printing of the room name), WhatsIn, and ListObjects. As far as ListObjects goes, there are probably more bits of text that I could sent to a message routine, but I'll add those as needed.

 I also finally added that DESCFORM_I constant to act as a FORMAT mask. When enabled, DescribePlace does not print the blank line before printing the room name. It now does this check (in RLibMessage):
                    if not (FORMAT & DESCFORM_I) or (verbroutine ~= &MovePlayer and
                    verbroutine ~= &DoLookAround and a = location)
                        print "\n";
The location check allows one to use DescribePlace to fake movement to rooms (where it should not print a new line) but still prints a new line for when things like newmenu.h call DescribePlace after having printed "returning to the story...".

The next thing I'm considering working on is a combination of Future Boy's time object class and improved resource.h  routines where things like audio.current_music is automatically cleared after the song is over. Going over it in my head, though, has me thinking it might be too bulky for Roodylib-inclusion so I may just improve my already-existing-but-separate jukebox system to do that. We shall see!