Check target words list when checking the guess word

This commit is contained in:
Juhani Krekelä 2022-02-24 19:14:25 +02:00
parent cd049240ea
commit b7e010e5ac
4 changed files with 100 additions and 39 deletions

View File

@ -1,16 +1,20 @@
NASM ?= nasm
PYTHON ?= python
# 'murky' is the rarest target word we'll use
# https://github.com/lynn/hello-wordl/blob/7da40c1f067eb1ec157d4c5b7a9bd8257ed39342/src/Game.tsx#L34
RAREST_WORD = murky
all: dosdl.com
dosdl.com: dosdl.asm dictionary.inc targets.inc
$(NASM) -fbin -o $@ $<
dictionary.inc: dictionary.json compress-dict.py
$(PYTHON) compress-dict.py $< $@
dictionary.inc: dictionary.json targets.json compress-dict.py
$(PYTHON) compress-dict.py $< targets.json $(RAREST_WORD) $@
targets.inc: targets.json compress-targets.py
$(PYTHON) compress-targets.py $< $@
$(PYTHON) compress-targets.py $< $(RAREST_WORD) $@
clean:
rm -f *.inc *.com

View File

@ -5,13 +5,27 @@ import sys
alphabet = 'abcdefghijklmnopqrstuvwxyz'
srcpath = sys.argv[1]
targetpath = sys.argv[2]
excludepath = sys.argv[2]
rarestword = sys.argv[3]
targetpath = sys.argv[4]
with open(srcpath, 'r') as f:
words = json.load(f)
with open(excludepath, 'r') as f:
exclude_all = json.load(f)
# We only care about 5-letter words
words = [word for word in words if len(word) == 5]
exclude_all = [word for word in exclude_all if len(word) == 5]
exclude = set()
for word in exclude_all:
exclude.add(word)
if word == rarestword: break
# Don't include words in the exclude list
words = [word for word in words if word not in exclude]
# Split dictionary into per-startletter arrays
arrays = {letter: [] for letter in alphabet}

View File

@ -5,17 +5,16 @@ import sys
alphabet = 'abcdefghijklmnopqrstuvwxyz*'
srcpath = sys.argv[1]
targetpath = sys.argv[2]
rarestword = sys.argv[2]
targetpath = sys.argv[3]
with open(srcpath, 'r') as f:
all_words = json.load(f)
# 'murky' is the rarest word we'll use
# https://github.com/lynn/hello-wordl/blob/7da40c1f067eb1ec157d4c5b7a9bd8257ed39342/src/Game.tsx#L34
words = []
for word in all_words:
words.append(word)
if word == 'murky': break
if word == rarestword: break
# We only care about 5-letter words
words = [word for word in words if len(word) == 5]
@ -29,6 +28,7 @@ for word in words:
array.append(packed)
with open(targetpath, 'w') as f:
f.write(f'targets_len equ {len(array)}\n')
f.write('targets:\n')
for packed in array:
f.write(f'\tdb {", ".join(str(byte) for byte in packed)}\n')

105
dosdl.asm
View File

@ -7,42 +7,16 @@ section .code
select_target:
; TODO: Implement target word selection
mov si, 1
; https://github.com/lynn/hello-wordl/blob/7da40c1f067eb1ec157d4c5b7a9bd8257ed39342/src/util.ts#L14
mov si, 1397
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
call unpack_target
read_guess:
; Number of thus far guessed letters stored in bx
@ -170,7 +144,30 @@ check_dictionary:
loop .dictionary_loop
check_targets:
; TODO: Check whether word is in the list of target words
mov cx, targets_len
mov si, targets
.targets_loop:
mov di, dictionary_entry
call unpack_target
xor bp, bp
.compare_loop:
cmp bp, 5
je .match
mov al, [di + bp]
cmp al, [guess + bp]
jne .not_match
inc bp
jmp .compare_loop
.match:
jmp word_found
.not_match:
loop .targets_loop
word_not_found:
mov ah, 9
@ -385,6 +382,52 @@ newline:
pop ax
ret
; in:
; si = packed target word
; di = 5 byte buffer for unpacking the target
; out:
; si = first byte after the packed target word
unpack_target:
push ax
push cx
push dx
push di
; 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
pop di
pop dx
pop cx
pop ax
ret
section .data
target times 5 db 0
guess times 5 db 0
@ -394,7 +437,7 @@ wrong_places times 5 db 0
guesses db 0
dictionary_entry times 4 db 0
dictionary_entry times 5 db 0
section .rodata