Saturday, 11 March 2023

"Doctor Who Adventure" Jeremy Guggenhiem (1983)

In a 2000 post, Jeremy Raynor claimed that this is the first ever Doctor Who computer game. It took the form of a 3 page of listing in the March 1983 edition of the British magazine Computer and Video Games. Like Jeremy I typed it in.  However, as I did so I converted the code to Micro Color BASIC from the original Atari 8-bit BASIC code. The original version seems to have had a creeping memory fault, which eventually corrupts the redefined character set, used in the game for all the onscreen graphic objects. Jeremey asked if anyone out on the Net, who was good at debugging BASIC, could figure out the problem. I think I have.

There were lots of un-RETURNed GOSUBs. A central room movement handler routine called by the main loop would GOSUB to the various different room description and character movement subroutines. But then sometimes Guggenhiem would use a GOTO to return back to the main loop, other times the room handler would be called *again* by room character movement routines when the player left those rooms. This would leave GOSUBs uncompleted or add further GOSUBs (recursively using the room handler jumping routine again). The stored memory addresses for each RETURN would pile up in stack memory somewhere.  Eventually that stack would accumulate enough unhandled addresses that it would begin to cannibalize the area of memory used for the redefined characters. Guggenhiem himself was aware of the problem and in the original article said it could occur after "15-50 games," but he couldn't figure out what caused it.

It is strange that it would occur across multiple games because Guggenhiem uses RUN to restart the program at the end of each game.  However, he also redefines some variables at the end before issuing the RUN command so I suspect that Atari BASIC doesn't necessarily clear all memory and variables back to null when a RUN is issued. Perhaps some special clearing command needs to be issued to get a true cold start. This is different from Microsoft BASIC where RUN reinitializes pretty much everything (string spaces, numeric variables, FOR loops and their return address, GOSUB calls and their addresses,  etc.)

I basically had to resolve this problem by getting rid of the use of GOTOs to jump back to the main game loop.  Instead, what I did was create a kind of pseudo "recursion" feature in the main program loop which calls the room handler (itself a subroutine).  When the room handler routine GOSUBs to a different room routine it increments a counter.  Then instead of jumping directly back to main loop, if that subroutine calls the room handler routine again to go to another room, the counter gets incremented.  An IF statement checks after each call to the room handler routine.  If the counter is not zero a RETURN is issued.  This will return the program to the room handler routine.  That routine then decrements the counter and issue a RETURN (which takes it back to the room handler again) until the counter is zero.  At that point a final RETURN is issued returning control the main loop, which had made the initial call to the room handler.  At that point all the RETURNs have been cleared, and a fresh call is then made to the room handler routine to put the player into the correct new room.  New calls might be made from that routine (an attempt at recursion) but each time a return is issued a cascade is triggered eventually returning control to the main loop, allowing for a fresh call to the room handler and the next desired room.  All this had to be done to eliminate the use of GOTOs and prevent any buildup of unresolved recursive calls to the room handler subroutine.

I made a few changes to the game to make it more in keeping with my understanding of the character of the Doctor. The original game called for the use of a ray gun to kill the Master. My understanding of the Doctor is that he never uses violence (God love him).  So I changed it so that the ray gun is "broken."  The player must figure out what to do with it so that the Master will end up trying to use it against the Doctor, resulting in its malfunction, which will kill the Master by his own hand.  Similarly, the player must avoid the deadly snake rather than kill it and find a way to ward off the deadly Sphinx rather than kill it.  I've added one red herring item to slightly increase the complexity of the puzzle.  Mishandling that object adds to the dangers that the Doctor' must face in the already dangerous maze/pyramid he is exploring.  I also added a rogue/lost Dalek to the monsters that must be faced.

Of course, instead of character graphics as in the original, I had to create new semigraphic images using semigraphic 4 characters. These take the form of 2X2 character blocks (4X4 semi-graphic pixels), which makes for a 16X8 map screen.  I think the Atari game used some kind of double-width character mode, because it seems to run on a 19X21 grid, so the difference between the two screens is not too great. The countdown clock is just a decimal variable decrementing counter used by all routines.  I had to shorten some of the messages because of the smaller screen of the MC-10.  Messages are printed in the "wall" spaces, since there are no spare lines at the bottom of the screen as in the Atari version. I used Greg Dionne's key PEEKs to get 8-way movement from the AWSZ keys used singly or in various combinations with each other.

Contrary to what Rayner suggests, this is not the first Doctor Who game. I have converted a text adventure by James Smith from 1982:

But it is perhaps among the earliest. It's a fun little graphic puzzle game with some minor arcade elements.  Actually, I find it hard to characterize its genre exactly. I wonder whether it is an early example of a hybrid genre of graphic-puzzle-adventure games.  There is definitely a story, including a detailed backstory from the original article, but also the story unfolds in the game itself as the puzzles are solved and the graphical "dungeon" (pyramid) is explored. So I didn't know whether to put it in my "Arcade", "Text Adventures" or "Puzzles" subdirectory.  But I eventually decided all the movement and visuals, and need for some quick reactions make it more of an arcade-style game. Certainly the use of the joystick in the original speaks in favour of this conclusion. In any case, here is the directory where the source can be found:

https://github.com/jggames/trs80mc10/tree/master/quicktype/Arcade/DocWho

The game be can played online using a TRS-80 MC-10 emulator here: https://archive.org/details/@james_gerrie

Saturday, 18 February 2023

"Gin Rummy" by S. Silverman (1980)

This one is a bit of a mystery.  I went looking for some early source of a Gin Rummy game.  I wanted to add this popular card game to my list of early attempts at BASIC AI opponent programming.  I first stumbled across a reference to a game for the Atari called Gin Rummy 3.0.  by Manhattan Software.  Some sites, such as the Giant List of Classic Game Programmers, designated the programmer as S. Silverman.

I have found converting programs from Atari BASIC difficult in the past. The emulators are complex and the BASIC is somewhat different from Microsoft versions of BASIC.  So I went looking for something by Silverman or Manhattan Software for the TRS-80.  This lead me to some BASIC source for Gin Rummy 2.0, which I was able to convert fairly easily to TRS-80 Micro Color BASIC.  The TRS-80 Model I/III has a 64X16 character screen so conversion mainly involves taking PRINT@ screen location values and dividing them by 2. That gives you the rough equivalent for the PRINT@ value for the MC-10's 32X16 screen. Then all you have to do is condense the length of messages by about a half to get everything to fit on a MC-10 screen.

