Wednesday, May 1, 2013

more character stuff

So, the character DoGet stuff mentioned two posts ago allows >GET ALL FROM <character>. I was thinking about how this will not always be optimal behavior and what to do about that.

There's probably a grammar-based solution (especially if you use Roodylib's GRAMMAR_HELPER stuff), and actually, that is probably the easiest way to deal with it.

Still, if you want to avoid grammar-tampering, another way to do it is to replace the ExcludeFromAll routine:
replace ExcludeFromAll(obj)
{
if obj is hidden
return true

! Exclude things NPCs are carrying unless the NPC is explicitly
! given as the parent
if parent(obj) is living
{
! if IsPossibleXobject(parent(obj)) or parent(obj) = player
! return false
return true
}

return false
}
Making sure it always returns true when the parent is living gets the player a "Nothing to get." message when he tries >GET ALL FROM <character>. To change this, we'll need to add a case to NewParseErrror:

replace NewParseError(errornumber,obj)
{
     select errornumber
case 9
{
if xobject is living and children(xobject)
{
"You will have to specify one object at a time."
return true
}
else
return false
}
         case else : return false
     return true
}
So yeah, that's that. To do more complicated behavior, like allowing the first item but not allowing the rest, I'd probably incorporate the use of a global or, more likely, the word array (with SaveWordSetting and CheckWordSetting), but that  scenario is unlikely enough that I won't put it together unless I need it myself or someone asks for it.

Roodylib 3.2 has been released

Just since practically everyone who uses Roodylib follows this blog, yes, I uploaded the latest version of Roodylib and it is available at the usual spot:
http://hugo.gerynarsabode.org/index.php?title=Roodylib

always more to do

I have to admit that recently, I've been yet again not working on my own games but have found a distraction. I've been applying Roodylib and my extensions to somebody else's already-released game-with-available-source-code. Mainly, I've been curious how well my code can integrate with other games and whether it helps the overall playing experience. So far, I'd say the results have been fairly promising, although the experience has brought some more issues to my attention

Objects Can Be Grabbed From the Possession of Friendly Characters Without Comment

I was kind of surprised to find out that a character has to be unfriendly to refuse you from taking its possessions, and when you do take possessions from a friendly character, you just get the default "Taken." message.

Now, without modifying Roodylib, there is this solution:
replace character
{
   type character
   pronouns "he", "him", "his", "himself"
   capacity 50
   holding 0
   is living, transparent, static
   exclude_from_all true
   before
   {
      parent(object) DoGet
      {
         local l
         l = string(_temp_string, self.name)
         l--
         print "Nah, that is "; The(self);
         if _temp_string[l] = 's'
         {
            "'."
         }
         else
            "'s."
      }
   }
}
The above disallows taking things from friendly characters. To allow it, you'd have to replace the before routine with something that calls Acquire and prints its own "so-and-so lets you have the <blank>" message.

Just in thinking about the issue while I write this post, I think I will update Roodylib so that DoGet calls a character's after property to allow for different messages when you take objects from friendly characters.

EDIT: Actually, looking at DoGet closer, it already has a parent(object).after check, so I think I'll just give a default after routine to the character class.

Platforms Get No DescribePlace Love

While testing my code, I also noticed that contents of scenery platforms were not being listed by DescribePlace. The game (and others) have gotten around this by having code like this in a room's long_desc:
if child(self)
Perform(&DoLookIn, self)
else
"There's nothing on it."
Really, though, I can't think of a reason why you wouldn't want DescribePlace to handle platforms automatically. You can always deny content listing for &DoLookAround in list_contents, if you want.

The original scenery-contents check looks like this:
         if obj.type = scenery
         {
            obj is known
            if player not in obj and
               (obj is open or obj is not openable)
My check now looks like:
if obj.type = scenery
{
if player not in obj and
! (obj is open or obj is not openable)
((obj is container and (obj is open or obj is transparent))  or
obj is platform) and obj is not quiet
There's probably some overkill in there, and hopefully I didn't introduce new problems.

Platform Problems Part 2

Another problem cropped up, where even looking at scenery platforms or containers like above didn't prompt a listing of their contents. Since I've run into a problem like this before, I quickly guessed that my DescribePlace had left those items with the already_listed attribute, which DoLook looks for before listing contents. At first, I tried updating DescribePlace to always remove that attribute from them, but the thing is, in my modular version of DescribePlace, I really want the author to be able to list objects in any order they want, and I didn't want to restrict them to always having to list scenery contents last.

In the end, I thought, huh, why does DoLook even care about already_listed, anyway? Those attributes will just be reset the next time DescribePlace is run. The only thing instance where I think the already_listed-check might be important is in the case of identical plurals, but in my cursory testing, removing the check has had no effect on identical-plural behavior. Guess I'll just keep the check off the next version of Roodylib and see what problems pop up.

Speaking of Roodylib, I should probably upload a new official release soon. I guess I've been putting it off. I think I'll probably do something about that DoGet issue mentioned above, and here is some other stuff that'll show up in the new version:
 * added a missing printed bracket in parser monitoring code
* added NEW_EMPTY system for more container/platform-emptying options
* added AMERICAN_ENGLISH flag to switch between quotation punctuation styles
* added NEW_DESCRIBEPLACE to give more DescribePlace options
* added WhatsIn replacement and ListObjects RLibMessage-call for more printing options
* updated CenterTitle to not draw extra window in simple, non-Glk terps
* Fixed some places in the supercontainer class that didn't work right with transparent supercontainers.
* Fixed a problem where non-door items with door_to properties weren't being accepted by DoGo. Probably still some perfecting to do on this one.
* Attachables DescribePlace code was missing some parentheses.

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!