; BOMBER - a tiny game - by Tylisha C. Andersen & Tenie Remmel
; the original idea for this was from a 256-byte-game contest
; our version has a score display, and is still only 248 bytes!
;
; commands:  <esc> = exit;  <space> = drop a bomb.

o           equ <offset>
b           equ <byte ptr>
w           equ <word ptr>

.model tiny
.code
.186
org 100h

;-----------------------------------------------------------

main:       xor   ax, ax            ; set video mode 0 (40x25)
            int   10h

            mov   ah, 11h           ; set chars C0 and C1 to airplane bitmap
            mov   bx, 0F00h
            mov   cx, 2
            mov   dx, 0C0h
            mov   bp, o font1
            int   10h

            dec   cx                ; set char 00 to bomb bitmap
            xor   dx, dx
            mov   bp, o font2
            int   10h

            mov   ah, 1             ; turn off cursor
            mov   ch, 20h
            int   10h

            push  0B800h            ; es = video-memory
            pop   es

            mov   b es:[78], 30h    ; draw the initial score (0)

;-----------------------------------------------------------

m_bigloop:  push  0                 ; ds = segment 0
            pop   ds

            mov   dx, 1996          ; dx = end of screen (2000-4)
            mov   bx, 38            ; 38 bars to draw

m_randloop: mov   cx, ds:[046Ch]    ; generate random number
            xor   cx, bx
            xor   cx, di

            mov   ax, 7DB1h         ; ah = random color, al = 50% gray
            and   ah, cl
            inc   ah
            and   cx, 0Fh           ; cx = random length 1-16
            inc   cx

            mov   di, dx            ; di = starting offset
m_barloop:  stosw                   ; draw this char
            sub   di, 82            ; next char
            loop  m_barloop         ; loop

            dec   dx                ; next bar
            dec   dx
            dec   bx                ; loop
            jnz   m_randloop

            mov   di, 82            ; initial di for main loop
            mov   bx, 2000          ; bx = offset of bomb flag
            inc   cx                ; cx:dx = 01B800h for delay
            mov   dx, es

            push  es                ; ds = video memory
            pop   ds

;-----------------------------------------------------------

m_mainloop: mov   b [di-2], 20h     ; clear char at [di-2]
            cmp   di, bx            ; made it to the bottom, start again
            je    m_bigloop

            mov   ax, 09C0h         ; draw bomber at current position
            stosw                   ; and move forward by one char
            inc   ax
            mov   [di], ax

            cmp   b [di+2], 0B1h    ; hit a building, game over
            je    m_gameover
            cmp   b [bx], cl        ; check if a bomb is falling (cl = 1)
            jne   m_cont

;-----------------------------------------------------------

            mov   w [bx+si], 0720h  ; erase the bomb
            add   si, 80            ; move down 1 line
            sbb   b [bx], ch        ; clear bomb flag if off screen (ch = 0)
            jz    m_cont            ; jump if flag was cleared

            cmp   b [bx+si], 0B1h   ; test this position
            mov   w [bx+si], 0E00h  ; draw the bomb again
            jne   m_cont            ; skip if not block

            push  si                ; save si
            mov   si, 78            ; offset of last char in score
m_incloop:  or    b [si], 30h       ; turn space into zero
            inc   b [si]            ; increment char
            cmp   b [si], '9'       ; if no carry, then quit
            jbe   m_incdone
            mov   b [si], '0'       ; otherwise, set to 0,
            dec   si                ; and continue
            dec   si
            jmp   m_incloop
m_incdone:  pop   si                ; restore si

;-----------------------------------------------------------

m_cont:     mov   ah, 086h          ; delay 1/9 second
            int   15h

            mov   ah, 1             ; check for a key
            int   16h
            jz    m_mainloop
            xor   ax, ax            ; get the key
            int   16h

            cmp   al, 1Bh           ; escape = done
            je    m_done
            sub   al, 20h           ; space = drop bomb:
            jnz   m_mainloop

            cmp   b [bx], cl        ; if a bomb is already falling,
            je    m_mainloop        ; then do nothing, otherwise,
            lea   si, [di-1920]     ; set the bomb position
            mov   b [bx], cl        ; set the bomb flag (cl = 1)
            jmp   m_mainloop        ; loop

m_gameover: xchg  ax, cx            ; wait for a key (ch = 0)
            int   16h
m_done:     mov   ax, 3             ; restore text mode and return
            int   10h
            ret

;-----------------------------------------------------------

font1   db      000h,000h,000h,000h,000h,0C0h,040h,0F1h
        db      07Fh,07Fh,03Dh,01Bh,007h,00Fh,000h
        db      000h,000h,000h,000h,000h,03Ch,0EAh,0BFh
        db      0FFh,0EEh,0DCh,080h

font2   db      000h,000h,000h,000h,000h,018h,03Ch,066h
        db      0EBh,0E7h,0EBh,066h,03Ch,018h,000h

end main
