gameMain - Starting Game - TADS3.1

A short time back, I submitted a post about starting a new game. I would like to show the introduction text with a pause at the end that waits for the space bar. I want neither the status bar nor the first room to be shown until the pause is cancelled. I received previous suggested ways to go about this but now I can’t get either suggestion to work. Is it because I’m now using TADS3.1?

I sure could use further help with this.

RonG

No, the relevant behavior hasn’t changed in 3.1. Can you post your gameMain code?

Here’s The code but it is incomplete. I started the game code over because I had so many problems with the old one


 gameMain: GameMainDef
/* the initial player character is 'me' */
  initialPlayerChar = me
 
  scoreRankTable = 
  [ 
   [ 0, 'a tourist'], 
   [ 5, 'a novice explorer'], 
   [ 10, 'a willing amateur'], 
   [ 15, 'an apprentice adventurer'], 
   [ 25, 'an accomplished adventurer'], 
   [ 40, 'a hero'] 
  ] 
  maxScore = 43
 
  crueltyLevel = 3
 
/* show our introduction */
   showIntro()
   {
     /* show the prologue */
     "\bIt was a great dream until you were rudely awakened by the loud ringing
     of the telephone; which is the reason that you ended up here.....\b";

   //     /* show the game title */
   //     "<b>Return to Ditch Day</b>\n
   //     by Michael J.\ Roberts\n
   //     Release <<versionInfo.version>> (<<versionInfo.serialNum>>)
   //     \b";
    }

    /* show our "goodbye" message */
    showGoodbye()
    {
        "<.p>Thanks for playing <i>Return to Ditch Day</i>!\b";
    }
    
    /* 
     *   Start a new game.  Before we launch into the game, we show some
     *   startup options.
     *   
     *   I use this extra pre-game screen because I personally like getting
     *   the "administrative" tasks out of the way before actually getting
     *   into the narrative.  It's become something of a convention in IF
     *   to show you the introductory text first, and only then ask you to
     *   type ABOUT and CREDITS and so on to see a bunch of information
     *   about the mechanics of the game.  I don't like this because it
     *   totally blows my sense of immersion - reading the introduction
     *   gets me all mentally geared for getting into the story, and then
     *   just as I'm getting to the good part, the author goes and blows it
     *   with an explanation of how ASK ABOUT works.  So, we get this out
     *   of the way up front - we offer options to see the usual sundry
     *   game-mechanics stuff, or to restore a previous session.  After the
     *   player's satisfied with the administrative stuff, we start the
     *   game.  
     */
    newGame()
    {
        /* restore the global default settings */
        SettingsItem.restoreSettings(nil);

        /* starting a new session - show the startup options */
        switch(runStartupOptions())
        {
        case 1:
            /* 
             *   regular startup - show the introduction and run the main
             *   command loop 
             */

            /*
             *   Clear and initialize the normal game screen, including the
             *   status line, before we display any text.  This will help
             *   minimize redrawing - if we waited until after displaying
             *   some text, we might have to redraw some of the screen to
             *   rearrange things for the new screen area taken up by the
             *   status line, which could cause some visible redraw
             *   flashing on the display.  By setting up the status line
             *   first, we'll probably have less to redraw because we won't
             *   have anything on the screen yet when figuring the
             *   subwindow banner layout.  
             */
            initScreen(true);

            /* show the introduction */
            showIntro();
        
            

            /* run the game, showing the initial location description */
            runGame(true);
            break;

        case 2:
            /*
             *   We've just restored a saved game.  Simply go directly to
             *   the main command loop; there's no need to show the room
             *   description, since the RESTORE operation will already have
             *   done so. 
             */
            runGame(nil);
            break;

        case 3:
            /*
             *   we're quitting from the startup options - there's no need
             *   to run the game 
             */
            break;
        }

        /* show our 'goodbye' message */
        showGoodbye();
    }

    /*
     *   Run the "startup options."  The game invokes this routine before
     *   we actually start the game, to give the player some options on how
     *   they want to proceed.  The player can simply proceed directly to
     *   the game, can view background (ABOUT) information and/or
     *   introduction-to-IF instructions first, or can restore a previously
     *   saved game.
     *   
     *   This returns 1 if we're to start the game normally, 2 if we're to
     *   skip the introductory text (because we restored a saved game, for
     *   example), 3 if we're to quit immediately.
     *   
     *   We show these startup options immediately after the game program
     *   is launched, before we show the story's introduction.
     */
    runStartupOptions()
    {
        /* 
         *   if we don't need to run the startup options, just continue
         *   into normal game startup 
         */
        if (!sessionInfo.showStartupOptions)
            return 1;

        /* 
         *   We won't need to show startup options again should we find
         *   ourselves back here at some point.  In particular, we'll
         *   return to the main() routine if the player enters the RESTART
         *   command; but we won't want to go through these options again,
         *   since RESTART should take us back to the start of the story,
         *   not this meta-game launch stuff.  So, indicate in our
         *   transient session information that we don't need to ask for
         *   startup options again during this session.  
         */
        sessionInfo.showStartupOptions = nil;

        /* show the title/author/version and startup options */
        "\b<b>The Magic Forest</b>
        \nRelease <<versionInfo.version>> (<<versionInfo.serialNum>>)
        \nCopyright &copy;2012 Ronald J.\ Gaudet
        / Freeware / Type <<aHref('copyright', 'COPYRIGHT')>> for details\n
        
        <.p>If this is your first time playing this game, please type
        <<aHref('about', 'ABOUT')>> (or just 'A') for some important
        information.  To restore a position you saved earlier, type
        <<aHref('restore', 'RESTORE')>> (or 'R').
        <.p>To <<aHref('', 'begin the game')>>, just press the Enter key. ";

        /* keep going as long as they want to stay here */
        for (;;)
        {
            local cmd;
            local kw;
            local rqArg = nil;
            
            "\b&gt;";
            cmd = inputManager.getInputLine(nil, nil);

            /* check the various allowed commands */
            if (rexMatch('<space>*$', cmd) != nil)
            {
                /* blank line - we're ready to begin the game */
                return 1;
            }
            
            /* check for a keyword */
            if (rexMatch('<space>*(<alpha>+)<space>*$', cmd) != nil)
            {
                /* get the keyword */
                kw = rexGroup(1)[3].toLower();
            }
            else if (rexMatch(
                /*
                 *   This is a little tricky: we match spaces, then RQ or
                 *   REPLAY, then spaces, then a quoted string.  The string
                 *   starts with either a single or double quote, and now
                 *   comes the tricky part: we match any number of
                 *   arbitrary characters, but we use a "negative
                 *   assertion" (that's the "(?!)" group) that says that
                 *   each of those arbitrary characters can't be the open
                 *   quote, which we marked with parens as group #2.
                 *   Finally, we can optionally match the open quote
                 *   character again as a matching close quote, but we
                 *   don't require it.  Then we accept spaces, and then the
                 *   string has to end.  
                 */
                '<space>*(rq|replay)'
                + '<space>+([\'"])(((?!%2).)+)%2?<space>*$', cmd) != nil)
            {
                /* get the keyword */
                kw = rexGroup(1)[3];

                /* get the argument */
                rqArg = rexGroup(3)[3];
            }
            else
            {
                /* there's no keyword - use a string we know we won't match */
                kw = ' ';
            }

            /* check which keyword we got */
            if ('about'.startsWith(kw))
            {
                /* they want the ABOUT information */
                versionInfo.showAbout();
            }
            else if ('restore'.startsWith(kw))
            {
                /* try restoring a game */
                if (RestoreAction.askAndRestore())
                {
                    /* we succeeded - proceed directly to the game */
                    return 2;
                }
            }
            else if ('quit'.startsWith(kw))
            {
                /* do they really want to quit? */
                libMessages.confirmQuit();
                if (yesOrNo())
                    return 3;
                else
                    "Okay. ";
            }
            else if ('hints'.startsWith(kw))
            {
                /* there's no point in showing hints yet; explain this */
                "Sorry, no hints are available right now.  Hints will be
                available as soon as you start the game. ";
            }
            else if ('instructions'.startsWith(kw))
            {
                /* show the instructions */
                InstructionsAction.execSystemAction();
            }
            else if ('copyright'.startsWith(kw))
            {
                /* show the copyright/license information */
                versionInfo.showCopyright();
            }
            else if (kw == 'rq' || 'replay'.startsWith(kw))
            {
                /* if there's no argument, ask for one */
                if (rqArg == nil)
                {
                    /* there's no file, so ask for one */
                    local result = inputFile(
                        'Enter command file', InFileOpen, FileTypeCmd, 0);
                    
                    /* if we got a file, it's the file argument */
                    if (result[1] == InFileSuccess)
                        rqArg = result[2];
                }
                
                /* if we got a file, open it and start the game */
                if (rqArg != nil)
                {
                    /* read from the file */
                    setScriptFile(rqArg, kw == 'rq' ? ScriptFileQuiet : 0);
                    
                    /* go start the game */
                    return 1;
                }
            }
            
            /* refresh them on what to do next */
            "\b(Please type <<aHref('about', 'ABOUT')>> for notes on
            how to play, or <<aHref('restore', 'RESTORE')>> to restore
            a saved position.  To <<aHref('', 'begin the game')>>, just
            press the Enter key.) ";
        }
    }
