adv3Lite Scene not working

I am unable to get an adv3Lite Scene to work.

Harry the player character starts out in his bed. For that one appearance, I want the descriptive text for the Room (his bedroom) to focus on Harry waking up. Then, once he’s out of bed, I want the descriptive text to just tell about the room.

So I have defined the Room to have specialDesc text that is to be used only when the introScene is happening…

harrysBedroom: Room '<font color=green>Harry\'s Bedroom</font>' 'bedroom' "To the west was a door to the bathroom, to the east the living room." specialDesc = "Harry's eyes opened with difficulty. They were red, dry and nearly glued shut with hangover-induced gunk." useSpecialDesc = (introScene.isHappening) ;

The introScene is to start when Harry is in bed and end when he is no longer in bed…

introScene: Scene startsWhen = (harry.isIn(harrysBed)) endsWhen = (!harry.isIn(harrysBed)) whenStarting() { "Intro is starting."; } ;

He’ll never be allowed to get back into the bed, so the wake-up text should only appear once. The text defined in the whenStarting() method is just marker text for my benefit during development, just an indicator that the scene is underway.

The game begins with Harry in bed…

// harry, main character harry: Actor 'Harry;;man' @harrysBed "" contType = Carrier globalParamName = 'harry' isFixed = true isHim = true isInitState = true ownsContents = true person = 3 proper = true ;

But the introScene never kicks in…

No indicator text, and the specialDesc text is never displayed.

What am I doing wrong? Is it that Harry never explicitly gets into bed, but rather is there when the game begins? Do I need to explicitly trigger the startsWhen property?

Here’s the complete source…

[code]#charset “us-ascii”

#include <tads.h>
#include “advlite.h”

versionInfo: GameID
IFID = ‘47ca87f1-2d0e-4b54-a776-2bc128e30927’
name = ‘TADS 3 Lite Test Bed’
byline = ‘by Jerry Ford’
htmlByline = ‘by
Jerry Ford

version = ‘1’
authorEmail = ‘Jerry Ford jerry.o.ford@gmail.com
desc = ‘Test bed for experimenting with TADS 3 Lite.’
htmlDesc = ‘Test bed for experimenting with TADS 3 Lite.’
;

gameMain: GameMainDef
initialPlayerChar = harry
;

// harry, main character
harry: Actor ‘Harry;;man’ @harrysBed
“”
contType = Carrier
globalParamName = ‘harry’
isFixed = true
isHim = true
isInitState = true
ownsContents = true
person = 3
proper = true
;

harrysBedroom: Room
‘Harry's Bedroom’ ‘bedroom’
“To the west was a door to the bathroom, to the east the living room.”
specialDesc = “Harry’s eyes opened with difficulty. They were red, dry
and nearly glued shut with hangover-induced gunk.”
useSpecialDesc = (introScene.isHappening)
;

  • harrysBed: Thing, Container ‘bed;;bed’
    “Harry’s Bed”
    ;

introScene: Scene
startsWhen = (harry.isIn(harrysBed))
endsWhen = (!harry.isIn(harrysBed))
whenStarting()
{
“Intro is starting.”;
}
;
[/code]

There’s a few problems with your code here.

  1. You can’t use specialDesc the way you’re trying to do here. Defining specialDesc on a Room is completely meaningless. The purpose of specialDesc is to give items within a Room their own paragraph in a listing of objects within a room (just as in adv3). There are no circumstances under which the specialDesc of a Room would ever be displayed, since that’s not what it’s for.

  2. Even if specialDesc did work as you thought it would, it wouldn’t be a good approach here, since you’d see it on every turn Harry remained in bed, whereas you’d presumably only want to see it once. (I appreciate this is only a test bed game, but I thought it worth pointing out, nonetheless). In reality, then, you’d probably want to write something like:

harrysBedroom: Room
    '<font color=green>Harry\'s Bedroom</font>' 'bedroom'
    "To the west was a door to the bathroom, to the east the living room.
    <<first time>>\bHarry's eyes opened with difficulty. They were red, dry and
    nearly glued shut with hangover-induced gunk. <<only>>"       
;
  1. The problem with the scene is more subtle. This is that the Scene-changing mechanism runs at the end of every turn, so it only checks the whenStarting condition at the end of the first turn. If you type WAIT (or Z) on the first turn, you’ll see what I mean. This is really only a problem if you either want a scene to be active when the game starts or become active at the start of the first turn. If you want the Scene to start out active, you could define isHappening = true and startedAt = 0 on the Scene object, like this:
introScene: Scene   
    endsWhen = (!harry.isIn(harrysBed))
   
    
    whenEnding()
    {
        "Harry stretches and yawns, before staggering uncertainly across the
        room. ";
    }
    
    isHappening = true
    startedAt = 0
;

Alternatively, if you want the Scene to become active at the start of the first turn you could call sceneManager.doScenes() just after showing the room description, something like this:

harrysBedroom: Room
    '<font color=green>Harry\'s Bedroom</font>' 'bedroom'
    "To the west was a door to the bathroom, to the east the living room.
    <<first time>><<sceneManager.doScenes()>><<only>>"       
;

With this type of coding pattern your code would become:

harrysBedroom: Room
    '<font color=green>Harry\'s Bedroom</font>' 'bedroom'
    "To the west was a door to the bathroom, to the east the living room.
    <<first time>><<sceneManager.doScenes()>><<only>>"       
;

