Add guessing

This commit is contained in:
Juhani Krekelä 2022-02-23 02:31:52 +02:00
parent 25f04d9a1c
commit 788bd63b38
2 changed files with 302 additions and 2 deletions

View File

@ -22,6 +22,6 @@ for word in words:
array.append(packed)
with open(targetpath, 'w') as f:
f.write('tagets:\n')
f.write('targets:\n')
for packed in array:
f.write(f'\tdb {", ".join(str(byte) for byte in packed)}\n')

302
dosdl.asm
View File

@ -1,6 +1,306 @@
bits 16
cpu 8086
org 0x100
ret
section .code
select_target:
; TODO: Implement target word selection
mov si, 1
extract_target:
shl si, 1
shl si, 1
add si, targets
mov di, target
; Target word is stored packed 5 bits per letter into 32 bits
; 2221_1111 4333_3322 5555_4444 0000_0005
; Load 4333_3322_2221_1111 into dx and extracts first three letters
mov dx, [si]
add si, 2
mov cl, 5
%rep 3
mov al, dl
and al, 0x1f
add al, 'a'
stosb
shr dx, cl
%endrep
; Load 0000_0005_5555_4444 into ax, shift over by one, combine into dx
; which has 0000_0000_0000_0004, and extract last two letters
mov ax, [si]
add si, 2
shl ax, 1
or dx, ax
%rep 2
mov al, dl
and al, 0x1f
add al, 'a'
stosb
shr dx, cl
%endrep
read_guess:
; Number of thus far guessed letters stored in bx
xor bx, bx
.loop:
mov ah, 8
int 0x21
cmp al, 8
je .backspace
cmp bx, 5
je .full
cmp al, 'A'
jb .loop
cmp al, 'Z'
jbe .letter
cmp al, 'a'
jb .loop
cmp al, 'z'
jbe .letter
jmp .loop
.full:
cmp al, 13
je .done
jmp .loop
.letter:
; Lowercase
or al, 32
mov byte [guess + bx], al
inc bx
; Echo to screen
mov dl, al
mov ah, 2
int 0x21
jmp .loop
.backspace:
test bx, bx
jz .loop
; Rub out the letter
; PC-DOS 1.1 documentation says only 8 is needed, but DOSBox
; seems buggy here
mov ah, 2
mov dl, 8
int 0x21
mov dl, ' '
int 0x21
mov dl, 8
int 0x21
dec bx
jmp .loop
.done:
check_guess:
; TODO: See whether guess is in the dictionary or targets
find_exact_hits:
mov si, guess
mov di, exact_hits
mov cx, 5
.loop:
lodsb
cmp al, [si - guess + target - 1]
je .hit
; Zero out if not the right letter
xor al, al
.hit:
stosb
loop .loop
find_wrong_places:
; Zero out first
mov di, wrong_places
mov cx, 5
xor al, al
rep stosb
xor bp, bp
.loop:
cmp bp, 5
je .done
mov al, [exact_hits + bp]
inc bp
test al, al
jnz .loop
; What was the guessed letter?
mov dl, [guess + bp - 1]
; How many times does it appear in the target?
xor bh, bh
mov cx, 5
mov si, target
.count_target:
lodsb
cmp al, dl
jne .not_found_in_target
inc bh
.not_found_in_target:
loop .count_target
; How many times does it appear in the feedback already?
xor bl, bl
mov cx, 5
mov si, exact_hits
.count_exact_hits:
lodsb
cmp al, dl
jne .not_found_in_exact_hits
inc bl
.not_found_in_exact_hits:
loop .count_exact_hits
mov cx, 5
mov si, wrong_places
.count_wrong_places:
lodsb
cmp al, dl
jne .not_found_in_wrong_places
inc bl
.not_found_in_wrong_places:
loop .count_wrong_places
; If in target more than in feedback → wrong place
cmp bh, bl ; target <= feedback
jbe .loop
mov byte [wrong_places + bp - 1], dl
jmp .loop
.done:
print_feedback:
call newline
mov cx, 5
xor bp, bp
xor bx, bx ; How many exact hits?
.loop:
mov al, [exact_hits + bp]
test al, al
jnz .exact_hit
mov al, [wrong_places + bp]
test al, al
jnz .wrong_place
mov dl, 'x'
jmp .print
.exact_hit:
mov dl, ' '
inc bx
jmp .print
.wrong_place:
mov dl, '^'
.print:
mov ah, 2
int 0x21
inc bp
loop .loop
call newline
is_finished:
inc byte [guesses]
cmp bx, 5
je victory
cmp byte [guesses], 6
je loss
jmp read_guess
loss:
mov dx, word_was_str
mov ah, 9
int 0x21
mov cx, 5
mov si, target
.loop:
lodsb
mov dl, al
mov ah, 2
int 0x21
loop .loop
jmp exit
victory:
mov dx, correct_in_str
mov ah, 9
int 0x21
mov dl, [guesses]
add dl, '0'
mov ah, 2
int 0x21
mov dx, guesses_str
mov ah, 9
int 0x21
exit:
ret
newline:
push ax
push dx
mov ah, 2
mov dl, 13
int 0x21
mov dl, 10
int 0x21
pop dx
pop ax
ret
section .data
target times 5 db 0
guess times 5 db 0
exact_hits times 5 db 0
wrong_places times 5 db 0
guesses db 0
section .rodata
word_was_str db 'The word was: $'
correct_in_str db 'Correct in $'
guesses_str db ' guesses.$'
%include "dictionary.inc"
%include "targets.inc"