Tuesday, July 31, 2012

more stuff

Ha, I had already forgotten what my last post was about, but having read it, I can say, my latest problem was a continuation of the old one.

So, newconverse has this feature where >UNDO can remind the player what is being undone:

> talk to man
The man's eyes catch the torchlight for a moment as he looks up at
you.

> undo
[ undoing >talk to man ]

Gloomy Hall

>
It exists for a couple different reasons. I think, originally, the point was so that in a game where >UNDO skips over whole conversations, I wanted a mechanism to allow for a "[undoing to before conversation]" (which it does, under the right circumstances). It's also useful because it clarifies what really is being undone. Sometimes, as Hugo game authors, we might accidentally put important game text or code in something that returns false or, just as likely, a player might perceive a turn as counting (when it did not). This feature always keeps the player in the loop as to what's being done. Take, for instance:
 > talk to man
The man's eyes catch the torchlight for a moment as he looks up at
you.

> sleep
Not now--there's work to be done.

> undo
[ undoing >talk to man ]

Gloomy Hall

>

 ANYWAY...

So I noticed that the above feature was having a conflict with the issue from the last post. If you type only an object, the engine runs FindObject. After that, it jumps straight to SpeakTo. Oddly enough, it clears the word array before calling SpeakTo so my undo-command-saving code (which I stuck in an event, as that runs after every successful turn) wasn't saving the command properly (as concise as it was).

Anyhow, lots of futzing later, I got it working, but I also found out that a major culprit to it not working had been that while roodylib uses the word array to save states during UNDOs, RESTOREs, and RESTARTs, I was saving too low on the word array so some of it was actually being written over after a successful UNDO, screwing over the word-array-checking after-UNDO code.

I don't know how well I described all that, but that's what I did today!

Sunday, July 29, 2012

SpeakTo me

Today, I was trying to add some polish to newconverse. At one point, I started trying to modify its SpeakTo replacement so it was more like the one I put in roodylib, as I have become rather fond of most of my roodylib replacements. Eventually, I decided it might be altogether better to just drop the SpeakTo replacement in newconverse and alter newconverse to work with regular old SpeakTo.

This presented some interesting problems. If a player only types <character name> at the prompt, the engine calls SpeakTo directly so there wasn't an obvious way to redirect things with a before property. I ended up putting some code in the parse_rank property (since FindObject is called a couple times before SpeakTo) to change the verbroutine global if need be. Knowing what verbroutines to expect helped me write an order_response for the character class that could interpret things properly.

As if that wasn't all a big enough pain, I wanted to give the player a "You are already speaking." line if you do >TALK TO CHARACTER repeatedly (instead of an endless barrage of "<character> is listening."). While this was easy enough to trap for a regular TALK TO command, this turned out to be a pain for things like CHARACTER, HELLO what with the way that SpeakTo is always clearing or setting the speaking global. I had to change it yet again (hopefully for the last time) so it only clears and sets the speaking global when absolutely necessary (like, it only sets the global after order_response has been run, so your order_response code can correctly gauge whether or not the character was given his first command of the conversation).

