Ring Technical Documentation: Miscellaneous Ring

Introduction

Version 1.0
by Paul R. Stevens

This page documents some parts of the engine behind Dungeon Master and Chaos Strikes Back.

I would love to have help/company in these endeavors.

Contents

Color palettes
Light Levels
The game clock
Attack Computations
Timers

Color palettes

During adventuring there are always two palettes active. Because the Atari had only 16 colors there were not enough colors to simultaneously display the portraits at the top of the screen and the viewport. Especially this was true because the viewport had to be able to be dimmed in low light levels while the portraits had to remain at full intensity. So, while the screen was being painted by the CRT electron gun, the lines were being counted. When the viewport was about to be displayed, the palette was quickly changed. Then, when the viewport was complete, the palette was switched back again to display the text. So sixty times per second (fifty in Europe) the palette was changed twice.

The 'viewport' palette has two colors that are variable, depending on what monsters are present. They are colors number 9 and 10 (starting with zero). When the party enters a new level the list of possible monsters is examined and colors 9 and 10 are modified accordingly.

In the 'graphics.dat' file there is a graphic that CSBwin calls 'graphic #22e'. Among other things, it contains an array of 12-byte structures. The array contains 27 such structures (one for each monster type, I suppose). Currently, this structure is referred to as 'ITEM12' because at the time of its discovery the only thing I knew about it was that it was 12 bytes long. Byte 11 of the structure is used to set colors 9 and 10. If the upper 4-bit nibble of byte 11 is non-zero then it is used to set color 9. If the lower 4-bit nibble of byte 11 is non-zero then it is used to set color 10.

Light Levels

The various levels of lighting are accomplished by the use of six different color palettes, each with sixteen colors.  There are three (yes, three!) levels of indirection between the number representing the 'Power' of a spell or the 'charges' remaining in a torch and the selection of a palette.  The 'Power' of a Spell is used to calculate its 'Intensity'.  Then Intensity, in turn, is used to calculate the 'Brightness'.  And the Brightness is used to calculate the Palette Index.  If you like to add a fourth and fifth layer of indirection then you could say that the palette index is used to select a palette and the palette is used to select RGB values.

First we need to convert the Power of a spell (1 through 6) to an integer called 'Intensity' and an integer called 'Delay'.  The Delay will be explained later and is used to deterine how long the effect will last. This conversion is accomplished using fomulas built into the code.  Here are the formulas that are used:



Formula for Intensity
Formula for Delay
Oh Ir Ra
Light
4*(Power +1)/2-1
10000+512*(4*(Power+1)-8)
Ful
Torch
4*(Power+1)/4+1
4000+128*(4*(Power+1)-3)
Des Ir Sar
Darkness
4*(Power+1)/4
98

Here is a table of the Intensity/Delay values to make things easier to evaluate the relative usefulness:
Power/Charges
1
2
3
4
5
6
Oh Ir Ra
3/10000
5/12048
7/14096
9/16144
11/18192
13/20240
Ful
3/4640
4/5152
5/5664
6/6176
7/6688
8/7200
Des Ir Sar
2/98
3/98
4/98
5/98
6/98
7/98
So you can see that the OhIrRa spell is a little brighter than the Ful spell and lasts over twice as long.  You can also see that the effect of the Darkness spell disappears very quickly.

The intensity must be a number between 0 and 15 and is converted to 'Brightness' by the following table which is contained in the 'graphics.dat' file:
Intensity Brightness
0 0
1 5
2 12
3 24
4 33
5 40
6 46
7 51
8 59
9 68
10 76
11 82
12 89
13 94
14 97
15 100

As an example, a spell might have an intensity of 5 and it would contribute 40 to the Brightness.  When the spell begins to wear off its intensity will be reduced to 4 and it will then contribute 33 to the Brightness.  Similarly for Dark Spells which subtract from the Brightness.

The Brightness is a 16-bit signed value that can take on any value between -32768 and +32767.  The Brightness is converted to a Palette number using the following table that is contained in the 'graphics.dat' file:

Brightness Palette Number
99 or more 0
75 to 98 1
50 to 74 2
25 to 49 3
1 to 24 4
less than 1 5

Now we need to know how the Intensity of a Spell is decreases with time.  When a spell is cast an Intensity and a 'Delay' are computed as described above.  The Brightness is immediately added to the ambient light level and a timer is set to go off after 'Delay' ticks of the game clock.  When the timer expires, and every four ticks of the clock thereafter until the Intensity is zero, the Intensity is decreased by one, a new Brightness is computed, and a new palette is selected based on the total brightness.

Torches are strange animals.  The code goes through all of the Champions and makes a list of torches held in either the left or right hand.  The four torches with the most charges are selected and any others are ignored.  The four are sorted so that the torch with the most charges is first.  Then the Brightness is computed for each of the four torches using the Brightness table above with the Torch's number-of-charges as the value of the Intensity.  The brightness of the first torch is used as-is.  The Brightness of the second torch is divided by 2; the third by 4; and the fourth by 8.  The resulting numbers are added to the total light in the dungeon.

