` COMPUTE! ISSUE 26 / JULY 1982 / PAGE 40`

Maze Race

Mike Peterson
Cheyenne, WY

With versions of this excellent game for PET/CBM Microsoft and Atari BASICs, this should provide hours of amusement. It will run on computers with 8K or more of RAM memory.

I was impressed by the Maze algorithm that appeared in COMPUTE!, December, 1981, #19. After watching the maze form several times, I had an idea for a program that incorporated the maze algorithm.

First, I modified the routine so that two symmetrical mazes would be formed. One starts in the upper left corner of the screen while the other starts in the lower right. By POKEing a 32 (\$20) in the center of the screen, identical (but opposite) mazes are formed. As one goes left, the other goes right. And as one goes down, the other goes up. This continues until the screen is full and the algorithm completed. The mazes are then linked together in the screen's middle and a "target" character is POKEd in the center.

Now, depending upon your choice of options during initialization, you race against a human opponent (or the computer) to the center of the maze. If you select the two-player option, I strongly recommend the use of joysticks. The program will process both player's joystick input during each cycle. On the keyboard, one player can prevent the other's input by holding a key pressed.

With the one-player version, you will always be on the right and use the right joystick or the number pad to control your movement. The computer will not begin until after your first input. Since the computer doesn't know the best path to follow, and strays down dead-end paths, it is easy to beat. My daughter loses just often enough to keep her interested and make each game a new challenge.

Through experimentation with the joysticks, I found that the left joystick sets the high four bits and the right joystick sets the low four bits of the byte at address 59471 (\$E84F). The byte, A, can be separated into a left value and a right value with : A= PEEK(59471) : L = (A/16) AND 15 : R = A AND 15. If both joysticks are in the same position, L = R. An array with 15 elements can be used to determine the new position of each player, move there if not off the screen, and then erase the previous position. The following table shows all possible joystick values, positions, and screen movement offsets:

 Lor R POSITION OFFSET 0 not used 0 1 left/button -1 2 right/button + 1 3 button 0 4 not used 0 5 left/up -41 6 right/up -39 7 up -40 8 not used 0 9 left/down +39 10 right/down +41 11 down + 40 12 not used 0 13 left -1 14 right + 1 15 center 0 Note: with the button pressed only the row can be determined.

Another feature of this program is the "flipping" of the marker that arrives in the center of the screen's maze first. This is performed by XORing the byte in the center screen address with 128 (\$80). The result of an XOR with 128 is that RVS characters become normal characters and vice versa.

Since BASIC doesn't provide us with an XOR function, I consulted a Boolean Algebra text and found the AND, OR, and NOT gates used to produce the XOR truth table. In BASIC, XOR would be this : Y = ((X AND (NOT 128)) OR ((NOT X) AND 128)).

Program 1. Atari Version

 Atari Notes After the dual maze has been generated, select the number of players (player vs. computer or player vs. player) by pressing SELECT. When ready to play, press START. To re-start the game, press START. Use joysticks plugged into jacks one and two to play.
