Victory Screen Mods

@EF: It uses nearly the exact same attitude counting method as the Glance screen on the BUG FA uses; I copied the calculateRelations function from there verbatim but I make two small additions later: an attitude of Friendly will be a mimimum of +10 and an attitude of Pleased will be a maximum of +9. This should make things slightly more accurate in some rare situations when the hidden diplo stuff pushes someone just over that border, but it's still based on what you actually see on the attitude summaries and so is spoiler-free. That adjustment is easy to identify and comment-out if you disagree.

@ruff: Code is attached. Should be easy enough to follow. I tried to make sure all my code changes are in blocks that begin with
Code:
#DAS START Changes -- [I]description[/I]
and end with
Code:
#DAS END Changes
If original code was modified it is still there but commented out. All the text is hardcoded but shouldn't be hard to localize.

A few caveats on my mechanism for determining candidates and support:
  • As you'll be able to read in my comments, I'm not sure of the best way to handle attitude ties.
  • The vassal situation is handled but permanent alliances may not be since I don't really understand the whole team thing.
  • My determining of the candidates might be too simple: the first candidate is the secretary general/AP resident and the second is the person with the most votes among the others. The whole full member/voting member thing might mess with that in some rare situations so there should probably be a check to make sure that the second candidate is a full member.

Anyhow, it should be a good starting point for you and if I find I made any major mistakes while I'm playing around with it, I'll be sure to warn you.
 
thanks for this - I'll take a look. This is the 3rd time that I've wanted to put attitudes on a screen - I'm going to pull the two glance defs into a separate py file so that we can re-use the same code in different situations.
 
I'm going to pull the two glance defs into a separate py file so that we can re-use the same code in different situations.

You read my mind. ;) May I recommend AttitudeUtil.py or DiploUtil.py?

@Dresden - Thanks for the code. I agree that sounds non-spoiler. I look forward to this being in BUG.
 
Yep, good idea on making a utility python file for those kinds of functions. That ought to make things much easier in the future. :thumbsup:

Also, I've alleviated one of my concerns. Finally got the guts to try some SDK modding tonight and was able to test the attitude tie situation. If an AI has the same exact high opinion of both candidates (i.e. they are the same and greater than 7), the first one gets the vote, so the logic I was using for estimating ties is sound.

That was such a pain to test without being able to see the exact attitude values because everytime I forcibly adjusted things to the point I *thought* was a tie, somebody would go and make a demand or sign a vassalage agreement or some bonus would expire in between turns and my careful planning would go poof....
 
@ruff_hi:

I can't find any changes in your 1047 version of CvVictoryScreen.py compared with the BtS origin file.
 
@ruff_hi:

I can't find any changes in your 1047 version of CvVictoryScreen.py compared with the BtS origin file.

I guess, the changes are not yet committed because the screen is still in development. :)
I've commited the original victory screen so that when I do commit our version of it, we have something that our system can compare against to show the changes.
 
Is the voting strictly based on the actual (visible plus hidden) attitude numbers, or is the attitude state (Friendly vs. Pleased) taken into account at all with regards to voting? I was under the impression that an AI had to be Friendly toward you to vote for you. Is this true?
 
Is the voting strictly based on the actual (visible plus hidden) attitude numbers, or is the attitude state (Friendly vs. Pleased) taken into account at all with regards to voting? I was under the impression that an AI had to be Friendly toward you to vote for you. Is this true?
 
I've added a temp version of the victory screen to the SVN. I'm still thinking about how we go about putting in the vote estimates.

Does anyone have a save game with any of the following:
  • the UN
  • just about to build the AP
  • just about to hold an AP victory election (I think I have one of those, but more is better)
  • just about to hold an AP election for pope
 
Is the voting strictly based on the actual (visible plus hidden) attitude numbers, or is the attitude state (Friendly vs. Pleased) taken into account at all with regards to voting? I was under the impression that an AI had to be Friendly toward you to vote for you. Is this true?
The voting for diplo victory is strictly based on the true attitude numbers and they don't actually have to be friendly. The relevant code is the function CvPlayerAI::AI_diploVote from CvPlayerAI.cpp. The spoiler contains the relevant parts.
Spoiler :
Code:
	if (GC.getGameINLINE().isTeamVote(eVote))
	{
		if (GC.getGameINLINE().isTeamVoteEligible(getTeam(), eVoteSource))
		{
			return (PlayerVoteTypes)getTeam();
		}

		if (GC.getVoteInfo(eVote).isVictory())
		{
			iBestValue = 7;
		}
		else
		{
			iBestValue = 0;
		}

		PlayerVoteTypes eBestTeam = PLAYER_VOTE_ABSTAIN;

		for (iI = 0; iI < MAX_TEAMS; iI++)
		{
			if (GET_TEAM((TeamTypes)iI).isAlive())
			{
				if (GC.getGameINLINE().isTeamVoteEligible((TeamTypes)iI, eVoteSource))
				{
					if (GET_TEAM(getTeam()).isVassal((TeamTypes)iI))
					{
						return (PlayerVoteTypes)iI;
					}

					iValue = GET_TEAM(getTeam()).AI_getAttitudeVal((TeamTypes)iI);

					if (iValue > iBestValue)
					{
						iBestValue = iValue;
						eBestTeam = (PlayerVoteTypes)iI;
					}
				}
			}
		}

		return eBestTeam;
	}