Here is the TRS-80 Model I/III main screen:

Here is the TRS-80 MC-10 main screen:

You can see how the prompts have been shrunk.  Also, the representation of the cards was switched from full text descriptions to two characters.  The face cards become letters, as does the ten and Ace, which become "T" and "A" respectively.  Otherwise the values are simply a number. The suits also just become single characters.  I separate the two with the standard suit colour of red or black character to help identify the suit and to separate the card value from the suit more clearly.  This is a much shorter way to identify the cards, which really helped with the confined screen space of the MC-10.

The real problem came with the program itself. The program contains a large number of unclosed FOR/NEXT loops.  Silverman uses multiple such loops to do searches of the hands, and then simply jumps out of them when some sought after value is found. The program then just continues execution by GOTOing to some location after the FOR/NEXT routine.  However, in one place (600-740) the author actual goes from in the midst of two nested FOR loops, to a subroutine and then GOTOs back to the NEXT of the calling loop.  It does this in two different FOR/NEXT routines.  To continue those routines it uses an IF to GOTO back to the NEXTS of the different calling routines. Or if a search item is found it simply continues with execution after those routines and the subroutine. All these crisscrossing FOR/NEXTs get the Micro Color BASIC interpreter confused.  Especially if it comes across a NEXT that doesn't have a specific variable attached to it. So occasionally I would get a NEXT without FOR error, which indicated that the interpreter was putting the program back into the midst of the inner loop of the nested FOR/NEXTs, but without initializing the outer FOR, perhaps because that loop and its variable had been reinitialized elsewhere in the code's meanderings.  It was a real mess.

So I tried to add proper exits to some FOR/NEXTs in a few places where I though this would help. I also entered in a few dummy loops at the start of the offending section of code. This is a way to ensure that all the FOR/NEXTs get reset before they are utilized again. Finally I put the appropriate variable on every NEXT command in the program, so there is no possibility for a NEXT to trigger a return to an unclosed loop. By doing all this I was able to eliminate the error and I was able to remove an ON/ERROR kluge command that Silverman had obviously used to recover from the error.

590 ON ERROR GOTO 600
600 RESUME 610

There was also a simple typo in a FOR/NEXT loop:

3360 FORX=(C+1)TOO111

I changed this to 3360 FORX=(C+1)TO11, as 11 was common search value.  O111 would just be interpreted as an undeclared variable and simply return a zero.  So the loop would only be run once.

