Friday, 9 December 2022

Usborne Books "Dungeon of Doom" (1984)


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

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

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

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

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

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


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

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


Acknowledgements

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

Thanks again to Erico for his wonderful wall graphics.

Addendum

Here's me playing and winning a C64 version:


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

2 comments:

  1. Hi Jim. This is a great post. I am the guy who ported this game to Ruby, and uploaded the BBC Basic Code. I have fixed the minor change in line 950. I placed a higher value there because if the level contains fewer monsters/items the character doesn't get enough experience to descend to the next level. I've fixed this line now.

    Also, In your point 4, my code has 1310 R(EX,EY)=RND(8)+1+C0. Where the book has RND(9), this I think eliminates the Idol from appearing at it's last on the list. Your solution is more robust.

    I'm a big fan of these books (I have most of them). I also have ported the Haunted House text adventure game using Scratch (https://scratch.mit.edu/projects/130894359/) and on the Amstrad with the "Adventure Kernel System" game engine. (see my github).

    Thanks for keeping this project alive...

    ReplyDelete
  2. Hey Brian, Thanks so much for providing the source on Github. You saved me from having to type it all in myself. And thanks for keeping these cool games alive by giving them a new incarnation in a modern language. I loved the books too. I'll edit my post to give you proper attribution (always in a rush when I type these things up, then go back and fix them up in post).

    ReplyDelete