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
For every computerChoice you invoke randomize twice. Sadly, the randomize code has some important errors:
You don't actually use the return you get from the system time because you erroneously move DL into AH.
Therefore, the calculation will be based on whichever was the last value loaded in AL and that happens to be 13 as returned by DOS in MOV DL, 13
INT 21H
.
So, the first time you invoke randomize, AL contains 13, which once divided by 3 produces a quotient of 4, that you then increment to 5.
The second time, AL contains 5, which once divided by 3 produces a quotient of 1, that you then increment to 2.
Follows that the computer always plays 2.
You should inspect the remainder from the division by 3 instead of the quotient like you are doing right now.
The remainder is going to be a number in the range [0,2], and incrementing that will produce a useful choice in the range [1,3].
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.