'What does it take for pacman to function correctly?

I'm experiencing 2 problems:

  1. the "you win" screen does not show up
  2. the pacman has a trail.
    IDEAL
p286
MODEL small
STACK 100h

DATASEG
pacman db "   _ __   __ _  ___ _ __ ___   __ _ _ __   ", 13, 10  
        db "| '_ \ / _` |/ __| '_ ` _ \ / _` | '_ \  ", 13, 10 
        db "| |_) | (_| | (__| | | | | | (_| | | | | ", 13, 10 
        db "| .__/ \__,_|\___|_| |_| |_|\__,_|_| |_| ", 13, 10 
        db "|_|                                      ", 13, 10,'$'
how_to_play db "# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #",13,10
            db "# how to play:                                                              #",13,10
            db "# The pacman is to eat the Apple                                            #",13,10
            db "# Use arrows to you'r move the pacman                                       #",13,10
            db "#                                                                           #",13,10
            db "# the game over when the pacman ate Apple                                   #",13,10
            db "#                                                                           #",13,10
            db "# good luck!                                                                #",13,10
            db "# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #",13,10
            db " press any key to start...$" 
you_win db"                       _          ", 13, 10 
        db" _   _  __   _   _  __      _(_)_ __     ", 13, 10 
        db"| | | |/ _ \| | | | \ \ /\ / / | '_ \    ", 13, 10 
        db"| |_| | (_) | |_| |  \ V  V /| | | | |   ", 13, 10  
        db" \__, |\___/ \__,_|   \_/\_/ |_|_| |_|   ", 13, 10 
        db" |___/                                  ", 13, 10, '$'
                        
AppleX dw 150
AppleY dw 20
    img db 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
        db 00,00,00,00,00,00,14,14,14,14,14,00,00,00,00,00
        db 00,00,00,00,12,14,14,14,14,14,14,14,14,00,00,00
        db 00,00,00,12,14,12,14,14,14,14,14,14,14,14,00,00
        db 00,00,12,14,14,14,14,14,14,14,14,15,15,00,14,00
        db 00,00,14,12,14,14,14,14,14,14,14,15,15,00,14,00
        db 00,12,12,14,14,14,14,14,14,14,14,14,14,14,14,00
        db 00,12,14,12,14,14,14,14,14,14,14,14,14,14,14,00
        db 00,12,12,14,12,14,14,14,14,14,14,14,14,14,00,00
        db 00,12,14,12,14,14,14,14,14,14,14,14,00,00,00,00
        db 00,12,12,14,12,14,14,14,14,14,00,00,00,00,00,00
        db 00,00,12,12,14,12,14,14,14,14,14,14,00,00,00,00
        db 00,00,12,14,12,14,12,14,14,14,14,14,14,14,00,00
        db 00,00,00,12,14,12,14,12,14,12,14,12,14,12,00,00
        db 00,00,00,00,12,12,12,14,12,14,12,14,12,00,00,00
        db 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
       img2 db 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
            db 00,00,00,00,00,00,14,14,14,14,14,00,00,00,00,00
            db 00,00,00,00,12,14,14,14,14,14,14,14,14,00,00,00
            db 00,00,00,12,14,12,14,14,14,14,14,14,14,14,00,00
            db 00,00,12,14,14,14,14,14,14,14,14,15,15,00,14,00
            db 00,00,14,12,14,14,14,14,14,14,14,15,15,00,14,00
            db 00,12,12,14,14,14,14,14,14,14,14,14,14,14,14,14
            db 00,12,14,12,14,14,14,14,14,14,14,14,14,14,14,14
            db 00,12,12,14,12,14,14,14,14,14,14,14,14,14,14,14
            db 00,12,14,12,14,14,14,14,14,14,14,14,14,14,14,14
            db 00,12,12,14,12,14,14,14,14,14,14,14,14,14,14,14
            db 00,00,12,12,14,12,14,14,14,14,14,14,14,14,14,00
            db 00,00,12,14,12,14,12,14,14,14,14,14,14,14,14,00
            db 00,00,00,12,14,12,14,12,14,12,14,12,14,12,00,00
            db 00,00,00,00,12,12,12,14,12,14,12,14,12,00,00,00
            db 00,00,00,00,00,00,12,12,12,12,12,00,00,00,00,00  
      black db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
            db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
            db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
            db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
            db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
            db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
            db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
            db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
            db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
            db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
            db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
            db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
            db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
            db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
            db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
            db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
    apple db 7,2,2,2,6,6,6,2,7,7
          db 7,2,2,7,6,6,7,2,2,7
          db 2,2,2,7,6,6,7,2,2,7
          db 7,7,7,4,4,4,4,7,7,7
          db 7,4,4,4,4,4,4,4,4,7
          db 4,4,4,4,4,4,4,4,4,4
          db 4,4,4,4,4,4,4,4,4,4
          db 4,4,4,4,4,4,4,4,4,4
          db 4,4,4,4,4,4,4,4,4,4
          db 4,4,4,4,4,4,4,4,4,4
          db 4,4,4,4,4,4,4,4,4,4
          db 7,4,4,4,4,4,4,4,4,7
          db 7,7,7,4,4,4,4,7,7,7
    imgA  dw ?
    x     dw 16
    y     dw 0
    color db 2
