bgri / m100le Goto Github PK
View Code? Open in Web Editor NEWA Wordle-like game for the vintage Tandy (Radio Shack) Model 100
A Wordle-like game for the vintage Tandy (Radio Shack) Model 100
Add a way for player to see what today's word was (if they want) after the game has concluded.
Just capturing this as an item so we don't lose it.
Perhaps at some point we can consider a way to ask the player if they want to see what the answer was...
Originally posted by @hackerb9 in #10 (comment)
Could be something simple like pressing the [?] key. Right side screen will then show current correct char/positions, with an incorrect/unguessed character revealed.
I was looking into what was needed for the Kyotronic-85 to work. The main thing needed is the start address of the Ram Directory. PEEK(1) on a K-85 is 225, which is how we're IDing the machines in line 2016.
I compared the tokenized BASIC for the K-85 and it seems to be equivalent to what runs on the Model 100/102/200. That makes life easier because we may have one less file format to deal with.
If what I remember from the N82 BASIC manual is correct, one cannot assign to the result of MID$() on the NEC PC-8201. For example, the following works under Tandy's BASIC but I believe it will fail on a NEC:
7341 IF MID$(H$,I,1) = MID$(TW$,I,1) THEN MID$(GW$,I,1) = MID$(TW$,I,1)
It looks like SO$, GW$, H$, A1$, A2$, and WF$ are written to this way. While there are workaround, it would be good to find a method which is not too verbose. Perhaps using an array of strings will work.
Here are all the occurrences which I see in M100LE.DO right now:
5033 IF ASC(MID$(SO$(I),J,1))>=65 THEN MID$(SO$(I),J,1)="*"
7341 IF MID$(H$,I,1) = MID$(TW$,I,1) THEN MID$(GW$,I,1) = MID$(TW$,I,1)
7342 IF MID$(H$,I,1) = MID$(TW$,I,1) THEN MID$(H$,I,1) = "!" :CC=CC+1
7415 IF T<=13 THEN IF MID$(A1$,T,1) <> "*" THEN: IF MID$(TM$,I,1) = MID$(GW$,I,1) THEN MID$(A1$,T,1)="*" ELSE MID$(A1$,T,1)=MID$(GW$,I,1)
7420 IF T>13 THEN IF MID$(A2$,T-13,1) <> "*" THEN: IF MID$(TM$,I,1) = MID$(GW$,I,1) THEN MID$(A2$,T-13,1) = "*" ELSE MID$(A2$,T-13,1) = MID$(GW$,I,1)
8350 MID$(WF$,5) = RIGHT$(AD$,2): 'CREATE THE YEAR'S WORD FILE NAME FROM AD$
From #6:
Since you know that every word is exactly 5 characters, you could omit [CRLF] and have a file that's 28% smaller.
I think I looked at that and disregarded it for some reason. I'll have to check my notes. Maybe time to scan 5 chr. chunks was too long to be practical?
My RNDACC program (issue #15) shows that one could remove CRLF and have fast access. There is still the downside that the file isn't as easily editable since all the words run together, but - at least on the Tandy 200 - the text editor can still handle it.
What the text editor wouldn't be able to handle would be compressing each word from 5 bytes of ASCII to 4 bytes of binary.
Still, sticking with plain text may be the best idea unless the space is absolutely necessary for a spellchecker (#12).
The code I have for handling comments is getting hairy because I forgot about single-ticks within double-quotes. For example,
6015 IF WA=0 THEN PRINT "Error: File '";WF$;"' File not found.": END
That line was getting cut off at the first single tick after the word "File". In the meantime, I've kludged the script to simply pass through any lines with double quotes.
The proper solution would be to write a lexer using flex. Technically, a Context-Free Grammar is equivalent to a regular expression, however, it should be a lot easier to understand and debug.
I was getting ?DS Error
when trying to LOAD the M100LE.DO file. It turns out it has UNIX style line endings (just line feeds). The Model 100 expects MS DOS style — Carriage Return + Line Feed — for DO files.
People who use TELCOM to transfer the file, won't notice a problem because TELCOM silently inserts the carriage return. However, other software will send the file verbatim. The solution to this is to add a carriage return before every line feed. This is easily done (presuming you've got a decent version of sed):
sed -i 's/$/\x0D/' M100LE.DO
Note that I tested the CRLF version with TELCOM and it works fine there, as well.
If your text editor can handle DOS style line endings, you may want to use that for M100LE.DO so that sed
won't be necessary in the future.
[Sidenote: It turns out that, technically, it is the UNIX host I'm logged into via TELCOM that is silently converting LF to CRLF, not TELCOM itself.]
There is a file named M100LE.BA, the BA extension implies that it is a tokenized BASIC file, but it appears to just be a plain ASCII BASIC file, which the Model 100 usually would call a .DO file. It would be beneficial to people if there was a genuine .BA file distributed as it will be much smaller and won't require the user to do the weird "LOAD" then "SAVE" step that is currently required by M100LEl.DO. (Of course, the original M100LE.DO should continue to be distributed as it can be transferred using programs like TELCOM which cannot handle 8-bit files).
I believe the tokenized BASIC for the Model 100 and the Tandy 200 are identical. I do not know about the NEC PC-8201.
I made a mistake (or possibly Wordle changed) and the bugfix I made in commit f8f136b should be reverted. Letters in the secret word which are matched exactly (*) by a letter in the guess, should be removed from consideration when looking for wrong place (?) letters. Or, to word it another way, duplicate letters in a guess should only be marked as ? if there actually is a potential place for them.
Here is how M100LE's current behaviour compares with that of the official NYT Wordle:
XEROX The secret word
FEMME User's guess
.*..? ← Current hint behaviour
.*... ← Correct hint behaviour
However, this bugfix cannot be simply reverted as it did correct one bug. If the secret word does have an unmatched letter, then a duplicate should be shown as right letter, wrong place (?):
XEROX The secret word
EXLAX User's guess
??..* ← Current hint behaviour is correct
?...* ← Incorrect, behaviour from before the bugfix
Neither duplicated letter actually needs to match for this to occur:
XEROX The secret word
EXXON User's guess
???*. ← Current hint behaviour is correct
??.*. ← Incorrect, behaviour from before the bugfix
Allow player to enable saving gameplay analytics to system. Could be things like:
Currently a user has no way to know that the file wasn't created correctly. Since CMPRSS creates the file before writing to it, it should delete the file if writing fails.
Line 8335 is incorrect as it presumes that a FOR loop from 1 to 0 will run zero times. That is true in C, but in BASIC it runs once. The result is that the puzzle for January 1st is for ordinal date 32, the same as February 1st.
Current buggy line:
8335 IF RF<>1 THEN:FOR I = 1 TO CM-1: DY=DY+DA(I): NEXT I: DY=DY+VAL(MID$(AD$,4,2))
Fixed code:
8355 IF RF<>1 AND CM>1 THEN: FOR I = 1 TO CM-1: DY=DY+DA(I): NEXT I
8337 IF RF<>1 THEN: DY=DY+VAL(MID$(AD$,4,2))
8201a ran [RNDACC] without error, though the data displayed when it showed the selected word was incorrect.
Word one in WL2022.DO should be REBUS.
And just to see what happens, I ran it on the 102... RNDACC runs, but can't find the file as 'unusual' data is discovered ... likely due to the offset in line 16 being inaccurate as
PEEK(1)
on the model 102 isn't tested( 167).
Originally posted by @bgri in #14 (comment)
Currently M100LE takes a long time when starting up as it reads through WL20xx.DO one word at a time. I've created a sample program that can instantly find the word by using the Ram Directory to lookup the file's location in RAM.
0 REM RNDACC by hackerb9 2022
1 REM Random access to files in RAM.
2 ' This program can read directly
3 ' from a file without OPENing it.
4 ' When you just need a small bit
5 ' of a large file, this is faster.
6 '
7 ' Files change their location in RAM, moving aside as other files grow.
8 ' Note: EDIT modifies a hidden file, but not the directory pointers!
9 ' CLEAR refreshes the pointers.
10 CLEAR
12 ' HW ID. 51=M100, 171=T200, 148=NEC, 35=M10, 225=K85
13 ID=PEEK(1)
14 ' Ram Directory address. (Anderson's "Programming Tips" gives RD=63842 for M100 and 62034 for T200.)
15 ' (Gary Weber's NEC.MAP gives RD=63567, but we can skip the system files by starting at 63633.)
16 RD=-( 63842*(ID=51) + 62034*(ID=171) + 63633*(ID=148) )
17 ' WL20xx.DO is the wordle wordlist for each day in 20xx.
18 WL$="WL20"+RIGHT$(DATE$, 2)+".DO"
19 ' Search directory for "WL20xx.DO"
20 FOR A = RD TO 65535 STEP 11
29 ' Attribute flag: See Oppedahl's "Inside the TRS-80 Model 100" for details.
30 FL=PEEK(A)
39 ' Stop at end of directory (255)
40 IF FL=255 THEN 300
49 ' X is file address in memory
50 X=PEEK(A+1)+256*PEEK(A+2)
59 ' Add filename all at once for speed
60 FN$=CHR$(PEEK(A+3)) + CHR$(PEEK(A+4)) + CHR$(PEEK(A+5)) + CHR$(PEEK(A+6)) + CHR$(PEEK(A+7)) + CHR$(PEEK(A+8)) + "." + CHR$(PEEK(A+9)) + CHR$(PEEK(A+10))
69 ' Got filename in FN$
70 PRINT FN$, X
80 IF FN$=WL$ THEN 200
90 NEXT A
99 GOTO 300
200 REM Found WL20xx.DO. Now access it.
210 INPUT "Enter an ordinal date (1 to 366)"; DY
220 DY=DY-1
228 ' X is WL20XX.DO's address in RAM
229 ' Format is 5 letters + CR + LF.
230 FOR T = X+DY*7 TO X+DY*7+5
240 PRINT CHR$(PEEK(T));
250 NEXT
260 PRINT
299 END
300 REM File not found
310 PRINT "Error: File ";WL$;" not found."
320 END
The code is overly garrulous for clarity. It could be much shorter if implemented in M100LE.
It would be good to consolidate information for developers who want to modify or extend M100LE in the future.
16 MD=1
manual date entry37 A1$="ABCDEFGHIJKLM": 'ALPHABET BOARD
38 A2$="NOPQRSTUVWXYZ"
8350 MID$(WF$,5) = RIGHT$(AD$,2): 'CREATE THE YEAR'S WORD FILE NAME FROM AD$
As mentioned in issue #15, European models may format DATE$ differently than the American MM/DD/YY, so any code that uses RIGHT$(DATE$,2) for the year would be wrong.
Here are the models which may have a different DATE$
PEEK(63548)+10*PEEK(63549)
According to https://www.nytimes.com/2022/11/07/crosswords/wordle-editor.html, the NYT Wordle Game now has a human editor. I do not quite understand why that was seen as necessary, but the upshot is their wordlist has diverged. I do not yet know if the new wordlist is downloadable. Here's an excerpt from the article:
Tracy Bennett, who joined The Times as an associate puzzle editor in 2020, will be the editor of Wordle. The game will have a Times-curated word list and will be programmed and tested like the Spelling Bee and the Crossword.
Wordle’s gameplay will stay the same, and answers will be drawn from the same basic dictionary of answer words, with some editorial adjustments to ensure that the game stays focused on vocabulary that’s fun, accessible, lively and varied.
The answer list will consist of five-letter words that fit those criteria, with the exception of plural forms of three- or four-letter words that end in “ES” or “S.” That is, the answer will never be FOXES or SPOTS, but it might be GEESE or FUNGI. As the game is currently designed, FOXES or SPOTS can be used as a guess word to help narrow down the answer, but FOXES or SPOTS will not be the answer.
I dislike it when modern apps asks me to put an unnecessary zero in the date in a misguided attempt to placate the computer. Doing menial work like that is what makes computers happy. Let's not take their jobs away by teaching humans to adapt to computers.
I think at some point I should fix M100LE so that various date formats can be recognized. However, that might not come until after version 0.m is released as the code needs to be trimmed down in size. I'd only do it beforehand if the fix saved more space than it uses. I doubt that'd be the case, because I have to remember to put the year first for the NEC portables.
The date formats I'd like M100LE to accept
-
instead of /
(MM-DD-YYYY)By the way, once sloppy date input is implemented, I do not think it would need to be documented as a "feature". In fact, we could remove some of the documentation that currently warns about always aligning the date.
Both 02/29/2024 and 03/01/2024 choose the 60th word in WL2024. The 366th word is only available by setting the date to 12/32/2024.
Just an idea.... There is currently a minor inconvenience in loading eight different files just to have the full game on the computer. Additionally, the [R]ANDOM option only picks words from this year.
It won't work everywhere, but on a machine with sufficient RAM (like my Tandy 200 with 24K), it is possible to load the crunched version of M100LE.BA (6K) plus all seven years of words (8K) and still have enough RAM free to play the game (about 5K).
Perhaps we should look into how the wordlists can be (optionally) merged.
Before the next release, it would be good to update the README.md file. I do not think it will require much.
I had an idea for how one could create a spelling dictionary by using a hashtable but not storing the words themselves, just a bit vector. There'd be some false negatives (bogus words that happen to hash to a valid word), but the chances are low if the vector is large enough. Normally a large vector would be a problem for limited memory, but since it would be sparse, it should be easily compressible.
Turns out someone beat me to... by forty years. There's an IEEE paper from 1982 by Doug McIlroy which lays out how he managed to fit a spell checker for 30,000 words (250 kilobytes) in a 64 kilobyte machine. From the abstract:
Stripping prefixes and suffixes reduces the list below one third of its original size, hashing discards 60 percent of the bits that remain, and data compression halves it once again.
So, potentially, hashing and compression could cut the wordlist down to a quarter of the size.
It appears Wordle uses a 13,000 word (72 kilobyte) list of what it will accept. Even a quarter of that, 18 kilobytes, is still rather large for a Model T, so it may make sense to use a smaller corpus.
SCOWL makes it easy to create a list of the most frequent five letter words. For example, here is a list of 7,000 words (35 kilobytes), but the size is flexible since the words are partitioned into frequency bins.
Alternately, one could use SCOWL's list of least common words and subtract them from Wordle's list, that way unusual words that Wordle knows about but SCOWL doesn't will be kept. Here's a list of 7500 words (44 kilobytes) created that way.
Currently, M100LE takes up about 8KB of storage (for the program and one year's worth of words). I do not know how much RAM is required at runtime, but I would not expect it to be more than a kilobyte. On a Model 200, which has only 19KB of RAM free for BASIC to use, That'd leave about 10KB for a wordlist to be stored plus the extra code to access it plus any extra RAM usage.
I believe, but am not sure, that, since files are actually already in RAM, a BASIC program can access the data without having to load up a second copy into memory. If so, it would be tight, but possible!
Program logic mixes symbols and cap. keys when caps lock key is ON.
Workaround: keep caps lock key off.
Fix in the works for next release.
@bgri wrote:
I was thinking of 'reverse video' initially [for Right Letter, Right Place], but dismissed it as I couldn't be consistent with the ones that were 'right letter, wrong place'.
Rapidly display and erasing is a good option. Maybe flipping between 'normal' and 'inverse' for those, or I'm also thinking maybe switching between proper letter and 'grey' box:
I guess it all depends on what they look like on the hardware. Emulators are one thing...
Originally posted by @bgri in #29 (comment)
Tried running the code on Virtual T's emulated M10 device and it gives a ?DS error just from running the program. Doing "CLEAR 512" seems to solve the problem. Of course, we'll need the Ram Directory address for this machine (35) as
well.
I believe the official version of Wordle will tell you what the answer was if you are not able to guess it. M100LE does not say anything but "SORRY". Was this intentional?
As of today (August 16, 2022), the word M100LE offers is behind the NYTimes by sixteen days. I believe this is because the NYT removed the most obscure words (like "AGORA") and words which are emotionally charged for some people ("LYNCH", "SLAVE"). Some words were moved to the end of the list ("FETUS").
Currently, if the correct letter is guessed in the right place, it will be shown only in the CLUES box, but appears as an asterisk in the ALPHABET box.
It would be nice if correct letters were shown in reverse video:
This could be done by making A1$
and A2$
include the escape sequence for "normal video" (Escq) before each letter. Then the letters which have been found can have the preceding q changed to a p for reverse video.
As mentioned in #6, the main thing missing aesthetically right now is slowly flipping over the letters when you win to give a sense of anticipation before the word "CONGRATS!!"
After adding in the DATE$ portability, the tokenized BASIC version takes up over 13KB of space. Not a big deal since the smallest machine we're likely to see is 24KB, but it could be improved.
Note that 13KB is the version with comments that could be removed for some space savings during tokenization. It might be a good idea to come up with a convention for lines with comments that should not be removed because they are targets for GOTO or GOSUB and lines which can be completely removed. Perhaps something like this
10 REM Lines that start with REM should never be removed
11 ' But comments using apostrophe mean the line isn't necessary
12 ' for the program to run correctly.
It would be good to go through the code again, with an eye towards minimizing it while still keeping it understandable.
Need to check logic for 'sorry' message on last guess (GN=6)
The Tandy computers use PRINT@
while the NEC computers use LOCATE
. However, both of them understand VT52 style escape sequences to position the cursor. It's a little more complicated but is something like:
PRINT CHR$(27) + "Y" + CHR$(32+row) + CHR$(32+column)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.