```100 REM *** MAZE RACE ***
110 REM *** ATARI VERSION ***
120 DIM A(3):REM SET UP DIRECTION TABLE
130 A(0) = 2 : A(1)=-80 = A(2) = -2 : A(3) = 80
140 WL = 128: HL = 0: SC = PEEK(88) +256*PEEKC (89) : A = SC + 43 : C = SC + 877
150 GRAPHICS 0 : POKE 752, 1 : SETCOLOR 2, INT (16*RND(0)), 4 : POKE 712, PEEK (710)
160 FOR I = 1 TO 23170 PRINT "| |"
180 NEXT I
190 REM GENERATE THE MAZE!
200 POKE A, 5 : POKE C, 2 : POKE SC + 499, HL
210 J = INT(RND(0)*4) : X = J
220 B = A + A (J) : D = C - A(J) : IF PEEK(B)<>WL THEN 240
230 POKE B, J + 1 : POKE D, J + 1 : POKE A + INT(A(J)/2), HL : POKE C-INT(A(J)/2), HL : A = B : C = D : GOTO 210
240 J = (J + 1)*(J<3) : IF J<>X THEN 220
250 J = PEEK(A) : POKE A, HL : POKE C, HL : IF J<5 THEN A = A - A (J-1) : C = C + A(J-l) : GOTO 210
260 A = SC + 43 : C = SC + 877 : J = 2
270 POKE A, 84 : POKE C, 111 : POKE SC + 459, 10 : POKE SC + 460, HL : POKE SC + 458, HL
280 DIM M(15) : FOR I = 0 TO 15 : M(I) = 0 : NEXT I : NP = 0
290 M(14) = -40 : M(13) = 40 : M(11) = -1 : M(7) = 1 : M(7) = 1 : M(10) = -41 : M(6) = -39
300 M(9) = 39 : M(5) = 41 : PLR = l
310 DIM MS\$(20) : MS\$ = "Maze Race" : FOR I = 1 TO LEN(MS\$) : POSITION 0, I + 5 : ? MS\$(I, I) : NEXT I
320 POSITION 9, 23 :? "One Player Vs. Computer";
330 K = PEEK(53279) : IF K = 7 THEN 330
340 IF K = PEEK(53279) THEN 340
350 IF K = 6 THEN 400
360 IF K = 3 THEN 330
370 NP = 1 - NP : IF NP = 0 THEN 320
380 POSITION 9, 23:? " Player Vs. Player";
390 GOTO 330
400 PLR = 1-PLR
410 IF PLR = 0 OR NP THEN 440
420 B = A + INT(A(J)/2) : Y = PEEK(B) : IF Y = HL OR Y = 10 THEN POKE B, 84 : POKE A, HL : A = B : J = (J + 2)-4*(J>1)
430 J = (J-l) + 4*(J = 0) : GOTO 480
440 IF PLR THEN 470
450 D = C + M(STICK(PLR)) : IF PEEK(D) =  HL OR PEEK(D) = 10 THEN POKE D, 111 : POKE C, HL : C = D
460 GOTO 480
470 B = A + M(STICK(PLR)) : IF PEEK(B) = HL OR PEEK(B) = 10 THEN POKE B, 84 : POKE A, HL : A = B
480 REM SOMEONE WON
490 IF A<>SC + 459 AND C<>SC + 459 THEN 400
500 P = PEEK(SC + 459) : PF = 0
510 FOR I = 1 TO 50 : POKE SC + 459, P + 128*PF : PF = 1-PF : NEXT I
520 REM
530 IF C = SC + 459 THEN 560
540 IF NP THEN POSITION 9, 23 : ? " Player 2 Won! "; : Goto 580
550 POSITION 9, 23 : ? "       I WIN! " : GOTO 580
560 IF NP THEN POSITION 9, 23 : ? "   Player 1 Won! "; : GOTO 580
570 POSITION 9,23 : ? "       You win! ";
580 IF PEEK( 53279)<>6 THEN 580
590 RUN
```
 If you want to make Maze Race (for Atari) more challenging, add the following lines. They cause the screen to blank out during the maze generation, preventing a "sneak preview." A side effect is that this decreases the time necessary to generate the maze: ```155 POKE 559,0 325 POKE 559,34 ```

Program 2. Microsoft Version

