Search code examples
assemblyemu8086

Is there a way to check for specific memory locations in assembly to make the snake grow in Snake Game on emu8086?


org     100h


jmp     start

s_size  equ     7       

snake dw s_size dup(0)

tail    dw      ?

left    equ     4bh
right   equ     4dh
up      equ     48h
down    equ     50h       

cur_dir db      right

wait_time dw    0

msg1    db "                                  Snake game", 0dh,0ah,0ah
    
    db "                        Yilani on oklari ile kontrol et.", 0dh,0ah,0ah  
    db "                         Duvarlara degersen yanarsin!!!", 0dh,0ah, 0ah  
    db "                            Esc programi sonlandirir.", 0dh,0ah,0ah,0ah
    db "                           Baslamak icin bir tusa bas.$"



msg3  db "", 0dh,0ah, 0ah,0ah, 0ah,0ah,0ah, 0ah,0ah,0ah, 0ah,0ah,0ah, 0ah,0ah, 0ah, 0ah, 0ah,               
db "                                  !!GAME OVER!!", 0dh,0ah,0ah, 0ah, 0ah, 0ah,0ah, 0ah,0ah,      
db " $"
start:       

; print welcome message:
mov     dx, offset msg1
mov     ah, 9 
int     21h


; wait for any key:
mov ah, 00h
int 16h 

mov ax, 0xB800  ; Video memory segment
mov es, ax      ; Set ES segment to video memory

es: mov [09b4h],'?'
es: mov [0848h],'0'
es: mov [06b0h],'0' 
es: mov [01E8h],'0'


; hide text cursor:
mov     ah, 1
mov     ch, 2bh
mov     cl, 0bh
int     10h           


game_loop:

; === select first video page
mov     al, 0  
mov     ah, 05h
int     10h

mov     dx, snake[0]

; set cursor at dl,dh
mov     ah, 02h
int     10h

; print 'o' at the location:
mov     al, 'o'
mov     ah, 09h
mov     bl, 0eh 
mov     cx, 1  
int     10h

; === keep the tail:
mov     ax, snake[s_size * 2 - 2]
mov     tail, ax

call    move_snake


; === hide old tail:
mov     dx, tail

; set cursor at dl,dh
mov     ah, 02h
int     10h

; print '.' at the old location:
mov     al, ' '
mov     ah, 09h
mov     bl, 0eh 
mov     cx, 1  
int     10h



check_for_key:

; === check for player commands:
mov     ah, 01h
int     16h
jz      no_key

mov     ah, 00h
int     16h

cmp     al, 1bh    ; esc - key?
je      stop_game  ;

mov     cur_dir, ah

no_key:

; === wait a few moments here:
; get number of clock ticks
; (about 18 per second)
; since midnight into cx:dx
mov     ah, 00h
int     1ah
cmp     dx, wait_time
jb      check_for_key
add     dx, 4
mov     wait_time, dx



; === eternal game loop:
jmp     game_loop


stop_game:

; show cursor back:
mov     ah, 1
mov     ch, 0bh
mov     cl, 0bh
int     10h

ret

move_snake proc near

; set es to bios info segment:  
mov     ax, 40h
mov     es, ax

  ; point di to tail
  mov   di, s_size * 2 - 2
  ; move all body parts
  ; (last one simply goes away)
  mov   cx, s_size-1
move_array:
  mov   ax, snake[di-2]
  mov   snake[di], ax
  sub   di, 2
  loop  move_array


cmp     cur_dir, left
  je    move_left
cmp     cur_dir, right
  je    move_right
cmp     cur_dir, up
  je    move_up
cmp     cur_dir, down
  je    move_down

jmp     stop_move       ; no direction.


move_left:
  mov   al, b.snake[0]
  dec   al
  mov   b.snake[0], al

  cmp   al, -1
  jne   stop_move       
  mov   al, es:[4ah]    ; col number.
  dec   al
  call game_over  ; return to right. 
  
  jmp   stop_move

move_right:
  mov   al, b.snake[0]
  inc   al
  mov   b.snake[0], al 
  cmp   al, es:[09b4h]
  cmp   al, es:[4ah]    ; col number. 
  jb    stop_move
  call game_over   ; return to left.    
  jmp   stop_move

move_up:
  mov   al, b.snake[1]
  dec   al
  mov   b.snake[1], al
  cmp   al, -1
  jne   stop_move
  mov   al, es:[84h]    ; row number -1.
  call game_over  ; return to bottom.     
  jmp   stop_move

