Compare commits

...

24 Commits

Author SHA1 Message Date
Juhani Krekelä b9feee6e25 Update wordlists 2023-03-20 16:42:34 +02:00
Juhani Krekelä 20be99d08f Update wordlist date in README.md 2022-02-27 16:11:56 +02:00
Juhani Krekelä 422297cadb Add note about Ctrl+C to exit into the greeting message 2022-02-27 16:11:42 +02:00
Juhani Krekelä 8bc078d452 Note that hello DOSdl is not only for IBM PC compatible 2022-02-25 15:55:11 +02:00
Juhani Krekelä 75ef4cd3d1 Align lists in help text 2022-02-25 15:53:55 +02:00
Juhani Krekelä df2cd4079f Allow upper case switches 2022-02-25 02:19:44 +02:00
Juhani Krekelä 2ae741d705 Add ability to set seed manually 2022-02-25 02:19:12 +02:00
Juhani Krekelä 9b2cd70f4d Include license info in the executable 2022-02-25 02:05:00 +02:00
Juhani Krekelä e5b42749e5 Tweak phrasing in the explanation for ultra hard mode 2022-02-25 01:53:47 +02:00
Juhani Krekelä e2cbdcaf92 Terminate program on ^C 2022-02-25 01:42:51 +02:00
Juhani Krekelä a6adf07fc7 Add ultra hard mode 2022-02-25 01:40:59 +02:00
Juhani Krekelä a90e026623 Implement hard mode 2022-02-25 01:26:18 +02:00
Juhani Krekelä 7af168618c Add command line parsing 2022-02-25 01:05:50 +02:00
Juhani Krekelä d157d8352b Add in-program help 2022-02-25 00:04:10 +02:00
Juhani Krekelä c538bd04f7 Track and which letters are not used in the word 2022-02-24 23:44:46 +02:00
Juhani Krekelä 47efb1dbb2 Add system requirements to README.md 2022-02-24 22:10:24 +02:00
Juhani Krekelä 1517f51b84 Link to hello wordl's 'Where are the words coming from?' section 2022-02-24 22:07:50 +02:00
Juhani Krekelä 2c2e5fa75b Update README.md 2022-02-24 22:05:57 +02:00
Juhani Krekelä a3e699a391 Pluralize victory message correctly 2022-02-24 21:38:54 +02:00
Juhani Krekelä ae8e8e69ce Seed the RNG based on current date 2022-02-24 21:33:35 +02:00
Juhani Krekelä 0661eb0f06 Put debug code behind DEBUG define 2022-02-24 21:19:02 +02:00
Juhani Krekelä b000857bb4 Implement the RNG for word selection 2022-02-24 21:14:37 +02:00
Juhani Krekelä b7e010e5ac Check target words list when checking the guess word 2022-02-24 19:14:25 +02:00
Juhani Krekelä cd049240ea Limit targets to words at least as common as "murky" 2022-02-23 03:20:21 +02:00
9 changed files with 870 additions and 63 deletions

View File

@ -1,20 +1,30 @@
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
dosdl.com: dosdl.asm dictionary.inc targets.inc license.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) $@
license.inc: LICENSE embed-textfile.py
$(PYTHON) embed-textfile.py $< license_str $@
clean:
rm -f *.inc *.com
distclean: clean
.PHONY: all clean distclean
run: dosdl.com
dosbox dosdl.com
.PHONY: all clean distclean run

View File

