0
votes

i have a code wherein it moves, it grows, generates food, last problem is that what if the snake bites itself.

;Snake Game without Borders
.model small

.data

row db 0FEh dup (?)
col db 0FEh dup (?)

temp_row db ?
temp_col db ?

;variables for food
rand_food_col db ?
rand_food_row db ?


;delay for snake movement
delaytime db 1

;use this delay time to pseudorandom the col and row for food
delay_food db 3


food db 'F' ,'$'


head db '@' ,'$'
snake_length db 5
snake_loop db ?

color db 0Fh
food_color db 0Fh

input db ?
;variables to display text messages:
game_over db 'GAME OVER';
.stack 100h
.code
;///////////////////////////////////////////////////////////////////////////////////////
;clear registers:
clear_reg proc
xor ax,ax
xor bx,bx
xor cx,cx
xor dx,dx
clear_reg endp
;//////////////////////////////////////////////////////////////////////////////////////////////
;food functions 

random_coor_food proc
;random function for col

mov ah, 00h
int 1ah

mov ax,dx
xor dx,dx
mov cx,20
div cx

mov al,dl
mov rand_food_col,al

;random function for row

mov ah, 00h
int 1ah

mov ax,dx
xor dx,dx
mov cx, 71
div cx

mov al,dl
mov rand_food_row,al

ret
random_coor_food endp


print_food proc
mov dl, rand_food_row
mov dh, rand_food_col
xor bh,bh
mov ah, 02h
int 10h

mov dx, offset food
mov ah, 09h
int 21h
ret
print_food endp

;//////////////////////////////////////////////////////////////////////////////////////////////
lefty proc
    mov dl,col[0]
    cmp dl, 0
    je resetposr

    sn:
    dec dl
    jmp leftyie

    resetposr:
    mov dl, 79


    leftyie:
    mov col[0],dl
    ret 
    lefty endp

righty proc
    mov dl,col[0]
    cmp dl,79
    je resetposl

    zero: 
    inc dl
    jmp rightyie


    resetposl:
    mov dl, 0

    rightyie:
    mov col[0],dl
    ret 
righty endp


upy proc
    mov dh,row[0]
    cmp dh,0
    je resetposd

    upzero:
    dec dh
    jmp uptie

    resetposd:
    mov dh,24


    uptie:
    mov row[0],dh
    ret


upy endp

downy proc
mov dh,row[0]
cmp dh,24
je resetposu

gozero:
inc dh
jmp downty

resetposu:
mov dh, 0

downty:
mov row[0],dh
ret 
downy endp

delay proc
    mov ah, 00
    int 1Ah
    mov bx, dx

jmp_delay:
    int 1Ah
    sub dx, bx
    cmp dl, delaytime
    jl jmp_delay

    ret
delay endp


clear proc near
    mov al, 03h 
    mov ah, 00h
    int 10h

    mov cx, 3200h  ;stop cursor blinking
    mov ah, 01h
    int 10h
    ret
clear endp

;////////////////////////////////////////////////////////////////////////////////
gameover proc
    call clear
    mov dh, 12 ;row
    mov dl, 35 ;column
    xor bh, bh
    mov ah, 02h
    int 10h 

     mov dx, offset game_over
    mov ah, 09h
    int 21h


    mov ax, 4c00h
    int 21h
gameover endp
;this macro will print the whole snake 
; r is for row c is for column char and color: check .data for values
complete_print macro r,c,char,color
    mov dh, r
    mov dl, c
    xor bh, bh
    mov ah, 02h
    int 10h 

    mov al, char
    mov bh, 0
    mov bl, color
    mov cx, 1
    mov ah, 09h
    int 10h 
endm
;function to print the snake body
snake proc

    call delay
    call clear


    mov bl,0
    mov bh,0
    print_snake:

    mov dl,[col+bx]
    mov temp_col,dl

    mov dl,[row+bx]
    mov temp_row,dl

    mov snake_loop,bl

    print_me:
    complete_print temp_row,temp_col,head,color
    inc snake_loop
    mov bl, snake_loop
    mov al, snake_loop
    cmp al, snake_length
    ;continue to print the body of the snake
    jl print_snake


    mov bl, snake_length

    ;transfer the coordinates   
    ;to insert new coordinates

    transfer:
    dec bx
    mov dl ,[col+bx]
    mov [col + bx + 1],dl

    mov dl,[row + bx]
    mov [row+bx+1],dl
    cmp bx,0
    jg transfer



    ret
