Tuesday, June 08, 2010

Hack Your Dunjonquest

My "map the Dunjonquest games" project was going fine until I hit level 8 of Hellfire Warrior. Not only does it feature some tricky "room connection" puzzles in the middle of the Great Plain, but it does not provide you with any room numbers. Even though I knew I'd still be able to solve the puzzle, it reduced my chances of ever being even remotely certain that the whole level was mapped. What would be the point of a half-assed job?

Well yeah, there'd be a point, but it would still be discouraging. So tonight I dove back into the Hellfire Warrior code -- which is very similar to the Temple of Apshai code -- and made a few changes.

Here are the things I've learned by poking around (literally). Some of them are generalizations based on Hellfire and Apshai that I haven't fully checked, so take them with a grain of salt.

The Files

"Temple of Apshai" contains the following files:

TEMPLE.PRG - The Innkeeper program
TEMPLE.DUN - The Dunjonmaster program
TEMPLE.PT1 to .PT7 - Files .PT3 to .PT6 are the data for levels 1-4, but the other .PT files are a mystery to me: character set data? Treasures? Traps? I haven't looked closely.

"Hellfire Warrior" is a bit more complicated, but the main files are:

INN - The Innkeeper program
DM - The Dunjonmaster program
HELLFIRE.5 to .8 - Levels 5 to 8.

There also appear to be different character sets for each level, and perhaps colour data for each level (since the levels ARE different colours).

The Code

The Innkeeper and Dunjonmaster programs are written in ATARI BASIC, with a few machine language routines that I think are for loading the custom character set and drawing the dungeon.

Here are some important things to remember when looking through the code.
  • It's atrocious. Just sayin'.
  • Variables that start with the letter U are really constants that represent numbers...U1 represents the number one, U10 represents ten, etc. This was a common way to conserve program memory, because the ATARI BASIC interpreter tokenized variables but treated every number as a separate piece of memory.
  • The code is full of PEEKs and POKEs, because all character and level data is stored directly to memory addresses, not usually -- as you'd expect -- in variables. This allows the data to persist when the Innkeeper switches to the Dunjonmaster and vice-versa, but it's extremely difficult to untangle.
  • Variable KA represents the memory address where the level data begins, and KB represents the address where the character data begins. In "Apshai," KA is page 103 (103*256) and KB is KA+2251.
  • Much character data is also mirrored in variables, and the program swaps between the variables and memory occasionally, which might explain some wacky behaviour.
  • Each level contains sixty (Q) rooms, but not all levels utilize every room. Judging by the file sizes (identical) I assume that the unused rooms are just full of padding.
Important Variables
  • L: Character level (see below).
  • O$: A string of all the commands that can be entered.
  • MSTR: The line number for monster routines (7000).
  • KF: The direction the character is facing (1 = up, 2 = right, 3 = down, 4 = left, I think).
  • YA: The character's vertical position.
  • XA: The character's horizontal position.
  • TA: Fatigue.
  • WC: Weight carried.
  • PC: Wounds.
  • PH: Maximum wounds.
Experience Points

One of the more mysterious aspects of both "Temple of Apshai" and "Hellfire Warrior" is how experience points are evaluated. You are told the number of points you have, and the "Book of Lore" says that you will benefit from a greater number of points, but it's difficult to figure out HOW.

Here's some insight. The programs DO check your "level" during combat, and characters with a higher level definitely get an edge in the calculations. Some stats also go up when you return to the Innkeeper with a higher level than you previous had (in a circuitous and bizarre chain of statements that I haven't bothered looking closely at).

How do you know when you've gone up a level? That would be nice to find out, wouldn't it? For some odd reason the programs never tell you, but the number of experience points you need to have for each level is 1000 times the square of the level number. So:

Level 1 = 2000
Level 2 = 4000
Level 3 = 9000
...
Level 20 = 400,000 etc.

The highest number of experience points you can get is 16,000,000.

Note that certain things in the game (like potions) can silently raise your stats, which might APPEAR to be a level bonus but isn't really. Also, "Hellfire Warrior" (at least the ATARI version) seems to have a bug where the Innkeeper gives you different numbers for your stats when you arrive from the ones you see when you return to the dungeon, and this discrepancy persists, as though the arrival stats are unmodified and the exit stats are modified by bonuses. Weird.

Important Line Numbers
  • 5000: Parses input at each turn.
  • 5100: Movement.
  • 5300 and higher: Other actions.
  • 7000: Monster stuff.
Unfortunately, many other routines -- various drawing and sound stuff, for instance -- is tucked away wherever it would fit. Lots of it is in the first hundred lines and is GOSUB'd to frequently. Presumably it's there because the earliest lines run fastest in ATARI BASIC.

Hacking the Program

It's easy enough to stop the program during operation (just press BREAK). To get back to the normal character set:

GRAPHICS 0

To reposition the coloured vertical bars (the remainder of the P/M graphics which represent you and a monster):

POKE 53248,0
POKE 53249,0

After you've made your changes, continue the program nicely with:

GOTO 5020

Make Mapping Easier

Here are some changes you can make to the "Hellfire Warrior" Dunjonmaster program to make mapping easier.

To force it to always print room numbers (which it skips for all levels numbered 6 and 8):

65 POSITION LS,U4:? "ROOM NO.:";

To always reveal a secret door when you (E)xamine a wall:

5701 IF PEEK(K+NT)=U3 THEN POKE K+NT,U2:RF(KF-U1)=U1:GOTO 5710

To always reveal traps when you (S)earch:

6300 IF PEEK(NP+KR)>U0 THEN GOSUB 670:GOSUB 679:GOTO MSTR

The last two might work in "Temple of Apshai" as well.

6 comments:

W.Robinson Mason III said...

Great stuff! I thought I saw a version of Hellfire Warrior out there higher than the file I'm using now that says "1.0" (I assume you have 1.0 as well). I wonder if the code is improved significantly in the later version. Perhaps I am thinking of one of the TRS-80 Dunjonquest titles...

Anyway, glad to see the project is still underway!

Gary said...

PEEKs? POKEs? Holy GOSUB, Batman!

I never got into these games on my trusty old Commodore 64 (which is still somewhere in a closet, near a dusty old 5-1/4" diskette drive).

But it's good to see the old BASIC code with its memory-specific PEEK and POKE commands. Brings back memories (and it beats programming in assembler).

Keep up the quest!

Muffy St. Bernard said...

Robinson, I think my Hellfire Warrior version is 1.0 too, but I'll double check...I actually have files from a few different sources.

Yup, still working through it all! Next step: maps that look a bit more professional. :)

Muffy St. Bernard said...

Gary, did you ever do Assembler programming? I wonder if anybody does nowadays. Ahhh, the days of the ML monitor wedge. :)

Also, the days of the million-dollar software success programmed by a single person in a bedroom.

Gary said...

I had tried my hand at Assembler just out of curiosity. Nothing like the smell of hexadecimal in the morning! Didn't do much of it, and I don't miss it.

Nowadays, computer success in the bedroom probably involves a Webcam and some acts more unnatural than machine code programming! ;-)

ballyalley said...

I used your tips to make the room numbers appear in "Hellfire Warrior" on the Atari 8-Bit computer. The tip worked well, but the BASIC line number that needs to be changed (at least in the version of the ATR disk that I downloaded from atarimania.com) is not the following:

65 POSITION LS,U4:? "ROOM NO.:";

It is line 95 instead. So it should read:

95 POSITION LS,U4:? "ROOM NO.:";

This is a great hint and it makes mapping the labyrinth much easier to do.