Turbo Pascal Text Adventure Primer cover: BEACON, the adventure the primer builds in Turbo Pascal 2.0, mid-game on the Tatung Einstein
← Back to Modules
module
10

Understanding The Sentence

Introduction

Two words are enough for TAKE LAMP. They are not enough for UNLOCK THE DOOR WITH THE KEY. This section builds the parser BEACON uses: it reads a sentence of up to four kinds of word, throws away the words that carry no meaning, and works out what the player asked for.

Four Kinds Of Word

Every word in the table now has a kind as well as a place:

type
  Kind = (Unknown, Verb, Noun, Prep, Noise);
KindWordsWhat the parser does
VerbTAKE, OPEN, UNLOCKremembers it in V
NounLAMP, DOOR, KEYthe first noun in N1, a noun after a preposition in N2
PrepWITH, INremembers it in P
NoiseTHE, A, ANnothing at all

Noise words need no code: the case on the kind has no branch for Noise, so they fall through and are forgotten. That is all "skipping" them takes.

UNLOCK THE DOOR WITH THE KEY comes out as V = UNLOCK, N1 = DOOR, P = WITH, N2 = KEY.

A Word It Does Not Know

When Find returns 0, the parser stops at once and says which word it was: I don't know SWORD. It is the single most useful thing a parser can tell a player, and Zork does the same, quoting the unknown word back (S7). Parse returns False, so the rest of the program knows not to act.

Verbs That Need A Noun

LOOK makes sense alone. GET does not. A set says which verbs need a noun:

NeedNoun: set of 1..Count = [1, 2, 3, 4, 6];

The numbers are places in the table: TAKE, GET, OPEN, UNLOCK and FILL. When one of them comes without a noun, the program asks: What do you want to GET?

The Code

program Sentence;
type
  Str12 = string[12];
  Str40 = string[40];
  Kind = (Unknown, Verb, Noun,
          Prep, Noise);
const
  Count = 16;
  Words: array[1..Count] of Str12 =
    ('TAKE', 'GET', 'OPEN', 'UNLOCK',
     'LOOK', 'FILL', 'LAMP', 'KEY',
     'DOOR', 'OIL', 'CROWBAR', 'WITH',
     'IN', 'THE', 'A', 'AN');
  Kinds: array[1..Count] of Kind =
    (Verb, Verb, Verb, Verb, Verb,
     Verb, Noun, Noun, Noun, Noun,
     Noun, Prep, Prep, Noise, Noise,
     Noise);
  NeedNoun: set of 1..Count =
    [1, 2, 3, 4, 6];
var
  Line: Str40;
  V, N1, P, N2: Integer;

function Find(W: Str12): Integer;
var
  I, Found: Integer;
begin
  Found := 0;
  for I := 1 to Count do
    if Words[I] = W then
      Found := I;
  Find := Found;
end;

function Parse(S: Str40): Boolean;
var
  W: Str12;
  K, Pl: Integer;
  Ok: Boolean;
begin
  V := 0; N1 := 0; P := 0; N2 := 0;
  Ok := True;
  S := S + ' ';
  while Ok and (S <> '') do
  begin
    Pl := Pos(' ', S);
    W := Copy(S, 1, Pl - 1);
    Delete(S, 1, Pl);
    if W <> '' then
    begin
      K := Find(W);
      if K = 0 then
      begin
        Writeln('I don''t know ', W);
        Ok := False;
      end
      else
        case Kinds[K] of
          Verb: V := K;
          Prep: P := K;
          Noun: if P = 0 then N1 := K
                else N2 := K;
        end;
    end;
  end;
  Parse := Ok;
end;

begin
  repeat
    Write('> ');
    Readln(Line);
    if Parse(Line) then
      if V = 0 then
        Writeln('There is no verb.')
      else if (V in NeedNoun)
              and (N1 = 0) then
        Writeln('What do you want to ',
                Words[V], '?')
      else
      begin
        Write(Words[V]);
        if N1 > 0 then
          Write(' ', Words[N1]);
        if P > 0 then
          Write(' ', Words[P]);
        if N2 > 0 then
          Write(' ', Words[N2]);
        Writeln;
      end;
  until Line = '';
end.

The table is short enough to search straight down; BEACON's, in S18, is in order and searched S9's way.

Starting from

A new work file SENTENCE. Type in capitals. ENTER alone ends it.

What you should see

> TAKE THE LAMP
TAKE LAMP
> UNLOCK THE DOOR WITH THE KEY
UNLOCK DOOR WITH KEY
> GET
What do you want to GET?
> LOOK
LOOK
> TAKE THE SWORD
I don't know SWORD
> THE LAMP
There is no verb.
> FILL LAMP WITH OIL
FILL LAMP WITH OIL

Change One Thing

  • Add 5 to NeedNoun. What does LOOK say now?
  • Change the Noun: branch to Noun: N1 := K;. What do the two sentences with WITH come out as?
  • In the main program, change Words[V] in the question to W. What does the compiler say, and why can the main program not see W?

Exercises

10.1 Put S5's Tidy in front of Parse, so that Take the lamp! and unlock door, with key. work.

10.2 Make GET a true synonym of TAKE: add a typed constant Same that gives, for each word, the word it means, and have the parser keep that in V. GET alone should then ask What do you want to TAKE?

10.3 A preposition with no noun after it is a half-finished sentence. Answer OPEN THE DOOR WITH with WITH what?

Worked solutions are in Appendix II.

When It Goes Wrong

SymptomCause
The second noun replaces the firstThe Noun branch does not look at P.
Error 41 naming a word you used in ParseVariables declared in a function belong to it.
There is no verb for a sentence with a verbThe verb's kind in the table is wrong, or the lists are out of step.

Summary

Every word has a kind: verb, noun, preposition or noise. The parser keeps the verb, the first noun, the preposition and the noun after it; noise words fall through the case and vanish; an unknown word stops the parse with its name; a set says which verbs need a noun. That is the whole of BEACON's parser.

Next

S11, Text In The Program: part two begins. The game has a great deal to say. Where does it all go?

Get the Newsletter

New guides, disk images and community finds, roughly once a quarter. No spam, we promise, this isn't Tatung's marketing department.
Your subscription could not be saved. Please try again.
Your subscription has been successful.

Newsletter

Subscribe to our newsletter and stay updated.

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.