snake endp

main proc
;//////////////////////////////////////////////////////////////////////
      mov ax, @data
    mov ds, ax
    call clear
    ;initialize starting body snake :)
    mov row[0],12

    mov row[1],12
    mov row[2],12
    mov row[3],12
    mov row[4],12

    mov col[0],40

    mov col[1],39
    mov col[2],38
    mov col[3],37
    mov col[4],36

    print:  
    call snake
    call random_coor_food
    call print_food

;//////////////////////////////////////////////////////////////////////
; moving the snake
    ;initialize the keyboard input:

    mov ah,00h
    int 16h
    mov input, 'd'

    getinput:
    ;to change direction or to keep going
    ; wait for keystroke
    ; if no key is pressed, value of input will be 
    ;last key pressed.
        mov ah, 01h
        int 16h
        jz key

    ;key is pressed, new value of input
        mov ah,00h
        int 16h
        mov input, al

    key: 
    ;UP
    cmp input, 'w'
    je w 
    ;DOWN
    cmp input, 's'
    je s
    ;LEFT
    cmp input, 'a'
    je a 
    ;RIGHT
    cmp input, 'd'
    je d

    jne getinput

    ;make the snake go up
    w:

    call upy
    jmp rak

    ;make the snake go up
    s:

    call downy
    jmp rak

    ;make the snake go left
    a:

    call lefty
    jmp rak

    ;make the snake go right
    d:

    call righty
    jmp rak



    rak:
    ;////// check first if snake hits the body
    ;if hit, then game over
    mov bh,0
    mov ah,08h ;scan
    int 10h
    cmp al, head
    je end_game




    call snake  
    mov cl,row[0]
    cmp cl,rand_food_col
    jne again

    mov cl,col[0]
    cmp cl,rand_food_row
    jne again


    ;compare the coordinates of head to the coordinates of the food


    increase:
    ;if the head row and col is equal to the coordinates of the food. increase snake_length then generate food again.
    inc snake_length
    call random_coor_food

    jmp rak

    again:
    call print_food
    jmp getinput



    end_game:
    call gameover

    mov ax, 4c00h
    int 21h

main endp
end main

look for rak:

there is a portion of the code after rak where it scans the character at the cursor position. it this code when the head of the snake hits the food. it goes game over. I wonder why,

the coordinates in this code is always stored in an array, it is possible to check if the head coordinates is equal to coordinates stored in an array. the limit of the loop should be around the snake_length

tried doing this loop but I failed

mov bl,0
    hit_me_baby:
    mov dl,[col+bx+1]
    cmp col[0],dl
    jne again
    je next
    next:
    mov dl,[row+bx+1]
    cmp row[0],dl
    jne again
    je gameover
    inc bl
    cmp bl,snake_length
    jl hit_me_baby

ANOTHER CODE [edited]


;Snake Game without Borders .model small

.data

row db 0FEh dup (?) col db 0FEh dup (?)

temp_row db ? temp_col db ?

;variables for food rand_food_col db ? rand_food_row db ?

;delay for snake movement delaytime db 1

;use this delay time to pseudorandom the col and row for food delay_food db 3

food db 'O' ,'$'

head db '@' ,'$' body db '#' ,'$' snake_length db 5 snake_loop db ?

color db 0Eh color_body db 02h food_color db 0Fh

input db ? ;variables to display text messages: game_over db 'GAME OVER', '$' start_game db 'SNAKE EATER III', '$' message db 'REVENGE OF THE SNAKE' ,'$' press_key db 'PRESS ANY KEY TO START......', '$' rjbc db 'RJBC GAMES INC.', '$' control db ' CONTROL KEYS: ','$' go_up db'W TO GO UP ','$' go_down db 'S TO GO DOWN ','$' go_left db 'A TO GO LEFT ','$' go_right db 'D TO GO RIGH ','$' go_otherkey db 'OTHER KEYS TO PAUSE ','$' go_exit db 'PRESS Q TO QUIT', '$' .stack 100h .code ;/////////////////////////////////////////////////////////////////////////////////////// ;clear registers: clear_reg proc xor ax,ax xor bx,bx xor cx,cx xor dx,dx clear_reg endp ;////////////////////////////////////////////////////////////////////////////////////////////// ;food functions

random_coor_food proc ;random function for col

mov ah, 00h int 1ah

mov ax,dx xor dx,dx mov cx,20 div cx

