Sunday, 19 March 2023

"Mission Adventure" by Michel Brassinne (1984)

The author of the Retroprogammez blog made a nice post about this game. It is an example program from a fairly regular contributor to the French computer magazine Jeux & Stratégie. Garry over on the CASA Adventure forums noted that in terms of items in the CASA database:

The only games I'm aware of from Jeux & Stratégie are 'Nordal le Magicien' and 'La Route de Samarcande'. Both are role-playing games for the Amstrad CPC written by Michel Brassinne.

Garry wasn't sure whether Mission Adventure would be worth translating to English (it might be an RPG given its pedigree). He also pointed out that the source I was working with from Retrprogrammez had been modified by a number of individuals.

3 REM Jeux & Strategie numero 29 - pages 44-48
5 REM Version : 1.0 du 17/12/2017 6 REM 1.1 : 16/09/2022 - Corrections avec VSC

I can confirm that it is definitely a text adventure, but it is not going to be a historically pristine representation of the original listing. It's unclear what if any "corrections" were made by Rioual or drawn from the follow-up article in VSC (See below). Taking a look at the scan of the original code I couldn't notice anything obvious. But I found that the code still seems to have some bugs, or oddities that perhaps I simply couldn't figure out correctly. There are some uncompleted or redundant (non-operative) lines and a number of other issues.

There is a "candle" listed among the items/objects in the program, but I couldn't find any aspect of the code that would seem to allow a player to find that item.  That being said, I did find a reference to an unmentioned single word command.  If you typed "LUX" at the "Action" prompt the variable for turning on light in the cave areas would be switched on and the French equivalent (at least according to Google) for "cheater" would be printed.  This seemed to be a kluge, perhaps used by Brassine during the debugging process, and maybe he mentions it in the original article.  I changed it to a formal "QUIT" command instead.

There is a routine for uncovering a hatch in room 5 of the cave.  You "move" the green foam, and then the hatch appears. Then you can open the hatch and see a lead box, which you can also open. Inside is a key.  But there isn't any apparent function for the key.  The box, however, will turn out to have a use.

The main source of light is to "search" the "uniform" of the skeleton in room 3.  You must issue the right command of "look skeleton" to find that he is wearing a uniform. "Search" and "examine" also produce various messages throughout the game, but for the most part the heavy lifting is done by using "look" in combination with an object.  That being said, "search" is needed for finding the matches in the pocket of the uniform and "examine" to find a paper in a book-- so standard "guess the verb stuff."  Also using "open" or "move" with many objects will produce interesting results.

"Look" normally must be used with any object, but I added the function of a single word version of it redisplaying the current room description and object list, which seemed absent.  Otherwise, you might find that you had to leave and re-enter a room to observe it.  Normally for most rooms, you need to periodically "light match," to get room descriptions displayed instead of the message "It's pitch black" because most of the adventure takes place deep in a cave complex (only the first few rooms do not require matches).

The main objective is to find the "portrait" in room 15, "move" it to reveal a hidden safe, and then use the hint written on a note found in room 8.  The note is inside a book in a cupboard in that room.  If you "examine" that book a "paper" falls out, with the cryptic message "U40.W25.U12" on it.  I took the "U"s and "W"s to be references to the directions for a combination lock, with German annotations.  Google translate produces "Uhrzeigersinn" for clockwise, but "counter clockwise" doesn't" produce an obvious "W" word.  But I went with that interpretation in trying to make the combo dial routine work for the safe in room 15.  A walkthrough in the next issue of the magazine mentions that the letters should actually be "L" and "R" as "in German (rechts and links)" (the words for "right" and "left").  But the original source definitely looks like "U" and "W".  Weird.  I left the message as at is.  I changed the routine that runs when you "read book" to make the output look more like actual text rather than simply a scoll of random characters.  I also added descriptions to make the messages clear that the book is a manual about  special "hydraulic safe" installation. 

For some reason the safe routine expects that you will reach a final total of 37.  But +40-25+12 only totals to 27.  I'm not sure if this was a typo or not.  Or whether I was missing something obvious.  But in the end I changed the number to reach after 3 turns to be 27 not 37.  As long as you get the dial to 0, which prompts a restart to your number of turns, then you can get the safe open by ending on 27 after three turns.  Inside are a bunch of "Bars" or "Ingots" depending on how Google feels like translating at any particular moment.  I standardized on "Bars" and added a few elements to the descriptions to clarify that these are solid gold bars.

Another aspect to the game is that you must carefully choose the number of bars you will try to get out of the cave.  If you select more than 3, then a gate will fall at the entrance.  If you try to "open" that gate you will be dropped down by a trapdoor to your doom.  You can increase the number of bars you can escape with up to 10 if you get the lead box and drop it in the safe.  If you do that the hydaulic mechanism will lift the gate.  There was no accurate way to report the number of bars. The variable that keeps track of the "weight" you are carrying seems to count other things as well.  So I added a dedicated bar count variable.

