Mercurial > hg > index.cgi
changeset 38:c8893fb9cacc
Decoded attack and damage calculations.
Decoded the code that calculates attack probabilities and also the damage
calculation. Also identified that several variables in the direct page MUST
remain in the same order with the same spacing for the combat routines to
work.
author | William Astle <lost@l-w.ca> |
---|---|
date | Sat, 27 Dec 2014 00:26:01 -0700 |
parents | 026865a318f3 |
children | 8fd288f0b01c |
files | dod.s |
diffstat | 1 files changed, 138 insertions(+), 89 deletions(-) [+] |
line wrap: on
line diff
--- a/dod.s Fri Dec 26 22:40:55 2014 -0700 +++ b/dod.s Sat Dec 27 00:26:01 2014 -0700 @@ -253,14 +253,16 @@ screendraw rmb 2 ; pointer to the parameter block of the screen to use for drawing V20D rmb 2 ; pointer to demo game command sequence objectfree rmb 2 ; pointer to next free object data slot -linebuffptr rmb 2 ; line input buffer pointer -playerloc rmb 1 ; current player position in maze (Y) -V214 rmb 1 ; current player position in maze (X) +linebuffptr rmb 2 ; line input buffer pointer +playerloc rmb 2 ; current player position in maze carryweight rmb 2 +; powerlevel, V219, V21A, V21B, V21C, and damagelevel must remain in the same specific order +; with the same spacing between them in order to match the same structure used by the creature +; data. powerlevel rmb 2 ; player power -V219 rmb 1 +V219 rmb 1 ; magical attack value (player) V21A rmb 1 -V21B rmb 1 +V21B rmb 1 ; physical attack value (player) V21C rmb 1 lefthand rmb 2 ; pointer to object carried in left hand righthand rmb 2 ; pointer to object carried in right hand @@ -833,22 +835,23 @@ stx 4,s ;* rti ; return to caller ; SWI 0 routine -LC384 lda effectivelight - tst V275 - beq LC38E - lda V26F - clr V275 -LC38E clrb +; Calculate base light level in dungeon. +LC384 lda effectivelight ; fetch effective light level in dungeon + tst V275 ; are we checking for special lighting conditions? + beq LC38E ; brif not + lda V26F ; get "passed out" fade state + clr V275 ; undo special light level checking +LC38E clrb ; default to full bright suba #7 suba V28B - bge LC39F - decb - cmpa #$f9 - ble LC39F - ldx #LCB96 - ldb a,x -LC39F stb lightlevel - rts + bge LC39F ; brif adjusted light level >= 0 + decb ; change to dark + cmpa #$f9 ; are we in a special light level range? + ble LC39F ; brif not - use the calculated value (dark) + ldx #LCB96 ; point to end of table of pixel masks + ldb a,x ; fetch value from pixel mask (1, 2, 4, 8, 16, 32) +LC39F stb lightlevel ; save new light level (full bright or dark) + rts ; return to caller ; SWI 1 routine ;*********************************************************************************************************** ; This routine renders a line graphic from the specification stored at (X). @@ -2702,10 +2705,10 @@ stb V21C tfr y,x ldu #powerlevel - jsr LD3D7 + jsr attack bmi LD099 playsoundimm $13 - jsr LD40C + jsr damage LD099 checkdamage jmp LD10F LD09E pshs a,b,x @@ -2990,9 +2993,9 @@ lda 13,u ; fetch physical offense value sta V21B ; save for combat calculations adda V219 ; calculate sum of magical and physical damage - rora ; divide by 8 - lsra - lsra + rora ;* divide by 8 + lsra ;* + lsra ;* ldx powerlevel ; fetch current player power jsr applyscale ; apply the scale factor calculated above addd damagelevel ; apply the wielding cost to play damage @@ -3012,15 +3015,15 @@ sta 9,u ; set to GOLD ring jsr LD638 ; update object stats appropriately LD2F7 ldd playerloc ; get current location in dungeon - jsr LCF82 - beq LD375 - ldu #powerlevel - exg x,u + jsr LCF82 ; find creature in the room + beq LD375 ; brif no creature + ldu #powerlevel ; point to player power level + exg x,u ; swap player and creature pointers lda 10,y ; fetch object type cmpa #1 ; is it a ring? beq LD31F ; go do successful attack if so - rings never miss - jsr LD3D7 - bmi LD375 + jsr attack ; calculate if attack succeeds (attacker in X, defender in U) + bmi LD375 ; brif attack fails ldy curtorch ; do we have a torch burning? beq LD319 ; brif not lda 9,y ; get torch type @@ -3032,20 +3035,20 @@ LD31F playsoundimm $12 ; play the "HIT" sound renderstrimmp ; display the "!!!" for a successful hit fcb $16,$f7,$b0 ; packed "!!!" string - jsr LD40C ; calculate damage, apply to victim - bhi LD375 - leax 8,u -LD32E ldx ,x - beq LD33A - clr 5,x - ldd 15,u - std 2,x - bra LD32E + jsr damage ; calculate damage, apply to victim + bhi LD375 ; brif not dead + leax 8,u ; point to inventory head pointer +LD32E ldx ,x ; get next inventory item + beq LD33A ; brif end of inventory + clr 5,x ; mark item as on the floor + ldd 15,u ; get location of creature + std 2,x ; put the object there + bra LD32E ; go process next inventory item LD33A ldx creaturecountptr ; point to creature count table for this level ldb 13,u ; get type of creature killed dec b,x ; reduce number of this creature type - clr 12,u - updatedungeon + clr 12,u ; flag creature as dead + updatedungeon ; update the dungeon display playsoundimm $15 ; play the "kill" sound ldd ,u ; fetch creature power level bsr asrd3 ; divide by 8 @@ -3117,54 +3120,100 @@ fadeout ; fade out the wizard resetdisplay rts -LD3D7 pshs a,b,x,u - lda #15 - sta accum0 - ldd ,u - subd 10,u - jsr LCA12 -LD3E4 subd ,x - bcs LD3EC - dec accum0 - bne LD3E4 -LD3EC ldb accum0 - subb #3 - bpl LD3FB - negb - lda #$19 - mul - jsr LCA99 - bra LD3FE -LD3FB lda #10 - mul -LD3FE std ,--s - getrandom - tfr a,b - clra - addd ,s++ - subd #$7f - puls a,b,x,u,pc -LD40C pshs a,b,x,y,u - tfr x,y - ldx ,y - lda 2,y - bsr applyscale - tfr d,x - lda 3,u - bsr applyscale - addd 10,u - std 10,u - ldx ,y - lda 4,y - bsr applyscale - tfr d,x - lda 5,u - bsr applyscale - addd 10,u - std 10,u - ldx ,u - cmpx 10,u - puls a,b,x,y,u,pc +; Calculate the probability of a successful hit. +; Enter with the attacker info pointed to be X and the defender data pointed to by U. +; +; It first does the following calculation: +; MAX(15-(4(DPOW-DDAM)/APOW),0) +; 4(DPOW-DDAM)/APOW yields a fraction which is < 4 if the defender's remaining health is +; less than the attacker's power or > 4 if the defender's remaining health is greater +; than the attacker's power. This ranges from 0% to 375% in steps of 25%. +; This result is subtracted from 15 so that low numbers mean the attacker relatively weaker +; and higher numbers mean the attacker is relatively stronger. The final range is from 0 +; (where the defender is much stronger than the attacker) to 15 where the attacker is very +; much stronger than the defender. +; +; These values are converted to a signed 16 bit number. Then an 8 bit unsigned random number +; is added to the result. Finally, 127 is subtracted. If the final result is < 0, then the +; attack fails. Otherwise, the attack succeeds. +; +; The following chart gives calculation results. V is the result of MAX(...) calculation +; above. Pb is the base value calculated by the routine. Rl is the low end of the range +; of the result once the random number is applied and the 127 is subtracted. Rh is the +; high end of the range. Finally, P% is the chance of a successful hit for that result. +; +; V Pb Rl Rh P% +; 0 -75 -202 53 21.1 +; 1 -50 -177 78 30.9 +; 2 -25 -152 103 40.6 +; 3 0 -127 128 50.4 +; 4 10 -117 138 54.3 +; 5 20 -107 148 58.2 +; 6 30 -97 158 62.1 +; 7 40 -87 168 66.0 +; 8 50 -77 178 69.9 +; 9 60 -67 188 73.8 +; 10 70 -57 198 77.7 +; 11 80 -47 208 81.6 +; 12 90 -37 218 85.5 +; 13 100 -27 228 89.5 +; 14 110 -17 238 93.4 +; 15 120 -7 248 97.3 +; +; As you can see, the lower 4 values are on a steeper slope than the remaining values. +; Otherwise, the scale is perfectly linear. Also, the worst chance of success, no matter +; how overmached, is 21.1%. The best chance, no matter how much stronger the attacker, +; is less than 100%. +attack pshs a,b,x,u ; save registers + lda #15 ; maximum value of the V calculation + sta accum0 ; initialze V accumulator + ldd ,u ; get victim power level + subd 10,u ; get difference between that and victim damage level (health) + jsr LCA12 ; multiply difference by 4 +LD3E4 subd ,x ; subtract attackers power + bcs LD3EC ; brif we wrapped - we have our quotient + dec accum0 ; count down quotient + bne LD3E4 ; brif we haven't counted down to nothing +LD3EC ldb accum0 ; get result (V as above) + subb #3 ; one of first three values? + bpl LD3FB ; brif not + negb ; now 0 became 3, 1 became 2, and 2 became 1 + lda #$19 ;* multiply by factor (25) + mul ;* + jsr LCA99 ; negate result (-75, -50, and -25) + bra LD3FE ; calculate attack +LD3FB lda #10 ;* multiply by factor (10) (all others are linear going up by 10 + mul ;* for each step +LD3FE std ,--s ; save probability base + getrandom ; get a random value + tfr a,b ; save random value + clra ; zero extend + addd ,s++ ; add to probabilty base + subd #$7f ; subtract 127 so that >= 0 is a hit, < 0 is a miss + puls a,b,x,u,pc ; restore registers and return +; This routine calculates the damage done by an attack. Enter with the attacker info at X and the defender +; info at U. +damage pshs a,b,x,y,u ; save registers + tfr x,y ; save attacker pointer + ldx ,y ; get attacker power + lda 2,y ; get magical offsense power + bsr applyscale ; scale it + tfr d,x ; save result + lda 3,u ; get defender magical defense + bsr applyscale ; scale it + addd 10,u ; add in defenders current damage + std 10,u ; save new defender damage + ldx ,y ; get attacker power + lda 4,y ; get physical offense power + bsr applyscale ; scale it + tfr d,x ; save it + lda 5,u ; get defender's physical defense power + bsr applyscale ; scale it + addd 10,u ; add to current defender damage level + std 10,u ; save new damage level + ldx ,u ; get defender's power + cmpx 10,u ; compare with new damage level + puls a,b,x,y,u,pc ; restore registers and return ; Multiply X by the value in A, where the binary point in A is to the left of bit 6. Return only the ; integer result in D (rounded down). applyscale pshs a,b,x ; save parameters and registers