Vault of Hugo II

This game was written for the PAX East 2011 Speed-IF “competition.” It took four or five hours to write, as the first several hours of the competition were used just to come up with a game idea.

Notes About the Design From The Author

I did not use every topic. Originally, I was going to put Marius Müller in there and use my altered version of Christopher Tate’s converse.h library contribution to talk to him, but when I realized how little time I had to implement what I wanted, I dropped that idea and did not replace it with an easier idea. I wanted to include “Alewife” by mentioning Community’s Dan Harmon, who used to be a member of a comedy troupe called the Dead Alewives and maybe say something about how “Braintree” always makes me think about headcrabs. “Chicken fingers” was omitted when the topic list was first relayed to me (I missed the start of the Speed-IF) so in my mind, it was not canon. So yeah, due to time constraints and what not, I did not do all of those things.

I ended up using Kent Tessman’s SuperContainer contribution since I had a desk that I wanted people to put stuff both on and in, although my final game ended up having so few items to hold that it was most-likely unnecessary (especially since I don’t think I gave the desk a capacity property so people couldn’t actually put things into it). I also made the floor in one of the rooms a SuperContainer since there was a compartment in it that people could put stuff in. All poorly coded.

I used my replacement PrintStatusLine routine since I like having the SCORE / MOVES look nice, but then I ended up turning SCORE / MOVES off since I didn’t want to come up with ranks. Oops!

The title, of course, is a nod to Hugo’s sample game, The Vault of Hugo.

In Retrospect

First off, I should have done a better job describing the typewriter. Having written the game just before (and during) the IF Demo Fair, I took for granted that all players would be familiar with the Automatypewriter, an electronic typewriter that was programmed to play Zork (the automatypewriter at PAX East 2011 was actually even more impressive; it was a 100 year old typewriter rigged up to do the same thing with a newly written IF game). I didn’t make it clear in the game that this typewriter plays IF games.

As glad as I am to have figured out how to use parse$ to capture words between quotes (and then using StringDictCompare), despite trying to direct players to TYPE "GAME COMMAND" ON TYPEWRITER, many would ignore the quotes and break my code. I should have also entered the exact commands into the verb grammar to allow for not-quoted commands, especially since my in-game typewriter accepts such a limited number of commands.

Yeah, spell-checking.

I also forgot to give the desk the quiet property so it lists its contents twice.

Lastly, while I included some ways to intentionally detonate the landmine, I missed many, including hitting. Oh well.

All in all, it was my first reasonably short Speed-IF so I was glad to have finished a game!

The Code Itself

!::
! New Game (Shell)
!
!:: Flags
!#set HUGOFIX             ! Compile with HugoFix Debugging Library commands available (type $? in game)
!#set HDX                 ! Compile as Hugo Debuggable Executable (see below for details)
!#set PRECOMPILED_LIBRARY ! Use a precompiled header library (see manual)
!#set VERBSTUBS           ! Include the grammar and routines from verbstubs.g and verbstubs.h, respectively
!#set USE_ATTACHABLES     ! Use attachable items
!#set USE_PLURAL_OBJECTS  ! Use plural objects
!#set USE_VEHICLES        ! Use vehicle objects
!#set NO_AUX_MATH         ! No advanced math needed
!#set NO_FONTS            ! Don't use font effects
!#set NO_FUSES            ! Don't use fuses
!#set NO_MENUS            ! Don't use menus
!#set NO_RECORDING        ! Don't allow transcripts
!#set NO_SCRIPTS          ! Don't use character scripts
!#set NO_STRING_ARRAYS    ! Don't use string arrays
!#set NO_VERBS            ! Don't use any standard verbs
!#set NO_XVERBS           ! Don't use any standard "out-of-world" verbs


!:: switches              ! example how one can add compiler switches to source
!#switches -ls            ! print compilation stats to .LST file

#ifset HUGOFIX
#set DEBUG
#endif

