home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / mbug / mbug117.arc / MAZE.LBR / MAZEBLD.ZQ0 / M.Z80
Text File  |  1979-12-31  |  23KB  |  1,150 lines

  1.  
  2.  
  3. ;                          MAZE BUILDER
  4. ;                        BY IAN JOHNSTONE
  5. ;                             13/9/87
  6. ;
  7. START:
  8.     PUBLIC START
  9.     CALL    PROLOG  ;Relocate stack and pass control to MAIN
  10.     JP    WARM    ;Tidy up and exit
  11. ;
  12. BEL    EQU    7
  13. CLS    EQU    26
  14. CR    EQU    0DH
  15. CTRLC    EQU    3
  16. LF    EQU    0AH
  17. TAB    EQU    9
  18. TBUF    EQU    80H    ;Default buffer
  19. TFCB    EQU    05CH    ;Default TFCB
  20. MAZE    EQU    7000H    ;Buffer to hold model of maze
  21. SCREEN    EQU    0F000H    ;Start of video RAM
  22. OFFSET    EQU    8000H    ;Offset from maze to screen
  23. LASTLN    EQU    0F730H    ;Last line of screen
  24. GRAPH    EQU    0F810H    ;Start of PCG RAM + 10H
  25. MGRAPH    EQU    80H    ;Mask to convert digit to related graphic
  26. DOT    EQU    90H    ;  ditto but with dot in centre
  27. ;
  28. WARM    EQU    0
  29. BDOS    EQU    5
  30. ;
  31. DIRIO    EQU    6
  32. GETCH    EQU    1
  33. LINEIN    EQU    10
  34. STATUS    EQU    11
  35. ;
  36. MAIN:    CALL    PRESS    ;Press any key
  37. MAIN2:    CALL    INIT    ;Init & set up Graphics
  38.     CALL    USERIN    ;Get user input
  39.     CALL    SETMAZE    ;Set up Maze boundaries
  40.     CALL    GSTART    ;Select a random entry point into maze
  41.     CALL    MOVE    ;Random move thru Maze leaving trail of
  42.             ;open cells until all cells opened
  43.     CALL    CHOOSE    ;Play maze game or view auto-escape
  44.     JP    NZ,MAIN2 ;Round again if desired
  45.     RET        ;Return to PROLOG
  46. ;
  47. INIT:    ;***** Initialise Maze
  48.     LD    HL,MAZE ;Fill maze area with ones
  49.     LD    (HL),1
  50.     LD    DE,MAZE+1
  51.     LD    BC,800H
  52.     LDIR
  53.     LD    DE,GRAPH ;Write graphics into PCG area
  54.     LD    HL,MAZDAT
  55.     LD    BC,240
  56.     LDIR
  57.     LD    DE,GRAPH+100H ;And into next page
  58.     LD    HL,MAZDAT
  59.     LD    BC,240
  60.     LDIR
  61.     LD    B,15
  62.     LD    HL,GRAPH+104H ;But put a dot in centre
  63.     LD    DE,14
  64. PUTDOT:    LD    A,(HL)
  65.     OR    8
  66.     LD    (HL),A
  67.     INC    HL
  68.     LD    A,(HL)
  69.     OR    28
  70.     LD    (HL),A
  71.     INC    HL
  72.     LD    A,(HL)
  73.     OR    8
  74.     LD    (HL),A
  75.     ADD    HL,DE
  76.     DJNZ    PUTDOT
  77.     RET
  78. MAZDAT:    DB    129,129,129,129,129,129,129,129,129,129,255,0,0,0,0,0
  79.     DB    255,128,128,128,128,128,128,128,128,128,255,0,0,0,0,0
  80.     DB    128,128,128,128,128,128,128,128,128,128,255,0,0,0,0,0
  81.     DB    255,129,129,129,129,129,129,129,129,129,129,0,0,0,0,0
  82.     DB    129,129,129,129,129,129,129,129,129,129,129,0,0,0,0,0
  83.     DB    255,128,128,128,128,128,128,128,128,128,128,0,0,0,0,0
  84.     DB    128,128,128,128,128,128,128,128,128,128,128,0,0,0,0,0
  85.     DB    255,1,1,1,1,1,1,1,1,1,255,0,0,0,0,0
  86.     DB    1,1,1,1,1,1,1,1,1,1,255,0,0,0,0,0
  87.     DB    255,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0
  88.     DB    0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0
  89.     DB    255,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0
  90.     DB    1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0
  91.     DB    255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  92.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  93. ;
  94. PROLOG: LD    HL,0    ;Re-locate stack
  95.     ADD    HL,SP    ;Get stack pointer
  96.     LD    (STAK),HL ;Save it
  97.     LD    HL,STAK
  98.      LD         SP,HL    ;SP is now at STAK
  99.     CALL       MAIN    ;Exedcutre program
  100.     JP    WARM    ;Return to CP/M
  101.     DS    40H    ;Buffer for stack
  102. STAK:    DW    0
  103. ;
  104. USERIN: ;Get user input
  105.     LD    DE,TBUF
  106.     CALL    SETDMA
  107.     CALL    RATE    ;Get & save delay timer
  108.     CALL    PRINT
  109.     DB    CR,LF,LF,'Enter Width, Height (Max 76,20)  '
  110.     DB    CR,LF,LF,'On error will default to 30,12 ',0
  111.     CALL    GETSTR    ;Get user input
  112.     LD    B,0    ;Digit counter
  113.     LD    HL,TBUF+2
  114.     LD    DE,WBUF    
  115.     CALL    ULP    ;Read width parameter into WBUF
  116.     OR    A
  117.     JR    Z,DFLT    ;Default if buffer empty
  118.     INC    HL
  119.     LD    DE,HBUF
  120.     LD    C,B    ;Save digit count
  121.     LD    B,0;Clear counter
  122.     CALL    ULP    ;Read Height parameter into HBUF
  123.     LD    HL,WBUF
  124.     CALL    TOBNRY    ;Convert ASCII width to binary
  125.     LD    (WIDTH),A
  126.     OR    A
  127.     JR    Z,DFLT
  128.     CP    77
  129.     JR    NC,DFLT    ;Default if under- or over-size
  130.     LD    HL,HBUF
  131.     LD    C,B    ;Count of height digits
  132.     CALL    TOBNRY    ;Now height
  133.     LD    (HEIGHT),A
  134.     OR    A
  135.     JR    Z,DFLT
  136.     CP    21
  137.     JR    NC,DFLT
  138.     JR    USRX    ;Exit to MAIN
  139. DFLT:    LD    A,30    ;Put default parameters in buffers
  140.     LD    (WIDTH),A
  141.     LD    A,12
  142.     LD    (HEIGHT),A
  143. USRX:    LD    A,CLS
  144.     CALL    PUTCH
  145.     RET
  146. ;
  147. SPEED:    DB    0
  148. WIDTH:    DW    0
  149. HEIGHT:    DW    0
  150. ;
  151. ULP:    ;Read contents of Input buff
  152.     LD    A,(HL)    ;HL -> start of text in buff
  153.     CP    ' '    ;Skip blanks
  154.     JP    NZ,ULP1
  155.     INC    HL
  156.     JP    ULP
  157. ULP1:      CP    0    ;Delimiter
  158.     RET    Z
  159.     CP    ','    ;Element seperator
  160.     RET    Z
  161.     INC    B    ;Digit count
  162.     LD    (DE),A    ;DE -> width or height buff
  163.     INC    DE
  164.     INC    HL
  165.     JR    ULP
  166. ;
  167. WBUF:    DW    0
  168. HBUF:    DW    0
  169. ;
  170. TOBNRY: ;Convert 2 ASCII digits -> by HL to binary
  171.     XOR    A
  172.     CP    (HL)
  173.     RET    Z    ;Abort if buffer empty
  174.     DEC    C    ;C=digit count
  175.     JR    Z,UUNITS
  176.     DEC    C
  177.     JR    Z,UTENS
  178.     JR    TBNRX
  179. UTENS:    LD    A,(HL)    ;Multiply tens digit
  180.     AND    0FH    ;Stripped of ASCII
  181.     ADD    A,A    ;by two
  182.     LD    C,A
  183.     ADD    A,A    ;by 4
  184.     ADD    A,A    ;by 8
  185.     ADD    A,C    ;by 10
  186.     LD    C,A
  187.     INC    HL
  188. UUNITS:    LD    A,(HL)
  189.     AND    0FH    ;Strip ASCII from units digit
  190.     ADD    A,C    ;& add to 10 times tens
  191. TBNRX:    RET
  192. ;
  193. SETMAZE: ;***** Set up maze in buffer and on screen
  194.     LD    A,(WIDTH)
  195.     OR    A    ;Reset carry
  196.     RRA
  197.     LD    L,A
  198.     LD    H,0
  199.     LD    (HALFW),HL ;Subtract half of width
  200.     LD    DE,MAZE+40 ;From centre of top line
  201.     OR    A
  202.     EX    DE,HL
  203.     SBC    HL,DE
  204.     LD    A,(HEIGHT)
  205.     PUSH    AF
  206.     OR    A
  207.     RRA
  208.     LD    B,A    ;Subtract half of height
  209.     LD    A,12    ;from half of maximum height
  210.     SUB    B
  211.     LD    B,A
  212.     LD    DE,80
  213. STM1:    ADD    HL,DE    ;and "line feed" this many lines
  214.     DJNZ    STM1
  215.     LD    (CORNER),HL ;Record top left corner
  216.     POP    BC    ;get height - 1
  217.     DEC    B
  218. STM2:    ADD    HL,DE    ;& calculate bottom left corner
  219.     DJNZ    STM2
  220.     LD    (BOTLEFT),HL
  221.     LD    HL,(CORNER)
  222.     OR    A
  223.     SBC    HL,DE
  224.     PUSH    HL    ;Tab up to balance later "line feed"
  225.     LD    A,(HEIGHT)
  226.     LD    C,A
  227. STM3:    POP    HL    ;Fill maze area of maze buff with zeros
  228.     ADD    HL,DE    ;"line feed"
  229.     PUSH    HL
  230.     LD    A,(WIDTH)
  231.     LD    B,A
  232. STM4:    LD    (HL),0
  233.     INC    HL
  234.     DJNZ    STM4    ;Zero fill one line
  235.     DEC    C
  236.     JR    NZ,STM3    ;LF and zero another, till done
  237.     POP    HL    ;Clear stack
  238.     LD    HL,(CORNER)
  239.     LD    DE,OFFSET-80 ;Now do the screen
  240.     ADD    HL,DE
  241.     LD    DE,80
  242.     PUSH    HL
  243.     LD    A,(HEIGHT)
  244.     LD    C,A
  245. STM5:    POP    HL
  246.     ADD    HL,DE
  247.     PUSH    HL
  248.     LD    A,(WIDTH)
  249.     LD    B,A
  250. STM6:    LD    (HL),'X'
  251.     INC    HL
  252.     DJNZ    STM6    ;Fill a line with 'X's
  253.     DEC    C
  254.     JR    NZ,STM5
  255.     POP    HL
  256.     ADD    HL,DE    ;Point to South boundary
  257.     LD    A,(WIDTH)
  258.     LD    B,A
  259. STM7:    LD    (HL),142
  260.     INC    HL
  261.     DJNZ    STM7    ;and draw a line
  262.     LD    HL,(CORNER)
  263.     LD    DE,OFFSET-80
  264.     ADD    HL,DE    ;Point to north boundary
  265.     LD    A,(WIDTH)
  266.     LD    B,A
  267. STM8:    LD    (HL),139
  268.     INC    HL
  269.     DJNZ    STM8    ;and draw a line
  270.     LD    HL,(CORNER)
  271.     LD    DE,OFFSET-1 ;Point to top of West boundary
  272.     ADD    HL,DE
  273.     LD    DE,80
  274.     LD    A,(HEIGHT)
  275.     LD    B,A
  276.     PUSH    BC
  277. STM9:    LD    (HL),141
  278.     ADD    HL,DE
  279.     DJNZ    STM9    ;and draw a line
  280.     LD    HL,(CORNER)
  281.     LD    DE,OFFSET
  282.     ADD    HL,DE
  283.     EX    DE,HL
  284.     LD    HL,(WIDTH)
  285.     ADD    HL,DE    ;point to top of east boundary
  286.     LD    DE,80
  287.     POP    BC
  288. STM10:    LD    (HL),135
  289.     ADD    HL,DE
  290.     DJNZ    STM10    ;and draw a line
  291.     RET
  292. ;
  293. HALFW:    DW    0
  294. HALFH:    DW    0
  295. CORNER:    DW    0
  296. BOTLEFT:DW    0
  297. ;
  298. GSTART:    ;Establish a random starting point
  299.     LD    HL,GSTX
  300.     PUSH    HL    ;Establish a return address
  301.     LD    A,4    ;Select a boundary for entry
  302.     CALL    RAND    ;Returns RND(4) + 1
  303.     DEC    A    ;1=N, 2=E, 3=S, 4=W
  304.     JR    Z,RNORTH
  305.     DEC    A
  306.     JR    Z,REAST
  307.     DEC    A
  308.     JR    Z,RSOUTH
  309.     JR    RWEST
  310. GSTX:    LD    (RNDSTART),HL ;Record selected starting point
  311.     LD    (HERE),HL ;twice
  312.     LD    (HL),A    ;Record direction code
  313.     ADD    HL,DE    ;DE=screen offset + offset to boundary
  314.     LD    (HL),' ' ;Punch a hole in the boundary
  315.     LD    (MZXIT),HL
  316.     RET
  317. RNORTH:    CALL    RHORIZ    ;Return RND(WIDTH-1)+1 in DE
  318.     LD    HL,(CORNER)
  319.     LD    A,2    ;Direction code for north
  320.     ADD    HL,DE    ;HL=starting point
  321.     LD    DE,OFFSET-80 ;Point to border on screen
  322.     RET
  323. RSOUTH:    CALL    RHORIZ
  324.     LD    HL,(BOTLEFT)
  325.     LD    A,8
  326.     ADD    HL,DE
  327.     LD    DE,OFFSET+80
  328.     RET
  329. RHORIZ:    LD    A,(WIDTH)
  330.     DEC    A
  331.     CALL    RAND    ;= RND(WIDTH-1)+1
  332.     LD    E,A
  333.     LD    D,0    ;= LD DE,A
  334.     RET
  335. REAST:    CALL    RVERT    ;Returns CORNER+RND(HEIGHT-1) LFs in HL
  336.     LD    DE,(WIDTH)
  337.     DEC    DE
  338.     LD    A,4    ;Direction code for east
  339.     ADD    HL,DE    ;HL=starting point
  340.     LD    DE,OFFSET+1 ;Point to screen border
  341.     RET
  342. RWEST:    CALL    RVERT
  343.     LD    A,16
  344.     LD    DE,OFFSET-1
  345.     RET
  346. RVERT:    LD    A,(HEIGHT)
  347.     DEC    A
  348.     CALL    RAND    ;Returns RND(HEIGHT-1)+1 in A
  349.     LD    B,A
  350.     LD    HL,0
  351.     LD    DE,80
  352. RVT1:    ADD    HL,DE    ;Multiply it by 80
  353.     DJNZ    RVT1
  354.     LD    DE,(CORNER)
  355.     ADD    HL,DE    ;& add to CORNER
  356.     RET
  357. MZXIT:    DW    0
  358. ;
  359. MOVE:    ;Move to an adjoining cell
  360.     LD    DE,OFFSET  ;Offset from maze to screen
  361.     LD    HL,(HERE) ;Mark current cell on screen
  362.     ADD    HL,DE
  363.     LD    (HL),'*'
  364.     LD    A,DIRIO    ;Scan for ^C
  365.     LD    DE,0FFH
  366.     CALL    HLBDOS
  367.     OR    A
  368.     CP    CTRLC
  369.     JP    NZ,MOVE0
  370.     POP    HL    ;Clear stack
  371.     RET        ;Exit on ^C
  372. MOVE0:    CALL    NEIGHB    ;Returns B=count of legal moves in array LOTTO
  373.     JR    NZ,MALL
  374.     INC    B    ;West move is legal so Inc count
  375.     LD    (HL),3    ;& put west code in array
  376. MALL:    LD    A,B
  377.     OR    A
  378.     JP    Z,BKTRK    ;If no legal exit, try a backtrack
  379.     CALL    RAND    ;Select a legal move
  380.     CALL    MKMOV    ;and make it
  381. MVBK:    LD    HL,(LAST) ;Put a dot graphic in previous cell
  382.     LD    A,(HL)
  383.     RRA
  384.     AND    0FH
  385.     OR    MGRAPH ;Mask for dot graphic
  386.     LD    DE,OFFSET
  387.     ADD    HL,DE
  388.     LD    (HL),A    ;Display dot
  389.     JP    MOVE    ;Try another move
  390. ;
  391. NEIGHB:    CALL    GOVERN    ;Delay loop
  392.     LD    B,0    ;Count of legal exits
  393.     LD    HL,LOTTO ;array "    "    "
  394.     PUSH    HL
  395.     LD    HL,(HERE)
  396.     LD    DE,-80    ;Test cell to north
  397.     ADD    HL,DE
  398.     LD    A,(HL)
  399.     POP    HL
  400.     OR    A
  401.     JR    NZ,ME    ;Is vacant if zero, else try east
  402.     INC    B    ;so inc count
  403.     LD    (HL),0    ;and put it in array (north=0)
  404.     INC    HL
  405. ME:    PUSH    HL    ;now try east
  406.     LD    HL,(HERE)
  407.     INC    HL
  408.     LD    A,(HL)
  409.     POP    HL
  410.     OR    A
  411.     JR    NZ,MS    ;If illegal, try south
  412.     INC    B
  413.     LD    (HL),1    ;put in array (east=1)
  414.     INC    HL
  415. MS:    PUSH    HL    ;now try south
  416.     LD    HL,(HERE)
  417.     LD    DE,80
  418.     ADD    HL,DE
  419.     LD    A,(HL)
  420.     POP    HL
  421.     OR    A
  422.     JR    NZ,MW
  423.     INC    B
  424.     LD    (HL),2    ;(south=2)
  425.     INC    HL
  426. MW:    PUSH    HL    ;now try west
  427.     LD    HL,(HERE)
  428.     DEC    HL
  429.     LD    A,(HL)
  430.     POP    HL
  431.     OR    A
  432.     RET
  433. LOTTO:    DB    0,0,0,0 ;Array of legal moves
  434. LAST:    DW    0    ;Location of last cell visited
  435. ;
  436. MKMOV:    LD    HL,(HERE) ;Get current cell
  437.     LD    (LAST),HL ;It's being superceded
  438.     LD    B,A      ;B=random choice
  439.     LD    HL,LOTTO  ;of array element
  440.     DEC    HL
  441. MKM1:    INC    HL    ;Locate chosen element
  442.     DJNZ    MKM1
  443.     LD    A,(HL)    ;Fetch it
  444.     OR    A    ;Zero=north
  445.     JR    Z,MVNOR
  446.     DEC     A    ;1=east
  447.     JR    Z,MVEAST
  448.     DEC    A    ;2=south
  449.     JR    Z,MVSOU
  450.     LD    HL,(HERE) ;else west
  451. MVWEST:    LD    A,(HL)
  452.     OR    16    ;West code = 16
  453.     LD    (HL),A    ;So mark cell
  454.     DEC    HL    ;Now move west
  455.     LD    (HERE),HL
  456.     LD    (HL),4    ;We can move east from new cell
  457.     RET
  458. MVNOR:    LD    HL,(HERE)
  459.     LD    A,(HL)
  460.     OR    2    ;North code = 2
  461.     LD    (HL),A
  462.     LD    DE,-80
  463.     ADD    HL,DE
  464.     LD    (HERE),HL
  465.     LD    (HL),8    ;We can move south from new cell
  466.     RET
  467. MVEAST:    LD    HL,(HERE)
  468.     LD    A,(HL)
  469.     OR    4    ;East code = 4
  470.     LD    (HL),A
  471.     INC    HL
  472.     LD    (HERE),HL
  473.     LD    (HL),16    ;We can move west from new cell
  474.     RET
  475. MVSOU:    LD    HL,(HERE)
  476.     LD    A,(HL)
  477.     OR    8    ;South code = 8
  478.     LD    (HL),A
  479.     LD    DE,80
  480.     ADD    HL,DE
  481.     LD    (HERE),HL
  482.     LD    (HL),2    ;We can move north from new cell
  483.     RET
  484. ;
  485. RATE:    CALL    PRINT
  486.     DB    CLS,CR,LF,LF,TAB,TAB,TAB,'RANDOM MAZE BUILDER'
  487.     DB    CR,LF,LF,'Do you want',CR,LF,TAB,'1. Fast',CR
  488.     DB    LF,TAB,'2. Medium',CR,LF,TAB,'3. Slow  ',0
  489.     CALL    DIRIN    ;Direct input
  490.     CP    CTRLC
  491.     JP    NZ,RATE1
  492.     POP    HL    ;Clear stack
  493.     RET
  494. RATE1:    AND    0FH    ;Strip ASCII
  495.     LD    (SPEED),A
  496.     RET
  497. GOVERN:    ;3 Speed delay loops (0, 4K & 8K loops)
  498.     PUSH    BC
  499.     LD    BC,0
  500.     LD    A,(SPEED)
  501.     DEC    A
  502.     JP    Z,ADJ2
  503.     LD    B,16
  504.     DEC    A
  505.     JP    Z,ADJ1
  506.     LD    B,64
  507. ADJ1:    DEC    BC
  508.     LD    A,B
  509.     OR    C
  510.     JP    NZ,ADJ1
  511. ADJ2:    POP    BC
  512.     RET    
  513. ;
  514. RNDSTART:DW    0 ;Starting entry to maze
  515. HERE:    DW    0 ;Location of current cell
  516. ;
  517. BKTRK:    ;Backtrack to an accessible cell
  518.     LD    DE,LOTTO ;Array of legal backtracks
  519.     LD    B,0     ;Count  "   "
  520.     LD    HL,(HERE)
  521.     LD    A,(HL)
  522.     AND    2    ;North = 2
  523.     JP    Z,BKT1
  524.     INC    B
  525.     LD    A,1
  526.     LD    (DE),A    ;Store 1=north
  527.     INC    DE
  528. BKT1:    LD    A,(HL)
  529.     AND    4    ;East=4
  530.     JP    Z,BKT2
  531.     INC    B
  532.     LD    A,2
  533.     LD    (DE),A    ;Store 2=east
  534.     INC     DE
  535. BKT2:    LD    A,(HL)
  536.     AND    8    ;South=8
  537.     JP    Z,BKT3
  538.     INC    B
  539.     LD    A,3
  540.     LD    (DE),A
  541.     INC    DE
  542. BKT3:    LD    A,(HL)
  543.     AND    16    ;West=16
  544.     JP    Z,BKALL
  545.     INC    B
  546.     LD    A,4
  547.     LD    (DE),A    ;Store 4=west
  548. BKALL:    LD    A,B    ;Legal backtrack count
  549.     OR     A
  550.     RET    Z    ;If no legal backtrack, all cells have
  551.             ;been visited
  552.     INC    (HL)    ;Set Lo bit to prevent more backtracks
  553.     LD    (LAST),HL ;Current cell will be superrceded
  554.     LD    A,(HL)
  555.     RRA
  556.     OR    MGRAPH ;Mask for non-dot graphic
  557.     LD    DE,OFFSET
  558.     ADD    HL,DE
  559.     LD    (HL),A    ;Remove dot from cell on screen
  560.     LD    HL,LOTTO-1
  561. BKA1:    INC    HL    ;Can new cell accept backtrack (i.e.Lo bit reset)
  562.     PUSH    HL
  563.     DEC    (HL)    ;1=north
  564.     JP    Z,BKN
  565.     DEC    (HL)    ;2=east
  566.     JP    Z,BKE
  567.     DEC    (HL)    ;3=south
  568.     JP    Z,BKS
  569.     JP    BKW    ;Only west left
  570. BKN:    LD    HL,(HERE)
  571.     LD    DE,-80
  572.     ADD    HL,DE    ;Goto north cell
  573.     LD    A,(HL)
  574.     AND    1    ;Entry illegal if Lo bit set
  575.     JP    BKTX    ;Zero flag set it so
  576. BKE:    LD    HL,(HERE)
  577.     INC    HL    ;visit east cell
  578.     LD    A,(HL)
  579.     AND    1
  580.     JP    BKTX
  581. BKS:    LD    HL,(HERE)
  582.     LD    DE,80
  583.     ADD    HL,DE    ;Visit south cell
  584.     LD    A,(HL)
  585.     AND    1
  586.     JP    BKTX
  587. BKW:    LD    HL,(HERE)
  588.     DEC    HL    ;Visit west cell
  589.     LD    A,(HL)
  590.     AND    1
  591.     JP    BKTX
  592. BKTX:    JP    NZ,BKTX1;Zero flag set if move not legal, try again
  593.     LD    (HERE),HL ;Record new cell
  594.     POP    HL    ;Clear stack
  595.     JP    MOVE    ;Try another move
  596. BKTX1:    POP    HL    ;Recover array pointer
  597.     DEC    B
  598.     JP    NZ,BKA1    ;Try again if more left
  599.     JP    BKALL    ;Else head for exit
  600. ;
  601. CHOOSE: ;Choose between Play, Auto escape & exit
  602.     LD    A,BEL
  603.     CALL    PUTCH
  604.     CALL    RNDCELL    ;Randomly select a cell to start from
  605.     LD    DE,SCREEN ;Display inverse text on top line of screen
  606.     CALL    HILITE
  607.     DB    'Choose from 1=Play, 2=Auto escape, 3=Exit ',0
  608.     CALL    DIRIN    ;Get direct input
  609.     CP    '1'
  610.     JP    Z,PLAY
  611.     CP    '2'
  612.     JP    Z,AUTO
  613.     AND    0FH
  614.     CP    3
  615.     RET        ;If 3 or ^C, return with zero set
  616. ;
  617. RNDCELL: ;Select a cell at random
  618.     LD    A,(WIDTH)
  619.     DEC    A
  620.     CALL    RAND    ;=RND(WIDTH-1)+1
  621.     LD    E,A
  622.     LD    D,0    ;Put it in DE
  623.     LD    HL,(CORNER)
  624.     ADD    HL,DE    ;Move along top line
  625.     LD    A,(HEIGHT)
  626.     DEC    A
  627.     PUSH    HL
  628.     CALL    RAND    ;=RND(HEIGHT-1)+1
  629.     POP    HL
  630.     LD    B,A    ;Use it as a counterA
  631.     LD    DE,80
  632. RCL1:    ADD    HL,DE    ;Line feed down
  633.     DJNZ    RCL1
  634.     LD    (HERE),HL ;Store the location
  635.     LD    (RCELL),HL ;twice
  636.     LD    DE,OFFSET
  637.     ADD    HL,DE
  638.     LD    (HL),'*' ;Display cell on screen
  639.     LD    (LASTSCR),HL ;Store screen location
  640.     LD    (HERESCR),HL
  641.     LD    (FSTSCR),HL
  642.     RET
  643. RCELL:    DW    0    ;Location of randomly selected cell
  644. FSTSCR    DW    0    ;Location of above on screen
  645. ;
  646. PLAY:    LD    DE,SCREEN ;Display inverse text
  647.     CALL    HILITE    ; on top line of screen
  648.     DB    'North=(N or 3), South=S, East=E, West=W,  '
  649.     DB    '^C=Abort',0
  650. PLAY1:    LD    HL,(FSTSCR)
  651.     LD    (HL),'*'
  652.     LD    HL,(HERESCR)
  653.     LD    (LASTSCR),HL
  654.     CALL    BLIP    ;Blink cursor, get user input
  655.     PUSH    AF
  656.     LD    HL,LASTLN ;Erase bottom line of screen
  657.     CALL    DELINE
  658.     POP    AF    ;Recover input
  659.     CP    CTRLC
  660.     RET    Z    ;Exit on ^C
  661.     LD    HL,(HERE) ;Get current cell
  662.     LD    (LAST),HL ;It will be superceded
  663.     CP    '3'    ;North?
  664.     JP    Z,PLN
  665.     AND    95    ;Make upper case
  666.     CP    'N'
  667.     JP    Z,PLN
  668.     CP    'E'
  669.     JP    Z,PLE
  670.     CP    'S'
  671.     JP    Z,PLS
  672.     CP    'W'
  673.     JP    Z,PLW
  674. ILLEG:    LD    A,BEL
  675.     CALL    PUTCH
  676.     LD    DE,LASTLN
  677.     CALL    HILITE
  678.     DB    'ILLEGAL MOVE',0
  679.     JP    PLAY1    ;Try again
  680. PLN:    LD    A,(HL)    ;Get cell data
  681.     AND    2    ;2=north
  682.     JP    Z,ILLEG ;Illegal if not north
  683.     LD    DE,-80    ;Else enter offset to north cell
  684.     JP    PLAYX    ;& update maze
  685. PLE:    LD    A,(HL)
  686.     AND    4    ;East
  687.     JP    Z,ILLEG
  688.     LD    DE,1
  689.     JP    PLAYX
  690. PLS:    LD    A,(HL)
  691.     AND    8    ;South
  692.     JP    Z,ILLEG
  693.     LD    DE,80
  694.     JP    PLAYX
  695. PLW:    LD    A,(HL)
  696.     AND    16    ;West
  697.     JP    Z,ILLEG
  698.     LD    DE,-1
  699. PLAYX:    ADD    HL,DE    ;Move to new location
  700.     LD    (HERE),HL ;& store it
  701.     LD    DE,OFFSET
  702.     ADD    HL,DE
  703.     LD    (HERESCR),HL ;Store screen location
  704.     LD    A,(HL)    ;Get screen graphic
  705.     CP    '*'    ;If '*' we are backtracking
  706.     CALL    Z,PLAYBK ;Remove dot from last cell
  707.     JP    Z,PLAY1 ;And try again
  708.     AND    16    ;Same if current cell is dot graphic
  709.     CALL    NZ,PLAYBK
  710.     LD    DE,(RNDSTART) ;Get exit location
  711.     LD    HL,(LAST) ;Compare to previous
  712.     CALL    CPHLDE
  713.     JP    NZ,PLAY1 ;If NE try another move
  714.     LD    HL,SCREEN ;If equal we are finished
  715.     CALL    DELINE    ;Delete top line of screen
  716.     LD    DE,SCREEN
  717.     CALL    HILITE
  718.     DB    'CONGRATULATIONS **** Try again Y/N ?',0
  719.     CALL    DIRIN
  720.     AND    95
  721.     CP    'N'
  722.     RET    Z
  723.     LD    HL,(HERESCR) ;Remove '*' marker
  724.     LD    (HL),' '
  725.     LD    HL,SCREEN
  726.     CALL    DELINE
  727.     LD    DE,SCREEN
  728.     CALL    HILITE
  729.     DB    'Do you want  1. Same Maze,  2. New Maze',0
  730.     CALL    DIRIN
  731.     CP    '1'
  732.     RET    NZ
  733.     LD    HL,SCREEN ;Clear dots from maze
  734.     LD    BC,1840
  735. AGIN:    LD    A,(HL)
  736.     AND    0EFH    ;Mask out the dot
  737.     LD    (HL),A
  738.     INC    HL
  739.     DEC    BC
  740.     LD    A,B
  741.     OR    C
  742.     JP    NZ,AGIN
  743.     LD    HL,(RCELL) ;Recover starting cell
  744.     LD    (HERE),HL
  745.     LD    DE,OFFSET ;& mark it on screen
  746.     ADD    HL,DE
  747.     LD    (HL),'*'
  748.     LD    (HERESCR),HL ;Store screen location of start
  749.     JP    PLAY    ;Play the maze
  750. BLIP:    ;Blink screen, await user input
  751.     LD    HL,(HERESCR)
  752.     LD    A,(HL)
  753.     LD    B,0
  754.     CP    '*'
  755.     JP    NZ,BLIP1
  756.     CALL    DIRIN
  757.     RET
  758. BLIP1:    OR    DOT
  759.     LD    C,A
  760.     AND    8FH    ;Mask out Dot bit
  761.     LD    (HL),A
  762. BLIP2:    CALL    BLIPIN
  763.     JP    NZ,BLIPX
  764.     DJNZ    BLIP2
  765.     LD    (HL),C
  766.     LD    B,0
  767. BLIP3:    CALL    BLIPIN
  768.     JP    NZ,BLIPX
  769.     DJNZ    BLIP3
  770.     LD    B,0
  771.     JP    BLIP
  772. BLIPX:    LD    (HL),C
  773.     RET
  774. BLIPIN:    LD    A,DIRIO
  775.     LD    DE,0FFH
  776.     CALL    HLBDOS
  777.     OR    A
  778.     RET
  779. ;
  780. PLAYBK:    PUSH    HL
  781.     PUSH    AF
  782.     LD    HL,(LASTSCR)
  783.     LD    A,(HL)
  784.     AND    8FH
  785.     LD    (HL),A
  786.     POP    AF
  787.     POP    HL
  788.     RET
  789. LASTSCR: DW    0    ;Screen pos'n of last cell
  790. HERESCR: DW    0    ;   "      "   " current cell
  791. ;
  792. AUTO:    CALL    ARATE    ;Get input - delay time
  793.     LD    A,4
  794.     CALL    RAND    ;Select starting direction
  795.     LD    (DIRECT),A
  796.     LD    C,4    ;Count of neighbouring cells
  797.     LD    HL,(HERE)
  798.     LD    (LAST),HL
  799.     DEC    (HL)    ;Lo bit reset means visited cell
  800. AUT1:    CALL    GOVERN    ;Delay loop
  801.     LD    A,STATUS
  802.     CALL    HLBDOS    ;Scan for keystroke
  803.     OR    A
  804.     RET    NZ    ;Exit on any key
  805.     LD    HL,(FSTSCR)
  806.     LD    (HL),'*' ;Refresh start display
  807.     LD    HL,(LAST) ;Compare last cell with exit cell
  808.     LD    DE,(RNDSTART)
  809.     CALL    CPHLDE
  810.     JP    NZ,AUT1A
  811.     LD    A,BEL    ;If equal, we have escaped
  812.     CALL    PUTCH
  813.     LD    DE,LASTLN
  814.     CALL    HILITE
  815.     DB    'Round again?  Y/N',0
  816.     CALL    DIRIN
  817.     AND    95
  818.     CP    'N'
  819.     RET
  820. AUT1A:    LD    HL,(HERE) ;Put graphic on screen
  821.     LD    (LAST),HL ;Record cell being exited
  822.     LD    A,(HL)    ;Get cell data
  823.     RRA        ;Get rid of Lo bit
  824.     AND    0FH
  825.     OR    DOT    ;Mask with graphic offset
  826.     LD    DE,OFFSET
  827.     ADD    HL,DE    ;Get screen location
  828.     LD    (LASTSCR),HL ;Save it
  829.     LD    (HL),A    ;& put a dot at screen location
  830. AUT2:    LD    A,(DIRECT) ;Get direction
  831.     LD    B,A
  832.     LD    HL,(HERE)
  833.     LD    A,(HL)    ;Get current cell data
  834.     DEC    B
  835.     JP    Z,AUTN    ;1=north
  836.     DEC    B
  837.     JP    Z,AUTE    ;2=east
  838.     DEC    B
  839.     JP    Z,AUTS    ;3=south
  840.     JP    AUTW    ;only west left
  841. AUTN:    LD    DE,-80    ;Displacement to north cell
  842.     AND    2    ;2=north
  843.     JP    Z,AUTX
  844.     ADD    HL,DE    ;Visit  north
  845.     LD    A,(HL)    ;Get new cell data
  846.     AND    1    ;1=entry permitted
  847.     JP    AUTX
  848. AUTE:    AND    4    ;4=east
  849.     JP    Z,AUTX
  850.     INC    HL    ;Visit east
  851.     LD    A,(HL)
  852.     AND    1
  853.     JP    AUTX
  854. AUTS:    AND    8    ;8=south
  855.     JP    Z,AUTX
  856.     LD    DE,80
  857.     ADD    HL,DE    ;Visit south
  858.     LD    A,(HL)
  859.     AND    1
  860.     JP    AUTX
  861. AUTW:    AND    16    ;16=west
  862.     JP    Z,AUTX
  863.     DEC    HL    ;Visit west
  864.     LD    A,(HL)
  865.     AND    1
  866. AUTX:    ;Zero flag has been reset if it's OK to move
  867.     LD    A,(DIRECT)
  868.     JP    NZ,OK    ;Complete move if OK
  869.     DEC    C    ;Else DEC cell count
  870.     JP    Z,AUTBAK ;Backtrack if all cells tried
  871.     DEC    A    ;Turn left (after failure)
  872.     JP    NZ,ATX2 ;Direction must be >0
  873.     ADD    A,4
  874. ATX2:    LD    (DIRECT),A
  875.     JP    AUT1    ;& try new direction
  876. OK:    LD    (HERE),HL
  877.     LD    C,4    ;Restore cell count
  878.     INC    A    ;Turn right (after success)
  879.     CP    5    ;Direction must be <5
  880.     JP    C,ATX3
  881.     SUB    4
  882. ATX3:    LD    (DIRECT),A
  883.     LD    (HERE),HL
  884.     DEC    (HL)    ;Lo bit was 1, now make it zero (no entry)
  885.     JP    AUT1    ;Try another move
  886. AUTBAK:    INC    A    ;Turn right (to restore original direct)
  887.     CP    5
  888.     JP    C,ATB1
  889.     SUB    4
  890. ATB1:    LD    (DIRECT),A
  891.     LD    HL,(HERE)
  892.     DEC    A
  893.     JP    Z,ATBN    ;1=North
  894.     DEC    A
  895.     JP    Z,ATBE    ;2=South
  896.     DEC    A
  897.     JP    Z,ATBS    ;3=North
  898.     JP    ATBW    ;Only west left
  899. ATBN:    LD    A,(HL)    ;Get cell data
  900.     LD    DE,-80    ;Displacement to north cell
  901.     AND    2    ;2=north
  902.     JP    Z,ATBX
  903.     ADD    HL,DE    ;Visit north
  904.     LD    A,(HL)    ;Get new cell data
  905.     AND    128    ;Hi bit set means no backtrack
  906.     SUB    128    ;Set zero flag if so
  907.     JP    ATBX
  908. ATBE:    LD    A,(HL)
  909.     AND    4    ;4=east
  910.     JP    Z,ATBX
  911.     INC    HL    ;Visit east cell
  912.     LD    A,(HL)
  913.     AND    128
  914.     SUB    128
  915.     JP    ATBX
  916. ATBS:    LD    A,(HL)
  917.     AND    8    ;8=south
  918.     JP    Z,ATBX
  919.     LD    DE,80
  920.     ADD    HL,DE    ;Visit south
  921.     LD    A,(HL)
  922.     AND    128
  923.     SUB    128
  924.     JP    ATBX
  925. ATBW:    LD    A,(HL)
  926.     AND    16    ;16=west
  927.     JP    Z,ATBX
  928.     DEC    HL    ;Visit west
  929.     LD    A,(HL)
  930.     AND    128
  931.     SUB    128
  932. ATBX:    JP    NZ,ATOK ;If OK, complete backtrack
  933.     LD    A,(DIRECT)
  934.     DEC    A    ;Turn left (after failure)
  935.     JP    NZ,ATBX1
  936.     ADD    A,4
  937. ATBX1:    JP    ATB1    ;& try again
  938. ATOK:    LD    C,4    ;Restore cell count
  939.     LD    (HERE),HL ;This completes the move
  940.     LD    HL,(LAST)
  941.     LD    A,(HL)    ;Get data for previous cell
  942.     OR    128    ;Set Hi bit to prevent backtrack
  943.     LD    (HL),A    ;Store it
  944.     RRA        ;Get rid of Lo bit
  945.     AND    0FH
  946.     OR    MGRAPH    ;Mask for graphic display (no dot)
  947.     LD    HL,(LASTSCR)
  948.     LD    (HL),A    ;Remove dot from screen
  949.     LD    A,(DIRECT)
  950.     INC    A    ;Turn right (after success)
  951.     CP    5
  952.     JP    C,ATOK1
  953.     SUB    4
  954. ATOK1:    LD    (DIRECT),A
  955.     JP    AUT1    ;& try another move
  956. ;
  957. DIRECT:    DB    0
  958. ARATE:    ;Get user's choice of speed
  959.     LD    HL,SCREEN ;Erase top line of screen
  960.     CALL    DELINE
  961.     LD    DE,SCREEN
  962.     CALL    HILITE
  963.     DB    'Enter speed ... 1=Fast, 2=Medium, 3=Slow',0
  964.     CALL    DIRIN
  965.     AND    0FH
  966.     LD    (SPEED),A
  967.     LD    HL,SCREEN ;Erase the message
  968.     CALL    DELINE
  969.     RET
  970. ;
  971. PRESS:    ;Get a keystroke, at the same time build a random seed
  972.     PUSH    HL
  973.     PUSH    DE
  974.     PUSH    BC
  975.     CALL    PRINT
  976.     DB    CR,LF,'Press any key  ',0
  977.     LD    HL,0
  978. PRS1:    INC    HL
  979.     LD    C,DIRIO
  980.     LD    DE,0FFH
  981.     CALL    BDOS
  982.     OR    A
  983.     JP    Z,PRS1
  984.     LD    (RANDY),HL
  985.     POP    BC
  986.     POP    DE
  987.     POP    HL
  988.     RET
  989. RANDY:    DW    0    ;Random seed
  990. ;
  991. RAND:    ;***** Get a random number (Mod A)
  992.     PUSH    AF
  993.     LD    HL,(RANDY)
  994.     LD    A,L
  995.     AND    0F0H
  996.     LD    L,A    ;Get Hi nybble of L
  997.     LD    A,H
  998.     AND    0FH
  999.     ADD    A,L    ;Add Lo nybble of H
  1000.     LD    C,A    ;Multiply A
  1001.     LD    A,R    ;by contents of refresh register
  1002.     LD    B,A
  1003.     LD    H,0
  1004.     XOR    A
  1005. RND1:    ADD    A,B
  1006.     JR    NC,RND2
  1007.     INC     H
  1008. RND2:    DEC    C
  1009.     JR    NZ,RND1
  1010.     LD    L,A
  1011.     LD    (RANDY),HL ;Use result as next seed
  1012.     LD    A,H
  1013.     POP    BC    ;Get modulo in B
  1014. RND3:    SUB    B    ;& divide
  1015.     JR    NC,RND3
  1016.     ADD    A,L
  1017. RND4:    SUB    B
  1018.     JR    NC,RND4
  1019.     ADD    A,B
  1020.     INC    A    ;Return RND(A)+1
  1021.     RET
  1022. ;
  1023. HLBDOS:; BDOS call saving register pairs
  1024.     PUSH    HL
  1025.         PUSH   DE
  1026.     PUSH    BC
  1027.     LD    C,A    ;Receives BDOS function if A
  1028.         CALL   BDOS
  1029.     POP    BC
  1030.         POP    DE
  1031.         POP    HL
  1032.         RET
  1033. ;
  1034. PUTCH:  ; Output char in A to console
  1035.     PUSH    BC
  1036.     PUSH    DE
  1037.     PUSH    HL
  1038.         PUSH    AF
  1039.     LD    E,A
  1040.     LD    C,2
  1041.     CALL    BDOS
  1042.     POP    AF
  1043.     POP    HL
  1044.     POP    DE
  1045.     POP    BC
  1046.     RET
  1047. ;
  1048. PUTS:   ; Output string pointed to by HL to console
  1049.     LD    A,(HL)
  1050.     OR    A
  1051.     RET    Z
  1052.     CALL    PUTCH
  1053.     INC    HL
  1054.     JP    PUTS
  1055.     RET
  1056. ;
  1057. DIRIN:    ;Wait for direct input
  1058.     PUSH    DE
  1059.     PUSH    BC
  1060. DIN1:    LD    A,DIRIO
  1061.     LD    DE,0FFH
  1062.     CALL    HLBDOS
  1063.     OR    A
  1064.     JP    Z,DIN1
  1065.     POP    BC
  1066.     POP    DE
  1067.     RET
  1068. ;
  1069. PRINT:  ;Output a string pointed to by contents of top of stack
  1070. ;            delimited by zero, to console.
  1071.         EX    (SP),HL    ;Put pointer to string in HL 
  1072.     XOR    A    ;Clear register & flags
  1073.     ADD    A,(HL)    ;Put char in A set/reset Z flag
  1074.     INC    HL    ;Point to next char (or return addr
  1075.             ;if current char a zero)
  1076.     EX    (SP),HL    ;and save itè    RET    Z    ;Return on delimiter (zero)
  1077.     CALL    PUTCH    ;Display char
  1078.         JP      PRINT    ;and get another char.
  1079. ;
  1080. HILITE:    ;Output a highlighted string to screen area -> by DE
  1081.         EX    (SP),HL    ;Put pointer to string in HL 
  1082.     XOR    A    ;Clear register & flags
  1083.     ADD    A,(HL)    ;Put char in A set/reset Z flag
  1084.     INC    HL    ;Point to next char (or return addr
  1085.             ;if current char a zero)
  1086.     EX    (SP),HL    ;and save itè    RET    Z    ;Return on delimiter (zero)
  1087.     OR    128    ;Set Hilite bit
  1088.     LD    (DE),A    ;and display char
  1089.     INC    DE
  1090.         JP      HILITE    ;and get another char.
  1091. ;
  1092. DELINE: ;Delete line -> by HL
  1093.     LD    D,H
  1094.     LD    E,L
  1095.     INC    DE
  1096.     LD    (HL),' '
  1097.     LD    BC,80
  1098.     LDIR
  1099.     RET
  1100. ;
  1101. GETSTR: ; Input console message into buffer
  1102.     PUSH    BC
  1103.     PUSH    HL
  1104.     PUSH    DE
  1105.     LD    HL,TBUF+1 ;Clear  char counter
  1106.     LD    (HL),0
  1107.     DEC    HL    ;Set maximum line length
  1108.     LD    (HL),80 ;in first byte of buffer
  1109.     EX    DE,HL    ;Switch to DE for BDOS Call
  1110.     LD    A,LINEIN
  1111.     CALL    HLBDOS    ;Call BDOS line input function
  1112.     LD    HL,TBUF+1 ;Get char count
  1113.     LD    E,(HL)    ;into LSB of DE
  1114.     LD    A,(HL)    ;and into A for return data
  1115.     LD    D,0    ;and zero MSB
  1116.     ADD    HL,DE    ;Add length to start
  1117.     INC    HL    ;plus 1 points to end
  1118.     LD    (HL),0    ;Insert zero as delimiter
  1119.     POP    HL
  1120.     POP    DE
  1121.     POP    BC
  1122.     RET
  1123. ;
  1124. SETDMA: ; -> DE points to transient buffer
  1125.     LD    A,26
  1126.     CALL    HLBDOS
  1127.     RET
  1128. ;
  1129. CPHLDE:    ;Compare HL & DE registers
  1130.     PUSH    HL
  1131.     PUSH    DE
  1132.     OR    A
  1133.     SBC    HL,DE
  1134.     POP    DE
  1135.     POP    HL
  1136.     RET    
  1137. ;
  1138. TWOCR:    CALL    CRLF    ;Execute <CR> & <LF> twice
  1139. CRLF:    PUSH    AF
  1140.     LD    A,CR
  1141.     CALL    PUTCH    ;Execute <CR>
  1142.     LD    A,0AH
  1143.     CALL    PUTCH    ;Execute <LF>
  1144.     POP    AF
  1145.     RET
  1146. ;
  1147.  
  1148. LASTBUF: DB    0    ;Mark last byte of program
  1149. END
  1150.