Skip to content

Look before you walk

Check a proposed step before moving the player.

  • Sinclair ZX Spectrum
  • BASIC

The player can now walk through the warehouse. A direction will propose a destination. Only after checking that destination will we change the player’s coordinates.

Continue from the room with its player at (6,3).

Propose, inspect, then move

Replace line 110.

Add lines 120, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240, 260, 500, 510, 520, 530, 600, 610, 700, 1020, 1030, 1070, 2500, 2540, 3000, 3010, 3020, 3025, 3030, 9000, 9010, 9020.

step-01-edits.bas
 110 GO SUB 3000
 120 IF k$="q" OR k$="Q" THEN GO TO 9000
 150 LET dr=0: LET dc=0
 160 IF k$="i" OR k$="I" THEN LET dr=-1
 170 IF k$="k" OR k$="K" THEN LET dr=1
 180 IF k$="j" OR k$="J" THEN LET dc=-1
 190 IF k$="l" OR k$="L" THEN LET dc=1
 200 IF dr=0 AND dc=0 THEN GO TO 110
 210 LET nr=pr+dr: LET nc=pc+dc
 220 IF nr<1 OR nr>8 OR nc<1 OR nc>8 THEN GO TO 700
 230 LET v=g(nr,nc)
 240 IF v=1 OR v=3 THEN GO TO 700
 260 GO TO 500
 500 LET oldr=pr: LET oldc=pc
 510 LET pr=nr: LET pc=nc: LET moves=moves+1
 520 LET r=oldr: LET c=oldc: GO SUB 2000
 530 LET r=pr: LET c=pc: GO SUB 2000
 600 GO SUB 2500
 610 GO TO 110
 700 GO TO 110
1020 PRINT AT 20,2; INK 7;"I up  J left  K down  L right"
1030 PRINT AT 21,13; INK 5;"Q quit";
1070 GO SUB 2500
2500 PRINT AT 1,2; INK 7;"STEPS ";moves;"    "
2540 RETURN
3000 LET k$=INKEY$
3010 IF k$=h$ THEN GO TO 3000
3020 LET h$=k$
3025 IF k$="" THEN GO TO 3000
3030 RETURN
9000 PAPER 0: INK 7
9010 PRINT AT 21,0;"Finished. RUN to try again.     ";
9020 STOP
Complete program for this step
step-01.bas
  10 GO SUB 7000: LET h$=""
  15 LET room=1
  20 DIM g(8,8)
  30 FOR r=1 TO 8: FOR c=1 TO 8
  40 IF r=1 OR r=8 OR c=1 OR c=8 THEN LET g(r,c)=1
  50 NEXT c: NEXT r
  60 LET g(3,4)=1: LET g(4,4)=1
  70 LET g(3,5)=2: LET g(5,4)=3
  80 LET pr=6: LET pc=3: LET moves=0: LET won=0
 100 GO SUB 1000
 110 GO SUB 3000
 120 IF k$="q" OR k$="Q" THEN GO TO 9000
 150 LET dr=0: LET dc=0
 160 IF k$="i" OR k$="I" THEN LET dr=-1
 170 IF k$="k" OR k$="K" THEN LET dr=1
 180 IF k$="j" OR k$="J" THEN LET dc=-1
 190 IF k$="l" OR k$="L" THEN LET dc=1
 200 IF dr=0 AND dc=0 THEN GO TO 110
 210 LET nr=pr+dr: LET nc=pc+dc
 220 IF nr<1 OR nr>8 OR nc<1 OR nc>8 THEN GO TO 700
 230 LET v=g(nr,nc)
 240 IF v=1 OR v=3 THEN GO TO 700
 260 GO TO 500
 500 LET oldr=pr: LET oldc=pc
 510 LET pr=nr: LET pc=nc: LET moves=moves+1
 520 LET r=oldr: LET c=oldc: GO SUB 2000
 530 LET r=pr: LET c=pc: GO SUB 2000
 600 GO SUB 2500
 610 GO TO 110
 700 GO TO 110