@ -1,14 +1,27 @@
hello DOSdl
===========
Hello DOSdl is a variant of Wordle / hello wordl for MS-DOS running on IBM PC
compatible systems.
Hello DOSdl is a variant of Wordle / hello wordl for MS-DOS.
System requirements
-------------------
- MS-DOS 1.25 or later, or PC-DOS 1.1 or later
- 64KiB of RAM
Notably, hello DOSdl has been written to only use the DOS APIs, meaning it
should work on non-PC DOS platforms as well.
Gameplay
--------
Gameplay is as in hello wordl's default daily mode. `x` under a letter marks it
as incorrect and `^` marks it as being in the wrong place.
Word lists
----------
The words lists are taken from
[hello wordl](https://github.com/lynn/hello-wordl) and are identical as of
2022-02-02, to allow cross-play between hello DOSdl and hello wordl. See the
link for further details.
[hello wordl](https://github.com/lynn/hello-wordl#where-are-the-words-coming-from)
and are identical as of 2023-03-20, to allow cross-play between hello DOSdl and
hello wordl. See the link for further details.
Licensing
---------

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,10 +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:
words = json.load(f)
all_words = json.load(f)
words = []
for word in all_words:
words.append(word)
if word == rarestword: break
# We only care about 5-letter words
words = [word for word in words if len(word) == 5]
@ -22,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')

View File

@ -1882,6 +1882,7 @@
"admeasures",
"admeasuring",
"admen",
"admin",
"administer",
"administered",
"administering",
@ -147269,6 +147270,7 @@
"sirupy",
"sirvente",
"sirventes",
"sirwal",
"sis",
"sisal",
"sisals",

793
dosdl.asm
View File

@ -3,46 +3,206 @@ cpu 8086
org 0x100
args_length equ 0x80
args_area equ 0x81
section .code
select_target:
; TODO: Implement target word selection
mov si, 1
parse_arguments:
xor ch, ch
mov cl, [args_length]
mov si, args_area
extract_target:
; Skip leading spaces
.skip_leading_space:
test cx, cx
jz .leading_spaces_skipped
cmp byte [si], ' '
jne .leading_spaces_skipped
dec cx
inc si
jmp .skip_leading_space
.leading_spaces_skipped:
; See whether we have /h, /u, /l, or /?
cmp cx, 2
jb .not_mode_option
cmp byte [si], '/'
jne .not_mode_option
cmp byte [si + 1], 'h'
je .hard_mode
cmp byte [si + 1], 'H'
jne .not_hard_mode
.hard_mode:
mov byte [hard_mode], 1
add si, 2
sub cx, 2
jmp .after_option_space
.not_hard_mode:
cmp byte [si + 1], 'u'
je .ultra_hard_mode
cmp byte [si + 1], 'U'
jne .not_ultra_hard_mode
.ultra_hard_mode:
mov byte [hard_mode], 1
mov byte [ultra_hard_mode], 1
add si, 2
sub cx, 2
.after_option_space:
test cx, cx
jz .option_done
cmp byte [si], ' '
jne .option_done
dec cx
inc si
jmp .after_option_space
.option_done:
.not_ultra_hard_mode:
cmp byte [si + 1], 'l'
je print_license
cmp byte [si + 1], 'L'
je print_license
cmp byte [si + 2], '?'
je print_help
.not_mode_option:
test cx, cx
jz seed_rng_date
seed_rng_argument:
xor ax, ax
xor dx, dx
mov bp, mull32
call store32
.loop:
xor dx, dx
mov ax, 10
mov bp, mulr32
call store32
call mul32
mov bp, addl32
call store32
lodsb
cmp al, '0'
jb print_help
cmp al, '9'
ja print_help
sub al, '0'
xor ah, ah
xor dx, dx
mov bp, addr32
call store32
call add32
mov bp, mull32
call store32
loop .loop
mov bp, rng_seed
call store32
jmp select_target
print_help:
mov ah, 9
mov dx, help_str
int 0x21
ret
print_license:
mov ah, 9
mov dx, license_str
int 0x21
ret
seed_rng_date:
; Get date
mov ah, 0x2a
int 0x21
mov [year], cx
mov [month], dh
%ifdef DEBUG
mov cx, 2022
mov dh, 2
mov dl, 24
%endif
mov [day], dl
; addl32 = year * 10000
mov ax, 10000
mul word [year]
mov bp, addl32
call store32
; addr32 = month * 100 + day
mov ax, 100
mul word [month]
add ax, [day]
mov bp, addr32
call store32
; rng_seed = addl32 + addr32 = year * 10000 + month * 100 + day
call add32
mov bp, rng_seed
call store32
select_target:
; Call rng to get a number
call rng
mov bp, rng_output
call store32
; Multiply rng output by number of target words
xor si, si
xor dx, dx
xor ax, ax
mov cx, targets_len
.multiply_loop:
add ax, [rng_output + 0]
adc dx, [rng_output + 2]
adc si, 0
loop .multiply_loop
mov ax, si
%ifdef DEBUG
call hexprint16
call newline
%endif
load_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
call unpack_target
; 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
; Figure out whether this is a removed word
; If so, reroll target word
cmp byte [target], '{'
je select_target
print_greeting:
mov ah, 9
mov dx, greeting_str
int 0x21
read_guess:
; Number of thus far guessed letters stored in bx
@ -52,6 +212,9 @@ read_guess:
mov ah, 8
int 0x21
cmp al, 3
je .ctrl_c
cmp al, 8
je .backspace
@ -111,6 +274,146 @@ read_guess:
jmp .loop
.ctrl_c:
ret
.done:
check_hard_mode:
cmp byte [hard_mode], 1
jne .done
; See whether exact hits are reused
xor bp, bp
mov cx, 5
.exact_hits:
mov al, [exact_hits + bp]
test al, al
jz .not_exact_hit
cmp al, [guess + bp]
je .exact_hit_match
mov dx, bp
add dl, '1'
mov [exact_hit_error_str.position], dl
mov [exact_hit_error_str.letter], al
mov si, exact_hit_error_str
jmp print_error
.exact_hit_match:
.not_exact_hit:
inc bp
loop .exact_hits
; See whether wrongly placed letters are reused
xor bp, bp
.wrong_places:
cmp bp, 5
je .done
mov dl, [wrong_places + bp]
test dl, dl
jz .not_wrong_place
; Count how many times letter is used in exact_hits + wrong_places
xor bx, bx
mov cx, 5
mov si, exact_hits
.count_exact_hits:
lodsb
cmp al, dl
jne .not_count_exact_hit
inc bh
.not_count_exact_hit:
loop .count_exact_hits
mov cx, 5
mov si, wrong_places
.count_wrong_places:
lodsb
cmp al, dl
jne .not_count_wrong_places
inc bh
.not_count_wrong_places:
loop .count_wrong_places
; Count how many times letter is used in guess
mov cx, 5
mov si, guess
.count_guess:
lodsb
cmp al, dl
jne .not_count_guess
inc bl
.not_count_guess:
loop .count_guess
cmp bl, bh
jae .used_enough
mov [wrong_place_error_str.letter], dl
mov ax, bp
add ax, '1'
mov [wrong_place_error_str.position], al
mov si, wrong_place_error_str
jmp print_error
.used_enough:
.not_wrong_place:
inc bp
jmp .wrong_places
.done:
check_ultra_hard_mode:
cmp byte [ultra_hard_mode], 1
jne .done
; See whether any ruled-out letters were used
xor bp, bp
mov cx, 5
.ruled_out:
xor bh, bh
mov bl, [guess + bp]
mov ax, bx
mov al, [alphabet + bx - 'a']
cmp al, ' '
jne .not_ruled_out
mov [ruled_out_error_str.letter], bl
mov ax, bp
add al, '1'
mov [ruled_out_error_str.position], al
mov si, ruled_out_error_str
jmp print_error
.not_ruled_out:
inc bp
loop .ruled_out
; See whether wrongly places letters were moved
xor bp, bp
mov cx, 5
.wrong_places:
mov al, [wrong_places + bp]
test al, al
jz .not_wrong_place
cmp al, [guess + bp]
jne .moved
mov [not_moved_error_str.letter], al
mov ax, bp
add ax, '1'
mov [not_moved_error_str.position], al
mov si, not_moved_error_str
jmp print_error
.moved:
.not_wrong_place:
inc bp
loop .wrong_places
.done:
check_dictionary:
@ -170,11 +473,37 @@ 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 si, not_found_str
print_error:
mov ah, 9
mov dx, not_found_str
mov dx, si
int 0x21
; Wait for a keypress
@ -190,7 +519,6 @@ word_not_found:
mov dx, erase_word_str
int 0x21
mov si, not_found_str
.clear_loop:
lodsb
cmp al, '$'
@ -202,7 +530,7 @@ word_not_found:
jmp .clear_loop
.done:
.done:
mov ah, 2
mov dl, 13
@ -230,7 +558,6 @@ find_exact_hits:
find_wrong_places:
; Zero out first
mov di, wrong_places
mov cx, 5
xor al, al
rep stosb
@ -287,6 +614,15 @@ find_wrong_places:
.not_found_in_wrong_places:
loop .count_wrong_places
; If not used in target at all, remove from list of possible letters
test bh, bh
jnz .used_in_target
xor dh, dh
mov di, dx
mov byte [alphabet + di - 'a'], ' '
.used_in_target:
; If in target more than in feedback → wrong place
cmp bh, bl ; target <= feedback
jbe .loop
@ -327,6 +663,20 @@ print_feedback:
inc bp
loop .loop
mov ah, 9
mov dx, space_dash_space_str
int 0x21
mov cx, 26
mov si, alphabet
.alphabet_loop:
lodsb
mov dl, al
mov ah, 2
int 0x21
loop .alphabet_loop
call newline
is_finished:
@ -366,9 +716,19 @@ victory:
mov ah, 2
int 0x21
mov dx, guesses_str
mov ah, 9
int 0x21
cmp byte [guesses], 1
je .singular
.plural:
mov dx, guesses_str
jmp .print
.singular:
mov dx, guess_str
.print:
mov ah, 9
int 0x21
exit:
ret
@ -385,7 +745,287 @@ 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
; out:
; dx:ax = result
rng:
; https://github.com/lynn/hello-wordl/blob/7da40c1f067eb1ec157d4c5b7a9bd8257ed39342/src/util.ts#L14
; rng_t = rng_seed += rng_seed + 0x6d2b79f5
mov bp, rng_seed
call load32
add ax, 0x79f5
adc dx, 0x6d2b
call store32
mov bp, rng_t
call store32
; xorl32 = rng_t
mov bp, xorl32
call store32
; xorr32 = rng_t >> 15
mov cx, 15
call rshift32
mov bp, xorr32
call store32
; mull32 = xorl32 ^ xorr32 = rng_t ^ (rng_t >> 15)
call xor32
mov bp, mull32
call store32
; mulr32 = rng_t | 1
mov bp, rng_t
call load32
or ax, 1
mov bp, mulr32
call store32
; rng_t = mull32 * mulr32 = (rng_t ^ (rng_t >> 15)) * (rng_t | 1)
call mul32
mov bp, rng_t
call store32
; xorl32 = rng_t
mov bp, xorl32
call store32
; xorr32 = rng_t >> 7
mov cx, 7
call rshift32
mov bp, xorr32
call store32
; mull32 = xorl32 ^ xorr32 = rng_t ^ (rng_t >> 7)
call xor32
mov bp, mull32
call store32
; mulr32 = rng_t | 61
mov bp, rng_t
call load32
or ax, 61
mov bp, mulr32
call store32
; addl32 = rng_t
mov bp, rng_t
call load32
mov bp, addl32
call store32
; addr32 = mull32 * mulr32 = (rng_t ^ (rng_t >> 7)) * (rng_t | 61)
call mul32
mov bp, addr32
call store32
; xorl32 = rng_t
mov bp, rng_t
call load32
mov bp, xorl32
call store32
; xorr32 = addl32 + addr32 = rng_t + (rng_t ^ (rng_t >> 7)) * (rng_t | 61)
call add32
mov bp, xorr32
call store32
; rng_t = xorl32 ^ xorr32 = rng_t ^ (rng_t + (rng_t ^ (rng_t >> 7)) * (rng_t | 61))
call xor32
mov bp, rng_t
call store32
; xorl32 = rng_t
mov bp, xorl32
call store32
; xorr32 = rng_t >> 14
mov cx, 14
call rshift32
mov bp, xorr32
call store32
; result = xorl32 ^ xorr32 = rng_t ^ (rng_t >> 14)
call xor32
ret
; in:
; bp = address of uint32
; out:
; dx = high 16 bits
; ax = low 16 bits
load32:
mov ax, [bp + 0]
mov dx, [bp + 2]
ret
; in:
; bp = address of uint32
; dx = high 16 bits
; ax = low 16 bits
store32:
mov [bp + 0], ax
mov [bp + 2], dx
ret
; in:
; dx:ax = uint32 to be shifted
; cx = shift amount (must not be 0)
; out:
; dx:ax = result
rshift32:
push cx
.loop:
shr dx, 1
rcr ax, 1
loop .loop
pop cx
ret
; in:
; [xorl32], [xorr32] = operands
; out:
; dx:ax = result
xor32:
mov ax, [xorl32 + 0]
xor ax, [xorr32 + 0]
mov dx, [xorl32 + 2]
xor dx, [xorr32 + 2]
ret
; in:
; [mull32], [mulr32] = operands
; out:
; dx:ax = result
mul32:
push bx
push cx
; c = 1<<16
; l = l₁<<16 + l₀
; r = r₁<<16 + r₀
; l·r = (l₁<<16 + l₀)·(r₁<<16 + r₀)
; = l₁<<16·r₁<<16 + l₁<<16·r₀ + l₀·r₁<<16 + l₀·r₀
; = l₁·r₁<<32 + l₁·r₀<<16 + l₀·r₁<<16 + l₀·r₀ ||1<<32 = 0 (mod 1<<32)
; = l₁·r₀<<16 + l₀·r₁<<16 + l₀·r₀
; l₀·r₀
mov ax, [mull32 + 0]
mul word [mulr32 + 0]
mov bx, ax
mov cx, dx
; l₀·r₁<<16
mov ax, [mull32 + 0]
mul word [mulr32 + 2]
add cx, ax
; l₁·r₀<<16
mov ax, [mull32 + 2]
mul word [mulr32 + 0]
add cx, ax
mov dx, cx
mov ax, bx
pop cx
pop bx
ret
; in:
; [addl32], [addr32] = operands
; out:
; dx:ax = result
add32:
mov ax, [addl32 + 0]
mov dx, [addl32 + 2]
add ax, [addr32 + 0]
adc dx, [addr32 + 2]
ret
%ifdef DEBUG
hexprint32:
xchg ax, dx
call hexprint16
xchg ax, dx
hexprint16:
xchg ah, al
call hexprint8
xchg ah, al
hexprint8:
%rep 4
rol al, 1
%endrep
call hexprint4
%rep 4
rol al, 1
%endrep
hexprint4:
push ax
and al, 0xf
cmp al, 10
jb .digit09
add al, 'a' - 10 - '0'
.digit09:
add al, '0'
mov ah, 0xe
int 0x10
pop ax
ret
%endif
section .data
alphabet db 'abcdefghijklmnopqrstuvwxyz'
target times 5 db 0
guess times 5 db 0
@ -394,15 +1034,90 @@ wrong_places times 5 db 0
guesses db 0
dictionary_entry times 4 db 0
dictionary_entry times 5 db 0
hard_mode db 0
ultra_hard_mode db 0
rng_seed dd 0
rng_t dd 0
rng_output dd 0
xorl32 dd 0
xorr32 dd 0
mull32 dd 0
mulr32 dd 0
addl32 dd 0
addr32 dd 0
year dw 0
month dw 0
day dw 0
exact_hit_error_str:
db ' - letter at position '
.position db '#'
db " must be '"
.letter db '#'
db "'$"
wrong_place_error_str:
db " - letter '"
.letter db '#'
db "' from position "
.position db '#'
db ' must be reused$'
not_moved_error_str:
db " - letter '"
.letter db '#'
db "' in position "
.position db '#'
db ' must be moved$'
ruled_out_error_str:
db " - letter '"
.letter db '#'
db "' in position "
.position db '#'
db ' has been ruled out$'
section .rodata
greeting_str db 'Welcome to hello DOSdl. Press Ctrl+C to exit. Run `dosdl /?` for help.', 13, 10, '$'
space_dash_space_str db ' - $'
not_found_str db ' - word not found$'
erase_word_str db ' $'
word_was_str db 'The word was: $'
correct_in_str db 'Correct in $'
guesses_str db ' guesses.$'
guess_str db ' guess.$'
help_str:
db 'Usage: dosdl [/h | /u | /l | /?] [seed]', 13, 10
db '/h Enable hard mode.', 13, 10
db '/u Enable ultra hard mode.', 13, 10
db '/l Display license info.', 13, 10
db '/? Display this help.', 13, 10
db 13, 10
db 'Hello DOSdl is a word guessing game. You have six tries to guess the correct', 13, 10
db 'English word. After a guess the game displays feedback under each letter:', 13, 10
db 13, 10
db "' ' Letter is in the correct place.", 13, 10
db "'^' Letter is in the wrong place.", 13, 10
db "'x' Letter is not in used in the word, or its uses are already covered by the", 13, 10
db ' above cases.', 13, 10
db 13, 10
db 'After the feedback, the game shows a list of letters that have not yet been', 13, 10
db 'ruled out.', 13, 10
db 13, 10
db 'In hard mode all letters marked as being in the correct place must stay fixed', 13, 10
db 'and those marked as being in the wrong place must be reused. In ultra hard mode', 13, 10
db 'letters marked as being in the wrong place must also be moved and letters that', 13, 10
db 'have been ruled out must not be played again.$'
%include "dictionary.inc"
%include "targets.inc"
%include "license.inc"

18
embed-textfile.py Normal file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env python
import sys
srcpath = sys.argv[1]
name = sys.argv[2]
targetpath = sys.argv[3]
with open(srcpath, 'r') as f:
lines = [line.rstrip() for line in f]
with open(targetpath, 'w') as f:
f.write(f'{name}:\n')
for line in lines:
encoded = line.encode('cp437')
if len(encoded) > 0:
f.write(f'\tdb {", ".join(str(char) for char in encoded)}, 13, 10\n')
else:
f.write('\tdb 13, 10\n')
f.write("\tdb '$'\n")

View File

@ -4134,7 +4134,7 @@
"casting",
"dominion",
"angular",
"nancy",
"*****",
"intend",
"monarchy",
"hurry",
@ -4386,7 +4386,7 @@
"compatible",
"obstruction",
"upright",
"fatty",
"*****",
"facial",
"minimize",
"transit",
@ -5464,12 +5464,12 @@
"journalism",
"inverse",
"bailey",
"nous",
"****",
"pathological",
"downtown",
"anticipate",
"collateral",
"quod",
"****",
"foliage",
"locus",
"moss",
@ -5514,8 +5514,8 @@
"gambling",
"decorative",
"sometime",
"anal",
"holt",
"****",
"****",
"assimilation",
"gamma",
"contend",
@ -5740,7 +5740,7 @@
"hymn",
"slain",
"tolerate",
"sperm",
"*****",
"dispose",
"steamer",
"abandonment",
@ -5749,7 +5749,7 @@
"disagree",
"brightness",
"suburban",
"insane",
"******",
"superstition",
"recollection",
"reactive",
@ -5849,7 +5849,7 @@
"cultivate",
"spontaneously",
"certification",
"cortical",
"********",
"polarization",
"everlasting",
"clement",
@ -18322,7 +18322,7 @@
"mesentery",
"adrenalin",
"scrip",
"auxin",
"*****",
"distantly",
"vagal",
"brag",
@ -37946,4 +37946,4 @@
"fullerene",
"doppelganger",
"alloxan"
]
]

28
word_selection.py Normal file
View File

@ -0,0 +1,28 @@
import json
import sys
# https://github.com/lynn/hello-wordl/blob/7da40c1f067eb1ec157d4c5b7a9bd8257ed39342/src/util.ts#L14
def rshift(n, a): return (n & 0xffff_ffff) >> a
def mulberry32(rng_state):
def worker():
nonlocal rng_state
rng_state += 0x6d2b79f5;
t = rng_state
t = (t ^ rshift(t, 15)) * (t | 1) & 0xffff_ffff
t ^= t + (t ^ rshift(t, 7)) * (t | 61) & 0xffff_ffff
return (t ^ (t >> 14))
return worker
with open('targets.json', 'r') as f:
targets = json.load(f)
targets = targets[:targets.index('murky') + 1]
targets = [i for i in targets if len(i) == 5]
rng = mulberry32(int(sys.argv[1]))
while True:
num = rng()
index = num * len(targets) >> 32
print(f'{num:08x}', index, targets[index])
if targets[index] != '*****': break