My reading of that code -- plus recent testing -- puts the algorithm like this:
  1. If we're eligible, vote for ourselves
  2. If we're a vassal of one of the candidates, vote for the master
  3. Otherwise, vote for whichever candidate we like best, as long as our attitude with them is at least +8. (Ties go to the first one checked.)
  4. If we are at +7 or below with all candidates and the first 2 situations don't apply, abstain.
So that's what I tried to duplicate in python when I made my test screen. Since the friendly minimum is +10, an AI can vote for someone they are only pleased with when the true attitude is +8 or +9. Complicating things further, this is not actually the player-to-player attitude value but is instead the team-to-team attitude value, a fact which I have cheerfully ignored up to this point...

Note that the secretary general election uses the same algorithm but there the minimum attitude to gain a vote is only +1 rather than +8.

Being "friendly" with the secretary gen does seem to make them vote for any other resolution proposed (handled later in that function) but I've never really looked at those votes too closely.

@ruff:
The attached archive contains saves with all those situations from my latest game (3.17). I tried to queue up Research in all the cities so you don't have too many popups jumping out at you when you end the turn.
 
@ruff:
The attached archive contains saves with all those situations from my latest game (3.17). I tried to queue up Research in all the cities so you don't have too many popups jumping out at you when you end the turn.
Excellent. Some test games to use.

Do you have one where you are close to finishing the apollo program / and / or launching?
 
Yep. I have one from my last game where the ship is fully-built but not yet launched. I could probably come up with an about-to-finish-apollo one fairly soon since my current game is close to that situation. (I have the tech but don't think it's built yet.)
 
@Dresden - Your reading of the C++ code is correct. The only addition I'd make is that the first check will make the AI vote for itself or its partner in a Permanent Alliance which causes them to form a single team. This could be added to the screen pretty easily.

Do I hear a call for VoteUtil.py? ;)

The effect of teams does have implications in various parts of the game, and I hadn't even considered attitude. Apparently each AI team maintains a single unified attitude toward every other team as well. I suspect that it's simply an average of each AI in the source and target teams.

This information isn't displayed anywhere in the normal game, though. Furthermore, I don't see any functions in the API that allow us to get it. Keep in mind the online API hasn't been updated for BtS.
 
The effect of teams does have implications in various parts of the game, and I hadn't even considered attitude. Apparently each AI team maintains a single unified attitude toward every other team as well. I suspect that it's simply an average of each AI in the source and target teams.
Yep, it sure looks to be the average of all team 1's members' attitudes towards team 2's members.
Quoting CvTeamAI.cpp
Spoiler :
Code:
int CvTeamAI::AI_getAttitudeVal(TeamTypes eTeam, bool bForced) const
{
	int iAttitudeVal;
	int iCount;
	int iI, iJ;

	FAssertMsg(eTeam != getID(), "shouldn't call this function on ourselves");

	iAttitudeVal = 0;
	iCount = 0;

	for (iI = 0; iI < MAX_PLAYERS; iI++)
	{
		if (GET_PLAYER((PlayerTypes)iI).isAlive())
		{
			if (GET_PLAYER((PlayerTypes)iI).getTeam() == getID())
			{
				for (iJ = 0; iJ < MAX_PLAYERS; iJ++)
				{
					if (GET_PLAYER((PlayerTypes)iJ).isAlive())
					{
						if (GET_PLAYER((PlayerTypes)iJ).getTeam() == eTeam)
						{
							iAttitudeVal += GET_PLAYER((PlayerTypes)iI).AI_getAttitudeVal((PlayerTypes)iJ, bForced);
							iCount++;
						}
					}
				}
			}
		}
	}

	if (iCount > 0)
	{
		return (iAttitudeVal / iCount);
	}

	return 0;
}

continued... said:
This information isn't displayed anywhere in the normal game, though. Furthermore, I don't see any functions in the API that allow us to get it. Keep in mind the online API hasn't been updated for BtS.
Indeed. There doesn't seem to be any of the attitude functions exposed to python in CyTeamInterface. Although since CvPlayer::getTeam() is available to python, I suppose one could write a team attitude estimator utility that mimics the above function by calling calculateRelations() to get the individual visible attitudes and then averaging those.
 
Thank you for enabling my laziness by looking up the SDK code. :D I'll add this to AttitudeUtil.py when I get a chance.