1000 BORDER 0: PAPER 0: INK 7: CLS
1010 PRINT AT 0,2; INK 5;"CRATES";AT 0,24; INK 7;"ROOM 0";room
1020 PRINT AT 20,2; INK 7;"I up  J left  K down  L right"
1030 PRINT AT 21,13; INK 5;"Q quit";
1040 FOR r=1 TO 8: FOR c=1 TO 8
1050 GO SUB 2000
1060 NEXT c: NEXT r
1070 GO SUB 2500
1080 RETURN
2000 LET y=3 +2 *(r-1): LET x=8 +2 *(c-1)
2010 LET z=g(r,c)+1
2020 IF r=pr AND c=pc THEN LET z=6
2025 IF z=6 AND g(r,c)=2 THEN LET z=7
2030 PRINT AT y,x; INK a(z);t$(z,1 TO 2);AT y+1,x;t$(z,3 TO 4)
2040 RETURN
2500 PRINT AT 1,2; INK 7;"STEPS ";moves;"    "
2540 RETURN
3000 LET k$=INKEY$
3010 IF k$=h$ THEN GO TO 3000
3020 LET h$=k$
3025 IF k$="" THEN GO TO 3000
3030 RETURN
7000 RESTORE 7200: FOR n=0 TO 159: READ b: POKE USR "a"+n,b: NEXT n
7010 DIM t$(7,4): DIM a(7)
7020 LET t$(1)="    ": LET t$(2)=CHR$ 144 +CHR$ 145 +CHR$ 146 +CHR$ 147
7030 LET t$(3)=CHR$ 148 +CHR$ 149 +CHR$ 150 +CHR$ 151
7040 LET t$(4)=CHR$ 152 +CHR$ 153 +CHR$ 154 +CHR$ 155: LET t$(5)=t$(4)
7050 LET t$(6)=CHR$ 156 +CHR$ 157 +CHR$ 158 +CHR$ 159
7055 LET t$(7)=CHR$ 160 +CHR$ 161 +CHR$ 162 +CHR$ 163
7060 LET a(1)=0: LET a(2)=1: LET a(3)=5: LET a(4)=6: LET a(5)=4: LET a(6)=7: LET a(7)=5: RETURN
7200 DATA 0,254,129,129,129,129,129,0
7210 DATA 0,254,2,2,2,2,2,0
7220 DATA 127,64,64,64,64,64,127,0
7230 DATA 127,129,129,129,129,129,127,0
7240 DATA 0,0,0,3,12,8,16,17
7250 DATA 0,0,0,192,48,16,8,136
7260 DATA 17,16,8,12,3,0,0,0
7270 DATA 136,8,16,48,192,0,0,0
7280 DATA 0,127,64,95,88,84,82,81
7290 DATA 0,254,2,250,26,42,74,138
7300 DATA 81,82,84,88,95,64,127,0
7310 DATA 138,74,42,26,250,2,254,0
7320 DATA 3,7,7,3,1,15,31,27
7330 DATA 192,224,224,192,128,240,248,216
7340 DATA 27,3,3,7,6,6,14,0
7350 DATA 216,192,192,224,96,96,112,0
7360 DATA 3,7,7,3,13,15,31,27
7370 DATA 192,224,224,192,176,240,248,216
7380 DATA 27,19,11,15,7,6,14,0
7390 DATA 216,200,208,240,224,96,112,0
9000 PAPER 0: INK 7
9010 PRINT AT 21,0;"Finished. RUN to try again.     ";
9020 STOP

Lines 150–190 translate I, J, K and L into offsets. Up means one row less (dr = -1); right means one column more (dc = 1). Each input starts with both offsets zero, so an unrecognised key cannot reuse the previous direction. We accept lower-case and upper-case letters.

nr,nc are the candidate row and column. Line 220 rejects values outside 1–8 before line 230 looks up g(nr,nc). This order matters even though our current room has border walls: another map might have an open edge. Indexing row 0 would be a BASIC error, not a collision check.

Line 240 rejects walls and crates. At this stage crates are solid obstacles. Floor and targets lead to line 500. We remember the old player position, accept the candidate position and increase moves once. A failed attempt returns to input through line 700 without reaching that increment.

Restore the squares we leave

Lines 520–530 draw the old and new player cells. At the old location, the overlay no longer matches, so the stored floor or target is drawn again. At the new location it does match, so the player appears. There is no need to clear and redraw all 64 cells after every step.

The new routine at 2500 prints the count. The spaces after the number erase leftover digits when a shorter count is drawn. Q goes to 9000, prints a closing message and stops. There is no restart key yet; use Q and RUN to begin again.

Read a deliberate press

INKEY$ reads the keyboard immediately and returns a character, or the empty string "". It does not wait for Enter. Our routine at 3000 compares that reading, k$, with the previous reading, h$.

An unchanged reading loops without returning an action. A changed reading becomes the remembered value. Empty readings keep waiting, but still clear the remembered key. This means holding I produces one step; releasing and pressing I again produces another. Changing directly to L can also produce a step when L is read.

This is polling, not a queue of key events. A very short tap made while BASIC is drawing can be missed. Press one direction at a time and let the move finish. The Spectrum can return an empty string when several ordinary keys are down, so overlapping keys are not a reliable way to steer.

The player is at (6,3). What changes after J, followed by another J?

Show the explanation

The first J moves to (6,2) and adds one step. The next candidate is (6,1), a wall. That attempt changes neither the coordinates nor the count. Release between the two presses so both are read.

Run and try each direction, a long hold, an unrelated letter and walking towards the crate. The crate must remain still. Walk across the target: its ring should return when you leave. Q should return you to BASIC.

If the player repeats while a key is held, check lines 3010–3025. If blocked attempts increase STEPS, check that the count changes only at 510. Colour is absent from the collision checks: the game asks what the array stores, not what colour happens to be on screen.

Sources

Steven Vickers, edited by Robin Bradbeer, ZX Spectrum BASIC Programming, second edition (Sinclair Research, 1983), chapters 5 and 12 (control flow and arrays), 15–16 (drawing), and 18, page 131 (INKEY$).

Run it here

This unit's program, built for you.

Program
step-01.tap
Machine
ZX Spectrum 48K (PAL)

Download step-01.tap