It was Greg Dionne who let me know about this bug, after I asked folks on the Facebook group for the MC-10 to have a look at the program.  He used his BASIC compiler to check for undeclared variables.  I had noticed before he made his bug report that sometimes the program would miscount the melds in my hand. Occasionally, a meld of 4 items like JH,JD,JS,JC would only count three of the items (It might also have done this on a 3 item meld but I can't precisely recall if this was something I spotted early in my testing or not).  I had hoped that Greg's fix would be the fix to this problem, but after much play testing it occurred again on a 4 item meld of Jacks.  It only happens very occasionally. I've checked the code for typos I might have entered, and don't think it is a result of any change I made. I  think it might be related to the special search (See the REM about "hidden meld") for whether a card is playing a role in a meld or a run. That is to say, the program has to distinguish between if you are using a card, say one of the jack's above, as part of a run, rather than as an item in 4 meld.  It certainly can count 4 item melds, but I need to generate multiple game conditions where I can test this hypothesis, which takes a long time.  And the code is so spaghetti that it is really difficult to get a sense of what is going on. It's also possible that a rule I'm simply unaware is what is causing the problem, or some nuance in the code conversion that I have overlooked.  I'll have to play the original TRS-80 on an emulator to see if the error occurs there too.

In any case, I've created a kluge work-around.  If on the SCORE SHEET screen you type 'C' at the "Another Hand" prompt you are given a chance to type in new values for the final scores for the player and the computer that are listed. That way, if you notice the error, you will at least have an opportunity to make a manual readjustment to the scoring tally and keep playing.  I think Silverman might have been aware of these errors and worked to fix them.  You can see the program being modified to work on different computer systems, but also increasing in version number.  The TRS-80 version is labeled 2.0." The Atari version is labeled "3.0."  And there appears to be a PC version labeled "4.0."

TRS-80 Version Ad

Atari Version Ad


I hope that I might be able to figure out some day how to get my hands on the Atari source code for 3.0. Then I could look through some of the search routines for analyzing the hands for changes to the code.  I have searched but can't find any copy of the PC version.  I might also continue to search for the bug myself.  But in the mean time, I would still agree with the rhetoric of the ads that Silverman's code does play "a strong game," and thus represents an interesting part of early BASIC AI opponent programming.  Of course that is an assessment of someone who'd never played Gin Rummy before this porting exercise.  So I only have Gin Rummy 2.0 as teacher (and some reading on Wikipedia) upon which to base my assessment.

"GINRUMMY" can be played online using an MC-10 emulator(just search for the program name): https://archive.org/details/@james_gerrie

P.S.
I went back and added a few more dummy FOR/NEXT loops just before the hand checking routine.  I'm not sure if this might have fixed the problem with rare miscounting melds, but I haven't seen any for some time.  I also added colourful graphic cards that somewhat emulate the cards which can be seen on the Atari version.  I have changed the version number to 2.5 to reflect this slight updating.  I also fixed up the Score Sheet screen to format the numbers properly via right justification.  The original used the PRINT USING command, which I had to emulate by the use of STR$(num var) and RIGHT$ commands to get things properly lined up.  Here's a vid of the new look:


I also think I might have stumbled on a possible explanation of the miscounting of melds.  The computer seems to prioritize RUNs over melds in its analysis of hands, such as can be seen in my hand in the following pic of the computer achieving Gin!  I might not have recognized this in my early play  testing as I was still learning the game.  

And I think I found some other bugs in the program.  The routine that prevents you from discarding the upcard you picked up before knocking, didn't do the same variable resets before returning you to line 80 as other checks did (e.gs. knocking with more than 10, lying about your knock points).  This seemed to cause some catastrophic weirdness.  So I changed it to mimic the resets of the other check routines.  Also, you can now type -1 at the discard prompt after knocking, to back out of that routine.  I found that I could knock right at the start of the game and it would allow me to discard any card and input any knock count under 10, and then reward me with 25 points, even though it reported that my unmatched cards and the computer's were both zero.  So I made a distinct check for this condition, and then display the warning that you have knocked with more than 10 knock points. It then does the resets and returns you to your hand.

Computer Got Gin!


Me Got Gin!

P.P.S.   I did catch the game miscounting melds again.  I had 3 aces, which the computer simply ignored in its count.  My new hypothesis is that the error may have something to do with the discarding of the 11th card.  In this case I might have had 4 aces, and been forced to discard 1.  Then something in the counting of this 4-meld and then the checking for the possible use of 1 of the cards in the meld being used instead in a run goes wrong.  Somehow the re-check for the 3-meld does not get done correctly.  I think what happens normally is that melds are found first, then runs, but if knock counts are different, then 4-melds are blanked, and then checks for runs are done again.  Then the meld checks are done again.  Or something like this.  But something is screwing up in very rare circumstances, and I think what makes them rare has to do with the 11th card (the one the player is forced to discard when they knock).  Which raises another issue, I'm unsure how 11-card Gin is handled for the player.  There is a message and a flag variable for the computer getting such, and some code to display the 11th card, but there doesn't seem to be anything like this for the player.  Sadly, I think I will have to leave this one with some extant errors.  I've created a special version GINRUM25_15.TXT that prints an error message and returns you to your hand if your knock count doesn't match with the computer's check of your count.  This will give me some ability to re-try after moving cards around.  But I don't think this will help much as the checking routines probably check the cards in their original slate orders of value and suit (by way of pointers) rather than the actual cards of the player's hand.

Friday, 10 February 2023

Programs for 2023 10Liner BASIC Contest

I have created three programs for the BASIC 10-Liner contest using Micro Color BASIC for the TRS-80 Micro Color Computer aka the MC-10.

SMASHUP (for PUR-120)

This program is a simple simulation of a smashup derby. You are the green car. The aim of the game is to hit the other cars.  Unless you are willing to risk driving head-on in the hope that your move/turn is timed as the last before the two colour blocks connect, the best strategy is to try to hit the other colours from the side as they pass in front of you.  this takes good timing.  If your timing is off and you drive in front of the oncoming colour block, then it hits you and you lose a life. 3 hits and you're out.  But if you hit the other car you get a point.  There is a time limit.  Your score is the number of hits achieved within the time limit.  A high score is displayed and you can then choose to play again.

Movement Keys: AWSD

VOLCANO (for Extreme-256)

This program involves flying your helicopter over a erupting volcano to retrieve a trapped person "Y" on the other side of the volcano.  Avoid the rocks flying out of the volcano. You can only take 3 hits, then you are dead.  Land on top of the victim to collect them.  When you do so, another person will appear on the other side of the island.  You must fly back and retrieve them. Continue to collect as many people as you can.  You must be careful when landing. The ground will not stop your descent. You must land gently and not simply hit the ground relying it to stop your descent.  How many people can you save before your craft reaches its limit?  Lives are printed in the bottom right.  Your score will be printed next to your helicopter after your last hit.

Movement Keys:  WASZ

Each game can be played here: https://archive.org/details/@james_gerrie

Here are the program listings:

SMASHUP

0 DIMT,L(8),D(8),V(8),C(8),R,I,J,K(255),H,Q,V,M:V(1)=-1:V(2)=-33:V(3)=-32:V(4)=-31:V(5)=1:V(6)=33:V(7)=32:V(8)=31:GOTO7
1 SOUND100,1:S=S+1:PRINT@480,"SC"S"HI"HI;:ON-(S<HI)GOTO5:HI=S:PRINT@480,"SC"S"HI"HI;:GOTO5
2 POKE49151,64:POKEL(T),134:L=L-1:PRINT@496,"LIVES"L;:POKEL(T),137:SOUND1,1:ON-(L>.)GOTO5:GOTO6
3 Q=2:FORV=1TO350:FORT=.TO7:IFPEEK(L(T)+V(D(T)))=.THEND(T)=RND(8):GOTO5
4 POKEL(T),H:L(T)=L(T)+V(D(T)):I=PEEK(L(T)):IFI>HTHENIFT=.ORI=RTHENON-(T=.)GOTO1:GOTO2
5 POKEL(T),C(T):NEXT:D(.)=K(PEEK(Q)ANDPEEK(J)):NEXT
6 FORT=1TO10:SOUND99,1:NEXT:PRINT@496,"TRY AGAIN?";:FORI=0TO1STEP0:Q=ASC(INKEY$+CHR$(0)):I=-(Q=89ORQ=78):NEXT
7 CLS:PRINT@452,"smash up! BY JIM GERRIE":V=32:H=128:I=16:J=17023:R=143:K(65)=1:K(68)=5:K(87)=3:K(83)=7:S=0:POKE16925,0
8 POKE16926,1:M=16384:FORT=MTOM+479:POKET,.:NEXT:FORT=1TO13:?@V*T+1,"€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€";:NEXT
9 FORT=0TO7:D(T)=RND(8):C(T)=R+T*I:NEXT:FORT=0TO7:L(T)=M+261+3*T:POKEL(T),C(T):NEXT:L=4:ON-(Q<>78)GOTO3:END
10 REM                                                                                             1         1         1
11 REM   1         2         3         4         5         6         7         8         9         0         1         2
12 REM789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
13 REM smash up! JIM GERRIE
14 REM 2023 10-LINER CONTEST
15 REM USE: W
16 REM    A S D
17 REM YOU ARE THE GREEN CAR.
18 REM SMASH INTO THE OTHER
19 REM CARS, BUT DON'T LET
20 REM THEM SMASH INTO YOU.
21 REM THERE IS A TIME LIMIT.

VOLCANO
0 CLEAR500:CLS:T=0:A=28:B=12:M=16384:FORT=1TO192:S$=S$+"":NEXT:D=1:V=32:G=17023:L=V*B+A:N=L+M:Z=RND(3):J=48+4:X=60:E=3:W=2
1 C$(1)="‚‡":C$(3)="‹":D$(1)="€‰":D$(3)="†€":Z(1)=16801:Z(2)=16651:Z(3)=16742:J=J-1:POKEM+511,J:SOUND1,2:IFJ<49THEN?S:END
2 ?@.,S$"Ž•ŸšŽÑߟßҍŽÑ¿¿Ÿ¿¿„ˆÓÓÓ¿¿";
3 ?"¿Ÿ¿¿¿Òˆ×¿¿¿¿¿¿Ÿ¿¿¿¿ÓŒˆ×¿¿¿ÿÿÿÿŸÿÿÿ¿¿Û„ŒˆÓÓ׿¿ÿÿÿÿŸŸŸŸŸÿÿ¿¿¿»Ò";
4 ?"ˆ×¿¿¿¿ÿÿÿÿŸŸŸŸŸŸŸÿÿÿÿ¿»„ÓÓÓÓ׿¿¿ÿÿÿÿÿŸŸŸŸŸŸŸŸŸÿÿÿÿ¿»£¢£¡¿¿¿¿¿¿¿ÿÿÿÿÿŸŸŸŸŸŸŸŸŸŸŸÿÿÿÿ¿¿ª¯";:POKEZ(Z),89
5 FORT=1TO5:X(T)=X(T)+A(T):Y(T)=Y(T)+B(T):IFX(T)<.THENX(T)=.
6 IFX(T)<EORX(T)>XORY(T)<2ORPOINT(X(T),Y(T))<>1THENX(T)=33+RND(8):Y(T)=8+RND(E):A(T)=W-RND(E)*(1+RND(.)):B(T)=W-RND(E)*1.5
7 RESET(X(T),Y(T)):NEXT:P=PEEK(N)+PEEK(N+1)+PEEK(N+V)+PEEK(N+33):C$(W)=C$(W+D):D$(W)=D$(W+D):?@L,C$(W);:?@L+V,D$(W);
8 K=PEEK(W)ANDPEEK(G):D=(K=65ANDA>.)-(K=83ANDA<30):A=A+D:B=B+(K=87ANDB>.)-(K=90ANDB<30):L=V*B+A:N=L+M:IFP=572THEN2
9 ON-(P<>518)GOTO1:Z=RND(E):S=S+1:?@.,"SCORE"S:SOUND99,1:FORT=1TO2000:NEXT:Z=.:Z(0)=16829:ON(1ANDS)GOTO2:Z=RND(E):GOTO2
10 REM                                                                                             1         1         1        
11 REM   1         2         3         4         5         6         7         8         9         0         1         2        
12 REM78901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
13 REM VOLCANO RESCUE
14 REM BY J.GERRIE
15 REM 10LINER CONTEST 2023
Both programs use PEEK and POKES to place the player objects on the screen and to check for collisions between objects.  Key sensing is also achieved using PEEKs for speed and for continuous input sensing rather than the single key press sensing of INKEY$.

Volcano uses a large number of PRINT statements with the graphic of the volcano to refresh the screen.  It also uses the RESET command (line 7) of Micro Color BASIC to plot the exploding debris from the volcano.  The POINT command is used to determine if a RESET space is clear.

In both programs ON-(A=B)GOTO2 constructs are used instead of IFA=BTHEN2 to allow for multiple  branches to be packed onto a single line.  For example see the end of line 9 in Smashup.


ERII (for SHAU category)

This program simply presents a memorial image of her Majesty Queen Elizbeth the Second. It uses a special screen mode of the MC-10 to get 9 colours rather than the regular 8.  One of those colours works better as a skin tone. This program is for the SHAU category.

0 CLS1:DIMC1,C2,M$,M:M=16384:GOTO2
1 C1=(PEEK(17024)AND1)*256+PEEK(17025)-1+M:FORC2=1TOLEN(M$):C3=ASC(MID$(M$,C2)):POKEC1+C2,C3-(C3AND64):NEXT:?@C1-M+C2,:RETURN
2 PRINT"¯¯Ÿ¯£    £¯¯¯¯¯­Ÿ¯¯¯¯¯¯¯¯¯¯¯®¯¯«¯¯¬¬¬¬¬¬¬­¯¯§¯";
3 PRINT"ß߯¯¯¯¯¯¯¯¯¯¯ßßߏßßßß ßß    ß߀ßߏß߀   Ï€    Ï€€ß";
4 PRINT"ß€   ÿÿ    ÿÿ€Ï€          €€       ÿ  €";
5 PRINT"€  ÿ       €€  ÿ ¿¿¿¿  €€    ¿¿¿¿  €";
6 PRINT"€  €      €€Ï      €€¯Ï €€€€";
7 PRINT"€¯¯ÏÀ";:POKE49151,64:PRINT@32*7+22,;:M$="GOD BLESS":GOSUB1:PRINT@32*8+22,"elizabeth";
8 PRINT@32*9+22,;:M$="    II   ":GOSUB1:PRINT@32*10+22,;:M$="1926-2022":GOSUB1
9 M$=INKEY$:ON-(M$<>CHR$(13))GOTO9:CLS0:SOUND1,1:CLS:END
10 REM                                                                                             1         1         1        
11 REM   1         2         3         4         5         6         7         8         9         0         1         2        
12 REM78901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
13 REM ELIZABETH REGINA II
14 REM BY J.GERRIE
15 REM 10LINER CONTEST 2023

Tuesday, 7 February 2023

The Day Type-in Mania Died: Joseph Roehrig's Scrabble (1981)

I recently worked on typing in a program from BYTE Magazine. It was for a Scrabble game "simulation"/AI opponent.  From the article accompanying the program you could tell that the author Joseph Roehrig was very proud of his creation.  Working completely in BASIC he had managed to create an AI opponent for a very complex game.  He had also created a version specifically for the TRS-80 that loaded as one file (i.e. could work from tape), only required a 32K machine (the oncoming standard replacing the 16K and 4K base versions first produced in 1977), and included a dictionary of over 700 words.  Compromises had to be made for the sake of speed and storage.  He limited the AI opponent to using only 2 and 3 letter words. There were other compromises made in terms of search rigor, and also you could choose a FAST game that lowered these standards even further.  But it could play a basic game that certainly might challenge a kid or maybe neophyte players (it's hard for to tell as I'm a neophyte).

The year of 1981 was still firmly a year of the "type-in mania" early informal 8-bit computing period.  Lots of home coders were making programs and sharing them with the wider world.  The period of selling cassette tapes from home sold in a plastic baggies with some simple reproduced documentation folded in was still a reality, exemplified by Scott Adam's Adventure International company.  At that point his "company" was essentially him and a loose group of collaborators.  However, by 1983, the company had become a proper software company and had a location and 40 employees (by 1986 it would be bankrupt).  It was somewhere in that period that computing pivoted from a do-it-yourself hobby, to an industry overseen by organized corporate actors serving clients.  In researching about Roehrig's program in subsequent issues of BYTE to check for possible bug reports, I cam across the following letter:

We were pleased to see an article discussing the feasibility of a computer opponent for Selchow & Righter's popular Scrabble word game (see "Computer Scrabble," December 1981 BYTE, page 320). Others who are intrigued by this concept will appreciate knowing that the state of the art in microcomputer Scrabble has made a great leap forward. It is far beyond the boundaries that Mr. Roehrig tells us will not be broken by anything less than a new, superior generation of microcomputers.

"Monty plays the Scrabble Brand Crossword Game" (a computer-opponent program available on disk for the Apple II and TRS-80 Models I and III from Ritam Corporation for $39.95) demonstrates both speed and ability, within the constraints of today's microcomputers. Monty spends an average of only 4 1/2 minutes per move at the highest skill level, and yet it uses an extensive word list (over 50,000), based in part on the Official Scrabble Players Dictionary. 

As for memory, the program requires no more than 48K bytes for Apple and 32K bytes for TRS-80 versions, much of which is ,devoted to machine-language graphics, music, and other user-interface requirements. The dictionary is accessed from disk and is stored in an average of only two bytes per word (with an average length of 6 or 7 letters) by use of advanced compression techniques. In addition, Monty is capable of challenging other players' words, based on linguistic analysis, without accessing the disk.

To give Mr. Roehrig's efforts due credit, the "game's complexities" do offer a challenge I It took us several major design breakthroughs, over four man-years of programming (for three different computers), and a lot of determination to develop "Monty plays Scrabble" without conceding to "certain constraints" on word length, search, and placement.

Although his conclusion that "improved computerized Scrabble will require a faster host computer with more memory capacity" has been disproved by example, we thank Mr. Roehrig for his article. It makes our endeavor seem quite worthwhile when we learn that we've achieved the impossible!

By the way, Mr. Roehrig neglected to properly acknowledge that Scrabble is a trademark of the Selchow & Righter Company, and to disclaim, as does Ritam, any sponsorship or endorsement by Selchow & Righter.

Robert Wall
Ritam Corporation
POB 921
Fairfield, IA 52556

* Scrabble is a registered trademark of Selchow & Righter Company. We apologize for not acknowledging this in a prior article ... MH 

(BYTE: Small Systems Journal, April 1982 Vol 7 No. 4., p. 20.)

This letter perfectly exemplifies the transition. The condescension is palpable.  You can sense the hand of Ritam Corp. patting poor Mr. Roehrig on the head for a his "good effort."  But the message is clear-- real programs require many "man-years" of programing using a real language like Assembly, and not a kiddie language like BASIC.   

The fact that I can't find anything else on the Net about Mr. Roehrig's program indicates his efforts were not rewarded with sales of his own via plastic baggies and reproduced sheets of paper documentation.  Around this time people started buying disk drives in North America and purchasing their programs from stores. There would still be a brief sunset for folks like me, getting our first machines in 1984, to "do it yourself" (my MC-10 cost $79.99 just twice the price of Ritam's $39.99 Scrabble program).  But if you had more than lawnmowing money, you wouldn't have to tarry with the type-in age very much longer. The software industry was on the march.

To make the program work on MC-10 I had to switch some of the larger two-dimensional numeric array's to string arrays.  Since the program only stored 0s or 1s in these two-dimensional matrixes, using strings and string operations like MID$ to look horizontally meant each "item" only will take a single byte to store.  This is much better than the 5 bytes needed for each floating-point numeric item in a numeric array. The TRS-80 Model I/III has a DEFINT command that allows such variables to be designated as INTs, saving memory, but the MC-10 only has floating point. But by making this change  to string arrays and searching and replacing multi-character variable names (some had more than 6 character long names!) to single character variable names allowed me to get the program to work in 20K.

Hopefully all this also speeds up the searches for the computer's move. Roehrig mentions that some of them can take over 15 minutes.  It's hard to tell how speed will translate from the TRS-Senior to the MC-10.  The Senior has a higher clock speed, but the MC-10 has a later more efficient version of Microsoft BASIC.  It also uses a Motorola MC6803 rather than the Senior's Z80.  My sense is that the MC-10 is normally faster.  A sign of this is that the standard delay for displaying a brief message on screen on the TRS-Senior is FORDL=1TO1000:NEXT, whereas for the MC-10 you need FORDL=1TO2500.  But who knows.  Perhaps the string array searches and string manipulations will trigger lots of garbage collection, which can slow things down.  I did most of my testing using the 8X normal speed mode of the VMC10 emulator.

If you have the patience and interest in seeing an old early BASIC AI at work, SCRABB2 can be played online using an MC-10 emulator (Just search for "SCRABB2"):

https://archive.org/details/@james_gerrie

The TRS source ("SCRABB2TRS80.TXT") and the source for my MC-10 version can be found here:


TRS-80 Model I/III Version

The original game used a system of numbers (1-225) listed on the TRS-80 Model I/III screen, that you typed in to enter words. I switched it to using arrow keys to move a cursor and added the color markers for word and letter bonuses to allow it to fit the smaller screen of the MC-10 and to ease use for those playing it online today.  I also added some checking to prevent errors if you try to enter characters other than letters.

Thursday, 12 January 2023

"Astronave Farmer" by Mario Pettenghi (1985)



"Astronave Farmer" or "Spaceship Farmer" in English is a text adventure game I've ported to Micro Color BASIC originally programmed for the Sharp MZ80B. I also translated it from Italian. This seems to have been a well loved game. There is an article about it (in Italian) in RetroMagazine by Antonino Porcino.  It is from 1985. I'm not sure if there are earlier Italian text adventures, but this is earlier one than the other Italian adventure I have, "Atzeco Adventure," which Gary from over on the CASA Solutions Archive converted and translated when I brought it to his attention.  It was from a magazine for the VZ-200, so I thought it would be an easier job converting it to MC-10, since they both share the Motorola MC6847 video chip.  But Gary is a real fan of that system and when he heard of a program that didn't seem to be part of the software archive for the system, he immediately set to getting it in working order and well translated.  He said he found lots of spelling mistakes.  I take this mean spelling mistakes in the original Italian-- probably with the distinctly Aztec terminology.  The game was probably made by a young Italian who wasn't overly concerned with the anthropological niceties of meso-America cultures. When I converted Garry's translation to MC-10, I also added a semigraphic-4 meso-American image for the title screen.

When I did my translation of Astronave I asked folks from the Facebook group to try out the rough early version.  Greg Dionne found some bugs by running it thought his BASIC compiler--  variables the weren't declared, which was probably a byproduct of Google translate. Otherwise Google translate seems pretty good at ignoring the BASIC command parts of the text, and just translating the messages for the most part.  This wasn't the case a few years ago.  You had to snip out the text messages, otherwise Google would garble all the BASIC commands. Walter Zeick pointed out some verbs that Google had failed to translate well (that is to say in keeping with two-word parser conventions).  I also had to go through and tweak the translation in a few places. Some phrases just seem completely colloquial, like "Light up your beard hippogriff!", which I just left as is. I had to make some guesses, but I hope it's pretty faithful to the original.  There is some clever humour in this adventure and some biting sarcasm in the remarks of your "puppet" or "alter ego" acting as your hands eyes and ears in the adventure.  Having now played the game to the end, I think I can understand why it is remembered with such fondness.

**SPOILER ALERT** (Below is a complete map of the adventure.)

There are only a few instant deaths that can't be anticipated, so you will have to play this one a few times if you are going to solve it on your own.  The puzzles are not overly hard.  Modern IF players will of course complain about the arbitrariness and limited vocabulary.  But as 8-bit adventures go this one is pretty fair and reasonably coherent. It's a nice little jaunt for an hour or two.  It has a hidden message in the code that you will only be able to (easily) see by playing the game through to the end yourself.  I have altered that secret code subroutine to present the message in English  If you need some help here's the map:

The source code can be found here:

https://jggames.github.io/jgames_TextAdventures.html

ASTRONAV can be played online (at least for a little while) here:

https://archive.org/details/@james_gerrie

Thursday, 29 December 2022

"Dr. Who Adventure" by James Smith (1982)


I ported this text adventure quite some time ago, but my techniques for squeezing games into the 20K space of the MC-10 have improved a lot since then.  I now don't have to use the two-file data-loading methods that I discuss in that post.  I've learned other ways to save memory space, especially regarding the management of string space.  By renumbering lines by ones and using all my other memory saving techniques I have now got Dr. Who Adventure to fit into 20K.

I worked from a scan of this game first published in Australian magazine Micro-80, Volume 3, Issue 8.  It was not a very good scan, so it was a real challenge to get the game working.  And once I did I discovered a very challenging early 8-bit BASIC text adventure. Originally requiring the loading of two separate programs to allow it to fit in the memory of a 16K TRS-80 Model 1, I have finally succeeded in modifying it to work as a single program for the TRS-80 MC-10.  I have also made some bug fixes (many of which I can't remember). However, the most significant is probably this one:

890 IFRND(0)>.998ANDWTANDPS<>99PRINTSY"hit over the back of the head and everything goes black...You awake to find that everything you were holding is gone.":FORI=2TO16:IFO(I,1)=90THENO(I,1)=6:NEXTI:GOTO840ELSENEXTI:GOTO840

This routine involves you getting mugged and all your items NO(I,16) from I=2 to I=16 being moved to location 6. Unfortunately, Smith did not also add the code needed to deduct the "weight" of each item from your inventory. They just get re-located. Since you have a max weight of 20 (each item has its own distinct weight), once you are mugged it's possible that if you recover the items you won't be able to carry all the ones you need back to Galafry to win the game. You have to be carrying the items when you reach the throne room and "talk" with the other Timelord there. Other items also "disappear" without subtracting their weight, but most of these were game ending anyway, since they involve you giving away or eating items, etc. that you need to win. In any case, I rationalized all the dropping/giving /eating routines to subtract the weight of the lost items.

Another significant bug involves the jumping out of FOR/NEXT loops. This has the practical impact for memory saving that all NEXTs have to include the variable reference, otherwise strange results can occur in the return to the top of unclosed FOR loops. The offending code occurs in the very fancy multiple word parsing subroutine:
860 J=0:K=-1:FORI=1TOLEN(A$):X$=MID$(A$,I,1):IFX$=" "THENIFKTHENNEXTIELSEK=-1:NEXTIELSEIFNOTKTHENSW(J)=SW(J)+X$:NEXTIELSEIFJ<5THENK=0:J=J+1:SW(J)=X$:NEXTI
870 FORI=1TOJ:SW(I)=LEFT$(SW(I)+"   ",3):NEXTI:K=0:FORI=1TOJ:A1=1:AN=78:FORI1=1TO78:AI=INT((A1+AN)/2):X$=MID$(SC,AI*3-2,3):IFSW(I)>X$A1=AI+1ELSEAN=AI-1
880 IFX$<>SW(I)ANDA1<=ANNEXTI1ELSEIFX$=SW(I)V(K)=ASC(MID$(S1,AI,1)):K=K+1:IFK>2THENGOSUB1840ELSENEXTI:GOSUB1840ELSENEXTI:GOSUB1840
I unraveled all the ELSEs used in this code and then made it so that the FOR/NEXT loops exit gracefully. This allowed me to remove all the variable references attached to NEXTs.  And it also prevents the variable stack from blowing its lid, which is deadly when you're trying to save every byte.

I have also changed some of the parameters of the game that were overly frustrating. You used to be limited to a random number of Tardis rides, which ranged from 20-40. Since the planets the Tardis goes to are arbitrary whenever you "reset" it, the game can be quite arbitrary in the level of challenge it presents.  I simply set it to 40. The random location selection is challenge enough.  I also changed the "search" function to a much lower level of possibility of not revealing items hidden in rooms.  As well, I made the "Renticulator" device report the exact number of required items that you have found.  It used to report a randomized "approximate" number. I made it report the exact number of required items  because it will be tough enough for people to figure out what it does, although a hint is given in the instructions published in the magazine and included in the CASA: Solutions archive description of the game.

Smith obviously loved using randomness to make his game more challenging, but it was to an extreme extent-- a typical flaw in early BASIC text adventure games.  Many authors of the era took grotesque pleasure in making their games diabolically tricky.  But it could often be too much.  In this game there are random mazes and random events a plenty, such as the "mugging" or walking off cliffs etc., so I don't feel bad about toning down the arbitrariness.  There is a really clever game here under all the gratuitous arbitrariness, with lots of interesting NPC interactions (for an 8-bit BASIC game) and a clever sense of humour, which I want other people to try and enjoy.

'PlayDalek' is pretty hot stuff

DRWHO can be played online here: https://archive.org/details/@james_gerrie


The VMC10 Emulator with DRWHO in the JIMG subdirectory of the Cassette directory can be downloaded here:

Friday, 9 December 2022

Usborne Books "Dungeon of Doom" (1984)


By Les Howarth, Cheryl Evans and Chris Oxlade, this game was the example program at the heart of Write your Own Fantasy Games by Usborne books. It's a fairly straightforward RPG, but unlike many others of the era it lets you design endless dungeons and characters. You can create dungeons of  up to 5 levels of difficulty (I have changed this to 9 for my version). I ported the game to Micro Color BASIC for TRS-80 MC-10 from BBC source found on Github typed in by Brian C as a first step to his conversion of the game to the modern Ruby programming language. I added a simple 3D first person view using a SG4 graphic system mocked up by Erico Patricio Monteiro. He's a real wizard of semi-graphic design. I have wanted for some time to find a program that could put his 3D graphics to good use. I think this one does that nicely.
 
The most difficult part of the conversion was re-creating the save/load features for the dungeon maps and character info. I had to consolidate various array variables so I could use a single CLOAD*array,"FILENAME" command for each file. For example, the map data also needed to save the starting position and level of the map.  It took a while but I was able to do it. The other thing I had to do was consolidate three separate programs (Map Maker, Character Generator, and Game Play Module) into one. This would allow me to post the program on the Net in a simple way for people to try it without all the fuss of loading and running multiple programs. It also allowed me to allow the player to create a character, map and then simply play the game from a single menu. However, you do get presented with the options to load files if you wish and are playing on an emulator that allows file saving and loading or on real hardware. The program requires you to create or load a character and create or load a map before it will allow you to enter the play game option of the menu.

I needed the 3D option because the original program used character redefinition to create unique character graphics to represent the items on its two-dimensional map of the dungeon. However, redefining screen characters is impossible on the MC-10. Instead, I simply upscaled the 8X8 redefined characters into SG4 8X8 pixel images that get presented in front of you on your first-person view when you come into contact with them.

DDOOM
3D View Top Left, 2D Map Top Centre

Meanwhile on a simple 2D map, you can see the walls, with monsters and traps flashing briefly as you move.  Activated monsters and traps briefly flash red and then monsters move to track you in the regular wall colour (cyan). Other items flash briefly but simply in the wall colour. They all appear when they are right next to you as you move, or when you use your torches to (R) "Reveal" in a grid up X3 in the 4 directions around you. Torches are limited, and pressing "R" also activates monsters, so torches have to be used carefully.

In the course of porting the program I uncovered a few bugs and quirks that I "fixed:"
  1. In the Dungeon Maker the variable used in the (O) "Offer" routine that allows you to haggle over prices was incorrect. The amount removed from your gold supply was the secret lowest possible price used by the computer to assess your offer rather than your offer.
  2. When you bumped into a monster while another monster was already active, the monster you bumped into wouldn't activate, but simply sit there. The program would remove a small amount from your health if you kept bumping into it, but that was it.  You couldn't even initiate conflict with it.  You could only fight the active monster.  I changed the program so that when you bump into monsters they activate and attack.  Any other active monster deactivates. The primary changes occur in line 210
  3. In line 2460 the DATA statement lists some short hand names for weapons and armour.  However, it was defined in a way that seemed different from the weapons and armour list of the character definition program. These short hands are used in the combat routine to indicate weapons that get broken. So weapons would be reported as broken that your character would not even be able to own.  So I realigned the two lists.  The problem was that the Game Play module was missing the broad sword, so everything was off by one.
  4. Line 1310 contained a real game breaking error discussed by WhatHoSnorkers. The metamorphosis spell randomly allows magical users to materialize any of the graphic characters used in the game in front of them. This included the "Idol" character, which ends the game in victory (conceivably to used only on the last of the levels of your dungeon).  So you could enter the dungeon launch the spell, get an idol, and finish the game. I created a short sub list of items that does not include the idol or exit from the level.  So you can materialize chests, safe spaces, vases, monsters, entry doors and traps.  Also, if a monster appears, it wouldn't necessarily activate and attack. The program made a check that if anything else appeared, it would deactivate any active monster on the chance that the materialized item actually was created in the space of that monster (i.e. transforming it into the new item and replacing it).  So I switched the program to just deactivate any active monster, and then check the transformed space to see whether a monster was there, which would then activate it if that was so. Otherwise, you are safe. These changes occur in the line 1340 area.
  5. There was an error in my BBC source, but not the original listing in the book, whereby experience was increased by .5 for every monster killed instead of .1, which made advancement too fast. The BBC micro also used the short hand "CAN" for labelling the number of your torches. I think this was for candle. I changed it to "TOR" for torches, since that is what is used in the Character Generator module. I have made further tweaks (downward) to the EXP earned so that experience keeps better pace with moving through dungeons with about 6-8 monsters slain  providing enough to get the player to the next level.  So when making dungeons, I would recommend putting at least 6, if not 8 on each level.
  6. Around line 1480 I added a routine to give the player random weapons when chests are found and "Got" if they are a fighter class (only weapons they are entitled to carry). This occurs only for a random number of chests opened. Similarly, you can on a chance of 1 in 6 find one of the 6 magic spells if you are a magic using class. Finally, there is a random chance (1 in 9) to find 2 torches. The original game provided no way to replenish broken or used up items. And weapons get broken quite frequently. The result is that your character would just get progressively weaker the deeper you went, which goes against the general principle of designing dungeons to get tougher as you go deeper.  It also gives a greater incentive for searching for chests than the single treasure point you get for each, which only contributes to your score. Now chests also play a practical function as well.
  7. In lines 620-650 the monster seeking routine was weird. A monster could get hung up on corners because the move routine was based on decimal incremented moves. These decimal moves were done to allow for different speeds for the monsters. The highest of the 3 would track the fastest, but the result was that often a monster could only always get at you once you moved to a parallel fully open track. I changed the system to move using only 1 space for each move, but that moves were activated only a random number of times based on the monster type. So the 3rd of the monsters is still the fastest, but there is also a slight randomness to all of their movements.
  8. Line 250 of the source has an IF that checks for I$>"" which was meant to trigger a small decrement of your health/strength for movements and actions.  When you input a command to move or do something then I$ will not be equal to null (<> "").  In other words, you've used energy.  Maybe the I$>"" command works on BBC BASIC to achieve this but I doubt it would work on any Microsoft incarnation of BASIC.  But I didn't spot any alternative code listed in the original book notifying the user to change this line for the other computers accommodated in the book (C64, VIC, Sinclair Spectrum).  So I think it might simply be a typo.  The result would be that you would not expend energy when doing stuff, just when fighting, which might have been bad enough and so the missing effect probably wasn't noticed by the programmers when testing.
  9. Line 730 defined the chances for monsters to break your weapons.  However, it does so in a way that seemed to make it more likely for the lower level monsters to break stuff more easily than the higher.  It simply looks for whether a random number based on the monster codes -2 (i.e. 7-9) equals 1. That means the lower 7 monster has a higher chance for a 1 to occur (1 in 7) than the higher monster, which only has a (1 in 9) chance.  I switched it so the higher level monster has the higher chance of breaking things.  It should be consistently meaner.  It certainly does more damage and moves quicker.  This should allow for the user to populate deeper levels with more of the higher level monsters to make those levels consistently tougher.
  10. Line 1630 is where to score is calculated. It involves using your current experience F(5) as a multiplier of treasure and also adds your strength and vitality, but it also adds your agility F(3) stat, which seemed strange, as this state never changes in the game beyond what you set it to when creating your character.  I think the reference was a mistake (between F(3) and F(5)) and that the authors really intended to add your current strength, vitality and experience level in their calculation, since experience level is a stat that changes depending on your performance.
  11. In line 50 of the Game Module, which checks for whether you have hit the "F" key to fight with a monster, there is also a check to see if the monster is actually active. That check was IF DX<255.  DX is the numeric value for the horizontal difference between your X location and the monster's X location. There is also a DY, which is the difference in vertical distance.  If no monster is attacking or when a monster is killed, DX is set to 255, so this variable plays the dual role of being the flag for when a monster is active and when you are not under attack (DX=255). Clearly, the authors were making sure that when you chose to fight, that a monster was also trying to fight you. But by not actually checking the specific distances of DX and DY, you could fight monsters through walls and even at great distances, once they were activated. This seemed very strange. So I changed the check to require that the distance between you and the monster in both the X and Y directions must be under 2. In other words, you can only fight monsters if they are next to you or right on top of you (i.e. zero distance--in your square-- which is also possible).
  12. I changed the Cleric class from being able to use only a knife (just like magicians) to being able to use the mace and the gauntlet. When I played original D&D, Clerics could use maces.  And why not a gauntlet too?  After all, they are acting as God's right hand against the denizens of the deep!
  13. The program excluded the shield from the calculation of your armour strength. I think the authors probably actually intended to exclude some of the shinier items like the gold helmet and the headpiece.  I suspect that they wanted to use such items as red herrings to lure the gullible into spending their money recklessly.  However, I think they might have at one point (as noted above with the differences in item lists between modules) shuffled items to perhaps help create a better illusion of legitimacy of the red herring items and inadvertently left out the humble shield from the calculations. I changed it so that the headpiece and gold crown (gold is relatively soft, and likely to be thin if used for something as large as a helmet) don't factor in, but that the humble shield does. The shield is one of the items that non-fighter class characters have access to, such as the cleric, so it is an important item for the purposes of balance.
  14. I made Spell 1 somewhat variable in its effectiveness. It allowed you a one shot kill of a monster, which seemed excessive. Now it gives you a 1 in "Your Aura" chance of failing to work. So the higher your Aura the better your chances the spell will be effective. And if your Aura decreases (which using higher level spells can cause), your general effectiveness as a magician decreases too.
  15. At line 1760 a check is made when you try to exit the dungeon to see if you have earned enough experience to be ready for the next level. It does this by checking your current experience level and seeing if it is at least +1 the experience you had when you started the level of dungeon you are on.  However, experience is calculated by percentage increments but only ever reported as an INT number, so you could enter a level with a certain EXP, say 5.2, which would be reported as 5, and then obtain EXP 6, but exactly 6 and be told you still "NEED EXPERIENCE." I found this confusing. So I changed it so that you only need to obtain INT(starting EXP)+1. That way, when you enter a level you know that you just need to get +1 whatever you see as EXP to be able to move on to the next level.
  16. Line 890 it reads "890 IF F(3)+F(6)< RND(M)+2 THEN M$=T$(4):HT=0".  Then just after that line you subtract the damage done by the player to an attacking monster: "900 MS=MS-H:GOSUB 430".  I think the reference to variable HT (thanks Greg Dionne for bringing this to my attention) is meant to zero out the damage if the player happens to miss (i.e. when message T$(4) is printed which is "missed").  But that doesn't happen because a different variable name HT is used instead of H.  In other words, the player never misses.  I suspect that when I fix this the difficulty of the game will go up.  I'll have to do some testing to see.
  17. I changed the reference to "Sire" in the "olden timey" lingo of the character creator routine to the plainer "Sir".  I think even in the middle ages ordinary folks weren't "sires"-- just the monarch.
Finally, I made some changes to make the game work better on the MC-10. The arrow movement keys are switched to the familiar (and marked) AWSZ diamond pattern. This necessitated changing the combat key from "A" for attack to "F" for fight.  I added a help screen in the Game Play module to let the user know what the keys do.  I also added a prompt to give you the choice of leaving when moving onto the exit. This way you can continue to scrounge for items. This was just a problem for the MC-10 version, since the player can't really identify objects, including the exit, until she/he tries to move into a space.

The program is called DDOOM. The full emulator can be downloaded here. DDOOM can be found in the JimG subdirectory of the Cassette directory.


And if you want some premade dungeons, you can find a .zip file with 5 of them, and a couple of pre made characters throw in a this link: https://drive.google.com/file/d/1xs7ocowKySWy70H5Yt_wfkVfOUrL8pDy/view?usp=sharing

If you are looking for a classic RPG experience from the early 1980s 8-bit era, you should give this program a try.  It's a real nice one.


Acknowledgements

Thanks to WhathoSnorkers for his excellent set of videos on the game.  He was the one who made me aware of the game-breaking error that I discuss in #4 above.  His fixes and updates also inspired me to put in the fixes to the Chest routine, which allow you to find treasures, magic and torches.

Thanks again to Erico for his wonderful wall graphics.

Addendum

Here's me playing and winning a C64 version:


It's from a site with lots of useful information on playing the game:
Usborne Books has made its old programming how-to books available free to download: https://usborne.com/ca_en/books/computer-and-coding-books