Wednesday, July 10, 2024

Roodylib 4.3.0

 Announcing Roodylib 4.3.0-  some updates listed in the previous post and more in the changelog.


At the time of this post, the IF Archive upload is probably still in "incoming," but you can also download it right here.  The Hugo Notepad++ bundle (Notepad++ setup with a toolbar for quick compilation and execution of Hugo games) and Hugo Notepad++ add-on (files to add to an existing Notepad++ installation- doesn't include the toolbar, though).  I even made a Hugo Notepad++ 32 bit bundle, just in case that would be useful to anyone out there.

the last few months

 When I last updated Roodylib a few months ago, I found a bug shortly after, but I didn't think it was important enough to bother IF Archive maintainers with another upload so soon.  Anyhow, good news!  The last few months have been very successful in finding and fixing several bugs.

To avoid having to actually get back to writing games, I had decided to distract myself by getting back to the project of applying Roodylib to other people's games.  In the past, this has been a great way for finding shortcomings in functionality and ease of configuration.

Anyhow, the game I was returning to has several randomized events and a lot of character scripting and other things that just made the original task of adding Roodylib quite daunting.

It wasn't long before I ran into an instance where a character with a long character script was never reaching his destination.  At first it drove me a little crazy trying to figure out why the last few steps in the script were not happening.

Long story short (and yes, I can easily make it a long story), I found a bug in Hugo's library code.  Character scripts are supposed to have a maximum of 32 steps; instead, if there were multiple character scripts running, the second script was overwriting the first at the 17th step.

Anyhow, I fixed the bug and I was pretty excited about this.  When I first starting making Roodylib, I had never researched how versioning numbers are supposed to work so I just jacked the numbers up willy-willy whenever an update felt big to me.  Eventually, someone pointed out to me that the major, minor, and patch numbers actually stand for things.  In the years since, of course, Roodylib version numbers crawl up by much smaller increments since most updates fall under the "patch" umbrella.

So, to me, fixing a system from the original library was BIG and merited a minor number increase, and what can I say, I find that exciting.  Also, of course, I was happy to be able to have a good reason to put out a new release because of that bug I mentioned at the start of this post, too.

Luckily, the bug fixing did not end there, nor was the hunt even limited to the Hugo library/Roodylib.

While troubleshooting that game I had been adding Roodylib, too, I found a bug where, if I referred to a known object not in scope, if there was another known object not in scope that shared an adjective (despite different nouns), the first one defined would always be the one sent to ParseError;  of course, this is noticeable if the objects have different pronouns ("You don't see him here." when you are expecting "her").

After testing, it became clear that the problem was not on the library side.  I wrote one of the people behind one of the Hugo interpreters and asked him to look at the problem;  he said that he didn't have time right away but pointed out that the problem was probably in "heparse.c" (in the source).  When I read that, I thought, huh, it never even occurred to me that I might have the chops to be able to understand the engine code but, hey, it couldn't hurt to look.

I wouldn't say that it was easy, but Kent's code is commented and organized nicely and it was fairly clear where I needed to look.   Plus, I have to give props to all of the people who have contributed to making the Hugo unix port so easy to build on modern systems so I could tinker and test my solutions relatively quickly.

I found the bug and went around making pull requests at several github projects that use the Hugo source.  Gargoyle accepted it right away, and it was kind of a bucket list moment for me.  I've always wanted to contribute to an open source project but didn't think I had the programming chops for the opportunity to ever come up.  In the acceptance, it was explained to me that Gargoyle (and several of the other interpreters) inherit their code from the Hugo unix port repository, and somewhere along the way I was made a collaborator of that so I'll never technically have to do a pull request again, but it sure was satisfying to make one and have it accepted!

After that, I was digging through old joltcountry.com posts to see if there were any problems that new light could be shed on, and I found one about Hugo's inability to write (and correctly read) negative numbers when it writes to file.  Someone helped me come up with a solution.  It won't work in 16 bit interpreters (I don't even know the likelihood that anyone will ever build a 16 bit interpreter again), but that's fine; writing negative numbers would probably never be needed by a game author- it was more for interpreters that use Nikos' opcode system for special instances.

Some years ago, I noticed that if an xverb grammar definition (xverbs in Hugo are system verbs like "save" or "restore" that don't use up a turn) was more than one line long, the additional lines would be interpreted as a verb.  I decided to look into this as well.  I initially thought the problem might be in the compiler on this one, but it turned out to be another engine error.  I got that one, too.

So, three engine fixes!  Now, I imagine that we are probably years away from our next Gargoyle or Hugor or whatever release, but it's nice knowing that those fixes will be out in the public one day.

Anyhow, I've been kind of rambling on and on.  I'll just say that in these last weeks, I also fixed some problems with Hugo's plural/identical class system and I was pretty stoked about that (another good excuse for the minor increase in the upcoming version).  The rest, I'll just save for the new release's changelog.


Sunday, July 7, 2024

Hugo's >GET ALL behavior

 I've been doing a lot of Hugo poking and prodding in the months since my last post, and I'll soon be releasing an update to Roodylib and talk about all of the improvements.  One thing that came up in this time is particularly useful to authors, though, so I wanted to give it its own post.

In the last post, I mentioned how I gave a Roodylib-ized version of Kent Tessman's Spur to someone.  Since he quickly uncovered a daemon bug due to changes in the official Hugo library over the years (I talk about this a bit in the previous post), he switched over the original version at some point.

He noticed that the >GET ALL responses were different in the two games.  Now, Roodylib intentionally skips some items from >GET ALL as I personally feel a long list of objects you can't grab makes a game feel shoddier-coded.  On the other hand, I have some sympathy for the way that >GET ALL can sometimes be used as a sledgehammer to list as many of the objects in the room that can be interacted with as possible.

This got me thinking that maybe Roodylib should have an optional "kleptomaniac" mode where the >GET ALL rules are looser, something akin to verbosity settings.

While researching this idea, though, I found that Roodylib's behavior wasn't as different from the old behavior as I thought;  hidden objects were ignored in both (which is for the best as authors might use hidden objects just for scope purposes).  Roodylib normally skips over trying to get other characters, but turning that behavior off didn't result in the multiple lines of "You can't pick that up." that I had envisioned.

Roodylib also had some code borrowed from Future Boy! that disallowed >GET ALL from being applied to the belongings of other characters, unless the player mentioned them specifically (>GET ALL FROM BOB), but even after I took away that code, belongings of the character I was testing with were being ignored.

In my "kleptomania" test game, >GET ALL only added the ability to try to pick up characters, and that seemed more like a case of being grabby than the kleptomania that I was shooting for.

I eventually figured out the following rules:

  • If a parent object (character or not) has a false exclude_from_all property, >GET ALL only attempts to get the parent, skipping all of the children.  This is why when I turned on the ability to try to get characters, the other code became irrelevant.
  • If a parent object (character or not) has a true exclude_from_all property (which is Roodylib's default), all of its unhidden children are available to >GET ALL (which the Future Boy! code stops if it's being used).
I just think this is good for authors to know.   Say your game has a coffee table with some stuff on it the player may want to pick up.  Better to make the coffee table's exclude_from_all property true so a >GET ALL automatically tries to get all of its children instead of making players type >GET ALL FROM COFFEE TABLE.  If you don't want the children of an object to show up in >GET ALL, giving the parent a false exclude_from_all property is a quick way to stop that.

Additionally, the ExcludeFromAll routine is what you'll want to edit if you want more control over how the children of objects are handled.  This is where that aforementioned Future Boy! code is.

In the end, "kleptomania mode" was a bust since I don't think I can provide a "kleptomania mode" experience satisfyingly different enough from normal behavior without breaking everything.   Still, I learned something.