IBM Mazes and Movement (COMPUTE! Magazine May 1986) This article discusses how to write a maze game to randomly generate a simple maze allowing one to choose the dimensions and still make it solvable. Few COMPUTE! programs have spawned so many offspring as Charles Bond's maze generation algorithm originally published in the December 1981 issue. This is an adaptation for SCREEN 1, the medium-resolution graphics screen. In place of the PEEKs and POKEs of the earlier versions, this one uses BASIC's SCREEN, LOCATE, and PRINT statements: 100 KEY OFF:SCREEN 1,0:COLOR 1,0:CLS:RANDOMIZE TIMER 110 MAXROW=23:MAXCOL=40:DIM P(3,1):FOR J=0 TO 3:READ P(J,0),P(J,1):NEXT 120 DATA 0,2,-2,0,0,-2,2,0 130 HL=8:YPOS=2:XPOS=2:LOCATE YPOS,XPOS:PRINT CHR$(5) 140 J=INT(RND(1)*4):X=J 150 NY=YPOS+P(J,0):NX=XPOS+P(J,1):IF NY<1 OR NY>MAXROW OR NX<1 OR NX>MAXCOL THEN 170 160 IF SCREEN(NY,NX)=0 THEN LOCATE NY,NX:PRINT CHR$(J+1):LOCATE (YPOS+P(J,0)/2),(XPOS+P(J,1)/2):PRINT CHR$(HL):YPOS=NY:XPOS=NX:GOTO 140 170 J=(J+1)*-(J<3):IF J<>X THEN 150 180 J=SCREEN(YPOS,XPOS)-1:LOCATE YPOS,XPOS:PRINT CHR$(HL);:IF J<4 THEN YPOS=YPOS-P(J,0):XPOS=XPOS-P(J,1):GOTO 150 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 address use of the joystick. The joystick is nice to maneuver 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: 190 CH=1:XPOS=2:XPOS=2:LOCATE YPOS,XPOS:PRINT CHR$(CH) 200 XMOV=STICK(0)-XCTR:XJOY=SGN(XMOV):IF ABS(XMOV)<10 THEN XJOY=0 210 YMOV=STICK(1)-YCTR:YJOY=SGN(YMOV):IF ABS(YMOV)<10 THEN YJOY=0 220 NY=YPOS+YJOY:NX=XPOS+XJOY:IF NY<1 OR NY>23 OR NX<1 OR NX>40 THEN 200 230 IF SCREEN(NY,NX)=0 THEN 200 240 LOCATE YPOS,XPOS:PRINT CHR$(8):LOCATE NY,NX:PRINT CHR$(1):YPOS=NY:XPOS=NX:GOTO 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 (liens 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: 10 CLS:WIDTH 40:STRIG ON:PRINT "Press fire button to set center position." 20 IF STRIG(0)=0 THEN 20 30 XCTR=STICK(0):YCTR=STICK(1)