;


/*
 *   Session information.  This is a transient object with some
 *   miscellaneous information about the gaming session.  It's
 *   transient because we want it to reflect the *session*
 *   status, which means we don't want it affected by things like
 *   Save, Restore, Undo, and Restart.  
 */
transient sessionInfo: object
    /* do we still need to show the startup options? */
    showStartupOptions = true
;



/* ------------------------------------------------------------------------ */
/* 
 *   An invisible COPYRIGHT finish-game option.  We provide this as an
 *   invisible option because we want to allow it (it's mentioned in the
 *   CREDITS message), but we don't want to clutter the prompt list with
 *   it. 
 */
finishOptionCopyright: FinishOption
    doOption()
    {
        /* just show the copyright message */
        versionInfo.showCopyright();

        /* ask for another option */
        return true;
    }

    responseKeyword = 'copyright'

    /* don't list the option in the prompt */
    isListed = nil
;

/* ------------------------------------------------------------------------ */
/*
 *   Initialize the screen.  This clears the screen and optionally sets up
 *   the status line. 
 */
initScreen(showStat)
{
    /* clear the screen */
    cls();

    /* show the status line immediately if desired */
    if (showStat)
        statusLine.showStatusLine();
}
;
     
/* Define help command. *******************************************************/ 
DefineSystemAction(Help)
execSystemAction () { helpText.showtext; }
;
VerbRule (Help)
 'help'
 : HelpAction
 verbPhrase = 'help/helping'