Newconverse still has a ways to go before perfection; some of the messages could be tailored for multiple player persons (right now, it's all written in second player person) and just some general polishing, but hey, we're getting there.

Friday, July 27, 2012

one more colorthing...

I forgot, when announcing my colorthing.hex color palette program, to remind everybody that colors are not the same across platforms, so still be aware that what looks cool on Windows might be totally unreadable in Linux (just another good reason to use the roodylib-bundled colorlib extension). Still, sometimes you just want to write a game that looks cool on your system.

Anyhow, I've updated the colorthing.hex file to include that information. Also, that file has the latest version of that HugoFix stuff I was talking about, so typing "$ot 0" should give you an idea of how windows and replaced objects are listed.

So, today was another day where my optimal coding window was in a place where I didn't have much privacy so I didn't work on game-y looking things. I was getting writer's block with the LibreOffice document I've been jotting room descriptions in, so I opened up my update to Christopher Tate's conversation system extension, as I've been meaning to do some things with it.

First, I checked over the properties I created for it and made sure they were alias-able, then proceeded to alias them. Then, I added some more comments to help some of my additions look more organized.

Looking over it now, I think I'm going to routine-ize more of the messages to make more responses configurable. There's a couple other tiny things to do, but overall, I'm thinking it's almost ready for an official release (well, an official upload to HbE, anyway... an ifarchive upload is a long ways off).

To remind people, this conversation system update aspires to give authors several menu conversation options. Conversation options can be at the top of the screen or in game text. Conversations can be topic-based, and players can be informed (or not) of available topics. There's a fair amount of mixing-and-matching available, too. Let's see some screenshots!

Main-text conversation menu, no topic-switching
Top-based conversation menu, topic-switching allowed

Thursday, July 26, 2012

go hug an object tree

The good news is, I've actually been writing game text lately. It's been slow going, but I basically have the opening to my new game done. It's coming together.

Now, this aforementioned game should have a couple color changes when its done, but I haven't decided on the color combinations yet. I was getting pretty sick of trying colors blindly. I thought somebody had made a utility that showed all of the available colors, but I couldn't find it so I coded my own: http://roody.gerynarsabode.org/notdead/colorthing.hex

While putting it together, for some reason, I was using HugoFix's "$ot" command to look at the object tree. All of the blank (no-named) objects due to my sample game's many windows bothered me, so I updated DoHugoFix's (and its companion routine, DrawBranch's) code so that the following usually-blank items now have a description:
  1. Object 1 is now listed as the display object, which it should always be in a standard library-using game.
  2. I gave the window_class object in "window.h" the type "window_class" so it can be checked for. Window objects get some special window-printing code.
  3. All other unnamed objects are assumed to be replaced objects and are listed as such.
Note: Even unnamed objects are given a name by the compiler- the object's name within parentheses. Window objects are special in that they override this behavior by declaring their name as "" (window names are assumed to be window titles that need to be printed underneath the applicable window). So, other than window objects and replaced objects, it is unlikely (though not impossible, of course) that an object will be without a name.
 
So yeah, admittedly, that's not the most important roodylib addition I've ever written, but I like it enough.

Other than that, I noticed that Hugor is not handling the MATCH_FOREGROUND constant correctly, so the input color is coming out wrong on some games. I e-mailed Nikos about it, although maybe I've said something about it before as the e-mail gave me a little bit of deja vu (the only implication here is that I'm so disorganized).

Oh, well, progress is progress!


Thursday, July 19, 2012

my ASK ABOUT conclusion

Ok, so I played with this a little bit today. Surprisingly, the method I thought would work better didn't work at all. I forgot that while an object's property can be a property routine, you can't just fill property array elements with calls to routines to add some extra dynamic elements. It's pretty important for a game to support multiple adjectives per object, so I ended up abandoning that route.

That leaves me with the other method. Here is the code I came up with:
verb "ask", "question", "consult"
    * (LivingAsk) "about" "his"/"her"/"its" anything                   DoAsk

routine LivingAsk(var)
{
    if var is not living
        {
        "That doesn't make any sense."
        return false
        }
    local i
    for (i = 2;i < words ;i++ )
        {
        if word[i] = "about"
            break
        }
    local a
    select word[(i + 1)]
        case "his" : a = "he"
        case "her" : a = "she"
        case "its" : a = "it"

    if var.pronoun ~= a or not Contains(var,xobject)
        {
        "That doesn't make any sense."
        return false
        }
    else
        return true
}
The downside of the above is that you have to predict proper error messages for every case (it's conceivable that there are times where "That doesn't make any sense." doesn't cut it). Just the same, I was pleased that this worked at all.

Anyhow, drumroll, please...

The easiest, simplest way to support >ASK CHARACTER ABOUT HIS POSSESSION

Just add this line to your code:
removal "his","her","its","your"
("Your" because we also want to accept, CHARACTER, GIVE ME YOUR POSSESSION)

Just ignoring these words completely will largely support our cause, I figure. It is more likely that the player will only use these words in instances where they make sense, then they are likely to type, ASK YOUR CHARACTER HIS ABOUT HER ITS POSSESSION (which will still be processed, using the removal method).

So, yeah, that'll make your game sound smarter. Otherwise, you could always mix-and-match between these two methods to make your game seem as smart as possible (I'd probably always declare "your" as a removal, as code that only applies to order_response's seems like it'd be a pain in the ass), and there's plenty of room for improvement with the routine-grammar-token route (for instance, you could have it rely on an ownership system that is unaffected by actual possession).

