From b7e010e5ac191b1857dc7ea3ba13688c4b341b41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juhani=20Krekel=C3=A4?= Date: Thu, 24 Feb 2022 19:14:25 +0200 Subject: [PATCH] Check target words list when checking the guess word --- Makefile | 10 +++-- compress-dict.py | 16 ++++++- compress-targets.py | 8 ++-- dosdl.asm | 105 +++++++++++++++++++++++++++++++------------- 4 files changed, 100 insertions(+), 39 deletions(-) diff --git a/Makefile b/Makefile index 4e94363..e018709 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/compress-dict.py b/compress-dict.py index 1ff9a68..b7e1dbd 100644 --- a/compress-dict.py +++ b/compress-dict.py @@ -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} diff --git a/compress-targets.py b/compress-targets.py index bc17562..d9f8a45 100644 --- a/compress-targets.py +++ b/compress-targets.py @@ -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') diff --git a/dosdl.asm b/dosdl.asm index b197e40..af58eb4 100644 --- a/dosdl.asm +++ b/dosdl.asm @@ -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