A few questions and other animals

Discuss Chaos Strikes Back for Windows and Linux, an unofficial port of Chaos Strikes Back to PC by Paul Stevens, as well as CSBuild, an associated dungeon editor.

Moderator: Zyx

Forum rules
Please read the Forum rules and policies before posting.
Post Reply
User avatar
Automaton
Journeyman
Posts: 88
Joined: Sat Aug 28, 2004 10:49 am

A few questions and other animals

Post by Automaton »

Hey Paul,

Thanks for the PM - nice to know you are still around.

As well as the question I asked you by PM;

I've been looking through the logs to see how damage is done both from your party members to mobs and mobs to your party members.

Did I catch it correctly, that the attack log is just characters -> monsters and you can't see what mobs are doing to characters? Is there an option for that. I'm trying to ascertain the usefulness of shields as well as exactly how sharp damage is calculated (type 04).

I found this over at https://gamefaqs.gamespot.com/snes/5882 ... faqs/33244
- Sharp Resistance (SR): A 0..7 value which is used when monsters have a "sharp" attack. Sharp attacks use the following format to calculate armor: (Sharp Resistance / 7) * Armor Strength, so if the Sharp Resistance value is 0, a creature having a Sharp attack will ignore your armor.
For the purpose of that, does it average across all your worn pieces? ..and does it consider an empty slot as 0 SR? Do mobs target a particular body part and it uses the SR of that slot?

Still the damage log from chars is an eye opener. If I decipher the log correctly;

D4W is the monsters armour value.
D6W is your attack probability.
D7W is your potential damage

(I did not realise this) a negative value modifier is derived from your currentLoad/Maxload?

Low limit and high limit are both random numbers but I don't see how they effect the jump from quickness to finalquickness

Here is a block from a recent forray
BOB attacks from 02(14,12) to 02(13,12)
Attack type = 13 = SWING
Skill number required = 04
Byte20046[attackType=13] = 2
staminaCost = Byte20046[attackType=13] + Random(1) = 2
experiencedGained = Byte20178[attackType=13] = 6
Enter AttackWithPhysicalForce (attackType=13, skillNumber=4)
D6W=Byte20002[attackType=13]=32
D7W=Byte19958[attackType=13]=16
Calling DeterminePhysicalAttackDamage(character, monster, D5W-1, D6W, D7W, skillNumber)
Entering DeterminePhysicalAttackDamage(char=0,monster,P4=1,P7=32,P8=16,skillNumber=4)
levelDifficulty = 1
pi26 word2 &0x40 == 0 or vorpalOrDisrupt
Entering function to determine character's Quickness
quickness = (Dexterity=42) + (random(8)=7) --> 49
About to compute Maximum load
Loading effect=(quickness/2)*(load=133)/(maxload=470)-->6
Subtract loading effect from quickness -->43
Low Limit = random(8) + 1 --> 8
High Limit = 100-random(8) --> 100
Final quickness = 21
character's quickenss = 21

required quickness = (pi26.uByte8[4]=41) + (random(32)=24) + (levelDifficulty=1) - 16 = 50
Enter IsCharacterLucky (BOB , (luckNeeded=43))
Returning 1
Attack was successful because IsCharacterLucky returned true
D7W = Throwing distance=49
D7W = D7W+random(D7W/2+1) = 56
D7W = D7W*(P8=16)/32 = 28
D4W = (i26->uByte8[0]=28) + (levelDifficulty=1) + (random(32)=11) = 40
D7W = D7W + (random(32)=14) - (D4W=40) = 2
D6W = D7W = 2
Divide D7W by 2 --> 1
D0W=random(D7W) --> 0
D7W += (random(4)=2) + (D0W=0) --> 3
D7W += (random(D7W)=2)--> 5
Divide D7W by 4 --> 1
D7W += (random(4)=2) + 1 --> 4
Enter DetermineMastery(hero=BOB, skill=4)
Extract two flags from skill number.
flag8000 = skill&0x8000 --> 0
flag4000 = skill&0x4000 --> 0
SkillNumber = 4
Mastery = log2(Experience=258) --> 3
Mastery of skill 4 is 3
D0W = ((D7W=4) * (Bits8_11(i26.word16)=1)/16) + 3 --> 3
AdjustSkills((skill=4), (D0W=3))
Decrement Stamina by random(4)+4 = 5
w_2 = DamageMonster() --> 4
PhysicalAttack returning D7W = 4
Word20264 = Result of calling DeterminePhysicalAttackDamage = 4
Return 1
What's the math turning quickness 43 to finalquickness 21?

I think I'm correct in saying what you need to hit against is monsterdefense (pi26.uByte8[4]) + rand(32) + leveldifficulty - 16

Then that if you do hit, you have to do a "your" dmg vs the monsters armour (with quite a few rands in there too)?

Is it also correct that there are 3 chances to hit, quickness, check vs luck and then a 1 in 4 chance of auto hitting?

Checking this against the giant wasps - I see their values here are insane (150 defence and 180 armour - higher than even the dragon for both!) which is why they have 0 fire and poison resist I guess.