Another change I made was a better check for whether items are in a room when you try to interact with them.  No check was made for whether an item is actually in the room, or your inventory.  The only check was that you typed the item name correctly, and that it was one of the items recognized in the game (I changed this check to look only at the first 5 characters-- this allows you to type "light match" instead of "light matches" while still allowing "matches" to be the default item name).  The lack of full checking meant that you could issue commands regarding items from anywhere in the dungeon and actions could work.  Now you must either be in the room with the item, or have it in your inventory.

I also fixed up the "dropping" and "taking" items routines so that items consistently get dropped in the room you are in, instead of some original room in which you might have found the object containing that item.  For example, you could get the skeleton's uniform, take it to another room, search it and then the matches would appear back in the skeleton room.  Similarly, if you took the book and examined it in another room, the paper would fall out back in the room where you originally found the book.

Finally, nothing would happen when you got back outside with your loot. I made the game print a message with the number bars you manage to "liberate" from the NAZIs.  Also, just for giggles, I added a graphic for the "portrait."  It's an ASCII image of der Führer and is displayed when you "look" at the portrait.

Here is my attempt at a walkthrough map:

“Mission Adventure” by Michel Brassinne (1984)

12 Narrow Corridor


13 Narrow Corridor


14 Narrow Corridor





10 Narrow Corridor


11Room (NESW Exits)

15 Room (NW Exits)

-          Portrait

-          Safe

-          Dial (R40,L25,R12)

-          Bars

9 Narrow Corridor

8 Nearly Empty Room

-          Wardrobe

-          Book

-          Paper

-          (Code: R40,L25,R12)



6 Passage (N.E.S)





7 Slippery (E-W) Corridor

-          Move east until Dead End is reached, then W


5 Damp N-S Corridor

-          Foam

-          Hatch

-          Box

-          Key


4 Dusty Room

-          Calendar

2 Crossroads

-          Gate (Don’t try leave with more than 3 bars)




3 Dark Room

-          Skeleton

-          Uniform

-          Matches






1 Start

-          Entry

-          Exit (to win)




Map: Jim Gerrie (2023)

Here are some of the details from the follow-up article that was published in the next issue of Jeux & Stratégie translated into English (curtesy of Google Translate):

Solution... of the Mission Adventure game

You had to discover that the cave was occupied by a German soldier (green uniform), who died on July 25, 1944, as the ephemeris indicates, that is to say during the Liberation. The exploration of the central corridor to the north is only possible with a means of lighting. This one is discovered by searching the uniform: a box of matches is there. Each match has a lifetime corresponding to three actions or moves. Then you had to strike a new match to see clearly. In one of the rooms, a portrait is visible. As is often the case in reality, there is a safe behind it. The order to move the painting makes the safe appear. However, you still have to open it.

Looking at the safe, you could see that it has a dial. The combination of the safe was written on a sheet of paper, slipped into the book placed in the cupboard (when leafing through the book, the paper falls out). The letters accompanying the numbers were the initials of the words "right" and "left"... in German (rechts and links). You could therefore turn the button of the safe to the right, to the left then to the right again, the number of notches indicated on the sheet providing the combination. And this, after having reset it. As the title of the book found in the cupboard suggested, it was a safe with hydraulic protection. Indeed, the bottom of the safe is like the plate of a scale, capable of knowing at any time what weight it supports. As soon as it detects a difference in weight compared to that initially indicated, it triggers the fall of a gate which condemns forever the intersection near the entrance. Grid which, in turn, triggers the opening of a hatch as soon as one tries to force it.

Cutting the Lines Several readers have rightly pointed out to us — after having tried in vain to type in the listings for the adventure game and checkers (J & S micro of n°29) — that their machine did not accept 255 characters at the sequence of a single instruction number. It is therefore necessary to cut the lines and to include each of the sections under a different line number. Two cases can arise: simple instructions and tests. Simple instructions can be split into as many lines as there are instructions separated by “:”. For example: 345 A = 2: Z 3: PRINT "ACTION —" T can become 345 A = 2. 346 Z = 3. 347 PRINT "ACTION -" T. Care must be taken when it comes to testing , i.e. lines of instructions where there is an IF THEN, because if what follows the IF is verified, then everything after the THEN will be carried out. If the condition following the IF does not hold, then nothing following the THEN will be read, and the program's read pointer will jump directly to the next line. You must therefore split the test in two, or even divide it into as many successive tests as necessary so as not to exceed your capacity of signs per line. Let's take the following example: IF A = ​​2 THEN B = 3 : C = 4 : D = 5 :.../... Z = 27. This test modifying the value of all the variables from B to Z will be much too long for one line of instructions. So you can do:

