; Control the snake using arrow keys. ; ; Any other keys stop the snake. ; ; Press Esc to exit. name "snake" org 100h ; jump over data section: jmp start ; ------ data section ------ s_size equ 7 ; the snake coordinates ; (from head to tail) ; low byte is left, high byte ; is top - [top, left] snake dw s_size dup(0) tail dw ? ; direction constants ; (bios key codes): left equ 4bh right equ 4dh up equ 48h down equ 50h ; current snake direction: cur_dir db right wait_time dw 0 ; welcome message msg db "==== How To Play ====", 0dh,0ah db "Control the snake using arrow keys", 0dh,0ah db "Any other keys stop the snake.", 0dh,0ah, 0ah db "Press Esc to exit.", 0dh,0ah db "====================", 0dh,0ah, 0ah db "Press any Key to start!$" ; ------ code section ------ start: ; print welcome message: mov dx, offset msg mov ah, 9 int 21h ; wait for any key: mov ah, 00h int 16h ; hide text cursor: mov ah, 1 mov ch, 2bh mov cl, 0bh int 10h game_loop: ; === select first video page mov al, 0 ; page number. mov ah, 05h int 10h ; === show new head: mov dx, snake[0] ; set cursor at dl,dh mov ah, 02h int 10h ; print '*' at the location: mov al, '*' mov ah, 09h mov bl, 0eh ; attribute. mov cx, 1 ; single char. 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 location: mov al, ' ' mov ah, 09h mov bl, 0eh ; attribute. mov cx, 1 ; single char. 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 ; ------ functions section ------ ; this procedure creates the ; animation by moving all snake ; body parts one step to tail, ; the old tail goes away: ; [last part (tail)]-> goes away ; [part i] -> [part i+1] ; .... 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 mov b.snake[0], al ; return to right. jmp stop_move move_right: mov al, b.snake[0] inc al mov b.snake[0], al cmp al, es:[4ah] ; col number. jb stop_move mov b.snake[0], 0 ; 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. mov b.snake[1], al ; 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 mov b.snake[1], 0 ; return to top. jmp stop_move stop_move: ret move_snake endp