>ASK ROODY ABOUT HIS NEXT TASK

A recent review of a game at the IF Database reminds me that it bugs me that a player can't easily ask an NPC about his or her possessions with something like >ASK MAN ABOUT HIS POSSESSION ('his' being the important word here). I think my next little distraction will involve trying to come up with the simplest, best way to handle this.

The two approaches I am considering:
  1. Make a routine to added to the adjective property array of any object that can be picked up by an NPC. Have the routine return the word "his" or "her" or "its" based on the NPC's gender and whether the object is in a character's possession.
  2. Make a verb grammar that uses a routine as a grammar token to verify that the item is being held by the right person.

The first approach will probably be easier and more-likely-to-succeed, but we'll see what works out better.

Monday, July 16, 2012

So...

When I go over my old code, I find mistakes at an alarming frequency. The only consolation is that one day, I'll stop writing new code long enough for the bug-catching to catch up. Also, it helps that there are only a handful of Hugo users in the world, so at any given time, only a couple of people might be swimming in the morass of my faulty code.

One of the things I like about roodylib is my system for saving globals over a session. I successfully put in some code so that extensions like beta.h can keep track of things like the "is transcripting on?" global over RESTOREs (and not just RESTARTs). I noticed today that my code didn't keep the reverse from happening- that is, routines that should be only run at the beginning of a game (like CalculateHolding(player) and InitPluralObjects) were also running after every game restore or even undo (if colorlib.h is included). That seemed like a pretty bad idea.

Anyhow, I think I have wrangled that issue pretty well, and I have mostly ironed out the PreParse thing how I want it. Still, one always has to wonder how many big, bad bugs there are still out there. Actually, it's no wonder. I know they're out there.

PreParse

I've been thinking that, as far as roodylib is concerned, I should do with PreParse what I already did with library extension init and main calls. That is, I'd have PreParse check some kind of preparse object for children, running all applicable routine properties of each child it finds. This downside is that this would make PreParse irreplaceable, but I figure I'd provide a child-of-preparse class object to easily add new PreParse code. Alternately, authors can always stick their code in the player object's before routines for PreParse.

Again, this may seem like more obfuscation. The main thing is, I'd like to get library extensions to a point where all you have to do is include them (and don't have to add any calls to init, main, or PreParse).

If PreParse code order ends up being a problem, I guess I could add some kind of priority ranking thing. We'll see.

Friday, July 13, 2012

another color oddity

So, today I was adding INPUTCOLOR support to my colorlib extension. After making my changes, I made a test case where the INPUTCOLOR changed every turn. Oddly enough, my game wasn't showing my input colors.

Eventually, I figured out that Hugo interprets:
color <first value>, <second value>
as:
color <first value>, <second value>, MATCH_FOREGROUND
This means that hugolib routines like PrintStatusLine, Menu, and CenterTitle automatically overwrite any non-default input colors you have set. I have updated the relevant routines in roodylib.h and newmenu.h, but anyone who is using non-default input colors in their game(s) should be aware of this.

Thursday, July 12, 2012

colorlib coordination

Yesterday, I was thinking how I probably should have coded the "colorlib" extension so that it saved and checked the input color (what the player types), too. I pretty much skipped it since, in my experience, it is not used a whole lot, but Robb Sherwin has used it a couple times in his games to nice effect.

