PieceOfMind's Advanced Combat Odds

Found a bug related to Siege units. If the Damage from attacking seige was in the low 20s or high teens, was getting false calculations. See image below. Not sure what is causing this. When the seige was doing damages of over 24 or so, it calculated just fine, it was only when R was almost exactly 1.0 that this showed up. I think this is due to first strikes as well, and the fact that the attacker only needs 4 hits in this example, but it's not showing up.

SeigeBug.jpg


The image brings up another idea for a visual improvement. Could be cool to have the defender's 1 hit left damage bar split colored with yellow for when the seige withdraws, like the way the retreat 1hit left HP bar does for the attacker when it retreats.
 
EDIT. Upon looking at it more closely it seems the bug goes deeper. I'm looking into it now. Thanks for making me aware of it phungus.

phungus, my initial impression is that you just stumbled across the BtS odds calculator's retreat odds bug.

http://forums.civfanatics.com/showthread.php?p=7780623

When the siege unit is able to damage the defender to exactly the combat limit (20HP in this case), there is a quirk in the way combat is resolved. The catapult actually needs to hit the defender a 5th time for 0 damage to be able to withdraw from combat. This is why the needed rounds for the attacker is shown as 5. If you redid the calculation assuming 4 strikes were needed, you'd get the value of 56.8 as the original calculator does. Basically the old calculator is over estimating the odds when the siege units can damage the defender to exactly the combat limit.

If your opinion is that what you've found is a different bug then let me know.

In any case, check it with v0.5. I think there was a minor bug in v0.4 relating to siege units that I accidentally introduced around v0.3 or so.
 
Wait.. I'm confusing myself here. What units are you using exactly? I just remembered the catapult combat limit is 75 - not 80 like I assumed in the previous post. I really need to know specifically what the combat limit is.

Attempting to replicate the situation you had, this is what I found. I agree completely with the odds in the following picture. It is a cannon vs. a str12 unit with 1 first strike. Due to the combatLimit being 80, the abnormal effect of the odds bug comes into play. I think if you were to test a number of battles in that scenario the odds I have displayed would agree with the results you'd get. ie. the cannon would die more than 50% of the time.

attachment.php
 

Attachments

  • replicate.PNG
    replicate.PNG
    32.3 KB · Views: 274
Oh, OK, so the BTS odds calculator is wrong, and you fixed this bug with the modcomp. Cool then, just figured I'd post it since there was disagreement, and I thought the 5 hits was a bug, didn't know it actually needed a 5th hit.

The attacking siege is a bombard from the Wolfshanze mod (WolfRevolution), attacking a longbowman in a city. The screenshot is from v 0.5 in progress which you posted on here, with the bugfixes I posted.

The 0.5 progress build works great. Been playing with it for the past week. Other then the above (which I guess is a bug in default BtS and not the mod), It's worked great. Actually it's really dang useful, don't know how I got along without it. What are you waiting for for the official 0.5 release version?

Since it's not officially released yet, here are suggestions after playing with it:

1)Needs the XP bugfix I posted on the last page
2)Would be nice to seperate out the 100% health, and 1 hit left individual HP bars and probabilities from being combined. Sometimes I want to know if that 100% health is really 0.00% and not some fraction of 2.7%.
3)For forced withdraw units (siege), would be nice to split the survived with 1Hit left HP bar for the defender with yellow for the %odds where the attacker is victorious and withdraws. Would normalize everything with the rest of the display colors in ACO. Also I just really like that with the retreats for the attacker, and think it would look cool to be shown on the defender against a siege attack as well.
4)Add in the attacker switcharoo thing, it's cool. But set it up so that it's disableable through the XML. That's trivial to do though, it's how I've got it set up:
Spoiler :
Code:
				if (SeeEnemyOdds > 0) {
					bool bctrl; bctrl = gDLL->ctrlKey(); if (bctrl)
					{
						CvUnit* swap = pAttacker;
						pAttacker = pDefender;
						pDefender = swap;
					}
				}
Unfortunately there is no easy way to have it show the odds for the best attacker in the stack. But the basic swap thing has worked great for me so far, haven't even wanted it to show the best attacker yet actually--no need, it shows the countering unit anyway.

Can't really think of anything else, v 0.5 looks great.
 
I'm having a problem where the box for the bars and part of the information is just a pink box. Any ideas?