mov al,dl mov rand_food_col,al

;random function for row

mov ah, 00h int 1ah

mov ax,dx xor dx,dx mov cx, 71 div cx

mov al,dl mov rand_food_row,al

ret random_coor_food endp

print_food proc mov dl, rand_food_row mov dh, rand_food_col xor bh,bh mov ah, 02h int 10h

mov dx, offset food mov ah, 09h int 21h ret print_food endp

;////////////////////////////////////////////////////////////////////////////////////////////// lefty proc mov dl,col[0] cmp dl, 0 je resetposr

sn:
dec dl
jmp leftyie

resetposr:
mov dl, 79


leftyie:
mov col[0],dl
ret 
lefty endp

righty proc mov dl,col[0] cmp dl,79 je resetposl

zero: 
inc dl
jmp rightyie


resetposl:
mov dl, 0

rightyie:
mov col[0],dl
ret 

righty endp

upy proc mov dh,row[0] cmp dh,0 je resetposd

upzero:
dec dh
jmp uptie

resetposd:
mov dh,24


uptie:
mov row[0],dh
ret

upy endp

downy proc mov dh,row[0] cmp dh,24 je resetposu

gozero: inc dh jmp downty

resetposu: mov dh, 0

downty: mov row[0],dh ret downy endp

delay proc mov ah, 00 int 1Ah mov bx, dx

jmp_delay: int 1Ah sub dx, bx cmp dl, delaytime jl jmp_delay

ret

delay endp

clear proc near mov al, 03h mov ah, 00h int 10h

mov cx, 3200h  ;stop cursor blinking
mov ah, 01h
int 10h
ret

clear endp

;//////////////////////////////////////////////////////////////////////////////// gameover proc call clear mov dh, 12 ;row mov dl, 35 ;column xor bh, bh mov ah, 02h int 10h

     mov dx, offset game_over
    mov ah, 09h
    int 21h


    mov ax, 4c00h
    int 21h

    ret

gameover endp

start_snake_game proc call clear mov dh, 8 ;row mov dl, 31 ;column xor bh, bh mov ah, 02h int 10h

     mov dx, offset start_game
    mov ah, 09h
    int 21h

    mov dh, 9 ;row
    mov dl, 29 ;column
    xor bh, bh
    mov ah, 02h
    int 10h 

     mov dx, offset message
    mov ah, 09h
    int 21h


    mov dh, 22 ;row
    mov dl, 27 ;column
    xor bh, bh
    mov ah, 02h
    int 10h 

         mov dx, offset press_key
    mov ah, 09h
    int 21h


    mov dh, 24 ;row
    mov dl, 31 ;column
    xor bh, bh
    mov ah, 02h
    int 10h 

         mov dx, offset rjbc
    mov ah, 09h
    int 21h


    mov dh, 12 ;row
    mov dl, 31 ;column
    xor bh, bh
    mov ah, 02h
    int 10h 

     mov dx, offset control
    mov ah, 09h
    int 21h

    mov dh, 13;row
    mov dl, 31 ;column
    xor bh, bh
    mov ah, 02h
    int 10h 

     mov dx, offset go_up
    mov ah, 09h
    int 21h

    mov dh, 14;row
    mov dl, 31 ;column
    xor bh, bh
    mov ah, 02h
    int 10h 

     mov dx, offset go_down
    mov ah, 09h
    int 21h


    mov dh, 15;row
    mov dl, 31 ;column
    xor bh, bh
    mov ah, 02h
    int 10h 

     mov dx, offset go_left
    mov ah, 09h
    int 21h

    mov dh, 16;row
    mov dl, 31 ;column
    xor bh, bh
    mov ah, 02h
    int 10h 

     mov dx, offset go_right
    mov ah, 09h
    int 21h

    mov dh, 17;row
    mov dl, 31 ;column
    xor bh, bh
    mov ah, 02h
    int 10h 

     mov dx, offset go_otherkey
    mov ah, 09h
    int 21h

    mov dh, 18;row
    mov dl, 31 ;column
    xor bh, bh
    mov ah, 02h
    int 10h 

     mov dx, offset go_exit
    mov ah, 09h
    int 21h
    ret

start_snake_game endp ;this macro will print the whole snake ; r is for row c is for column char and color: check .data for values complete_print macro r,c,char,color mov dh, r mov dl, c xor bh, bh mov ah, 02h int 10h

mov al, char
mov bh, 0
mov bl, color
mov cx, 1
mov ah, 09h
int 10h 