Every ninety seconds each torch currently in use has its number-of-charges decremented by one.  When it reaches zero the torch is marked as 'un-important'.  So, if you want your torch to last forever, put it down on the floor for a moment during the ninety-second update period so that it will be ignored.

The game clock

Here is what I remember and (hopefully) understand about the operation of the clock in CSBwin. Feel free to report disagreements, questions, and results contrary to what is reported here.

CSBwin was translated from the Atari machine language and the operation of its clock is, of course, patterned after the Atari version of CSB. The Atari clock was driven by the vertical retrace interrupts of the monitor. One unfortunate result of this is that in Europe people played CSB at 50 Hertz while people in the United States played at 60 Hertz. So here in the US we had to have 20 percent quicker wits when chasing Gigglers.

The internal clock in the game 'ticked' every 11 vertical retraces. That would be 183.33 milliseconds or about 5.45 'ticks' per second. I had initially assumed that the clock 'ticked' every 10 vertical retraces.....but I changed my mind. I now believe it was 11. At any rate, everywhere I have written about the game's timing I have said that each 'tick' of the clock represented one-sixth of a second. And that value has become the de-facto standard when converting time in the game's world to time in our world. For example, all the record-breaking races use this value to report the race's result. It may not be right, but it is consistent over the years and accurately reflects the number of opportunities the party has to make a move or the number of times a monster will attack or the time before a torch will burn out, etc.

So I wrote CSBwin and tried hard to reproduce the effect of the vertical retraces on the Atari. Of course your Windows machine has a vertical retrace much different and each monitor will be different, so I based the game's clock on the 'time-of-day' as reported by Windows. This is reported in sub-millisecond units as I recall and should be quite accurate. And I added one to the game's clock every 10 'virtual retraces'.

Then people wrote to me to say that the game ran much too fast. They were getting killed by Oitus that were dancing around much too quickly. Most of these people seemed to be in places that had 50-Hertz electricity. That would explain some of the difference since I was assuming 60-Hertz. Further investigation convinced me that I had made a mistake by assuming 10 vertical retraces per clock 'tick'....it should have been 11. But people were still unhappy. A lot of study convinced me that one big reason for the problem was that the Atari itself was so SLOW that even though it tried to run at 5.45 'ticks' per second it was not capable of this. It ran that fast when no changes were occuring in the viewport, but when the viewport had to be redrawn then the graphics overhead caused the game to slow down very significantly. The fact that the Atari programmers added an 'Extra Tick' to the clock whenever the pplayer moved is some evidence that they thought that movement caused a 'tick' to be lost.

Well, I finally gave up trying to make it exactly like the Atari (I did not want to try to emulate slowness). It is good enough. And I added a 'Speed' menu so that everyone can play it a speed they prefer. The 'Normal' speed is was set to only 4.0 'ticks' per second in deference to all those people who said the game was much too fast. The 'Fast' setting is at 5.45 'ticks' per second, the speed that the old Atari tried to maintain. Other settings are faster and slower yet. An the setting is noted in the recordings in a way that cannot be erased.

Attack Computations

Many people have asked about how to calculate the damage done when the party attacks a monster. Recently, a bug in the original Atari code caused me to look into this matter a bit deeper. The result is here.

Many variables are considered when computing the damage done when attacking a monster. And most are included in a non-linear fashion. It seems quite impossible to summarize the results in a formula or in words. So I have drawn a couple of flowcharts of the code. The names of the variables in these flowcharts are commonly the names of the registers used to hold the variables in the Atari code. Anyone who studies these diagrams and can suggest better names will find that I am eager to redraw the diagrams with the new names. Moreover, I would very much like to include some description in words. So if you can help me out, let me know.

One function, named DetermineThrowingDistance is used in several places (and for different purposes, it seems) to determine the effectiveness of a weapon. It should probably be renamed but I don't know yet what its name should be. It takes into account the skill required to use the weapon or object and the condition of the Hero's hand that is manipulating the object and the weight of the object, etc. There are 20 skills altogether, with the player seeing only the basic 'Strength', 'Dexterity', etc.

The function DetermineAttackDamage is called to determine the number of Hitpoints to subtract from a monster. Notice that 'Non-Material' beings and the 'Vorpal Blade' and the 'Dispell' attack are treated as special cases in the code. Also, the 'Diamond Edge' and the 'Executioner' are special cases. Notice also that there are several places where the damage done is set to zero and in each of these cases the player's Stamina is changed by 2 or 3. When the damage is non-zero stamina is changed by 4 to 7.

Timers

All of the action (opening doors, moving monsters, etc) in DM and CSB is operated by Timers. When you press a switch, a timer is created. A timer has a 'Target' cell (Level, X, Y). A Timer has a 'Timer Type' which depends on the type of cell (Trick Wall, Door, etc.) at its target. A timer has an 'Action' (Set, Clear, or Toggle). Here are diagrams of the various Timer Types:

Type 7 - Directed at a Trick Wall