First Post updated. New version released. Change log in first post.
First Post updated. New version released. Change log in first post.
Hey, the simulator is great, but it would be cool to have some probability distribution information. I talked to you briefly in the chat earlier today, and the best way to go about it is probably the simplest: just run a bunch of simulations. I don't suppose I could convince you to open source it so I can have a look? I'm still thinking about doing an exact probability calculation, or maybe I can make it faster for running a bunch of simulations. It's very hard to tell if I could do anything useful without knowing how it works now.
And for the record I start work on my PHD this fall. I am actually a computer scientist, for realz : www.alrecenk.com .
Thanks, Selak. Thoughtful of you.
First Post updated.
New features added and more checks to make sure the battles run are valid battles as well as a few error corrections.
Enjoy
Seems to be a few bugs in how splash damage is calculated, unless my own understanding of it is very wrong.
I thought it would simply take the damage and apply it to multiple units as necessary. For example, Skunk does 1-100 damage with 50% accuracy. Lets say he's up against 3 recruits.
If he does 100, he would do 40-40-20, killing two recruits and leaving one at half health. If he does 1, he would do 1 damage, leaving 1 recruit at 39/40 and 2 at full health.
But looking at the simulator, it's doing something weird. If he hit's all three, it says:
First, there's no way recruits should be going to -60... I would think he would take them to 0, then apply the damage to the next down the list. I'm assuming that's what the counter in parenthesis is supposed to be... the amount of splash damage left to apply. But then there's two bugs: the actual damage considered applied is wrong (its applying a full 100 at each step on the recruit HP display), and when it gets to a unit where the damage left should not be lethal it's doubly bugged: it's applying the full 100 (considering that unit "dead") and also considering him to apply the full unit's HP worth of damage (leaving a negative number in the damage remaining).Code:Skunk (3470HP) caused 40 splash damage (60) at Recruit (-60HP) Skunk (3470HP) caused 40 splash damage (20) at Recruit (-60HP) Skunk (3470HP) caused 40 splash damage (-20) at Recruit (-60HP)
Same bug is also happening when he rolls a 1:
In this case, again it's applying the full damage (in this case, 1) in the recruit's HP column but the bug with the first part is also there: it's considering him to do full lethal damage (40 splash damage) and thus bugging the damage remaining again (-39).Code:Skunk (2795HP) caused 40 splash damage (-39) at Recruit (39HP)
I hope that helps track down the bugs in the simulator, it's a really nice thing to have, I'm just trying to make it better and better![]()
Ill take a look at that. This is largely translated from an older german combat simulator and I am still learning how everything works (i understand 99% of it though). I will take a look at that splash code though and see if i cant figure out why its doing that. it could just be pulling wrong numbers from somewhere.
ok after looking at the code and fixing a small error in the code I can tell you what that phrase means and how it is fixed.
first ill start with the line in general:
Skunk (3470HP) caused 40 splash damage (60) at Recruit (-60HP)
that means the skunk that has 3470 hp at the time he did the attack caused 40 splash damage (with 60 splash left to do) to a recruit which was left at (x HP).
there are a few bugs in the code though. Instead of only applying the splash damage, the orginal code was applying full damage to each target, so it was basically saying it was hitting each from some amount of damage that was part of the full damage possible while really hitting each unit for full damage. That has been corrected in a new version I have just compiled.
the second bug is that it assumed that splash always had enough damage to kill the next unit (something that is about to be fixed with yet another new executable compiled).
there are probably a number of bugs like that throughout the program that are near impossible to see with out running every single case imaginable and that would take me forever to do on my own. Thus I am very glad that others are using this and providing helpful responses on thing they find funny in terms of program output. that second bug also causes the bug you see when the skunk fails his max hit role and instead only deals 1 damage.
Last edited by Selak; 08-03-11 at 10:54 am.
My guess is whatever code they put in for splash damage isn't working fully or isn't accounting for it right: part of it seems to be it's treating it like normal damage (thus the HPs going to -60, as if they were taking full damage). It needs to go to splash code fully whenever splash damage is given though, that way it doesn't "overkill" them and so it applies the only up to min(full hp, damage remaining).
Is the code open source? I don't do much with windows apps, but I'm pretty familiar with programming in general so I'd be happy to help if you'd like.
I can make what i have done open source and probably set up a page at sourceforge for working on it.
I have fixed the splash damage bit as i have mentioned in the above post, just need get around to zipping it and uploading it here. but as an example below is the code that actually does the damage (as i have fixed it i hope) but it relies on many other functions that I have no idea if they produce correct results yet because at level 20 I can't build all the units and have not sent armies at all the enemies I would need to attack to make sure its entirely correct. Though most of them its more of changing some static values to fix attack orders and the like.
Please note that some variables I have not changed to make them more understable yet and while I know what they represent, they are abreviations for the german words for what they represent like ae = attackingunit (agreifereinheiten in german).
Code:private void BattleRoundPhase(ArrayList a, ArrayList d, bool tower, int phase, int BattleType) { //Sort Attacker a.Sort((IComparer)new Unit.SortByPrioThenHp()); //Sort Defender if (phase != 1) d.Sort((IComparer)new Unit.SortByPrioThenHp()); foreach (Classes.Unit ae in a) { //Check that unit has the right attack initiative if (phase == 1 && ae.skills.Skill5 == false) continue; if (phase == 2 && (ae.skills.Skill5 == true || ae.skills.Skill6 == true)) continue; if (phase == 3 && ae.skills.Skill6 == false) continue; //Sorting due to First Strike if (phase == 1) { //If SequencePriority 12=chuck or 11=waltraud; reordering SortBysequencePrioThenHp, otherwise SortByHpThenPrio if (ae.SeqPriority.Equals(11) || ae.SeqPriority.Equals(12)) d.Sort((IComparer)new Unit.SortByPrioThenHp()); } //Calculate Damages - full of hits or blocks in order of hit with Tower bonus int damage = 0; // normal damage int splash = 0; // splash Counter if (BattleType == 1) { if (rdm.Next(0, 101) <= ae.HitChance) damage = ae.MaxDamage; else damage = ae.MinDamage; } else if (BattleType == 2) { damage = ae.MaxDamage; } else if (BattleType == 3) { damage = ae.MinDamage; } damage += damage / 100 * ae.skills.Skill1; //Bonus damage vs. units if (ae.skills.Skill3 == true) { splash = damage; } //Set splash damage counter, if any foreach (Classes.Unit de in d) { if (de.HitPoints <= 0) continue; //If defender has no HP move to next defender if (de.skills.Skill8 == true) //Specialists (Generals) will only be attacked when all normal units have no HP. { bool z = true; foreach (Classes.Unit item in d) { if (item.HitPoints > 0 && item.skills.Skill8 == false) break; else z = false; } if (z) continue; } if (de.skills.Skill4 == true && tower == true && ae.skills.Skill7 == false) damage = damage / 2; //Ignore Tower Armor int spl = de.HitPoints; //prep for dealing splash damage if (spl > splash) { spl = splash; } if (ae.skills.Skill3 == true) { splash -= spl; // Dealt splash damage will be removed from splash counter de.HitPoints -= spl; //Dealt splash damage applied to unit } else { de.HitPoints -= damage; // Results will be deducted from defenders } //Battle Report if (fullreport) { battlereport += "<p>" + ae.Typ + " (" + ae.HitPoints.ToString() + "HP)" + " caused "; if (ae.skills.Skill3 == true) battlereport += spl + " splash damage (" + splash.ToString() + ")"; else battlereport += damage + " damage"; battlereport += " at " + de.Typ + " (" + de.HitPoints + "HP)</p>\r\n"; } if (splash <= 0) { //12=chuck; 11=waltraud; resort where dogs attack yet if (ae.SeqPriority.Equals(11) || ae.SeqPriority.Equals(12)) d.Sort((IComparer)new Unit.SortByHpThenPrio()); break; // If the splash damage less than or equal to zero then next attacker } } } }
Cool, just tested the new executable and it's calculating and displaying it properly now it looks like. /thumbsup
The next thing I wonder is how the game sorts recruits... it looks like the simulator random sorts them each round (ie recruit #1 the first round takes 1 damage... next round he's recruit #10 so new recruit #1 takes 1 damage giving two at 39 instead of 1 at 38). I'm guessing it might be a bug within SortByPrioThenHp() but it's quite minor.
Are you aware that the version doesn't calculate the cavalry/guard dogs correctly? In the simulator, guard dogs will attack recruits first, not cavalry like they do in the game.