; --------------------------
CODESEG
proc PutPixel
    pusha
    mov bh,0h
    mov cx,[x]
    mov dx,[y]
    mov al,[color]
    mov ah,0ch
    int 10h
    popa
ret
endp PutPixel

proc Waiting
    pusha
    L3:
    push cx
        mov cx, 400
        L4:
            nop
            loop L4
        pop cx
    loop L3
    popa
    ret
endp Waiting
proc Instruction
    pusha
    mov ah, 09
    mov dx, offset how_to_play
    int 21h
    ; Wait for key press
    mov ah,0bh
    int 21h
    popa
    ret
endp Instruction
proc PrintPacman
    pusha
    mov ah, 09
    mov dx, offset pacman
    int 21h
    popa
    ret
endp PrintPacman
proc YouWin
    pusha
    ; Return to text mode
    mov ah, 0
    mov al, 2
    int 10h
    
    mov ah, 09
    mov dx, offset you_win
    int 21h
    popa
    ret
endp YouWin
proc PrintPacmanImg
    pusha
    mov cx, 16
    mov si,[imgA]
lop:
    push cx
    mov cx, 16
    sub [x],cx
    lop2:
        mov dl, [si]
        mov [color], dl
        call PutPixel
        inc [x]
        inc si
        loop lop2
        inc [y]
        pop cx
    loop lop
    sub [y],16
    popa
    ret
endp PrintPacmanImg
proc DelPacmanImg
    pusha
    mov si,offset black
    mov cx, 16
lopb:
    push cx
    mov cx, 16
    sub [x],cx
    lop2b:
        mov dl, [si]
        mov [color], dl
        call PutPixel
        inc [x]
        inc si
        loop lop2b
        inc [y]
        pop cx
    loop lopb
    sub [y],16
    popa
    ret
endp DelPacmanImg

proc lopDelete
    pusha
lopdel: 
    call DelPacmanImg
    mov si, offset img2
    mov [imgA], si
    call PrintPacmanImg
    call waiting
    call DelPacmanImg
    mov si, offset img
    mov [imgA], si
    call PrintPacmanImg
    call waiting
    call DelPacmanImg
    add [x],10
    cmp [x],336
    ja down
    jmp lopdel
    down:
        add [y],15
        cmp [y], 60
        ja stop
        mov [x],16
        jmp lopdel
stop:   popa
    ret
endp lopDelete
proc PrintApple
    pusha
    push [x]
    push [y]
    mov bx,[AppleX]
    mov [x], bx
    mov bx,[Appley]
    mov [y], bx
    lea si, [apple]
    mov cx, 13
l:
    push cx
    mov cx, 10
    sub [x],cx
    l2:
        mov dl, [si]
        mov [color], dl
        call PutPixel
        inc [x]
        inc si
        loop l2
        inc [y]
        pop cx
    loop l
    sub [y],16
    
    pop [y]
    pop[x]
    popa
    ret
endp PrintApple
proc Game
    mov ax, 013h               ; Init Graph
    int 010h
    call PrintApple
    ;the place pacman start moving
    mov [x], 20
    mov [y],100
    
  ReadKey:
    cmp [x],150
    jb continu
    cmp [x],160
    jnbe continu
    
  checky:
    cmp [y],15
    jb continu
    cmp [y], 25
    jbe gameover
    
  continu:
    call DelPacmanImg
    mov si, offset img2
    mov [imgA], si
    call PrintPacmanImg
    call waiting
    call DelPacmanImg
    mov si, offset img
    mov [imgA], si
    call PrintPacmanImg
    call waiting
    
    
    mov ah, 0
    int 016h

    cmp ah, 75                 ; Left
    jne Skip1
    sub [x], 10
  
  Skip1:
    cmp ah, 77                 ; Right
    jne Skip2
    add [x], 10
  
  Skip2:
    cmp ah, 72                 ; Up
    jne Skip3
    sub [y], 10
    
  Skip3:
    cmp ah, 80                 ; Down
    jne Skip4
    add [y], 10
    
  Skip4:
    jmp ReadKey

  gameover:
    mov ax, 02h                ;RestoreTextMode
    int 010h
    
