#charset "us-ascii"
#include <advlite.h>

pterodactyl: Thing 'pterodactyl; fluffy winged large hungry; fluffikins reptile pterosaur'
    "The pterodactyl has a wide wingspan, a sharp beak, beady little eyes, and a
    coarse, scaly skin. It's busy wolfing down its meal. "
    specialDesc = "The pterodactyl is continuing its messy and unsavory meal. "
    dobjFor(Ride) {
        verify() {}
        check() {
            "You don\'t have a pilot\'s license. ";
        }
    }
;

// He will leap off the ledge as you leave. This can happen before or after you've given him
// the crystal ball and before or after you've told him about Bianca. Those things may need
// to happen later in the fortune teller's lair, in which case she might comment on them.

zarbolphung: Actor 'little man;; wizard; him'
    "{The zarbolphung} is frankly rather ugly and disagreeable-looking. He's no more than five feet tall,
    not counting the droopy pointed hat, and his shoulders are hunched forward. His
    hair is long, grayish, and not recently combed, but
    it's an inspired bit of fine grooming compared to his mustache, which is both grotesquely large
    and rather alarmingly filthy. 
    
    <.p> He's wearing a long gray robe --- not a bathrobe, fortunately --- whose hem nearly brushes
    the ground. The hem fails to conceal his feet, however. Not only are his feet bare, he
    is endowed (if that's the right word) with a strikingly large and gnarled complement of toes. "
    cannotTakeMsg = 'He might bite you. '
    cannotPutPersonMsg = 'That\'s unlikely to be a useful thing to do. '
    cannotEatMsg = 'You\'ve heard of food poisoning, right? '
    kissResponseMsg = 'The likely result would be that you\'d catch several diseases. '
    attackResponseMsg = 'The fiendish glint in his eye suggests that that may be a bad idea. '
    
    globalParamName = 'zarbolphung'
    giveName {
        proper = true;
        knownToBeWizard = true;
        replaceVocab ('Zarbolphung; ugly little (filthy) short disagreeable; man wizard sorceror; him');
    }
    smellDesc = "The pungent odor suggests that he may not have bathed since the end of the last century.
        Or maybe it's just the leftover reek of the pterodactyl. "
    shouldNotFeelMsg = "The likely result would be that you'd catch several diseases. "
    knownToBeWizard = nil

    ballReceived = nil
    marigoldsReceived = nil
    toeReceived = nil
    topReceived = nil
    paintbrushReceived = nil
    giltPaintReceived = nil
    pinkFolderReceived = nil
    blueFolderReceived = nil 
    
    // This next bit means he has given you the list of what he needs.
    itemsListed = nil
    listingItems() { itemsListed = true; }
    
    allReceived() {
        return (marigoldsReceived && toeReceived && topReceived
            && paintbrushReceived && giltPaintReceived && pinkFolderReceived && blueFolderReceived);
    }
    countNotReceived() {
        local cnt = 0;
        if (!marigoldsReceived) cnt++;
        if (!toeReceived) cnt++;
        if (!topReceived) cnt++;
        if (!paintbrushReceived) cnt++;
        if (!giltPaintReceived) cnt++;
        if (!pinkFolderReceived) cnt++;
        if (!blueFolderReceived) cnt++;
        // If the player has been using the hints, and has failed to ask
        // Z the right question, this next line will move the scenario forward
        // as if he had actually explained what he needed:
        if (cnt > 3) listingItems();
        return cnt;
    }
    countNotManaged() {
        local cnt = 0;
        if (!ballReceived) cnt++;
        if (!marigoldsReceived) cnt++;
        if (!toeReceived) cnt++;
        if (!topReceived) cnt++;
        if (!paintbrushReceived) cnt++;
        if (!giltPaintReceived) cnt++;
        if (!pinkFolderReceived) cnt++;
        if (!blueFolderReceived) cnt++;
        if (!mirrorBall.spinning) cnt++;
        if (ajou.getOutermostRoom != chartreuseCaboose) cnt++;
        if (bianca.getOutermostRoom != chartreuseCaboose) cnt++;
        if (!monkeys.readyToJam) cnt++;
        return cnt;
    }
    
    goToCaboose() {
        me.moveInto(chartreuseCaboose);
        zarbolphung.moveInto(chartreuseCaboose);
        "The wizard leads the way downstairs to the Chartreuse Caboose. As you arrive,
        he gazes around with interest. <q>Well, well,</q> he says.<.p> ";
        zarbolphung.setState(zWaiting);
        chartreuseCaboose.lookAroundWithin();
        if (zWaiting.checkComplete()) zWaiting.finalScene();
        else {
            "<q>It looks as if you still have one or two things to accomplish. But I'm
            in no hurry. I'll just wait here. ";
            if (bianca.getOutermostRoom() != chartreuseCaboose)
                "You'll need to bring the mannequin. ";
            if (ajou.getOutermostRoom() != chartreuseCaboose)
                "You'll need to bring the wooden soldier. ";
            if (!mirrorBall.spinning)
                "I see the mirror ball isn't spinning. ";
            if ((monkeys.getOutermostRoom() != chartreuseCaboose) || (!monkeys.talented))
                "I don't see a dance band. ";
            "When you've taken care of that, we'll be ready to go.</q> ";
            zWaiting.startGameEndDaemon();
        }
    }
    roofSimpleReceived() {
        if (!ballReceived)"First of all, you need
            to find my crystal ball and bring it to me. I\'m not going to lift a finger for you until
            you\'ve managed that. ";
        if (!marigoldsReceived) "You need to bring me a bunch of fresh-picked marigolds, that should be easy. ";
        if (!toeReceived) "I\'ll need the toe bone of a mummy. I think there\'s a mummy somewhere
            downstairs, but he\'s kind of evasive, so good luck with that.";
        if (!topReceived) "I\'ll need a little toy top --- you know, the kind that spins. ";
        if (!paintbrushReceived) "A paintbrush to paint magical symbols on the top. ";
        if (!giltPaintReceived) "I\'ll want some gold paint so I can paint magical symbols. ";
    }
    answerWhatsNeededQ() {
        if (countNotManaged == 0) {
            "<q>I think you\'ve accomplished absolutely everything.
            Really, that\'s remarkable. You\'re to be congratulated!</q> ";
            goToCaboose();
        }
        else {
            "<q>It\'s a good thing one of us is well organized,</q> he says. <q>What do you still
            need to do in order to bring this three-ring circus to a satisfactory conclusion?
            Hmm.</q><.p>
            He ticks off the items on his fingers. <q>";
            if (!ballReceived)"First of all, you need
            to find my crystal ball and bring it to me. I\'m not going to lift a finger for you until
                you\'ve managed that. ";
            if (!marigoldsReceived) "You need to bring me a bunch of marigolds. ";
            if (!toeReceived) "I\'ll need the toe bone of a mummy. ";
            if (!topReceived) "I\'ll need a little toy top --- you know, the kind that spins. ";
            if (!paintbrushReceived) "A paintbrush to paint magical symbols on the top. ";
            if (!giltPaintReceived) "I\'ll want some gold paint so I can paint magical symbols. ";
            if (!pinkFolderReceived && !blueFolderReceived) "You\'ll need to provide some forged
                identity papers for the mannequin and the wooden soldier. ";
            else {
                if (!pinkFolderReceived) "I\'ll want some forged identity papers for the mannequin. ";
                if (!blueFolderReceived) "I\'ll want some forged identity papers for the soldier. ";
            }
            if (!mirrorBall.spinning) "You\'ll have to get the mirror ball in the nightclub spinning. ";
            if (ajou.getOutermostRoom != chartreuseCaboose) "You\'ll need to bring the
                wooden soldier downstairs to the nightclub. ";
            if (bianca.getOutermostRoom != chartreuseCaboose) "The mannequin will have to be
                in the nightclub. ";
            if (!monkeys.readyToJam) "To get the happy couple dancing, you\'ll need to provide a
                dance band. ";
            "I think that\'s everything.</q> ";
        }
    }
    // The somewhat misnamed listStillNeeded is mainly to print out what you still need to
    // acquire. But that may be nothing at all, in which case we're ready for goToCaboose().
    // This could technically even happen up on the roof!
    listStillNeeded(obj) {
        if (allReceived && (curState == zFriendly))
        {
            "He nods in satisfaction. <q>Very good. That seems to be everything. And I hope you've
            got the mirrorball spinning, found a dance orchestra, and led the two of them to the
            nightclub. Shall we go?</q> He gestures to you to precede him.<.p> ";
            goToCaboose();
            return;
        }
        else if (curState == zGrumpy)
        {
            "<q>You've been busy,</q> the wizard says. <q>But until you've found my crystal ball,
            really I have no reason to assist you in your quest.</q> ";
            return;
        }
        // The meat of this method is to print a list of the stuff you haven't yet given him.
        // Bearing in mind, you may be just about to do so. Note that the gift itself will already
        // have been sent into nil by the GiveShow routine, so we don't need to do that here.
        "<q>Very good, very good,</q> he says<<if (obj)>>, taking <<obj.theName>> from you and tucking it away somewhere
        among the folds of his robe<<end>>. <q>You're making progress.";
        if (countNotReceived() < 5) {
            " Now, let's see --- what is it that
            you'll still need to bring me? ";
            if (!marigoldsReceived) "A bunch of marigolds. ";
            if (!toeReceived) "The toe bone of a mummy. ";
            if (!topReceived) "A toy top, suitable for spinning. ";
            if (!paintbrushReceived) "A fine-tipped paintbrush so I can paint symbols on the top. ";
            if (!giltPaintReceived) "A little bottle of gold paint. ";
            if (!pinkFolderReceived && !blueFolderReceived) "Some identity papers for our soon-to-be humans. ";
            else if (!pinkFolderReceived) "Some identity papers for the young lady. ";
            else if (!blueFolderReceived) "Some identity papers for the handsome soldier. ";
            "I think that's everything. I'm happy to assume you've managed to hire a dance band, lead them
            both to the nightclub, and set the
            mirror ball spinning, I have great confidence in you.";
        }
        "</q> ";
    }
    
    // When you empty the chow into the trough, here's what happens:
    appeared = nil
    appear() {
        // purely as a precaution:
        if (appeared) return;
        appeared = true;
        moveInto(ledgeSouth);
        pterodactyl.moveInto(ledgeSouth);
        pteroAch.awardPointsOnce();
        "For a few seconds after you empty the bag into the trough, it appears that you've accomplished
        nothing. But then you hear, far overhead, a heavy leathery flapping sound, accompanied by a harsh
        <i>scrawkk!</i> Shading your eyes, you look up into the sky. Sure enough, something large, dark,
        and winged is spiraling down toward you.
        
        <.p>You take a precautionary step back from the trough --- and none too soon. An enormous
        pterodactyl flops down on the roof beside you and hops in an ungainly reptilian way toward the
        trough. A little man wearing a long gray robe  slides off of the pterodactyl
        as it begins feasting.
        
        <.p>The creature's wingspan is close to ten feet --- it's huge. And evidently hungry. Its
        table manners are not of the most refined, however. In digging into the chow, it flings as many
        of the brownish lumps of stuff here <<zarbolphung.addToAgenda(mentionCrystalBall.setDelay(3))>>
        and there with its beak as it gets down its gullet.
        
        <.p>As you gaze in muted horror at the beast's unsavory dining habits, the little man chuckles
        in a gruff, grumbly way. <q>Got a healthy appetite, doesn't he? Thanks for feeding
        him. I was so busy flying around looking for something I lost, I forgot to get him
        his chow.</q> ";
    }
;

// Note: Other NPCs need ownerNamed added to their body parts and garments! ownerNamed causes
// body parts to be referred to by the parser as "Zarbolphung's mustache" rather than "the mustache."

+ zMustache: Component 'filthy mustache; gray large (breakfast); crumbs'
    "Quite aside from the breakfast crumbs and other assorted bits of filth embedded in
    {the zarbolphung}'s mustache, you can't quite escape the impression that there might be a nest of small rodents
    lurking in there somewhere. Or even, given the size of the mustache, some fairly large rodents. "
    ownerNamed = true
;

+ zToes: Component 'hideously gnarled toes; hairy bulging; knuckles; them'
    "Nothing you've ever seen of human anatomy has prepared you for the sight of {the zarbolphung}'s
    hideously gnarled toes. The toes themselves seem (from what you can glimpse where they obtruded
    from under the hem of his robe)
    to be nearly as long as the rest of his foot. The toes arch like the legs of a spider, they're covered
    with coarse grayish hair, and their bulging knuckles are as rough as pebbles. "
    ownerNamed = true
;

+ zRobe: Wearable 'long gray robe'
    "The robe hangs loose on the little man's frame. Its hem is caked and smeared with dirt --- and
    not impossibly with things less savory than dirt. "
    cannotTakeMsg = 'Why would you want it??? '
    ownerNamed = true
;

+ zCap: Wearable 'floppy cloth cap; drooped droopy pointed; point'
    "The cloth cap may once have risen to a point, but in its present condition it has drooped
    so that he has to keep brushing the point out of his face. "
    ownerNamed = true
;

+ AskTopic, StopEventList @zarbolphung
    [
        { : "<q>I couldn\'t help noticing your pointed hat,</q> you say. <q>Are you by any
            chance a wizard?</q>
            <.p>He grins and nods his head firmly. <q>Clever of you to notice. You\'re an
            intelligent young lady, I can see
            that.<<zarbolphung.giveName()>> My name is Zarbolphung.</q> " },
        
        '<q>So you do magic and stuff?</q>
        <.p><q>That I do,</q> he affirms. <q>Only for my friends, though.</q> '
    ]
;

+ mentionCrystalBall: DelayedAgendaItem
   invokeItem {
        if ((zarbolphung.getOutermostRoom == gPlayerChar.getOutermostRoom) &&
            (zarbolphung.curState == zGrumpy)) 
        {
            "<q>Say, I don't suppose you've seen my crystal ball around anywhere,</q> {the zarbolphung}
            says. <q>I lost the damn thing somewhere. If you happen to spot it, bring it
            back to me, would you? I'd be ever so grateful. Oh, and I'm not usually up on the roof.
            Fluffikins can take care of himself. Fluffikins, that's what I call my passenger lizard. I'll
            more likely be downstairs visiting with Madame Bloviatsky.</q> ";
            tCrystalBall.makeFamiliar();
            isDone = true;
        }
    }
;
+ GiveShowTopic @crystalBall
    topicResponse() {
        crystalBall.moveInto(nil);
        zarbolphung.ballReceived = true;
        zarbolphung.setState(zFriendly);
        "<q>Is this what you're looking for?</q> you say, holding out the crystal ball.
        <.p><q>Holy corn fritters, you found it!</q> he replies. He takes it from you,
        lifts it reverently with his fingertips, kisses it, and then tucks it away in a
        hidden pocket in his robe. <q>You've earned a favor, right enough,</q> he says.
        <q>Anything you want, I'll do my best.</q> ";
        // We'll only call listStillNeeded() if in fact nothing is still needed:
        if (zarbolphung.allReceived) zarbolphung.listStillNeeded(nil);
        crystalToZarbolAch.awardPointsOnce();
    }
;

+ AskTellTopic, StopEventList @tMagic
    [
        '<q>I guess wizards must know a lot of magic,</q> you comment.
        <.p><q>Oh, immense amounts of it, yes. But don\'t ask me to teach you
        any. First you\'d have to join the union, and that would be difficult, as
        the entire membership committee of the BOOWWSMU --- that\'s the Benificent and
        Omnipotent Order of Wizards, Witches, Sorcerers,
        and Magic Users --- all disappeared a hundred years ago. If you\'re asking
        about specific magical workings, now....</q> ',
        
        { : "<q>If you\'re asking what you need to do in order to get your hands
            on the elusive prom dress --- let me see.</q> He scratches his 
            chin. <<zarbolphung.answerWhatsNeededQ()>>" }
    ]
;

+ AskTellTopic @tIdentification
    "<q>You said something about how the mannequin and the wooden soldier would need
    identification, isn\'t that right?</q>
    <.p>The wizard nods.
    <.p>Feeling a little desperate, you go on, <q>But how can I possibly come up with
    anything like that?</q>
    <.p><q>There\'s a machine downstairs somewhere,</q> he says. <q>Forged papers are
    illegal, so I think they keep the machine pretty well hidden. You\'ll need to enter
    some kind of code to get it working, but don\'t ask me what the code is, because
    I don\'t know. You\'ll need photos of them too, I know that much. Can\'t forge a driver\'s
    license without a proper photo.</q> "
;

+ AskTellTopic @ajou
    "<q>I saw a wooden soldier in the recruiting office,</q> you comment.
    <.p><q>Not one of my great successes,</q> the wizard admits. <q>He\'s not
    entirely inert, though. Play a bugle call at him and he\'ll become a bit more
    responsive.</q> "
;

// We can get here either before or after he has his crystal ball, so this bit
// goes directly in the Actor.
+ AskTellTopic, StopEventList @bianca
    [
        { : "<q>Excuse me, Mr.\ Wizard. <<if (!zarbolphung.proper)>>You <i>are</i> a wizard, isn\'t that right?</q>
        <.p>He
        nods impatiently. <q>That\'s right. <<zarbolphung.giveName()>>Name\'s Zarbolphung.</q>
        <.p>You hurry on. <q><<end>>I have a big problem. There\'s this mannequin,
        only she\'s sort of half alive, not just a mannequin anymore, and she stole
        something that I really need! It\'s a long story, but she said she\'d give me
        the dress if you could make her into a real human. Do you think you could do
        that?</q><<zarbolphung.listingItems()>>
        <.p>The wizard chews on his mustache for a minute. <q>Don\'t know why I should
        do you any favors,</q> he says. <q>You\'ve never done anything for me. That\'s how
        it is in a retail emporium like this. No such thing as a free lunch.
        But <<if (zarbolphung.curState == zGrumpy)>>I\'ll
        tell you what. I could give it a try, if you can find my crystal ball for me.</q>
        <.p><q>I\'ll try,</q> you assure him.
        <.p><q><<else>>I\'m happy to give it a try, since you found my
            crystal ball. <<end>>Magic spells are complicated, you know. Or maybe you don\'t. Here\'s
        what I would need.</q> He ticks off items one by one on his
        fingers. <q><<zarbolphung.roofSimpleReceived()>>
        And let\'s see, what else?</q> He
        chews his mustache some more.<.p>
            
        <<if (bianca.soldierMentioned)>>    
        <q>She said it wasn\'t just for her,</q> you tell him. <q>She said
        something about a handsome soldier.</q>
        <.p><q>You mean the one upstairs in the recruiting office? Yes, he\'s
       
        <<else>><q>It would be more efficacious, for magical purposes, if there were a bit of
            romance in the air,</q> he reflects. <q>I believe I may have an idea that
            would work. She might even like it. Have you seen that wooden soldier upstairs
            in the recruiting office? He\'s
            
        <<end>>
        halfway there too. The side effects of my experiments, you see. I believe
        I can finish the transformation for both of them at once, but
        you\'ll have to arrange it so that they\'re dancing. The night club downstairs
        would be perfect, but of course you\'ll need some sort of orchestra or dance band to provide
        the music. And also, for two of them together, I don\'t think the spinning
        top will quite do the job by itself. I\'ll still need the top, but
        you should try to get the mirror ball in the ceiling spinning. Do you think
        you can manage all that?</q>
        <.p>He ticks the items off on his fingers again. <q>Marigolds, the toe bone
        of a mummy, a top, some gold paint, a little paintbrush, get the mirror ball
        spinning, find a dance orchestra somewhere, and you\'ll need to convince the
        wooden soldier to come downstairs with you. He\'s rather rigid, I fear.</q>
        <.p>You have a sinking feeling. Surely you won\'t need to do all that! But
        what choice do you have?
        <.p><q>Oh, and one more thing,</q> the wizard adds. <q>In the modern world,
        humans can\'t just get along without various sorts of identification. Driver\'s
        license, Social Security card, that type of thing. Both the mannequin and the
        soldier will need identification. <<tIdentification.makeFamiliar()>>I can\'t
        very well undertake to send them
        out into the world unprepared. I hope you understand.</q> "},
        
        'The wizard has told you what he\'ll need in order to solve your problem with
        the mannequin --- marigolds, some gold paint, a small paintbrush, a top,
        the toe bone of a mummy (!), a dance orchestra (!!), some legal identification papers for
        the new humans, and you\'ll have to lead the soldier downstairs and get the
        mirror ball in the night club spinning.<<if (zarbolphung.curState == zGrumpy)>> Also,
        he won\'t do a darn thing unless you can find his crystal ball and give it back to him.<<end>>
        <.p>Maybe Samantha can wear her best jeans to the prom. But no, you owe it to
            her to try your best. '
    ]
;

// This version of the topic will be available after Bianca has run off with the
// dress, but before you've located her:
+ AskTellTopic [tPromDress, tSamantha]
    "<q>Excuse me, Mr.\ Wizard,</q> you begin. <q>I\'ve been trying to get a prom dress for
    my daughter, for the senior prom, and it's kind of a long story. I'm wondering if you might
    be able to help me at all.</q>
    <.p><q>Don't see how,</q> he replies. <q>Do I look like a seamstress? No, don't answer
    that. When you get a better idea what you want me to do, come back and tell me about it.</q> "
;
++ AltTopic
    "<q>Excuse me, Mr.\ Wizard,</q> you begin. <q>I\'ve been trying to get a prom dress for
    my daughter, for the senior prom, and it's kind of a long story, but a mannequin ran off
    with the dress! It had to have been some kind of magic, so I'm wondering if maybe you
    could help me.</q>
    <.p><q>It's conceivable,</q> he admits. <q>Some of my recent experiments have had the side
    effect of bringing formerly inanimate figures to life, or at least they now have some lifelike
    behaviors. But their behaviors and their desires can be unpredictable. Come back and talk to
    me after you've located her and learned what she wants.</q> "
    isActive = ((phantomBiancaDaemonID != nil) && (inanimateBianca.isIn(nil)))
;
++ AltTopic
    "<q>Excuse me, Mr.\ Wizard. <<if (!zarbolphung.proper)>>You <i>are</i> a wizard, isn\'t that right?</q>
        <.p>He
        nods impatiently. <q>That\'s right. <<zarbolphung.giveName()>>Name\'s Zarbolphung.</q>
        <.p>You hurry on. <q><<end>>I have a big problem. There\'s this mannequin,
        only she\'s sort of half alive, not just a mannequin anymore, and she stole
        something that I really need! It\'s a long story, but she said she\'d give me
        the dress if you could make her into a real human. Do you think you could do
        that?</q><<zarbolphung.listingItems()>>
        <.p>The wizard chews on his mustache for a minute. <q>Don\'t know why I should
        do you any favors,</q> he says. <q>You\'ve never done anything for me. That\'s how
        it is in a retail emporium like this. No such thing as a free lunch.
        But <<if (zarbolphung.curState == zGrumpy)>>I\'ll
        tell you what. I could give it a try, if you can find my crystal ball for me.</q>
        <.p><q>I\'ll try,</q> you assure him.
        <.p><q><<else>>since you found my crystal ball, I\'m happy to give it a
        try. <<end>>Magic spells are complicated, you know. Or maybe you don\'t. Here\'s
        what I would need.</q> He ticks off items one by one on his
        fingers. <q><<zarbolphung.roofSimpleReceived()>>And let\'s see, what else?</q> He
        chews his mustache some more.
        <.p><q>She said it wasn\'t just for her,</q> you tell him. <q>She said
        something about a handsome soldier.</q>
        <.p><q>You mean the one upstairs in the recruiting office? Yes, he\'s
        halfway there too. The side effects of my experiments, you see. I believe
        I can finish the transformation for both of them at once, but
        you\'ll have to arrange it so that they\'re dancing. The night club downstairs
        would be perfect, but of course you\'ll need some sort of orchestra or dance band to provide
        the music. And also, for two of them together, I don\'t think the spinning
        top will quite do the job by itself. I\'ll still need the top, but
        you should try to get the mirror ball in the ceiling spinning. Do you think
        you can manage all that?</q>
        <.p>He ticks the items off on his fingers again. <q>Marigolds, the toe bone
        of a mummy, a top, some gold paint, a little paintbrush, get the mirror ball
        spinning, find a dance orchestra somewhere, and you\'ll need to convince the
        wooden soldier to come downstairs with you. He\'s rather rigid, I fear.</q>
        <.p>You have a sinking feeling. Surely you won\'t need to do all that! But
        what choice do you have?
        <.p><q>Oh, and one more thing,</q> the wizard adds. <q>In the modern world,
        humans can\'t just get along without various sorts of identification. Driver\'s
        license, Social Security card, that type of thing. Both the mannequin and the
        soldier will need identification. <<tIdentification.makeFamiliar()>>I can\'t
        very well undertake to send them
        out into the world unprepared. I hope you understand.</q> "
    isActive = (bianca.getOutermostRoom() == behindCaboosePanel)
;

// ----------------------------------------------------------------------------------
// Giving Z the goodies he needs:
// ----------------------------------------------------------------------------------

// In this section, we'll give Z (a) the marigolds, (b) the toe, (c) the top, (d) the paintbrush,
// (e) the gilt paint, and (f) the pink and blue folders. We may need to construct a list of the
// actual items and then subtract items from the list, but let's try doing it the old-fashioned
// way.

+ GiveShowTopic @bunchOfMarigolds
    topicResponse() {
        bunchOfMarigolds.moveInto(nil);
        zarbolphung.marigoldsReceived = true;
        if (zarbolphung.itemsListed) {
            zarbolphung.listStillNeeded(bunchOfMarigolds);
        }
        else "<q>Ah, some nice flowers. Thank you.</q> He tucks the marigolds away in a fold
            of his capacious robe. <q>They might come in handy, you never know.</q> ";
    }
;

+ GiveShowTopic @mummyToe
    topicResponse() {
        mummyToe.moveInto(nil);
        zarbolphung.toeReceived = true;
        if (zarbolphung.itemsListed) {
            zarbolphung.listStillNeeded(mummyToe);
        }
        else "<q>What an odd specimen! The toe bone of a mummy, unless I miss my
            guess. Well, thank you. Such things do have
            their uses in magical workings.</q> He tucks the mummy's toe away in a fold
            of his capacious robe. <q>It might come in handy, you never know.</q> ";
    }
;

+ GiveShowTopic @spinningTop
    topicResponse() {
        spinningTop.moveInto(nil);
        zarbolphung.topReceived = true;
        if (zarbolphung.itemsListed) {
            zarbolphung.listStillNeeded(spinningTop);
        }
        else "<q>A very pretty little toy. Thank you. Such things do have
            their uses in magical workings.</q> He tucks the top away in a fold
            of his capacious robe. <q>It might come in handy, you never know.</q> ";
    }
;

+ GiveShowTopic @paintbrush
    topicResponse() {
        paintbrush.moveInto(nil);
        zarbolphung.paintbrushReceived = true;
        if (zarbolphung.itemsListed) {
            zarbolphung.listStillNeeded(paintbrush);
        }
        else "<q>Very nice. Thank you. I expect I'll be able to find a use for
            it.</q> He tucks the paintbrush away in a fold
            of his capacious robe. <q>It might come in handy, you never know.</q> ";
    }
;
    
+ GiveShowTopic @goldPaint
    topicResponse() {
        goldPaint.moveInto(nil);
        zarbolphung.giltPaintReceived = true;
        if (zarbolphung.itemsListed) {
            zarbolphung.listStillNeeded(goldPaint);
        }
        else "<q>That's a lovely color. Thank you.</q> He tucks the bottle of paint away in a fold
            of his capacious robe. <q>It might come in handy, you never know.</q> ";
    }
;

+ GiveShowTopic @biancaIdentiKit
    topicResponse() {
        biancaIdentiKit.moveInto(nil);
        zarbolphung.pinkFolderReceived = true;
        if (zarbolphung.itemsListed) {
            zarbolphung.listStillNeeded(biancaIdentiKit);
        }
        else "He flips through the folder, inspecting the contents.
            <q>This all seems to be in order. Very good.</q> He tucks the folder away in a fold
            of his capacious robe. ";
    }
;

+ GiveShowTopic @ajouIdentiKit
    topicResponse() {
        ajouIdentiKit.moveInto(nil);
        zarbolphung.blueFolderReceived = true;
        if (zarbolphung.itemsListed) {
            zarbolphung.listStillNeeded(ajouIdentiKit);
        }
        else "He flips through the folder, inspecting the contents.
            <q>This all seems to be in order. Very good.</q> He tucks the folder away in a fold
            of his capacious robe. ";
    }
;

// ----------------------------------------------------------------------------------
// Zarbolphung's ActorStates
// ----------------------------------------------------------------------------------

+ zGrumpy: ActorState
    isInitState = true
    stateDesc = "He's scowling at you in a way that doesn't seem entirely friendly. "
    specialDesc = "{The zarbolphung} is standing nearby, munching on the loose ends of his
        mustache. "
;

++ AskTopic @tCrystalBall
    "<q>You mentioned your crystal ball,</q> you say. <q>Can you tell me anything more
    about it?</q>
    <.p><q>Only that I lost it,</q> he replies. <q>I suppose it might have fallen out
    of my rucksack when I was flying figure-eights with Fluffikins. We were
    mostly flying over the garden behind the tower, if that helps.</q> "
;

+ zFriendly: ActorState
    stateDesc = "He's smiling amiably at you. "
    specialDesc = "{The zarbolphung} is <<if (gPlayerChar.getOutermostRoom() == narrowLedge)>>standing<<else>>sitting<<end>> nearby,
        scratching himself and muttering softly, pausing from time to time to comb his mustache with his fingers. "
;

+ zWaiting: ActorState
    stateDesc = "He's gazing around at the decor. "
    specialDec = "The wizard is standing nearby. "
    checkComplete() {
        local ready = true;
        if (monkeys.getOutermostRoom() != chartreuseCaboose) ready = nil;
        if (!monkeys.talented) ready = nil;
        if (bianca.getOutermostRoom() != chartreuseCaboose) ready = nil;
        if (ajou.getOutermostRoom() != chartreuseCaboose) ready = nil;
        if (!mirrorBall.spinning) ready = nil;
        return ready;
    }
    startGameEndDaemon {
        if (gameEndDaemonID == nil)
            gameEndDaemonID = new Daemon(self, &gameEndDaemon, 1);
    }
    gameEndDaemonID = nil
    gameEndDaemon {
        if ((!checkComplete) && (me.getOutermostRoom() == chartreuseCaboose))
            "The wizard <<one of>>fidgets and taps his toes<<or>>grumbles under his breath<<or>>tugs
            on his mustache<<or>>clears his throat meaningfully<<at random>>. Possibly
            he's <<one of>>growing impatient<<or>>getting bored<<or>>feeling restless<<at random>>. ";
        else if (checkComplete()) {
            finalScene();
        }
    }
    finalScene() {
        promDressAch.awardPointsOnce();
        "The wizard looks around and nods in satisfaction. <q>Good. You've managed it all. I
        congratulate you. Now, if you'll forgive me for just a moment, I have a few final
        preparations of my own.</q><.p>
        From somewhere in the folds of his robe he produces not just the mummy's toe bone but
        a small mortar and pestle, with which he grinds the bone to a gritty powder. After adding
        the marigolds to the mixture, he grinds some more and then sprinkles
        a pinch of the powder over the soldier, and another pinch over the mannequin. They look at
        one another and shrug, but they don't object.<.p>
        Next he brings out the top, the paintbrush, and the gold paint. He deftly paints a few magical
        symbols on the top, blows on the paint to dry it, and with a quick flick of his fingers sets
        it spinning on the floor.<.p>
        A gesture in the direction of the band of monkeys sets them playing a dreamy waltz. The soldier
        bows to the mannequin, and they begin to dance.<.p>
        The wizard raises both hands and
        utters a sonorous incantation, and the cascading multicolored light from the mirror ball
        grows brighter and more dazzling by
        the moment. It swirls most thickly around the dancing couple, nearly blinding you.<.p>
        As the monkeys finish the final measures of their waltz, the light
        returns to normal. And sure enough --- both the mannequin and the soldier appear now to be fully
        human! She rushes up to the wizard, hugs him, and kisses him fervently on the cheek. He pats
        her arm and says, <q>Now, now. Don't thank me. Thank this nice lady here. I think you owe
        her something, don't you?</q><.p>
        <q>Oh, yes! But I'll need something else to wear, won't I? I can't very well run around naked.
        Oh, I know. Wait right here --- I'll be back before you know it.</q> She trots off through the
        panel. In a few moments she's back, wearing a stylish pair of slacks and a silk top. She hands
        you the prom dress (!!!) and says, <q>Here. It's yours now. I don't need it anymore.</q><.p>
        The wizard says, <q>I believe you'll need these. Everything seems to be in order.</q> He
        hands them their folders of identity papers. The soldier pauses to shake your hand, and in
        another moment they've ventured out the door of the nightclub and they're gone.<.p>
        The wizard brushes off his hands. <q>All in a day's work,</q> he says gruffly. <q>Will you be needing
        me for anything else? Hope not. I'm off. Oh, wait. I suppose you'd like me to put all the
        things you borrowed back in the shops where they belong. I can manage that.</q> He snaps his
        fingers, and everything you've been carrying around (except for your purse, your cell phone,
        and of course the prom dress) vanishes.<.p>
        <q>Sending your primate friends back home may be a tiny bit more difficult, but I think I
        can manage that too.</q> After licking his fingers, he somehow opens a glowing magic portal.
        He beckons to the monkeys, and they troop through the portal. The portal snaps shut.<.p>
        <q>Well, that's that. Have a nice day.</q> The wizard saunters off, whistling a little tune.
        <.p>Feeling exhausted but happy, you head out to the parking lot, carrying the prom dress
        <i>very</i> carefully, and head for home. ";
        finishGameMsg('You have triumphed in your quest!', finishOptionFullScore); 
    }
;

