Wednesday, September 7, 2016

roody labs

My latest bit of Hugo coding has been comprised of distracted yet productive meandering.

*  * *

Roodylib takes several important Hugo library routines and breaks them up into several routines for the sake of readability and modification (I'd rather provide authors with a method to change just the important thing instead of having to switch out the entire 126 lines of FindObject).  Of course, one side effect of this is that it greatly increases the starting number of routines in any given game.  The Hugo default max limit of routines is 320.  Now, this is a changeable, soft limit, but it worries me when a Roodylib game creeps up to that 320 limit; I don't want it to get to the point where my beginning advice to new authors includes how to raise the routine limit.  They have enough things to take in at that point.

DescribePlace, the routine responsible for room descriptions, was one that I split into several routines so authors had the ability to change the order in which things are listed.  To combat the creeping-routine problem, I redesigned the routines as objects with one routine to execute them.  It's actually been done for a while, but I didn't mention it because it's kind of a useless modification, all things considered, and the number of routines probably only bothers me.

* * *

I also modified the "shell" files included with Roodylib to automatically compile with the -s switch.  This provides compilation statistics like number of objects, routines, etc.  I always find this useful; I figure others will, too.

* * *

Sir Jiz has a lot of timers in his game- most of which he's been handling with the room each_turn property.  I usually do this by keeping the number-of-turns-spent-in-room in the misc property so the each_turn property routine can have some "select self.misc" code and go from there.  Long story short, Jiz was getting sick of reminding himself where the best place to set the misc value was.  I figured, ah, yeah, I guess Roodylib could do something about that.  So now there's a RoomTurnCount thing so nobody has to mess with misc anymore.

select RoomTurnCount
case 0
"Runs as soon as player enters room."
case 1
"Runs after first turn."
case 2
"And so on."

Although maybe I should have pushed him towards using a daemon instead.  Ah, well, always nice to have multiple ways to do things.

* * *

Some months ago, someone expressed interest in there being a Hugo Comp this year, so I tried to gauge interest from everybody at the forums and throw some theme ideas around.  I had been in the middle of playthrough of "Spellcasting 201: The Sorcerer's Appliance" so I figured a magic-themed comp would be fun.  I even offered to throw together an extension for authors to use so they wouldn't have to write the magic system themselves.

I started off by looking at Cardinal Teulbachs' (yes, back in the olden days, we used to have an IF community member named "Cardinal Teulbachs") take on a spellcasting system.  His code strictly prohibited modification, though, so I was going to have to write my own thing by scratch (I don't always honor code licenses, but hey, this time I did).

I think I came up with the base design for my system, but I decided I needed to refresh my memory on how spells worked in the Enchanter trilogy (how many memory slots the player has, if all spells can be memorized multiple times- stuff like that).

The funny thing, though, is that I found myself super distracted by the fact that you could not read dropped scrolls in Teulbachs' sample game which was a departure from expected Infocom behavior.  Just the same, it made some sense, and I decided it'd be nice to write an object class system for objects that had to be held to be read (like a pamphlet) while still allowing for ones that don't (like a billboard).

More difficultly, I wanted to do this on the grammar level so all "You don't have that." messages didn't use up a turn.  Truthfully, it's not easy to have varied behavior when it comes to held/unheld verbs.  I knew that when I did get around to writing this system, I'd have to use my Roodylib "routine grammar helper" system.

I finally got around to looking at this problem yesterday.  It was one of those funny times where you return to an old problem a bit smarter and almost resent the obligation to improve your solution ("WHY CAN'T I JUST STAY STUPID FOREVER?").