ret
endp Game



proc second_apple_pos
    mov [AppleX], 220
    mov [AppleY], 300
    ret
endp second_apple_pos

start:
    mov ax, @data
    mov ds, ax
; --------------------------
    mov ax, 013h               ; Init Graph
    int 010h
    
    call DelPacmanImg
    mov si, offset img2
    mov [imgA], si
    call PrintPacmanImg
    call waiting
    call DelPacmanImg
    mov si, offset img
    mov [imgA], si
    call PrintPacmanImg
    call waiting
    call game
    call second_apple_pos
    call game
    ;Return to text mode
    mov ah, 0
    mov al, 2
    int 10h
    
    
    call YouWin
    

        
    
    
    
; --------------------------
    
exit:
    mov ax, 4c00h
    int 21h
END start


Solution 1:[1]

Why the pacman exhibits a trail

For an object to move on the screen, you must delete it prior to changing one (or both) of its coordinates. Your code currently is drawing the object, changing the coordinates according to the inputted arrow key, and then redrawing the object in its new location. The old version was not removed from the screen.

  continu:
    call DelPacmanImg      <<< This is redundant
    mov  si, offset img2
    mov  [imgA], si
    call PrintPacmanImg
    call waiting           <<< This needs an argument in CX
    call DelPacmanImg      <<< This is redundant
    mov  si, offset img
    mov  [imgA], si
    call PrintPacmanImg
    call waiting           <<< This needs an argument in CX
    
    mov  ah, 00h           ; BIOS.WaitKeyboardKey
    int  16h               ; -> AX
    call DelPacmanImg      <<< Here you must delete the object

    cmp ah, 4Bh            ; Left
    jne Skip1
    sub [x], 10
  
  Skip1:
    ...

Why the 'you win' screen doesn't show up

You have chosen to play two games before showing the "you win" screen. For the second game you initialize the position of the apple offscreen! The screen that you use (13h) has a resolution of 320 pixels horizontally and 200 pixels vertically, so mov [AppleY], 300 is outside of the screen's rectangle. Under these circumstances it can become very hard to find the area on the screen where your program can detect a win...
Also, if you position the apple alternatively, you should change the testing area correspondingly instead of keeping that rectangle hard coded.


Some free review

The outer loop (L2) in the Waiting procedure depends on CX for which your program does not provide a value. Either specify one as an argument to the proc or assign a value within the proc itself.

Your program uses the rather bizarre method of referring to an object via a coordinate that lies outside and to the right of the enclosing rectangle. It's very strange (to me at least), but hey, it can work.

The (first) apple at (150,20) and the area that you test:

    130       140       150       160
    v         v         v         v
                        ttttttttttt     <- 15
                        t         t
                        t         t
                        t         t
                        t         t
              aaaaaaaaaa*         t     <- 20
              a        at         t
              a        at         t
              a        at         t
              a        at         t
              a        attttttttttt     <- 25
              a        a
              a        a
              a        a
              a        a
              a        a
              a        a
              aaaaaaaaaa

When pacman eats the apple at (150,20):

    130       140       150       160
    v         v         v         v
                        ttttttttttt     <- 15
                        t         t
                        t         t
                        t         t
                        t         t
        pppppppppppppppp*         t     <- 20
        p     a        pt         t
        p     a        pt         t
        p     a        pt         t
        p     a        pt         t
        p     a        pttttttttttt     <- 25
        p     a        p
        p     a        p
        p     a        p
        p     a        p
        p     a        p
        p     a        p
        p     aaaaaaaaap
        p              p
        p              p
        pppppppppppppppp
; Wait for key press
mov ah,0bh
int 21h

This DOS function does not wait for a key press! It merely reports if a key is available. It does not wait for one to become available.

; Return to text mode
mov ah, 0
mov al, 2
int 10h

It's more usual to select the 80x25 text mode via its number 3.

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

I would suggest you wait for a key press here, instead of having the program terminate directly after.

cmp [x],336
ja  down

In the lopDelete procedure (what does that do?), this instruction refers to a non-existing X coordinate! Valid X range from 0 to 319.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Sep Roland