```10 REM *** MAZE RACE ***
20 REM * MIKE PETERSON *
30 REM ** CHEYENNE, WY **
40 REM
50 REM MAZE GENERATOR BY CHARLES BOND
60 REM COMPUTE! : DECEMBER, 1981
70 REM
80 GOTO 120
90 POKE 167,0
100 GETZ\$ : IFZ\$ = ""THEN 100
110 PRINTZ\$ : Z = VAL (Z\$) : POKE 167, 1 : RETURN
120 PRINT " {CLEAR} {05 DOWN}" : PRINTTAB (15) "MAZE RACE {02 DOWN}"
130 PRINTTAB (5) "HOW MANY PEOPLE ARE PLAYING? {LEFT}"; : GOSUB 90 : NP  =  Z-1 : PRINT
140 IF Z> 2 THEN PRINT TAB (5) "SORRY, ONLY 2 CAN  PLAY. {DOWN}" : GOTO 130
150 IF Z = 0 THEN PRINTTAB (5) "PLEASE ENTER 1 OR. 2. {DOWN}" : GOTO 130
160 PRINTTAB (7) "ARE YOU USING JOYSTICKS ? {L LEFT}"; : GOSUB 90 : PRINT
170 IFZ\$  = "Y" THEN JJ = 1 : GOTO 190
180 IFZ\$ <> "N" THEN PRINTTAB (7) "PLEASE ENTER Y OR N. {DOWN} " : GOTO 160
190 IFNPTHENPRINT" {DOWN} LEFT PLAYER  =  Q : RIGHT PLAYER = W" : GOTO 210
200 PRINT" {DOWN} I AM THE Q : YOU ARE THE W"
210 IFJJTHENPRINT"{DOWN} USE THE JOYSTICK TO MOVE AROUND" : GOTO 250
220 IFNPTHENPRINT" {DOWN} Q USES W FOR UP, A FOR LEFT, D FOR RIGHT,"
230 IFNPTHENPRINT"AND X FOR DOWN."
240 PRINT" {DOWN} W USES 8 FOR UP, 4 FOR LEFT, 6 FOR RIGHT, AND 2 FOR DOWN."
250 PRINT" {DOWN} PRESS ANY KEY TO BEGIN *{LE LEFT} "; : GOSUB 90
260 DIMM (255) : JS = 151 : IFJJTHENJS = 59471 : GOTO 290
270 M(18) = 40 : M(42) = -1 : M(41) = 1 : M(50) = -40
280 M(24) = 40 : M(48) = -1 : M(47) = 1 : M(56) = -40 : GOTO 300
290 M(7) = -40 : M(11) = 40 : M(13) = -1 : M(14) = 1300 DIM A(3): A(0) = 2 : A(1) = -80 : A(2) = -2 : A(3) = 80 : WL = 160 : HL = 32 : SC = 32768
310 BL\$ = "{REV}                                    ~
{OFF}"
320 A = SC + 81 : C = SC + 917
330 PRINT "{CLEAR}" : FOR I = 1 TO 23 : PRINT BL\$ : NEXT
340 POKE A, 4 : POKE C, 1 : POKE SC + 499, HL
350 J = INT(RND (TI) * 4) : X = J
360 B = A + A (J) : D = C - A(J) : IF PEEK(B) < > WL THEN 380
370 POKE B, J : POKED, J : POKE A + A(J)/2, HL : POKE C - A(J)/2, HL : A = B : C = D : GOTO 350
380 J =(J + 1) * -(J < 3) : IF J <> X THEN 360
390 J = PEEK (A) : POKE A, HL : POKE C, HL : IF J < 4 THEN A = A - A(J) : C = C + A(J) : GOTO 350
400 POKE SC + 498, HL : POKE SC + 499, 42 : POKE SC + 500, HL : A = SC + 81 : C = SC + 917
410 POKE A, 81 : POKE C, 87 : J = 2 : K = 2
420 PP = PEEK(JS) : IF PP = 255 THEN 420
430 PP = PEEK(JS)
440 IF NP THEN 470
450 B = A + A(J)/2 : Y = PEEK(B) : IFY = HLORY = 42 THEN POKE B, 81 : POKE A, HL : A = B : J = (J + 2) + 4 * (J >1)
460 J = (J - 1) - 4 * (J = 0) : GOTO 510
470 IF JJ THEN 500
480 IF PP <> 24 AND PP <> 48 AND PP <> 47 AND PP <>56 THEN 520
490 B = A + M(PP) : IF PEEK (B) = HLOR PEEK (B) = 42 THEN POKE B, 81 : POKE A, HL : A = B : GOTO 510
500 Q = (PP/16) AND 15 : B = A + M (Q) : IF PEEK (B) = HLOR PEEK (B) = 42 THEN POKE B, 81 : POKE A, HL : A = B
510 IF JJ THEN 540
520 IF PP <> 18 AND PP <> 42 AND PP <> 41 AND PP <> 50 THEN 550
530 D = C + M(PP) : IF PEEK (D) = HLOR PEEK(D) = 42 THEN POKE D, 87 : POKE C, HL : C = D : GOTO 550
540 Q = (PP AND 15) : D = C + M(Q) : IF PEEK(D) = HLOR PEEK (D) = 42 THEN POKED, 87 : POKE C, HL : C = D
550 IF A <> SC + 499 AND C <> SC + 499 THEN 430
560 FOR I = 0 TO 99 : W = PEEK (SC + 499) : X = (WAND(NOT 128)) OR ((NOT W)AND 128) : POKE SC + 499, X
570 NEXT
580 PRINT "ANOTHER GAME ?{LEFT}"; : GOSUB 90
590 IF Z\$ = "Y" THEN 320
600 IF Z\$ <> "N" THEN PRINT "{02 UP}" : GOTO 580
```