!*************************** AMUS Program Label ******************************
! Filename: MAZE2.BAS                                       Date: 24Jan1991
! Category: GAME         Hash Code: 311-410-345-712      Version: 1.0(101)
! Initials: ARCH/US      Name: STEVE ARCHULETA
! Company: ALPHA MICRO USERS SOCIETY               Telephone #: 3034496917
! Related Files: NONE
! Min. Op. Sys.:                               Expertise Level: BEG
! Special:
! Description: Generates random maze using proper TAB(-1,??) calls - see
! notes below.
!
!*****************************************************************************
!
! This "maze generator" is the start of a game. What that game is,
! I don't know. Perhaps someone can use this to come up with something
! fun. In itself, I have tried to keep the program flexible. You can
! adjust the size of the maze by changing the initial value of SIZE (values
! from 4 to 13 will work). You can also change the position of the maze
! on the screen by adjusting the initial values of SROW and SCOL. I did not
! include the option to change the size of the maze cells.
!
! If you do try to use this for a game, you can keep track of what the
! maze "looks like" in memory by adding some code to the DRAW routines.
! Also, all generated mazes have the same general property: there is always
! a path from any one corner to any other corner.
!                                                   Steve Archuleta
!                                                   ARCH/US
! This version uses proper TCRT calls. rrm. (MCMA/AM)
!==========================================================================
       PROGRAM MAZE2,1.0(101)
                               ! Change these 3 values to alter size and
                               ! position of maze.
       MAP1    SIZE,F,,13              ! Size of one side of grid
       MAP1    SROW,F,,1               ! Row    (upper left corner of maze)
       MAP1    SCOL,F,,16              ! Column (upper left corner of maze)
                               ! Use DIM for arrays so we can use SIZE
       DIM     GRID(SIZE^2)            ! Grid of cells represented by array
       DIM     POS'ARRAY(SIZE^2)       ! Keep track of cell positions
       MAP1    NUM'CELLS,F,,SIZE^2     ! Total number of cells
       MAP1    CELL,F                  ! Current cell location
       MAP1    NEW'CELL,F              ! New cell location
       MAP1    SCRMAP(25,80),B,1       ! Screen map of maze
       MAP1    N'COUNT,F               ! Neighbor cell counter
       MAP1    START'NUM,F             ! Starting cell location
       MAP1    COUNT,F                 ! Generic counter
       MAP1    INDEX,F                 ! Generic array index
       MAP1    X,F                     ! X coordinate (column)
       MAP1    Y,F                     ! Y coordinate (row)

       RANDOMIZE

