Текст программы
bufaddr equ 0b800h ;адрес текстовой видеопамяти
space equ 0000000000100000b ;пробел на черным фоне
sprt equ 0000111111000100b ;белый знак '-' на черным фоне
lfhr equ 0000111110110010b ;живой заяц
ddhr equ 0000110010110010b ;мёртвый заяц
clwf equ 0000100110110010b ;волк
codesg segment para 'code'
assume ss:codesg,ds:codesg,cs:codesg
org 100h
begin: jmp main
;--------------- объявление переменных ----------------------------
hare dw ? ;координаты зайца
wolf dw ? ;координаты волка
step db ? ;флаг, указывает, что будет сделан ход
gmover db ? ;флаг конца игры
time dw ? ;хранит время
;--------------- управляющая функция ----------------------------
main proc near
tostart:
call init
q0:
call info ;вывод времени
call getchar ;проверим нажатия клавиш
call prepare ;обработка нажатой клавиши
call wolfst ;ход волка
call harest ;ход зайца
call extest
cmp [gmover],1
je toexit
jmp q0
toexit: ;ожидаем нажатия 1-го символа
mov ah,1
int 21h
ret
main endp
;--------------- инициализация ------------------------------------
init proc
push bufaddr
pop es ;поместим в es адрес текстового видеобуфера
mov ah,2 ;поместим курсор
mov dh,25 ;на 25 строку
int 10h ;т.е. спрячем его
call clrscr ;очистим экран
call prtln ;проводим разделительную линию
mov [hare],0b13h ;начальные координаты зайца
mov [wolf],0b3bh ;начальные координаты волка
call drlfhr ;нарисовать зайца
call drwolf ;нарисовать волка
mov [gmover],0 ;не конец игры
mov ah,0
int 1ah ;получим текущее время
mov [time],dx ;сохраним его
ret
init endp
;------------------- очистка экрана -------------------------------
clrscr proc
mov cx,2000 ;80 * 25 = 2000
mov si,0
mov ax,space ;очищаем пробелами
a0:
mov es:[si],ax ;поместим в видеобуфер
add si,2 ;к следующему символу
loop a0
ret
clrscr endp
;-------------------- разделительная линия ---------------------------
prtln proc
mov cx,80 ;линия во всю строку
mov si,3680 ;80 * 23 * 2 = 3680
mov ax,sprt
b0:
mov es:[si],ax ;поместим в видеобуфер
add si,2 ;к следующему символу
loop b0
ret
prtln endp
;-------------------- рисует символ ------------------------------
draw proc ;координаты передаются в bx
;символ с атрибутами передаётся в ax
call topos ;рассчитать положение в видеобуфере
mov es:[bx],ax ;нарисовать символ
ret
draw endp
;-------------- рисует живого зайца ------------------------------
drlfhr proc
mov ax,lfhr ;вид живого зайца
mov bx,[hare] ;получить координаты
call draw ;нарисовать
ret
drlfhr endp
;---------------------- рисует мёртвого зайца ----------------------
drddhr proc
mov ax,ddhr ;вид мёртвого зайца
mov bx,[hare] ;получить координаты
call draw ;нарисовать
ret
drddhr endp
;--------------------- рисует волка --------------------------------
drwolf proc
mov ax,clwf ;вид волка
mov bx,[wolf] ;получить координаты
call draw ;нарисовать
ret
drwolf endp
;------------------------ очищает позицию -------------------------
clear proc ;координаты передаются в bx
push ax
mov ax,space ;пробел
call draw ;нарисовать
pop ax
ret
clear endp
;------------------ очищает позицию зайца ------------------------
clhare proc
mov bx,[hare]
call clear ;очистить
ret
clhare endp
;-------------------- очищает позицию волка ---------------------
clwolf proc
mov bx,[wolf]
call clear ;очистить
ret
clwolf endp
;----- перевод координат в положение в текстовом видеобуфере ---------
topos proc ;координаты передаются в bx, bl - x, bh - y
push ax
mov al,80
mul bh ;80 * y, результат умножения в ax
mov bh,0 ;теперь в bx содержится значение x
add bx,ax ;80 * y + x
shl bx,1 ;(80 * y + x) * 2
pop ax
ret ;положение в видеобуфере возвращается в bx
topos endp
;-------------- получение кода нажатой клавиши -------------------
getchar proc
mov ah,1
int 16h ;проверим, есть ли в буфере символ
jz c0 ;если нет, то уйдём
mov ah,0
int 16h ;если есть, то считаем его
c0:
ret ;код нажатой клавиши сохраняется в ax
getchar endp
;-------------- обработка нажатой клавиши --------------------
prepare proc
mov [step],0 ;сбрасываем флаг
cmp ax,4800h ;клавиша up?
jne testdn ;если нет, перейти к проверке down
mov bx,0ff00h ;16h = 22
jmp tostep
testdn:
cmp ax,5000h ;клавиша down?
jne testlf ;если нет, перейти к проверке left
mov bx,0100h ;18h = 24
jmp tostep
testlf:
cmp ax,4b00h ;клавиша left?
jne testrt ;если нет, перейти к проверке right
mov bx,00ffh ;4fh = 79
jmp tostep
testrt:
cmp ax,4d00h ;клавиша right?
jne tonoth ;если нет, эта клавиша не повлияет на работу программы
mov bx,0001h ;51h = 81
tostep:
mov [step],1 ;если была нажата клавиша управления, устанавливаем флаг
tonoth:
ret
prepare endp
;---------------------- ход волка -----------------------------
wolfst proc
cmp [step],1
jne d0
mov ax,[wolf]
add al,bl
cmp al,0ffh ;если al = -1
je d0
cmp al,50h ;если al = 80
je d0
add ah,bh
cmp ah,0ffh ;если ah = -1
je d0
cmp ah,17h ;если ah = 23
je d0
call clwolf
mov [wolf],ax
call drwolf
jmp d1
d0:
mov [step],0
d1:
ret
wolfst endp
;------------------ ход зайца -----------------------------------
harest proc
cmp [step],1
jne g4
mov ax,[hare]
mov cx,ax
call getdist ;найдём текущее расстояние между З и В
mov si,ax ;сохраним его в si
mov ax,[hare]
add al,0ffh ;если пойдём влево
mov dx,ax ;сохраним полученные координаты
cmp al,0ffh ;если al = -1
je g0
call getdist ;найдём предполагаемое расстояние
cmp ax,si
jbe g0 ;если получилось ещё меньше, проверять дальше
mov si,ax ;а если нет, запомнить расстояние
mov cx,dx ; и координаты
g0:
mov ax,[hare]
add al,01h ;если пойдём вправо
mov dx,ax ;сохраним полученные координаты
cmp al,50h ;если al = 80
je g1
call getdist ;найдём предполагаемое расстояние
cmp ax,si
jbe g1 ;если получилось ещё меньше, проверять дальше
mov si,ax ;а если нет, запомнить расстояние
mov cx,dx ; и координаты
g1:
mov ax,[hare]
add ah,0ffh ;если пойдём вверх
mov dx,ax ;сохраним полученные координаты
cmp ah,0ffh ;если ah = -1
je g2
call getdist ;найдём предполагаемое расстояние
cmp ax,si
jbe g2 ;если получилось еще меньше, проверять дальше
mov si,ax ;а если нет, запомнить расстояние
mov cx,dx ; и координаты
g2:
mov ax,[hare]
add ah,01h ;если пойдём вниз
mov dx,ax ;сохраним полученные координаты
cmp ah,17h ;если ah = 23
je g3
call getdist ;найдём предполагаемое расстояние
cmp ax,si
jbe g3 ;если получилось ещё меньше, проверять дальше
mov si,ax ;а если нет, запомнить расстояние
mov cx,dx ; и координаты
g3:
call clhare ;стереть зайца
mov [hare],cx ;сохранить новые координаты
call drlfhr ;по ним нарисовать нового зайца
g4:
mov [step],0
ret
harest endp
;-------- определение расстояния между зайцем и волком -------
getdist proc ;в ax передаётся предполагаемая координата зайца
mov bx,[wolf] ;получение координат волка
;найдём расстояние между волком и зайцем по x
cmp al,bl
ja f0 ;если al > bl
xchg al,bl
f0:
sub al,bl
;найдём расстояние между волком и зайцем по y
cmp ah,bh
ja f1 ;если ah > bh
xchg ah,bh
f1:
sub ah,bh ;рассчитаем количество шагов, между зайцем и волком
add al,ah
mov ah,0
dec ax
ret ;расстояние возвращается в ax
getdist endp
;-------------- вывод игрового времени ------------------
info proc
mov ah,0
int 1ah ;получим текущее время
sub dx,[time] ;найдём разницу
mov ax,dx ;напечатаем её
mov dx,0
mov bx,18
div bx
mov si,10 ;делим на 10
mov cx,0 ;счёт чисел помещённых в стек
h0:
mov dx,0
div si ;частное в ax, остаток в dx
push dx ;поместить 1 цифру в стек
inc cx
cmp ax,0 ;сравнение ax с 0
jne h0
mov bl,0
mov bh,24
call topos
h1:
pop dx ;взять цифры в обратном порядке
add dl,'0'
mov dh,00001111b ;белый цвет на чёрном фоне
add bx,2
mov es:[bx],dx
loop h1
ret
info endp
;------------ проверка на конец игры ------------------------
extest proc
mov ax,[wolf]
cmp ax,[hare]
jne x0
call drddhr
mov [gmover],1
x0:
ret ;расстояние возвращается в ax
extest endp
codesg ends
end begin