It would have been nice had I coded it right the first time, but oh well. Anyhow, the main reason I'm posting here is to share a bit of advice that I learned in my colorlib-writing process. If you create a global variable meant to hold color values (example: TEXTCOLOR, MENU_TEXTCOLOR, etc.), it is best to define it with a default value, like:
global TEXTCOLOR = DEF_FOREGROUND
(TEXTCOLOR is defined this way. MENU_TEXTCOLOR is not.)

The importance of this is because later on, you might want to check if a global has a value, but this is easily confused by the fact that the color BLACK equals 0. Giving it a default value (default interpreter color constants range from 16 to 20) ensures that a 0 value always means BLACK.

Tuesday, July 10, 2012

more debugging stuff

I updated the "roodylib suite" file today (roody.gerynarsabode.org/notdead/roodylib_suite.zip). First off, it fixes a couple things in the included shell file that were caught by Royce Odle (yes, the Royce Odle of Hugo by Example fame). Secondly, I threw in some more debugging commands that are available when the HUGOFIX flag is set. The first two commands are SCOPE and SCOPE ROOMS, meant to remind an author exactly what the player can "see" at any point. SCOPE just checks what is available in the current room, while SCOPE ROOMS makes a list for every room in the game. I previously had shared the code for these routines on Hugo by Example, but in priming it for roodylib, I made a couple things work nicer. The other thing I did was add a VERBTEST <object> command. This is my attempt to emulate an extension that Juhana Leinonen made for Inform 7. It automatically barrages an object with a bunch of library verbs, as a way to remind yourself of what kind of obvious commands a player might use.

So yeah, hopefully, those are somewhat useful.

Lately, I've admitted to myself that I should probably start looking into filing my extensions in some source code management system, but I haven't yet looked into my options. Hopefully some of them are pretty simple. Also, rights-wise, I probably can't choose some open source site for any extensions that use standard library code (like roodylib).

Saturday, July 7, 2012

that menu thing

Ok, so yesterday, my prime coding time was spent at a coffee house where my laptop didn't have a lot of privacy. In such scenarios, being a full grown man (fuller than I'd like, even), I don't like people to see that I am obviously working on a game. As my current WIP has cover art and music and looks much too "game-like", I jumped right into working on that menu thing right away, as I basically knew everything I wanted to do and could spend most of my time in my text editor.

Doing the auto-generating thing was easy. The hard part (which I got to today) was writing the rest of the menu, which was the "About Hugo" and "How to Play Interactive Fiction" sections. Anyhow, I just finished working on it for today. Some of it needs to be completely rewritten; the current "About Hugo" page reads: Hugo is an interactive fiction authoring system written by Kent Tessman. It supports graphics and music!. The "What is interactive fiction?" page could use a lot of work, too, and honestly, everything probably needs some smoothing over.

Still, I'm pretty pleased with how it came out. You can take a look at it yourself by downloading the file at http://roody.gerynarsabode.org/notdead/colortest.hex. Inside the game, type "ABOUT".

The third option in the first menu is the auto-generated one. It has two groups of commands in there, based on the fact that colortext.hex was compiled with colorlib.h and cheaplib.h.

Anyhow, feel free to give me your thoughts or provide me with a nice, professional sounding "About Hugo" page or something. I should get all of the updated files uploaded in the next day or so. After that, it'll just be a matter of writing Hugo by Example pages that cover all of the new stuff.

Thursday, July 5, 2012

how suite it is

Of course, every time I look at one of my library extensions, I usually twiddle with this or that, so it's hard to promise that anything is done or complete (it'd help if my code was more foolproof). Just the same, I've got the "roodylib" library in a place that I'm happy with it. I wrote up some documentation and threw in some optional libraries in the form of "colorlib" and "cheaplib". I also included a roodylib-optimized shell file.

All in all, some aspects of "roodylib" are still too fiddly for my tastes, but oh well. I hope it's good enough that I can put it down for a while. Anyways, you can download the "roodylib suite" at http://roody.gerynarsabode.org/notdead/roodylib_suite.zip