!***************************************************************
! Initialize squares around main grid (represented by array) to
! a value of 50. This set of cells acts as a buffer zone for the
! main maze grid.
!***************************************************************
INIT:
       FOR COUNT = 1 TO SIZE
         GRID(COUNT) = 50
       NEXT COUNT
       FOR COUNT = SIZE + 1 TO (NUM'CELLS - 2 * SIZE) + 1 STEP SIZE
         GRID(COUNT) = 50
         GRID(COUNT + SIZE - 1) = 50
       NEXT COUNT
       FOR COUNT = (NUM'CELLS - SIZE + 1) TO NUM'CELLS
         GRID(COUNT) = 50
       NEXT COUNT

!**************************************************************
! This is where the various cells of the grid (as represented
! by the GRID array) are filled in. Each cell will contain a
! number representing how it should be displayed on the screen.
! First we randomly choose a cell to start with. Since it is
! the first cell, there is some initialization to do before we
! can start looping. We exit the loop when the STRAY'CELLS
! routine does not find any more empty cells.
!***************************************************************
START:
       START'NUM = (NUM'CELLS - SIZE + 1) - (SIZE + 2)
       CELL = INT(START'NUM * RND(0) + (SIZE + 2))
       IF GRID(CELL) = 50 THEN GOTO START &
       ELSE GRID(CELL) = 1
       CALL NEIGHBORS
       CALL NEXT'CELL
       GRID(CELL) = GRID(CELL) - 1
       CELL = NEW'CELL
NEXT'ELEMENT:                           ! start of loop
       CALL NEIGHBORS
       IF N'COUNT = 0 THEN GOTO STRAY'CELLS
       CALL NEXT'CELL
       CELL = NEW'CELL
       GOTO NEXT'ELEMENT



!************************************************************
! GRID array has been set up so we're ready to blast
! out the maze to the screen. First draw the initial
! maze grid, next overlay each individual cell on top
! of this, and finally draw a border around the whole thing.
!************************************************************
DISPLAY'MAZE:
       ? TAB(-1,23);   ! Turn on graphics mode
       CALL GRID'DRAW
       CALL DISPLAY
       CALL OUTLINE
       ? TAB(-1,24);   ! Turn off graphics mode
       ? TAB(1,1);
       END


!*******************************************************
! Randomly choose one of the neighbor cells and set
! value of current cell and this chosen neighbor cell
! so that the barrier between the cells is removed.
! Finally, make the neighbor cell the new current cell.
!*******************************************************
NEXT'CELL:
       INDEX = INT(N'COUNT * RND(0)) + 1
       NEW'CELL = POS'ARRAY(INDEX)
       IF (NEW'CELL - CELL) = SIZE THEN &
         GRID(CELL) = GRID(CELL) + 4 :&
         GRID(NEW'CELL) = 1
       IF (NEW'CELL - CELL) = -SIZE THEN &
         GRID(CELL) = GRID(CELL) + 1 :&
         GRID(NEW'CELL) = 4
       IF (NEW'CELL - CELL) = 1 THEN &
         GRID(CELL) = GRID(CELL) + 2 :&
         GRID(NEW'CELL) = 8
       IF (NEW'CELL - CELL) = -1 THEN &
         GRID(CELL) = GRID(CELL) + 8 :&
         GRID(NEW'CELL) = 2
       RETURN


!*****************************************************************
! Based on current cell location, mark four neighbor cells (no
! diagonal neighbors) with a -1, and keep track of neighbor
! locations in position array.
!*****************************************************************
NEIGHBORS:
       N'COUNT = 0
       IF GRID(CELL + SIZE) <= 0 THEN &
         GRID(CELL + SIZE) = -1 :&
         N'COUNT = N'COUNT + 1 :&
         POS'ARRAY(N'COUNT) = CELL + SIZE

       IF GRID(CELL - SIZE) <= 0 THEN &
         GRID(CELL - SIZE) = -1 :&
         N'COUNT = N'COUNT + 1 :&
         POS'ARRAY(N'COUNT) = CELL - SIZE

       IF GRID(CELL + 1) <= 0 THEN &
         GRID(CELL + 1) = -1 :&
         N'COUNT = N'COUNT + 1 :&
         POS'ARRAY(N'COUNT) = CELL + 1

       IF GRID(CELL - 1) <= 0 THEN &
         GRID(CELL - 1) = -1 :&
         N'COUNT = N'COUNT + 1 :&
         POS'ARRAY(N'COUNT) = CELL - 1

       RETURN


!***********************************************************
! If there weren't any neighbor cells found, then scan
! through entire element list and find all the "stray"
! neighbor cells (marked with -1). If there are none, then
! we're ready to display the maze. If we do find some, then
! randomly choose one of them and make it the current cell.
! Finally, knock down any barriers between this new cell and
! its current neighbors.
!***********************************************************
STRAY'CELLS:
       INDEX = 0
       FOR COUNT = 1 TO NUM'CELLS
         IF GRID(COUNT) = -1 THEN &
           INDEX = INDEX + 1 :&
           POS'ARRAY(INDEX) = COUNT
       NEXT COUNT
       IF INDEX = 0 THEN GOTO DISPLAY'MAZE
       INDEX = INT(INDEX * RND(0)) + 1
       CELL = POS'ARRAY(INDEX)
       GRID(CELL) = 0
       IF (GRID(CELL + SIZE) <> 50) AND (GRID(CELL + SIZE) > 0) THEN &
         GRID(CELL + SIZE) = GRID(CELL + SIZE) + 1 :&
         GRID(CELL) = GRID(CELL) + 4 :&
         GOTO NEXT'ELEMENT
       IF (GRID(CELL - SIZE) <> 50) AND (GRID(CELL - SIZE) > 0) THEN &
         GRID(CELL - SIZE) = GRID(CELL - SIZE) + 4 :&
         GRID(CELL) = GRID(CELL) + 1 :&
         GOTO NEXT'ELEMENT
       IF (GRID(CELL + 1) <> 50) AND (GRID(CELL + 1) > 0) THEN &
         GRID(CELL + 1) = GRID(CELL + 1) + 8 :&
         GRID(CELL) = GRID(CELL) + 2 :&
         GOTO NEXT'ELEMENT
       IF (GRID(CELL - 1) <> 50) AND (GRID(CELL - 1) > 0) THEN &
         GRID(CELL - 1) = GRID(CELL - 1) + 2 :&
         GRID(CELL) = GRID(CELL) + 8

       GOTO NEXT'ELEMENT



!********************************************************
! This routine simply scans through the GRID array and
! calls the appropriate DRAW routine to display the
! individual cell. Note that the X and Y coordinates,
! which the DRAW routines are based on, are set here.
!********************************************************
DISPLAY:
       X = SCOL - 1  : Y = SROW + 2
       FOR COUNT = 1 TO NUM'CELLS
         IF GRID(COUNT) = 50 THEN GOTO SKIP
         X = X + 4
         IF X = ((SIZE-2)*4+SCOL+3) THEN Y = Y + 2 : X = SCOL + 3

         ON GRID(COUNT) CALL DRAW'1,DRAW'2,DRAW'3,DRAW'4,DRAW'5,  &
                             DRAW'6,DRAW'7,DRAW'8,DRAW'9,DRAW'10, &
                             DRAW'11,DRAW'12,DRAW'13,DRAW'14,DRAW'15
SKIP:
       NEXT COUNT
       RETURN


!*******************************************************************
! These draw routines write over the initial grid design to create
! each cell. The routines assume that a cell is labeled as follows:
!
!                             1
!                           _____
!                          |     |
!                         8|     |2
!                          |_____|
!                             4
!
! Therefore, the DRAW'2 routine simply removes the right side of the
! cell. The DRAW'9 routine removes the top and left sides of the
! cell (the sums of the side) and so on. The X and Y coordinates are
! set in the DISPLAY routine above.
!********************************************************************
DRAW'1:
       ? TAB(Y-1,X-2);TAB(-1,43);"   ";TAB(-1,44);
       RETURN

DRAW'2:
       ? TAB(Y-1,X+2);TAB(-1,45);
       ? TAB(Y,X+2)   " ";
       ? TAB(Y+1,X+2);TAB(-1,42);
       RETURN

DRAW'3:
       ? TAB(Y-1,X-2);TAB(-1,43);"   ";TAB(-1,40);
       ? TAB(Y,X+2)   " ";
       ? TAB(Y+1,X+2);TAB(-1,42);
       RETURN

DRAW'4:
       ? TAB(Y+1,X-2);TAB(-1,43);"   ";TAB(-1,44);
       RETURN

DRAW'5:
       ? TAB(Y-1,X-2);TAB(-1,43);"   ";TAB(-1,44);
       ? TAB(Y+1,X-2);TAB(-1,43);"   ";TAB(-1,44);
       RETURN

DRAW'6:
       ? TAB(Y-1,X+2);TAB(-1,45);
       ? TAB(Y,X+2)   " ";
       ? TAB(Y+1,X-2);TAB(-1,43);"   ";TAB(-1,38);
       RETURN

DRAW'7:
       ? TAB(Y-1,X-2);TAB(-1,43);"   ";TAB(-1,40);
       ? TAB(Y,X+2)   " ";
       ? TAB(Y+1,X-2);TAB(-1,43);"   ";TAB(-1,38);
       RETURN

DRAW'8:
       ? TAB(Y-1,X-2);TAB(-1,45);
       ? TAB(Y,X-2)   " ";
       ? TAB(Y+1,X-2) ;TAB(-1,42);
       RETURN

DRAW'9:
       ? TAB(Y-1,X-2);TAB(-1,41);"   ";TAB(-1,44);
       ? TAB(Y,X-2)   " ";
       ? TAB(Y+1,X-2) ;TAB(-1,42);
       RETURN

DRAW'10:
       ? TAB(Y-1,X-2);TAB(-1,45);TAB(-1,46);TAB(-1,46);TAB(-1,46);TAB(-1,45);
       ? TAB(Y,X-2); "     ";
       ? TAB(Y+1,X-2);TAB(-1,46);TAB(-1,46);TAB(-1,46);TAB(-1,46);TAB(-1,46);
       RETURN

DRAW'11:
       ? TAB(Y-1,X-2) ;TAB(-1,41);"   ";TAB(-1,40);
       ? TAB(Y,X-2)   "     ";
       ? TAB(Y+1,X-2);TAB(-1,42);TAB(-1,46);TAB(-1,46);TAB(-1,46);TAB(-1,42);
       RETURN

DRAW'12:
       ? TAB(Y-1,X-2) ;TAB(-1,45);
       ? TAB(Y,X-2)   " ";
       ? TAB(Y+1,X-2);TAB(-1,39);TAB(-1,46);TAB(-1,46);TAB(-1,46);TAB(-1,44);
       RETURN

DRAW'13:
       ? TAB(Y-1,X-2);TAB(-1,41);"   ";TAB(-1,44);
       ? TAB(Y,X-2)   " ";
       ? TAB(Y+1,X-2);TAB(-1,39);"   ";TAB(-1,44);
       RETURN

DRAW'14:
       ? TAB(Y-1,X-2);TAB(-1,45);TAB(-1,46);TAB(-1,46);TAB(-1,46);TAB(-1,45);
       ? TAB(Y,X-2)   "     ";
       ? TAB(Y+1,X-2);TAB(-1,39);"   ";TAB(-1,38);
       RETURN

DRAW'15:                                ! Keep this in for consistency
       RETURN


!********************************************************
! Draw initial grid outlay on screen. Good example of
! a kludged subroutine - adapting screen for varying maze
! sizes and positions gets messy.
!********************************************************
GRID'DRAW:
       ? TAB(-1,0);
       ? TAB(SROW+1,1)
       FOR Y = SROW + 1 TO SIZE - 3 + SROW
         ? TAB(SCOL) "    ";
         FOR X = 1 TO SIZE - 3
           ? TAB(-1,47);"   ";
         NEXT X
         ?
         ? TAB(SCOL) " ";TAB(-1,46);TAB(-1,46);TAB(-1,46);
         FOR X = 1 TO SIZE - 3
           ? TAB(-1,48);TAB(-1,46);TAB(-1,46);TAB(-1,46);
         NEXT X
         ?
       NEXT Y
       ? TAB(SCOL) "    ";
       FOR X = 1 TO SIZE - 3
         ? TAB(-1,47);"   ";
       NEXT X
       RETURN


!**********************************************************
! Draw final border around grid.
! See Kludge notes from GRID'DRAW routine.
!**********************************************************

OUTLINE:
       X = 1 : Y = SROW
       ? TAB(Y,X)
       ? TAB(SCOL) TAB(-1,38);TAB(-1,46);TAB(-1,46);TAB(-1,46);
       FOR X = 1 TO SIZE - 3
         ? TAB(-1,42);TAB(-1,46);TAB(-1,46);TAB(-1,46);
       NEXT X
       ? TAB(-1,39)
       FOR Y = SROW + 2 TO (SIZE * 2 - 3) + SROW - 1
       ? TAB(SCOL); TAB(-1,47);
       ? TAB(Y,(SIZE-2)*4+SCOL+1);TAB(-1,47)
       NEXT Y
       ? TAB(SCOL);TAB(-1,40);TAB(-1,46);TAB(-1,46);TAB(-1,46);
       FOR X = 1 TO SIZE - 3
         ? TAB(-1,45);TAB(-1,46);TAB(-1,46);TAB(-1,46);
       NEXT X
       ? TAB(-1,41);
       RETURN