Update #3
This should've been included in the last update, but it caused me some headache; it may not even be the final version (see explanation below).
Fixed a minor bug where the alliance mapping was broken due to another change in the code. This caused the alliance setup to be never working, and the stacks were always fighting every other stack. Now the allies control for the stacks should be working correctly, like before.
Another major issue I tried to tackle was the 50% min roll phenomenon¹. As you may know, if a unit has 10 attack or defence, that means it can roll an integer between 1 and 10 during the corresponding battles. If you play scenarios you should've noticed already though, that units above a certain atk/def will always have a min roll of half of that value¹. The stack bonus² may work oddly due to this (if you have a 20 attack unit and the stack bonus² "nerfs" the rolls, you will see a lot of '10s' in that battle - given the logic, this is "normal").
Nerd section
Since the simulator is fixed at having a minimum roll of 1, I made an extension method and used the power of algebra to get closer to the mean value of the actual in-game behavior.
In practice this means the atk/def/crit values you're seeing visually on the UI are not always what is get sent directly to the API. So we modify the max roll and the crit, to mathematically get as close to the real mean value we would be getting in game as possible. A unit with 16 attack and 0% crit will have a range of 8-16 in terms of rolls, so the mean is 12, not the expected 8.5 ((1 + 16) / 2). In this example, the max roll we should be sending to the simulator's API would be 23, since (1 + 23) / 2 = 12.
IF YOU'RE A MAP MAKER, YOU SHOULD BE WARY OF THIS (looking at you Estus).
I'm not sure this actually works correctly, I might have made some mistakes in the math, with the criticals specifically. You can find this piece of code in
scripts/adjustAtkCrit.js. If you want to verify the math, use a javascript interpreter online or various other methods. There are commented out examples on the usage that I deliberately left in there >> printExample(16, 0.05); >> a unit with 16 attack/defence and 5% crit chance.
Please also be aware that the simulator is only taking in integers, I cannot use fractionals, leading to slight inaccuracies - the only way to solve this is sending multiple simulations with different inputs and then merge the data into the final result (which I don't want to do, as I believe the current solution is
accurate enough... just so you know, this is solvable too).
1. 50% min roll phenomenon: I have no idea whether this is a bug or a memory management issue or purposefully built this way, but when a unit's attack or defence value in the game reaches 4 bits (a value of 16) the minimum roll of that unit in battles turns from 1 into half of the max value, rounded down; this is affected by upgrades, strategies, the general bonus and Defence type buildings (according to extensive testing, the range seems to dynamically "hop" into the top half of the range and treat it normally, but further investigation might be needed to know for sure whether it converts the lower values into 8s - in this case - or just crop the values of 1-7 completely).
2. Stack bonus: Clovis already put a lot of math-heavy explanations on this in the last 10 years, you can find that on the forum, it's built into this simulator as well (...) the amount of units on the offensive and defensive side of a battle will alter the RNG of the rolls.