PieceOfMind's Advanced Combat Odds

phungus,
It seems the updated XP has not affected the XP thresholds in the XP range display. That's understandable because the way I coded that line was pretty hard to alter. But it looks a little bit off at the moment with 6XP at R=1.1 and lower values on both sides of it. I'm thinking the bonus XP you have in cyan should instead go directly beside the XP displayed in both the Victory and Retreat Odds.

eg.
Victory: 68.05% for 3+3XP

Bonus XP is never going to be non-integer amounts anyway.
OK, I can do this, any chance you could upload your CVTextMngr file so I can incorporate your latest additions (mainly the display bars), when I add that this in?
 
Having a separate checkbox option is totally fine. I suggested the None setting in case that was easier. I actually prefer a separate option to disable the mod and use the normal code.

When you say the mod has problems because it uses the min/max/attacker XP values, are you saying you use 1, 10, 4 and 2 in the code? If so, it would be good to swap them out to use getDefineINT(). It's really not hard to do.

Similarly, I'd love to see the XP capped if you are fighting barbs or animals. I can help with that if you want. The code to check for those cases will be wherever the XP is assigned in the normal code.
 
When you say the mod has problems because it uses the min/max/attacker XP values, are you saying you use 1, 10, 4 and 2 in the code? If so, it would be good to swap them out to use getDefineINT(). It's really not hard to do.

I know how easy it normally is but for one of the features (the XP range display) it's actually a lot more difficult to work with general numbers rather than 1 or 10. I would need to be able to create an array of size depending on a variable (I haven't been able to figure out how to do that). After that, you'd need to let me know how to find the length of the array CombatRatioThresholds.

Code:
if(pAttacker->combatLimit() == (pDefender->maxHitPoints() ))
                     {
                        float CombatRatioThresholds[9];
                        for (int i = 0; i < 9; i++) //setup the array
                        {
                            CombatRatioThresholds[i] = ((float)(pDefender->attackXPValue()))/((float)(10-i));//max XP per combat assumed to be 10
                            //szTempBuffer.Format(L"combatratio[%d] = %.2f",
                            //                    i,CombatRatioThresholds[i]);
                            //                    szString.append(NEWLINE);szString.append(szTempBuffer.GetCString());
                        }

                        for (int i = 8; i >= 0; i--) // find which range we are in
                        {
                            if(CombatRatio>CombatRatioThresholds[i])
                            {

                                if (i==8)
                                {
                                    szTempBuffer.Format(L"(%.2f:%dXP), (R=" SETCOLR L"%.2f" ENDCOLR L":%dXP)",
                                            CombatRatioThresholds[i],10-i,TEXT_COLOR("COLOR_CYAN"),CombatRatio,iExperience);
                                            szString.append(NEWLINE);szString.append(szTempBuffer.GetCString());
                                }
                                else // normal situation
                                {
                                    szTempBuffer.Format(L"(%.2f:%dXP), (R=" SETCOLR L"%.2f" ENDCOLR L":%dXP), (>%.2f:%dXP)",
                                            CombatRatioThresholds[i],10-i,TEXT_COLOR("COLOR_CYAN"),CombatRatio,iExperience,CombatRatioThresholds[i+1],10-(i+2));
                                            szString.append(NEWLINE);szString.append(szTempBuffer.GetCString());
                                }
                                break;

                            }
                            else//very rare (ratio less than or equal to 0.4)
                            {
                                if (i==0)
                                {
                                //i should be 0
                                szTempBuffer.Format(L"(R=" SETCOLR L"%.2f" ENDCOLR L":%dXP), (>%.2f:%dXP)",
                                                TEXT_COLOR("COLOR_POSITIVE_TEXT"),CombatRatio,iExperience,CombatRatioThresholds[i],10-(i+1));
                                                szString.append(NEWLINE);szString.append(szTempBuffer.GetCString());
                                                break;
                                }//if

                            }// else if
                        }//for
                    }//if
 
Ahh, dynamic arrays. Not too hard in C++.

Code:
int size = GC.getDefineINT("MAX_EXPERIENCE_PER_COMBAT") - GC.getDefineINT("MIN_EXPERIENCE_PER_COMBAT");
float[B]*[/B] CombatRatioThresholds = [B]new float[size][/B];
for (int i = 0; i < size; ++i)
{
	...
}

... use CombatRatioThresholds as necessary ...

// throw out array
[B]delete CombatRatioThresholds[/B];

