iopietro / Travianz-Legacy

Join our Discord Server: https://discordapp.com/invite/9fbJKP9 | New repo: https://github.com/iopietro/Travianz
GNU General Public License v3.0
160 stars 94 forks source link

The battle formula does not work properly #450

Open velhbxtyrj opened 6 years ago

velhbxtyrj commented 6 years ago

Please review the code in which the bonuses for the troops are summed up from the hero and from the Blacksmith and Armoury. According to my calculations, these bonuses are not taken into account.

There is a possibility that I made improvements through the admin panel. But it is unlikely that the problem arose because of this.

Shadowss commented 6 years ago

Works in combat simulator. Why you don`t give us a screen for an example :

Send 2000 Imperian with 20 level in Armoury to battle with 2000 Spearman with 20 level in Backsmith. Also send same 2000 Imperian level 0 in Armoury to battle with 2000 Spearman with level 10 in Blacksmith. And print us the screens.

velhbxtyrj commented 6 years ago

Most likely I was mistaken. But as for me, the formula does not work very well for calculating these bonuses.

velhbxtyrj commented 6 years ago

I understood what you meant

Here are some comparison attacks. And this happens in every report.

First Attack

1 2

Second Attack

3 4

martinambrus commented 6 years ago

calculations, calculations....... @AL-Kateb would you care to investigate this math as well perhaps? :)

AL-Kateb commented 6 years ago

I'm on it :)

AL-Kateb commented 6 years ago

Here are some comparison attacks. And this happens in every report.

I tested the bonus from blacksmith and armory, according to the code, and according to my testing it is working fine, I did not check the hero bonus yet, but as for these two, the battle report matched the simulation 100%, even though it was a little bit off compared to the regular T4 legends simulator, but that's a different story.

I think I know why your reports are different from the simulation, as I noticed you entered 2677 in the population, there is no village that can go that high in population, clearly you're assuming the population taken into account here is the account population, but this is inaccurate, the population used in calculation is the VILLAGE POPULATION not the account population, hence the real attack does not match the simulation.

As a side note, while I was at it, I was transferring troops from one village to another (Same account), and apparently there's something wrong with that code, something is wrong with returning the troops, after a few actions I was able to change the home for my troops from one village to another! Which is a big issue, players can exploit this to produce troops from one village and send them all (change their home) to another, it is not as straight forward as this, some condition needs to be met, I am gonna check how to replicate this and see how to fix it, then I will get back to you.

velhbxtyrj commented 6 years ago

The general population is taken into account (the entire account), since there is an additional bonus of protection for weak players (when attacking the strong on the weak), this exists from the very first travian.

I'll give an example: I'm top in the houses and the strongest player on the server. I have a village with a small population (in which all my main attacking troops) in order that the bonus in the attack is not taken into account. It will be stupid compared to players who started playing much later and much weaker than me.

Perhaps this is the problem of calculating battles. Because of the fact that only the population of the village is attacked.

Sorry for the bad english. I write through translator.

In English, I could not find descriptions where it was said that the general population was taken into account, I could only find it in Russian.

AL-Kateb commented 6 years ago

I completely understand your logic, and it makes perfect sense, but as far as I remember, I was in an argument with a friend of mine over this a couple of years ago, we tested the original Travian and we concluded that the population used here is the one of the village, not the entire account. Which as you said defeats the purpose of the bonus.

But regardless of how original Travian behaves, the code as it stands today calculates the population of the village, not the account.

I will do more research to check what population original Travian uses, and if it is the account's population, it is easy to edit the code to reflect that.

velhbxtyrj commented 6 years ago

I can give you a link to the Russian-language text, which describes completely how the simulator of strife works. You can read this through an interpreter. There is also an excellent resource where this calculator is available in an expanded form. It is recommended by a lot of people to use. There is an account of everything that is present in the game of travian. Also this calculator is available here. If you are interested in calculating, then I think you can ask Kirilloid himself what and how to count. I will also give a link to the calculation of formulas (also in Russian). If there are difficulties with the translation, I can help.

http://travian.kirilloid.ru/warsim2.php - Advanced battles calculator (excellent resource), pay attention to the population (when hovering on the field is written what kind of population) http://t4.answers.travian.ru/?view=answers&action=answer&aid=261 - How does the battle simulator work? (http://t4.answers.travian.com/index.php?aid=289 - I found this in English.)

An important factor is the total population of the attacker and defender (not just of the village, but the total pop of the account across all villages).

http://travian.wikia.com/wiki/Combat_simulator - on this site speak about Kirilloid https://github.com/kirilloid/travian - from Kirilloid for travian

AL-Kateb commented 6 years ago

I just tested on Travian, even though the result was not exactly as the simulator it was closer to the one where I put the whole population instead of just the village population, so you're right.

I will modify the code accordingly

velhbxtyrj commented 6 years ago

http://t4.answers.travian.ru/index.php?aid=345 - it's in Russian, I could not find it on the English site (The battle system: formulas) I'll try to find it in English, but it's unlikely.

martinambrus commented 6 years ago

A very nice debate guys, I appreciate the time you took to look into this :)

velhbxtyrj commented 6 years ago

@AL-Kateb you have not forgotten about this problem? :)

velhbxtyrj commented 6 years ago

@iopietro Please pay attention to this problem, it is very serious for the game process.

iopietro commented 6 years ago

Fixed in c3e2bae.

simulation attack

@velhbxtyrj Let me know if i can close this issue.

velhbxtyrj commented 6 years ago

With the game calculator this perfectly matches. But a little different from that of another calculator :)

iopietro commented 6 years ago

Which calculator do you use? I've tried kirilloid and it works fine. (without walls, palace/residence and blacksmith/armoury) kirilloid

velhbxtyrj commented 6 years ago

I only know the kirilloid calculator and I've been making attacks with improvements. Perhaps the situation is in bonuses from forges and walls. Here is my result of the attack: default 2

iopietro commented 6 years ago

Yeah, you're right, with no forges/walls our battles are equal to kirilloid battles, but with forges/walls they're slightly differtents.

iopietro commented 6 years ago

Ok, it should be finally fixed in 5f9186b . Blacksmith and armoury upgrades are now counted correctly: simulation simulation2

velhbxtyrj commented 6 years ago

This is an almost perfect battle :) You make the final decision :) default 1

iopietro commented 6 years ago

I think that our formula has a very little differences than the kirilloid's formula. So, considering that the two battles are very very similar to each other, this issue is finally resolved :) (the battle formula can't be better than this, unless kirilloid gives us his formula).

velhbxtyrj commented 6 years ago

@iopietro I wrote a letter to Kirilloid. Let's wait can help :)

kirilloid commented 6 years ago

Attack/defense points for units are rounded to 4 decimals places after upgrades. So values for units in the bottom table are EXACT: http://travian.kirilloid.ru/troops.php#s=1.36 52.4048 means 52.4048000000...

Wall bonus is rounded to 3 decimal places or 1 place if percents are used. Again, these are exact values: http://travian.kirilloid.ru/build.php#b=31&s=1.36 80.6% means 80.6000000...%

kirilloid commented 6 years ago

Total attack/defense points are rounded to the nearest integer. Also notice there’s a slight difference between upgrade formulas in T3 and T4/T5. The formula is correct with the latest commit—just pay attention, which version do you use in my site, everyone.

Formula guide in English: https://wbb.forum.travian.com/thread/75248-combat-system-formulas/

iopietro commented 6 years ago

@kirilloid, Thanks a lot! Tomorrow i'll look into these formulas.

iopietro commented 6 years ago

@kirilloid I've looked at our formulas, and they seem equal to your formulas.

For example: simulator1 simulator2

I think that the different results (with no wall bonus, no residence/palace bonus, no morale bonus, no unit upgrades bonus, etc.) are because of a wrong approximation in our formulas.

This is how our battle system works (without any kind of bonus):

For example: The attacker has 10k of Legionnaires and 90k of imperians (for a total of 100k of attacking troops). The defender has 50k of Phalanxes.

1) Calculate the total cavalry and infantry defensive points for the defender:

50k 40 = 2 Millions of infantry defensive points. 50k 50 = 2,5 Millions of cavalry defensive points. (useless in this case, because the attacker has no cavalry)

Involved troops in the attack= 50k.

2) Caltulate the total cavalry and infantry attacking points for the attacker:

10k 40 = 400k (Leggionaires) 90k 70 = 6,3 Millions (Imperians) For a total of 6,7 Millions of infantry attacking points and 0 cavalry attacking points.

Involved troops in the attack = 50k+100k, for a total of 150k troops.

3) Calculate the total attacking points:

Total attacking points = 6,7 Millions (because the attacker has no bonus in this case).

4) Calculate the total defensive points:

Total defensive points = Infantry defensive points * (Total infantry attacking points/Total attacking points)+0 (0 because there are no cavarly units).

Total defensive points = 2,0 Millions * (6,7 Millions/6,7 Millions) = 2,0 Millions.

5) And the winner is?

Total attacking points > Total defensive points, the attacker won.

6) Calculate the "K" factor: Involved troops >= 1000, so we have to calculate the K factor.

round(2*(1.8592 - Total involved units^0,015)) rounded at the nearest integer (or float), for a maximum of 4 decimal digits.

2 * (1.8592 - 150000^0,015)) = 1,3269 --> K = 1,3269

7) Calculate the result of the battle:

Attacker result (winner) = round((Total defensive points / Total attacking points)^K) rounded at the nearest integer (or float), for a maximum of 8 decimal digits.

Attacker result = (2000010 / 6,7 Millions)^1,3269 = 0,20105780 = 0,2010578

Defender result (loser) = round((Total attacking points / Total defensive points)^K) rounded at the nearest integer (or float), for a maximum of 8 decimal digits.

Defender result = (6,7 Millions / 2000010)^1,3269 = A number greater than 1. Defender result = 1.

8) Calculate the attacker losses:

10k 0,2010578 = 2010,578 = 2011 Leggionaires (rounded at the nearest integer/float number). 90k 0,2010578 = 18095,202 = 18095 Imperians

9) Calculate the defender losses:

50k * 1 = 50k Phalanxes, all defender's units are dead.

So, i don't know what approximation is wrong.

P.S: Sorry for the wall of text, lol.

kirilloid commented 6 years ago

Step 6: rounds to the nearest multiple of 0.0002, the formula should be

2 * round(1.8592 - pow($total_units, 0.015), 4); // 1.3268946071185956

K = 1.3268

iopietro commented 6 years ago

Ok, I modified the formula from:

round(2*(1.8592-pow($involve,0.015)),4);

To:

2*round((1.8592-pow($involve,0.015)),4);

($involve = total units)

But there's still a very little difference (without bonuses):

simulation2 simulation1

Infantry attacking points = 1635870 Cavalry attacking points = 628080

Infantry defensive points = 805660 Cavalry defensive points = 2275410

Total attack points = 2263950 Total defensive points = (Infantry defensive points (Infantry attacking points/Total attacking points)) + (Cavalry defensive points (Cavalry attacking points/Total Attacking points)) + 10 = 1213417,7771152

K = 1,3634

Attacker final result = round((Total defensive points/Total attacking points)^K),8) = 0.42728169 Defender final result = 1

Attacker losses: 19293 0,42728169 = 8243,54564517 = 8244 Leggionaires 12345 0,42728169 = 5274,79246305 = 5275 Imperians 5234 * 0,42728169 = 2236,39236546 = 2236 Equites Imperatoris

Defender losses: all troops are dead.

iopietro commented 6 years ago

I changed that formula with your formula and it seems to work great:

 $rdp = round($cap/$rap, 4)*($cdp) + round($ap/$rap, 4)*($dp) + 10;

1) $rdp = Defender result points 2) $cap = Cavalry attacking points 3) $ap = Infantry attacking points 4) $cdp = Cavalry defending points 5) $dp = Defensive points

kirilloid commented 6 years ago

Yes, wanted to say about the mix of infantry and cavalry, should be round to 4 decimal places. Total defensive points would be 1213418 rather than 1213417,7771152, total points are rounded to the nearest integer (that's obviously important for small values). Attacker final result no need to rounded with round(... , 8) Doesn't really matter, though.

iopietro commented 6 years ago

Ok, thanks, i modified it and now it works great, with all kinds of bonus (walls, residence/palace + base defense, troops upgrades) except for the morale bonus, i don't know how it should be approximated (i tried 3 decimal digits):

If Total attacking points < Total defending points

$moralbonus = round(min(1.5, pow($attpop / $defpop, 0.2 * ($rap / $rdp))), 3);

else

$moralbonus = round(min(1.5, pow($attpop / $defpop, 0.2)), 3);

But it's slightly different than your simulator.

kirilloid commented 6 years ago

Yes. I use a single expression with min function, but the logic is the same. The trick is inverse value should be rounded. You might think about it as a handicap for attacker rather than moralebonus.

// here it's still a bonus, you multipy it the same way in all other parts of code.
$moralebonus = 1 / round(max(0.667, pow($defpop / $attpop, 0.2 * min(1, $rap / $rdp))), 3);

Also I don't see from the code your shown, whether there's a check that moralebonus cannot be less than 1.

iopietro commented 6 years ago

Nice, it works perfectly :)! Yes, it's a huge handicap in certain cases. Yeah, there's a control which decides if it should apply or not the formula, this is the whole code:

        if($attpop > $defpop) {
            $moralbonus = 1 / round(max(0.667, pow($defpop / $attpop, 0.2 * min(1, $rap / $rdp))), 3);  
        }else{
            $moralbonus = 1.0;
        }
iopietro commented 6 years ago

I've another question, what is the formula which determines the new level of a building partially demolished by catapults/rams (I can't find it in your guide)?

For example (with no bonuses, no defenses, no losses):

10 catapults will bring a building from level 20 to level 18, how can i know that the new level must be 18?

kirilloid commented 6 years ago

https://wbb.forum.travian.com/thread/75248-combat-system-formulas/ See 3.a Catapults Target level N. For every level k find amount of catapults enough to demolish building completely. Find minimum k such that (amount of catapults to demolish N) minus (amount of catapults to demolish level k), that would be final level.

Actually I don't know why do you need super-precise calculations. My research is not ideal anyway. There are problems with stonemason or/and artifact. Formula gives big error for lower level buildings.

iopietro commented 6 years ago

Thanks! Yeah, I saw that chapter, but I haven't thought about that formula. Because your combat system simulator is the best external tool for simulating travian battles :)! It could give errors for lower level buildings and stonemason/artifact, but it's much better than our previous formula (not the actual one that I've made, that works pretty good) that used to calculate square roots of negative numbers, lol (resulting in an error, obviously).

Shadowss commented 6 years ago

Can be closed ?

iopietro commented 6 years ago

Not yet, there's still a discrepancy with the battle formula, when you attack a village with a wall and you damage/destroy it, the whole battle is recalculated, but battle results are a lot different than the original travian.

Shadowss commented 6 years ago

Ahh ok

Shadowss commented 6 years ago

I wanna ask if is counted in battle formula next attributes :

kirilloid commented 6 years ago

Maybe, create a separate issue for rams? For me “combat formulas” seems more like an epic, rather than one issue. But it’s up to you.

Walls durability coefficients are:

kirilloid commented 6 years ago

Also you might be interested in https://github.com/kirilloid/travian/commit/4a78db0d614e58a97dd03facf0581220665d3330

iopietro commented 6 years ago

@shadowss, Yes, they're already implemented.

@kirilloid, The only wrong formula is the one that recalculates the battle after the destruction/damaging of the walls, while the formulas that calculate how much a building have to be damaged (for rams and catapults) are slightly different than yours.

iopietro commented 6 years ago

@kirilloid Sorry in advance for the distrubance, but I would ask you some questions:

  1. I implemented your exact formula ("demolishPoints" in kirilloid/travian@4a78db0), but I don't know the exact point of it in which I can divide or multiply the catapults morale bonus.
  2. In a forum thread, you talked about this: immagine How can this "virtual intermediate level" be calculated?

Thanks for the help!

kirilloid commented 6 years ago

Technically now I have a solution, but it is incorrect with low wall levels and artefacts. Let me play with new simulator on PTR and I'll return back to you.

iopietro commented 6 years ago

Ok, thanks again :).

kirilloid commented 6 years ago

In new simulator rams works just incorrectly

iopietro commented 6 years ago

Lol, nice, did you report it to the Travian's devs?

kirilloid commented 6 years ago

Yes, I reported and they accepted it. I'm in the process of updating code, rams weren't added yet, but you might be interested in other aspects, illustrated with tests: https://github.com/kirilloid/travian/commit/26b27f0a9a98dda196c9154faf1545dbd9ac5066