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