You cannot ask the array for its size, but you create it with "size" elements.
 
That reminds me. What things do I have to worry about in terms of memory management? Am I going to accidentally create memory leaks?

Is it only the arrays I create I have to make sure to delete?
 
Your code up to now will not cause any memory leaks. Everything is created on the stack and will be cleaned up when the function exits. Using the dynamic array code I posted will cause a leak if you exit the function without deleting it. Just make sure that you don't skip the delete line using break or return, and you'll be fine.
 
Thanks to some help form phungus, here is the current state of v0.5.

This combat is between two unlikely units - both have the Leadership promotion.

Spoiler :


phungus,
It might be a day or two before I'll send the code to you. I'm still making large changes to pieces of the code.
 

Attachments

  • v0_5 demo.PNG
    v0_5 demo.PNG
    52.3 KB · Views: 190
That looks really nice. I forgot to answer your question about BUG. I'm putting out the 3.6 release right now. I'll let the dust settle a little and then release 4.0 and BULL, so you've got some time before it's officially released. I will, however, be making a pre-release version available via SVN in a week or so.
 
I really like the look of v0.5, I'd go so far to say it looks like the appropriate point to call it v1.0 :goodjob: You've already done everything I was looking to do in it, so I'll just wait for it's release, nothing to work on from my perspective. I think the X+Y XP in the top battle outcomes came out looking well.

Two quick questions, was the red color intentional for the bonus XP of the defender? If not making it cyan, like for the attacker is trivial to do, and would be more consistant. Also I know I originally pushed for the elimination of the (AttHP, DefHP) split for withdrawls, and overall I think it's a good thing, but I rather liked it when I reintroduced it in the Everything! detail, of course that's a matter of taste, just wanted to throw that out there.

Oh, and one more thing; I noticed a minor issue with the SHIFT button being used to switch to Everything! detail: It trips the windows hotkeys and takes you to Windows if you hold it down for 8 seconds. Should probably consider changing the key to Ctrl or something because of that, that's very easy to change though.

Edit: Just thought of something; Would it be worth it/useful to add in a note on free strikes somewhere? The X , Y HP a , b Hits @ AttHit% line might be the easiest place for it. Something like making a note after the AttHit% so it shows ...AttHit% (+z(Att)/z(Def) Free Attempts). Free strikes are subtracted if both units have them, so only one unit (the one with more)will get them.
-Anyway just a thought.
 
EF or phungus can you help me with this?

Here's the situation:
When you play at prince difficulty or lower a certain number of "free wins vs barbs" are allocated. I spoke to EF a bit about it already..

If the player still has free wins left, whenever he fights a barb the barb's odds for each round can be no greater than 10%. Hence the human's odds each round are always at least 90%.

To determine whether these odds for each round apply, in CvUnit, we have this code:

Code:
if (kDefender.isBarbarian())
	{
		if (GET_PLAYER(getOwnerINLINE()).getWinsVsBarbs() < GC.getHandicapInfo(GET_PLAYER(getOwnerINLINE()).getHandicapType()).getFreeWinsVsBarbs())
		{
			iTheirOdds = std::min((10 * GC.getDefineINT("COMBAT_DIE_SIDES")) / 100, iTheirOdds);
		}
	}
	if (isBarbarian())
	{
		if (GET_PLAYER(kDefender.getOwnerINLINE()).getWinsVsBarbs() < GC.getHandicapInfo(GET_PLAYER(kDefender.getOwnerINLINE()).getHandicapType()).getFreeWinsVsBarbs())
		{
			iTheirOdds =  std::max((90 * GC.getDefineINT("COMBAT_DIE_SIDES")) / 100, iTheirOdds);
		}
	}

What I want to know is how can I access the getWinsVsBarbs() and getFreeWinsVsBarbs() from my code in GameTxtMgr?

I can already determine if the defender is barbarian by:

Code:
if(pDefender->isBarbarian() ) {
}

Thanks in advance if one of you can help me.
 
Wow, you must really want to know! :lol: You can call getOwnerINLINE() by putting pAttacker-> or pDefender-> in front. For example,

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

Note that in the second if test block, they use kDefender as the name. Just replace them with pDefender.
 
I really like the look of v0.5, I'd go so far to say it looks like the appropriate point to call it v1.0 :goodjob: You've already done everything I was looking to do in it, so I'll just wait for it's release, nothing to work on from my perspective. I think the X+Y XP in the top battle outcomes came out looking well.