#ifset HDX
#switches -d              ! if the -d switch is not set in the compiler itself, #set HDX will produce
                          ! a Hugo Debuggable Executable (.HDX) with extension .HEX
#endif                    ! Sneaky!

!:: Constants and globals  (some constants must be set before hugolib is included)
!constant AFTER_PERIOD " "     ! include one space after full stops (as opposed to two)
!constant INDENT_SIZE 0        ! no indentation in room descriptions and room content listings
constant IFID "put-IFID here"

!:: Includes (grammar must come first)
! put your new grammar here
verb "push","pull"
    * object            DoMove
verb "clean","vacuum"
    * object            DoVacuum
verb "load"
    * typewriter            DoPaper
    * typewriter "with" "paper"     DoPaper
    * paper "in"/"into" "typewriter" DoPaper
verb "type"
    * string            DoType
    * string "on"/"into"/"in" typewriter DoType
verb "step","stand"
    * "on" landmine         DoStepOn
verb "depress"
    * object            DoMove
verb "scrape"
    * "parrot"          DoScrape
! new grammar needs to be defined before the including verblib
#include "verblib.g"    ! Verb Library

#ifset PRECOMPILED_LIBRARY
#link "hugolib.hlb"     ! Your Precompiled Library
#else
#include "hugolib.h"    ! Standard Hugo Library
#endif
#include "contain.h"

!:: Game Initialization routine
routine init
{
        STATUSTYPE = 0  ! 0 = none :: 1 = score/turns :: 2 = time
        counter = -1    ! 1 step before first turn
!       If STATUSTYPE = 2 (time), counter is minutes since midnight, so a game that starts at 3 pm
!       should have:
!       counter = 899
!       (900 minutes minus the one minute the main routine will add on the first turn)
        TEXTCOLOR = DEF_FOREGROUND
        BGCOLOR = DEF_BACKGROUND
        SL_TEXTCOLOR = DEF_SL_FOREGROUND
        SL_BGCOLOR = DEF_SL_BACKGROUND
        color TEXTCOLOR, BGCOLOR

        verbosity = 2   ! 1 = normal (rooms described only if not previously
                        !     described)
                        ! 2 = full (rooms described every time they are entered)

        display.title_caption = "Vault of Hugo II: Electric Boogaloo"  ! used for GUI clients for title bar text.
        prompt = ">"

        window 0 ! resets the windows in case the player is restarting a game
        cls

        DEFAULT_FONT = PROP_ON
        Font(DEFAULT_FONT)

        !:: Opening Text
        "The future's not what it's cracked up to be! Jetpacks and joybooths are cool and all,
     but you've always had a special place in your heart for history and its artefacts- so
     much that it was long ago that you decided you wanted to be a roguish space pirate
     (way before it was considered cool, in fact).\n"
     "Among the many who had heard the tale of a fabled lost museum devoted to interactive
     fiction, you alone thought the myth was rooted in truth. Perseverence paid off, though,
     and by golly, you found it. Tragicly, you lost your cohorts
    Jim and Kevin to an ill-considered mining
      expedition to Pluto, so you are embarking on this adventure alone.
      You have already ransacked the other wings of the museum. The one thing left
      to do is to crack the..."
        print ""    ! For a blank line between the intro and the game title

        Font(BOLD_ON)
        "Vault of Hugo II: Electric Boogaloo"
        Font(BOLD_OFF)
        "An Interactive Scavenging by Roody Yogurt"
        print BANNER;
        #ifset HUGOFIX
        print " (Now with HugoFix Technology TM!)"
        #else
        print ""
        #endif
 !       print IFID

        player = you
        location = STARTLOCATION

        move player to location
    MoveOnto(desk,typewriter)
    MoveOnto(desk,output)
    MoveInto(desk,paper)
    move landmine to player
        old_location = location
        FindLight(location)
        DescribePlace(location)
        location is visited
        CalculateHolding(player)

        #ifset USE_PLURAL_OBJECTS
        InitPluralObjects
        #endif
}