Next library-related thing I'll do is that auto-generating help menu thing I talked about (which, unfortunately, will require an update to roodylib, I'm sure), but before that, I mean to actually work on game-writing for a little bit (game writing seems so much less fun sometimes).

Tuesday, July 3, 2012

init simplification / compression

The init routine in the "new shell" listed on Hugo by Example currently is as follows (actually, I took some comments out of it to make it even more readable here):
!:: Game Initialization routine
routine init
{

#ifset BETA
        if word[1] = "script"
                transcript_is_on = true
#endif
        word[1] = ""    ! clear word[1] in case of game restart
        MAX_SCORE = 0   ! ready to change for a scored game
        STATUSTYPE = 0  ! 0 = none :: 1 = score/turns :: 2 = time
        counter = -1    ! 1 step before first turn

        TEXTCOLOR = DEF_FOREGROUND
        BGCOLOR = DEF_BACKGROUND
        SL_TEXTCOLOR = DEF_SL_FOREGROUND
        SL_BGCOLOR = DEF_SL_BACKGROUND
        color TEXTCOLOR, BGCOLOR

        verbosity = 2

        display.title_caption = "<game title>"
! display.title_caption - used for GUI clients for title bar text.
        prompt = ">"
        window 0 ! resets the windows in case the player is restarting a game  
        cls      ! clear the screen, too

#ifset GLK
        glkcheck
#endif

        DEFAULT_FONT = PROP_ON
        Font(DEFAULT_FONT)

!:: Opening Text
        "Intro to game"
        print ""    ! For a blank line between the intro and the game title

        Font(BOLD_ON)
        "Game Title"
        Font(BOLD_OFF)
        "Game Blurb"
        print BANNER;

#if defined IFID  ! print the IFID, if there is one
        print IFID
#endif

        player = you
        location = STARTLOCATION
 
        move player to location
        old_location = location
        FindLight(location)
        DescribePlace(location)
        location is visited
        CalculateHolding(player)

#ifset USE_PLURAL_OBJECTS
        InitPluralObjects
#endif
}
 I've mentioned on here that I would also like to make init simpler, so authors new to Hugo can get to writing their games quicker (and are less likely to do something out of order, like trying to start a daemon before the location and player globals have been set). In one of my more recent test games, I got init down to this:
routine init
{
!: First Things First
SetGlobalsAndFillArrays
!: Screen clear section
SimpleIntro
InitScreen
!: Set up any special libraries
Init_Calls
!: Game opening
IntroText
MovePlayer(location)
}
 Of course, all of the same routines and lines of code are being run; they're just moved around into their respective routines. This is how I break it down:
  1. SetGlobalsAndFillArrays - This routine would reside nearby in the shell, as it requires game-specific information to be set.

    Example:
    routine SetGlobalsAndFillArrays
    {
    !\ Uncomment and modify this section if your game has scoring and ranking.
        MAX_SCORE = 50
        ranking[0] = "Amateur Adventurer"
        ranking[1] = "Competent Door-Unlocker"
        ranking[2] = "Bomb-Meddling Adventurer"
        ranking[3] = "Master Magic Wand Finder"
        ranking[4] = "The Genuine Article Sample Game Solver"
        MAX_RANK = 4  \!

        counter = -1                    ! 1 turn before turn 0

        STATUSTYPE = 1   ! 1 = score/turns, 2 = time, 3 = moves: score:
        TEXTCOLOR = DEF_FOREGROUND
        BGCOLOR = DEF_BACKGROUND
        SL_TEXTCOLOR = DEF_SL_FOREGROUND
        SL_BGCOLOR = DEF_SL_BACKGROUND
        prompt = ">"
        DEFAULT_FONT = PROP_ON
        player = you
        location = STARTLOCATION
    }
     
  2. SimpleIntro - A roodylib routine that prints some blank lines before a simple, non-glk game starts (sort of faking a clearscreen). This could be replaced if you wanted to do a cool logo like mentioned in another post.
  3. InitScreen - This is a screen clearing routine. The roodylib version has different behavior for simple, regular, and glk interpreters. It also sets the font and colors.
  4. Init_Calls - This automatically calls all library routines that need to be executed in init. I gave each library an object that goes into an init_instructions object. Init_Calls just checks for children of init_instructions and runs all applicable code.
  5. If any of the library routines print anything (like beta.h asking if the player would like to start a transcript), it returns a value telling Init_Calls to run InitScreen again so the screen is cleared before the "game proper" begins.
  6. Then, Intro_Text would be another "shell-side" routine. This is where the opening text of the game would go.
  7. MovePlayer automatically prints the location name and description.