340 IF A = ​​2 THEN B = 3 : C = 4 : GOTO 350 

345 GOTO 1000 (case where A is different from 2) 

350 IF A = ​​2 THEN D = 8

5: E = 6: GOTO 360 355 GOTO 1000 Another way to proceed, this one faster, by reversing the test:

350 IF A < > 2 THEN 1000

360 B = 3: C = 4: D = 5: F=6

370 G=7: H=8: I=9: J=10 etc. 

If A = 2, the pointer does not jump to 1000 and reads all lines that follow the test. Reversing the test is often the most practical procedure. NOTICE NOTICE NOTICE Adventure game on Commodore Philippe Peltier, from Juan-Les-Pins, tells us that owners of Commodore (Pet, Vie. 64) must very slightly modify the program proposed in J & S n°29, page 44 to respect the syntax of the Commodore, otherwise it is guaranteed to crash. It is particularly necessary on this machine to concatenate (paste!) a space at the end of the string A$, otherwise MID$ (A$, I, 1) will cause a “BAD SUSCRIPT ERROR” when it reaches its maximum value. On the other hand, there is memory loss of the loop pointer because of the ON T GOTO in line 1 100. Here is the remedy proposed by Philippe Peltier:

1000 IFX=OTHEN370

1010 00SuB1230 1020 IFY.OTHEN370

1030 011SUB1300 1>340 GOT0370

1050 REM========


1077 1071 RṢ. -R$+" 1020 

1090 IFEe=CHR$(32)ORE$=CHR4(39)THENT=T+1 ri0T01130

1100 ONTOOT01130,1120 

1110 Ve-VS+1 ; e:GOT01130

1120 Ne-,N.e+B $ 1130 I=I+1

My version of the game can be played online at the following.  Just select the MISSADV from the cassette menu and type RUN in the main (green) emulator screen:


Another fix I made was to the parser. The French language parser was actually a neat variation of the standard English 2-word parser.  Because of the standard use of definite articles with all nouns in French, it was actually a 3-word parser.  "POUSER L'ARMOIRE" for example, would be the standard command structure, with the directive verb form followed by the definite article and then the noun.  This meant that the parser had to search not only for spaces between words, but also the apostrophe, for contractions between article and noun, as in this example.  Took me a bit to twig to that before I realized I had to modify it to the English 2-word format.  It is interesting in the original article to read Brassine's comments on the origins of the "text adventure" game form.  He attributes it to American college students and mentions Colossal Cave "Adventure" as a founding program of the genre.  It obviously took until 1984 for this type of game to start to become more common in France and Brassine felt he was helping to introduce it (and modify it as necessary) to a French audience.  Another example of this is the need to include gendered indefinite articles for the objects (UN, UNE, DES).  It provided an interesting case study for seeing how one culture appropriates the technological practices of another.  And a fun little adventure to boot once I got it working.

Saturday, 11 March 2023

"Doctor Who Adventure" Jeremy Guggenhiem (1893)

In a 2000 post, Jeremy Raynor claimed that this is the first ever Doctor Who computer game. It took the form of 3 pages of listings 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 problem, 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 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 the different 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 obviously pile up in stack memory.  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 this 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 clear memory and variables back to null.  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 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 that had initially called the room handler the firs time.  At that point all the RETURNs will 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.  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 using it against the Doctor, resulting in a 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 killing it.  I've added one red herring item to increase the complexity of the puzzle that must be figured out.  Mishandling that object adds to the dangers that the Doctor' must face in the already dangerous maze/pyramid he is exploring.  I added a 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 on the original speaks in favour of this conclusion. In any case, here is the directory where the source can be found:

The game be can played using the TRS-80 MC-10 Javascript emulator by Mike Tinnes. Select DOCWHO from the Cassette menu.  Then type RUN in the main (green) emulator screen:

*NEW* Type-in Mania contest. Anyone who can post visual evidence on the MC-10 Facebook group first of them solving the game, wins a Type-in Mania mug.

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.

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 the MC-10 Javascript emulator.  Just select the program name from the Cassette menu and then type RUN in the main (green) screen of the emulator:

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 ( 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:

Use the Cassette menu to select SMASHUP or VOLCANO and then type RUN and hit Enter in the main (green) screen.  Or you can type LIST to see program.  However, here are the program listings:


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
2 POKE49151,64:POKEL(T),134:L=L-1:PRINT@496,"LIVES"L;:POKEL(T),137:SOUND1,1:ON-(L>.)GOTO5:GOTO6
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
16 REM    A S D

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
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
10 REM                                                                                             1         1         1        
11 REM   1         2         3         4         5         6         7         8         9         0         1         2        
12 REM78901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678

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 the JavaScript MC-10 emulator.  Just select SCRABB2 from the Cassette menu, and then type RUN in the main (green) screen.

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:

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