Warlords TBS Series
Spin-off Projects
Home Forum
Welcome,
Guest
|
TOPIC: Leadership, Fear and Combat
Re: Leadership, Fear and Combat 12 years, 11 months ago #235
Turtle,
Turtle wrote: I don't think so. I'm guessing average damage for a hit is actually: .9*(5+8 )/2 + .1*12 = 8.6 You'd added something wrong here when trying to factor in criticals. It should be: 5.85+1.2=7.05 So your numbers should be: Avg Damage Fear = .59*7.05+.41*1 = 4.56 per swing Avg Damage Leadership = .41*7.05 + .59*1 = 3.48 per swing First, for a 10 hp enemy unit, that result is based on your incomplete formulae. When critical hits are included that is not the case, and (using your "math") Fear gets to kill in 2 swings while Leadership requires 3 swings. (The same result is obtained for a 9 hp enemy unit, but not for an 8 hp one.) No, when corrected for the actual critical numbers we are once again back to 3 swings to kill with Fear or Leadership. Second, applying average damage in this way is not mathematically sound and is therefore not guaranteed to yield correct answers. In fact, such answers are almost certainly wrong -- the correct average # of swings are likely going to be non-integers. If you want to compute the real average # of swings the math isn't difficult, but it is a bit tedious. No, it's perfectly mathematically correct to apply average damage per swing in this manner to calculate theoretical results for balancing. How are you implying it's not sound? The average number of swings can *never* be non-integers. That's because swings are discrete events. You can't get a half swing AND there is no carry over damage. The only variable is the amount of damage done from the swing. Hence that's what you average. The concern was with the mixed-race stack causing a -3 morale drop giving the enemy extra attacks/hits and thereby offsetting the gains provided by the Fear +1. Not sure you get a -3 drop right away for having 1 evil unit as I recall you don't in all cases (forget exactly when those are). You might not even be getting the +2 unless you have 4+ men in your stack. Fear +1, Leadership +X, and -3 relative morale (against Leadership +X) = .55*8.6+.45*1 = 5.18 damage Leadership +X (against Fear +1, Leadership +X, and -3 relative morale) = (.45*8.6+.55*1) * (1 + 3% * +3 morale) = 4.8178 damage This comparison formula only makes sense if you have more Morale than your opponent AND after losing 3 Morale you still have more morale than your opponent. If it causes a switch in who gets the extra swings (or your opponent gets 9% more swings because he already had more Morale) then it changes quite a bit because you lose the chance and the opponent gains it. Plus the opponent strikes first in combat which can make a difference. So there are 3 cases to look at here: 1) You had more morale and STILL have more morale. 2) You had more morale and now your opponent has more morale. 3) Your opponent had more morale and now he has even more morale. KGB |
|
|
Re: Leadership, Fear and Combat 12 years, 11 months ago #236
You'd added something wrong here when trying to factor in criticals. Or divided/multiplied/entered... I'm going with "TI-85 malfunction" as I have no idea how that happened. Avg Damage Fear = .59*7.05+.41*1 = 4.56 per swing Avg Damage Leadership = .41*7.05 + .59*1 = 3.48 per swing And my 33% for amount of more damage from Fear than Leadership should instead be 31%. No, when corrected for the actual critical numbers we are once again back to 3 swings to kill with Fear or Leadership. True when using invalid math, but the invalid math is irrelevant because I am now computing the real thing. (See SIMULATION below.) No, it's perfectly mathematically correct to apply average damage per swing in this manner to calculate theoretical results for balancing. How are you implying it's not sound? I could argue the math theory, but that would consume much space and time and it might be hard to convince you that way. So instead I will just show that the results your math generates are wrong (and must therefore be invalid). (See SIMULATION below.) The average number of swings can *never* be non-integers. That's because swings are discrete events. Yes, swings are discrete events. Yes, against any SINGLE opponent the number of swings to kill that opponent is going to be an integer. However, the AVERAGE number of swings/kill against MULTIPLE opponents need not be an integer. And in fact when a sufficient number of opponents are considered the average is rather unlikely to be an integer. Let's say you are fighting 3 ememy units. It takes 2 swings to kill the first one, 5 to kill the second, and 3 swings to kill the third. What is the average number of swings per kill? At the risk of another TI-85 malfunction, I will state that the average in that case is about 3.33 swings/kill. SIMULATION As mentioned in a previous post, doing the correct math to compute average swings per kill is tedious. (And tedious math is also error prone, and my TI-85 is obviously not up to the task.) So instead I wrote a simulation. I ran a couple of scenarios: run parameters:
opponent HP: 10
chance to hit: 41.0%
# of opponents: 1000000
average swings/kill: 3.727246
average damage/swing: 3.4809274729921236
average absorbed damage/swing: 2.682946067954731 run parameters:
opponent HP: 10
chance to hit: 59.0%
# of opponents: 1000000
average swings/kill: 2.953923
average damage/swing: 4.5706810908747455
average absorbed damage/swing: 3.3853285952274312 ("absorbed damage/swing" takes into account the situation where the attacker would have done X damage but the opponent only had Y hit points remaining, where X > Y.) Because it is a simulation and operates over a finite number of simulated battles and uses a pseudo random number generator, it does not produce mathematically perfect results. (Then again, the Warlords game itself doesn't really produce mathematically perfect results either, which just means that "mathematically perfect" isn't actually what we want, but it's probably close enough.) However, you can see that the results are fairly close by comparing the average damage/swing with what you previously computed: fear case (+2 relative combat case; 59% chance to hit): exact = 4.56 sim result = 4.5706810908747455 leadership case (-2 relative combat case; 41% chance to hit): exact = 3.48 sim result = 3.4809274729921236 So, from the swings/kill sim results, we can see that Fear kills in an average of about 2.953 swings while Leadership kills in an average of about 3.727 swings. So Leadership on average requires about 26% more swings. (This is with 10 hp units and assuming those units have the same base combat score. The simulation can easily be run for other scenarios to see how it plays out.) This comparison formula only makes sense if you have more Morale than your opponent AND after losing 3 Morale you still have more morale than your opponent. ??? All of my scenarios have been "all else being equal". So this scenario was assuming that the two stacks' morale scores were equal before applying the morale adjustment caused by the use of the Fear hero. Note that the "+3 morale" in the equation is purely relative -- in reality it could be that the resulting morale was +1 for the Fear stack and +4 for the Leadership stack (both stacks at +4 before adjustment), but the actual absolute values do not matter to the combat equation, only the relative value matters. If it causes a switch in who gets the extra swings (or your opponent gets 9% more swings because he already had more Morale) then it changes quite a bit because you lose the chance and the opponent gains it. That's not right. Unlike the combat case, the morale function is "single ended". I.e., when there is a one point shift in relative COMBAT score you lose % chance to hit AND the opponent gains it. However, when there is a one point shift in relative MORALE score, EITHER you lose % chance for an extra swing OR the opponent gains it, NOT BOTH. Say the base Fear damage is FD and the base Leadership damage is LD, and the previous Fear morale multiplier is FM (e.g., 1.03 if the Fear stack had a morale score 1 higher than the Leadership stack) and the previous Leadership morale multiplier is LM. Then there are exactly 4 possible scenarios (ignoring cases where floor/ceil effects kick in): FD / (LD/LM * (LM + .09)) ; FM = 1.00; LM >= 1.00 ; ~0.91743 <= relative multiplier <= 1 (FD / 1.03)/(LD * 1.06) ; FM = 1.03; LM = 1.00 ; relative multiplier = ~0.91592 (FD / 1.06)/(LD * 1.03) ; FM = 1.06; LM = 1.00 ; relative multiplier = ~0.91592 (FD / 1.09)/ LD ; FM >= 1.09; LM = 1.00 ; relative multiplier = ~0.91743 (The "relative multiplier" is what you have to multiply the pre-morale-adjustment damage ratio by to get the post-morale-adjumstment damage ratio.) The difference between 0.91743 and 0.91592 is less than 0.2%, which is not particularly significant. In the first case, as the Leadership stack morale gets higher and higher, the 3 point morale shift has less and less impact on the relative damage, so it doesn't change the conclusion that Fear +1 is worth the morale hit. Plus the opponent strikes first in combat which can make a difference. That doesn't change relative combat score or relative # of hits (my original topic), or average damage/swing or swings/kill (per your expansion of the topic). How far do you really want to expand this topic? When we get to the point where one side wins the map are you going to bring up "Ah, but this side's retinue got more experience and will perform better on the next map..."? So there are 3 cases to look at here Actually you left out a case -- the one I was actually discussing. (I.e., opponent had same morale and now your opponent has more morale.) You also left out the case where you had more morale and now you have the same morale. ******************** source: hits.java ******************** import java.util.Random;
public final class hits {
public final static void main(String[] _) {
final int opponent_hp = 10;
final double hit_chance = 0.59;
final int num_opponents = 1000*1000;
final boolean details = false;
System.out.println("run parameters: ");
System.out.println(" opponent HP: " + opponent_hp);
System.out.println(" chance to hit: " + (100 * hit_chance) + "%");
System.out.println(" # of opponents: " + num_opponents);
final Random rand = new Random();
double total_swing_count = 0;
double total_damage = 0;
for (int i = 1; i <= num_opponents; i++) {
int hp_left = opponent_hp;
int swing_count = 0;
if (details) System.out.println("starting fight:");
do {
final int damage;
if (rand.nextDouble() > hit_chance) {
damage = 1; // miss
} else if (rand.nextInt(10) == 0) {
damage = 12; // critical
} else {
damage = 5 + rand.nextInt(4); // 5 + 0..3 => 5..8
}
if (details) System.out.println(" damage: " + damage);
hp_left -= damage;
total_damage += damage;
++swing_count;
} while (hp_left > 0);
if (details) System.out.println(" # of swings:" + swing_count);
total_swing_count += swing_count;
}
System.out.println("average swings/kill: " + (total_swing_count / num_opponents));
System.out.println("average damage/swing: " + (total_damage / total_swing_count));
System.out.println( "average absorbed damage/swing: "
+ ((double)(opponent_hp * num_opponents)) / total_swing_count);
}
} EDIT (4/19/11): Fixed hit/miss bug reversal by changing "rand.nextDouble() < hit_chance" to "rand.nextDouble() > hit_chance". Replaced output with data from new runs. (The new output is essentially the same as the old except the 41% and 59% cases are flipped.) |
|
Last Edit: 12 years, 11 months ago by Turtle.
|
Re: Leadership, Fear and Combat 12 years, 11 months ago #237
BTW, I realized there's an easy way to explain why your technique of taking HP and dividing by average damage/swing doesn't produce average swings/kill. And that is that you are failing to do two crucial things:
What I mean by #2 above is: What you are calculating is a kind of hypothetical/theoretical/potential average damage/swing, not the actual average damage/swing. I used the same terminology as you did (because switching terminology in the middle of a thread just confuses everyone), but I did feel compelled to qualify it with the words "ignoring things like ... an enemy unit not actually having enough HP to absorb the damage". To get the right answer for average damage/swing, though, you can't actually ignore that part. (That right answer, the actual average damage/swing, is what my program calls "average absorbed damage/swing". Because it is the actual average damage/swing, you can take the program's output and multiply "average swings/kill" by "average absorbed damage/swing" and get "opponent HP".) As long as I'm rattling on... Another way to see that the method you are using is invalid is to make the combat system simpler and the conditions absurd so the invalidity can't hide from even the casual observer. Say a combat system is either hit or miss (no criticals to complicate things) and a miss is 0 damage. To make the conditions absurd, say all units have 1 HP, all hits do 100 trillion HP damage, and % chance to hit is 0.001%. Calculating (the not correct) "average damage/swing" as 0.001% * 100e12 yields an average of 100e7 damage/swing. Trying to determine swings/kill the way you were would then mean dividing 1 HP by 100e7 and getting something very close to 0, which by your system you would round up to 1 swing/kill. Of course, it's obvious in this case that something's wrong, because only 1 out of every 10,000 swings even hits so there's no way the average swings/kill can be 1. When I talked about it being tedious to calculate, it's because to directly calculate it (rather than just simulate it) you have to basically build up a probability tree that terminates at the correct number of HP. You can represent this tree with one or more recursive functions. In general, if you want to actually be able to evaluate it you have to take care in how the functions are defined in order to avoid infinite recursion. (Basically you need to directly compute entire chains of "no forward progress" so they can't be infinitely long. That's actually not an issue in this case though since misses do 1 point of damage rather than 0.) And you will end up with a mess of an equation. (That's why I just skipped it and wrote the simulation, which is way easier to write/understand/verify/modify/etc.) But I wondered how bad it would be and decided to find out. Rather than try to expand/evaluate by hand, I made a program that does it (hits2.java). Here are the same two scenarios that I ran against the previous program: run parameters:
opponent HP: 10
chance to hit: 41.0%
average swings/kill: 3.727449182580777
average absorbed damage/swing: 2.682799821049818
counter: 265 run parameters:
opponent HP: 10
chance to hit: 59.0%
average swings/kill: 2.9538953171746165
average absorbed damage/swing: 3.3853603212875334
counter: 265 Unlike the previous progam, these are direct computations (no pseudo random number generator is involved), so they should be much more accurate. The function which is used to evaluate "average swings/kill" is avg_swings_per_kill, and then "average absorbed damage/swing" is just derived from that (and opponent HP): public final class hits2 {
final static double hit_chance = 0.59;
static int counter;
static double avg_swings_per_kill(int hp_left) {
++counter;
if (hp_left <= 0) return 0;
double temp = 0;
for (int i = 5; i <= 8; ++i) {
temp += avg_swings_per_kill(hp_left - i);
}
return 1
+ hit_chance * ( .9 * temp/4
+ .1 * avg_swings_per_kill(hp_left - 12))
+ (1 - hit_chance) * avg_swings_per_kill(hp_left - 1);
}
public final static void main(String[] _) {
final int opponent_hp = 10;
System.out.println("run parameters: ");
System.out.println(" opponent HP: " + opponent_hp);
System.out.println(" chance to hit: " + (100 * hit_chance) + "%");
final double aspk = avg_swings_per_kill(opponent_hp);
System.out.println("average swings/kill: " + aspk);
System.out.println("average absorbed damage/swing: " + (((double) opponent_hp) / aspk));
System.out.println("counter: " + counter);
}
} The "counter" variable isn't part of the computation, but instead (for my own curiosity) keeps track of how many times this recursive function would have to be expanded to compute the result. 265 times! Imagine doing that by hand. I think "tedious" may have been a slight understatement. Note that the number of branches in the probability tree blows up as the number of HP goes up. At 30 HP the function is expanded 778,993 times. At 100 HP -- well, who knows, it was taking too long to finish so I just killed the program. |
|
Last Edit: 12 years, 11 months ago by Turtle.
|
Re: Leadership, Fear and Combat 12 years, 11 months ago #238
I realized my code was unnecessarily inefficient. I added some explicit memoization code which completely collapses identical subtrees in the probability tree and run-time is now O(n) (where n = # of hit points). Using this optimization, doing the 10 HP case by hand would be feasible, though still at least a little tedious.
As long as this thing is now a quick-running program, I thought I'd modify it to spit out a full table of results. In the below table relative combat score is across the top, # of HP down the left side, and each entry indicates the average number of swings per kill for that combination of combat and HP (assuming no other influences on the battle).
import java.util.HashMap;
public final class hits4 {
static double hit_chance;
static HashMap<Integer,Double> cache = new HashMap<Integer,Double>();
static double avg_swings_per_kill(int hp_left) {
if (hp_left <= 0) return 0;
if (cache.containsKey(hp_left)) return cache.get(hp_left);
double temp = 0;
for (int i = 5; i <= 8; ++i) {
temp += avg_swings_per_kill(hp_left - i);
}
final double result =
1
+ hit_chance * ( .9 * temp/4
+ .1 * avg_swings_per_kill(hp_left - 12))
+ (1 - hit_chance) * avg_swings_per_kill(hp_left - 1);
cache.put(hp_left, result);
return result;
}
final static double[] chances = new double[]{
0.50, 0.55, 0.59, 0.63, 0.67, 0.70, 0.73, 0.76, 0.79, 0.82, 0.84
};
static double get_chance(int rel_combat) {
return rel_combat >= 0 ? chances[rel_combat] : 1 - chances[-rel_combat];
}
static double round(double value) {
return ((double)((int)(value * 1000 + 0.5)))/1000;
}
public final static void main(String[] _) {
final int opponent_hp = 10;
final int min = -5;
final int max = 5;
System.out.println("[table]");
System.out.print("[tr]");
System.out.print("[td]");
System.out.print("HP\\combat");
System.out.print("[/td]");
for (int c = min; c <= max; ++c) {
System.out.print("[td][b]");
System.out.print(c);
//System.out.print(" (" + ((int)(get_chance(c)*100 + 0.5)) + "%)");
System.out.print("[/b][/td]");
}
System.out.println("[/tr]");
for (int hp = 1; hp <= 30; hp++) {
System.out.print("[tr]");
System.out.print("[td][b]");
System.out.print(hp);
System.out.print("[/b][/td]");
for (int c = min; c <= max; ++c) {
System.out.print("[td]");
hit_chance = get_chance(c);
cache.clear();
final double aspk = avg_swings_per_kill(hp);
System.out.print(round(aspk));
//System.out.print(";");
//System.out.print(round(hp/aspk));
System.out.print("[/td]");
}
System.out.println("[/tr]");
}
System.out.println("[/table]");
}
} EDIT (4/19/11): Added source code. |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Last Edit: 12 years, 11 months ago by Turtle.
|
Re: Leadership, Fear and Combat 12 years, 11 months ago #239
Turtle,
Thanks for posting all this. I copied your code because I wanted to verify your results. I use C++ rather than Java so I ported it there basically 'as is'. I found I could not get your results. I also couldn't get anything that 'theoretically' looked close either. So I took a second look at the code you posted and found the following { final int opponent_hp = 10; final double hit_chance = 0.59; if (rand.nextDouble() < hit_chance) { damage = 1; // miss } else if (rand.nextInt(10) == 0) { } This says that 59% of the time you are missing. Thus it would indicate you are doing the leadership stack (41%) chance to hit. But the opponent_hp is 10 and not 8. So there is something wrong here. I suspect you may have been switching the hit chance and hp back and forth and forgot to change one of them thus skewing your results. So I put the combat code into a routine and pass the hit chance + hits to avoid this mistake myself which I am also prone to do I also added a bunch more data to the final results. I did this to verify my logic against the theoretical values for hits, damage, critical hits, first swing kill percentage (against the 10 hit unit it's only on a crit, against the 8 hit unit it's on a crit plus on 8 damage). It also has the added value of checking the randomness of the simulation.
void doCombat(int opponent_hp, int hit_chance)
{
int num_opponents = 1000*1000;
// int num_opponents = 10;
bool details = false;
int oneSwing = 0;
int twoSwings = 0;
int threeSwings = 0;
int moreSwings = 0;
int crits = 0;
int hits = 0;
printf("Run parameters: \n");
printf(" Opponent HP: %d\n", opponent_hp);
printf(" Chance to hit: %d\n" , hit_chance);
printf(" # of opponents: %d\n", num_opponents);
int roll;
double total_swing_count = 0;
double total_damage = 0;
srand(time(NULL));
for (int i = 1; i <= num_opponents; i++)
{
int hp_left = opponent_hp;
int swing_count = 0;
if (details) printf("starting fight:\n");
do {
int damage;
int roll = (rand()%100);
int crit = (rand()%10);
if (roll >= hit_chance) // Switched your logic here to make this right
{
damage = 1; // miss
}
else if (crit == 0)
{
damage = 12; // critical
crits++;
hits++;
}
else
{
damage = 5 + (rand()%4); // 5 + 0..3 => 5..8
hits++;
}
if (details) printf(" roll: %d\n", roll);
if (details) printf(" crit: %d\n", crit);
if (details) printf(" damage: %d\n", damage);
hp_left -= damage;
total_damage += damage;
++swing_count;
} while (hp_left > 0);
if (details) printf(" # of swings: %d\n", swing_count);
if (swing_count == 1) oneSwing++;
if (swing_count == 2) twoSwings++;
if (swing_count == 3) threeSwings++;
if (swing_count > 3) moreSwings++;
total_swing_count += swing_count;
}
printf("\nResults\n");
printf("total swings %d\n", (int)total_swing_count);
printf("total hits %d vs expected %f\n", hits, total_swing_count*(hit_chance/100.0));
printf("total crits %d vs expected %f\n", crits, (total_swing_count*(hit_chance/100.0)*.1));
if (opponent_hp == 10)
{
printf("One swing kills %d vs expected %f\n", oneSwing, num_opponents*(hit_chance/100.0)*.1);
}
else
{
printf("One swing kills %d vs expected %f\n", oneSwing, num_opponents*(hit_chance/100.0)*.1 + num_opponents*(hit_chance/100.0)*.9*.25);
}
printf("Two swing kills %d\n", twoSwings);
printf("Three swing kills %d\n", threeSwings);
printf("More than three swings %d\n", moreSwings);
printf("Average swings/kill: %f\n", (total_swing_count / num_opponents));
printf("Average damage/swing: %f\n", (total_damage / total_swing_count));
printf("Average absorbed damage/swing: %f\n",
((double)(opponent_hp * num_opponents)) / total_swing_count);
}
int main(void)
{
printf("Fear Stack\n");
doCombat(10, 59);
printf("\n\nLeadership Stack\n");
doCombat(8, 41);
}
These are my results: Fear Stack Run parameters: Opponent HP: 10 Chance to hit: 59 # of opponents: 1000000 Results total swings 2951708 total hits 1743127 vs expected 1741507.720000 total crits 174134 vs expected 174150.772000 One swing kills 59205 vs expected 59000.000000 Two swing kills 338277 Three swing kills 333202 More than three swings 269316 Average swings/kill: 2.951708 Average damage/swing: 4.572478 Average absorbed damage/swing: 3.387869 Leadership Stack Run parameters: Opponent HP: 8 Chance to hit: 41 # of opponents: 1000000 Results total swings 2992678 total hits 1227620 vs expected 1226997.980000 total crits 122628 vs expected 122699.798000 One swing kills 133176 vs expected 133250.000000 Two swing kills 301337 Three swing kills 264159 More than three swings 301328 Average swings/kill: 2.992678 Average damage/swing: 3.481348 Average absorbed damage/swing: 2.673191 The randomness seems *very* good over the million trials. The expected values for hits, critical hits and one swing kills are just about perfect. I also see the average swing per kills is 2.95 and 2.99. Virtually 3 swings and virtually identical. The big advantage for the Leadership stack is that you get SO many more 1 swing kills due to killing on 8 damage. This makes up for having fewer overall successful hits. Can you confirm again your code and results. Try adding in my extra output to see what you get. Not sure about your other tables since I don't have the code for those and thus didn't try to verify. KGB |
|
|
Re: Leadership, Fear and Combat 12 years, 11 months ago #240
Epic win on this whole thread.
But may I add something? There's just one thing that I don't like about your logic, KGB. You're assuming that the leadership stack to a larger degree will be fighting against evil units and opposite. This in itself is wrong. For example, in the Campaign you will fight approximately equal amounts of Good/Evil/Neutral foes, and this isn't in any way depending on the race you're playing. And even if it was, evil races can get Leadership heroes and the other way around. The average Life for a fodder unit is (including the Dragon Knight) 9.7. So that's what the stats should be run on (or 10). |
|
"Negate does not negate Negate."
--- KGB "Moreover, I advise that Daemons and Dark Elves must switch places on the Race Wheel." --- Marcus Porcius Cato
Last Edit: 12 years, 11 months ago by Seppuccu.
|
Re: Leadership, Fear and Combat 12 years, 11 months ago #241
Thus it would indicate you are doing the leadership stack (41%) chance to hit. Yes, the '<' should have been a '>' and I didn't notice because I was just looking for correct numbers in the output and I found them -- I just didn't notice that the correct numbers for 59% was in the 41% run and vice-versa. I have edited the post to fix that code bug and have replaced the output with fresh runs with the fixed code. But the opponent_hp is 10 and not 8. And? If you look at the included ouptut it clearly says "opponent HP: 10", which was my intention. I was just checking what happens if you have a Leadership +5 hero vs a Fear +5 hero, all else being equal. I suspect you may have been switching the hit chance and hp back and forth and forgot to change one of them thus skewing your results. The run parameters and results are both printed out by the progam, and I always copy paste them as a block, so you can count on the displayed "run parameters" being the real parameters I used to do the run and get the displayed results. Fear Stack Run parameters: Opponent HP: 10 Chance to hit: 59 ... Average swings/kill: 2.951708 Your 2.951708 result is pretty close to the (more accurate) 2.954 from my table (look at row HP=10, column combat=2), and is also pretty close to the "2.953923" my (now fixed) pseudo-random-number-generator (PRNG) based code produces. Leadership Stack Run parameters: Opponent HP: 8 Chance to hit: 41 ... Average swings/kill: 2.992678 Again, your 2.992678 result is pretty close to the 2.994 from my table (row HP=8, column combat=-2). It of course does not match either of my original (or fixed) "hits.java" runs because those were (as per its "run parameters") both run with 10 HP rather than 8 HP. I also see the average swing per kills is 2.95 and 2.99. Virtually 3 swings and virtually identical. But only if the Fear hero is loaded with low-HP units. What all of this is telling me is that you want to have high-ish HP (and high-ish combat) fodder (which may be a side which normally produces Leadership heros) and load up your retinue with Fear +5 heros (and/or produce/train Fear heroes as necessary/possible). If it's just Fear hero vs Leadership hero, with identical HP (and combat) units on both sides, what you get is:
(The above are average swings/kill, and are taken straight from the larger table in my previous post.) Even if you want to put all-same-race Fear stacks vs Leadership stacks, using 8 HP is kind of questionable because more of the Fear races have 9 HP than 8 HP. Furthermore, most of the 9 HP ones have 5 combat while all of the 8 HP ones have 4 combat, so the 8 HP Fear races will tend do even worse than you have predicted, and they make a very poor choice if you want decent fodder. If you go with the more common 9 HP Fear race rather than 8 HP, you end up with 3.382 swings/kill (for a Leadership +5 stack with 10 HP units) vs 2.954 swings/kill (for a Fear +5 stack with 9 HP units). The big advantage for the Leadership stack is that you get SO many more 1 swing kills due to killing on 8 damage. This makes up for having fewer overall successful hits. And that goes away if you are using 9 HP Fear units. Not sure about your other tables since I don't have the code for those and thus didn't try to verify. I have edited the post containing the table to also include the code that generates it. (If you don't have easy access to a hash map implementation that part can be easily removed -- the code will just run a bit slower without it.) And even if it was, evil races can get Leadership heroes and the other way around. Exactly. I think the correct assumption is that players will be playing to win. And that means (assuming they can get past all of the complexities we have been discussing and find their way to a good understanding of the game mechanics), they will be mixing things up in whatever way works best for them. |
|
|||||||||||||||
|
Re: Leadership, Fear and Combat 12 years, 11 months ago #242
Turtle,
I didn't realize you were using 10 hp units for both sides in your first run of the program. Thanks for amending the program + table. I agree that all players are playing to win. But you can only build either Fear or Leadership heroes. So you'll have to rely on ruins/offers to get the one you lack. So the exercise with the table can help to decide whether you prefer to play with a race that has Leadership heroes or Fear heroes. The trade off being extra moves all the time vs extra combat only at high levels. Typically I end up with my retinue containing 2 Fear and 1 Leadership hero regardless of Race I play. I don't find I have any problems winning with any of the Races so for me at least the Leadership/Fear difference isn't anything I think about when picking a side. I'm far more concerned with unit/race skills and Warlord type as those have 10X as much importance in the game as an extra point of life/strength. Otherwise everyone would just play the Dwarves and yet most players avoid that race due to it's slow speed / lack of flight. KGB |
|
|
Re: Leadership, Fear and Combat 12 years, 11 months ago #243
KGB wrote:
But you can only build either Fear or Leadership heroes. So you'll have to rely on ruins/offers to get the one you lack. Am I the only one who almost never produces heroes? KGB wrote: Otherwise everyone would just play the Dwarves and yet most players avoid that race due to it's slow speed / lack of flight. Straying somewhat from the topic, but yes and no. Dwarves have (imho) the best fodder units in their Axemen, but on the other hand they don't have any units that are really powerful. That's their major drawback in my, once again humble, opinion. |
|
"Negate does not negate Negate."
--- KGB "Moreover, I advise that Daemons and Dark Elves must switch places on the Race Wheel." --- Marcus Porcius Cato |
Re: Leadership, Fear and Combat 12 years, 11 months ago #250
But you can only build either Fear or Leadership heroes. What??? Help! Help! I'm being repressed! I think you have just provided the ending for a post I am working on. (That statement will make more sense when you see it. It may be a few days before it's ready though.) So you'll have to rely on ruins/offers to get the one you lack. Speaking of which, how is the distribution of sides determined as far as hero offers are concerned? Is it just flatly random, or is your side more likely but the rest equally likely, or are heros from adjacent sides more likely? I.e., should I stick to certain races if I want a better chance at being offered heros of the "opposite" (Fear vs Leadership) persuasion? Do ruins work the same way? I'm far more concerned with unit/race skills and Warlord type as those have 10X as much importance in the game as an extra point of life/strength. But many/most fodder units don't have very useful combat skills (X-slayer is too rarely applicable for me to consider it useful). And even for the ones that do it doesn't make a lot of difference because (due to Warlord 4's simplistic tactical combat system) fodder doesn't live long enough to level up and improve those skills to more effective levels. Dwarves have (imho) the best fodder units in their Axemen, but on the other hand they don't have any units that are really powerful. That's their major drawback in my, once again humble, opinion. I have (tentatively) made a similar assessment of the dwarves (and of the few W4 games I've played so far, most were played with dwarves). I think to do well you need two things: Cheap, quickly replaceable units that (with some stack bonuses, a tower, and possibly warlord/magic bonuses) are good enough to eat up the majority of enemy units, and some high-end units that can deal with the better enemy units. If you try to take out those better enemy units with your low-end fodder they just get chewed through too fast, and then you don't have enough fodder left to deal with the rest of the enemy stack (or later stacks). There are a lot of 11 and 12 base combat units which puts elementals/dwarf-heroes at 7/8 combat at a serious disadvantage. (12 vs 7 means +133% more relative damage, and 30 HP is not nearly enough to make up for that.) The reason I say "tentative" though is that crushing blow is a nice combat skill (which I almost always choose instead of warding) and I haven't done sufficient analysis to determine how much that combined with the high HP offsets the lower combat skill. (I'm guessing I will soon be expanding my program to account for various special abilities so I can check these things out.) I haven't minded the slow speed of dwarves because my play style has been to just slowly creep over the whole map and take it over. Most of my fights are defensive ones -- let the enemies slaughter their own units on my fortified cities while I slowly, when I'm good and ready, expand by taking theirs one by one. |
|
Last Edit: 12 years, 11 months ago by Turtle.
|
Time to create page: 2.83 seconds