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

#ifdef __DEBUG

Test 'betsy' ['terse', 's', 's', 's', 'w', 'knock on window', 'x woman', 'e', 'e', 'e', 'd', 'nw',
    'take lid', 'se', 'u', 'n', 'n', 'w', 'tell guards about octopus', 'x corkboard', 'take key',
    'e', 'unlock shop door', 'e', 'take matches', 'open case', 'take cigarettes',
    'w', 's', 'w', 'w', 'n', 'put matches and marlboros on shelf', 's', 'tell betsy about marlboros',
    'lock closet door'];

Test 'dowsing'
    [
        'e', 's', 'e', 'e', 'd', 's', 's', 'w', 'purloin matchbook', 'purloin cigar',
        'purloin big square perfume bottle', 'purloin scarf', 'light cigar', 'catch pixies with scarf',
        'pour eau on pixies', 'purloin shoes', 'give shoes to homeless man', 'purloin dowsing rod',
        'give stick to man', 'man, follow me'
    ]
;

#endif

// She won't leave the betsyRegion. Initially, it doesn't include the archedPassage
// or palmTreeNiche.

betsySmallRegion: Region
    rooms = [beautyParlor, arcadeWest, arcadeNorth, arcadeCenter, arcadeEast,
    restroom, footOfStairs, narrowPassage, utilityRoom, lowerConcourseSouth, securityOffice,
    lowerConcourseNorth, upperPromenadeEast, upperPromenadeWest, upperConcourseNorth, upperConcourseEast,
    upperConcourseSouth, upperConcourseWest, starkPassage, archedPassage, smokeShop, palmTreeNiche]
    
    interiorLoc = archedPassage
    exteriorLoc = mainEntrance
    
    travelerLeaving (traveler, dest) {
        if (betsy.currentBetsyRegion != self) return;
        if ((traveler == gPlayerChar) && (betsy.curState == betsyClinging)) {
            // She won't announce that she's not following if you're just going into the
            // lounge or the security office:
            if ((dest == mainEntrance) || (dest == behindBuilding) || (dest == hedgeBorderedPath)) {
                "<q>I guess I'll just wait here,</q> {the betsy} says. <q>You're coming
                back, right?</q><.p> ";
                betsy.setState(betsyHovering);
            }
        }
    }
    travelerEntering (traveler, origin) {
        if (betsy.currentBetsyRegion != self) return;
        if ((traveler == gPlayerChar) && (betsy.curState == betsyHovering)) {
            // Because we don't want her to greet you if you've just been in
            // the lounge ... or crawling under the diorama:
            local betsyGreet = nil;
            betsy.setState(betsyClinging);
            // Possibly the player is coming up the stairs:
            if (origin == hedgeBorderedPath) {
                if (!betsy.isIn(upperPromenadeEast)) betsy.moveInto(upperPromenadeEast);
                betsyGreet = true;
            }
            // We'll assume that if you're coming out of the Octagonal Room
            // or world headquarters, she
            // will of necessity be waiting for you:
            else if (origin == octagonalRoom) betsyGreet = true;
            else if (origin == worldHeadquarters) betsyGreet = true;
            else if (origin == mainEntrance) {
                if (!betsy.isIn(archedPassage)) betsy.moveInto(archedPassage);
                betsyGreet = true;
            }
            else if (origin == behindBuilding) {
                if (!betsy.isIn(narrowPassage)) betsy.moveInto(narrowPassage);
                betsyGreet = true;
            }
            else if (origin == hedgeBorderedPath) {
                if (!betsy.isIn(upperPromenadeEast)) betsy.moveInto(upperPromenadeEast);
                betsyGreet = true;
            }
            if (betsyGreet)
            "When she sees you approaching, {the betsy} rushes up to you. <q>Oh, there
            you are! I thought for a minute you'd gone home or something. I hope it's
            all right if I kind of hang around with you a little while longer. My boyfriend still hasn't
            gotten here, darn it.</q>\b<.p> ";
        }
    }

    regionBeforeAction () {
        if (betsy.currentBetsyRegion != self) return;
        if (!gActionIs(Travel)) return;
        // At this point we need to trap ClimbUp and ClimbDown somehow. We have to do this in a separate
        // block, because these actions don't have a direction property.
        // There's also some question whether she can get trapped in the Octagonal Room.
        
        // letFollowerPrintRun means "leave the printout routine to run as usual":
        local letFollowerPrintRun = true;
        local pcLoc = gPlayerChar.getOutermostRoom();

        // Eric's suggested new code:
         local dir = gAction.direction;
         switch(pcLoc.propType(dir.dirProp))
         {
              case TypeNil:
              case TypeSString:
              case TypeDString:
                    letFollowerPrintRun = nil;
                 break;
              case TypeCode:
                    letFollowerPrintRun = nil;
                  break;
              case TypeObject:
                   /* We presumably have some kind of TravelConnector */
                   local conn = pcLoc.(dir.dirProp);  // obtain the connector object

                   /* If travel is possible and the connector is not locked, display our message */
                   if(!conn.canTravelerPass(gPlayerChar) || conn.isLocked)
                        letFollowerPrintRun = nil;
                   break;
         }   

        if (betsy.curState == betsyClinging) {
            if ((pcLoc == archedPassage) && (gTravelActionIs(north)))
                letFollowerPrintRun = nil;
            else if ((pcLoc == upperPromenadeEast) && ((gTravelActionIs(north)) ||
                                                       (gTravelActionIs(down)) ||
                                                        (gTravelActionIs(northeast))))
                letFollowerPrintRun = nil;
            else if ((pcLoc == upperConcourseWest) && ((gTravelActionIs(up)) ||
                     (gTravelActionIs(northwest)) ||
                     (gTravelActionIs(west))))
                letFollowerPrintRun = nil;
            else if ((pcLoc == lowerConcourseSouth) && ((gTravelActionIs(south)) ||
                    (gTravelActionIs(east)) || (gTravelActionIs(west))))
                letFollowerPrintRun = nil;
            else if ((pcLoc == narrowPassage) && (gTravelActionIs(south)))
                letFollowerPrintRun = nil;
            else if ((pcLoc == arcadeCenter) && (gTravelActionIs(southeast)))
                letFollowerPrintRun = nil;
            else if ((pcLoc == arcadeNorth) && (gTravelActionIs(northeast)))
                letFollowerPrintRun = nil;
            else if ((pcLoc == arcadeEast) && (gTravelActionIs(east)))
                letFollowerPrintRun = nil;
            else if ((pcLoc == starkPassage) && (gTravelActionIs(east)))
                letFollowerPrintRun = nil;
            else if (pcLoc == arcadeCenter) {}
            else if ((pcLoc == beautyParlor) && ((gTravelActionIs (north)) ||
                                                 (gTravelActionIs(south))))
                letFollowerPrintRun = nil;
            else if ((pcLoc == archedPassage) && (gTravelActionIs (east)) && (!vibratesPrinted)) {
                letFollowerPrintRun = nil;
                vibratesPrinted = true;
                // betsyLargeRegion.vibratesPrinted = true;
                "{The betsy} vibrates for a moment as you approach the door. <q>Well, I
                guess we could go in for just a minute,</q> she says. <q>I mean, what could it
                hurt? But I\'m not buying any cigarettes! I don\'t smoke. Not anymore.</q> ";
            }

        // If leaveItAlone is still true, we'll print a message indicating
        // Betsy is still tagging along. If she's not, we'll leave it up to
        // travelerLeaving to put her into a hovering state:
        if (letFollowerPrintRun)
            betsyClinging.departMessages.doScript();
            
        }
    }
    // This property is global to the Region object:
    vibratesPrinted = nil