I had the same problem. The directions for doing it without making it a mod in the OP are incomplete/misleading. As at first it only says to replace the DLL and then see if it works. Go into the Art folder under assets in the mod's folder and copy the ACO folder into the Art folder for Civ. Using worldbuilder combat that seems to have fixed it but I haven't played a game with it yet. Edit1: It seems to have defaulted to low detail, which sucks because I don't know how to edit xml and xml is too short of a word to search for. Edit2: Copying the globaldefinesalt xml into the custom assets folder restored the default to 1 (medium). Though I still have no idea how to edit the xml, lol. There should probably be a way to change the detail level in-game to make it easier for everybody and accessible to those who don't edit code. (:

Very cool mod/add-on though. The "odds defender undamaged" display is especially nice for assessing when using siege is worthwhile.
 
I had the same problem. The directions for doing it without making it a mod in the OP are incomplete/misleading. As at first it only says to replace the DLL and then see if it works. Go into the Art folder under assets in the mod's folder and copy the ACO folder into the Art folder for Civ. Using worldbuilder combat that seems to have fixed it but I haven't played a game with it yet. Edit1: It seems to have defaulted to low detail, which sucks because I don't know how to edit xml and xml is too short of a word to search for. Edit2: Copying the globaldefinesalt xml into the custom assets folder restored the default to 1 (medium). Though I still have no idea how to edit the xml, lol. There should probably be a way to change the detail level in-game to make it easier for everybody and accessible to those who don't edit code. (:

Very cool mod/add-on though. The "odds defender undamaged" display is especially nice for assessing when using siege is worthwhile.

I can appreciate how confusing it is installing the mod. It's pretty hard to explain how to install itfor a number of different possible setups that people may be going for.

If you still want some help with it, let me know how you are trying to install it (as part of another mod, as its own mod or in custom assets) and whether you are intending to use it with other mods (including unofficial patches).

If you copied the art folder to that for civ, make sure you are copying it to the BtS art folder not the civ4 one, although maybe that doesn't matter(?) - I haven't tried in the civ4 art folder.

Editing the XML in the customassets folder is straightforward - just open up the file in notepad or any other text editor and you will see some variables defined via numbers. You can change the detail setting by choosing a number between 0 and 3.
 
I can appreciate how confusing it is installing the mod. It's pretty hard to explain how to install itfor a number of different possible setups that people may be going for.

If you still want some help with it, let me know how you are trying to install it (as part of another mod, as its own mod or in custom assets) and whether you are intending to use it with other mods (including unofficial patches).

If you copied the art folder to that for civ, make sure you are copying it to the BtS art folder not the civ4 one, although maybe that doesn't matter(?) - I haven't tried in the civ4 art folder.

Editing the XML in the customassets folder is straightforward - just open up the file in notepad or any other text editor and you will see some variables defined via numbers. You can change the detail setting by choosing a number between 0 and 3.

I wasn't installing it as a mod, but rather the other option you gave since I don't do multiplayer. The three things I did (replaced the DLL, copied the Art folder, copied the xml file) together seemed to work. I don't currently use other mods but I don't know if my approach would clash with that if I ever do.

However, when I try to open an xml file it tries to open a webpage, lol. But if I start in notepad and try to open it it works. Thanks. (:
 
How solid is this? I'd like to include it in my Modmod to Fall From Heaven.

Thanks.
 
How solid is this? I'd like to include it in my Modmod to Fall From Heaven.

Thanks.

If by solid you mean doesn't cause crashes then this should be very solid. I'm still testing to make sure there are not very minor bugs in the defender detailed HP displays, only used at the Everything detail setting.

Are you thinking about merging it with your own DLL? If so, you should find my code in the included files relatively easily because I've only inserted blobs of code that are tagged at beginning and end.
 
Yes, it would be into my own DLL, and I love properly tagged code. :)
 
1)Needs the XP bugfix I posted on the last page
2)Would be nice to seperate out the 100% health, and 1 hit left individual HP bars and probabilities from being combined. Sometimes I want to know if that 100% health is really 0.00% and not some fraction of 2.7%.
3)For forced withdraw units (siege), would be nice to split the survived with 1Hit left HP bar for the defender with yellow for the %odds where the attacker is victorious and withdraws. Would normalize everything with the rest of the display colors in ACO. Also I just really like that with the retreats for the attacker, and think it would look cool to be shown on the defender against a siege attack as well.
4)Add in the attacker switcharoo thing, it's cool. But set it up so that it's disableable through the XML. That's trivial to do though, it's how I've got it set up:
Spoiler :
Code:
				if (SeeEnemyOdds > 0) {
					bool bctrl; bctrl = gDLL->ctrlKey(); if (bctrl)
					{
						CvUnit* swap = pAttacker;
						pAttacker = pDefender;
						pDefender = swap;
					}
				}
