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.

Thursday, April 25, 2024

2024 update

 Well, it's been three years since the last one, so I guess I'm due for a new Not Dead Hugo post.  In the past few months, I have been cracking open some Hugo code once again.

First off, a special shout out to the hundreds of bots who visit this blog every month.  Thank you, Hong Kong!  

I still have never learned any general purpose coding languages to the extent that I know Hugo.  I mentioned on here at one point how I wrote a Hugo "game" to coordinate my family's Secret Santa program.  It allows me to easily disallow Secret Santa matches from previous years so people don't get the same pick, and using game transcripts, it writes all of the picks to text files so I can be as surprised as everyone else, as far as who has picked whom.

In the last year, I decided that it would be nice to have a companion compilation that would allow my family members to look up Secret Santa's on their own (for the times you have a really inspired gift idea for someone so you would like to pass the idea on to their actual Secret Santa... or whatever other reason you might want to know).

So, I wrote this companion app.  The two programs shared a file that both could write to or read from (like I did in my joke game "The Halloween Horror").  For some reason, though, at first, values were getting overwritten by the second one.  I decided this merited some more in-depth examination of my "configuration file helper" extension, but by the time I got around to doing the deep dive, I had already redesigned my pair of "games" and was no longer able to replicate the issue.  Sometimes it's kind of disappointing when everything works, no longer able to figure out why anything ever went wrong.

Hugella over at the Jolt Country interactive fiction started a project to review all of the IF Archive's uploaded Hugo games at the tail end of 2022.  One of the early games covered was Robb Sherwin's port of the BBS door game "HAMMURABI."  Opening up the game myself reminded me that I once thought it'd be a good coding exercise to add some perks.  The main thing I wanted to do was to have the game use the normal Hugo engine game loop instead of 'while' loop so that meta commands like SAVE, RESTORE, and (most importantly) QUIT worked.  I also wanted to stop it from accepting negative numbers and other things that could easily mess up the game.

I thought about this idea in 2023 but I think I actually even gave up on it at some point, since Hugo only understands a few numbers as dictionary words by default and commands need to be understood for the game loop to work.

But there I was, in 2024, with new ambition and grit!  And I was successful (the new version is now up at the IF Archive, I believe)!  So that was fun.

There was a snag at one point, though.  My Roodylib code that turns inputted-numbers into actual numbers expected unrecognized words in the word array to have the value 0, and in my code, they were coming up as -1.  Part of me remembered seeing parse$ (the variable where Hugo saves unrecognized words) having the value -1 in the past, but I just figured I must have gotten something wrong.

So this (and another sort of meaningless update- just added some additional information at the start of game transcripts in games compiled in debug mode) caused me to upload a new version of the Roodylib suite and updated the Notepad++ packages.

Only after all of this was done did I discover the true culprit.  parse$ in a word array filled by the parsing engine gets the value -1, but parse$ in a word array filled by the input command has the value 0.  So future releases of Roodylib will allow for both values (since no legitimate dictionary word will ever have those values) but I'm not going to upload a new Roodylib suite right away.

In other Hugo news, I recently made the acquaintance of a blind IF fan so I was excited to share some Hugo games I've compiled with some accessibility stuff that strives to make games work better with screenreaders.  I don't think he noticed any of those features (which isn't a big deal since they are barely noticeable, to be honest), but he did notice that a daemon wasn't triggering properly in the game Spur.  While I was quick to suspect that some of my Roodylib updates had broken something, it turned out that some of Spur's 1999 daemon code doesn't play nice with the modern Hugo library.

It was easy enough to replicate the intended behavior in other ways, though, and I made a note about this Spur code over at Hugo By Example.  I've been trying to update Hugo By Example more in general.  Among a handful of pages, I added a step-by-step walkthrough on using the Windows Debugger as I get the impression that many Hugo authors don't take advantage of it.

In other project news, as someone who feels he has awful time management, I coded a thing in Hugo that randomly picks tasks I want to do and rewards I could have (again, I don't know any general coding languages well).  I used Hugo's system time stuff to determine what day of the week it is and what time of day so that some tasks can be limited to day or night or weekday or weekend, if need be.  Finding online equations for finding the day of the week was fun; I can't remember the last time I've needed the mod function for a game.  Still, it's unlikely that any game most people write will care if players are playing the game on a Monday so I don't think I'll be adding that code to any of the Roodylib libraries.

The plan is that I will work on my own game ideas at some point, but since working on my own games is the worst, I'll probably find one or two distraction projects to do before that happens.