Two quick questions, was the red color intentional for the bonus XP of the defender? If not making it cyan, like for the attacker is trivial to do, and would be more consistant. Also I know I originally pushed for the elimination of the (AttHP, DefHP) split for withdrawls, and overall I think it's a good thing, but I rather liked it when I reintroduced it in the Everything! detail, of course that's a matter of taste, just wanted to throw that out there.

Actually the colour was orange but looked very similar to red. I've changed it back to cyan for now.

Keeping in mind I'm trying to stick with a forced distinction between the two terms withdraw and retreat, I'm happy to leave the expected defender HP off the retreat odds, but my code definitely still includes both for Withdraw odds.

Oh, and one more thing; I noticed a minor issue with the SHIFT button being used to switch to Everything! detail: It trips the windows hotkeys and takes you to Windows if you hold it down for 8 seconds. Should probably consider changing the key to Ctrl or something because of that, that's very easy to change though.

That's sticky keys for windows isn't it? I think this can be disabled with the OS but we can definitely go with Ctrl instead. I am thinking about using Shift for disabling ACO entirely, to do some more testing against the original odds calculator. I haven't done a lot of testing with the more recent changes so I'm not as confident of their accuracy.

Edit: Just thought of something; Would it be worth it/useful to add in a note on free strikes somewhere? The X , Y HP a , b Hits @ AttHit% line might be the easiest place for it. Something like making a note after the AttHit% so it shows ...AttHit% (+z(Att)/z(Def) Free Attempts). Free strikes are subtracted if both units have them, so only one unit (the one with more)will get them.
-Anyway just a thought.

Hmm ...first strikes are already shown with the ordinary combat modifiers at the bottom? Did you know this?
 
Wow, you must really want to know! :lol: You can call getOwnerINLINE() by putting pAttacker-> or pDefender-> in front. For example,

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

Note that in the second if test block, they use kDefender as the name. Just replace them with pDefender.

Cheers,
There will be some funny screenshots once these freewinsvsbarbs are implemented.:)
 
:eek: This is how free wins vs barbs can be abused.



EDIT
By the way, these are the changes in v0.5 so far:

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.
-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.
 

Attachments

  • easy barb battle.PNG
    easy barb battle.PNG
    285.2 KB · Views: 218
-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.
Screenshot above brings up an issue, the 100HP bar should be excluded from merging (unharmed %).
Hmm ...first strikes are already shown with the ordinary combat modifiers at the bottom? Did you know this?
Yeah, and the Everything! detail is at the point where it is close to being overcrowded. Here is my point though, for someone not very familiar with the effects of First Strikes, the ACO display has the effect of making it appear as though First Strikes do nothing. There is nothing in there that shows what they do. To the uneducated casual player, the ACO display may have the effect of making them believe First Strikes do nothing, hence my suggestion to include them in the #hits and damage + hit chance line, so that it shows their effect in the battle.
 
Screenshot above brings up an issue, the 100HP bar should be excluded from merging (unharmed %).

Well, you DO know that it's 0,5% or less, since it's merged...
 
Been trying to add in what I was talking about with First Strikes, just to see what it looks like, but I can't find out where the # of first strikes is handled in the code. Could you point me to it? I think I've figured out a way to go about it, but it's alot more complex if it's pullable from the advanced combat mod section itself.
 
I, too, would like to see something about first strikes added, only because this is the Advanced Combat Odds calculator. ;) And PoM is allllll about those yummy Drill promotions, right? :lol:

From reading your article, PieceOfMind, I believe this is the info we need: who gets them, how many, what probability for each "chance" strike.

This battle is between a unit with 3-5 first strikes and a unit with 1 first strike. 1 FS cancels out on each side, leaving the attacker with 2-4 FS. Oh, I assume that 0 chances is one of the options, so with 2 chances there are 3 possibilities, each at 33.33%, right?

First Strikes: 2+2 at 33.33%

Now when both units have FS chances, IIRC the dice are rolled for each units' chances once at the start of the battle, the one that totals to fewer cancels out against the one with more, and then the one with more gets their remaining chances, right? However, we need to show the chances for both units and cancel out only the guaranteed FS.

This battle is the same units as above, but the defender also has 1 FS chance (1-2 FS).

First Strikes: 1+2 at 33.33% vs. 1 at 50.00%
 
Top Bottom