Monday, July 14, 2014

Clothing Update Part I

So, it feels like I've been working on Roodylib a lot over the last few weeks.  It'll be interesting when I put up the next official release and go over all of the updates one last time for the changelog.

Robb Sherwin has been looking to get his game Cryptozookeeper sold online at places such as Steam and Desura, so I've been looking over the code to suggest tweaks to make this or that more user-friendly to those not familiar with IF.  Anyhow, looking at some of the things that game does made me go, "oh yeah, that probably should be an option in Roodylib!" on several occasions.

One thing CZK does is list worn clothing items before listing the rest of the inventory.  I actually wrote that code in the first place, but I didn't like how it replaced SpecialDesc in such an awkward way.  I felt, this time around that, hey, Roodylib can do it better!

So, first off, Roodylib has a new LIST_CLOTHES_FIRST flag that you should set if you want to run the new code. Then, for any character you want clothing to be automatically listed for, you add this:


    list_contents
        return ListClothesFirst(self)

Interestingly, ListClothesFirst only returns true if the character is wearing all of their belongings (this keeps an extra space from being printed after the worn-clothing list).  If you have an NPC where you only want clothing and held items to be listed when you examined them (and not in room descriptions), you could do this:


    list_contents
    {
        if verbroutine = &DoLookAround
            return true
        else
            return ListClothesFirst(self)
    }


Here is a screenshots of this system in action:




So, let's take a look at how this works. First off, of course, there's that ListClothesFirst routine:


routine ListClothesFirst(char)
{
    local x,w,c, list_save, v
    v = verbroutine
    verbroutine = &ListClothesFirst
    list_save = list_count
    list_count = 0
    for x in char
    {
        if x is worn and x is clothing
        {
            w++
            list_count++
        }
        elseif x is not hidden
        {
            x is already_listed
            c++
        }
    }
    if w and c
        list_nest = 1
    if list_count
    {
        if v ~= &DoInventory
            Indent
        if v = &DoLook
            FORMAT = FORMAT | USECHARNAMES_F
        RLibMessage(&ListClothesFirst,1,char) ! "You are wearing"
        ListObjects(char)
        if FORMAT & USECHARNAMES_F
            FORMAT = FORMAT & ~USECHARNAMES_F
        else
            FORMAT = FORMAT & ~USECHARNAMES_F
        list_nest = 0
    }
    for x in char
    {
        if x is not worn or (x is not clothing and x is worn)
            x is not already_listed
        else
        {
            AddSpecialDesc(x) ! tags worn items as already_listed
        }
    }
    verbroutine = v
    list_count = list_save - w
    return (not c and w)
}

It checks to see if any objects are worn, lists them, and marks them as already_listed.  I also needed to add this bit to ListObjects:


The ClothingCheck routine makes sure that children of worn clothing items aren't listed a second time (as they were listed by the ListClothesFirst routine).  There's also some code to make sure character names are used when it might be confusing.

Anyhow, here is the ClothingCheck routine:


routine ClothingCheck(a)
{
#ifset LIST_CLOTHES_FIRST
    if (a is worn and a is clothing and verbroutine ~= &ListClothesFirst) or
        (a is not worn and verbroutine = &ListClothesFirst)
        return true
    else
#endif
        return false
}


As you see, it has to check the verbroutine (which ListClothesFirst temporarily sets).

Anyhow, part of the reason I break this all down is because it's very possible you'll want to split up your player's or characters' inventories in other ways, and hopefully this is enough of a blueprint to get you on your way.

(All of this will be in the next official Roodylib release... coming soon!)

Thursday, May 8, 2014

>EXAMINE HACKER'S KEYRING

One of the things I've wanted for Hugo was an automated way to support possessive adjectives when referring to characters' belongings.  Since Hugo doesn't really give you complete control over the grammar, this is pretty hard to do.  Recently, I coded the best solution I could come up with.  Basically, it's a wrapper routine for Acquire that sets or clears adjectives as needed.  The downside is, you'd have to add an extra empty element to any object that might be used with it, like this:

       

object potato "potato"
{
 article "a"
 adjective "hot" 0
 noun "potato"
 in you
}

       
 

Now, I couldn't really decide on an intuitive name for the routine, but since I figured it was for games where objects are passed around between characters a lot, I opted for the name "HotPotato":

       