Unfortunately there is no easy way to have it show the odds for the best attacker in the stack. But the basic swap thing has worked great for me so far, haven't even wanted it to show the best attacker yet actually--no need, it shows the countering unit anyway.

Can't really think of anything else, v 0.5 looks great.


1)done
2)done
4)done

3) not done.
I'm wondering whether your third point is worth doing. I know it looks a bit funny to have huge red bars on the bottom defender HP value whenever you use siege, but I think it would look equally strange to have a big yellow bar there when there are no yellow odds displayed earlier.

I have to agree the switcharoo thing is really neat. You can actuall notice sometimes by using the switcharoo that the way the die is rolled always favours the attacker slightly. You won't notice it in those battles where R=1 exactly but you'll you often notice that reversing attacker and defender will not change the round odds by 100%-odds all the time.

v0.5 changes
Spoiler :
v0.5
-1 decimal place only for Low setting
-Merged HP bars when they were individually less than some cutoff - currently 0.5%. Note the attacker min HP bar was left alone in case retreat odds came into it.
-Added XP modifiers (eg. Great General promotion - Leadership)
-Fixed XP range calculations so they will work with mods
-Added detail about free wins vs barbs - now shows correct odds for such battles unlike old calculator which lied to the user. (note this only works if defender is barb at the moment)
-Added correct XP taking barb XP caps into account, including animals. e.g. if on 8XP and killing the barb would normally result in large xp, the shown amount will be only 2.
-Fixed negative XP bug in barb normalization code (thanks to phungus420) (it was only present in earlier builds of this version)
-Prevented the unit unharmed HP bars from being combined with others. eg. if you use a warrior to attack an infantry it will still show you the bar with the probability of your warrior keeping 100HP or whatever other hitpoints it starts with.
-


To Do (later versions)
+Flanking damage
+GG point modifiers? eg. great wall and IMP leaders
+does not yet cover the barb odds for switcharoo
 
Oh, OK, so the BTS odds calculator is wrong,

I could have told you that a year ago

and guy.. this looks real good havent gotten a chance to look over the code.. But im going to and if i find any errors or bugs in it (unlikely at this stage of development) iill let you know.
 
I could have told you that a year ago

Why didn't you then? In all seriousness I can't imagine why you think you already knew about the siege unit bug. It happens infrequently and usually when it does it's hard to notice because it isn't actually off by too much. I am pretty sure I never would have noticed it if it weren't for the discrepency I spotted on one occasion during the comparison/testing of the two calculators.

and guy.. this looks real good havent gotten a chance to look over the code.. But im going to and if i find any errors or bugs in it (unlikely at this stage of development) iill let you know.

I have version 0.5 ready to go soon so keep an eye on this thread.
 
At the moment, there is a problem with the switcharoo code when the other unit is a barbarian.

I'm pretty sure the problem lies in the first line of this code. EF or phungus, if you know how to fix this it'd be great!

From CvGameCoreUtils.cpp (and in CvGameTxtMgr)
Code:
    if (GET_PLAYER(pAttacker->getOwnerINLINE()).getWinsVsBarbs() < GC.getHandicapInfo(GET_PLAYER(pAttacker->getOwnerINLINE()).getHandicapType()).getFreeWinsVsBarbs())
        {// then we still have free wins left
            //I have assumed in the following code only one of the units (attacker and defender) can be a barbarian
            if(pDefender->isBarbarian())
            {
                iDefenderOdds = std::min((10 * GC.getDefineINT("COMBAT_DIE_SIDES")) / 100, iDefenderOdds);
                iAttackerOdds = std::max((90 * GC.getDefineINT("COMBAT_DIE_SIDES")) / 100, iAttackerOdds);
            }
            else
            {
                if(pAttacker->isBarbarian())
                {
                    iAttackerOdds = std::min((10 * GC.getDefineINT("COMBAT_DIE_SIDES")) / 100, iAttackerOdds);
                    iDefenderOdds = std::max((90 * GC.getDefineINT("COMBAT_DIE_SIDES")) / 100, iDefenderOdds);
                }
            }
        }

How should this be written so that the attacker or defender could be a barbarian? We can probably safely assume only one of the units is a barbarian.

See attached image for the sort of nonsense it's causing. All the attacker odds for each come are coming out as 0.

But the problem may be somewhere else. I can't figure out why, but if I disable all of the code that is different for barbs, it still goes screwy with barb switcharoo.
 

Attachments

  • too many zeroes.JPG
    too many zeroes.JPG
    300.8 KB · Views: 68
Try this (untested) code:

