global _start
extern itos, stoi, print, getInput, exit
section .data
intro_msg: db 0x0a,0x0a,"Welcome to Hangman!",0x0a,"The object of the game is to guess all the letters in the hidden word.",0x0a,"If you guess incorrectly 5 times, you lose.",0x0a,0x00
intro_msg_len: equ $ - intro_msg
bad_letter_msg: db "Please input a valid letter (a-z.)",0x0a,0x00
bad_letter_msg_len: equ $ - bad_letter_msg
guess_msg: db "Guess a letter: ",0x00
guess_msg_len: equ $ - guess_msg
prior_guess_msg: db "You've already guessed that letter before.",0x0a,"Please try again.",0x0a,0x00
prior_guess_msg_len: equ $ - prior_guess_msg
win_msg: db 0x0a,"You win!",0x0a,0x00
win_msg_len: equ $ - win_msg
lose_msg: db 0x0a,"You lose! Try harder next time.",0x0a,0x00
lose_msg_len: equ $ - lose_msg
wrong_msg: db "That letter does not exist in the word.",0x0a,"You have this many tries left: ",0x00
wrong_msg_len: equ $ - wrong_msg
guess_word: db "juxtaposition",0x00 ;modify this to change the word to be guessed (as of now)
guess_word_len: equ $ - guess_word
alphabet: db "abcdefghijklmnopqrstuvwxyz",0x00
alphabet_len: equ $ - alphabet
guess_list_msg: db "Previously guessed letters: ",0x00
guess_list_msg_len: equ $ - guess_list_msg
newline: db 0x0a,0x00
space: db " ",0x00
underscore: db "_",0x00
section .bss
input: resd 1
curletter: resb 1
guessed: resb 1
remguesses: resd 16
guessleft: resb 4
section .text
checkletter:
mov dl, 0 ;no guesses were correct
mov cl, 0 ;letters remain unguessed if 0 after return below
mov esi, 0
mov bl, byte [guessed]
check_loop:
mov al, byte [guess_word + esi]
cmp al, 0
je check_end
inc esi
mov [curletter], al
cmp al, 0x60
jl check_loop
cmp al, bl
je mark
or cl, 1
jne check_loop
mark:
or dl, 1
and byte [guessed], 0xDF
mov al, [guessed]
mov byte [guess_word + (esi-1)], al
jmp check_loop
check_end:
mov byte [guessed], 0
ret
draw_guesses:
mov esi, 0
loop_guesses:
mov al, byte [alphabet + esi]
cmp al, 0
je loop_guesses_end
add esi, 1
mov [curletter], al
cmp al, 0x60
ja loop_guesses
push curletter
push 1
call print
add esp, 8
push space
push 1
call print
add esp, 8
jmp loop_guesses
loop_guesses_end:
ret
check_alpha:
mov esi, 0
mov cl, 0
mov dl, 0
mov bl, byte [guessed]
check_range:
cmp bl, 0x61 ;if the guessed letter is not between 'a' and 'z' then it's bad input
jl bad_input
cmp bl, 0x7A
ja bad_input
jmp loop_alpha
bad_input:
cmp cl, 1
je failed_input
add bl, 32
add byte [guessed], 32
mov cl, 1
jmp check_range
failed_input:
push bad_letter_msg
push bad_letter_msg_len
call print
add esp, 8
mov dl, 2
ret
loop_alpha:
mov al, byte [alphabet + esi]
cmp al, 0
je loop_alpha_end
add esi, 1
mov [curletter], al
cmp al, 0x60
jl loop_alpha
cmp al, bl
jne loop_alpha
mov dl, 1
and al, 0xDF
mov byte [alphabet + (esi-1)], al
ret
loop_alpha_end:
ret
displayword:
mov esi, 0
push newline
push 1
call print
add esp, 8
loop_word:
push space
push 1
call print
add esp, 8
mov al, byte [guess_word + esi]
cmp al, 0
je loop_word_end
add esi, 1
mov [curletter], al
cmp al, 0x60
ja undiscovered
push curletter
push 1
call print
add esp, 8
jmp loop_word
undiscovered:
push underscore
push 1
call print
add esp, 8
jmp loop_word
loop_word_end:
push newline
push 1
call print
add esp, 8
ret
finished:
call displayword
push win_msg
push win_msg_len
call print
add esp, 8
call exit
_start:
push intro_msg
push intro_msg_len
call print
add esp, 8
pop eax
mov cl, 1 ;set unguessed letters flag in cl to 1
mov word [guessleft], 5
guess:
cmp cl, 0 ;check if checkletter has set this flag to 0 (all letters guessed)
je finished
call displayword
push newline
push 1
call print
add esp, 8
push guess_list_msg
push guess_list_msg_len
call print
add esp, 8
call draw_guesses
push newline
push 1
call print
add esp, 8
;Prompt user for first number
push guess_msg
push guess_msg_len
call print
add esp, 8
;Get character from user
push guessed
push 4
call getInput
add esp, 8
call check_alpha
cmp dl, 2
je guess
cmp dl, 1
je check_word
push prior_guess_msg
push prior_guess_msg_len
call print
add esp, 8
jmp guess
check_word:
call checkletter
cmp dl, 1
je guess
dec byte [guessleft]
mov eax, [guessleft]
cmp word [guessleft], 0
je lose
push eax
push wrong_msg
push wrong_msg_len
call print
add esp, 8
pop eax
mov ebx, remguesses
mov ecx, 16
call itos
push remguesses
push 16
call print
add esp, 8
jmp guess
lose:
push lose_msg
push lose_msg_len
call print
add esp, 8
call exit