Classic Computer Magazine Archive COMPUTE! ISSUE 72 / MAY 1986 / PAGE 10

Readers Feedback

The Editors and Readers of COMPUTE!

IBM Mazes And Movement
I am trying to write a maze game for the IBM. How could I write the program to randomly generate a simple maze, allowing me to choose the dimensions, and make sure that it is a solvable one?

Aaron Greenberg

Few COMPUTE! programs have spawned so many offspring as Charles Bond's maze generation algorithm, originally published in the December 1981 issue. The short and simple procedure generates a maze that's different every time the program is run, yet is always solvable. Here's a PC/PCjr adaptation for SCREEN 1, the medium-resolution graphics screen (for the PC, this requires a color/graphics adapter). In place of the PEEKS and POKES of the earlier versions, this one uses BASIC's SCREEN, LOCATE, and PRINT statements:

QK 100 KEY OFF:SCREEN 1,0:COLOR
       1,0:CLS:RANDOMIZE TIMER

DJ 110 MAXROW=23:MAXCOL=40:DIM P
       (3,1):FOR J=0 TO 3:READ P
       (J,0),P(J,1):NEXT

lE 120 DATA 0,2,-2,0,0,-2,2,0
DM 130 HL=8:YPOS=2:XPOS=2:LOCATE
        YPOS,XPOS:PRINT CHR$(5)

00 140 J=INT(RND(1)*4):X=J
MP 150 NY=YPOS+P(J,0):NX=XPOS+P(
       J,1):IF NY<1 OR NY>MAXROW
        OR NX<1 OR NX>MAXCOL THE
       N 170

JP 160 IF SCREEN(NY,NX)=0 THEN L
       OCATE NY,NX:PRINT CHR$(J+
       1):LOCATE (YPOS+P(J,0)/2)
       ,(XPOS+P(J,1)/2):PRINT CH
       R$(HL):YPOS=NY:XPOS=NX:GO

       TO 140
CC 170 J=(J+1)*-(J<3):IF J<>X TH
       EN 150

JK 180 J=SCREEN(YPOS,XPOS)-1:LOC
       ATE YPOS,XPOS:PRINT CHR$(
       HL);:IF J<4 THEN YPOS=YPO
       8-P(J,0):XPOS=XPOS-P(J,1)
       :GOTO 150

NO 190 GOTO 190

    To customize the routine for your own use, change MAXROW and MAXCOL (line 110) for the maximum number of rows and columns in the maze. (Don't make MAXROW greater than 23, since printing on the bottom two lines of the screen causes scrolling.) As it stands now, the routine always starts constructing the maze from the upper-left corner. You can change this by changing the values of XPOS and YPOS (line 130). The values should always be at least 2, but less than MAXROW and MAXCOL. The variable HL (line 130) defines the character used for the paths of the maze. You can change this to any character you desire, but its value must be greater than 5 (lower values are used to draw the maze) and less than 128 (higher values are not available on the graphics screen). Unfortunately, this set of characters does not include a reverse space that would draw solid paths for the maze. It's up to you to define which end point is the finish of the maze.
    Now that the maze is in place, it's an ideal time to answer a letter from R.C. Loveland, who wants to know how to use the IBM joystick. The joystick is an ideal tool for maneuvering a player through the maze, and BASIC's STICK and STRIG functions make it easy to read. IBM joysticks are "positional"; they return values that reflect the horizontal and vertical deflection of the stick relative to a simple coordinate system. In this system, coordinate 0,0 means the stick is pushed to the upper-left corner, and 255,255 means the stick is pushed to the lower-right corner. STICK(0) returns the horizontal (x) coordinate of the first joystick, while STICK(1) returns the vertical (y) coordinate. STICK(2) and STICK(3) perform the corresponding functions for the second joystick. The only special rule is that STICK(0) must be read first, before any other directions. (Even if you only want positions from the second joystick, you must read STICK(0) first.)
    STRIG reads the status of the joystick buttons-most IBM joysticks have two, but only one per joystick can be read unless you're using BASICA. You must use the statement STRIG ON before you can read button status. After enabling button reading, STRIG(0) returns -1 if the primary button on the first joystick has been pressed since the last time STRIG(0) was called, or 0 if it has not been pressed. STRIG(1) is slightly different-it returns -1 if the primary button on the first joystick is currently pressed (regardless of its previous state), or 0 if it is not pressed. STRIG(2) and STRIG(3) perform the corresponding functions for the primary button on the second joystick.
    This system makes it easy to determine the position of the joystick. But in a situation like navigating the maze drawn by the routine above, what you really need to know is the direction in which the stick is pressed. Add the lines below to the maze-drawing routine above:

LO 190 CH=1:XPOS=2:XPOS=2:LOCATE
        YPOS,XPOS:PRINT CHR$(CH)

NK 200 XMOV=STICK(0)-XCTR:XJOY=S
       GN(XMOV):IF ABS(XMOV)<10
       THEN XJOY=0

JN 210 YMOV=STICK(1)-YCTR:YJOY=S
       GN(YMOV):IF ABS(YMOV)<10
       THEN YJOY=0

OB 220 NY=YPOS+YJOY:NX=XPOS+XJOY
       :IF NY<1 OR NY>23 OR NX<1
        OR NX>40 THEN 200

CO 230 IF SCREEN(NY,NX)=0 THEN 2
       00

36 240 LOCATE YPOS,XPOS:PRINT CH
       R$(B):LOCATE NY,NX:PRINT
       CHR$(1):YPOS=NY:XPOS=NX:G
       OTO 200


    Line 190 defines character 1 (the reverse-smiling face) as the player, then positions it at the start of the maze. Lines 200-210 calculate two directional values, XJOY and YJOY, based on how far the stick is moved from the center positions (XCTR and YCTR). XJOY is -1 if the stick is moved to the left, 1 if the stick is moved to the right, and 0 if the stick is not moved horizontally. YJOY is -1 if the stick is moved up, 1 if the stick is moved down, and 0 if the stick is not moved vertically.
    The advantage of this system is that the screen player can be moved very simply in relationship to the joystick by adding the XJOY and YJOY values to the current position and using the LOCATE statement (lines 220 and 240). The sensitivity of the joystick can be adjusted by changing the value in the ABS test (lines 200-210). As shown, the joystick must be moved at least 10 increments in the desired direction for the change to register. This prevents small jiggles of the stick from causing unwanted movement. The test in line 230 prevents the player from leaving the maze. The SCREEN function returns 0 if no character has been printed in a position, while a maze path position will hold the value defined by HL in the maze-drawing routine.
    One additional step is required to use this joystick routine. Each joystick returns slightly different readings, so it's difficult to predict what the values for the center coordinates will be. Thus, it's necessary to calibrate the joystick at the start of every program that reads it. The following lines show how this can be done:

PC 10 CLS:WIDTH 40:STRIG ON:PRIN
      T "Press fire button to se
      t center position."

PL 20 IF STRIG(0)=0 THEN 20
CO 30 XCTR=STICK(0):YCTR=STICK(1
      )