move_down:
  mov   al, b.snake[1]
  inc   al
  mov   b.snake[1], al
  cmp   al, es:[84h]    ; row number -1.
  jbe   stop_move
  call game_over   ; return to top.   
  jmp   stop_move

stop_move:


ret      

grow_snake:

ret

    
game_over: 

mov     dx, offset msg3
mov     ah, 9 
int     21h


; wait for any key:
mov ah, 00h
int 16h   

  
move_snake endp

I tried to grow snake when it reaches to these memory locations:

es: mov [09b4h],'?'
es: mov [0848h],'0'
es: mov [06b0h],'0' 
es: mov [01E8h],'0'

but i couldnt get it done. My first plan was check it in stop_game and call grow_snake in there but i didnt work no matter how i tried. But couldnt do anything about grow_snake part triend to inc s_size but it also doesnt work.

How am i gonna check if snake reaches the memory location that i printed something and gro accordingly?

Thank you.


Solution

  • Update

    If You don't mind I wrote CheckFood proc after printing snake's head on screen. Which translates head's X Y coords to offset in mem and search if there is same address in array targetInMem.

        org     100h
    
        jmp     start
    
        s_size  equ     7       
    
        snake dw s_size dup(0)
    
        tail    dw      ?
    
        left    equ     4bh
        right   equ     4dh
        up      equ     48h
        down    equ     50h       
    
        targetInMem dw 09b4h,0848h,06b0h,01E8h 
    
        cur_dir db      right
    
        wait_time dw    0
    
        Food1  db "Food 1                       ", 0dh,0ah,'$'
        Food2  db "Food 2                          ", 0dh,0ah,'$'
        Food3  db "Food 3                          ", 0dh,0ah,'$'
        questMark  db "Question mark", 0dh,0ah,'$'
    
        msg1    db "             Snake game",0dh,0ah,0ah
                db "       Yilani on oklari ile kontrolet.",0dh,0ah,0ah  
                db "          Duvarlara degersen yanarsin!!!", 0dh,0ah, 0ah  
                db "  Esc programi sonlandirir.", 0dh,0ah,0ah,0ah
                db "                           Baslamak icin bir tusa bas.$"
    
        msg3  db "", 0dh,0ah, 0ah,0ah, 0ah,0ah,0ah, 0ah,0ah,0ah, 0ah,0ah,0ah, 
              db "                                  !!GAME OVER!!", 0dh, 0ah, 
              db 0ah, 0ah, 0ah, 0ah,0ah, 0ah,0ah," $"
    
        start:       
        mov ax,0003h
        int 10h
        ; print welcome message:
        mov     dx, offset msg1
        mov     ah, 9 
        int     21h
    
        ; wait for any key:
        mov ah, 00h
        int 16h 
    
        mov ax, 0xB800  ; Video memory segment
        mov es, ax      ; Set ES segment to video memory
    
        es: mov [09b4h],'?'
        es: mov [0848h],'1'
        es: mov [06b0h],'2' 
        es: mov [01E8h],'3'
    
        ; hide text cursor:
        mov     ah, 1
        mov     ch, 2bh
        mov     cl, 0bh
        int     10h           
    
        game_loop:
    
        ; === select first video page
        mov     al, 0  
        mov     ah, 05h
        int     10h
    
        mov     dx, snake[0]
    
        ; set cursor at dl,dh
        mov     ah, 02h
        int     10h
    
        ; print 'o' at the location:
        mov     al, 'o'
        mov     ah, 09h
        mov     bl, 0eh 
        mov     cx, 1  
        int     10h
    
        call CheckFood
    
        ; === keep the tail:
        mov     ax, snake[s_size * 2 - 2]
        mov     tail, ax
    
        call    move_snake
    
        ; === hide old tail:
        mov     dx, tail
    
        ; set cursor at dl,dh
        mov     ah, 02h
        int     10h
    
        ; print '.' at the old location:
        mov     al, ' '
        mov     ah, 09h
        mov     bl, 0eh 
        mov     cx, 1  
        int     10h
    
        check_for_key:
    
        ; === check for player commands:
        mov     ah, 01h
        int     16h
        jz      no_key
    
        mov     ah, 00h
        int     16h
    
        cmp     al, 1bh    ; esc - key?
        je      stop_game  ;
    
        mov     cur_dir, ah
    
        no_key:
    
        ; === wait a few moments here:
        ; get number of clock ticks
        ; (about 18 per second)
        ; since midnight into cx:dx
        mov     ah, 00h
        int     1ah
        cmp     dx, wait_time
        jb      check_for_key
        add     dx, 4
        mov     wait_time, dx
    
        ; === eternal game loop:
        jmp     game_loop
    
        stop_game:
    
        ; show cursor back:
        mov     ah, 1
        mov     ch, 0bh
        mov     cl, 0bh
        int     10h
    
        ret
    
        move_snake proc near
    
        ; set es to bios info segment:  
        mov     ax, 40h
        mov     es, ax
    
        ; point di to tail
        mov   di, s_size * 2 - 2
        ; move all body parts
        ; (last one simply goes away)
        mov   cx, s_size-1
       move_array:
       mov   ax, snake[di-2]
       mov   snake[di], ax
       sub   di, 2
       loop  move_array
    
       cmp     cur_dir, left
       je    move_left
       cmp     cur_dir, right
       je    move_right
        cmp     cur_dir, up
       je    move_up
       cmp     cur_dir, down
       je    move_down
    
       jmp     stop_move       ; no direction.
    
        move_left:
        mov   al, b.snake[0]
        dec   al
        mov   b.snake[0], al
    
        cmp   al, -1
        jne   stop_move       
        mov   al, es:[4ah]    ; col number.
        dec   al
        call game_over  ; return to right. 
      
        jmp   stop_move
    
        move_right:
        mov   al, b.snake[0]
        inc   al
        mov   b.snake[0], al 
        cmp   al, es:[09b4h]
        cmp   al, es:[4ah]    ; col number. 
        jb    stop_move
        call game_over   ; return to left.    
        jmp   stop_move
    
        move_up:
        mov   al, b.snake[1]
        dec   al
        mov   b.snake[1], al
        cmp   al, -1
        jne   stop_move
        mov   al, es:[84h]    ; row number -1.
        call game_over  ; return to bottom.     
        jmp   stop_move
    
        move_down:
        mov   al, b.snake[1]
        inc   al
        mov   b.snake[1], al
        cmp   al, es:[84h]    ; row number -1.
        jbe   stop_move
        call game_over   ; return to top.   
        jmp   stop_move
    
        stop_move:
    
        ret      
    
        grow_snake:
    
        ret
    
        CheckFood: 
           pusha
       
           xor ax,ax        ;calculate head position
           mov al,dh;[yPos]
            mov cl,80
            mul cl 
            xor cx,cx
            mov cl,dl;[xPos]   
            add ax,cx    ; ax offset in mem   
            mov cx,2
            mul cx
       
            mov bx, offset targetInMem
            mov cx,4
       
            push dx       
          
          MemSearch:       ;search array, what snake eat    
          mov dx,[bx]       
          cmp dx,ax
          jz PrintMsg
          add bx,2
          loop MemSearch  
           
          jmp NoFood
          
          PrintMsg:
             ; set cursor at dl,dh
            mov ah, 2
            mov bh,0
            mov dx, 1010h
            int 10h 
            
            cmp cx,4           
            jz msgFood1
            cmp cx,3           
            jz msgFood2
            cmp cx,2           
            jz msgFood3
            cmp cx,1           
            jz qMark        
            jmp NoFood
            
            msgFood1:
                mov     dx, offset questMark
                mov     ah, 9 
                int     21h                
                jmp NoFood
                
            msgFood2:
                mov     dx, offset Food1
                mov     ah, 9 
                int     21h                
                jmp NoFood
                        
            msgFood3:
                mov     dx, offset Food2
                mov     ah, 9 
                int     21h                
                jmp NoFood              
                
            qMark:
                mov     dx, offset Food3 
                mov     ah, 9 
                int     21h                 
                
          NoFood:          
             pop dx  
            
        popa    
    ret
        
    game_over: 
    
    mov     dx, offset msg3
    mov     ah, 9 
    int     21h
    
    
    ; wait for any key:
    mov ah, 00h
    int 16h   
      
    move_snake endp

    I don't know if this will be Your answer. This is just an example. Screen coords translate to video memory offset.

     
       xor ax,ax        ;calculate head position
       mov al,[yPos]
       mov cl,80
       mul cl 
       xor cx,cx
       mov cl,[xPos]   
       add ax,cx    
       mov cx,2
       mul cx
       
       mov cx,[targetInMem]
       cmp cx,ax
       jz game_over
    
    
    

    And Example below

    org     100h
    
    jmp     start
    
    s_size  equ     7       
    
    snake dw s_size dup(0)
    
    tail    dw      ?  
    Head    db      79 
    KeyNumber db      ?
    xPos db 2           ;cursor x position on screen    
    yPos db 2           ;cursor y position on screen    
    targetX  db  13
    targetY  db  3
    targetInMem  dw 01fah 
    
    msg1    db "Use arrows.  $"     
    
    msg2  db "Target reached!$"
    
    msg3  db "!!GAME OVER!!$"
    
              ;;;Macros
              
              SetCharAttrib MACRO char,attr       
                push bx
                push ax
                push dx
                push cx
    
                mov ah,9
                mov al,char
                mov cx,1
                ;mov dl,y
                ;mov dh,x
                mov bh,0 
                mov bl,attr
                int 10h
                
                pop cx
                pop dx
                pop ax
                pop bx
              ENDM 
              
            SetCursor MACRO x,y
            
                push bx
                push ax
                push dx
                push cx
    
                mov ah,02h
                mov dl,x
                mov dh,y
                mov bh, 00h 
                int 10h
    
    
                pop cx
                pop dx
                pop ax
                pop bx
            ENDM          
    
    start:    
       mov ax,0003h
       int 10h
    
        mov ax, 0xB800  ; Video memory segment
        mov es, ax      ; Set ES segment to video memory
    
        es: mov [01fah],'X' ;506
        ; print welcome message:
        mov     dx, offset msg1
        mov     ah, 9 
        int     21h
    
        ; hide text cursor:
        mov     ah, 1
        mov     ch, 2bh
        mov     cl, 0bh
        int     10h           
                
        ;set cursor position            
        SetCursor [xPos],[yPos]          
        
        SetCharAttrib 79,14                  
                                  
        game_loop:
                          
        ; wait for any key:
            call CheckKey
    
            cmp al,27       ;Esc, exit program
            jz stop_game
        
        
      ;SetCursor [xPos]+12,[yPos]     
    
       call BoardAction 
       
       SetCharAttrib 0,0   
       
       SetCursor [xPos],[yPos]          
        
       SetCharAttrib 79,14              
       
     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  
     ;;;;  Translate from screen coords
     ;;;;  to video mem adress  
     
       xor ax,ax        ;calculate head position
       mov al,[yPos]
       mov cl,80
       mul cl 
       xor cx,cx
       mov cl,[xPos]   
       add ax,cx    
       mov cx,2
       mul cx
       
       mov cx,[targetInMem]
       cmp cx,ax
       jz game_over
    
     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  
    
    
    ; === eternal game loop:
        jmp     game_loop
    
    
    stop_game:
    
    ; show cursor back:
    mov     ah, 1
    mov     ch, 0bh
    mov     cl, 0bh
    int     10h
    jmp game_over
    
    
    CheckKey Proc
        
        mov ah,0
        int 16h
              
        cmp al,0
        jz Extended
        jmp Normal
        
        Extended:      
            mov [KeyNumber], ah
             mov al,ah
        jmp NextTurn
        
        Normal:                       
            mov [KeyNumber], al
                                       
        NextTurn:   
        ret
    CheckKey Endp
    
    BoardAction Proc
                                
        cmp al,77      ;right arrow
        jz moveRight                 
        cmp al,75      ;left arrow
        jz moveLeft
        cmp al,72      ;up arrow
        jz moveUp             
        cmp al,80      ;down arrow
        jz moveDown
        cmp al,32      ;Space, place X,O on Board
        jmp BoardEdge
    
        moveRight:
            mov al,[xPos]   
            cmp al,15
            jz BoardEdge
            
            add [xPos],1
            jmp BoardEdge
            
        moveLeft:
            mov al,[xPos]       
            cmp al,2
            jz BoardEdge
            
            sub [xPos],1
            jmp BoardEdge
            
        moveUp:
            mov al,[yPos]   
            cmp al,1
            jz BoardEdge
            
            sub [yPos],1
            jmp BoardEdge
            
        moveDown:
            mov al,[yPos]   
            cmp al,5
            jz BoardEdge
            
            add [yPos],1
            
            BoardEdge:
            
        ret
    BoardAction Endp
    
        
    game_over: 
    
    mov     dx, offset msg2
    mov     ah, 9 
    int     21h
    
    
           mov ax, 4c00h
            int 21h