Code:
if ([B][COLOR="Green"]!GET_PLAYER(pAttacker->getOwnerINLINE()).isBarbarian() &&[/COLOR][/B] GET_PLAYER(pAttacker->getOwnerINLINE()).getWinsVsBarbs() < GC.getHandicapInfo(GET_PLAYER(pAttacker->getOwnerINLINE()).getHandicapType()).getFreeWinsVsBarbs())

Hmm, the strange thing is that this code as it was (and still as it is) only checks if the attacker has free wins versus barbs. But inside the if test, it also checks if the attacker is a barbarian, and if so, gives the defender a "free win". How odd. This means that you'll never get free wins versus barbs on defense assuming barbarians never get free wins of course.

We probably don't want to fix it if it was that way in the original code, but I'd probably rewrite it this way:

Code:
//I have assumed in the following code only one of the units (attacker and defender) can be a barbarian
if(pDefender->isBarbarian())
{
	if (GET_PLAYER(pAttacker->getOwnerINLINE()).getWinsVsBarbs() < GC.getHandicapInfo(GET_PLAYER(pAttacker->getOwnerINLINE()).getHandicapType()).getFreeWinsVsBarbs())
	{// then we still have free wins left
		iDefenderOdds = std::min((10 * GC.getDefineINT("COMBAT_DIE_SIDES")) / 100, iDefenderOdds);
		iAttackerOdds = std::max((90 * GC.getDefineINT("COMBAT_DIE_SIDES")) / 100, iAttackerOdds);
	}
}
else if(pAttacker->isBarbarian())
{
	if (GET_PLAYER(pDefender->getOwnerINLINE()).getWinsVsBarbs() < GC.getHandicapInfo(GET_PLAYER(pDefender->getOwnerINLINE()).getHandicapType()).getFreeWinsVsBarbs())
	{// then we still have free wins left
		iAttackerOdds = std::min((10 * GC.getDefineINT("COMBAT_DIE_SIDES")) / 100, iAttackerOdds);
		iDefenderOdds = std::max((90 * GC.getDefineINT("COMBAT_DIE_SIDES")) / 100, iDefenderOdds);
	}
}

This new logic will keep us from checking if a barbarian has free wins which is probably a no-no, and it will let the human get their free wins as both attacker and defender.

It looks like the attacker and defender stats aren't reversed at the bottom (below 2.00 vs. 2.44 or maybe that too). I see 16HP, 24HP x 5, 5, but then below HP are 68/100. Are those reversed? I don't know the units involved so I can't say for sure.
 
EF you just made me realise another problem.

It says +10% due to tile defense but using the switcharoo that modifier shouldn't be getting applied. I assume when deciding if that modifier is applied the game must look at the current tile - not the tile the defender is on. By using the switcharoo we hover over the attacker's tile, not the defender's tile, so we get some wrong numbers by the looks of it.

Also, this may be a bizzare thing to say but it looks like the barbs have free wins vs. barbs! I'll see if I can re-write the code like how you said so it avoids checking for free wins for barb units.

Oh by the way, the code I showed you above was my code. In fact the first line of code was code you supplied for me IIRC.
 
I assume when deciding if that modifier is applied the game must look at the current tile - not the tile the defender is on.

Are you sure it doesn't check pDefender->plot()? If not, then ya we're pretty screwed.

I'll see if I can re-write the code like how you said so it avoids checking for free wins for barb units.

I edited my post and wrote the code in actual C++. Notepad++ to the rescue! :)
 
Are you sure it doesn't check pDefender->plot()? If not, then ya we're pretty screwed.

I haven't checked yet but it looks plainly wrong in the game, hence the guess.

I edited my post and wrote the code in actual C++. Notepad++ to the rescue! :)
lol I already wrote up the code by the time I saw your post. :D At least your code agrees.



I think I know how to fix the problem with the modifiers showing up the wrong way round. I just need to move the code that swaps them higher up in GameTxtMgr, or something like that. I'll go look now.
 
And you can rearrange the plots the are checked easily too.

Code:
CvPlot* pAttackerPlot = pAttacker->plot();
CvPlot* pDefenderPlot = pDefender->plot();

And just to be clear, if the function is being passed a CvPlot*, you can safely assign a different plot pointer to it without affecting the calling code.

Code:
void foo()
{
   CvPlot* x = ...;
   bar(x);
   // x here still has the same value it did before calling bar()
}

void bar(CvPlot* x)
{
    x = ...;
}

This is because the x in foo() is a totally different variable from the x in bar(). foo()'s x is said to be passed "by value" to bar() because a copy of its value is passed. If this doesn't make sense or is confusing, just know that if the function to do all this takes a CvPlot* called pPlot, you can safely change pPlot to point elsewhere. :)
 
Back
Top Bottom