endm ;function to print the snake body snake proc

call delay
call clear





mov bl,0
mov bh,0
print_snake:

mov dl,[col+bx]
mov temp_col,dl

mov dl,[row+bx]
mov temp_row,dl



mov snake_loop,bl
cmp snake_loop, 0
je printhead
jne printbody

printhead:
complete_print temp_row,temp_col,head,color
jmp finish

printbody:
complete_print temp_row,temp_col,body,color_body

finish:
inc snake_loop
mov bl, snake_loop
mov al, snake_loop
cmp al, snake_length
;continue to print the body of the snake
jl print_snake



mov bl, snake_length

;transfer the coordinates   
;to insert new coordinates

transfer:
dec bx
mov dl ,[col+bx]
mov [col + bx + 1],dl

mov dl,[row + bx]
mov [row+bx+1],dl
cmp bx,0
jg transfer
jmp return_me


return_me:
ret

snake endp

main proc ;////////////////////////////////////////////////////////////////////// mov ax, @data mov ds, ax call start_snake_game ;initialize the keyboard input:

mov ah,00h
int 16h
mov input, 'd'
call clear
;initialize starting body snake :)
mov row[0],12

mov row[1],12
mov row[2],12
mov row[3],12
mov row[4],12

mov col[0],40

mov col[1],39
mov col[2],38
mov col[3],37
mov col[4],36

print:  
call snake
call random_coor_food
call print_food

;////////////////////////////////////////////////////////////////////// ; moving the snake

getinput:
;to change direction or to keep going
; wait for keystroke
; if no key is pressed, value of input will be 
;last key pressed.
    mov ah, 01h
    int 16h
    jz key

;key is pressed, new value of input
    mov ah,00h
    int 16h
    mov input, al

key: 
;UP
cmp input, 'w'
je w 
;DOWN
cmp input, 's'
je s
;LEFT
cmp input, 'a'
je a 
;RIGHT
cmp input, 'd'
je d

cmp input, 'q'
je end_game

jne getinput

;make the snake go up
w:

call upy
jmp rak

;make the snake go up
s:

call downy
jmp rak

;make the snake go left
a:

call lefty
jmp rak

;make the snake go right
d:

call righty
jmp rak



rak:


 comment @
 mov bh,0
mov ah,08h ;scan
int 10h
cmp al, body
je end_game
cmp al, food
je increase
@


call snake  


;compare the coordinates of head to the coordinates of the food
;kinda made a mistake over here. 
;#houston, we got a problem 
mov cl,row[0]
cmp cl,rand_food_col
jne again

mov cl,col[0]
cmp cl,rand_food_row
jne again

;////// check first if snake hits the body ;if hit, then game over comment @ mov bl,0 hit_me_baby: mov dl,[col+bx+1] cmp col[0],dl jne again mov dl,[row+bx+1] cmp row[0],dl jne again je end_game inc bl cmp bl,snake_length jl hit_me_baby

@ increase: ;if the head row and col is equal to the coordinates of the food. increase snake_length then generate food again. inc snake_length call random_coor_food jmp rak again: call print_food jmp getinput end_game: call gameover call clear jmp end_game mov ax, 4c00h int 21h

main endp end main