attribute keep_adjectives
routine HotPotato(obj,new_parent)
{
 local a
 a = parent(obj)
 if a is living and obj is not keep_adjectives
 {
  if CharacterKey(a)
   obj.adjective #(obj.#adjectives) = 0
 }
 if not new_parent
  remove obj
 else
 {
  a = CharacterKey(new_parent)
  if Acquire(new_parent, obj) and obj is not keep_adjectives
  {
   if a
    obj.adjective #(obj.#adjectives) = a
  }
 
}
       
 

If not provided with a "new_parent" object, HotPotato just removes the object after clearing any applicable adjectives.  Any game that uses this would have to provide its own CharacterKey routine, which would look like this:

       
routine CharacterKey(char)
{
 local a
 select char
  case fred: a = "fred's"
  case player: a = "my"
 return a
}
       
 

Now, all of this work is kind of useless since among games with characters, there usually isn't so much object-swapping that most of this couldn't be done by hand.  Plus, you'll notice that HotPotato only checks for one layer of containment in characters and there might be games where you'd want to check for grandchildren (or further).  Still, this is as close to automating this in Hugo as it's going to get, I think.

There's also the issue of words like "your","my","his", and "her" (>ASK FRED ABOUT HIS HAT).  I find the best solution is to just define these words as removals so the parser completely ignores them.

       
removal "his","her"
removal "my","your"
       
 
How many of these you define as removals depends on your game (games like Spur use "your" as a permanent adjective for certain things).  Also, because of games like Spur where some objects keep a certain ownership despite who is carrying them (like, "your gun" compared to "O'Grady's gun"), I added that keep_adjectives attribute to give objects that should be left alone.

Monday, March 24, 2014

Roodylib 3.8

So, this release feels like it adds a lot more than it probably will feel to the end user, but here is the changelog:

* Added an "elevated" attribute for enterable platforms (such as ladders) where "down" is an accepted exit direction
* Changed the vehicle class again (check out roodylibdocs.odt)
* Added USE_SMART_PARENTS flag so if the player tries going into an invalid direction while in an enterable object, they get "You can't go that way." instead of "You'll have to get up/out."
* In doing so, updated DoGo, and the vehicle and door classes to support it
* Added SKIP_DOORS flag so player can breeze through unlocked doors without opening them like NPCs
* Added a HugoFix settings object so debug monitor settings are kept after a restart
* If daemon/fuse monitoring is on (in HugoFix), a prompt asks whether to run the relevant daemon/fuse (to make it easy to skip during testing, if wanted)
* Got rid of an unnecessary AUX_MATH routine call in printstatuslib
* Made sure Roodylib is more NO_OBJLIB, NO_VERBS, and NO_XVERBS compatible
* Added USE_DARK_ROOM flag so dark rooms appear like an actual room when you enter them (check out roodylibdocs.odt)
* Updated flags.h to include new flags
* Update "go" grammar
* Added the coverart extension to Roodylib because of its configlib compatibility
* Updated old files to have UNIX line feeds and fixed indenting on older code

I also touched up some of the documentation files to mention a couple more things.  Still, there is probably lots of stuff that I could describe more.  If there are Roodylib functions that you'd like to see be better described, shoot me an e-mail!

You can download the latest version here: http://roody.gerynarsabode.org/notdead/roodylib_suite.zip

Monday, January 20, 2014

Roodylib v 3.7

Of course, as soon as I submitted that last version, I remembered some other things I had meant to put in.  Luckily, a couple other things popped up along the way so this update isn't quite as minimal as it could be.

Get it here: http://hugo.gerynarsabode.org/index.php?title=Roodylib

v 3.7 -
        * Added CallFinish, MakePlayer, CoolPause, PauseForKey routines
* Updated shell files to make it easier to turn Roodylib off (for tracking errors down to original library code)
* Updated credits text

Monday, January 13, 2014

Roodylib version 3.6 release

Uploaded a new Roodylib.  Mainly, it fixes some things that Juhana Leinonen found in his Hugo dabbling.  Go download it from Hugo By Example or the Hugo Code Lab (up in the links section to the right).

v 3.6 - * Added DoOpen replacement
* Fixed a ParseError bug (caused by me, not original)
* Added DoGet replacement, updated CheckReach for dealing with instances where the player is in a closed enterable
object and is trying to get something else in the same object

Thursday, November 21, 2013

I'm no good at versioning

I recently ran into some annoyances with my WIP where I realized that Hugo's default message for GO-ing at a non-enterable object is "You can't enter that."  I think, more often than not, GO TO <object> will be typed by an IF newbie unfamiliar with IF's world model.  I have updated DoGo to reflect this.  It now results in a "<the object> is right here." message.

Anyhow, I had forgotten that I had already uploaded a version 3.5 of Roodylib (in my memory, I was still sitting on some changes for the next version), so I have uploaded another version 3.5.  Don't care enough right now to change it.

Other things:

  • Been meaning to write a game design theory post with thoughts about designing routines for jumping around your game.  My WIP has several dream and flashback sequences that can be triggered almost whenever so debugging theory has been on my mind.
  • I asked Kent for some ideas for responses for the "You can't enter <the object>." replacement mentioned above.  Besides giving several responses, he jokingly suggested randomizes between them.  It didn't sound like a terrible idea, though.  While I wouldn't provide multiple, random responses to something like verbstub verbs, I could almost imagine randomized responses for some hugolib-centric messages, like ParseError or something.  Ideally, it could give the illusion that the parser/library is more robust than it is.  Still, at the moment, it's probably not worthwhile to go through hugolib and decide which responses could be multiplied.  More important things to do.

Tuesday, November 5, 2013

Roodylib update

After months of neglect, I've uploaded a new Roodylib.

One is the DoExit bug mentioned in the last post.  Additionally, there are some verb things suggested by Mike Snyder.

Not sure if I ever properly uploaded the previous release (3.4), so here's the changelog from that, too:

v 3.4 - * Updated DescribePlace so it can be called without arguments
* Found another USE_PLURAL_OBJECTS DescribePlace bug in the NEW_DESC stuff
* Updated SpecialDesc, WhatsIn, DoTakeOff
* Checkheld versions of DoWear and DoTakeOff
* Updated FindObject, ExcludeFromAll, VerbHeldMode, SpeakTo, CheckReach
* DoLookIn no longer requires container grammar (now works with non-container, transparent objects)

As always, Roodylib can be downloaded here:
http://hugo.gerynarsabode.org/index.php?title=Roodylib