;

// The main purpose of scBetsyFollowing is to spit out the messages about the smoke shop, which are
// a huge clue. The daemon also runs randomTwitches. This could as easily be done in the ActorState.

scBetsyFollowing: Scene
    startsWhen {
        return (betsy.curState == betsyClinging);
    }
    endsWhen {
        return (betsy.curState == betsySmoking);
    }
    noticedPuff = nil
    eachTurn {
        if (!noticedPuff && (betsy.getOutermostRoom == archedPassage) &&
                 (gPlayerChar.getOutermostRoom == archedPassage)) {
            noticedPuff = true; 
            "<q>I used to go in there twice a day to buy smokes,</q> {the betsy} says,
            pointing at the door of Puff the Magic Stogie. <q>But I quit smoking. Did I tell you
            that? Two whole months ago. No, more than two. Almost three. So I\'m glad it\'s
            closed this afternoon, because that means I\'m not tempted. Not that I would be anyway.
            Tempted, I mean....</q> ";
        }
        // We need to test if betsy is actually in the room with you, because the sense context
        // of the scene is probably global.
        else if ((betsy.getOutermostRoom != beautyParlor) && (betsy.isIn(me.getOutermostRoom)))
            randomTwitches.doScript;
    }
    randomTwitches: ShuffledEventList {
    [
        '<q>It feels kind of creepy with all the stores closed in broad daylight
        like this,</q> {the betsy} says. ',
        '<q>Do you shop here a lot?</q> {the betsy} asks. <q>That\'s a
            nice outfit you\'re wearing.</q> ',
        '<q>I wonder why my boyfriend hasn\'t picked me up yet,</q> {the betsy}
            says. ',
        '<q>They have really nice things in some of these shops,</q> {the betsy} says. ',
        '{The betsy} scratches her nose. ',
        '{The betsy} chews on a fingernail. ',
        '{The betsy} hums a little tune, and then says, <q>Oh, I\'m sorry. I didn\'t
            mean to be....</q>'
    ]
        // These parameters cause the randomTwitches to dribble off:
        eventPercent = 50
        eventReduceAfter = static eventList.length()
        eventReduceTo = 20
    }
;

betsyGoneRegion: Region
// The roomList is built at preInit and should not be altered by the author.
// The point of the betsyGoneRegion is that once she is in the closet, her boyfriend
    // will invisibly arrive and invisibly take her home -- but that won't happen
    // if you're in a place where you could see it.
;

// The scBetsySmoking scene runs while she's in the closet. Its main purpose was to run a daemon
// that would cause her to emerge from the closet (thus making the game unwinnable) after 20
// turns, but we no longer think we need to lock her in.
scBetsySmoking: Scene
    startsWhen {
        return (betsy.curState == betsySmoking);
    }
    endsWhen {
        return (betsy.getOutermostRoom == nil);
    }
    
    eachTurn {
        local rm = gPlayerChar.getOutermostRoom();
        if (!rm.isIn(betsyGoneRegion)) {
            betsy.moveInto(nil);
            coatClosetDoorOutside.makeLocked(nil);
        }
    }
            
;

////////////////////////////////////////////////////////////////////////////////////////

betsy: Actor
    'young hairdresser; thin skinny awkward awkward-looking pale neurotic nervous; betsy woman shopgirl girl beautician; her'
    @beautyParlor
    desc {
        if (!firstDescPrinted) {
            
            firstDescPrinted = true;
            "You realize, belatedly, that you know her<<if !proper>>. Her name is Betsy<<end>>. She used
            to work at the place
            where you have your hair done. Then, last year, you noticed she was gone. Nobody ever said why,
            and you were too polite to ask. It wasn't hard to guess why: Betsy was annoying. She snapped
            her gum, she bumped into things, she dropped things, she spilled things, she mixed up
            customers' names, she trimmed their hair shorter on one side than on the other --- she
            was just a walking disaster area. Plus, she was always sneaking out back to have a cigarette,
            so she reeked of tobacco smoke.<.p>Today she looks just the way you remember: She's ";
            giveName;
        }
        else "Betsy is ";
        "pale, thin, and nervous. She twitches constantly, and her fingernails are gnawed to ragged nubs. ";
    }
    firstDescPrinted = nil

    cannotTakeMsg = 'You\'ve never learned the fireman\'s carry. Besides, she probably
        wouldn\'t appreciate it. '
    cannotPutPersonMsg = 'That\'s unlikely to be a useful thing to do. '
    cannotEatMsg = 'You\'re joking, right? '
    kissResponseMsg = 'You don\'t feel nearly that much affection for her. '
    attackResponseMsg = 'She\'s rather annoying, to be sure ... but you\'re not that
        uncivilized. '
    // The point of hasJustExited is to suppress the mention of the betsy as still being
    // visible through the shop window the very first time you exit with her.
    nowExiting() { hasJustExited = true; }
    hasJustExited = nil
    globalParamName = 'betsy'
    giveName {
        proper = true;
        replaceVocab ('Betsy; thin skinny young neurotic pale nervous awkward; hairdresser shopgirl beautician woman elizabeth elsie beth betty; her');
    }
    smellDesc = "She\'s surrounded by a haze of perfume --- one of those bitter, tangy fragrances that always
        remind you of insecticide --- beneath which you can detect the unmistakable
        reek of cigarette smoke. "
    shouldNotFeelMsg = "<< if (rubyRing.known)>>If you get that close to her, you'd be more likely to strangle her. Best
            keep a safe distance. <<else>>She's not your type. "
    
    hasSeenOllie = nil
    ollieSeen() {
        hasSeenOllie = true;
    }
    // The currentBetsyRegion will be reset from betsySmallRegion to betsyLargeRegion when
    // the octopus is allowed to escape, thus allowing her to follow you into the archedPassage
    // and the smokeShop.
    currentBetsyRegion = betsySmallRegion
    // We're going to override Actor's followDaemon routine, so as to check where the PC has
    // gone and prevent Betsy from following to certain locations (such as into the closet):
    followDaemon()
    {
        // While she's in the closet, she won't follow you:
        if (curState == betsySmoking) return;
        
        local oldLoc = getOutermostRoom;
        local pcLoc = gPlayerChar.getOutermostRoom;
        
        // New code:
        if ((pcLoc == coatCloset) || (pcLoc == tackyLounge)
            // Assumedly, you won't be able to get to any of these locations, because Betsy
            // won't let you use the key. However, if you fail to lock her in the closet and
            // then go directly to the Tarzan, almost anything could happen.
            || (pcLoc == inTheTarzan) || (pcLoc == jungleClearing) ||
            (pcLoc == buddhaClearing) || (pcLoc == carpetOfSticks) || (pcLoc == damagedHallwayNorth) ||
            (pcLoc == toyShop) || (pcLoc == dioramaUnderside)
            )
            return;
        // Because she's going to stay in the building:
        if (!pcLoc.isIn(currentBetsyRegion)) {
            return;
        }
        
        if(oldLoc != pcLoc)
        {
            // "Testing -- PC has moved out of Betsy's vicinity. ";
            if(pcConnector != nil)                
                pcConnector.travelVia(self);
            else
                gPlayerChar.getOutermostRoom.travelVia(self);
            // We'll try commenting this out, so as to call it from the region code:
            // sayFollowing(oldLoc, pcConnector);
            // This will call arrivingTurn in the current ActorState:
            arrivingTurn();            
        }
        /* 
         *   Reset pcConnector to nil in any event so that a spurious value
         *   isn't left for a later turn.
         */
        pcConnector = nil;
    }
;

////////////////////////////////////////////////////////////////////////////////////////

+ bFingernails: Component
    'gnawed fingernails; chafed chewed chewed-on; finger fingers nail nails fingertips; them'
    "Her fingernails are ragged, and the fingertips have that chafed, chewed-on look. "
    cannotTakeMsg = 'You would have no use for her fingers or fingernails. '
    cannotEatMsg = 'She\'s already doing a pretty good job of that herself. '
;

//----------------------------------------------------------------
// Betsy's AgendaItems
//----------------------------------------------------------------

// This AgendaItem will fire on the 7th turn after you've met Betsy, but the count
// only increments during non-travel turns (and perhaps during non-conversation turns
// too -- not sure). It's set to a 7-turn delay in the door and window objects, when
// you knock on them. If you're out of the room, it will delay until you return, and
// then fire immediately.
+ mentionSmoking: DelayedAgendaItem
    invokeItem {
        if (betsy.getOutermostRoom == gPlayerChar.getOutermostRoom) {
            "<q>Have I mentioned I finally quit smoking?</q> {the betsy}
            says irrelevantly. <q>I haven't had a cigarette in weeks. I don't
            even want one. Don't miss it at all.</q> She puts one haggard thumbnail between
            her teeth and gnaws on it briefly, an act that draws your attention to
            her fingers. Wait, now: Isn't that the ... no, it couldn't be!
            Except, the longer you stare at it (trying not to be too obvious), the
            more certain you become: {The betsy} is wearing the beautiful
            ruby ring you lost last year!
            
            <.p>And didn't you lose it at the shop where she was working then?
            Yes, you're almost sure you did. You asked all the stylists in the
            shop, and none of them had seen it. But now, here it is, on {the betsy}'s
            finger! ";
            rubyRing.isHidden = nil;
            rubyRing.known = true;
            isDone = true;
        }
    }
;

// Also found in the room's code (???). Question: What happens if you leave the room without
// freeing ollie? Will she remind you the next time you're down there?

+ noticeOllie: AgendaItem 
  initiallyActive = true 
  nudgeCount = 0
    reNudge = nil
  isReady = (getActor.canSee(ollie) || reNudge) 
  invokeItem 
  {
        local rm = betsy.getOutermostRoom();
        local me_rm = me.getOutermostRoom();
        if (nudgeCount == 0) {
            "{The betsy}'s eyes crinkle up and fill with tears when she sees the
            octopus in its tank. <q>Oh, I just think that's so <i>sad</i>,</q> she says in a lachrymose
                tone that's almost a moan. <<betsy.ollieSeen()>>
            <q>Being cooped up like that, with anybody who comes by staring at you all day long.
            My soul feels just exactly like that, almost all the time.
            I don't think animals should ever be caged, do you?</q> Not waiting for an
            answer, she hurries on: <q>Isn't there something we could do? Let the poor
            thing run free?</q>
            
            <.p>You start to explain that the octopus is an aquatic animal, and can't breathe
                air, but {the betsy} isn't paying any attention to you. After cooing at the octopus
                through the glass and making little kissing noises, she starts fussing
            and tugging at the heavy sheet of plywood that lies on top of the tank. <q>Come on,
            help me,</q> she says. <q>Let's free the poor sad thing from its awful
            confinement!</q> ";
            reNudge = true;
        }
        nudgeCount++;
        
        if ((nudgeCount == 5) && (!ollie.released) && (rm == me_rm))
            "<q>We just <i>have</i> to go let that poor octopus out,</q> {the betsy} says. ";
        if ((nudgeCount == 11) && (!ollie.released) && (rm == me_rm)) {
            "<q>I haven't forgotten about the poor octopus,</q> {the betsy} says. <q>I sure
            hope you haven't! Can't we do something about him?</q> ";
            isDone = true;
            reNudge = nil;
        }
        if (ollie.released) { reNudge = nil; isDone = true; }
  } 
; 

//--------------------------------------------------------------------
// Betsy's ActorStates
//--------------------------------------------------------------------

+ betsyClinging: ActorState
    stateDesc = "She's <<if (gPlayerChar.getOutermostRoom == beautyParlor)>>wandering around
        the beauty parlor in a vague way, touching things
        but not picking them up, as if possibly searching for something without being entirely
        sure what it is<<else>><<randomBusiness.doScript()>><<end>>. "
    specialDesc {
        if (betsy.getOutermostRoom == gPlayerChar.getOutermostRoom) "{The betsy} is
            <<specialDescList.doScript()>>. ";
    }
    specialDescList: ShuffledEventList {[
        'standing nearby, fidgeting',
        'looking at you expectantly',
        'gazing off into the distance',
        'examining her fingernails',
        'tugging at her hair',
        'standing uncomfortably close to you',
        'humming a little tune',
        'fiddling with an earring',
        'pinching her nose and snuffling',
        'scratching her elbow'
    ]}
    // There's a more general solution to this next problem: Put all of the places
    // where Betsy can't go into a region, and then test if conn is in the region.
    beforeTravel (traveler, conn) {
        // "Test: In beforeTravel() in betsyClinging. ";
        if ((conn == upperPromenadeStairwayDown) || (conn == mainEntrance) ||
            (conn == behindBuilding) || (conn == scootersPub) || (conn == artGallery)) {
            "<q>I think I'll just wait here,</q> {the betsy} says. <q>In case
            my boyfriend comes.</q> ";
            betsy.setState(betsyHovering);
        }
        
    }
    // Here we'll prevent you from unlocking shop doors. The hard-coded assumption is that at
    // this stage of the story there's nothing ELSE (such as a suitcase) that you would want
    // to unlock. Unfortunately, I've also hard-coded the assumption that you alraedy have
    // the key....
    beforeAction() {
        if (gActionIs(Open) && gDobj.ofKind(ShopDoorOutside) && (gDobj != smokeShopDoorOutside)) {
            doorBlockResponses.doScript();
            exit;
        }
        else if (gActionIn(Unlock, UnlockWith)) {
            if ((gDobj != smokeShopDoorOutside) && (gDobj != coatClosetDoorOutside)) {
                doorBlockResponses.doScript();
                exit;
            }
        }
    }
    doorBlockResponses: StopEventList {[
        { : "{The betsy} narrows her eyes at you. <q>That shop is <i>closed,</i></q> she says
            pointedly. <<if (masterKey.isIn(me))>><q>I don\'t know where you got that key, but we shouldn\'t be going
            in there!</q> " },
        '<q>You\'re trying it again, aren\'t you,</q> {the betsy} says, frowning. <q>Can\'t
        you see that shop is closed?</q> ',
        
        '{The betsy} presses her lips together, wrinkles her delicately plucked eyebrows
        at you, and shakes her head firmly. No, she\'s just not
        going to let you go into any of the closed-up shops. If only there were some way to
        get rid of her.... '
    ]}
    
    catchUp {
        local rm = me.getOutermostRoom;
        betsy.moveInto(rm);
        "{The betsy} rushes up to you, looking harried. <q>Oh, I thought for a second you'd
        run off and ";
        if (rm.ofKind(Shop)) {
            "... hey, wait a minute! You're not supposed to be in here! The store is closed. This is
            not good. I think I'd better let the security office know about this.</q><.p>
            You stammer for a moment, trying to come up with a reasonable explanation, but what
            you're saying hardly matters, because she isn't listening. She trots off. You
            slip outside and turn to lock the shop door, but when you turn around, the guards are
            standing right there, their fists on their hips, looking disgusted and disbelieving.<.p>
            {The betsy} points at you, gloating. <q>See? What did I tell you?</q><.p>
            <q>You'd better come with us, ma'am,</q> one of the guards says. They escort
            you back to the security office and make a phone call. Ten minutes later a female security
            guard arrives, searches you, and finds the passkey you were trying to hide.<.p>
            You're hauled off in handcuffs. Samantha misses the prom, becomes a drug addict,
            joins the Scientologists, and then disappears on a mission to Upper Guyana
            and is never heard from again. ";
            finishGameMsg('<b>You have failed in your quest.</b>', nil);
        }
        else "left me!<./q> ";
    }
    // Eric's suggestion for how to get the Ollie item to fire immediately:
    arrivingTurn() { getActor.executeAgenda(); }
    
  departMessages : ShuffledEventList { 
    [
        { : "{The betsy} says, <q>If it\'s all right with you, could I, like, <<betsy.nowExiting()>>
            tag along for a few minutes? <<viewOfBetsy.moveInto(nil)>>My boyfriend was
            supposed to pick me up, but I guess he\'s
            running late or something, which doesn\'t surprise me, he\'s usually kind
            of forgetful, but you look like a nice person, and I guess....</q> Without waiting
            for you to say okay, she follows you out of the beauty shop. " }
    ]
    [
         '{The betsy} comes with you. ', 
         '{The betsy} follows you. ', 
         '{The betsy} is at your elbow. ', 
         '{The betsy} trails along behind, but then catches up. ', 
         '{The betsy} follows hot on your heels. ', 
         '{The betsy} darts after you. ',
         '{The betsy} trots along with you like a faithful puppy. ',
         '{The betsy} says, <q>Where are you going? Oh, okay. I\'m right behind you.</q> ',
         '{The betsy} strolls along with you. ' 
    ]} 
    randomBusiness: ShuffledEventList {
    [
        'gazing at you with a fixed expression that mingles hope and fear',
        'inspecting her complexion closely in a pocket mirror',
        'chewing on a fingernail',
        'scratching her elbow',
        'fiddling with her hair',
        'humming tunelessly',
        'tapping her foot nervously'
    ]} 
;

// These states should never be visible to the PC ... I hope. They're used when
// you've left the building, or are under the diorama:
+ betsyHovering: ActorState
    specialDesc = "{The betsy}'s eyes light up when she sees you approaching. "
;
+ betsyByDiorama: ActorState
    specialDesc = "<q>Oh, there you are,</q> {the betsy} says. "
;

+ betsyWaiting: ActorState
    stateDesc = "She's wandering around the beauty parlor in a vague way, touching things
        but not picking them up, as if possibly searching for something without being entirely
        sure what it is. "
    isInitState = true
;

+ ImpHelloTopic
    ""
;

+ HelloTopic
    "<q>Excuse me,</q> you say. <q>I don't mean to intrude, but....</q><.p>
    <q>Oh, that's all right,</q> {the betsy} replies. "
;

+ ByeTopic
    "<q>I need to be going,</q> you tell {the betsy}.<.p><.>I hope I'm
    not being any trouble,</q> she replies. <q>It's just --- my boyfriend said
    he'd pick me up, but I guess he's running a little late, and practically
    everybody else left to go to the parade, so I thought maybe you wouldn't mind
    if I sort of hung around with you. I'm not getting in your way or anything,
    am I?</q> "
;

//-----------------------------------------------------------
// Conversations with Betsy
//-----------------------------------------------------------

+ AskTopic, StopEventList @betsy
    [
        '<q>Do you work in the beauty parlor?</q> you ask.<.p><q>Me? Oh, yes. Yes,
            I do. My name is Elizabeth, but everybody calls me Betsy. <<betsy.giveName>>I think I remember
            you from --- from someplace where I used to work.</q> She seems to be waiting
            for you to tell her your name, but you don\'t feel quite that friendly toward
            her. ',
        '<q>I\'m not really very interesting,</q> she says. <q>I mean, even my boyfriend
        doesn\'t think I am. He claims he does, but....</q> '
    ]
;

+ AskTellTopic, StopEventList @woodenIndian
    [
        '<q>What do you know about the wooden Indian?</q> you ask.<.p><q>I think he\'s
        really creepy,</q> {the betsy} replies. <q>Sometimes I think he\'s <i>staring</i>
        at me. I expect you probably think I\'m crazy, but I can\'t get over that
        feeling.</q> ',
        'You attempt to pursue the topic, but {the betsy} only murmurs vaguely. '
    ]
;

// This is tricky. We don't know when you're asking her. First, you've been downstairs
// and seen the octopus, but she hasn't. Second, you've both seen it, but you failed to
// take the hint and lift the lid. Third, the octopus is released but you haven't thought
// to tell the guards. Fourth, you've told the guards, but perhaps it's not recaptured
// yet. Fifth, it's recaptured.

+ AskTellTopic @ollie
    topicResponse() {
        if (!betsy.hasSeenOllie) "<q>Have you seen that octopus downstairs in the
            tank?</q> you ask.
            <.p><q>Oh, that poor thing? We should go down there right now and set
            him free!</q> ";
        else if (betsy.hasSeenOllie && !ollie.released)
            "<q>I keep thinking about that octopus,</q> you comment.
            <.p><q>Me too,</q> she replies. <q>Let's go set him free right now!</q> ";
        else if (ollie.released && !ollie.recaptured && guardsGroup.isIn(securityOffice))
            "<q>I feel bad about letting the octopus out,</q> you say.
            <.p><q>Oh, but I'm sure he's so much happier now!</q> she insists.
            <.p><q>I don't think so,</q> you reply. <q>I think we should tell the guards
            so they can capture him and put him back in the tank where he belongs.</q> ";
        else
            "<q>Have you ever thought you might have been an octopus in a previous
            incarnation?</q> you ask.
            <.p><q>That's a weird thing to say,</q> she replies. <q>But I do
            dream about being under water sometimes.</q> ";
    }
;

+ AskTellTopic, StopEventList @rubyRing
    [
        'Trying to sound casual, you point at the ring {the betsy} is wearing. <q>That\'s a
        very nice ring,</q> you comment. <q>Can I ask where you got it?</q><.p>
        She holds out her hand proudly to admire the ring, and beams smugly. <q>My boyfriend gave it to me,</q>
        she proclaims. ',
        '<q>I can\'t help thinking the ring looks a lot like one I used to have,</q> you say,
        trying to keep your voice casual. <q>I lost it. In a beauty shop.</q><.p>
        Just for a moment, you fancy you see a flicker of guilt and terror cross her face. <q>Well,
        my boyfriend gave me this one,</q> she says firmly. ',
        'Pestering her further about the ring is unlikely to do any good. Whether she stole it or only
        found it, she\'s never going to admit it. Damn! '
    ]
;

+ AskTopic @tBoyfriend
    "<q>He\'s coming to pick me up,</q> she explains. <q>He should be here any time now.</q> "
;

+ GiveShowTopic, StopEventList @marlboros
    [
        '<q>Look what I found,</q> you say, holding out the pack of Marlboros.<.p>{The betsy}\'s
            eyes fill with moist longing. <q>Oh, they look ... no, I mustn\'t.</q> She
            quivers for a moment, and turns resolutely away. ',
        '<q>Are you sure I can\'t interest you in taking these?</q> you say, not quite willing
            to give up (even while hating yourself the whole time). She averts her eyes,
            presses her lips together, and shakes her head stiffly. ',
        'It\'s no use. The direct approach isn\'t going to work. Clearly she\'s dying to grab
            the cigarettes, but she\'s also determined to exhibit strength of character. 
            If you\'re hoping to bribe her
            to leave you in peace, or distract her somehow, you\'ll have to find some way to be sneaky about it. '
    ]
;

+ GiveShowTopic @singleMatchbook
    "<q>What would I want with matches?</q> she says. <q>I'm sure I told you I don't smoke.</q> "
;

+ AskTopic @tSmoking
    "<q>You say you've stopped smoking?</q> you ask.
    <.p><q>That's right,</q> she replies. <q>I don't miss it at all.</q> She blinks rapidly,
    twitches, and nibbles on a fingernail. "
;

+ AskTellTopic, StopEventList @marlboros
    [
        '<q>I found a pack of cigarettes outside the smoke shop,</q> you mention.<.p>She shakes
            her head firmly. <q>Why should that matter to <i>me</i>? <i>I</i> don\'t smoke.</q> ',
        '<q>I\'m proud of you for stopping smoking,</q> you say. <q>But the pack of Marlboros
            is just going to waste.</q><.p><q>I do kind of wish I had a cigarette,</q> she
            admits wistfully. <q>But not right now. Maybe later.</q> ',
        'Just reminding her of the cigarettes doesn\'t seem to be getting you anywhere. Maybe a less direct
            approach would get better results. '
    ]
;
// Note: This AltTopic only works when Betsy is in the Beauty Parlor. That requires some
// mind-reading on the part of the player.
++ AltTopic
    topicResponse {
        "<q>I saw a pack of cigarettes in the coat closet,</q> you say, pointing at the closet
        door.<.p><q>Oh, really?</q> {The betsy}
        tries to look nonchalant, but the way she\'s licking her lips and tugging at her hair is
        a giveaway. <q>Well, maybe I\'ll just.... Back in a jiffy!</q> She dives for the closet
        door, slips inside, and slams it behind her. ";
        betsy.setState(betsySmoking);
        coatClosetDoorOutside.makeLocked(nil);
        coatClosetDoorOutside.makeOpen(true);
        betsy.moveInto(coatCloset);
        coatClosetDoorOutside.makeOpen(nil);
        betsyAch.awardPointsOnce();
        
        // And now she's carrying the smokes, so they won't be reported in the room description
        // of the closet:
        marlboros.moveInto(betsy);
        marlboros.ripOpen();
    }
    isActive = ((marlboros.getOutermostRoom == coatCloset) && betsy.isIn(beautyParlor))
;
// This version should work if you're not in the beauty parlor. Note, however, that in this
// version the closet door is not locked by the player. Maybe that's not important.
++ AltTopic
    topicResponse {
        "<q>I thought I saw a pack of cigarettes in the coat closet
        in the salon,</q> you say.<.p><q>Oh, really?</q> {The betsy}
        tries to look nonchalant, but the way she\'s licking her lips and tugging at her hair is
        a giveaway. <q>Well, maybe I\'ll just.... Back in a jiffy!</q> She sprints away. What a relief! ";
        betsy.setState(betsySmoking);
        coatClosetDoorOutside.makeLocked(nil);
        coatClosetDoorOutside.makeOpen(true);
        betsy.moveInto(coatCloset);
        coatClosetDoorOutside.makeOpen(nil);
        betsyAch.awardPointsOnce();
        
        // And now she's carrying the smokes, so they won't be reported in the room description
        // of the closet:
        marlboros.moveInto(betsy);
        marlboros.ripOpen();
    }
    isActive = ((marlboros.getOutermostRoom == coatCloset) && !betsy.isIn(beautyParlor))
;

+ AskTellTopic, StopEventList @tPromDress
    [
        '<q>I came here this afternoon to get a dress for my daughter for the senior prom,</q>
        you say.<.p>
        <q>They have lots of nice dresses downstairs in the boutique,</q> {the betsy} replies. ',
        
        '<q>Do you think you might be able to help me get the dress?</q> you ask.
        <.p><q>I guess the store is probably closed on account of the parade,</q> she
        replies. With a little laugh she adds, <q>It\'s not like I have a master key or anything!</q> ',
        
        'It doesn\'t appear she\'s going to be much use in the prom dress department. '
    ]
;

+ AskTellTopic @tJoe
    "<q>I wouldn't know anything about him,</q> she replies with a sniff. "
;

+ DefaultAskTellTopic, ShuffledEventList
    [
        { : "{The betsy} smiles vaguely. <q>I\'m sorry, I guess I didn\'t catch that.</q> " },
        { : "{The betsy} shrugs. <q>Whatever.</q> " },
        { : "{The betsy} is fiddling with a strand of her hair, and doesn\'t respond. " },
        { : "{The betsy} squirms uncomfortably. <q>I feel all <i>itchy</i>,</q> she complains. " }
    ]
;

// Here she's smoking in the closet, so evidently you've opened the door and gone in:

+ betsySmoking: ActorState
    stateDesc = "She\'s puffing avidly on a Marlboro. "
    specialDesc = "{The betsy} is huddled in the closet, sucking on a lighted cigarette. Smoke
        swirls around her in a thick cloud. <<one of>><q>Oh, hi,</q> she says. <q>I guess you
        found out my little secret. You go on. I'll be out in a minute.</q> <<or>><<stopping>>"
;

++ DefaultAskTellTopic
    "{The betsy} is busy smoking, and doesn\'t seem to have heard you. "
;