Cheers!
Nick.
User avatar
Paul Stevens
CSBwin Guru
Posts: 4318
Joined: Sun Apr 08, 2001 6:00 pm
Location: Madison, Wisconsin, USA

Re: A few questions and other animals

Post by Paul Stevens »

What's the math turning quickness 43 to finalquickness 21
/2 (Subject to low and high limits)

Line 2251 character.cpp

I'll add that to the log in future releases (if any)
User avatar
Paul Stevens
CSBwin Guru
Posts: 4318
Joined: Sun Apr 08, 2001 6:00 pm
Location: Madison, Wisconsin, USA

Re: A few questions and other animals

Post by Paul Stevens »

Automaton asked about this bug in a private message. I think this has
been discussed elsewhere, but I will repeat it here at the risk of being chastised.

Code: Select all

  //
  // *************** Spohia thinks the '/256' is a bug.**********
  // I will remove it as a test to let people try the game without it.
  //
  //D7W = sw(170 - w_10/256); //They stored a word and fetch a byte!
                            //Appears it was purposeful!
  //D7W = sw(170 - w_10); //They stored a word and fetch a byte!
  // *************************************************************

  D7W = sw(170 - w_10); //They stored a word and fetch a byte!  See discussion below.
/*
 *              Forum discussion.  Christophe Fontanel wrote the following:
 *But I did some additional research, and now I still think you should fix CSBwin as proposed, 
 *but this time for a different reason 
 *
 *Two facts:
 *1) What I said about the C source code I provided in my first post stands true: 
 *this code is the code that FTL used, because when compiled with the compiler that
 *they used back at the time, I get the exact same binary machine code.
 *Additional information: I have disassembled all Atari ST versions of both Dungeon 
 *Master and Chaos Strikes Back, and this function is exactly the same
 *in all of these versions.
 *2) What you said about the 68000 processor is correct, and clearly shows that the 
 *actual byte that is used in the computation is not the expected one. I have run the 
 *game in Steem debugger (ST emulator) and confirm the behavior that you described:
 *At the beginning of the machine code, d0 is initialized (as a word) with the statistic 
 *index that was passed as a parameter. This value can be 0 to 6 (there are 7 
 *statistics per champion). Then it is multiplied by 3 resulting in value 0 to 18. 
 *Consequently, the high byte of d0 is always 0 in all calls to this function. This 
 *means that the code always computes 170 - 0 = 170, thus completely ignoring the 
 *antifire, antimagic or vitality values of the champion. Clearly, this cannot be 
 *a behavior intended by the designers, that would make no sense!
 *
 *Because of these two facts, the only possible conclusion is that this is a bug 
 *in the Megamax C compiler itself. The 10 bytes temporary local variable is fully 
 *managed by the compiler, so this byte/word mismatch is now clearly a bug on the 
 *compiler part. The C code, as written by FTL, is correct, but the resulting 
 *machine code is just wrong.
 *
 *By using "/256" in the CSBwin source code, you reproduce the same buggy 
 *behavior: the statistic value is stored in one byte so with a value 
 *between 0 and 255. Divided by 256, you always get 0. You could as 
 *well replace D7W = sw(170 - w_10/256); by D7W = sw(170);
 *
 *
 *I had a look at the Amiga version of Dungeon Master 2.0 (that I have also 
 *disassembled). It was compiled with a completely different compiler (Aztec C, from Manx company).
 *Here is the assembly code for the same function:
 *Code: Select all
 *            LINK.W    A5,#0
 *            MOVE.L    D4,-(A7)    Backup D4 to the stack (D4 is used for 
 *                                  a local variable in this function)
 *            MOVE.W    12(A5),D0   12(A5) contains the statistic index, 
 *                                  as a function parameter
 *            MULU      #$0003,D0   3 bytes for each statistic
 *            MOVEA.L   D0,A0
 *            ADDA.L    8(A5),A0    8(A5) contains the address of the 
 *                                  champion data
 *            MOVEQ     #0,D0
 *            MOVE.B    71(A0),D0   This gets the current statistic byte 
 *                                  value and "converts" it to a word (high byte 
 *                                  set to 0 on previous line)
 *            MOVE.W    #$00aa,D4
 *            SUB.W     D0,D4       D4 = 170 - CurrentStatistic
 *            CMP.W     #$0010,D4
 *            BGE.S     LAB_0D77    Branch if D4 >= 16
 *            MOVE.W    14(A5),D0   Attack value
 *            LSR.W     #3,D0
 *LAB_0D76:   MOVE.L    (A7)+,D4    Restore D4 from the stack
 *            UNLK      A5
 *            RTS
 *LAB_0D77:   MOVE.W    D4,-(A7)
 *            MOVE.W    #$0007,-(A7)
 *            MOVE.W    14(A5),-(A7)
 *            JSR       -31104(A4)  Call ScaledMultiply function
 *            ADDQ.W    #6,A7
 *            BRA.S     LAB_0D76
 *
 *
 *As you can see, there is no mumbo jumbo with hidden local variables as 
 *in the Atari ST version. There is no ambiguity, and this time the correct 
 *statistic value is used to compute the difference with 170. Antifire and Antimagic do work fine in Amiga versions of the game.
 *
 *As a conclusion, I think there is indeed a bug in the original Atari ST 
 *version, but it is not a bug by FTL, it is a compiler bug. This bug is not 
 *present in other versions of the game because they use other compilers.
 *
 *You may choose to leave CSBwin as it is in order to be as faithful as 
 *possible to the original Atari ST game, or to fix this bug.
 *As you have already fixed in CSBwin many bugs of the original game, I 
 *think this one should be fixed too.
 *
 *
 * And I agree that the intent of the designers was to use the full word.
*/
User avatar
Automaton
Journeyman
Posts: 88
Joined: Sat Aug 28, 2004 10:49 am

