[76-byte Life Simulator]                              [Assembler][/][80286]

This is a small implementation of the well known 'Game Of Life'.
It has now been reduced to 65 bytes. All previous published versions on the
page is included in the archive. Here follows a description of what has
been optimized:

     If there is to be any reduction in life's filesize, it looks like it
     must be at the beginning where it gets a random number and initializes
     the DS.
     Life currently starts with:

     Start:  mov     al,13h          ; Set mode 13h
             int     10h

             mov     ds,ax           ; Seed RNG with clock
             mov     ax,[033Ch]

     ... in an attempt to get a semi-random value from the tic counter.
     Because the program begins with AH=00, it's smaller to get the clock
     counter from INT 1Ah:

     Start:
             int     1a              ; ah=00: cx=hours, dx=tic counter
             mov     al,13h          ; Set mode 13h
             int     10h

     ;        mov     ds,ax           ; Seed RNG with clock
     ;        mov     ax,[033Ch]

             xchg    dx,ax           ; transfer tics into AX

             push    09000h          ; DS = last 64K segment
             pop     ds
             push    0A000h          ; ES = video memory
             pop     es
                                     ; BX is already zero

     You can reduce the size even more, by changing the randloop from:

     RandLoop:
             add     ax,ax           ; Generate random number
             setc    [bx]
             jnc     RandSkip
             xor     al,045xd
     RandSkip:
             dec     bx
             jnz     RandLoop

     It isn't necessary for DS to be filled with 0x01's, since that gets
     taken care of within the first few passes:

     RandLoop:
             rol     ax,1            ; add ax,ax     ; Generate random number
             adc     [bx],al         ; setc [bx]
                                     ; jnc RandSkip
                                     ; xor al,045xd
     RandSkip:
             dec     bx
             jnz     RandLoop

     Making these changes results in a reduced size of 65 bytes.

There have been reports that using 9000h as a 64k buffer may crash the
computer. This is however not the case with the 4 computers I have tested
it with. I run Win95 DOS (DOS7.0) and Win95 DOS box. Both have that area
free. Since the source is included anyone wishing to correct this problem
may do so. The 9000h segment is used as memory management in some
configurations. This might be avoided by loading DOS high.

The source and a compiled version is available for download (2805 bytes).

; Life simulator, 72 bytes  - Vladislav Kaipetsky and Tenie Remmel
;                 65 bytes  - Mark Andreas

; If no args, regs on startup are:

; AX = BX = 0000h
; SI = IP = 0100h
; DI = SP = FFFEh

IDEAL
MODEL TINY
P386
CODESEG
ORG 100h

Start:  int     1ah             ; ah=00: cx=hours, dx=tic counter

        mov     al,13h          ; Set mode 13h
        int     10h

        push    09000h          ; DS = last 64K segment
        pop     ds
        push    0A000h          ; ES = video memory
        pop     es
                                ; BX is already zero
RandLoop:
        rol     ax,1            ; Generate random number
        adc     [bx],al
        dec     bx
        jnz     RandLoop

; BX will not be equal to 3 the first time this loop is executed, but
; it will be for all other times.   As SI = 0100h and DI = FFFEh on
; startup, SI - DI will be equal to 258.

LifeLoop:
        xchg    cx,ax
AccLoop:
        add     cl,[di+bx-64]   ; Add in this column
        add     cl,[si+bx-2]
        add     cl,[si+bx+318]
        dec     bx              ; Loop back
        jnz     AccLoop

        mov     al,[si]         ; Get center cell, set pixel
        stosb
        stc                     ; 3 = birth, 4 = stay (tricky):
        rcr     al,cl           ; 1.00?0000x --> 0.0x100?00 (rcr 3)
        and     al,20h          ; ^carry   |         ^
                                ;          +---> 0.00x100?0 (rcr 4)
        or      [si],al         ; Add in new cell     ^
        shr     [byte di-65],5  ; Shift previous value

        mov     bl,3            ; 3 iterations in AccLoop
        inc     si              ; Loop while not zero
        jnz     LifeLoop

        mov     ah,1            ; Check for key
        int     16h
        jz      LifeLoop        ; Loop if no key

        xchg    ax,bx           ; Set text mode
        int     10h
        ret                     ; Return

End     Start

Note from John:
You may replace the key check with the following snippet:

        in      al,60h
        das
        jc      LifeLoop

It will save one byte, it is however not as reliable as the solution
presented above.
                                  Gem writers: (optimisations) Mark Andreas
                                                   (comments) John Eckerdal
                                                        Vladislav Kaipetsky
                                                               Tenie Remmel
                                                   last updated: 1998-06-07
