"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.