Re: A few questions and other animals

Post by Automaton »

Thanks Paul,

I am currently pottering around your source code and I did see the text you posted - If I take it from the current live code, you have taken this bug out (the /256 is omitted)? Judging by the swap you had with Christophe, it looks like a compiler error to me. DM is already shady with all the things it hides, the last thing you need is hidden things going on that don't work :)

I'm no C++ expert (A long time ago, much basic, a bit of pascal and a fair chunk of 68000 assembly on the 'ol atari) but I am currently comparing your code against trace logs to see how things work and I've already got a few hundred lines of notes on how attacks are calculated. I got thrown a bit by by TAG0166b2 DetermineThrowingDistance (2268 in character.cpp). What you call throwing distance to me looks like a function to calculate a damage coefficient for any kind of hand held weapon. Quickness is definitely the D&D "To hit roll" and throwing distance is IMHO the base damage coefficient (including a weighting system based on how loaded the character is, the weapons actual weight). The more I looked at the trace and the code, the more I thought "Paul's own remark is correct, D4 is the monsters AC, why is it interacting with this 'throwingdistance' result?"

I particularly liked the StaminaAdjustedAttribute function. I would never have realised how you loose +/- 25% damage potential if you are under half stamina.

A few snippets of what my notes look like with values taken from a trace file (I worked out I could have the timer and attack trace at the same time.. ..duh)

Code: Select all

    Attack was successful because Lucky Hit (1 chance in 4)
D3	str //49 
D7	damage_coefficient = str+rnd(15) //56
D6	weapon_weight //35
D5	temp_maxload maxload/16 // (44/16)=27

if weapon_weight <= temp_maxload

damage_coefficient=(damage_coefficient+weapon_weight-12) //=(56+35-12)=79

else

	w_2 = (temp_maxload-12)/2+temp_maxload =((27-12)/2+27) //= 34
	w_12 = w_2 //=34
	
	if weapon_weight<=w_12
	damage_coefficient=(damage_coefficient+(weapon_weight-temp_maxload)/2) //= (56+(35-34)/2)=56
	
	else
	damage_coefficient=(damage_coefficient-2*(weapon_weight-w_2)) //= (56-2*(35-34))=54

if held_object != null and held_object is a weapon

	damage_coefficient = damage_coefficient + weapon byte 2 //= 54+42=96 // weighted coefficient is 54 and weapon byte 2 for the sabre is = 42 (base dmg)

Code: Select all

D4	monster_ac_coefficient //D4 is monster_ac_coefficient formed from the monsters AC (i26->uByte8[0]) + a rand + dungeon_level_difficulty

	monster_ac_coefficient = rand(32) + monster_ac + dungeon_level_difficulty //((0 to 32)+28+1) = (29 to 61) = 49
	
//So for a rockmonster this would be		(0 to 32)+170+1 = temporary AC of 171-203
//So for a screamer this would be		(0 to 32)+5+1 = temporary AC of 6-38

Code: Select all

//Required_to_hit (required quickness)
//pi26.uByte8[4] (in the code) placed in D3, is monster_defence_rating http://dmweb.free.fr/?q=node/1363
//to_hit value placed in D0
//D1 is a rand (32)
//leveldifficulty = dungeon_level_difficulty http://dmweb.free.fr/?q=node/692

required_to_hit = rand(32)+monster_defence_rating+dungeon_level_difficulty-16

//So for a trolin this would be 		(0-32)+41+1-16 = a defense rating of 26-58
//So for a scorpion this would be	(0-32)+55+4-16 = a defense rating of 43-75
//So for a dragon this would be		(0-32)+70+6-16 = a defense rating of 60-92
Cheers!
Nick.

P.S. I hope you don't mind me taking a poke about.
User avatar
Paul Stevens
CSBwin Guru
Posts: 4318
Joined: Sun Apr 08, 2001 6:00 pm
Location: Madison, Wisconsin, USA

Re: A few questions and other animals

Post by Paul Stevens »

I hope you don't mind me taking a poke about.
Good grief, no. That's why I publish it. After all, for the most part It's FTL code, not mine.
(You can blame me for the DSA. Sorry about that.)
Post Reply

Return to “Chaos Strikes Back for Windows & Linux (CSBWin) / CSBuild”