Here's a screenie of the display tool prototype
(http://i.imgur.com/f4O8uZj.png)
It's about 80% functional atm and needs an actual UI design, but I am already finding it useful.
Here's the close of day screenshot. As you can see, it is coming right along.
Turns out that if you have large arena battle, the lua engine can miss some events, so that will just be part of life. I don't think it will be an issue to only use a handful of combatants at a time, since this is a very detailed and "zoomed in" tool.
I'm almost ready to open it up for beta testing after a few more UI features and polish.
(http://i.imgur.com/g3Mpr47.png)
Any thoughts? Wishes? Outrage?
I'm basically finished with set of 1.0 features that I want, but before I show off the final teaser screenshots, I should report on my analysis regarding the event system accuracy.
The event system has been shown to be missing events, duplicating events, and sometimes giving the event out of order. The heuristic system in the external analyzer app has been able to cope with this to the point that I can reasonably blame the apparent errors on the df hack lua eventful system. It's a great tool, but unfortunately with its polling mechanics, I don't think it will be able to achieve 100% accuracy. Repeat, I think that is OKAY for our uses.
I did experiment with turning down the calculation fps to 1, and it had no effect on the error rate.
I did experiment with pausing and stepping forward one frame at a time, it had no effect.
I did experiment with the unit.actions pattern that Roses suggested. In the end, I decided that our accuracy level is fine without having to resort to taking live samples every tick to ascertain my own high level events.
That said, I just made the external analyzer app detect missing events and highlight them for you. If we are going to be wrong, at least we can know we are wrong :) Furthermore, if any great and altruistic person ever took it upon themselves to try to increase the accuracy of eventful, then our tool might be a helpful aide.
With out further ado, I will now show the design I finally went with.
There are two parts to the solution.
The first is a combat sniffer lua script that you drop in %DF%/hack/scripts. To use the script, you go into arena mode and design whatever kind of battle you would like to record. When ready to start, you run the sniffer in the df hack window. This creates a "session", which is just a helpful way to group your combat data. You can also optionally give the session a name.
The result of running the sniffer is a combat-sniffer-log.txt that gets dropped in your %DF% directory next to game log.
The second part of the solution is the external analyzer app. With it, you can open sniffer log file, and it will show the results in exploded form for your analysis. I will let the screenshots answer the big questions for me, and you guys can point anything confusing. The ui design is basically just a 3 tab display, and here they are in order.
Report log display:
(http://i.imgur.com/Vnrk85x.png)
The Report Log tab highlights any combat log text that looks like combat information. If we were able to map it to a discrete event, then it is highlighted green. If we failed to find an event for the line, it is highlighted red. Sometimes it is red just because I haven't written a black list rule for things like "the elephant gives into pain", but most of the time it is because of the lua event system dropping data. My analysis of nearly 40 fights has shown ~95% accuracy, which I think is good enough.
The highlighted lines hyper link to the discrete strike data.
Strikes display:
(http://i.imgur.com/qGAjMkR.png)
This tab shows the stream of recognized attack strikes (no ranged yet), and you can see the resulting wound information, per body part tissue layer.
The attacker/defender lines hyper link to the units display.
Units display:
(http://i.imgur.com/GdYRv8M.png)
This tab lets you see all the body part information about the units involved, including body parts, tissue layer properties, attacks, armors, and weapons.
Anyway, thanks for anybody still hanging on to this thread. I can't wait to get it out in beta test so I can see how you guys use/break it :P I will report back with links and things once I'm ready for launch.
Here is an interesting case. Look at the two expanded strike results. This is from a big free for all where I gave a bunch of dwarves silver maces. The two highlighted are both the first strikes on an upper arm. Dwarf 2 swings with a momentum of 136 and Dwarf 7 swings with 145. However, the results are very different. In both strikes, each of the tissue results were the same so I only highlighted one in each strike result.
The big question is: If Dwarf 7 had more momentum, then how come Dwarf 2's swing managed to bruise the muscle, but Dwarf 7's swing only bruised the fat?
(http://i.imgur.com/lcqYXsk.png)
(http://i.imgur.com/o5BATTH.png)
Clearly there is at least one more factor at play here. They both did the exact same computed damage to all layers involved. Perhaps there is an RNG roll at each layer that might stop the attack, or something...
Here's another thing I'm stuck on. I have been focusing on understanding naked dwarves fighting with wooden swords. I am able to predict most of the behavior I see, except that the combat analysis tool shows me a very surprising value for the sharpness of a wagon wood short sword.
(http://i.imgur.com/TfgsS9Q.png)
It has a value of 500. However, the WOOD_TEMPLATE has [MAX_EDGE:1000]. I don't understand how it gets this value. My best guess is that the sharpness might be multiplied by a quality factory, and the arena creates average quality items with this factor = 0.5.
That's a conjecture. Does anybody know for sure how this 500 is arrived at as the sharpness for a wagon wood short sword?
Here's another one of the interesting cases that I'm currently analyzing. In this case, a kick attack (which does blunt damage) was performed on a toe. The nail was shattered. The interesting part is that the skin was "torn apart", flavor text usually reserved for edged attacks. The sniffer shows that indeed the nail and the skin layers took cutting damage. I am starting to suspect when subsequent layers are tested, the previous layer is treated as the strike material, and the stress mode (blunt or edged) might be picked dynamically based on the material/tissue properties. I suspect this kind of interlayer damage mechanic would only make sense for blunt damage inputs. Another alternative is that there is an unknown feature that can translate blunt damage back into cutting damage in some cases.
(http://i.imgur.com/McHgUko.png]http://i.imgur.com/McHgUko.png)
Hey everybody. I've been silent for a while, so I'll just post a teaser to give you an idea of my progress.
This is a screen shot of the list of combat simulation tests that I've been developing for my engine, and the output is within acceptable levels of variation from recorded arena data. They act like spot checks for all the numerical dynamics we are uncovering.
(http://i.imgur.com/VSDDSvc.png)
I'm still adding and exploring features, but I think you can see my general method. Once I have an engine with capabilities on these test points, which are meant to be low bounds, then I can set about formalizing everything into a comprehensive mathematical model that doesn't live only in my code. Said model documentation will either live here or on the wiki in a simplified form.
Finally, here is some sample combat log output from my program. I think it is very comparable to DF's output. Currently, I have a constructive model regarding all the mechanics you can see here. I still have lots of ancillary features to add, but the broad strokes are there, as you can see. I am currently only targeting the first strike consequences for a body part. Cumulative damage will be added as a separate stage of the analysis project.
(http://i.imgur.com/VdsJGtl.png)
In other forum threads regarding combat damage, there is a common topic of "strain" and, so far, I haven't been able to find any canonical definitions for DF's concept of strain. I will describe my interpretation of this number, which I give a high confidence since my engine uses it to produce output which agrees with DF. It has been working for me, and I use this to calculate dynamic strain (a value different for each strike), as opposed to the static strain that is implied from reading on forums.
double CalculateStrain(double strainAtYield, double stressAtYield, double currentStress)
{
var say = strainAtYield;
var youngs = stressAtYield / say;
return (currentStress / youngs) * 100000d;
}
The first argument is either IMPACT_STRAIN_AT_YIELD, or SHEAR_STRAIN_AT_YIELD, depending on the attack type (blunt or edged, respectively). The second parameter is either IMPACT_YIELD or SHEAR_YIELD, depending on the attack type. The third parameter is the dynamic stress felt by the layer in question. This value is calculated slightly differently depending on attack type and relative contact areas (deviations Da Vinci's model), but in the general case :
stress = Momentum / VolumeDamaged
The volume damaged is calculated exactly as described by Da Vinci:
if(weaponContactArea < layerContactArea)
{
VolumeDamaged = (weaponContactArea / layerContactArea) * ActualLayerVolume
}
else
{
VolumeDamaged = ActualLayerVolume
}
Anywho, I just wanted to share this tidbit, because it is a topic that comes up quite a bit, without any known definitive answers. Again, this will all be formalized, I hope you aren't put off by the little bit of c# code I gave to illustrate the calculation.
The only thing that this dynamic strain influences in my simulation is that it acts like an extra test before triggering the blunt bypass. If the stricken layer has STRAIN_AT_YIELD > 50k, then I check to see if the dynamic strain is greater than the STRAIN_AT_YIELD. If it is, then I trigger the blunt bypass case. If it is not, then there is no blunt bypass. This is how you can get wooden sword slashes and stabs that only "dent" the skin. If it only used the statically defined material property, then it would not be possible to dent the skin.
I also did some major deviations regarding the momentum deductions as damage passes through the layers, but I gotta stop myself somewhere :)
For completeness, you can find the referenced Da Vinci thread here : http://www.bay12forums.com/smf/index.php?topic=142372.0 (http://www.bay12forums.com/smf/index.php?topic=142372.0)