The Bridge of Death (Source Code)

The Bridge of Death
Stop! Who would cross the Bridge of Death must answer me these questions three, ‘ere the other side he see.
  • Release 1 (2016-02-12)
    • Initial release.
  • Release 2 (2016-02-17)
    • Added a routine to choose the final question.
    • Re-arranged questions so the always wrong question has the least chance of being chosen.
    • Added a PANIC and DON’T PANIC command for some additional comic effect.
    • Added end the game routines, and changed Eternal Peril so the game doesn’t end immediately.
    • Fixed the ultimate question so the answer can be 42 or forty-two.
  • Release 3
    • Eliminated the setting of variables when play beings.
    • Changed question answer checking from choosing a table row to repeating through the table.
  • Release 4
    • Added prologue.
    • Fixed bug concerning matching in lower case vs. case insensitively with Xyzzy and Text Fiction Android apps.
    • Added bridgekeeper photo for Glulx version.
  • Release 5 (2018-10-26)
    • Revised and updated final question content and frequency.
    • Fixed reference to bridgekeeper’s picture.
    • Added support for HELP command.
    • Made minor improvements to some commands and responses.
    • Added a knight to the list of knights you can name.
  • Release 6 (2019-11-22)
    • Reorganized source code.
    • Made minor improvements.
    • Added a coconut.
"The Bridge of Death" by "A. J. Mako"

The story headline is "Do you have what it takes to cross the Bridge of Death?".
The story genre is "Comedy".
The story creation year is 2016.
The release number is 6. 
The story description is "This is an adaptation of the scene from Monty Python 
    and the Holly Grail, used exclusively as a learning exercise."

Figure of Bridgekeeper is the file "bridgekeeper.png".

Include Basic Screen Effects by Emily Short.

Part 1 - Globals

Quest continues is a truth state that varies. Quest continues is initially false.
Questions answered is a number that varies. Questions answered is initially 0.
Final Question is a number that varies. Final Question is initially 0.
Peril counter is a number that varies. Peril counter is initially 0.
The description of the player is "As resplendent as ever in [our] regalia as one 
    of the famous Knights of the Round Table."

Part 2 - Start Up

When play begins:
    say "[bold type]England 932 A. D.[roman type][paragraph break][bold type]
        The story so far...[roman type][paragraph break]Arthur, son of 
        Urthur Pendragon, King of the Britons has ridden the width and 
        breadth of the land in search of knights who would join him in his 
        court at Camelot. After repressing a bloody peasant, dismembering 
        an invincible Black Knight, and helping to erroneously convict and 
        therefore cause the burning of an alleged witch, Arthur was tasked 
        by God to find the Holy Grail.[paragraph break]The quest began 
        ominously with Arthur and his Knights of the Round Table being 
        taunted by some Frenchmen. Defeat at the French castle utterly 
        disheartened King Arthur. The ferocity of the French taunting took 
        him completely by surprise.[paragraph break]Please press SPACE to 
        continue.[paragraph break]";
    wait for the SPACE key;
    say "So, the Knights separated and searched for the Grail individually. Sir 
        Robin rode north where he bravely ran away from the dreaded Three-
        Headed Knight. Sir Galahad was rescued from almost certain temptation 
        at the hands of the sisters of the Castle Anthrax. Sir Lancelot, 
        having saved Sir Galahad, continued his search by single-handedly 
        sacking Swamp Castle.[paragraph break]Meanwhile, Arthur discovered 
        a vital clue from the old man from Scene 24. He learned of Tim the 
        Enchanter, the Cave of Caerbannog, the Gorge of Eternal Peril, and 
        the Bridge of Death. To continue the quest, Arthur was forced to 
        say 'Ni' to an old crone in order to defeat the Knights Who Say Ni.
        [paragraph break]Please press SPACE to continue.[paragraph break]";
    wait for the SPACE key;
    say "Arthur's Knights reassemble while searching for Tim the Enchanter. 
        Many knights were defeated by the rabbit who guards the entrance to 
        the Cave of Caerbannog, but Arthur proved finally victorious after 
        using the Holy Hand Grenade of Antioch. Within the cave, Arthur 
        discovered the last words of Joseph of Arimathea, which told of the 
        final resting place of the Grail.[paragraph break]Now, having escaped 
        the attack of the Legendary Black Beast of Arrrghhh, Arthur and his 
        remaining knights approach the Bridge of Death...";
    pause the game.

Part 3 - The Map

Chapter 1 - Rooms

The Edge of the Abyss is a room. "The narrow path leads [us] to the edge of the 
    Bridge of Death, which provides the only way across the Gorge of Eternal 
    Peril. An eerie mist wanders up from the gorge and surrounds you eerily." 

The Far Beyond is a room. "The narrow path leads [us] away from the edge of the 
    Gorge of Eternal Peril. The Bridge of Death provides the only way back 
    across the gorge. An eerie mist wanders up from the gorge and surrounds you 
    eerily."

Eternal Peril is a room. "All around [us] the mist swirls, obscuring the sky, the 
    sides of the gorge, and even the ground. [We] continue to fall as the peril 
    engulfs [us] perilously."

The Bridge of Death is a door. 
The description of the Bridge of Death is "A rotting and dangerous looking bridge 
    across a perilous, mist-filled gorge appears to be the only way to continue 
    [our] quest." 
It is north of The Edge of the Abyss. 
Through it is the Far Beyond. 
The Bridge of Death is scenery. 
The bridge is open and unopenable.

Chapter 2 - Scenery

The gorge is a backdrop. "An eerie mist billows forth, obscuring the bottomless 
    gorge below." 
The gorge is everywhere. 
Understand "mist/gorge" or "gorge of eternal peril" as the gorge. 
Understand "edge" or "abyss" as the gorge.

The path is a backdrop in the Edge of the Abyss. 
"The narrow, treacherous path leads back up into that Cave of Caerbannog, away 
    from the bridge."

The cavern is a backdrop in the Edge of the Abyss. 
"The steep, sharp sides of the cavern disappear into the darkness from whence 
    [we] came."

The new path is a backdrop in the Far Beyond. 
"The narrow, treacherous path leads up into the mist and away from the bridge." 
Understand "path" as the new path.

The new bridge is scenery in the Far Beyond. 
The description of the new bridge is "A rotting and dangerous looking bridge 
    across a perilous, mist-filled gorge [we] have just crossed. It no 
    longer prevents [us] from continuing [our] quest." 
Understand "bridge" as the new bridge.

Chapter 3 - Characters

The bridgekeeper is a man in the Edge of the Abyss. 
The initial appearance of the bridgekeeper is "[We] can see the old man from 
    Scene 24 here." 
The description of the bridgekeeper is "The man is a broken-down example of a 
    human being, with wild hair and blind eyes that peer in different 
    directions and never at [us]." 
Understand "old", "man", "from", "scene", and "24" as the bridgekeeper.

Chapter 4 - Things

The coconut is a thing. 
The description is "There are two halves to this coconut." 
The player carries it.

Part 4 - Going Operations

Chapter 1 - Retreating

Retreating is an action applying to nothing.
Understand "go back" as retreating. 
Understand "back" or "return" or "retreat" as retreating. 

Carry out retreating:
    if the location is the Edge of the Abyss, try going up instead;
    otherwise try going south instead.

Chapter 2 - Going Nowhere

instead of going nowhere:
    if the location is Edge of the Abyss:
        if the noun is:
            -- south:
                say "[rockface block].";
            -- east:
                say "[rockface block].";
            -- west:
                say "[gorge block].";
            -- northeast:
                say "[gorge block].";
            -- northwest:
                say "[gorge block].";
            -- southeast:
                say "[rockface block].";
            -- southwest:
                say "[backup block].";
            -- up:
                say "[backup block].";
            -- down:
                say "[gorge block].";
    otherwise if the location is the Far Beyond:
        if the noun is:
            -- north:
                end the game victoriously;
            -- south:
                say "[crossing block].";
            -- east:
                say "[hillside block].";
            -- west:
                say "[hillside block].";
            -- northeast:
                say "[hillside block].";
            -- northwest:
                say "[hillside block].";
            -- southeast:
                say "[gorge block].";
            -- southwest:
                say "[gorge block].";
            -- up:
                end the game victoriously;
            -- down:
                say "[gorge block]."
    
To say rockface block:
    say "There's a solid rock cavern wall blocking [our] path".

To say gorge block:
    say "There are easier ways to get into the Gorge of Eternal Peril than 
        jumping down from here".

To say backup block:
    say "[We] could climb back up the cavern into the Cave of Caerbannog, 
        but [our] quest is in the other direction".

To say crossing block:
    say "[We] successfully crossed the Bridge of Death. Crossing back is as 
        useful as throwing [ourselves] into the Gorge of Eternal Peril".

To say hillside block:
    say "The hill is rather steep and difficult to climb. If only there were 
        a path [we] could follow to make travel easier".

instead of going north from the edge of the abyss, try going the bridge of death.

Instead of going the bridge of death while quest continues is false:
    display the Figure of Bridgekeeper;
    say "'STOP![line break]Who would cross the bridge of death must answer me 
        these questions three, ere the other side he see.' says the 
        Bridgekeeper.";
    now the command prompt is "What is your name? >".

Instead of entering the new bridge in the far beyond, try going south.

Part 5 - Talking Operations

Instead of telling someone about something, try asking the noun about it. 
Instead of answering the noun that something, try asking the noun about it.

Instead of asking the bridgekeeper about something:
    display the Figure of Bridgekeeper;
    if "[the topic understood]" matches the text "grail", case insensitively:
        say "The bridgekeeper's blind eye stares blankly at [us] as he 
            says 'Seek you the Bridge of Death.'";
    otherwise if "[the topic understood]" matches the text "cave", case 
      insensitively:
        say "The bridgekeeper's blind eye stares blankly at [us] as he 
            says 'Heh, heh, heh, heh, heh. We know of a cave; a cave 
            which no man has entered; the Cave of Caerbannog.'";
    otherwise if "[the topic understood]" matches the text "bridge", case 
      insensitively:
        say "The bridgekeeper's blind eye stares blankly at [us] as he 
            says 'Who would cross the bridge of death must answer 
            me these questions three, ere the other side he see.'";
    otherwise if "[the topic understood]" matches the text "gorge", case 
      insensitively or "[the topic understood]" matches the text "peril", 
      case insensitively:
        say "The bridgekeeper's blind eye stares blankly at [us] as he 
            says 'There is much danger, for beyond the cave lies the
            Gorge of Eternal Peril, which no man has ever crossed.'";
    otherwise if "[the topic understood]" matches the text "question", case 
      insensitively:
        say "'STOP![line break]Who would cross the bridge of death must 
            answer me these questions three, ere the other side he 
            see.' says the Bridgekeeper.";
        now the command prompt is "What is your name? >";
    otherwise:
        say "The bridgekeeper's blind eye stares blankly at [us] as he 
            chuckles [one of]gleefully[or]colorfully[or]laughingly
            [or]wickedly[or]naughtily[purely at random]."

Part 6 - Handling Questions

To decide whether collecting answers:
    if the command prompt is ">", no;
    yes.

To choose the final question:
    let N be a random number between 1 and 100;
    if N is less than 16:
        now final question is 1; 
    otherwise if N is less than 30:
        now final question is 2; 
    otherwise if N is less than 44:
        now final question is 3; 
    otherwise if N is less than 56:
        now final question is 4; 
    otherwise if N is less than 67:
        now final question is 5; 
    otherwise if N is less than 76:
        now final question is 6; 
    otherwise if N is less than 84:
        now final question is 7; 
    otherwise if N is less than 90:
        now final question is 8; 
    otherwise if N is less than 95:
        now final question is 9; 
    otherwise if N is less than 98:
        now final question is 10; 
    otherwise:
        now final question is 11. 

To complete failed questioning:
    now the command prompt is ">";
    say "The bridgekeeper chuckles gleefully and [we] are launched into 
        the Gorge of Eternal Peril!";
    now the player is in Eternal Peril.

To complete successful questioning:
    if the bridgekeeper is in the location, say "The bridgekeeper says: 
        'Right, off you go.'";
    now the command prompt is ">".
    
To complete launching bridgekeeper:
    say "The bridgekeeper looks surprised and alarmed. 'What? I don't 
        know that!' he says, before being launched into the Gorge of 
        Eternal Peril.";
    now the bridgekeeper is in Eternal Peril;
    now quest continues is true;
    now questions answered is 3.

After reading a command when collecting answers:
    if questions answered is:
        -- 0:
            let txtLongName be some text;
            repeat through the Table of Allowed Names:
                if "[the player's command]" matches the text 
                  "[shortname entry]", case insensitively:
                    now txtLongName is "[fullname entry]";
            if txtLongName is not empty:
                now questions answered is 1;
                say "The bridgekeeper says: 'Correct. Your name 
                    is [txtLongName].'";
                now the command prompt is "What is your quest? >";
            otherwise:
                complete failed questioning;
                say "You might try remembering which knights 
                    appeared in the scene.";
        -- 1:
            if "[the player's command]" matches the text "grail", case 
              insensitively:
                choose the final question;
                choose row final question from the Table of Final Questions;
                now questions answered is 2;
                say "The bridgekeeper says: 'Correct. Your quest
                    is the Holy Grail.'";
                now the command prompt is "[query entry] >";
            otherwise:
                complete failed questioning;
                say "I would have thought the answer was obvious. 
                    Think 'Monty Python and...'";
        -- 2:
            repeat through the Table of Final Questions:
                if the id entry is the final question:
                    if the final question is 1:
                        now quest continues is true;
                        now questions answered is 3;
                    otherwise if the final question is 7:
                        if "[the player's command]" matches the regular 
                          expression "[answer entry]":
                            complete launching bridgekeeper;
                    otherwise if the final question is 2 or the final 
                        question is 3 or the final question is 4:
                        if "[the player's command]" matches the regular 
                          expression "[answer entry]", case insensitively:
                            now quest continues is true;
                            now questions answered is 3;
                    otherwise if the final question is 11:
                        now quest continues is false;
                    otherwise if "[the player's command]" matches the text 
                      "[answer entry]", case insensitively:
                        now quest continues is true;
                        now questions answered is 3;
            if quest continues is false, complete failed questioning;
            otherwise complete successful questioning;
    reject the player's command.

Table of Final Questions
id query                                answer
1  "What is your favorite color?"       --
2  "What is the capital of Assyria?"    "(?i)assur|nimrud|dur sarukin|nineveh"
3  "What is the answer to the ultimate  "(?i)42|forty-two|forty two"
       question of life, the universe 
       and everything?"
4  "Shall we play a game?"              "(?i)y|yes|thermonuclear war"
5  "Surely, you can't be serious?"      "don't call me shirley"
6  "What are you rebelling against?"    "what you got"
7  "What is the airspeed velocity of    "(?i)african or european|european or african"
       an unlaiden swallow?"
8  "Who you gonna call?"                "ghostbusters"
9  "Who framed Roger Rabbit?"           "judge doom"
10 "How can the net amount of entropy   "insufficient data"
       of the universe be massively 
       decreased?"
11 "Did you ever dance with the devil   --
       in the pale moonlight?"

[The (revised) weighted list is used to select the third question. This list 
gives each question the following chance to be selected:
    
1    15% (1-15)    Source: Monty Python and the Holy Grail (1975)
2    15% (16-30)   Source: Monty Python and the Holy Grail (1975)
3    14% (31-44)   Source: The Hitchhiker's Guide to the Galaxy (1978)
4    12% (45-56)   Source: War Games (1983)
5    11% (57-67)   Source: Airplane! (1980)
6     9% (68-76)   Source: The Wild One (1953)
7     8% (77-84)   Source: Monty Python and the Holy Grail (1975)
8     6% (85-90)   Source: Ghostbusters (1984)
9     5% (91-95)   Source: Who Framed Roger Rabbit? (1988)
10    3% (96-98)   Source: The Last Question by Isaac Asimov © 1956*
11    2% (99-100)  Source: Batman (1989)

* Full answer is: "INSUFFICIENT DATA FOR MEANINGFUL ANSWER"]

Table of Allowed Names
shortname          fullname
"arthur"           "Arthur, King of the Britons"
"lancelot"         "Sir Lancelot of Camelot"
"bedevere"         "Sir Bedevere of Camelot"
"galahad"          "Sir Galahad of Camelot"
"robin"            "Sir Robin of Camelot"
"not appearing"    "Sir Not-Appearing-In-This-Film"

Part 7 - Other Operations

Chapter 1 - Panicking

Understand "panic" as panicking. Understand "scream for help" as panicking. 
Panicking is an action applying to nothing.

Carry out panicking:
    say "[one of]Not surprised.[or]No, no, no. DON'T panic![or]Would [we] 
        like some toast?[at random]" instead.

Chapter 2 - Not Panicking

Understand "don't panic" as panicking anyway. 
Panicking anyway is an action applying to nothing.

Carry out panicking anyway:
    if the player is in Eternal Peril:
        say "Very clever. It looks like there's a lot [we] should be 
            panicking about." instead;
    otherwise:
        say "[one of]Why not? [Our] position appears quite hopeless[or]
            [We] try [our] best. [We] fail[or]I always thought 
            something was fundamentally wrong with the universe[at 
            random]." instead.

Chapter 3 - Helping (Actually Not)

Understand "help" as summoning help. 
Summoning help is an action applying to nothing.

Carry out summoning help:
    if the player is in Eternal Peril:
        say "There isn't much anyone can do for [us] now!" instead;
    otherwise:
        say "Why? Are [we] being repressed? [bracket]Bloody peasant.
            [close bracket][paragraph break]" instead.

Part 8 - Ending the Game

Every turn when the location is Eternal Peril:
    increase peril counter by 1;
    if peril counter is 3:
        end the game perilously.

Report an actor waiting when the location is Eternal Peril (this is the eternal 
    peril report waiting rule):
    if the actor is the player:
        if the action is not silent:
            now the prior named object is nothing;
            say "Time [pass] perilously." instead;
    otherwise:
        say "[The actor] [wait] perilously." instead.

Instead of doing anything other than examining, looking, waiting, summoning 
  help, panicking, or panicking anyway when the location is Eternal Peril:
    decrease peril counter by 1;
    say "[We][']re in too much peril to think about doing that right now." 
        instead.

To end the game perilously:
    end the story finally saying "[We] succumb to the peril".

To end the game victoriously:
    end the story finally saying "Congratulations! [Our] Quest for the Holy 
        Grail Continues!".