Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sample data for combat tests #488

Open
wheybags opened this issue May 1, 2020 · 13 comments
Open

Sample data for combat tests #488

wheybags opened this issue May 1, 2020 · 13 comments
Labels

Comments

@wheybags
Copy link
Owner

wheybags commented May 1, 2020

We need some sample data from the original game to verify our combat calculatiosn against.
I have implemented melee combat in accordance with the formulae from Jarulfs' guide, and from what I can tell they should be correct. However, it still feels to me like there is something off when attacking monsters in the first dungeon level, sometimes they seem to survive too long.

It would be useful to have some test data from the original game (ie, with this gear, hit this enemy, and then measure the damage dealt). Ideally we could rig the RNG to always do the max damage in range, never miss etc, to make it easier to compare.

We could use this sample data for automated tests.

@wheybags
Copy link
Owner Author

wheybags commented May 1, 2020

ping @AJenbo
I know it's probably a bunch of work, but given your involvement with the devilution project, is there any chance you would be interested in gathering some data for this? No pressure :)

@wheybags
Copy link
Owner Author

wheybags commented May 1, 2020

To start with just some values for a level 1 warrior in default gear hitting a zombie would be enough.

@AJenbo
Copy link

AJenbo commented May 1, 2020

warrior in default gear hitting a zombie

RNG locked to 0 (because zero is normally success)

INFO: MonsterTrapHit: monster -64
INFO: PlrHitMonst: monster -128
INFO: M_StartKill: Zombie
INFO: PlrHitMonst: monster -128
INFO: M_StartKill: Zombie
INFO: PlrHitMonst: monster -128
INFO: M_StartKill: Zombie
INFO: PlrHitMonst: monster -128
INFO: M_StartKill: Zombie
--- At this point I got stunlocked by the zombies because they always hit
INFO: M_TryH2HHit: player -35
INFO: M_TryH2HHit: player -32765
INFO: M_TryH2HHit: player -32765
INFO: M_TryH2HHit: player -31
INFO: M_TryH2HHit: player -8
INFO: M_TryH2HHit: player -32765
INFO: M_TryH2HHit: player -32765
INFO: M_TryH2HHit: player -32765
INFO: M_TryH2HHit: player -32765
INFO: M_TryH2HHit: player -31
INFO: M_TryH2HHit: player -8
INFO: M_TryH2HHit: player -32765
INFO: M_TryH2HHit: player -29
INFO: M_TryH2HHit: player -31
INFO: M_TryH2HHit: player -8
INFO: M_TryH2HHit: player -32765
INFO: M_TryH2HHit: player -27
INFO: M_TryH2HHit: player -31
INFO: M_TryH2HHit: player -8
INFO: M_TryH2HHit: player -32765
INFO: M_TryH2HHit: player -32765
INFO: M_TryH2HHit: player -31
INFO: M_TryH2HHit: player -29
INFO: M_TryH2HHit: player -32765
INFO: M_TryH2HHit: player -35
INFO: M_TryH2HHit: player -31
INFO: M_TryH2HHit: player -8
INFO: M_TryH2HHit: player -32765
INFO: M_TryH2HHit: player -32765
INFO: M_TryH2HHit: player -31
INFO: M_TryH2HHit: player -27
INFO: M_TryH2HHit: player -32765
INFO: M_TryH2HHit: player -32765
INFO: M_TryH2HHit: player -31
INFO: M_TryH2HHit: player -8
--- palyer dead

Note that health is health << 6 internally so that you can take fractional damage.

Some fighting with RNG enabled:

INFO: PlrHitMonst: monster -192
INFO: M_StartKill: Skeleton Captain
INFO: PlrHitMonst: monster -64
INFO: PlrHitMonst: monster -192
INFO: M_StartKill: Skeleton
INFO: PlrHitMonst: monster -448
INFO: M_StartKill: Scavenger
INFO: PlrHitMonst: monster -192
INFO: M_StartKill: Skeleton
INFO: PlrHitMonst: monster -576
INFO: M_StartKill: Fallen One
INFO: PlrHitMonst: monster -64
INFO: PlrHitMonst: monster -128
INFO: M_StartKill: Skeleton
INFO: PlrHitMonst: monster -192
INFO: M_StartKill: Skeleton
INFO: PlrHitMonst: monster -64
INFO: PlrHitMonst: monster -192
INFO: M_StartKill: Zombie
INFO: PlrHitMonst: monster -64
INFO: M_TryH2HHit: player -35
INFO: PlrHitMonst: monster -128
INFO: M_StartKill: Zombie
INFO: PlrHitMonst: monster -192
INFO: M_StartKill: Zombie
INFO: PlrHitMonst: monster -448
INFO: M_StartKill: Fallen One
INFO: PlrHitMonst: monster -128
INFO: M_StartKill: Skeleton
INFO: MonsterTrapHit: monster -128
INFO: M_StartKill: Fallen One
INFO: PlayerMHit: player -728
INFO: PlrHitMonst: monster -192
INFO: M_StartKill: Scavenger
INFO: PlrHitMonst: monster -128
INFO: M_StartKill: Skeleton
INFO: PlrHitMonst: monster -192
INFO: M_StartKill: Fallen One
INFO: PlrHitMonst: monster -448
INFO: M_StartKill: Fallen One
INFO: PlrHitMonst: monster -192
INFO: M_StartKill: Skeleton Captain
INFO: M_TryH2HHit: player -28
INFO: M_TryH2HHit: player -28
INFO: PlrHitMonst: monster -192
INFO: M_StartKill: Scavenger
INFO: PlrHitMonst: monster -192
INFO: M_StartKill: Skeleton
INFO: PlrHitMonst: monster -256
INFO: M_StartKill: Scavenger
INFO: PlrHitMonst: monster -256
INFO: M_StartKill: Fallen One

