
Part three builds BEACON, a section at a time, from the best of what parts one and two found. It starts with the world itself. In DRIFT, the BBC BASIC course's adventure, the four rooms are lines of DATA in the program. BEACON's twelve are records in a file, and the program does not hold a word of their description.
Room = record
Name: Str16;
Exits: array[1..6] of Byte;
end;
The exits are room numbers, in the order north, south, east, west, up, down; 0 means there is no way that way. The beach is room 1, and its exits are 5 3 4 2 0 0: north to room 5, the cliff path, south to the jetty, east to the shed, west to the cove, and no up or down.
The twelve records are in BEACON.DAT, one after another, and the program reads them all into Map, an array of twelve rooms, when it starts. Each record is 23 bytes, 17 for the name and 6 for the exits, so the whole map is 276 bytes of memory.
The description is not in the record. Room N's description is message N in BEACON.MSG, S13's file: the rooms are its first twelve messages. So Look prints Map[Here].Name from memory and then Say(Here) from the disc.
Both files are made from BEACON.TXT by MAKEDAT, which is on the disc. It is S13's MAKEMSG with one addition: when a line starts *ROOM, it makes a room record as well. The name is the rest of that line, and the next line's six numbers are read straight into the exits with Read:
for I := 1 to 6 do
Read(T, R.Exits[I]);
Readln(T);
Read of a number from a text file takes the next number on the line, skipping the spaces; Readln(T) then moves on to the next line.
program MakeDat;
type
Str255 = string[255];
Str16 = string[16];
Room = record
Name: Str16;
Exits: array[1..6] of Byte;
end;
var
T: Text;
F: file of Str255;
D: file of Room;
Line, Msg: Str255;
R: Room;
N, I: Integer;
begin
Assign(T, 'BEACON.TXT');
Reset(T);
Assign(F, 'BEACON.MSG');
Rewrite(F);
Assign(D, 'BEACON.DAT');
Rewrite(D);
N := 0;
while not Eof(T) do
begin
Readln(T, Line);
if Copy(Line, 1, 1) = '*' then
begin
if N > 0 then
Write(F, Msg);
N := N + 1;
FillChar(Msg, SizeOf(Msg), 0);
if Copy(Line, 1, 5) = '*ROOM' then
begin
FillChar(R, SizeOf(R), 0);
R.Name := Copy(Line, 7, 16);
for I := 1 to 6 do
Read(T, R.Exits[I]);
Readln(T);
Write(D, R);
end;
end
else if (N > 0) and (Line <> '') then
begin
if Msg <> '' then
Msg := Msg + '|';
Msg := Msg + Line;
end;
end;
Close(T);
Writeln(FileSize(D), ' rooms, ',
FileSize(F), ' messages');
Close(D);
Close(F);
end.
You need not type it: it is on the disc as MAKEDAT.PAS. Load it with W, MAKEDAT, and run it with R, and it says 12 rooms, 27 messages. Run it whenever you change BEACON.TXT, and the game changes with it, without one line of the game being touched.
program Beacon;
const
Rooms = 12;
type
Str255 = string[255];
Str16 = string[16];
Room = record
Name: Str16;
Exits: array[1..6] of Byte;
end;
var
Map: array[1..Rooms] of Room;
Msg: file of Str255;
Here: Integer;
procedure Wrap(S: Str255);
var
P: Integer;
begin
S := S + '|';
while S <> '' do
begin
P := Pos('|', S);
if P > 40 then
begin
P := 40;
while S[P] <> ' ' do
P := P - 1;
end;
Writeln(Copy(S, 1, P - 1));
Delete(S, 1, P);
end;
end;
procedure Say(N: Integer);
var
S: Str255;
begin
Seek(Msg, N - 1);
Read(Msg, S);
Wrap(S);
end;
procedure Load;
var
D: file of Room;
I: Integer;
begin
Assign(D, 'BEACON.DAT');
Reset(D);
for I := 1 to Rooms do
Read(D, Map[I]);
Close(D);
Assign(Msg, 'BEACON.MSG');
Reset(Msg);
end;
procedure Look;
begin
Writeln;
Writeln(Map[Here].Name);
Say(Here);
end;
begin
Load;
Here := 1;
Look;
Close(Msg);
end.
Wrap and Say are S13's, unchanged. Load reads the map and opens the messages, leaving BEACON.MSG open for the whole game.
Starting from
A new work file BEACON1, on the primer's disc. Save it before you run it (S); S18 starts from it.
What you should see
Beach
You are on a strip of shingle at the
foot of the cliffs. Wreckage from your
boat rolls in the surf. A path climbs
north. The beach runs west to a cove
and south to a jetty, and a store shed
stands to the east.
Here := 1 to Here := 12. Where are you?Look, change Say(Here) to Say(Here + 12). What does the beach say now, and where did that come from?Writeln(Map[Here].Name) to Writeln(Map[Here + 1].Name).17.1 Instead of looking at room 1, print the number and name of every room.
17.2 After the description, list the beach's exits by direction and the name of the room each leads to: North to Cliff Path.
17.3 Print how many messages there are in BEACON.MSG.
Worked solutions are in Appendix II.
| Symptom | Cause |
|---|---|
I/O error 01 | BEACON.DAT or BEACON.MSG is not on the disc. Run MAKEDAT. |
| The wrong description under a name | The message number is off by one, or the rooms in BEACON.TXT are not in the same order as the messages. |
A room is a record: a name and six exits. MAKEDAT turns BEACON.TXT into twelve room records in BEACON.DAT and 27 messages in BEACON.MSG. The game reads the map into an array, and prints each room's description straight from the disc when it needs it.
S18, Moving And Looking: the parser from part one joins the game.
This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.