Chapter 19: Advanced Text
19.8. Replacements

Suppose V is an indexed text which varies - perhaps a property of something, or a variable defined everywhere, or a temporary "let"-named value. How do we change its contents? The easiest way is simply to assign text to it. Thus:

let V be "It is now [the time of the day in words]."

And, for instance,

let V be "[V]!"

adds an exclamation mark at the end of V.

Otherwise, it is more useful (also a little faster) to modify V by changing its characters, words and so on. Thus:

replace character number (number) in (indexed text) with (indexed text)

This phrase acts on the named text by placing the given text in place of the Nth character, counting from 1. Example:

let V be an indexed text;
let V be "mope";
replace character number 3 in V with "lecul";
say V;

says "molecule".

replace word number (number) in (indexed text) with (indexed text)

This phrase acts on the named text by placing the given text in place of the Nth word, counting from 1, and dividing words at spacing or punctuation. Example:

let V be an indexed text;
let V be "Does the well run dry?";
replace word number 3 in V with "jogger";
say V;

says "Does the jogger run dry?".

replace punctuated word number (number) in (indexed text) with (indexed text)

This phrase acts on the named text by placing the given text in place of the Nth word, counting from 1, and dividing words at spacing, counting punctuation runs as words in their own right. Example:

let V be an indexed text;
let V be "Frankly, yes, I agree.";
replace punctuated word number 2 in V with ":";
say V;

says "Frankly: yes, I agree.".

replace unpunctuated word number (number) in (indexed text) with (indexed text)

This phrase acts on the named text by placing the given text in place of the Nth word, counting from 1, and dividing words at spacing, counting punctuation as part of a word just as if it were lettering. Example:

let V be an indexed text;
let V be "Frankly, yes, I agree.";
replace unpunctuated word number 2 in V with "of course";
say V;

says "Frankly, of course I agree.".

replace line number (number) in (indexed text) with (indexed text)

This phrase acts on the named text by placing the given text in place of the Nth line, counting from 1. Lines are divided by paragraph or line breaks.

replace paragraph number (number) in (indexed text) with (indexed text)

This phrase acts on the named text by placing the given text in place of the Nth paragraph, counting from 1.

Last, but not least, we can replace text wherever it occurs:

replace the text (indexed text) in (indexed text) with (indexed text)

This phrase acts on the named text by searching and replacing, as many non-overlapping times as possible. Example:

replace the text "a" in V with "z"

changes every lower-case "a" to "z": the same thing done with the "case insensitively" option would change each "a" or "A" to "z".

All very well for letters, but it can be unfortunate to try

replace the text "Bob" in V with "Robert"

if V happens to contain, say "The Olympic Bobsleigh Team": it would become "The Olympic Robertsleigh Team". What we want, of course, is for Bob to become Robert only when it's a whole word. We can get that with:

replace the word (indexed text) in (indexed text) with (indexed text)

This phrase acts on the named text by searching and replacing, as many non-overlapping times as possible, where the search text must occur as a whole word. Example:

replace the word "Bob" in V with "Robert"

changes "Bob got on the Bobsleigh" to "Robert got on the Bobsleigh".

replace the punctuated word (indexed text) in (indexed text) with (indexed text)

This phrase acts on the named text by searching and replacing, as many non-overlapping times as possible, where the search text must occur as a whole word or run of punctuation.

But these are all just special cases of the grand-daddy of all replacement phrases:

replace the regular expression (indexed text) in (indexed text) with (indexed text)

This phrase acts on the named text by matching the regular expression and replacing anything which fits it, as many non-overlapping times as possible. Example:

replace the regular expression "\d+" in V with "..."

changes "The Battle of Waterloo, 1815, rivalled Trafalgar, 1805" to "The Battle of Waterloo, ..., rivalled Trafalgar, ...". The "case insensitively" causes lower and upper case letters to be treated as if the same letter.

When replacing a regular expression, the replacement text also has a few special meanings (though, thankfully, many fewer than for the expression itself). Once again "\n" and "\t" can be used for line break and tab characters, and "\\" must be used for an actual backslash. But, very usefully, "\1" to "\9" expand as the contents of groups numbered 1 to 9, and "\0" to the exact text matched. So:

replace the regular expression "\d+" in V with "roughly \0"

adds the word "roughly" in front of any run of digits in V, because \0 becomes in turn whichever run of digits matched. And

replace the regular expression "(\w+) (.*)" in V with "\2, \1"

performs the transformation "Frank Booth" to "Booth, Frank".

Finally, prefixing the number by "l" or "u" forces the text it represents into lower or upper case, respectively. For instance:

replace the regular expression "\b(\w)(\w*)" in X with "\u1\l2";

changes the casing of X to "title casing", where each individual word is capitalised. (This is a little slow on large texts, since so many matches and replacements are made: it's more efficient to use the official phrases for changing case.)


408
* Example  Blackout
Filtering the names of rooms printed while in darkness.

RB
409
* Example  Igpay Atinlay
A pig Latin filter for the player's commands.

RB
410
* Example  Fido
A dog the player can name and un-name at will.

RB
411
** Example  Northstar
Making Inform understand ASK JOSH TO TAKE INVENTORY as JOSH, TAKE INVENTORY. This requires us to use a regular expression on the player's command, replacing some of the content.

RB
412
** Example  Mr. Burns' Repast
Letting the player guess types for an unidentifiable fish.

RB

Suppose we have an unhappily mutated fish that the player can refer to by any of a number of species names, or any word followed by -fish. We want to reject these commands, but preserve a memory of what the player last tried to call the thing:

"Mr. Burns' Repast"

Wharf is a room.

There is an unknown fish in the Wharf. The unknown fish has some indexed text called supposed name. The description of the unknown fish is "The victim of heavy mutagens, this thing is not really recognizable as any species you know.".

Fish variety is a kind of value. The fish varieties are salmon, albacore, mackerel.

Rule for printing the name of the unknown fish:
    if the supposed name of the unknown fish is "", say the printed name of the unknown fish;
    otherwise say the supposed name of the unknown fish.

After reading a command:
    let N be indexed text;
    if the unknown fish is visible and player's command matches the regular expression "\b\w+fish":
        let N be the player's command;
        replace the regular expression ".*(?=\b\w+fish)" in N with "";
        now N is "[N](?)";
        now the supposed name of the unknown fish is N;
        respond with doubt;
        reject the player's command;
    otherwise if the unknown fish is visible and the player's command includes "[fish variety]":
        now supposed name of the fish is "[fish variety understood](?)";
        respond with doubt;
        reject the player's command.

To respond with doubt:
    say "You're not [italic type]sure[roman type] you're seeing any such thing."

Test me with "get swordfish / look / touch monkfish / look / listen to tunafish / x fish / x salmon / look".

413
*** Example  Cave-troll
Determining that the command the player typed is invalid, editing it, and re-examining it to see whether it now reads correctly.

RB


PreviousContentsNext