
Every turn of an adventure starts the same way: the player types a line and presses ENTER. Turbo has a statement that does exactly that, and it is the obvious choice. This section builds a second way, and you will find that on the Einstein the second way is the better one.
Readln(Line);
waits for a line, lets the player correct it, and puts it in Line when ENTER is pressed. Three things about it matter for an adventure.
It cuts what does not fit. A string[30] keeps the first thirty characters of the line and drops the rest, without a word.
It does not split the line into words. It is tempting to write Readln(Verb, Noun) with two string variables and hope for a verb in one and a noun in the other. What happens is that the first variable takes as many characters as it can hold, and the second gets whatever is left. With two string[10]s, TAKE THE LAMP gives TAKE THE L and AMP. Taking the line apart is your job, and S6's.
Its correcting keys are not the Einstein's. While a Readln waits, CONTROL and H, or SHIFT and TAB, rub out the last character, and CONTROL and X clears the line. The DELETE key does nothing at all. A player who reaches for DELETE gets no help.
Two smaller facts. A line can be at most 127 characters long. And setting BufLen just before a Readln, as BufLen := 10, limits that one Readln to ten characters: the keyboard simply stops taking more. The next Readln is back to 127.
The Turbo course's S24 read single keys with Read(Kbd, Ch): no echo, no ENTER. Build a line out of those and every decision is yours.
Which keys count. Accept a key only if it is a space or a letter: Ch in [' ', 'A'..'Z']. Digits, punctuation and the arrow keys (which type [, ] and ^) are simply ignored.
Capitals. UpCase each key as it arrives, so the player sees capitals whatever CAPS LOCK says, and the rest of the program only ever deals with capitals.
Rubbing out. DELETE arrives as code 25, and CONTROL and H as 8. On either, take the last character off the string with S[0] := Pred(S[0]), and take it off the screen. Write(#8) moves the cursor back one place without erasing, so Write(#8, ' ', #8) steps back, prints a space over the character, and steps back again.
How long. Stop taking keys when the line is full. Nothing is ever cut, because nothing too long ever got in.
Finishing. ENTER is code 13. Stop there, and Writeln to move to a new line.
program TwoWays;
type
Str30 = string[30];
var
Line: Str30;
procedure GetLine(var S: Str30);
var
Ch: Char;
begin
S := '';
repeat
Read(Kbd, Ch);
Ch := UpCase(Ch);
if (Ch in [#8, #25])
and (Length(S) > 0) then
begin
Write(#8, ' ', #8);
S[0] := Pred(S[0]);
end
else if (Ch in [' '..'Z'])
and (Length(S) < 30) then
begin
Write(Ch);
S := S + Ch;
end;
until Ch = #13;
Writeln;
end;
begin
Write('Readln> ');
Readln(Line);
Writeln('[', Line, ']');
Write('GetLine> ');
GetLine(Line);
Writeln('[', Line, ']');
end.
[' '..'Z'] takes everything from the space to Z: digits and punctuation as well as letters. Exercise 4.1 narrows it.
Starting from
Turbo freshly started, Y, a new work file TWOWAYS. Before you run it, press CAPS LOCK once so that letters come out small.
What you should see
At each prompt, type take lamq, press DELETE, then type p and ENTER.
Readln> take lamqp
[take lamqp]
GetLine> TAKE LAMP
[TAKE LAMP]
Readln ignored DELETE and kept the small letters. GetLine rubbed out the q and made capitals as you typed. In MAME: DELETE is Backspace.
Ch := UpCase(Ch);. Type the same thing at GetLine>. What appears, and why? (Look at the set the letters are tested against.)(Length(S) < 30) to (Length(S) < 8). What does GetLine give for the same keys?Write(#8, ' ', #8); (leave the begin, the end and the line after). What does the screen show now, and what is in the string?4.1 Make GetLine accept only letters and spaces, so that go 2 north! arrives as GO NORTH.
4.2 Make CONTROL and X (code 24) clear the whole line, on the screen and in the string, as it does in Readln.
4.3 Write a short program that reads a command with Readln into a string[30], but lets no more than ten characters be typed.
Worked solutions are in Appendix II.
| Symptom | Cause |
|---|---|
GetLine takes nothing at all | Small letters, with no UpCase: they are not in [' '..'Z']. |
DELETE does nothing at a Readln | It never does. CONTROL and H, or SHIFT and TAB, rub out there. |
| The characters you rubbed out are still on the screen | GetLine changed the string but not the screen: the Write(#8, ' ', #8) is missing. |
Readln is one statement, but it ignores the Einstein's DELETE key, keeps whatever case was typed, and silently cuts a long line. A line read with Read(Kbd, Ch) one key at a time can take DELETE, make capitals as the player types, refuse characters you do not want, and stop at exactly the length you choose. BEACON uses the second way.
S5, Tidying It Up: a line typed by a person is untidy, and the parser wants it clean.
This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.