assemblycpu-architecturex86-16emu8086microprocessors

Why is my function not producing a different number every time in my rock, paper, scissors game in assembly 8086 language?


I have a problem in assembly 8086 language. I'm trying to make rock, paper, scissors game. When user gives an input, program asks the question again. The problem is computer choice never changes. Every time calling the function, I want to produce a number between 1 - 3 again.

Here's the code:

.MODEL SMALL
.STACK 100H

.DATA
    playerChoice DB ?
    computerChoice DB ?
    userInput DB 'ROCK PAPER SCISSORS? (1-Rock 2-Paper 3-Scissors q-Quit) : $'   
    playerWinsMsg DB 'Result : Player Won! $'
    computerWinsMsg DB 'Result : Computer Won! $'
    tieMsg DB 'Result : Tie!! $'
    invalidChoiceMsg DB 'Invalid choice! Try again!! $'

.CODE
    MAIN PROC 
        
       MOV AX, @DATA
       MOV DS, AX
       
    GAME_LOOP:
 
        MOV AH, 09H
        LEA DX, userInput
        INT 21H
              
        
        MOV AH, 01H
        INT 21H
        CMP AL, 'q'
        JE EXIT
        SUB AL, 30H
        MOV playerChoice, AL
        
        MOV AH,2
        MOV DL, 10
        INT 21H
        MOV DL, 13
        INT 21H

        CALL RANDOMIZE
        CALL COMPUTER_CHOICE
        
        

        CMP playerChoice, 1
        JE ROCK
        CMP playerChoice, 2
        JE PAPER
        CMP playerChoice, 3
        JE SCISSORS
       

        LEA DX, invalidChoiceMsg
        MOV AH, 09H
        INT 21H 
        
        MOV AH,2
        MOV DL, 10
        INT 21H
        MOV DL, 13
        INT 21H
        
        JMP GAME_LOOP

    ROCK:
        
        CMP computerChoice, 1
        JE TIE
        CMP computerChoice, 2
        JE COMPUTER_WINS
        CMP computerChoice, 3
        JE PLAYER_WINS
        JMP EXIT

    PAPER:

        CMP computerChoice, 1
        JE PLAYER_WINS
        CMP computerChoice, 2
        JE TIE
        CMP computerChoice, 3
        JE COMPUTER_WINS
        JMP EXIT

    SCISSORS:

        CMP computerChoice, 1
        JE COMPUTER_WINS
        CMP computerChoice, 2
        JE PLAYER_WINS
        CMP computerChoice, 3
        JE TIE
        JMP EXIT

    PLAYER_WINS:
        MOV AH, 09H
        LEA DX, playerWinsMsg
        INT 21H
        
        MOV AH,2
        MOV DL, 10
        INT 21H
        MOV DL, 13
        INT 21H
        
        JMP GAME_LOOP

    COMPUTER_WINS:
        MOV AH, 09H
        LEA DX, computerWinsMsg
        INT 21H 
        
        MOV AH,2
        MOV DL, 10
        INT 21H
        MOV DL, 13
        INT 21H
        
        JMP GAME_LOOP

    TIE:
        MOV AH, 09H
        LEA DX, tieMsg
        INT 21H
        
        MOV AH,2
        MOV DL, 10
        INT 21H
        MOV DL, 13
        INT 21H
        
        JMP GAME_LOOP    

    RANDOMIZE:
        MOV AH, 2CH
        INT 21H
        MOV AH, DL
        XOR AH, AH
        ADD DL, 1
        MOV BX, 3
        XOR DX, DX
        DIV BX
        ADD AL, 1
        MOV computerChoice, AL
        RET

    COMPUTER_CHOICE:
        CALL RANDOMIZE
        RET 
        
    EXIT:
        MOV AH, 4CH
        INT 21H

    MAIN ENDP
END MAIN

Solution

  • For every computerChoice you invoke randomize twice. Sadly, the randomize code has some important errors:

    This is the improved code where I additionally removed some redundancies and preferred to use the byte-sized division:

    RANDOMIZE:
      mov  ah, 2Ch   ; DOS.GetSystemtime
      int  21h       ; -> CX DX
      mov  al, dl    ; [0,99]
      cbw
      mov  dl, 3
      div  dl        ; AX / DL --> Quotient AL, Remainder AH
      inc  ah
      mov  computerChoice, ah
      ret
    

    I believe it will not be necessary to keep invoking randomize twice for every computerChoice.