;
helpText: object
 showtext {
  "This is the help text. ";
 }
;

This is code taken from RTDD, which I am modifying because I like it. It compiles and runs with no problems as it is right now.

RonG

Your code works for me. It seems to do what you’re describing … it waits for a Return key before opening up the first room and displaying the status bar.

I get a couple of warnings on compilation, telling me that serialNum and showCopyright are not defined, but I assume you’ve defined those in your versionInfo object.

So what exactly is the problem you’re having?

Those two compile warnings are indeed taken care of in another part of the code. I can send the whole game source code if you’d like. The whole source, right now, is not much longer than what I already sent. What I’m trying to do is listed in order:

  1. When the game actually starts, I want the player to receive a telephone call. In this call, the goals of the game will be broadly explained and the game will stop; waiting for the space bar.

  2. The game will then show the ‘start game’ screen that you see. If the options on that screen are bypassed then another piece of text will be shown and will wait for another space bar.
    .

  3. At this point, the player when be at the first room and the game proper will have begun.

All this stuff is really not a ‘problem’. It’s just the way I’d like everything to get going.

Have you read “Some Common Input/Output Issues” in the Technical Manual? That should give you the tools you need. (I’ve never actually tried pausing for more, so I can’t supply the details.)

At a higher level, I would suggest that perhaps you’d find it productive to leave this particular coding conundrum for later. In the process of developing a working game, you’ll learn a lot (perhaps more than you want to know!) about TADS programming. This will make it much easier to go back and tidy up things that mystified you when you first stumbled over them.

That has been my experience, anyway.

I think it’s pretty easy to get discouraged when something in a project isn’t going your way and you can’t figure out why. I find it useful to set those problems aside, whatever they happen to be at the moment, and work on things that I can deal with. That way, I keep my momentum going.

I have to agree with everything you’ve said. My huge problem is that once I decide to do something I find it almost impossible to set it aside. But, I’m going to do that for now and start working on the player coding and some of the rooms.

Thanks for your thoughts.

Rong