2
tried doing the loop. it was a mistake :(((Dr.DOOM
You are on the right track : you can get the character at cursor position or you can have an array with the X,Y coordinates of every character on the snakes body. The first one is easier, but you cannot use the snake's characters for anything else. ON THE OTHER HAND, you can just ignore it, I mean, let the snake to move over itself, after all, that's what snakes do in real life.Jose Manuel Abarca Rodríguez
but that is not the snake game right? hahaha.Dr.DOOM
but that is not the snake game right? hahaha. tried doing the array with the coordinates of every character. didnt succeed :( can you help me? i deleted my algo cant remember how i did it. ill try to comment it here if I could write it again. tried using the character at the cursor position doesnt work either dont know why it ends the game immediately.Dr.DOOM
Get the character at cursor position and, if it's an asterisk (or whatever character you are using for the snake's body), ignore it. This way the snakes will not bite itself.Jose Manuel Abarca Rodríguez

2 Answers

0
votes

Here is the last edited version of your code, I made two little changes : first, below label rak:, I added another compare with food that jumps to increase:, second, below label increase:, I commented the jump to rak, here it is:

;Snake Game without Borders
.model small

.data

row db 0FEh dup (?)
col db 0FEh dup (?)

temp_row db ?
temp_col db ?

;variables for food
rand_food_col db ?
rand_food_row db ?


;delay for snake movement
delaytime db 1

;use this delay time to pseudorandom the col and row for food
delay_food db 3


food db 'F' ,'$'


head db '@' ,'$'
snake_length db 5
snake_loop db ?

color db 0Fh
food_color db 0Fh

input db ?
;variables to display text messages:
game_over db 'GAME OVER';
.stack 100h
.code
;///////////////////////////////////////////////////////////////////////////////////////
;clear registers:
clear_reg proc
xor ax,ax
xor bx,bx
xor cx,cx
xor dx,dx
clear_reg endp
;//////////////////////////////////////////////////////////////////////////////////////////////
;food functions 

random_coor_food proc
;random function for col

mov ah, 00h
int 1ah

mov ax,dx
xor dx,dx
mov cx,20
div cx

mov al,dl
mov rand_food_col,al

;random function for row

mov ah, 00h
int 1ah

mov ax,dx
xor dx,dx
mov cx, 71
div cx

mov al,dl
mov rand_food_row,al

ret
random_coor_food endp


print_food proc
mov dl, rand_food_row
mov dh, rand_food_col
xor bh,bh
mov ah, 02h
int 10h

mov dx, offset food
mov ah, 09h
int 21h
ret
print_food endp

;//////////////////////////////////////////////////////////////////////////////////////////////
lefty proc
    mov dl,col[0]
    cmp dl, 0
    je resetposr

    sn:
    dec dl
    jmp leftyie

    resetposr:
    mov dl, 79


    leftyie:
    mov col[0],dl
    ret 
    lefty endp

righty proc
    mov dl,col[0]
    cmp dl,79
    je resetposl

    zero: 
    inc dl
    jmp rightyie


    resetposl:
    mov dl, 0

    rightyie:
    mov col[0],dl
    ret 
righty endp


upy proc
    mov dh,row[0]
    cmp dh,0
    je resetposd

    upzero:
    dec dh
    jmp uptie

    resetposd:
    mov dh,24


    uptie:
    mov row[0],dh
    ret


upy endp

downy proc
mov dh,row[0]
cmp dh,24
je resetposu

gozero:
inc dh
jmp downty

resetposu:
mov dh, 0

downty:
mov row[0],dh
ret 
downy endp

delay proc
    mov ah, 00
    int 1Ah
    mov bx, dx

jmp_delay:
    int 1Ah
    sub dx, bx
    cmp dl, delaytime
    jl jmp_delay

    ret
delay endp


clear proc near
    mov al, 03h 
    mov ah, 00h
    int 10h

    mov cx, 3200h  ;stop cursor blinking
    mov ah, 01h
    int 10h
    ret
clear endp

;////////////////////////////////////////////////////////////////////////////////
gameover proc
    call clear
    mov dh, 12 ;row
    mov dl, 35 ;column
    xor bh, bh
    mov ah, 02h
    int 10h 

     mov dx, offset game_over
    mov ah, 09h
    int 21h


    mov ax, 4c00h
    int 21h
gameover endp
;this macro will print the whole snake 
; r is for row c is for column char and color: check .data for values
complete_print macro r,c,char,color
    mov dh, r
    mov dl, c
    xor bh, bh
    mov ah, 02h
    int 10h 

    mov al, char
    mov bh, 0
    mov bl, color
    mov cx, 1
    mov ah, 09h
    int 10h 
endm
;function to print the snake body
snake proc

    call delay
    call clear


    mov bl,0
    mov bh,0
    print_snake:

    mov dl,[col+bx]
    mov temp_col,dl

    mov dl,[row+bx]
    mov temp_row,dl

    mov snake_loop,bl

    print_me:
    complete_print temp_row,temp_col,head,color
    inc snake_loop
    mov bl, snake_loop
    mov al, snake_loop
    cmp al, snake_length
    ;continue to print the body of the snake
    jl print_snake


    mov bl, snake_length

    ;transfer the coordinates   
    ;to insert new coordinates

    transfer:
    dec bx
    mov dl ,[col+bx]
    mov [col + bx + 1],dl

    mov dl,[row + bx]
    mov [row+bx+1],dl
    cmp bx,0
    jg transfer



    ret
snake endp

main proc
;//////////////////////////////////////////////////////////////////////
      mov ax, @data
    mov ds, ax
    call clear
    ;initialize starting body snake :)
    mov row[0],12

    mov row[1],12
    mov row[2],12
    mov row[3],12
    mov row[4],12

    mov col[0],40

    mov col[1],39
    mov col[2],38
    mov col[3],37
    mov col[4],36

    print:  
    call snake
    call random_coor_food
    call print_food

;//////////////////////////////////////////////////////////////////////
; moving the snake
    ;initialize the keyboard input:

    mov ah,00h
    int 16h
    mov input, 'd'

    getinput:
    ;to change direction or to keep going
    ; wait for keystroke
    ; if no key is pressed, value of input will be 
    ;last key pressed.
        mov ah, 01h
        int 16h
        jz key

    ;key is pressed, new value of input
        mov ah,00h
        int 16h
        mov input, al

    key: 
    ;UP
    cmp input, 'w'
    je w 
    ;DOWN
    cmp input, 's'
    je s
    ;LEFT
    cmp input, 'a'
    je a 
    ;RIGHT
    cmp input, 'd'
    je d

    jne getinput

    ;make the snake go up
    w:

    call upy
    jmp rak

    ;make the snake go up
    s:

    call downy
    jmp rak

    ;make the snake go left
    a:

    call lefty
    jmp rak

    ;make the snake go right
    d:

    call righty
    jmp rak



    rak:
    ;////// check first if snake hits the body
    ;if hit, then game over
    mov bh,0
    mov ah,08h ;scan
    int 10h
    cmp al, head
    je end_game
    cmp al, food
    je increase




    call snake  
    mov cl,row[0]
    cmp cl,rand_food_col
    jne again

    mov cl,col[0]
    cmp cl,rand_food_row
    jne again


    ;compare the coordinates of head to the coordinates of the food


    increase:       
    ;if the head row and col is equal to the coordinates of the food. increase snake_length then generate food again.
    inc snake_length
    call random_coor_food

;    jmp rak

    again:
    call print_food
    jmp getinput



    end_game:
    call gameover

    mov ax, 4c00h
    int 21h

main endp
end main

Explanation : in increase:, when it jumps back to rak, the char at cursor position is '@', so, what we have to do is NOT jump to rak but to getinput.

-1
votes

here is the code, go try it.


;Snake Game without Borders
.model small

.data

row db 0FEh dup (?)
col db 0FEh dup (?)

temp_row db ?
temp_col db ?

;variables for food
rand_food_col db ?
rand_food_row db ?


;delay for snake movement
delaytime db 1

;use this delay time to pseudorandom the col and row for food
delay_food db 3


food db 'O' ,'$'


head db '@' ,'$'
body db '#' ,'$'
snake_length db 5
snake_loop db ?

color db 0Eh
color_body db 02h
food_color db 0Fh

input db ?
;variables to display text messages:
game_over db 'GAME OVER', '$'
start_game db 'SNAKE EATER III', '$'
message db 'REVENGE OF THE SNAKE' ,'$'
press_cont db 'PRESS ANY KEY TO VIEW CONTROLS', '$'
press_key db 'PRESS ANY KEY TO START......', '$'
rjbc db 'RJBC GAMES INC.', '$'
control db 'CONTROL KEYS: ','$'
go_up db'W TO GO UP   ','$'
go_down db 'S TO GO DOWN ','$'
go_left db 'A TO GO LEFT ','$'
go_right db 'D TO GO RIGHT  ','$'
go_otherkey db 'OTHER KEYS TO PAUSE   ','$'
go_exit db 'PRESS Q TO QUIT', '$'
go_warning db 'GOOD LUCK, SOLID SNAKE IS EXTREMELY FAST', '$'

.stack 100h
.code
;///////////////////////////////////////////////////////////////////////////////////////
;clear registers:
clear_reg proc
xor ax,ax
xor bx,bx
xor cx,cx
xor dx,dx
clear_reg endp
;//////////////////////////////////////////////////////////////////////////////////////////////
;food functions 

random_coor_food proc
;random function for col

mov ah, 00h
int 1ah

mov ax,dx
xor dx,dx
mov cx,20
div cx

mov al,dl
mov rand_food_col,al

;random function for row

mov ah, 00h
int 1ah

mov ax,dx
xor dx,dx
mov cx, 71
div cx

mov al,dl
mov rand_food_row,al

ret
random_coor_food endp


print_food proc
mov dl, rand_food_row
mov dh, rand_food_col
xor bh,bh
mov ah, 02h
int 10h

mov dx, offset food
mov ah, 09h
int 21h
ret
print_food endp

;//////////////////////////////////////////////////////////////////////////////////////////////
lefty proc
    mov dl,col[0]
    cmp dl, 0
    je resetposr

    sn:
    dec dl
    jmp leftyie

    resetposr:
    mov dl, 79


    leftyie:
    mov col[0],dl
    ret 
    lefty endp

righty proc
    mov dl,col[0]
    cmp dl,79
    je resetposl

    zero: 
    inc dl
    jmp rightyie


    resetposl:
    mov dl, 0

    rightyie:
    mov col[0],dl
    ret 
righty endp


upy proc
    mov dh,row[0]
    cmp dh,0
    je resetposd

    upzero:
    dec dh
    jmp uptie

    resetposd:
    mov dh,24


    uptie:
    mov row[0],dh
    ret


upy endp

downy proc
mov dh,row[0]
cmp dh,24
je resetposu

gozero:
inc dh
jmp downty

resetposu:
mov dh, 0

downty:
mov row[0],dh
ret 
downy endp

delay proc
    mov ah, 00
    int 1Ah
    mov bx, dx

jmp_delay:
    int 1Ah
    sub dx, bx
    cmp dl, delaytime
    jl jmp_delay

    ret
delay endp


clear proc near
    mov al, 03h 
    mov ah, 00h
    int 10h

    mov cx, 3200h  ;stop cursor blinking
    mov ah, 01h
    int 10h
    ret
clear endp

;////////////////////////////////////////////////////////////////////////////////
gameover proc
        call clear
        mov dh, 12 ;row
        mov dl, 35 ;column
        xor bh, bh
        mov ah, 02h
        int 10h 

         mov dx, offset game_over
        mov ah, 09h
        int 21h


        mov ax, 4c00h
        int 21h

        ret
gameover endp



start_snake_game proc
call clear
        mov dh, 10 ;row
        mov dl, 31 ;column
        xor bh, bh
        mov ah, 02h
        int 10h 

         mov dx, offset start_game
        mov ah, 09h
        int 21h

        mov dh, 11 ;row
        mov dl, 29 ;column
        xor bh, bh
        mov ah, 02h
        int 10h 

         mov dx, offset message
        mov ah, 09h
        int 21h

            mov dh, 20 ;row
        mov dl, 26 ;column
        xor bh, bh
        mov ah, 02h
        int 10h 

         mov dx, offset press_cont
        mov ah, 09h
        int 21h


        mov dh, 24 ;row
        mov dl, 31 ;column
        xor bh, bh
        mov ah, 02h
        int 10h 

             mov dx, offset rjbc
        mov ah, 09h
        int 21h
        ret
start_snake_game endp


control_view proc
call clear
        mov dh, 10 ;row
        mov dl, 31 ;column
        xor bh, bh
        mov ah, 02h
        int 10h 

         mov dx, offset control
        mov ah, 09h
        int 21h

        mov dh, 11;row
        mov dl, 31 ;column
        xor bh, bh
        mov ah, 02h
        int 10h 

         mov dx, offset go_up
        mov ah, 09h
        int 21h

        mov dh, 12;row
        mov dl, 31 ;column
        xor bh, bh
        mov ah, 02h
        int 10h 

         mov dx, offset go_down
        mov ah, 09h
        int 21h


        mov dh, 13;row
        mov dl, 31 ;column
        xor bh, bh
        mov ah, 02h
        int 10h 

         mov dx, offset go_left
        mov ah, 09h
        int 21h

        mov dh, 14;row
        mov dl, 31 ;column
        xor bh, bh
        mov ah, 02h
        int 10h 

         mov dx, offset go_right
        mov ah, 09h
        int 21h

        mov dh, 15;row
        mov dl, 31 ;column
        xor bh, bh
        mov ah, 02h
        int 10h 

         mov dx, offset go_otherkey
        mov ah, 09h
        int 21h

        mov dh, 16;row
        mov dl, 31 ;column
        xor bh, bh
        mov ah, 02h
        int 10h 

         mov dx, offset go_exit
        mov ah, 09h
        int 21h


        mov dh, 19 ;row
        mov dl, 20 ;column
        xor bh, bh
        mov ah, 02h
        int 10h 

         mov dx, offset go_warning
        mov ah, 09h
        int 21h

        mov dh, 21 ;row
        mov dl, 25 ;column
        xor bh, bh
        mov ah, 02h
        int 10h 

         mov dx, offset press_key
        mov ah, 09h
        int 21h



        ret
control_view endp
;this macro will print the whole snake 
; r is for row c is for column char and color: check .data for values
complete_print macro r,c,char,color
    mov dh, r
    mov dl, c
    xor bh, bh
    mov ah, 02h
    int 10h 

    mov al, char
    mov bh, 0
    mov bl, color
    mov cx, 1
    mov ah, 09h
    int 10h 
endm
;function to print the snake body
snake proc

    call delay
    call clear





    mov bl,0
    mov bh,0
    print_snake:

    mov dl,[col+bx]
    mov temp_col,dl

    mov dl,[row+bx]
    mov temp_row,dl



    mov snake_loop,bl
    cmp snake_loop, 0
    je printhead
    jne printbody

    printhead:
    complete_print temp_row,temp_col,head,color
    jmp finish

    printbody:
    complete_print temp_row,temp_col,body,color_body

    finish:
    inc snake_loop
    mov bl, snake_loop
    mov al, snake_loop
    cmp al, snake_length
    ;continue to print the body of the snake
    jl print_snake



    mov bl, snake_length

    ;transfer the coordinates   
    ;to insert new coordinates

    transfer:
    dec bx
    mov dl ,[col+bx]
    mov [col + bx + 1],dl

    mov dl,[row + bx]
    mov [row+bx+1],dl
    cmp bx,0
    jg transfer
    jmp return_me


    return_me:
    ret
snake endp

main proc
;//////////////////////////////////////////////////////////////////////
      mov ax, @data
    mov ds, ax
    call start_snake_game
    mov ah,00h
    int 16h
    call control_view
    ;initialize the keyboard input:

    mov ah,00h
    int 16h
    mov input, 'd'
    call clear
    ;initialize starting body snake :)
    mov row[0],12

    mov row[1],12
    mov row[2],12
    mov row[3],12
    mov row[4],12

    mov col[0],40

    mov col[1],39
    mov col[2],38
    mov col[3],37
    mov col[4],36

    print:  
    call snake
    call random_coor_food
    call print_food

;//////////////////////////////////////////////////////////////////////
; moving the snake


    getinput:
    ;to change direction or to keep going
    ; wait for keystroke
    ; if no key is pressed, value of input will be 
    ;last key pressed.
        mov ah, 01h
        int 16h
        jz key

    ;key is pressed, new value of input
        mov ah,00h
        int 16h
        mov input, al

    key: 
    ;UP
    cmp input, 'w'
    je w 
    ;DOWN
    cmp input, 's'
    je s
    ;LEFT
    cmp input, 'a'
    je a 
    ;RIGHT
    cmp input, 'd'
    je d

    cmp input, 'q'
    je end_game

    jne getinput

    ;make the snake go up
    w:

    call upy
    jmp rak

    ;make the snake go up
    s:

    call downy
    jmp rak

    ;make the snake go left
    a:

    call lefty
    jmp rak

    ;make the snake go right
    d:

    call righty
    jmp rak



    rak:

     ;////// scan
     ; current position has a character 
     ;if it has, jump to end_game

     mov bh,0
    mov ah,08h ;scan
    int 10h
        cmp al, body
    je end_game





    proceed:
    call snake  


    ;compare the coordinates of head to the coordinates of the food
    ;kinda made a mistake over here. 
    ;#houston, we got a problem 
        mov cl,row[0]
    cmp cl,rand_food_col
    jne again

    mov cl,col[0]
    cmp cl,rand_food_row
    jne again

;////// check first if snake hits the body
    ;if hit, then game over
    comment @
    mov bl,0
    hit_me_baby:
    mov dl,[col+bx+1]
    cmp col[0],dl
    jne again
    mov dl,[row+bx+1]
    cmp row[0],dl
    jne again
    je end_game
    inc bl
    cmp bl,snake_length
    jl hit_me_baby

    @


    increase:
    ;if the head row and col is equal to the coordinates of the food. increase snake_length then generate food again.
    inc snake_length
    call random_coor_food



    again:
    call print_food
    ;set cursor position at head
    mov dh, row[0]
    mov dl, col[0]
    xor bh,bh
    mov ah,02h
    int 10h
    jmp getinput

    end_game:
    call clear
    call gameover



    mov ax, 4c00h
    int 21h

main endp
end main

btw, if you press opposite directions the game ends :) say your last key was d then you press a, it will end the game :)