All in all, I'm pretty happy with this system. I'm not sure if I'll recommend it for the "official shell", but I think I might distribute a "roodylib shell" with roodylib. The one other thing I'd possibly do is just add a dummy routine after Init_Calls so authors can just fill it with whatever other calls they want (even though they could conceivably add such routines to the end of SetGlobalsAndFillArrays).

Anyhow, I'm sort of conflicted about how I should handle this. On one hand, of course, I'm designing init so the author really has to change it as little as possible, but since that goes against init's traditional handling, I hope the new way isn't even more confusing. Ah well, time will tell, I guess.

Monday, July 2, 2012

updates

Today, I wrote that color-support extension I mentioned the other day. I don't remember if I mentioned it already, but I also threw together the optional "cheap mode" extension on Friday. Unfortunately, I was too lazy to write code in these libraries to support non-"roodylib" usage. I tried to keep non-roodylib support in my updates to the various libraries, but now it's all kind of a jumbled mess so I'm not even sure. I figure I'll give roodylib and the updated libraries their own page on HbE to quarantine them for a while.

Anyhow, after a day away this weekend, coming back to work on these things wasn't the rewarding challenge I was hoping it'd be, so I think I'm starting to get a little burnt out. I'll try to use my waning attention in the next couple days to organize and document what I've got so people can take a better look at it.

Next on the agenda (when I feel like working on the agenda) is:
  1. NewMenu, like the Menu routines it borrows from, looks for a default menu if not given a particular one. It doesn't come with an example menu, so in a way, the extension feels kind of like it's "shipping" a defective product. I was thinking it should come with a default menu that comes with three options. The first option would be general information about Hugo itself. The second one would a thing on general IF commands. The third one, though, would be the interesting page, as it'd write itself based on what libraries have been included. For instance, if my new cheaplib or colorlib libraries are included, it'd automatically inform players of the "COLORS ON" and "CHEAPMODE OFF" commands. Authors would be free to alter or replace the default menu completely, but there'd be a functional menu there without any effort.
  2. Another thing to consider is a better way to automate file inclusion.
  3. See if I can update my "newconverse" update to play nice with "roodylib" 
An issue to ponder-
One of the things that "roodylib" does that I am overly fond of involves the status bar. In glk, once the status window has been drawn, it is not possible to make it disappear with a "window 0". Often, when you restart a game, the status bar will show the last session's information until the first time PrintStatusLine is called (which may be a keypress or two away, depending on the length of the introductory text). Instead of trying to fix that by clearing the status bar at the beginning of the game- showing a blank bar- I thought it'd be cooler to write something up there. I wrote some code where if the constant GAME_TITLE is defined, it prints that. Otherwise it just prints "HUGO INTERACTIVE FICTION". The end result looks pretty sharp. In fact, if someone turns cheap mode on in a cheaplib-enabled game it just shows that all of the time.

So, that's all fine and dandy, but in a regular, non-cheap-mode session, "window 0" does work, and it looks kind of cool to have no status bar up until the first PrintStatusLine of the game hits you. Unfortunately, though, this can cause some problems if there is a long opening, as the start of the intro text gets all of the way to the top of the screen, and when we get to PrintStatusLine, the new status window can cause text corruption or cover the top of our intro text completely.

So, the question is, should even regular interpreters get the "HUGO INTERACTIVE FICTION"/GAME_TITLE window treatment just to avoid buffer/screen issues? I have not yet committed myself to an answer yet.