home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / sampler0 / life.asm < prev    next >
Assembly Source File  |  1986-03-01  |  7KB  |  303 lines

  1. COMMENT $
  2.  
  3.      FILE NAME GAM_LIFE.ASM
  4.      TITLE     THE GAME OF LIFE ON THE IBM-PC
  5.      SOURCE    DR. DOBB'S JOURNAL,#80,JUNE 1983
  6.      AUTHOR    SIMSON L. GARFINKEL
  7.  
  8.      *****************************
  9.      *                 *
  10.      *       THE GAME OF LIFE     *
  11.      *                 *
  12.      *****************************
  13.  
  14.      John Conway's mathematical game of life, implemented on
  15.      the IBM/PC, by Simson L. Garfinkel.
  16.  
  17.      Written in 8088 assembly language using the Microsoft
  18.      Macro Assembler.
  19.  
  20.      Notes on running the program:
  21.  
  22.        When program is run:
  23.  
  24.         1.    Screen clears.
  25.         2.    User enters first generation from keyboard.
  26.         Arrow keys move the cursor.  INS key deposits
  27.         a live cell, DEL removes a live cell, (in case
  28.         the user makes a mistake.)
  29.         3.    Pressing ESC starts program.
  30.         4.    For each generation, cells which will have life
  31.         on the next turn are inverted.
  32.         5.    Screen is updated to next generation.
  33.         6.    Keyboard is interrogated for command.
  34.         7.    If ESC is pressed, program terminates.
  35.         8.    If a number 0-9 is pressed, speed is selected.
  36.         At speed 0, approx. 2.7 generations/sec are performed.
  37.         At speed 9, each generation takes 3.5 sec.
  38.         9.    program loops to #4.
  39.  
  40.      $
  41.  
  42.       ;global definitions
  43.  
  44. LIVE    EQU   02       ;CHARACTER FOR A LIVE CELL
  45. DEAD    EQU   00       ;CHARACTER FOR A DEAD CELL
  46.  
  47. REV    EQU   70H      ;REVERSE VIDEO (MARKS CELL TO LIVE)
  48. DARK    EQU   2        ;NORMAL VIDEO  (MARKS CELL TO DIE )
  49.  
  50. TIME    EQU   300      ;TIME DELAY BASE
  51.  
  52. TERM    EQU   27       ;CHARACTER TO EXIT MODE
  53.  
  54. CSEG  SEGMENT PARA PUBLIC 'CODE'
  55. START    PROC FAR
  56.     ASSUME CS:CSEG,DS:NOTHING,SS:NOTHING,ES:NOTHING
  57.  
  58.                ;SET UP RETURN LOCATION
  59.     PUSH  DS
  60.     SUB   AX,AX    ;NOT I CAN GO HAME WHEN I'M FINISHED
  61.     PUSH  AX
  62.  
  63.     CALL  ENTER    ;ENTER BOARD
  64.     MOV   CX,0     ;INITIAL DELAY, 0
  65. MAIN:
  66.     PUSH  CX       ;SAVE DELAY VARIABLE
  67.     CMP   CX,0
  68.     JZ    S13
  69.  
  70. S1:    PUSH  CX
  71.       MOV  CX,TIME
  72. S11:      PUSH    CX
  73.         MOV  CX,TIME
  74.         LOOP  S12
  75. S12:      POP  CX
  76.       LOOP    S11
  77.     POP   CX
  78.     LOOP  S1       ;WHAT A TIME DELAY!
  79.  
  80. S13:    CALL  COUNT    ;COUNT UP EVERY CELL'S NEIGHBOURS,
  81.     CALL  UPDATE   ;UPDATE SCREEN
  82.     POP   CX       ;GET BACK THE TIME DELAY
  83.  
  84.     MOV   AH,1     ;SEE IF USER HAS PUSHED A KEY
  85.     INT   16H
  86.     JZ    MAIN     ;NOPE - LOOP BACK
  87.  
  88.     MOV   AH,0     ;GET THE CHARACTER OUT OF THE BUFFER
  89.     INT   16H
  90.  
  91.     CMP   AL,TERM
  92.     JNZ   S2
  93.     RET           ;FINISHED - GO BACK TO MS/DOS
  94.  
  95. S2:    CMP   AL,'0'   ;SEE IF IT IS A SPEED COMMAND
  96.     JB    MAIN
  97.     CMP   AL,'9'
  98.     JNBE  MAIN
  99.                ;IT'S A NUMBER
  100.     SUB   AL,'0'   ;NOW IT GOES FROM 0 TO 9
  101.     MOV   AH,0
  102.     MOV   CX,AX    ;PUT IT IN CX
  103.     JMP   MAIN
  104. START    ENDP
  105.  
  106.  
  107. ENTER    PROC  NEAR     ;SUBROUTINE TO ENTER BOARD
  108.                ;DEFINE SCAN-CODES:
  109. LEFT    EQU  75
  110. RIGHT    EQU  77
  111. UP    EQU  72
  112. DOWN    EQU  80
  113. POINT    EQU  82
  114. DEL    EQU  83
  115. ESC    EQU   1
  116.  
  117.     CALL  CLS      ;CLEAR THE SCREEN
  118.  
  119.     ;REGISTERS ARE USED AS FOLLOWS:
  120.     ;DH - Y POSITION
  121.     ;DL - X POSITION
  122.  
  123.     MOV   AH,12
  124.     MOV   DL,40
  125.  
  126. E1:    MOV   BH,0     ;MOVE THE CURSOR TO X,Y POSITION
  127.     MOV   AH,2     ;CODE THE CURSOR MOVE
  128.     INT   10H      ;INTERRUPT FOR CURSOR MOVE
  129.  
  130.     MOV   AH,0     ;SET UP TO READ THE NEXT KEYPRESS
  131.     INT   16H      ;KEYPRESS READ
  132.  
  133.     CMP   AH,LEFT  ;MAKE A RATIONAL DECISION ABOUT THE USERS
  134.     JZ    GO_LEFT  ;ENTRY
  135.     CMP   AH,RIGHT
  136.     JZ    GO_RIGHT
  137.     CMP   AH,UP
  138.     JZ    GO_UP
  139.     CMP   AH,DOWN
  140.     JZ    GO_DOWN
  141.     CMP   AH,POINT
  142.     JZ    GO_POINT
  143.     CMP   AH,DEL
  144.     JZ    GO_DEL
  145.  
  146.     CMP   AH,ESC
  147.     JNZ   E1       ;LOOP BACK - UNKNOWN COMMAND
  148.     MOV   DX,23*256   ;PUT THE CURSOR AT LOWER-LEFT HAND CORNER
  149.     MOV   AH,2
  150.     INT   10H
  151.     RET           ;GO BACK TO CALLER
  152.  
  153. GO_LEFT:           ;MOVE LEFT IF I CAN
  154.     CMP   DL,0     ;IN LEFTMOST COLLUMN?
  155.     JZ    E1       ;YES - GO BACK
  156.     SUB   DL,1     ;NO - SUBTRACK ONE
  157.     JMP   E1       ;GO BACK
  158.  
  159. GO_RIGHT:           ;MOVE RIGHT IF I CAN
  160.     CMP   DL,79
  161.     JZ    E1
  162.     ADD   DL,1
  163.     JMP   E1
  164.  
  165. GO_UP:               ;GO UP IF I CAN
  166.     CMP   DH,0
  167.     JZ    E1
  168.     SUB   DH,1
  169.     JMP   E1
  170.  
  171. GO_DOWN:           ;GO DOWN IF I CAN
  172.     CMP   DH,24
  173.     JZ    E1
  174.     ADD   DH,1
  175.     JMP   E1
  176.  
  177. GO_POINT:           ;PUT A LIVE DOT WHERE THE CURSOR IS -- DON'T MOVE IT
  178.     MOV   AL,LIVE  ;IT'S THE LIVE CHARACTER
  179. GP2:    MOV   CX,1     ;ONE CHARACTER TO WRITE
  180.     MOV   AH,10    ;CODE TO WRITE CHARACTER
  181.     INT   10H      ;DO IT
  182.     JMP   E1       ;GET NEXT COMMAND
  183.  
  184. GO_DEL:            ;DELETE CHARACTER AT CURSOR
  185.     MOV   AL,DEAD
  186.     JMP   GP2      ;LET GO_POINT DO THE REST
  187. ENTER    ENDP
  188.  
  189.  
  190. CLS    PROC  NEAR     ;SUBROUTINE TO CLEAR THE SCREEN
  191.     MOV   AX,6*256
  192.     MOV   CX,0
  193.     MOV   DX,24*256+79
  194.     MOV   BH,2
  195.     INT   10H
  196.     RET
  197. CLS    ENDP
  198.  
  199.  
  200. COUNT    PROC  NEAR     ;SUBROUTINE TO COUNT UP EVERY CELL'S NEIGHBOURS
  201.     ;REGISTERS USED:
  202.     ;DH,DL:  Y,X OF SURRENT CELL BEING INTERROGATED
  203.     ;DS   :  BASE OFFSET - INTO SCREEN MEMORY
  204.     ;DI   :  OFFSET FOR CHARACTER PRESENTLY BEING LOOKED AT
  205.     ;
  206.     ;OUTLINE FOR EACH CHARACTER
  207.     ;  1.  COUNT UP NUMBER OF NEIGHBOURS
  208.     ;  2.  IF THREE NEIGHBOURS, OR IF TWO AND CELL IS LIVE, PUT
  209.     ;      A REV ON THE SCREEN AT THE ATTRIBUTE PASITION, ELSE
  210.     ;      PUT A DARK
  211.     ;  3.  GO TO NEXT CHARACTER
  212.  
  213. CHK MACRO   YY,XX
  214.     LOCAL CH1,OFFS
  215. OFFS    EQU   (XX+YY*80)*2
  216.     MOV   CX,[DI+OFFS]    ;GET BYTE TO CHECK
  217.     CMP   CL,LIVE          ;CHECK TO SEE IF THIS CELL IS ALIVE
  218.     JNZ   CH1          ;NOPE
  219.     ADD   AL,1          ;YES - INCREASE NEIGHBOUR COUNT
  220. CH1:
  221.     ENDM
  222.     MOV   AX,0Bb00H
  223.     MOV   DS,AX          ;OFFSET VALUE FOR MONOCHROME DISPLAY
  224.  
  225.     MOV   DH,1          ;START AT 1,1 AND GO TO 23,78
  226.     MOV   DL,1          ;TO PREVENT WRAP-ARROUND
  227.  
  228. C1:    MOV   AX,160          ;GET TRUE OFFSET FROM DS INTO SCREEN MEMORY
  229.     MUL   DH
  230.  
  231.     MOV   CX,DX
  232.     MOV   CH,00          ;JUST GET DL
  233.     ADD   AX,CX
  234.     ADD   AX,CX          ;AX:=(DH*80+DL)*2
  235.  
  236.     MOV   DI,AX          ;DI:=AX
  237.     MOV   AX,0          ;AX WILL BE USED FOR NEIGHBOUR COUNTING
  238.  
  239.     CHK   -1,-1          ;COUNT NUMBER OF NEIGHBOURS
  240.     CHK   -1, 0
  241.     CHK   -1,+1
  242.     CHK    0,-1
  243.     CHK    0,+1
  244.     CHK   +1,-1
  245.     CHK   +1, 0
  246.     CHK   +1,+1          ;TEST ALL OF THE NEIGHBOURS
  247.  
  248.     MOV   CX,[DI]          ;GET BYTE TO CHECK
  249.     CMP   AL,3
  250.     JZ    GIVE_LIFE       ;LIFE IF HAS 3 NEIGHBOURS
  251.     CMP   CL,LIVE          ;IS IT ALIVE?
  252.     JNZ   GIVE_DEATH      ;NO
  253.     CMP   AL,2          ;HE LIVES IF HE HAS 2 NEIGHBOURS AND HE IS
  254.                   ;ALREADY ALIVE
  255.     JNZ   GIVE_DEATH      ;NOPE
  256.  
  257. GIVE_LIFE:              ;MAKE THIS ONE ALIVE
  258.     MOV   CH,REV
  259.     JMP   C2
  260.  
  261. GIVE_DEATH:
  262.     MOV   CH,DARK
  263. C2:    MOV   [DI],CX          ;PUT BACK ON THE SCREEN
  264.  
  265. NEXT_CELL:
  266.     CMP   DL,78          ;AM I AT THE END OF THE X LINE?
  267.     JZ    C3          ;YES
  268.     ADD   DL,1          ;NOPE
  269.     JMP   C1
  270. C3:    MOV   DL,1
  271.     CMP   DH,23          ;AM I AT THE END OF THE Y LINE?
  272.     JZ    C4          ;YES
  273.     ADD   DH,1          ;NOPE
  274.     JMP   C1
  275. C4:    RET              ;YES - GO HOME
  276. COUNT    ENDP
  277.  
  278. UPDATE    PROC  NEAR        ;THIS UPDATES THE GENERATION ON THE SCREEN
  279.     MOV   AX,0Bb00H     ;GET SCREEN OFFSET
  280.     MOV   DS,AX
  281.  
  282.     MOV   BX,24*80*2-2  ;LOOP THROUGH ALL OF THE SCREEN BUT LAST LINE
  283. U1:    MOV   CX,[BX]        ;LINE
  284.     CMP   CH,REV        ;IS IT LIVE?
  285.     JNZ   U2        ;NO
  286.     MOV   CL,LIVE        ;YES
  287.     JMP   U3
  288. U2:    MOV   CL,DEAD        ;NO
  289. U3:    MOV   CH,DARK        ;TURN OFF REVERSE
  290.     MOV   [BX],CX        ;PUT IT BACK ON THE SCREEN
  291.     SUB   BX,2        ;LOOP BACK UNTIL DONE WITH THE SCREEN
  292.     JG    U1
  293.     RET            ;GO BACK TO CALLER
  294. UPDATE    ENDP
  295. CSEG    ENDS
  296.  
  297. STACK    SEGMENT PARA STACK 'STACK'
  298.     DB 30 DUP('STACK  ')
  299. STACK    ENDS
  300.  
  301.     END
  302.  
  303.