Turbo Pascal 2.0 course cover
← Back to Courses
module
31

Levels From A File

Introduction

The six levels are part of the program. To change one, you change the program; to add one, you change the program and Count. And in S32 the game will want to remember each level's best score - which no program can do by changing its own constants.

So the levels move to the disc, into a file called LEVELS.DAT, one record per level. The game reads the level it needs when it needs it, and later sections write to the same file: the best scores, and levels you design.

A File Of Levels

S21's files of records were made for exactly this:

F: file of Level;

Each record is one whole Level - its name, its grid, its start and its best score - and they are numbered from 0. Level N is record N - 1.

ReadLevel reads level N:

Reset(F);
Seek(F, N - 1);
Read(F, L);
Close(F);

It opens the file, goes straight to the record, reads it into L and closes the file again. Closing after every use keeps the disc's directory up to date, as Borland's manual advises (S21) - and the game never has to remember whether the file is open.

The First Time

The very first time the game runs, there is no LEVELS.DAT. OpenFile finds out, with S21's trick:

{$I-}
Reset(F);
{$I+}
if IOresult <> 0 then

If the file is not there, it makes it: Rewrite creates it, and each of the six plans is turned into a level by MakeLevel and written in. Every run after that finds the file and leaves it alone.

Either way, OpenFile sets Total to the number of levels in the file, with FileSize. From now on the game goes by Total, not by Count - so a file with more levels in it means a game with more levels, and not one line of the game has to change.

That first run writes six levels to the disc, and while the disc is writing the Einstein does not take in keys. Wait for the warehouse to appear before you press anything.

The Code

Start WARE5 from WARE4.

Add the file and Total to the variables:

var
  L: Level;
  F: file of Level;
  N, R, C, Total: Integer;
  LeftCol, TopRow: Integer;
  Wide, High: Integer;
  Ch: Char;

Before Start, add the two new procedures:

procedure OpenFile;
var
  K: Integer;
begin
  Assign(F, 'LEVELS.DAT');
  {$I-}
  Reset(F);
  {$I+}
  if IOresult <> 0 then
  begin
    Rewrite(F);
    for K := 1 to Count do
    begin
      MakeLevel(K);
      Write(F, L);
    end;
  end;
  Total := FileSize(F);
  Close(F);
end;

procedure ReadLevel;
begin
  Reset(F);
  Seek(F, N - 1);
  Read(F, L);
  Close(F);
end;

In Start, MakeLevel(N); becomes:

  ReadLevel;

In Won, if N > Count then becomes:

  if N > Total then

And in the main program, OpenFile comes first:

begin
  OpenFile;
  N := 1;
  Start;

Starting from

WARE4 from S30, read into a new work file WARE5. Make the changes, CTRL-K CTRL-D, S, R.

What you should see

The same game as before - which is the point. Behind it, the first run made LEVELS.DAT: quit, press D and ENTER, and it is there in the list.

Change One Thing

  • Take out {$I-} and {$I+} round the Reset in OpenFile. Run it on a disc that has no LEVELS.DAT yet (ERA LEVELS.DAT at the 0: prompt, S6, first). What happens, and where does ESC put the cursor?
  • In ReadLevel, change Seek(F, N - 1) to Seek(F, N). Which level does Level 1 show?
  • Change 'LEVELS.DAT' to 'LEVELS2.DAT'. Run it, quit, and look at D.

Exercises

31.1 Show how many levels there are on the top line, as Level 1 of 6: First Steps.

31.2 Write a separate short program, LEVLIST, that lists the names of all the levels in LEVELS.DAT. It needs the game's const and type for a level, but none of its procedures.

31.3 Write another, ADDLEVEL, that copies level 1 to the end of the file as a new level called First Again. Then run the game: does it know there is a seventh level?

Worked solutions are in Appendix II.

When It Goes Wrong

SymptomCause
I/O error 01 on the first runReset of a file that is not there yet, without {$I-} round it.
The first key is ignored, the first time the game runsThe game was writing LEVELS.DAT. Wait for the warehouse.
A change to Plans makes no differenceThe levels now come from LEVELS.DAT, made before the change. Erase it (ERA LEVELS.DAT at 0:) and the game makes a new one from Plans.
Every level is the next oneSeek(F, N) for Seek(F, N - 1): records count from 0.
You have changed the Level recordThe records already in LEVELS.DAT were written in the old shape. Erase it, and the game makes a new one.

Summary

The levels live in LEVELS.DAT, a file of Level records. OpenFile makes it from Plans the first time, when {$I-} and IOresult show it is missing, and counts the levels with FileSize. ReadLevel opens the file, Seeks to record N - 1, reads it, and closes it. The game now plays whatever levels the file holds.

Next

S32, Counting Moves - a move counter, and the best score for each level, written back into the file.

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.