First, to help me design the readable object classes, I looked over some grammar classes I had made previously for containers that are emptied in different ways (those that had to be held vs those that don't and so forth).  In my testing, though, the "empty" code wasn't working, and for a while there, I thought maybe I had broken FindObject somewhere along the way (and getting FindObject to do the things I already have it do was a scary, confusing journey so I wasn't looking forward to working on it again).

It turned out that a call to FindObject from AnythingTokenCheck (which itself is called from within FindObject) should have used the "recurse" argument.  Whew!

I also decided that half of my original "routine grammar helper" code was unnecessary.

But anyway, that's all working better now, although I might redesign the routine grammar helper again, possibly to use attributes instead of variable masking.

And, oh yeah, if you were curious, no, I don't think the Hugo Comp is happening.  That discussion fizzled out pretty quickly.

* * *

STATUSTYPE is a global variable that determines what kind of information is displayed in the upper right corner of the status window.  One of the several options displays a game clock like in the game Deadline.  Since the HoursMinutes routine used to print the time could also do military time, a while back, I added a STATUSTYPE value that provides a military time clock (like in Border Zone).   It kind of bugged me that the code didn't have an easy way to switch between the military time with colon and without.  While easy enough to provide a choice for the author, I really wanted it to be as unobtrusive as possible because, really, there's like no chance anyone is going to write a military time game again, and it'd just be embarrassing to show that I spent much time doing some sort of time-configuration system for a feature no one would ever use.  I ended up with just going with a #set NO_MILITARY_COLON flag.

* * *

There are a couple other things, but I'm getting tired of writing.  Anyway, probably will try to put out a Roodylib update within the next couple weeks and then maybe do a round of uploading-stuff-to-the-IF-archive.  Then, maybe, write some IF?  (gasp)


  1. Roody, if you're in effect rebuilding the system to make it easier to use and that requires increasing a default value in order to compensate for it, then it's probably worth doing so and explaining this in the README file or the documentation for Roodylib. Let's be honest, I doubt seriously someone is going to use Roodylib on trying Hugo initially or on writing a game in Hugo until after they've had some experience with the system as initially set up and would only start using yours having had some experience with Hugo and discovering what you've done improves what was in the original distribution. Thus someone is using yours to enhance the system and as such, with an enhancement you may have to make changes. But simply enough if you push things far enough you may have to bite the bullet and admit you can't do everything in 350 routines, not counting the fact the programmer doing a game may have their own routines to include.

    If anything, I think the problem, which I've given some implication on my comments on Jolt Country, is that Hugo is a 16-bit environment in a world that has gone beyond even 32 bit applications into 64-bit and the underlying system has not kept up with what is available now in terms of resources and capability. When the system first came out, probably for Win 3.1, a machine might have 4 meg of memory and the limits it had were reasonable. My current machine has 8 GB of memory on Windows 8.1 64 bit, and some of the restrictions set then were valid but today the resources are much greater and some of them might be much too small for what we can do now.

    1. Hello, Paul! As far as your suggestions go, yes, instructions for raising default limit values is already one of the first things mentioned in the Roodylib documentation. I also personally recommend new Hugo users start off with Roodylib as I've made efforts to make the initial game shell cleaner and more organized so non-programmers get less discouraged (beyond all of the stuff that is fixed or improved "behind the curtain").

      I still think you shouldn't give up on TADS, though! You can do it!

    2. No, I'm not going to give up on TADS anytime soon but from what I've seen I suspect Hugo has just as much capacity to do (almost) anything TADS can. (I qualified it; there might be some useful features TADS offers that Hugo doesn't.) But I think everyone who does programming should try something new every so often in order to get out of their comfort zone. It's the reason I wrote Tripkey and Teleport_Test in the first place. The latter was a proof of concept to show you could implement something Jonsey thought was impossible; a teleporter that could be designed to dynamically go to any room, and the former was to implement a portable teleporter.

      Getting out of the regular and into new things can give real benefits. I taught myself PHP from scratch over a few months and got pretty good at it.

      But I really think Hugo provides maybe 95% of what someone would want in an IF authoring system; about the only missing things are better string support, actual timer interrupts, and delimiterless input, the ability to accept and process keypresses without an enter key being pressed.

      Now, the really big thing TADS provides is an IDE. If I get mad enough at TADS that I throw my hands up in disgust, it wouldn't be too hard to modify the IDE to support .HUG, .G and .H files, instead of .T files, include either the standard library or Roodylib, and call the Hugo compiler, perhaps even including the "click on error message" window that goes to the source code line in error. Then that would really take out a big incentive to use TADS. Their IDE is a big selling feature of the system.

    3. Yes, string support could be improve but I also imagine you aren't yet familiar with what's there, and there already is the ability to accept and process keypresses.

      Also, as far as an IDE goes, some of the features you've wished for over a already exist in any decent text editor with "send output to window" support. Most will let you doubleclick on line errors and go to the relevant spot in the code without any tweaking.

      Anyhow, it has been interesting to follow your progress as you look into these systems. Occasionally, you complain about their limitations. What I've found is that remarkable things can still be accomplished if you're clever enough. Andrew Plotkin's game, Hunter, In Darkness, has a 32K room maze with only a 16 bit VM. Great creativity comes out of working against limits. If you're unable to coax the system to do what you want, there's a reasonable chance you just don't know your tools well enough.