I'm making sure to only fight one monster at a time, all the hits will be on the monster that subsequently appears with the M_StartKill line.

I do at times get attacked by more than one mosnter so you won't be able to see exactly who dealt the damage to the player.

*: player -d The player was hit
*: monster -d A monter was hit
M_StartKill: * A monter played it death animation

@AJenbo
Copy link

AJenbo commented May 1, 2020

Also note that RNG in Diablo is biased.

@wheybags
Copy link
Owner Author

wheybags commented May 3, 2020

Nice, thanks a lot! When you say the RNG is biased, do you mean they do the modulo trick for generating a number in a range? (so, eg, rand(100) = rand() % 101) Or is it something deeper in their RNG implementation? I'm hoping we can just not replicate that defect, do you think it's significant to gameplay?

@AJenbo
Copy link

AJenbo commented May 3, 2020

It does affect gameplay a bit, but mostly in a negative way (streaks are more common then they should). If you aim to have comparability with save game files you will need to implement the RNG from Diablo (Borland C/C++) or items will not be regenerated correctly, but you could limit it's use to just the item loading code.

@wheybags
Copy link
Owner Author

wheybags commented May 3, 2020

I probably won't bother with that level of import, but a character stats / inventory importer is definitely on the todo list.

@AJenbo
Copy link

AJenbo commented May 3, 2020

Well you will need it for inventory

@wheybags
Copy link
Owner Author

wheybags commented May 7, 2020

Oh, are items stored as an rng seed or something?

@wheybags
Copy link
Owner Author

wheybags commented May 7, 2020

Ok, so I did some tests with damage:
We are currently handling damage as ints, so issue # 1 is that we need some fractional support.
Apart from that, I tried running the algorithms from Jarulf's guide in a python interpreter, and didn't get results that match the data you posted:

>>> strength = 30
>>> player_level = 1
>>> weapon_dmg = (2,6)
>>> weapon_type_modifier = 0.5 # zombie is undead and weapon is sword https://wheybags.gitlab.io/jarulfs-guide/#how-to-calculate-monster-data
>>> 
>>> def rand_in_range(lo, hi):
...      return lo # hack for testing
...  
... 
>>> base_damage = (strength * player_level) / 100 # https://wheybags.gitlab.io/jarulfs-guide/#damage-done
>>> base_damage
0.3
>>> 
>>> damage_calc = base_damage + rand_in_range(weapon_dmg[0], weapon_dmg[1]) # https://wheybags.gitlab.io/jarulfs-guide/#player-versus-monster
>>> damage_calc
2.3
>>> 
>>> final_dmg = damage_calc * weapon_type_modifier
>>> final_dmg
1.15

Final damage calculation is 1.15, whereas your data indicates it should be 128 / (1 << 6) = 2.

Any idea what's wrong here?

@AJenbo
Copy link

AJenbo commented May 7, 2020

Sorry, no clue about how to handle damage.

The first int in the item struct is it's seed value.

@wheybags
Copy link
Owner Author

wheybags commented May 7, 2020

Fair enough, thanks a lot for your help anyway!

@wheybags
Copy link
Owner Author

wheybags commented May 7, 2020

Ok, I did some more digging around, and it seems that while the hp variable for enemies is a fixedpoint value << 6, the damage calculations for melee attacks are actually done in unscaled ints anyway.
Some samples, of a warrior in default gear attacking an undead:
str 30, level 1: 2/128
str 50, level 4: 4/256

It seems freeablo is actually correct after all :p Still, it would be nice to get some tests in for this, I plan to add that soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants