Turbo Pascal 2.0 course cover
← Back to Courses
module
29

Pushing A Crate

Introduction

The worker can walk. Now he gets his job: pushing crates. It is one rule, and the whole puzzle grows out of it - a crate moves only when it is pushed, only one square, and only if there is room for it.

Room To Push

When the worker steps towards a crate, two squares matter: the crate's, one step ahead - NR, NC - and the one beyond it, two steps ahead, NR + DR, NC + DC. The push happens only if both are right:

if (L.Grid[NR, NC] in
     [Crate, Stored]) and
   (L.Grid[NR + DR, NC + DC] in
     [Floor, Goal]) then

There is a crate ahead - on a goal or not - and the square beyond is floor or a goal. A wall beyond, or another crate, and nothing moves: the worker can push one crate, never two.

Sets make this read almost as it would in English, and they make it hard to get wrong. Without them, the same test would be a tangle of four comparisons joined by or and and.

Lift And Drop

Moving a crate is two jobs: take it off one square, put it on another. Each must remember the goals:

  • Lift takes a crate off a square. A Crate leaves Floor; a Stored crate leaves the Goal it was standing on.
  • Drop puts a crate on a square. On Floor it becomes a Crate; on a Goal it becomes Stored.

Each redraws its square as it goes.

And Then He Steps

Go pushes first, then does exactly what it did before: if the square ahead is now floor or a goal - because the crate has just left it - he steps into it. If the push could not happen, the crate is still there, and he stays put. Nothing else in Go had to change.

The Code

Start WARE3 from WARE2: W WARE3, E, CTRL-K CTRL-R, WARE2.

After Delta, before Go, add:

procedure Lift(Row, Col: Integer);
begin
  if L.Grid[Row, Col] = Crate then
    L.Grid[Row, Col] := Floor
  else
    L.Grid[Row, Col] := Goal;
  Show(Row, Col);
end;

procedure Drop(Row, Col: Integer);
begin
  if L.Grid[Row, Col] = Floor then
    L.Grid[Row, Col] := Crate
  else
    L.Grid[Row, Col] := Stored;
  Show(Row, Col);
end;

In Go, straight after NC := C + DC;, add the push:

  if (L.Grid[NR, NC] in
       [Crate, Stored]) and
     (L.Grid[NR + DR, NC + DC] in
       [Floor, Goal]) then
  begin
    Lift(NR, NC);
    Drop(NR + DR, NC + DC);
  end;

so that Go now reads:

procedure Go(Key: Char);
var
  DR, DC, NR, NC: Integer;
begin
  Delta(Key, DR, DC);
  NR := R + DR;
  NC := C + DC;
  if (L.Grid[NR, NC] in
       [Crate, Stored]) and
     (L.Grid[NR + DR, NC + DC] in
       [Floor, Goal]) then
  begin
    Lift(NR, NC);
    Drop(NR + DR, NC + DC);
  end;
  if L.Grid[NR, NC] in [Floor, Goal]
  then
  begin
    R := NR;
    C := NC;
    Show(R - DR, C - DC);
    Show(R, C);
  end;
end;

Starting from

WARE2 from S28, read into a new work file WARE3. Make the changes, CTRL-K CTRL-D, S, R.

What you should see

The first level again. Walk round behind the crate - LEFT, LEFT, UP - and push it with RIGHT, RIGHT. It slides onto the goal and turns into **.

The crate pushed onto its goal

Push it on, off the goal, and the .. comes back. Try to push it into a wall: nothing happens. The game does not yet notice that you have finished; that is next.

Change One Thing

  • Take out the line Lift(NR, NC); in Go, and push the crate. What appears, and why does the worker not move?
  • Take out the Show(Row, Col); at the end of Drop. Push the crate onto the goal, then step away. Where is the crate?
  • Replace the whole if in Lift with L.Grid[Row, Col] := Floor;. Push the crate onto the goal and then off it again. What has happened to the goal?

Exercises

29.1 Count the pushes - only the steps that moved a crate - and show Pushes and the count on the top line.

29.2 A crate pushed into a corner, not on a goal, can never be moved again. Write a function Cornered(R0, C0) that is True when the square has a wall above or below it and a wall to its left or right, and make Go print Stuck! when it pushes a crate into such a square.

29.3 Write a function Home that counts the crates on goals, and show On goals and the count after every key.

Worked solutions are in Appendix II.

When It Goes Wrong

SymptomCause
The crate will not moveThe two tests are the wrong way round, or Lift and Drop have their squares swapped. The crate is one step ahead; the free square is two.
Crates multiplyLift is missing: the new crate is dropped, the old one never taken away.
A crate disappears, but is still in the wayDrop does not Show the square it put the crate on.
Goals vanish after a crate has been on themLift always leaves Floor; it must leave Goal under a Stored crate.

Summary

A push needs a crate one step ahead and a free square - floor or a goal - two steps ahead; two sets say so in one if. Lift and Drop move a crate off and onto squares, keeping the goals underneath. After the push, the worker steps as before.

Next

S30, A Level Complete - noticing the last crate going home, and moving on to the next level.

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.