Saturday, 22 February 2025

"Bally's Alley" by John Collins (1980)

Jason Dyer made a post about an interesting little text adventure for the Bally Astrocade system. He was able to get a version of the game running from source code typed-in by Paul Thacker in November 2022 from a printed listing and handwritten notes of the original author, which were preserved by Bally Astrocade hobbyists. This game fits in 4K of memory, which is quite a feat of programming by the author. Jason wasn't able to complete the game because he ran into some apparent bugs. My MC-10 version contains bug fixes to ensure that it can be played to completion. 

The following is a map of how far Jason got (pink box) from the start (green):

The problems were probably a result of a few slightly misinterpreted numbers by Thacker from the handwritten notes.

I have two proposed fixes to the hand recorded list of variables:

  • @(17) change from 370 to 3170. This allows the player to move on to room #19 of the Color Maze, which I don't think Jason would have been able to do. This was my best guess of where a typo would most likely have occurred to prevent a move to room #19 (and the whole subsequent section), as the method of room number parsing only allows jumps from 1 to 2 (plus or negative) from the current room number. So the problem had to be either #17 or #18 that was preventing movement onwards in the Color Maze. The handwritten note for room # 17 looked like it had a possibly partial "1"that needed to be added to its 3 digits (370)-- just the hint of a "1" in front of the "7." When I tried it, it worked. 
  • @(14) change from 1603 to 10603 (this one is optional). Thacker's version just lets you go N from the WELL directly into the COLOR MAZE, which I think undermines a puzzle Collins wanted/was working on. I suspect he had some problems with his room number parser, possibly due to rounding errors (a problem for the MC-10 version) that might have been frustrating him. I've fixed these problems now, but Collin's handwritten notes have numerous scribbled-out numbers and replacements for the room data. This data had to be entered directly by the user, to help conserve memory.