+ harrysBed: Thing, Container 'bed;;bed'
    "Harry's Bed"
    
    dobjFor(GetOff) asDobjFor(GetOutOf)
;

introScene: Scene
    startsWhen = (harry.isIn(harrysBed))
    endsWhen = (!harry.isIn(harrysBed))
    whenStarting()
    {
        "\bHarry's eyes opened with difficulty. They were
        red, dry and nearly glued shut with hangover-induced gunk. ";
    }
    
    whenEnding()
    {
        "Harry stretches and yawns, before staggering uncertainly across the
        room. ";
    }
    
;

Or alternatively, and I think preferably:

harrysBedroom: Room
    '<font color=green>Harry\'s Bedroom</font>' 'bedroom'
    "To the west was a door to the bathroom, to the east the living room.
    <<first time>>\bHarry's eyes opened with difficulty. They were red, dry and
    nearly glued shut with hangover-induced gunk. <<only>>"       
;

+ harrysBed: Thing, Container 'bed;;bed'
    "Harry's Bed"
    
    dobjFor(GetOff) asDobjFor(GetOutOf)
;

introScene: Scene
    startsWhen = (harry.isIn(harrysBed))
    endsWhen = (!harry.isIn(harrysBed))
    
    
    whenEnding()
    {
        "Harry stretches and yawns, before staggering uncertainly across the
        room. ";
    }
    
    isHappening = true
    startedAt = 0
;

Note that I’ve also added dobjFor(GetOff) asDobjFor(GetOutOf) to the definition of the Bed object, since people might quite reasonably type GET OFF BED and that should work the same as GET OUT OF BED.

For the next release (which should be quite soon), I’ll tweak the sceneManager so that it also checks for Scenes whose startsWhen conditions are true at the start of play, so that they start out happening, since this is probably more intuitive behaviour. Note that this change will mean that the whenStarting methods of any such scenes will be executed before the initial room description is displayed, which may or may not be what you want.

If you want to try out this alteration, simply located the sceneManager object in scenes.t and add the following line at the end of its execute() method:

doScenes();

Eric:

Thanks. With your suggestions in place, it is working, though I’m still tinkering with the details.

I think I like using the scene rather than the <>…<> structure because when I do it without the scene, the game window opens with the character’s location shown a title bar in a gray banner which is followed immediately in the game window by the same text…

If I use a scene, the descriptive text is shown ahead of the location-dentifier text in the window…

I just think it looks nicer with the two location identifiers separated by some intervening text. But, as noted, I’m still tinkering, still getting a feel for what can, and should, be done.

However, I believe there is a bug in the doScene() rendering.

When I try to use a message substitution parameter in the text defined in the scene block, it does not work…

introScene: Scene startsWhen = (harry.isIn(harrysBed)) endsWhen = (!harry.isIn(harrysBed)) whenStarting() { "{the subj harry} woke up hard---eyes red and dry, glued shut by the dried up gunk induced by too much drink and too little sleep."; } ;

…while the same substitution in the Room code block…

harrysBedroom: Room '<font color=green>Harry\'s Bedroom</font>' 'bedroom' "{the subj harry} tentatively twitched a leg, then an arm, his muscles protesting at the movement." ;

…does work. Here’s the display text with both of those substitutions in place…

This is a timing issue, which only occurs because the scene is starting before the first turn. The problem is that it’s executing before the library has set the function to use for outputting double-quoted strings (via a call to t3SetSay()), so the double-quoted string in the whenStarting() method is being processed before the library knows it’s meant to pass strings through the message-substitution filter.

The fix, which I’ve now applied to my copy, so it’ll be in the version 0.8 update, is to add the following property definition to the sceneManager object:

execBeforeMe = [adv3LibInit]

This will ensure that the adv3LibInit object, which calls t3SetSay(), is executed before the sceneManager does its stuff.

I have been tinkering with the fix you implemented for starting a game with a scene in play, and it works. To a degree. As you suggested…

…there are some unintended consequences.

When I start the game with a scene in play, text defined in whenStarting() is the very first thing displayed in the game window. For a while, that worked out well, and I adjusted my text to go with it. Then I decided to add a showIntro() method.

Now the game window starts with the whenStarting() text, then displays the showIntro() text, then the room name and description…

Back to the drawing board, I guess. I’ll forgo the opening scene. The reason I wanted it was to separate the banner text, which reads…

Bedroom

…from the room label, which resulted in…

Bedroom
Bedroom

That’s no longer the case; it’s now…

Bedroom
showIntro text
Bedroom

…which is what I wanted to begin with.

Jerry

If you’re displaying text in showIntro() then there’s indeed little point in displaying other text in whenStarting() as well. As you suggest, it’s much easier simply to display all the text you want to appear before the first room description in your showIntro() method.

The reasons you (or people in general) might want to have a scene active right at the start of play are:

  1. To make use of its eachTurn() method.
  2. To make use of its isHappening method in a condition in some other part of your code.
  3. To make use of it in a during condition on a Doer.
  4. To make something happen when the scene ends.

Note that you could also use an initially active scene to display text after the first room description but just before the first command prompt with a coding pattern like this:

introScene: Scene
    startsWhen = (harry.isIn(harrysBed))
    endsWhen = (!harry.isIn(harrysBed))    
    
    whenEnding()
    {
        "Harry stretches and yawns, before staggering uncertainly across the
        room. ";
    }
   
    whenStarting()
    {
        new OneTimePromptDaemon(self, &groan);
    }
    
    groan = "Harry groans. "
;