!:: Main game loop
#ifset PRECOMPILED_LIBRARY
replace main
{
#else
routine main
{
#endif
        counter = counter + 1
        PrintStatusLine
        run location.each_turn
        runevents
        RunScripts
        if speaking not in location
                speaking = 0
}

player_character you "you"
{
    long_desc
        "You are rugged and roguish and space-pirate-tastic."
    before
    {
        actor
        {
            if parent(object).type = SuperContainer
            {
                if Inlist(parent(object), contents_in, object) and
                    parent(object) is not open
                {
                    print capital player.pronoun #1;
                    MatchPlural(player, "doesn't", "don't")
                    " see that."
                    return true
                }
            }
            return false
        }
    }
}

room STARTLOCATION "The Hugo Wing"
{
    long_desc
        {
        if desk not in STARTLOCATION
            {
            "Oh, the humanity! The desk and awesomatic-typewriter have been
             blown to a better place. Luckily, though, the Hugo Vault door
             is left hanging on its hinges, leaving the exit north unblocked."
            }
        else
        "This place is pretty amazing. Of course, your attention is mainly
         drawn to the north, where the big Hugo Vault Door keep you from
         its treasures. Also somewhat neat is the desk near it. You came from
         the east, but there was a cave-in just moments ago, trapping you.
         Luckily, there seems to be a room past a tight squeeze to the
         southwest."
         }
    n_to    {
        if desk in STARTLOCATION
            {
            "The massive Hugo Vault door blocks your progress."
            }
        else
            {
            "Whistling a happy tune, you walk though the smoking debris,
             onward to happiness and success and more effective roguishness!"
             endflag = 1
             }
        }
    sw_to   {
        if child(player) ~= 0
            "You'd never make that squeeze while carrying anything!"
        else
            {
            "It's a tight fit, but you make it, finding yourself in..."
            return tomb
            }
        }
    e_to    {
        "The way back to the ALAN Wing has been blocked by a cave-in.
        Those plaques written in Comic Sans are inaccessible to you for now."
        }
}

replace PrintStatusline
{
    if display.linelength < 80
        display.statusline_height = 2
    else
        display.statusline_height = 1

    Font(BOLD_OFF | ITALIC_OFF | UNDERLINE_OFF | PROP_OFF)
    window display.statusline_height
    {
        color SL_TEXTCOLOR, SL_BGCOLOR
        cls
        locate 1, 1
        if not location
            print "_";
        elseif not light_source
            print "In the dark";
        else
        {
            if FORMAT & DESCFORM_F:  print "_";
            print capital location.name;
        }

        if display.statusline_height = 1
! The part we're changing
!           print to 65;
! Ok, let's begin writing to array "_temp_string"
! _temp_string is an array declared by the library if NO_STRING_ARRAYS is not set
                        {
                        text to _temp_string
                if STATUSTYPE = 1
                    print number score; " / "; number counter;
                elseif STATUSTYPE = 2
                    print HoursMinutes(counter);
            text to 0
! Ok, we've closed off the string array
! Now, let's move to the end of the screen MINUS the length of the _temp_string array
! plus two extra spaces for good measure (so there's a little space to the right on the status bar)
            print to (display.screenwidth - (StringLength(_temp_string) + 2));
                        }
        else
        {
            locate 1, 2
            if FORMAT & DESCFORM_F:  print "_";
        }

        if STATUSTYPE = 1
            print number score; " / "; number counter;
        elseif STATUSTYPE = 2
            print HoursMinutes(counter);
    }
    color TEXTCOLOR, BGCOLOR
    Font(DEFAULT_FONT)
}

object vault "vault door"
{
    article "the"
    in STARTLOCATION
    adjective "vault","giant","huge"
    noun "vault","door"
    long_desc
        {
        if desk in STARTLOCATION
            "This thing is the real deal. There's no way you're getting this bad boy open
             without some serious firepower."
        else
            "Oh, it is a Hugo shell of its former self, but it was for the greater good."
        }
    before
        {
        object DoEnter
            {
            Perform(&DoGo,n_obj)
            }
        }
    is static, hidden, enterable
}

SuperContainer desk "desk"
{
    article "the"
    noun "desk"
    in STARTLOCATION
    long_desc
        "This is quite a sturdy work desk. On top of it is a typewriter, and behind
        the typewriter is an output tray for sheets of paper to fall into."
    is static, openable, hidden
}

object drawers "drawers"
{
    article "some"
    noun "drawers"
    part_of desk
    before
        {
        object DoOpen
            {
            Perform(&DoOpen,desk)
            }
        object DoClose
            {
            Perform(&DoClose,desk)
            }
        }
    is openable, hidden
}

object typewriter "100 year old awesomatic-typewriter"
{
    article "the"
    adjective "100","year","old","awesomatic"
    noun "automatypewriter","typewriter","awesomatic-typewriter","typewriter"
    long_desc
        "Unbelievable! Everybody remembers the \"automatypewriter\" that
         predates this one, but not many remember the Awesomatic-Typewriter that
         came much later, playing only Hugo games. This one seems to be in the
         middle of a game of \"Quest For Museum\" and is currently waiting for a
         command. If you feel up to the challenge, TYPE \"COMMAND\" ON TYPEWRITER."
    before
        {
        object DoGet,DoMove
            {
            "Either it's really heavy or bolted to the desk. You can't
            move it and are too lazy to investigate exactly why."
            }
        xobject DoPutIn
            {
            if object = landmine
                {
                "The landmine is much too thick to put in the typewriter."
                return true
                }
            else
            return false
            }
        }
}

object sheet "sheet of paper"
{
    article "a"
    adjective "sheet","of"
    noun "sheet","paper"
    long_desc
        "The paper in the awesomatic-typewriter has some printed text but not much."
    before
        {
        object DoGet
            {
            "Nah, then you'd just have to replace it with another piece of paper!."
            }
        }
    in typewriter
    is readable
}

object output "output tray"
{
    long_desc
        "The output tray seems more than capable of catching any 8 by 10 inch piece of paper
         that falls into it."
    article "an"
    adjective "output"
    noun "output","tray","bin"
    is static, container
    capacity 10
}


object paper "sheaf of paper"
{
    long_desc
        "Lots of sheets of Feather Light Brand Paper."
    article "a"
    adjective "sheaf","of"
    noun "sheaf","paper","sheets"
    before
        {
        object DoGet
            {
            if sheet in typewriter
                {
                "There is no need to grab more paper while the typewriter still has paper in it."
                return true
                }
            if infodump.tick
                {
                "The typewriter is still printing!"
                return true
                }
            "You grab a blank sheet of paper and load it up into the typewriter. It automatically
             prints a line of text and waits with a new prompt."
             move sheet to typewriter
             return true
             }
        object DoPutIn
            {
            if xobject = typewriter
                {
                if sheet in typewriter
                    {
                    "There is no need to grab more paper while the typewriter still has paper in it."
                    return true
                    }
                if infodump.tick
                {
                "The typewriter is still printing!"
                return true
                }
                "You grab a blank sheet of paper and load it up into the typewriter. It automatically
                 prints a line of text and waits with a new prompt."
                move sheet to typewriter
                 return true
                 }
             else
                return false
            }
        }
}

object landmine "landmine"
{
    article "a"
    adjective "land"
    noun "landmine","mine"
    long_desc
        "The only thing you have left- after using all of your good ordnance raiding this museum-
         is your trusty landmine.
         With its hair-trigger mechanism, it'll explode at a moment's notice. It may not
         be the safest kind of landmine to carry around on one's person, but hey, they are
         among the cheapest! It is roughly 8 by 10 inches in length and fires powerful
         shrapnel in all directions."
    size 9
    before
        {
        object DoStepOn
            {
            if parent(landmine)= STARTLOCATION
                {
                "Like a genius, you chortle to yourself and
                 hop onto the landmine."
                 endflag = 4
                 }
            else
                "The landmind ought to be on the floor."
                return true
            }
        object DoMove
            {
            if word[1] = "press","push"
                {
                "\"Gee, I wonder what this button does...\""
                endflag = 4
                }
            }
        }

}

object floor2 "floor"
{
    article "the"
    noun "floor"
    is static, hidden
    in STARTLOCATION
}

room tomb "The Tomb of the Unknown Tool"
{
    long_desc
        "What a weird place. Some graffiti lines the concrete walls, but the real
         star of the room is the little creepy coffin at its center. Also, did I
         mention that the floor is dusty?"
    after
        {
        location DoGo
            {
            if sheet in output
                {
                "/nNoticing a full sheet of game transcript in the output tray,
                 you roll it into a ball and throw it away- NEVER TO BE SEEN
                 AGAIN."
                 remove sheet
                 }
            }
        }
    ne_to   {
        if child(player) ~= 0
            "You'd never make that squeeze while carrying anything!"
        else
            {
            "It's a tight fit, but you make it, finding yourself in..."
            return STARTLOCATION
            }
        }
}

object coffin "coffin"
{
    article "the"
    adjective "little","creepy"
    noun "coffin","lid"
    long_desc
        {
        "Creepy! Little! Coffin! It is ";
        if self is open : "open." :  else : "closed."
        }
    in tomb
    before
        {
        object DoOpen
            {
            if self is not special
                {
                "Scary stuff! With great trepidation, you slowly
                open up the coffin's lid. Shockingly enough,
                the contents are revealed to be a hand vacuum
                (a dustbuster, ya know?). Somebody here had a sense of
                humor."
                self is special
                tomb.name = "The Tomb of the Known Tool"
                coffin is open
                dustbuster is known
                return true
                }
            else
            return false
            }
        }
    is static, container, openable, hidden
}

object dustbuster "dustbuster"
{
    article "a"
    adjective "hand"
    noun "dustbuster", "vacuum"
    long_desc
        "Whoa! It's a dustbuster just like in the Inform 6 classic, \"Death To My
         Enemies!\" You're pretty sure this particular model is hugely famous in
         Austria."
    in coffin
}

SuperContainer floor "floor"
{
    long_desc
        "What a horribly dirty floor! Where's the abandoned museum cleaning staff?"
    article "the"
    adjective "dusty"
    noun "floor","dust"
    before {
        object DoVacuum
            {
            if self is not special
                {
                if dustbuster is not known
                    {
                    "You have nothing to vacuum with!"
                    return true
                    }
                elseif FindObject(dustbuster,tomb) and parent(dustbuster) ~= player
                    {
                    "(Picking up the dustbuster first)"
                    move dustbuster to you
                    }
                "In a fit of dustbusting fever, you attack the dusty floor
                 with the dustbuster. Your efforts are rewarded by revealing
                 a trapdoor. Huzzah!"
                 move trapdoor to tomb
                 self is special
                 return true
                 }
            return false
            }
        }
    is static, hidden,open
    in tomb
}

object trapdoor "trapdoor"
{
    short_desc
        {
        "In the center of the floor is ";
        if self is open : "an open "; :  else : "a closed ";
        "trapdoor."
        }
    long_desc
        {
        "Wonder of wonders, a trapdoor! It is ";
        if self is open : "open.": else : "closed."
        }
    article "the"
    adjective "trap"
    noun "trapdoor","door"
    is static, openable, container
}

object cheat "game walkthrough"
{
    article "a"
    adjective "game"
    noun "walkthrough"
    long_desc
        "Somebody hid away this walkthrough for the game \"Quest
         For Museum.\" There are lots of little comments making snide
         remarks about the game itself. Interestingly, there's a note
         that the command >SCRAPE PARROT at any point results in the
         biggest infodump in the game."
    is readable
    in trapdoor
}

object graffiti "graffiti"
{
    noun "graffiti"
    in tomb
    long_desc
        "It reads, \"Don't you hate spelling 'graffiti' right in
        IF games???\""
    is static, hidden
}

routine DoVacuum
{
!  When I wrote this game, I did not understand what CheckReach is good for.
!  This is bad code and should be ignored.
    !if parent(dustbuster) = you
    !"The "; object.name;" is dust-busted!"
    if not CheckReach(dustbuster)
        {
        "You have nothing to vacuum with!"
        return true
        }
    elseif CheckReach(dustbuster) and parent(dustbuster) ~= player
        {
        "(Picking up the dustbuster first)"
        move dustbuster to you
        }
    if object = you
        "You are dust busted enough."
    elseif object = dustbuster
        "Wise guy, eh?"
    else
        print "The "; object.name; " is slightly more dust-busted."
    return true
}

routine DoPaper
{
    if CheckReach(paper)
        {
                    if sheet in typewriter
                    {
                    "There is no need to grab more paper while the typewriter still has paper in it."
                    return true
                    }
                if infodump.tick
                {
                "The typewriter is still printing!"
                return true
                }
                "You grab a blank sheet of paper and load it up into the typewriter. It automatically
                 prints a line of text and waits with a new prompt."
                move sheet to typewriter
                 return true
        }
    elseif sheet in typewriter
        {
        "The typewriter is already loaded."
        return true
        }
    "You see no paper here."
    return true
}

array command[20]

routine DoType
{
    if player in tomb
        {
        "There is nothing to type on here!"
        return true
        }
                elseif infodump.tick
                {
                "The typewriter is still printing!"
                return true
                }
    elseif sheet not in typewriter
        {
        "You'll have to load the typewriter up with some paper first."
        return true
        }
    string(command, parse$, 20)
    if StringDictCompare(command, "scrape parrot") = 0
        {
        Typewrite()
        return true
        }
    else
    "The awesomatic-typewriter prints a pithy response, leaving lots
     of blank sheet yet."
}

fuse infodump
{}

event infodump
{

        if not self.tick
            {
            event_flag= true
            if landmine in output and you in STARTLOCATION
                {
                "\nLike an idiot, you watch while the page
                 falls lightly onto the landmine."
                 endflag = 3
                 }
            elseif landmine in output and you in tomb
                {
                "\nBOOM! You hear a deafening explosion from the other room!"
                remove desk
                }
            elseif you in STARTLOCATION
                {
                "\nThe page finishes printing and falls into the output
                 tray without much fanfare. Uninterested with the result,
                 you instantly throw the paper away- NEVER TO BE SEEN AGAIN."
                 remove sheet
                 }
            else
                {
                move sheet to output
                }
            }
}

routine Typewrite
{

        "The awesomatic-typewriter springs to life, printing a giant screed
        filled with the author's views on politics, religion, and his complicated
        relationship with his mother. In fact, it still is printing!"
        Activate (infodump, 2)
}

replace PrintEndGame(end_type)
{
    Font(BOLD_ON)
    select end_type
        case 1:  print "\n*** HUGO GLORY IS YOURS! ***"
        case 2
        {
            if player_person = 2
                print "\n*** YOU HAVE DIED ***"
            else
                print "\n*** "; CThe(player); \
                    MatchPlural(player, "has", "have"); \
                    " died! ***"
        }
        case 3: print "\n*** SHRAPNEL IS NOT JUST AN IF GAME ***"
        case 4: print "\n*** KABOOM IS NOT JUST AN ATARI GAME ***"
    Font(BOLD_OFF)
    PrintScore(true)
}

routine DoStepOn
{}

routine DoScrape
{
    "This is life, man, not a game!"
    return true
}