home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / GENASM / FLIFEH89.LBR / FASTLIFE.MZC / FASTLIFE.MAC
Text File  |  2000-06-30  |  18KB  |  442 lines

  1. ; Fast life program written in Z-80 code by Jim Petersen in 3/85.
  2. ;
  3.         .Z80
  4.         ASEG
  5. ;
  6. ; Constant storage
  7. ;
  8. BDOS    EQU     0005H           ; Function calls to BDOS go here
  9. DIRCON  EQU     6               ; Direct console input/output function #
  10. PRSTR   EQU     9               ; String output to console, ending with '$'
  11. ;
  12. ESC     EQU     1BH
  13. CR      EQU     0DH
  14. LF      EQU     0AH
  15. ;
  16. UPKEY   EQU     05H             ; move cursor up (^K)
  17. DNKEY   EQU     18H             ; move cursor down (^J)
  18. LFKEY   EQU     13H             ; move cursor left (^H)
  19. RTKEY   EQU     04H             ; move cursor right (^L)
  20. ;
  21. CTRLC   EQU     03H             ; user can abort program with CTRL-C
  22. CTRLQ   EQU     11H             ; user can make program run with CTRL-Q
  23. CTRLS   EQU     13H             ; user can suspend program with CTRL-S
  24. CTRLZ   EQU     1AH             ; user can start program again with CTRL-Z
  25. ;
  26. EMPTY   EQU     ' '             ; character to use to imply an empty cell
  27. FILL    EQU     'o'             ; character to use to imply a living cell
  28. TOGGLE  EQU     ' '             ; key to press to toggle life on/off in a cell
  29. ;
  30. ROWS    EQU     24              ; number of rows in board
  31. COLS    EQU     78              ; number of cols. in board
  32. ;
  33.         ORG     100H
  34. ;
  35. ; Initialization section
  36. ;
  37.         LD      (OLDSTK),SP     ; save entry stack pointer
  38.         LD      SP,STACK        ; and set a new one for us
  39. ;
  40.         LD      DE,BOARD        ; give instructions
  41.         LD      C,PRSTR
  42.         CALL    BDOS
  43. ;
  44. USRRDY: LD      C,DIRCON
  45.         LD      E,0FFH
  46.         CALL    BDOS
  47.         OR      A
  48.         JR      Z,USRRDY
  49. ;
  50. START:  LD      DE,CLEAR        ; clear the screen
  51.         LD      C,PRSTR
  52.         CALL    BDOS
  53. ;
  54.         LD      HL,BOARD        ; zero out board
  55.         LD      BC,256*(ROWS+1)
  56. ZERO:   LD      (HL),0
  57.         INC     HL
  58.         DEC     BC
  59.         LD      A,B
  60.         OR      C
  61.         JR      NZ,ZERO
  62. ;
  63. CENCUR: LD      A,ROWS/2        ; start user off at ROWS/2
  64.         LD      (SCRNX),A
  65.         LD      A,COLS/2        ; and COLS/2
  66.         LD      (SCRNY),A
  67. ;
  68. ; End of initialization.  Turn cursor on, position cursor at appropriate
  69. ; place, update screen cell with appropriate data, and wait for a key press.
  70. ;
  71.         LD      DE,ONCRS        ; output cursor-on command
  72.         LD      C,PRSTR
  73.         CALL    BDOS
  74. DISPLY: LD      A,(SCRNX)
  75.         LD      D,A             ; current row in D
  76.         LD      A,(SCRNY)
  77.         LD      B,A             ; current column in B
  78.         CALL    DISPXY          ; position cursor, display data
  79.         LD      C,DIRCON
  80.         LD      E,08H           ; back cursor up over cell
  81.         CALL    BDOS
  82. WAITKY: LD      C,DIRCON        ; wait for user to press a key
  83.         LD      E,0FFH
  84.         CALL    BDOS
  85.         OR      A
  86.         JR      Z,WAITKY
  87. ;
  88. ; They input something.  Test for program action keys.
  89. ;
  90.         CP      CTRLQ           ; start the action?
  91.         JP      NZ,QTEST        ; go to quit test if not
  92.         LD      DE,OFFCRS       ; output off-cursor command
  93.         LD      C,PRSTR
  94.         CALL    BDOS
  95.         JP      MAKBOX          ; start with calculations
  96. QTEST:  CP      CTRLC           ; quit the game?
  97.         JP      Z,EXIT
  98.         CP      CTRLZ           ; start game over?
  99.         JP      Z,START
  100. ;
  101. ; Not yet; test for cursor positioning keys.
  102. ;
  103.         CP      UPKEY           ; move cursor up?
  104.         JR      NZ,STAY1
  105.         LD      A,(SCRNX)       ; valid movement?
  106.         DEC     A
  107.         JP      Z,WAITKY        ; ignore if not
  108.         LD      (SCRNX),A       ; otherwise, store change
  109.         JP      DISPLY          ; and move cursor
  110. ;
  111. STAY1:  CP      DNKEY           ; move cursor down?
  112.         JR      NZ,STAY2
  113.         LD      A,(SCRNX)       ; valid movement?
  114.         CP      ROWS
  115.         JP      Z,WAITKY        ; ignore if not
  116.         INC     A
  117.         LD      (SCRNX),A       ; otherwise, store change
  118.         JP      DISPLY          ; and move cursor
  119. ;
  120. STAY2:  CP      LFKEY           ; move cursor left?
  121.         JR      NZ,STAY3
  122.         LD      A,(SCRNY)       ; valid movement?
  123.         DEC     A
  124.         JP      Z,WAITKY        ; ignore if not
  125.         LD      (SCRNY),A       ; otherwise, store change
  126.         JP      DISPLY          ; and move cursor
  127. ;
  128. STAY3:  CP      RTKEY           ; move cursor right?
  129.         JR      NZ,LIFCMD       ; check for life changing command if not
  130.         LD      A,(SCRNY)       ; valid movement?
  131.         CP      COLS
  132.         JP      Z,WAITKY        ; ignore if not
  133.         INC     A
  134.         LD      (SCRNY),A       ; otherwise, store change
  135.         JP      DISPLY          ; and move cursor
  136. ;
  137. ; Last possibility for their key is command to add or remove a cell
  138. ; from the board.
  139. ;
  140. LIFCMD: CP      TOGGLE          ; is it the toggle key for life?
  141.         JP      NZ,WAITKY       ; NO MORE VALID KEYS; IGNORE AND WAIT IF NOT
  142.         LD      A,(SCRNX)
  143.         LD      H,A             ; current row # in H
  144.         LD      A,(SCRNY)
  145.         LD      L,A             ; current column # in L
  146.         LD      DE,BOARD
  147.         ADD     HL,DE
  148.         LD      A,(HL)          ; get cell from board
  149.         AND     A               ; is there life here now?
  150.         LD      (HL),01B        ; assume there is no life, and add life
  151.         JP      Z,DISPLY        ; if OK, go back and show it
  152.         DEC     (HL)            ; but if life, take it away
  153.         JP      DISPLY
  154. ;
  155. ; Beginning of section to determine next generation
  156. ;
  157. ; We do a nested loop using the borders as limits.  We check each
  158. ; cell by counting the number of neighbors in the eight surrounding
  159. ; positions, and acting accordingly:
  160. ;
  161. ; If life exists in the current cell:
  162. ;
  163. ; 0,1 neighbors ---> life dies from isolation
  164. ; 2,3 neighbors ---> life lives another generation
  165. ; 4-8 neighbors ---> life dies from over-population
  166. ;
  167. ; If life does not exist in the current cell, and there are 3 neighbors,
  168. ; a new cell will be created here in the next generation.
  169. ;
  170. MAKBOX: LD      DE,100H+ROWS            ; set D to row 1, E to max. row #
  171.         LD      BC,100H+COLS            ; set B to col. 1, C to max. col. #
  172. LOOP:   PUSH    DE                      ; save current row #, row limit
  173.         PUSH    BC                      ; save current col. #, col. limit
  174. ;
  175. ; D contains current row, B contains current column.  Check the eight
  176. ; neighboring cells, or less if we would fall off the board.
  177. ;
  178.         LD      E,D                     ; save copy of cur. row in E
  179.         DEC     D                       ; one row above if not off board
  180.         JP      NZ,AREA1
  181.         INC     D                       ; top row established
  182. ;
  183. AREA1:  LD      A,E                     ; one row below if not off board
  184.         CP      ROWS
  185.         JP      Z,AREA2
  186.         INC     E                       ; bottom row established
  187. ;
  188. AREA2:  LD      C,B                     ; save copy of cur. col in C
  189.         DEC     B                       ; one col. left if not off board
  190.         JP      NZ,AREA3
  191.         INC     B                       ; left col. established
  192. ;
  193. AREA3:  LD      A,C                     ; one col. right if not off board
  194.         CP      COLS
  195.         JP      Z,AREA4
  196.         INC     C                       ; right col. established
  197. ;
  198. AREA4:  LD      L,0                     ; number of lives in neighboring cells
  199. AREALP: PUSH    BC                      ; save neighboring cols. limits
  200.         PUSH    DE                      ; save neighboring rows limits
  201. ARLP1:  LD      E,B                     ; current row, col. now in DE
  202.         PUSH    HL                      ; save life count
  203.         LD      HL,BOARD
  204.         ADD     HL,DE
  205.         LD      A,(HL)                  ; get cell data from table
  206.         POP     HL                      ; restore life count
  207.         AND     1                       ; keep only bit 0 (life or no life)
  208.         ADD     A,L                     ; inc. neighbor count if live neighbor
  209.         LD      L,A
  210. ;
  211.         LD      A,B                     ; inner loop:  from col. B to col. C
  212.         CP      C
  213.         JR      Z,AREA5                 ; go to next row if done with this one
  214.         INC     B                       ; or next col. if not done with row
  215.         JP      ARLP1
  216. ;
  217. AREA5:  POP     DE                      ; restore neighboring row limits
  218.         POP     BC                      ; we'll start at left-most col. again
  219.         LD      A,D                     ; outer loop:  from row D to row E
  220.         CP      E
  221.         JR      Z,EVAL                  ; evaluate # of neighbors if done
  222.         INC     D                       ; if not done, do next row...
  223.         JP      AREALP
  224. ;
  225. EVAL:   POP     BC                      ; restore current col. & col. limit
  226.         POP     DE                      ; restore current row & row limit
  227.         PUSH    DE                      ; save again for bottom of loop
  228.         PUSH    HL                      ; save life count
  229.         LD      E,B                     ; current row, col now in DE
  230.         LD      HL,BOARD
  231.         ADD     HL,DE
  232.         LD      A,(HL)                  ; get cell from board
  233.         POP     DE                      ; restore life count
  234.         AND     1                       ; do proper evaluation
  235.         LD      A,E                     ; # of neighbors to A
  236.         JR      NZ,YESLIF
  237. ;
  238.         CP      3                       ; no life here, but 3 neighbors?
  239.         JR      NZ,NXTCEL               ; no changes needed if not 3
  240.         LD      A,10B
  241.         LD      (HL),A                  ; update for new life in next gen.
  242.         JP      NXTCEL                  ; on to the next cell
  243. ;
  244. ; For the evaluation which takes place when life is present at the current
  245. ; location, remember that the current cell was also counted along with the
  246. ; neigboring cells, so compare numbers have 1 added to them.
  247. ;
  248. YESLIF: CP      3                       ; 0,1 neighbors means life will die
  249.         JR      C,DIE
  250.         CP      5                       ; will live more if 2-3 neighbors
  251.         JR      C,NXTCEL                ; otherwise it will die (4-8 nbrs.)
  252. ;
  253. DIE:    LD      A,11B
  254.         LD      (HL),A                  ; life will die in next gen.
  255. ;
  256. NXTCEL: POP     DE                      ; restore current row, row limit
  257.         LD      A,B                     ; test current column,
  258.         CP      C                       ; loop until col. limit reached
  259.         JR      Z,BASE                  ; go to next row if done with this one
  260.         INC     B                       ; or next col. if not done with row
  261.         JP      LOOP
  262. ;
  263. BASE:   LD      A,D                     ; outer loop:  to bottom row of board
  264.         CP      E
  265.         JR      Z,ADJUST                ; if done, go adjust screen display
  266.         INC     D                       ; if not done, do next row...
  267.         LD      B,1                     ; starting at first col.
  268.         JP      LOOP
  269. ;
  270. ; Update screen for next generation.
  271. ;
  272. ; We do a nested loop to cover the board.  For cells that are empty now
  273. ; but will have life next gen. (data=10B), the data is changed to 01B.  For
  274. ; cells that have life now but will die next gen. (data=11B), the data is
  275. ; changed to 00B.  In both cases, the screen is updated to show the change.
  276. ;
  277. ADJUST: LD      DE,100H+ROWS            ; start at row 1, go to max. row
  278.         LD      BC,100H+COLS            ; go from col. 1 to max. col.
  279. SHOWLP: PUSH    DE                      ; save current row #, max. row #
  280. SHWLP1: LD      E,B                     ; current row now in D, col. in E
  281.         LD      HL,BOARD
  282.         ADD     HL,DE
  283.         LD      A,(HL)                  ; get cell data from board
  284.         CP      10B                     ; if 00 or 01, no changes needed
  285.         JR      C,NOSHOW
  286.         LD      A,01B                   ; assume new life in next gen.
  287.         JR      Z,NEWNXT                ; if so, don't change new life byte
  288.         LD      A,00B                   ; but change if life will die (11B)
  289. NEWNXT: LD      (HL),A                  ; update to reflect change
  290.         CALL    DISPXY                  ; update display, too
  291. ;
  292. NOSHOW: LD      A,B                     ; continue with next col., same row
  293.         CP      C
  294.         JR      Z,BASE1
  295.         INC     B
  296.         JP      SHWLP1
  297. ;
  298. BASE1:  POP     DE                      ; restore current row # and row limit
  299.         LD      A,D                     ; or next row, first col. if row done
  300.         CP      E
  301.         JR      Z,DONE                  ; leave loop if done
  302.         INC     D
  303.         LD      B,1
  304.         JP      SHOWLP
  305. ;
  306. DONE:   LD      C,DIRCON                ; check to see if a key is pressed
  307.         LD      E,0FFH
  308.         CALL    BDOS
  309.         OR      A
  310.         JP      Z,MAKBOX                ; ON TO NEXT GEN. IF NO KEY
  311.         CP      CTRLS                   ; is their key CTRL-S?
  312.         JP      Z,CENCUR                ; pause game, center cursor
  313.         CP      CTRLC                   ; is their key CTRL-C?
  314.         JP      NZ,MAKBOX               ; exit game if so, next gen. if not
  315. ;
  316. ; Exit to CP/M routine.
  317. ;
  318. EXIT:   LD      DE,ONCRS                ; turn cursor back on
  319.         LD      C,PRSTR
  320.         CALL    BDOS
  321.         LD      DE,CLEAR                ; and clear the screen
  322.         LD      C,PRSTR
  323.         CALL    BDOS
  324. ;
  325.         LD      SP,(OLDSTK)             ; restore old stack
  326.         RET                             ; and return to CP/M
  327. ;
  328. ; Subroutine to position cursor at (X,Y) and display the character that
  329. ; should be there.  (Currently set up for Kaypro 10.)
  330. ;
  331. ; Entry:        D contains row number X
  332. ;               B contains col. number Y
  333. ;
  334. ; Exit:         DE & BC preserved
  335. ;
  336. DISPXY: PUSH    DE              ; save row & col. information
  337.         PUSH    BC
  338.         LD      E,B             ; get row, col. in DE
  339.         LD      HL,BOARD
  340.         ADD     HL,DE
  341.         LD      A,(HL)          ; get cell from board
  342.         AND     1               ; is cell blank?
  343.         LD      A,FILL          ; assume filled in first
  344.         JR      NZ,LIFEXY
  345.         LD      A,EMPTY         ; but change if no life here
  346. LIFEXY: LD      (CRSCHR),A      ; save char. to output
  347. ;
  348.         LD      HL,1F1FH        ; add offset so that row 1, col. 1 = 20,20
  349.         ADD     HL,DE
  350.         LD      D,H             ; swap H & L...
  351.         LD      H,L             ; because cursor positioning format...
  352.         LD      L,D             ; is ROW, COL
  353.         LD      (CRSLOC),HL
  354. ;
  355.         LD      HL,CRSATN       ; position cursor and display char.
  356. DISPLP: LD      C,DIRCON
  357.         LD      A,(HL)          ; end of string?
  358.         OR      A
  359.         JR      Z,DISP1
  360.         PUSH    HL              ; if not, save current string pointer
  361.         LD      E,A             ; move to E for BDOS
  362.         CALL    BDOS            ; and display
  363.         POP     HL
  364.         INC     HL              ; on to next char. in string
  365.         JR      DISPLP
  366. ;
  367. DISP1:  POP     BC              ; restore row & column information
  368.         POP     DE
  369.         RET
  370. ;
  371. ; Storage area for variables
  372. ;
  373. SCRNX:  DS      1               ; current screen X pos.
  374. SCRNY:  DS      1               ; current screen Y pos.
  375. ;
  376. CRSATN: DB      ESC,'Y'         ; ADM-3A cursor addressing attention
  377. CRSLOC: DB      '  '            ; row & col. for cursor positioning
  378. CRSCHR: DB      ' '             ; cell data to display goes here
  379.         DB      0               ; end of string
  380. ;
  381. CLEAR:  DB      1BH,'E'         ; clear screen sequence
  382. ONCRS:  DB      ESC,'x5'       ; command to turn cursor on
  383. OFFCRS: DB      ESC,'y5'       ; command to turn cursor off
  384. ;
  385.         DS      50              ; stack space
  386. STACK   EQU     $
  387. OLDSTK: DS      2               ; location of old stack saved here
  388. ;
  389. ; Instructions on how to play.  This area is erased when the game begins,
  390. ; and is used as storage for the board cell pattern.
  391. ;
  392. BOARD:  DB      1AH
  393.         DB      'This is a Z80 version of the famous Game of Life, '
  394.         DB      'invented by John Conway.',13,10,13,10
  395.         DB      'I will start you off at the center of the screen.  '
  396.         DB      'You use the arrow keys to',13,10
  397.         DB      'move the cursor.  To place a cell at a certain '
  398.         DB      'spot, press the space bar.',13,10
  399.         DB      'Pressing the space bar on a location that already has '
  400.         DB      'a cell removes that cell.',13,10,13,10
  401.         DB      'Action keys are:',13,10,13,10
  402.         DB      'CTRL-Z will erase all cells and begin again',13,10
  403.         DB      'CTRL-Q will start the action',13,10
  404.         DB      'CTRL-S will stop the action so you can edit cells again',13,10
  405.         DB      'CTRL-C will return you to CP/M.',13,10,13,10
  406.         DB      'Remember, the rules of the Game of Life are:',13,10,13,10
  407.         DB      'Each location has 8 neighboring locations.  If a cell '
  408.         DB      'exists in a neighboring',13,10
  409.         DB      'position, it is called a neighbor.',13,10,13,10
  410.         DB      'No cell here, but 3 neighbors ---> new cell next gen.',13,10
  411.         DB      'Cell here, 2-3 neighbors ---> lives another gen.',13,10
  412.         DB      'Cell here, 0-1 neighbors ---> dies from isolation',13,10
  413.         DB      'Cell here, 4-8 neighbors ---> dies from overpopulation',13,10
  414.         DB      13,10
  415.         DB      'Press any key to begin  > $'
  416. ;
  417.         END
  418. 
  419.  
  420.  
  421.  
  422.  
  423.  
  424.  
  425.  
  426.  
  427.  
  428.  
  429.  
  430.  
  431.  
  432.  
  433.  
  434.  
  435.  
  436.  
  437.  
  438.  
  439.  
  440.  
  441.  
  442.