To the team and users, what exactly is our stance on using SDK calculation information in BUG? Some of the hidden attitude information is set and easily checkable by the human once they've read the SDK code. Do we want to expose that information?

One example where we do this already (it's borderline I suppose) is the whip calculation. The player cannot know how much overflow they will receive without a) knowing the calculation in the SDK and b) doing the math themselves. Granted, after whipping enough times one could figure out the calculation without reading the SDK code. This is why I consider it borderline.

Some of the hidden attitude modifiers could be viewed similarly. For example, there's a rule (I'm paraphrasing from memory, so I may not be entirely correct) that makes AIs in the lower half of the scoreboard dislike those in the upper half. Anyone who cares can find this out, so it's not truly hidden in the sense that an enemy's unit locations are hidden.

Should we expose this SDK-knowledge to the average player?

Should we take it into consideration when calculating the likely winner of a vote, even if we don't show the player the actual modifiers?
 
I think this is pushing the limit slightly. The whip assistant can be figured out fairly easily, and you can get a feel for it even if you don't completely figure it out. AI Attitudes still pose a mystery to most players, and I think it would ruin a bit of the game play. That's just my 2 cents, so take it or leave it.
 
the whole game is an algorithm so we could expose much more than we do on the argument that it is in the code. I would prefer to have the voting remain a little bit of a mystery. We might even consider putting in some vote estimates and using code that makes sense but ends up being an approximation.
 
Should we expose this SDK-knowledge to the average player?

Should we take it into consideration when calculating the likely winner of a vote, even if we don't show the player the actual modifiers?

My best choice is: no and yes.
No as default, yes with an option to manually enable in BUG.ini (not in option screen).
I sugest this solution for all these borderline things, so that the player has to enable them with a clear act of will.
 
I think even the most casual player understands the first 2 voting rules:
  1. Always vote for yourself or your teammate
  2. If you're a vassal, vote for your master.

So, if you decide to include a vote estimator in BUG, the only real decision is how to make the guess in the situation where it's down to attitude difference? You want to balance having a useful, accurate feature with not revealing too much stuff that shouldn't be revealed. Here are a few different methods, in order from most accurate (and thus most potentially spoilerrific) to the least so.

  1. Use calculateRelations (along with the friendly/pleased adjustment) for all involved teammembers, average the results and use that along with the 8+ minimum for voting. This is the closest possible emulation of the actual voting procedure as most recently discussed while still being based solely on information provided by the foreign advisor.

    I, obviously, like this way because I'm a tinkerer. I read articles at CFC, I look into the code, I pry off the cover and poke around inside. Of course this is still just an estimate and those hidden diplo modifiers could kick in and give you a rude surprise, so there's some mystery still involved, even if it is the best guess. I will grant you that I'm in the minority on this and won't put up too much of a fight if it's deemed to go too far.

  2. Ignore the team stuff and just use calculateRelations directly on the two candidates. However still apply the friendly/pleased adjustment and the 8+ vote minimum. This is the situation on the code posted earlier.

    This assumes the user is still fairly sophisticated. While the voting algorithm isn't listed in the civilopedia, this is the kind of detail that strategy articles at sites like this one openly discuss. I expect that most people who are interested enough to read ori's AI Attitude thread would probably go along with this method. But if you want to keep BUG more focused on the average player and choose to operate without relying on the "hidden" details of the game mechanics, then it might still be too much.

  3. Since the 8+ vote minimum and the friendly/pleased numerical thresholds are not listed in the game's documentation, consider them off-limits and simply use the raw player-to-player calculateRelations numbers: whoever they like better gets the vote estimate. It also seems to me to make sense that the vote will only be counted with a minimum level of friendly (or even pleased) since experience shows that an AI basically always abstains if they're cautious or worse with both candidates.

    This is probably the least disagreeable choice as it is pretty much all common-sense. It casts out the most arcane bits of the algorithm and focuses simply on the glance-screen numbers that every BUG user should already be very familiar with. And with an assumed attitude minimum it will hopefully remain a reasonable, though conservative, estimate.

  4. Ignore the calculateRelations number entirely and simply look at the friendly/pleased values. If the voter is friendly to one candidate but not friendly to the other, count the vote; in all other situations abstain.

    This really pares things down and will likely result in a lot of "abstain" estimations for civs that do wind up voting. But I can't imagine anyone thinking this method reveals too much information. If you are going to include any kind of vote estimate in BUG, this is probably the bare minimum useful level.

  5. Don't even attempt to estimate the attitude-based vote. Simply mark all voters that aren't candidates or team-members of candidates as "undecided."

    The simplest method, included for completeness. But my opinion, as alluded to above, is that if you are going to resort to this level of opacity in the voting, don't even bother including a vote estimate since it's not really providing any extra information.
 
Top Bottom