I'm making the snake game and I ran into 2 problems.
dw 452, 743, 534
and when I run the replacement proc it'll look like: "new number", 452, 743
I tried the following (it didn't work. no matter what direction I move, the stars don't delete themselves):proc replace_stars
mov cx, [st_am] ;the amount of stars, how many loops
mov bx, [st_am]
dec bx
shl bx, 1
replace:
mov di, [stars+bx-2] ;the one before last stars
mov bx, [stars+bx] ;the last stars
mov [bx], di ;in the last one, now the one before it
sub di, 2
sub bx, 2
loop replace ;loop the amount of stars
ret
endp replace_stars
2)I don't know how to do that when I move in any direction and eat an apple, another star and its coordinates will add to the array.
(The first number is the coordinates of the first star)When I move (let's say right), say I have in the DS: dw 2342, 4532, 4653
and after I move it'll look like: (moved right, so +2)2344, 2342, 4532, 4653
MY whole code is:
MODEL small
STACK 100h
DATASEG
; --------------------------
; Your variables here
; --------------------------
saveal db ' ' ;used in line 223-233
dir db 0
app dw 0 ;place of the apple
st_am dw 3
stars dw 0, 0, 0 ;places of the *
CODESEG
proc black
body:
mov [es:si], ax
add si, 2
cmp si, 25*80*2
jnz body
ret
endp black
proc up
mov di, 80*2
cmp si, di
jb not_move_up
cmp si, [app]
jnz move_up
call apple
move_up:
call delete
call replace_stars
;mov di, [stars+2] failed attempt
;mov [stars+4], di
;mov di, [stars]
;mov [stars+2], di
;sub di, 80*2
;mov ah, 156
;mov al, '*'
mov [es:di], ax
sub si, 80*2
mov ah, 156
mov al, '*'
mov [es:si], ax
not_move_up:
ret
endp up
proc down
mov di, (24*80*2)-1
cmp si, di
jg not_move_down
cmp si, [app]
jnz move_down
call apple
move_down:
call delete
call replace_stars
;mov di, [stars+2] failed attempt
;mov [stars+4], di
;mov di, [stars]
;mov [stars+2], di
;add di, 80*2
;mov ah, 156
;mov al, '*'
mov [es:di], ax
add si, 80*2
mov ah, 156
mov al, '*'
mov [es:si], ax
not_move_down:
ret
endp down
proc left
mov dx, 0
mov bx, si
mov ax, si
mov si, 80*2
div si
mov si, bx
cmp dx,0
jz not_move_left
cmp si, [app]
jnz move_left
call apple
move_left:
call delete
call replace_stars
;mov di, [stars+2] failed attempt
;mov [stars+4], di
;mov di, [stars]
;mov [stars+2], di
;mov ah, 156
;mov al, '*'
;mov [es:di], ax
mov [stars], si
sub si, 2
mov ah, 156
mov al, '*'
mov [es:si], ax
not_move_left:
ret
endp left
proc right
mov dx, 0
mov bx, si
mov ax, si
mov si, 80*2
div si
mov si, bx
cmp dx,158
jz not_move_right
cmp si, [app]
jnz move_right
call apple
move_right:
call delete
call replace_stars
;mov di, [stars+2] failed attempt
;mov [stars+4], di
;mov di, [stars]
;mov [stars+2], di
;mov ah, 156
;mov al, '*'
;mov [es:di], ax
mov [stars], si
add si, 2
mov ah, 156
mov al, '*'
mov [es:si], ax
not_move_right:
ret
endp right
proc apple
mov ax, 40h
mov es, ax
mov ax, [es:6ch]
and ax, 0000001111111110b
mov di,ax
mov [app], di
mov ax, 0b800h
mov es, ax
mov al, '@'
mov ah, 154
mov [es:di], ax
ret
endp apple
proc delete
mov bx, offset stars
mov di, [st_am]
dec di
shl di, 1
mov di, [bx+di]
mov ax, 0b800h
mov es, ax
mov al, ' '
mov ah, 0
mov [es:di], ax
;mov di, [stars+2]
;mov [stars+4], di
;mov di, [stars]
;mov [stars+2], di
mov [stars], si
ret
endp delete
proc replace_stars
mov cx, [st_am] ;the amount of stars, how many loops
mov bx, [st_am]
dec bx
shl bx, 1
replace:
mov di, [stars+bx-2] ;the one before last stars
mov bx, [stars+bx] ;the last stars
mov [bx], di ;in the last one, now the one before it
sub di, 2
sub bx, 2
loop replace ;loop the amount of stars
ret
endp replace_stars
proc first_3_dots
mov bx, offset stars
mov si, ((12*80+40)*2)-2
mov al, '*'
mov ah, 156
mov [es:si], ax
mov [bx], si
mov si, (12*80+40)*2
mov al, '*'
mov ah, 156
mov [es:si], ax
mov [bx+2], si
mov si, ((12*80+40)*2)+2
mov al, '*'
mov ah, 156
mov [es:si], ax
mov [bx+4], si
ret
endp first_3_dots
proc delay
mov cx, 0FFFFh
delay1:
mov ax, 300
delay2:
dec ax
jnz delay2
loop delay1
ret
endp delay
proc move_stars_right
mov cx, [st_am]
mov di, offset stars
mov bx, di
move_loop:
mov ax, [di]
add ax, 2
mov [bx], ax
mov ah, 156
mov al, '*'
mov [es:di], ax
add di, 2
add bx, 2
loop move_loop
ret
endp move_stars_right
start:
mov ax, @data
mov ds, ax
; --------------------------
; Your code here
; --------------------------
mov ax, 0b800h
mov es, ax
mov si,0
mov al, ' '
mov ah, 0
call black
call first_3_dots
mov si, ((12*80+40)*2)-2
call apple
wasd:
mov ah, 1h
int 21h
mov [byte ptr saveal], al
cmp [byte ptr saveal], 'w'
jz w
cmp [byte ptr saveal], 'a'
jz a
cmp [byte ptr saveal], 's'
jz s
cmp [byte ptr saveal], 'd'
jz d
cmp [byte ptr saveal], 'q'
jmp exit
w:
call up
jmp wasd
s:
call down
jmp wasd
a:
call left
jmp wasd
d:
call right
jmp wasd
exit:
mov ax, 4c00h
int 21h
END start
dw 452, 743, 534 dw 2342, 4532, 4653
I find it worrying to see these examples of what you think could be in the stars array. The values stored in the stars array represent offset addresses in the video memory at linear address 000B8000h for the 80x25 text screen. Then what is wrong?
(The first number is the coordinates of the first star)
Not really! The first number on the array is the offset address on the screen of the first star. Coordinates would be the mention of column and row, or X and Y.
after I move it'll look like: (moved right, so -2) 2340, 2342, 4532, 4653
Just another example of not truly understanding what moving the snake entails. When you move to the right on the screen, the address (that you keep in SI) gets increased by +2, therefore the expected numbers would start with 2344, 2342, ...
The replace_stars proc is disastrously mixing addresses that refer to the screen with addresses that refer to the stars array that resides in DATASEG
!
And it is doing one iteration too many, because in an array with 3 elements you can do just 2 of those movements.
This is the revised code:
mov cx, [st_am] ; The amount of stars (3 or more)
dec cx ; How many loops
mov bx, cx
shl bx, 1 ; Offset to the last star
replace:
mov ax, [stars+bx-2]
mov [stars+bx], ax
sub bx, 2
loop replace
ret
The better version of this loop does not use the loop
instruction (and so does not clobber the CX register):
mov bx, [st_am] ; The amount of stars (3 or more)
dec bx
shl bx, 1 ; Offset to the last star
replace:
mov ax, [stars+bx-2]
mov [stars+bx], ax
sub bx, 2
jnz replace
ret
I take it that your move_stars_right proc is an attempt to make the snake grow? Forget about it, it's too early! You need to fix the errors first. You didn't even apply corrections about which I spoke in previous answers...
And similar to what I told about the replace_stars proc, this one is also disastrously mixing addresses that refer to the screen with addresses that refer to the stars array that resides in DATASEG
!
When the snake is currently moving to the left, you cannot allow a request to move to the right.
When the snake is currently moving to the right, you cannot allow a request to move to the left.
When the snake is currently moving to the top, you cannot allow a request to move to the bottom.
When the snake is currently moving to the bottom, you cannot allow a request to move to the top.
I had solved this in my previous answer.
[EDIT]
From a comment:
it worked except for something strange. When I go up or down, it leaves behind random characters.
At some point you have decided about a 'failed attempt' and you have turned a number of lines into comments. Sadly, for the up and down procs you forgot to put the instruction mov [es:di], ax
behind such a semicolon. Those are the two lines that produce random characters.
For the up and down procs you further forgot to update the first value in the stars array:
sub si, 80*2
mov [stars], si
and
add si, 80*2
mov [stars], si
And for the left and right procs you did not forget to update the first value in the stars array but it comes too soon (so the value stays the same):
sub si, 2
mov [stars], si
and
add si, 2
mov [stars], si