I think the problems with transcription and the parser combined were what was preventing Jason from being able to initiate interaction with the WELL and also the similar PURPLE room puzzle. Both these rooms need to have 5 digit numbers to initiate a COMMAND prompt after typing a DOWN direction. But only the PURPLE room (room #20 on my map) had 5 digits. It is possible that Collins had switched to 1603 for the WELL room (#14) just as a kluge, to temporarily deal with these problems.

# of Room Jumps------>


 

 

 

 

Rooms

Get a Command?

+2

+1

-1

-2

17

 

 

3

7

0

New 17

 

3

1

7

0

20

1

0

6

0

8

14

 

1

6

0

3

New 14

1

0

6

0

3

The trick with the WELL is to be carrying the KEYS, have just tried to move DOWN, and then issue the command UNLOCK when prompted. This should take you to the COLOR MAZE room with the LAMP (I'm sensing that Collins was inspired by Crowther's original, Adventure and its formula of "get lamp").

Similarly, in the problematic PURPLE room (it's red in my MC-10 version), the player must have just tried to move in the DOWN direction, and then must issue the command "F."  I'm not sure what "F" stands for, but perhaps "Find" or "Fire," because the player must also be carrying the OIL (but the LAMP doesn't seem to be required in the original). I changed it so that if the player types "F" or "L" (Look) or "S" (Search), a descent downward to a new section which I call the "Echoing Cave" is initiated (room 30 "No Way Up" in my map below). It also might simply be for "Fall" (If so, wouldn't "J" for jump be better?)  However, since the COMMAND parser only looks at one or two characters (G for Get, DR for drop, L in unLock), it doesn't much matter. Apparently Collins mentioned that people could play the game "for weeks." I can understand why.

The descent takes the player to an area, where the rooms don't have descriptions. Instead, I'm pretty sure each room makes a different noise. I don't have Jason's patience to get an Astrocade emulator running, so I'm guessing based on a rough knowledge of Astrocade BASIC (original and extended versions). Maybe there are some screen effects too. I'm not super familiar with the system but I was able to build some knowledge converting Clyde Perkin's classic "O-Jello"4K "Othello" game, which has a wicked AI opponent for a 4K game. Each room has a slightly different tone/pitch to its sound. This is an absolutely intriguing game dynamic. I don't think I've ever seen a text adventure from this era that uses sound as a critical part of the navigation/description system. It could be a first.

My new MC-10 version fits into 4K like the original (I am in total awe of Collins) and has a few other "fixes" (possible improvements). I added an "L" Look command that can be used in any room to redisplay the description as well as other function ("S" for search will have a similar effect, and both will also accomplish the "F" Find/Fall action). I also added save/load to the main menu and an extra hint to help with the purple room puzzle. I made it so that the player must have both the LAMP and the OIL to descend into the Echoing Cave, based on the assumption that the player needs these items to navigate "the darkness." BALLYSAL.C10 for MC-10 emulators can be found here, but people should be aware that my colors for the Color Maze will be different from those of the Bally Astrocade original:

The MC-10 version can be played online at the Internet Archive.

BALLYSAL.C10 can also be found and played online at the Color Computer Archive (Thanks Guillaume!)

I have managed to play it to completion. I'm not sure if 956 is a good score, but your score is decreased by how many moves you take. Since I was using maps and cheats (most importantly reading the source to know what to do), I suspect it's a pretty high score compared to what a real player, working from scratch, would be able to get:


Unlike Jason, I used maps and a temporary modification to the room display routine to print the room numbers (and to allow me to jump to rooms). This helped keep me well-oriented for my own map making. The following are two maps that I created, the first one based on those he posted:

Adjustments to Jason's Map for my new MC-10 version:

My additions to Jason's Map (for the MC-10 version):


Thanks to Jason for the inspiration for such an interesting "Reading Week" coding project, and for his map making and game history and links, which are so helpful when it comes to bug chasing. I'm curious if any of the Astrocaders will figure out other more accurate fixes to Thacker's groundbreaking work. I never know when I bug fix whether I am helping to restore/complete a programmers original vision, or mangling a classic piece of software. I hope it is the former. This one certainly deserves it.

Friday, 7 February 2025

"Computer Dominoes" by David Smith (1982)


I've typed in another game with an AI opponent and modified it to work on the TRS-80 Micro Color Computer ("MC-10") using Micro Color BASIC.  It's from source code in Your Computer Magazine, February 1982, and originally was for the Commodore PET.  The game plays a variation of the "All Fives" game of Dominoes.  But instead of just multiples of 5, scores are also awarded for end totals that can make multiples of 3.  A single point is awarded for each possible multiple of the two types. The computer and human player start with 9 dominoes. When a player uses up their dominoes or neither can place a domino, then a new hand of 9 is dealt. The goal is to be the first to earn a total of exactly 72.  If points are earned over this amount, they are ignored until the exact amount is achieved.

As usual, I had to chop out the Petsci text-graphic part of the program (involving lots of POKEs), and replace it with an MC-10  semi-graphic-4 character printing routine (using lots of PRINT@s).  I created a routine to lay down a string of dominoes that snakes around the screen so that all 18 possible dominoes can fit. The routine had to print horizontal and vertical dominoes, depending on their location in the string.  It also is used to list the human player's dominoes at the bottom of the screen.  The very low res. nature of the Semigraphics-4 (64X16) mode called for some compromises. The 6 dot domino looks like two solid bars instead of 3 discreate dotes for each bar and in order to differentiate between individual touching tiles, I alternate the colors of the tiles between white and yellow.  It is based on my recollections of  "mixed" sets of dominoes from my youth, which had pure white tiles and more yellowish "ivory" tiles.

Also as usual, I found what I think are some bugs in the original code, which would have affected play on the original PET version too.  One involved the zeroing of the array holding the tile info for the player's hand.  This array is a 0-6 by 0-6 grid.  But the routine meant to put the hand back to an empty state didn't start from zero for the "J" dimension:

1540 FORI=0TO6
1550 FORJ=1TO6:D(I,J)=0:NEXTJ
1560 NEXT

The result was that sometimes, after the first hand, some un-discarded low numbered tiles could be left in the array. Then, when the array was searched for tiles belonging to the player, more than 9 could be found. This error might not have caused an crash in the original program, but in mine it caused the program to try to print a domino to an undefined 10th screen location.  Since those locations were stored in an array (which only went up to 9 locations), an out of array bounds error was triggered.  So I just changed line 1550 above to:

1550 FORJ=0TO6:D(I,J)=0:NEXTJ

This ensures that when the array is repopulated with 9 tiles for a new hand, there is no possibility for old data to be left behind in the first J column.

The other error involved sensing when the computer had played out its final domino. The routine to select the piece would, if possible, select the last tile and designate it as played (=3), and then increment the number of pieces played variable (CD) for the computer. Then it would immediately check if that was the last tile or not (CD<>0).  If it was zero it would proceed to a message that it was "out of dominoes" and then go to the deal a new hand routine.  But this meant the routine would never get to the routine to print the tile on screen and would also miss the end of game/win checks, which follow line 3950.

3950 D(X,Y)=3:D(Y,X)=3:CD=CD-1
3960 IFCD<>0THEN3990
3970 M1$="OUT OF":M2$="DOMINOES"

I noticed that when the computer ran out of tiles it would always flash the "last domino" message and then go directly to a re-deal. Did it win?  Was it a good play?  Did it earn points? The lack of any domino played animation was weird.  So I switched the CD=0 check to the end of the display routine instead.

4140 IFCS<>72THEN4190
4150 M1$="COMPUTER WINS!":M2$="":M$=""
4160 IFPS<66THENM2$="MORE PRACTICE!"
4170 IFPS>65THENM2$="GOOD GAME!"
4180 GOTO2340
4190 D(X,Y)=3:D(Y,X)=3
4191 IFCD=0THEN3970
4195 GOTO1670

Now it displays the domino played (line 3990 - 4130) and then does the win check.  If the computer doesn't win it goes to 4190 and then checks if no tiles are left.  If there are none, it jumps to the no more dominoes message and does a re-deal.  Otherwise, it heads back to the input routine for the next player's move (1670).

I find that it plays a pretty tough game.  But then again, I'm no Dominoes player (no game player of any sort actually), but I forced myself to test it to the point of a "human win."  It was actually kind of fun.

Human for the win!



The game source can be found on my Github:


It can be played online at the Internet Archive:


Another Human for the win!

Saturday, 18 January 2025

"Treasure House" AKA "Chateau of Gold" by C.J. Davison (1982)


I've been working on a port of a game called "Chateau of Gold" for the Dragon 32 computer by GEM Software to the TRS-80 MC-10 using Micro Color BASIC. The remarks at the top of the GEM code suggest that it was authored by a P. Allen:
10 REM***********************
20 REM**                   **
30 REM** CHATEAU           **
40 REM** WRITTEN BY P.ALLEN**
50 REM***********************

However, it turns out the original program was by C.J. Davison and was published as a type-in BASIC program in Your Computer Magazine January 1982 for the MZ-80 Computer. I learned this from a Chronologically Gaming video and from L. Curtis Boyle talking about that video on the Coco Nation livecast show:


I had to fix a few bugs in Allen's code having to do with RND function differences between Dragon and MZ-80 BASIC. I think my version should play a more faithful rendition and error free version of Davison's original game.

The problem with RND function conversion by Allen was that the Coco allows RND calls with a whole number like RND(10) or RND(100) to get ranges of 1-10 and 1-100, whereas most Microsft BASICs use the convention INT(1+10*RND(1)) or INT(1+100*RND(1)) to get ranges like this. The MZ-80 is a little different again, as it seems to use random numbers (or maybe this is just a quirk of Davison) in the place of the RND(1) or RND(0) to seed the RND function used in most MS BASICs. But these whole numbers do not produce whole number ranges as with Micro Color BASIC. So in the following random coordinate picker routine for putting objects into the 6X6 floor plan of each floor (Z), the refs to RND(7) and RND(5) simply seed the RND function:
1200 A=INT(1+6*RND(7))
1210 B=INT(1+6*RND(7))
1220 C=INT(1+3*RND(5))
1230 IF M(A,B,C)<5 OR M(A,B,C)>8 THEN 1200
For the Dragon, getting a random number from 1-6 can instead be accomplished with a simpler RND(6) call, and Allen correctly converted most of the RND calls to this method.  But in the case of the objects placement routine above, his eye seems to have been distracted by the "seed" number, so that he actually designated a range value of (7) instead of (6) for the 6X6 room populating function. This is Allen's modified Dragon code:
330 FORC=0TO3:FORA=1TO6:FORB=1TO6
340 IFM(B,A,C)<>0THEN360
350 M(B,A,C)=5+RND(7)
360 NEXTB,A,C
370 FORD=1TO2
380 A=RND(7)
390 B=RND(7)
400 C=RND(3)

410 IFM(A,B,C)<5ORM(A,B,C)>8THEN380

This use of 7 means that some items could be placed into the wall zone to the left and bottom of the 6X6 room grid. The wall zones (0 or 7) of the matrix were supposed to remain as zeros. Those zeros prevent the player from moving outside of the bounds of the 6X6 inner dimensions of the M(7,7,3) array, which stores what's in each room. So very occasionally I could move into the 7th space and then if I tried to move beyond the 7th space the program would try to check the un-dimensioned 8th space and a "Bad Subscript" BS error would be triggered.  Allen might never have done this because he had a better sense of the map, and paid attention to staying in the bounds of the walls while navigating the house. In my testing, I just kept moving in random directions to see how the program worked.

So, I checked all of the RNDs in the program. I think I might have found some other anomalies with the map creation logic (with some of the IFs for example), but I can't recall all the details now (too much late night coding). I think I recall a problem with how stairwells, desks, clues, entrances to the basement and the places to store your clues were distributed, leading them not to appear, or not to appear frequently enough. But I think my alterations, including how randomization was being handled, has got everything working like Davison originally intended.

The other major problem that I do recall clearly was with how Allen had implemented the final "mastermind-like" guessing game for opening the treasure chest that you find if you gather all the clues and make it to a place to store the clues. You  have to guess a four digit code (1-9) that has no digits repeating (I added a mention of this to the instructions). Instead of preserving the screen readout of the score of your prior guesses, as I think occurred in the MZ-80 version, Allen cleared the screen (he had implemented a fancy red semi-graphic border drawing system) and requested the input of a new code for each guess. This made it very difficult to work out the code by using your prior guesses, unless you were recording the scores on paper. Also, Davison's original version included a system call, probably to a beep routine, for indicating right numbers in a wrong position (1 point each), to help differentiate those from right numbers in a right position (3 points).  Since you are simply given an aggregated total for each guess, it is helpful to hear a number of "beeps" for how many of those are 1 point guesses. So I added in a SOUND command to do this (hoping my guess is right about the function call).

And Davison's original version compounds the difficulty by only allowing a random number of guesses between 1 and 10. But finding the code in anything less than 10 guesses is probably impossible, logically speaking, leaving game completion entirely up to chance. This seemed unfair. So I changed the system to a fixed 10 tries. In the magazine article Davison mentions only winning once in a month of tries. This indicated to me that there were problems in game balance. One area that also might have contributed to this was the random number used to determine any magical items you sometimes find when you uncover a cash of gold. You are given a 1 in 9 chance of also getting one such item. I changed this to a 1 in 4 chance, but I reduced the gold amount possible from 900 to 700 to compensate. Still, since treasure is fairly rare, finding special items is still fairly rare.

I also fixed how movement into a stairwell from a closed door is handled, and the ability to forego choosing to move up or down them after using the (E)xplore command. I also added back in (from Davison's original version) a message indicating that you are passing through a door. This seemed to have been removed by Allen. When you are on a door space, you are not shown that a hallway is next to it (doors close automatically?). I think it is a good reminder to the player that doors block indication of  the direction of nearby hallways. The message about a door being open reminds the player of this. It took me a while to figure out the ways doors work, and it required going back and carefully reading the original article.

I've also added 2 more color alternatives to the red borders that Allen had added and worked hard to improve and standardize the layout of messages. I had to remove REM statements and combine lots of single command lines to get the program shrunk to fit a 20K MC-10. Allen had added a nice mapping or (P)lan function to show the layout of the house and where you had travelled already. I added to that by using reversed characters in a way that indicates which rooms you have searched and found nothing. I also fixed some quirks with how the (E)xplore function reports messages. Sometimes Allen had it explicitly report that that nothing could be found, but other times it would just return to the main menu without a message. I changed it so that it always tells you explicitly when nothing was found. And I fixed a message that could appear after you open an object and find the entrance to the basement.  Sometimes, if you selected "yes" to exploring the basement, a message about "not being able to open an X" would be displayed.

The following video contains a demonstration of my new final puzzle routine, and fancy colors:

Chateau is a game with unique random map layout generation and interesting "hot key" text adventure command entry. There are a bunch of challenges and puzzles to overcome to solve the game, so I can understand why it would have taken Davison so long to accomplish a victory.  Back in the day, this would have been considered evidence of lots of "repeat play value." Today, I suspect this would just be considered frustrating. But in a time when software was expensive and relatively scarce, we were keen to find any computer gaming opportunities, especially if they were "free" just for the price of a little typing. This game shines in comparison to many contemporary type-in CRPG/text adventures BASIC games.

CHATEAU can be found in my Github repository here:

https://github.com/jggames/trs80mc10/tree/master/quicktype/Text%20Adventures/Chateau

It can be played from my GameJolt page.  Select the big green PLAY button.  Then choose the "8-bit BASIC Text Adventures" collection. Choose "CHATEAU" from the Cassette menu and then type RUN and hit Enter in the main emulator screen.

https://gamejolt.com/games/jgmc-10games/339292

It can also be played on the Internet Archive:

https://archive.org/details/chateau_202501

Saturday, 4 January 2025

"Schatzoeken" or "Treasure Caves" by Unknown Author (198?)

Original Map Playthrough

I ran across a simple little BASIC Action game/CRPG on Jason Dyer's Renga in Blue blog. It was called "Schatzoeken" and was written in Dutch. Jason mentioned it because he was discussing a text adventure by the same name, which he needed to disambiguate as he did his research. His brief mention peaked my interest. The game was for the Sinclair ZX-81 and from the image of the simple semi-graphic "dungeon" screen, it looked like it should be able to be translated to TRS-80 MC-10 fairly easily. I've never had much problems with Sinclair BASIC, which is a good BASIC with some unique features that are fairly easy to work around. Translating to Dutch was made easy by Google translate. It rendered the title from the titlepage/instruction screen as "Treasure Caves".  However, Renga had mentioned that "Schatzoeken" is used in Dutch as something like "Treasure Hunt" and is even used more generically for things like "geocaching" in modern Dutch.

So the move from Sinclair to Microsoft BASIC and from English to Dutch was not too difficult.  However, once I had the game running I noticed that the movement between rooms seemed very odd.  It was extremely difficult to map, and there were all kinds of geographical incongruities. The first oddity was that it didn't matter which of the two differently numbered exits that you took from a room, you always ended up in the same room. But since the exits were numbered, it seemed like you should be able to get to different rooms depending on the numbered exit you selected.  A quick look at the code revealed an obvious cause of this behaviour:

800 REM ROOM CHANGEOVER 

805 CLS

810 LR=PR:IF PR<>21 THEN 815

813 PR=R3:REM INT(RND(0)*19+1)

814 GOTO 825

815 IF N=0 THEN PR=R1

820 IF N=15 THEN PR=R1

The N variable in the above is the Y coordinate of your player location.  0 is the top of the screen where one exit is, and 15 is at the bottom where the other exit is.  Clearly the assignment of PR (present room) needed to be set to different variables depending on which location you exited from.  It seemed obvious that R1 should be for the top and R2 should be for the bottom exit, so I changed those lines to the following:

815 IF N=0 THEN PR=R1
820 IF N=15 THEN PR=R2

This at least made it possible to go to different rooms, but there was still weirdness (see the video at the top of this post). The following spreadsheet shows how the map looked once I could travel in multiple directions and explore a little easier. I also added some test code to turn off the monsters, so I could explore in peace. Doing that made it fairly obvious that the map wasn't a random dungeon, but instead more like a cross, with the "Entrance hall" (Room 0) at the centre. This made sense of the start screen, which prompted you to choose a starting direction/room (1-4). The weird thing was that you could choose start room, 4 for example, but once you did the "exits" for that room would not allow you to go back to room 0 and on to another beyond (down the line), but instead to go sideways to room 3 or on to room 8. This "offset" return direction was echoed for all rooms.

There was also a kind of "tear" in this offset pattern at room 14/15 on the room 3 line, which clearly took you to room 14 that was also a part of the room 4 line. The whole thing was just very confusing.  The physical layout of the rooms with two entrances seemed to indicate that the original programmer wanted to have a cross-shaped dungeon.  Another thing that indicated this was that the game expects you to regularly return to Room 0 to cache your treasure. You can't carry more than 50 points worth at any time, but if you cache it in room 0 you can go back to get more to add to your score. The original map, also seemed to be missing room 15 and 18. If you could get to room 21 you could find a large hoard of treasure, although the treasure carrying limit still applied.  You would then have to navigate back from whichever random room you were sent to after exiting that room (see line 813 above).



Repeated rooms in red

So I examined the string containing the data for the map, which consisted of 3 characters per room.  Two of those characters obviously were meant to symbolize the two rooms that the exits would take you to. There was a special condition where the third character would be substituted for those two exit room numbers:

960 IF R1=LR THEN R1=R3

965 IF R2=LR THEN R2=R3

It seemed obvious that LR meant something like "last room" or "room just left."  But from the data it seemed clear that the numbers being assigned to the 3 characters were out of sink in terms of the pattern being broken at around 14 and 15 in the original map above, and also there was some confusion between the 2nd and 3rd character (R2 and R3).  The IF statements above seemed to be some kind of kluge to fix that confusion. Once I had fixed the break in the data pattern at 14/15, the cross-structure came into better focus. Now you could travel back and fourth on each of the 4 lines of the dungeon.  But there was sill a problem at the end of each line.

It seemed that the bounty of the special treasure of room 21 was meant to lure the adventurer down each line. As you travel down a line, if you fail to get the single treasure in each room it disappears not to be seen when you return back along the line. This was a normal function of the existing movement routine. It seemed to be an incentive for making periodic returns to Room 0 to cache treasure, and then make new forays to reach the (randomly) large treasure at the end. In the existing room rendering routine, you would then be sent to a random location after leaving the treasure chamber via its single exit at top of the screen. Once again this seemed geographically confusing. It seemed to me that the R3 value might have been added to each room so that for the last 4 rooms before the treasure room an extra coordinate could be stored to allow the player to return to a specific line after leaving that line's treasure room. So I changed the data to allow the program to do that instead.

Now, you can play for a max score by carefully exploring each line. This would involve getting all the single treasure from each of the total of 20 normal rooms (5 per line) and whatever treasure you can get returning to the treasure rooms as many times as possible, while making return journeys back through the cleared line rooms.  To maintain a random element to game movement I have added randomly appearing "magical white portals", which if you hit them, will transport you to a random room in the dungeon complex. You can simply avoid these if you wish, or duck into them if you find yourself trapped by the monsters.

New Map Playthrough

Because the MC-10 is so much faster than the ZX-81 I also had to change another feature. In the original the monsters tracked slowly.  Perhaps this was why the programmer made the walls kill you instantly if you carelessly stumbled into them. But this dynamic was impossible to deal with on the speedier MC-10 version. So I changed the walls to be simple solid barriers. Also, the monsters normally would just transit right through interior walls. But since they move so much faster now, I made it that they couldn't move only though the full block characters of those walls. However, they can still transit through the partial block characters (the "craggy" bits) of the interior walls. This means you must navigate in ways that take into account the possibilities of monsters being blocked, while trying to recognize and account for the less tangible walls that will not block them. But even with these changes, I found the monsters were too quick, so I added a level system at the beginning of the game that decreases their speed for the lower levels.

I'm not sure if I have destroyed some unique vision of the original programmer in terms of the "map" and game play, or whether I have untangled a coding knot in the mapping routine that they simply couldn't fix. They might have got the game to the point where it provided enough of a navigable "maze" for adventuring to occur, and then simply called it a day. Back in the day, especially on a dangerously unreliable machine like the ZX-81 (long cassette loading, ram pack wobble) and its horrible keyboard and awkward editing features, I can imagine the programmer might have felt that more bug chasing simply wasn't worth the trouble or risk.

It is a neat little CRPG, which I hope my tweaks have helped nudge towards an original vision. There were a couple of Youtube walkthrough videos that indicate that others were also been intrigued by its unique dungeon aesthetic. However, neither of those playthoughs went very far. For example, neither player seemed to have discovered that there was an ability to fire arrows to kill monsters and neither stuck with the game long enough to make it to a treasure room and its perilous "trap."

Playthrough of original

Another playthrough

My final edits involved adding to the instruction screen to give a description of the keys used for movement and firing. I also changed the movement keys to the more familiar (to modern game players) WASD pattern and added some sounds, "blood spatter" and a high score readout. I hope these changes will encourage people to try out this unique type-in game. I'd also like to say "classic game," but there is no date mentioned on archive sites, so it might not be from the early 1980s. However, from the limited bug chasing that seems to have been done I suspect that it is. If anyone knows anything about its programmer or timing, please let me know.

New Instructions

Here is the source code for the original game:



"SCHATZOE" can be played on GameJolt. Hit the green Play button and then choice "More 8-Bit BASIC Game Ports."  https://gamejolt.com/games/jgmc-10games/339292

It can also be played on the Internet Archive:

Thursday, 24 October 2024

"Stellar Odyssey" by Nick Marentes (1982)-- A Conversion Odyssey

I was watching The Coco Nation live stream stream show the other day, when somehow the conversation got on to Nick Marentes' first game "Stellar Odyssey" I was intrigued to hear that the game was mostly BASIC. I think Nick mentioned that it was a hard game to get running on emulators because it was designed in the form of three tape files. The first was a loader program that poked M/L language routines into memory. The main program was then loaded and run.  Finally a save game file was loaded to get you off and running, either from the initial starting point, or some other point that had been saved while playing. This system was used to save memory on the limited 16K of space of the early TRS-80 model 1 computer. Nick noted that it was unlikely people would bother to give the game a spin these days because of these complexities. I think Curtis suggested that it might be nice if someone could convert it to Coco.

I immediately typed into the chat to volunteer, since this is precisely the kind of program I love to convert. The program sounded intriguing. From the description Nick provided and subsequent investigation, I learned that the game uniquely combines elements of the text adventure genre, the RPG genre, rogue-likes, graphic adventures, and arcade animation. I searched online to see if I could find a copy on one of the TRS-80 sites I know, but I realized it wasn't listed in any of the usual places. So I asked in the chat if Nick would share his source code.  He generously agreed, so I sent him an email and he responded with the three files.

My first challenge was to try and load the files into my Model 1 emulator. For some reason this would not work. In the course of trying to figure out why, two things happened.  I somehow ruined my Model 1 ROM that I was using with the emulator, so that it stopped working. The second thing was I re-discovered forgotten knowledge I had once had about the different speeds that cassette files could be saved and loaded with on the TRS-80.  I think Nick's files were probably saved using the low speed setting and that I needed to type "L" at the Cass? prompt that TRS-80 Model 1s with Extended BASIC start up with.  But by this point, this knowledge didn't matter because my emulator was fried, and I had to go looking for either a new ROM or a new emulator. 

I came across an interesting online TRS-80 emulator that had some nice file handling utilities built in.  Using it I was at least able to view the files and extract the ASCII text of the main BASIC program file. Once I had that working I could begin examining the code. I couldn't run the whole program though because the emulator would only allow one file at a time to be drag and dropped on it. So I couldn't load Nick's loader program, and then have it load the main program, and then the game file to start the game. But not being able to run the program was not my chief worry. By just examining the code of the main program I was starting to suspect that the loader program might not just contain M/L routines to handle sound generation (as I had hoped), but that might also handle drawing the walls of the maze-like ship that you explore. I could tell that the USR calls spread throughout the main program were mostly of a type USR(0) to USR(255), which appeared from the BASIC routines to be doing something roughly equivalent to SOUND command-like stuff. Swapping the USRs for many such instances created the typical kinds of effects I also use in games using SOUND, so part of the mystery of the M/L USR calls was solved.

But there were some calls with values other than 0-255 (they appeared to be memory addresses). These were usually preceded by or connected with POKE commands to specific areas of memory. Some of the USR (0-255) type calls also had POKEs connected with them, but I guessed that these were simply fiddling with the pitch or length of the sounds being produced for certain sound effects.  But the ones relating to memory addresses were, I guessed, communicating info about rooms, so that a specific one could be rendered. There were a lot of rooms (86), and I began to despair that I would be able to port the game.

Then Canadian Thanksgiving happened and my software engineer son Charlie came home from Halifax. With his help I was able to view the bits of integer DATA from the loader program. I was able to guess by the length of that data that each room was composed by 5 single bytes, with the bits of each byte being used to render the 7 horizontal spaces of the 5 rows of each room. Then Charlie was able to craft an elegant algorithm in BASIC (with his old man's help with the archaic language) that would render the byte numbers into a stream of zeros and ones to print 3X2 blue blocks or black semi-graphic spaces to create the rooms on screen. Then we just had to extract the data from the loader program and put it into my slowly evolving Micro Color BASIC version of Nick's main program.

At this point we descended into Unicode Hell. I asked Charlie to create a Javascript routine to take the bytes from the loader program turn them into characters and break them into the 5 character strings for each room. First, the Javascript compiler wouldn't recognize some of the bytes generated from the code as ASCII because it insisted on translating some (sometimes all) of them from UTF-8 to two byte UTF-16 codes.  It was a monumental struggle informing ourselves and navigating these processes that occur behind the scenes in the Windows environment. So many landmines tripped over. Just switching between Notepad (Charlie's preferred editor) and Wordpad (mine), caused what felt like endless confusion. There was much hair pulling and debate about what was going on, but we finally figured it out and got what appeared to be a clean stream of 5 byte strings to render each of the 86 rooms. I say "appeared" because we seemed to have a few extra bytes. Two to be exact.

Then we descended into Micro Color BASIC text handling Hell. The BASIC Interpreter in the MC-10 and the Coco doesn't like dealing with characters below 32. And even some characters above that range have problems.  ASCII 32, for example, is always being hot swapped for a light green character 96 in the printable character set. Others can't be typed in from the keyboard and are annihilated by the interpreter when they are "quick-typed" in. Some of the graphic characters above 128, cannot be displayed in Windows editors and "disappear" when working with them. This meant we couldn't just easily create plain text strings to economically store the room DATA. But by translating that DATA into raw list of integers, and then rendering those as rooms, we at least were able to create a utility (ROOMS) to examine the maze. Most rooms looked okay, especially early in the list. But some of the later rooms looked messed up and didn't link up with other rooms properly. Those "two extra bytes" were clearly affecting things at certain points. But the real problem was that using raw numbers in DATA statements would require too much memory to work with Nick's main program. It was fine for a utility to just examine the map, but not for the game. We had to translate the data into CHR$ commands for some of the problematic bytes concatenated with strings of regular characters. Once again my son's Javascript (with another slight foray in Unicode Hell) was able to automate the process.

Then my son went home, and left me to figure out the extra two byte problem. This simply required using the evolving ROOM utility to explore the map and make guesses where the list of bytes had become misaligned by the rogue bytes. In the end there were not just two extra bytes, but also a few incorrect bytes.  As I said, the space character does not play nicely in the way the Color BASIC Interpreter handles it. So there were two rooms that I had to find close binary approximations to ASCII code 32. I think room 48 was one of these. In the end I was able to get all the rooms of the maze to properly connect up as I believe they did in Nick's original.

In the course of working on the rooms, and in examining and working on the main game code, I was able to begin to create a solution map of the evolving MC-10 version of the game.  I slowly was figuring out the puzzles and the clues (variables used in the save data were a great help here). I was creating lower res Colour equivalents (64X32) for Nick's higher res (128X48) semi-graphic characters and animations. I like to think that in making conversions from TRS-80 Senior to MC-10 there is an acceptable trade off between added colour versus lost resolution. But I don't know if Nick would agree.  But I think I've done the best that I can in rendering the game elements in a MC6847 environment. But I wish some folks would take the game for a spin, and offer constructive criticism to help improve it if necessary.

The process of translating the screen took more trial and error than I normally have to do for TRS-80 to MC-10 conversions, because the lower resolution of the MC-10 (32 versus 48 in the vertical) forced the title block at the top to have to be 3 lines, instead of two, to properly render readable letters of the game title. This meant everything on screen was pushed down by 1 row.  So instead of just taking all PRINT@s and dividing them by 2 (my normal process), I had to calculate the location of each PRINT@ and screen POKE and PEEK command. This would have been necessary eventually anyway, because I soon realized the game would just barely fit into the 20K of memory of an expanded MC-10. In other words, no simple divide by 2 kludge would be enough. Of course, in the emulator I could just turn on extra memory until I could get the program properly "slimmed down."

As I played the game I began to suspect that Nick's expectation of player expertise and persistence may have been just a bit too high. As a programmer, I have sometimes come to have overly high expectation of players. You live with a program so intimately as a coder that you know all its nuances and secrets. This can incline you to make a game more and more challenging so that it can maintain a challenge for you. As I played the game it appeared to me that the aliens, who begin to attack you above room 14 (there are two other main levels/areas of the map-- see above), come so often and with such intensity that I couldn't actually get through the map to the end without saving the game at the end of every screen to preserve my health and life. I had to resort to programmer tricks so I could test features, such as breaking out of the game, modifying the room number variable, entering "CONT" and zapping myself immediately somewhere I wanted to go.

So, I added difficulty level selection at the start of the game and nerfed the RNDs used for combat elements of the game. I have now played though on level 1, but if you choose level 3, you will be playing on an unadulterated Marentes level of play. The final win screen now also reports which level you are playing at. I also added to the clue provided by Nick (he has at least one clue for every puzzle) for solving the final puzzle. It makes it a little more apparent what you must do.  Otherwise you will likely have to die several times and restore from a saved game before you can figure out the final puzzle. Finding that clue is pretty tough and it will still require some careful interpretation. I also added a clue to another puzzle, to help you find a needed object a little more easily. I really would like some folks to try playing the game on the tougher levels (and without my map above) and to hear some feedback about whether I have nerfed the game too much.

The old clue.

I also changed the game save and load features. The original requires you to load a game at the start of each launch of the program. The standard "gamefile" just stores the ordinary starting details. Then you could just save new files, to start at different points in your progression through the game and load those instead. I chose to hard code the starting details and begin the game with those every time.  Then, if you want to save or load you simply choose "Q" to go to a file menu for these actions.  You can also restart the game from that menu, hence the "Q" for "quit" key choice.  You have to hold the Q down slightly to launch this menu, as it uses a different method (PEEKing the keyboard roll-over table)  rather than INKEY$ used for commands entry. This is a good thing, because it helps prevents triggering of the menu if you just brush the key. I also changed a few other keys. I switched the "V" key command (Verbs) to what I feel is a more standard "H" for help screen command. Since the normal MC-10 right arrow "S" key is used for the "Sprint" command, I used the < > keys (i.e. the comma and period) for TURN LEFT and TURN right commands. The other commands should be the same as the original and are listed by the "H" command. I should note that on Nick's web page it mentions one of the commands being "Attack" conceivably using the "A" key, but the command I found in his sources code was "F" for Fire.

I hope that I can take this completed program and convert it to Coco BASIC, but realistically, I don't think this will happen until Christmas. Once again, I had Charlie try to create a Javascript program to consistently convert all the raw semigraphic-4 characters embedded in strings into CHR$ and STRING$ commands as appropriate. But once again we descended into Unicode Hell, with some characters just not being sensed or sensed correctly. It is simply too daunting a task to think of doing this manually. But once we figure the graphic character conversion issue out, then I can simply manually translate the lines which the Color computer requires spaces to be inserted before command keywords, that the MC-10 interpreter doesn't have trouble with:

FORA=B_TOC_STEP

IFA_ORB_THEN

IFA_ANDB_THEN

I will also have to switch the CLOAD*array commands and CSAVE*array commands to Coco equivalent disk load and save routines. I had to convert Nick's routine, which saves 16 numeric items, and then a single string containing hashed information about items carried and/or the rooms in which they are currently located.  I convert that string into a bunch of integers, which I simply add to the numeric array values that I load and save using the special CLOAD* and CSAVE* command of the MC-10 (it's really convenient). I must say, the hashing routines created by Nick are amazing examples of memory saving technique, especially when one considers he was only in high school at the time. The whole program, in fact is a master class of memory parsimonious BASIC programming. And it's still elegant and readable to boot. My hat goes off to Nick. He's a national treasure of the Coco nation.

I think Nick might have had some M/L special effects as part of the final Win Game scene, which I have converted to flashing the screen to the alternate yellow/red character screen colours of the MC6847. But having never got the original game running, the special effects in the game are just my best guesses.

The Internet Archive is currently down from a cyber attack, but when it is back up and running, Maybe I'll put the Coco version of the game up there, unless Nick wants to pull the distribution in-house. But in the mean time, for testing purposes, the MC-10 version can be played for the next little while at my Gamejolt page:

https://gamejolt.com/games/jgmc-10games/339292

Just hit the big green "Play" button then select the "Text Adventures Requiring Save/Load" menu option.  Use the "Cassette" menu of the online emulator to select STLODSSY and type RUN and hit Enter in the main emulator screen. You should also be able to save and load the GAMEFILE, using the the buttons under the main screen.  Comments welcome.

ADDENDUM:

Nick contacted me, and helped me figure out the nuances of Discord so that we could have a chat about his game. He had some suggestions for how to make the screen more aesthetically pleasing and clearer. I've started to implement his suggestions, which really streamline things nicely. Nick thought the big title could go and be replaced by a simpler text title, but I'm kind of attached to his swoopy graphic title. But I did centre it a bit better. We also agreed to get rid of the difficulty level and just settle on the middle difficulty.

I've made some headway on the Coco conversion too! Should be out in the next couple of weeks.


Coco version finally completed! Here is the game playing on VCC


Edits up (Nov 8, 2024). Tweaked room descriptions. Added "You are" back to the beginning of the descriptions. And altered the hint I embedded in one of the room descriptions to help in locating a needed item.


ADDENDUM TO THE ADDENSUM:

I hoped to begin work on Nick's Stellar Odyssey II over Christmas, again with the help of my son Charlie, but he was only able to get back for a few days. I'm also worried that the second version is just that bit larger (it adds graphic "items" on screen rather than just as a list), that it wouldn't be able to fit it into an MC-10, and possibly not even a Coco 2. So I've shunted it to a back burner for the time being. But who knows, if Charlie comes back home for a longer period, maybe I'll resurrect the project. In the meantime, I did manage to squeeze in a brief coding activity over the holiday in the form of a simple Christmas demo and we had some discussions about my struggles with the "Cavernes" program conversion (see the prior post to this one). As usual, Charlie provided the music programing, and many helpful suggestions for the visuals. Thanks my Good Chum...


Merry Christmas folks and Happy Hogmanay 2024!

Friday, 30 August 2024

"Des cavernes dans le poquette" by Charles Feydy (1982) Update


"Some caverns in the pocket" is how I would translate the title of the game and article by Charles Feydy published in 1982. A while back I made and English translation from French and port of this little game from TRACE magazine Issue 2, 2nd quarter 1982, p. 62. This post is an supplement to the one I originally made on the project (https://jimgerrie.blogspot.com/2021/09/retrochallenge-2021-les-cavernes-by.html). It was prompted by a post by Jason Dyer on his "All Text Adventures" blog, who helpfully took the game for a spin.  He confirmed my vague sense at the time that the game was not functioning properly before I lost interest. I went back to look at some suspicions I had that differences in precision between Micro Color BASIC and the TRS-80 Pocket Computer 1, which was the original target machine, were not fully dealt with. In particular the exponent function's decimal precision has some wonkiness (try printing 10^7).

There is a bug/accuracy limitation in some early 80s Microsoft BASIC's exponent functions which produces erroneous decimals results rather than a whole number. For example, 10^7 on the MC-10 produces 9999999.99 instead of 10000000. Simply adding .5 and adding an INT (integer) function to any exponent function call can often clean up these possibilities. It seemed to clean up some of the weird room descriptions, but not all, and there seemed to be an inordinate number of dead ends still happening. It also improved the combat results, because the exponent function was also used in that subroutine.

I also altered some of the translation choices I made based on the comments from readers of Jason's blog. One about "trappe" being “hatch” versus an actual “trap,” as I had naively assumed, was especially helpful in clarifying an oddity I had noticed that "traps" didn't seem dangerous.

I now think the port might be functioning more-or-less correctly, and that any remaining difficulties might be inherent. The game represents an exercise in producing a simple “procedurally generated” dungeon based on the initial number you enter and the oscillating and pseudo random decimal numbers produced by the SIN function. Those numbers result in calculations that will recreate the same “dungeon” (arrangement of nodes, monsters, rings). What results is a mathematically generated series of unique interconnections that when combined with descriptive words creates a simple unique “maze".  However, this maze is not actually fully interconnected as you cannot actually reverse paths to go back the exact way you came.

Sometimes these interconnections end in dead ends–- either because you can’t pass a monster given the "rings" you have found– or because the node is simply empty (no ways out). Overall, I think this is essentially a mathematical challenge (not surprising for pocket computer owning crowd) of finding the right starting Dungeon Number and combat Level Number combo that actually has a possible solution.  Such a solution will involve being able to find a path that includes the right arrangement of rings and interconnected nodes to get all 10 of those rings, while also defeating all the monsters encountered along the way. The number of monsters defeated is counted as one's score.  So I think the ultimate goal of the game is to find the Dungeon number and path that will allow one to collect all 10 rings, with the intermediate goal being simply to get the highest monster kill rate.

I have to do some more testing, but that is the win hypothesis I am currently working on. I might be able to set my software engineer (and Math major) son onto the problem to see if gaining all 10 rings is mathematically possible. Maybe he could use a proper language and some AI techniques to find if there actually is “a solution” if my hypothesis is correct.  It is an interesting game-theory question if anyone is looking for a grad thesis.

I decided to create a completely alternate exponent subroutine to do my testing and allow me to fiddle with alternate ways of implementing the exponent function. As I noted, simply INTing the result was not enough to fully correct all the apparent errors in maze generation. In revisiting the source code and original listing I think might have also found a few bracketing errors, but not sure if they were the causes of any of the troubles I was having.

In the end I realized the problem was also a result of a slightly lower level of mathematical accuracy between the MC-10 and Pocket PC. The game relies heavily on the mathematical accuracy of the Pocket PC and its BASIC. Simply put, it needs 10 decimal digits to come out of SIN, whereas the MC-10 could only give 9. That is because the decimal is multiplied by 100 to give two hole number digits, which are used for combat calculations, plus 8 decimal numbers, which are used to store maze node information for 4 directions of moves. The Pocket PC apparently could give you a number like

90.12345678

Whereas the MC-10 can only give you

90.1234567

The 8 decimal number give 4 groups of 2 numbers which store the node information for the four directions of movement. If the first digit is 4 - 9 then you can go in that direction. If the second digit is odd and there is a monster present, then you will be blocked. If you defeat the monster then you will be allowed to move to a new room by adding one to that digit to make it an even number and then a new SIN number will be generated based on the current number. Since I was missing an 8th decimal digit I made it so that it is simply replaced by a zero.  So there will likely be differences in the maps of the original machine and the MC-10, but I don’t think it should matter that much. It is really a math nerd’s game, allowing the player to explore the interactions of a complex set of calculations “Fibonacci-style” as a dungeon maze.

Here is a vid of some early testing: https://youtu.be/N4bUl5sQNtA?si=k0mLNOnd-EH-Nu0j

Here’s a vid of a long play of the final iteration (I hope): https://youtu.be/M8UySLhMr80

The game can be played online here: https://archive.org/details/CAVERNES

As part of the testing I also did a MS Quick Basic conversion, which can be seen here:



The source for that version can be found on Github here:

https://github.com/jggames/QuickBASIC/tree/main/Cavernes

The source for the MC-10 version can be found here:

https://github.com/jggames/trs80mc10/tree/master/quicktype/Text%20Adventures/Cavernes

The last point I would like to make is about what genre this game fits into. It straddles the line between CRPG and text adventure. Since there is combat and "items" that can improve one's performance it seems like its a CRPG.  But there is no ability to define one's character or change it in any way beyond collecting the single type of item, which makes it an extremely limited form of CRPG.  But it also has all the tropes of a text adventure in terms of vocabulary: N S E W directional movement, Inventory, Look, and Get. The room descriptions are sparse but it is not really randomized in terms of the maze, as they are in many CRPGs.  There is a narrative "Get the 10 Rings" which will play out in the same environment every time, as in a text adventure.  And as in a text adventure there is a puzzle to solve-- Can the path to the 10 rings be found?  In the end I would describe this as a simple mathematical text adventure with CRPG elements.  Credit must be granted to the Feydy for being able to fit this into a machine with extremely limited memory.  He used a bunch of tricky techniques, including having the user key in all the description data by hand before every session, instead of using costly DATA statements redundantly reading their contents into separate array variables. Amazing! It is a tribute to the persistence of early computing pioneers on these extremely limited machines.

P.S.  Turned out there maybe were some precision errors in the mathematical routine to "snip out" the individual decimals in the node variable. When I printed its results they were offset at the third digit for some reason (more rounding errors?). That routine made two calls to the exponent function to do its calculations to derive a single digit from a designated location in the string of decimals. In the end I realized I could simply convert the decimal to a string and then use the MID$ function to snip the desired digit from the desired location. Then I could just use VAL to make that character back into a number. I had the luxury of memory to do this, although I think the routine was actually shorter, but it uses string handling, so I can't say for sure if it is actually more memory parsimonious.  Oh well, now the routine seems to work reliably.