Advertisement
Civilization Fanatics' Center  

Welcome to Civilization Fanatics' Center.

You are currently viewing our site as a guest which gives you limited access to our site features. By joining our free community, you will be able to participate in the discussions, search the forum, send private messages, vote in polls, upload your own screenshots to the gallery, and access many other special features. Registration is fast, simple and absolutely free, so sign up today! If you have any problems with the registration process or your account login, please contact support.

Go Back   Civilization Fanatics' Forums > CIVILIZATION IV > Civ4 - Creation & Customization > Civ4 - SDK/Python

Notices

Reply
 
Thread Tools
Old Apr 12, 2009, 09:06 AM   #1
Gooblah
Heh...
 
Gooblah's Avatar
 
Join Date: Jun 2007
Posts: 4,282
Team Diplomacy (incl. Capitulation/Vassals)

Browsing through the files, I found the code for capitulation. My main concern is the way average power is calculated - literally, Total Power divided by the Number of Civs. Sounds good, but the presence of weak colonies or vassals makes an AI impossible to capitulate even if they have one city left and one unit, so long as that unit is an MA and a backwards colony is using Longbowmen. Okay, maybe a bit of exaggeration, but the point holds.

Anywho, I'm considering two methods to change this.
1) Drop the last three (variable, based on MapSize) Civs in terms of power.
2) Ignore colonies and vassals in the calculations.

Any tips on how to go about the first? It seems less drastic than the second, and more player-friendly.
__________________
It'll all work out.

Last edited by Gooblah; Apr 28, 2009 at 05:26 PM. Reason: changed title
Gooblah is offline   Reply With Quote
Old Apr 24, 2009, 02:18 PM   #2
Gooblah
Heh...
 
Gooblah's Avatar
 
Join Date: Jun 2007
Posts: 4,282
I found an incredibly simple solution, but I'm having trouble figuring how to identify Worldsize.

I included CyMap.h in CvTeamAI.cpp, but I'm sure how to utilize the getWorldSize() function. any ideas?

Edit, never mind, i think i got it. Could someone review this code for me?

Code:
      int mapsize = CyMap::getWorldSize;
		int iAveragePower;
		if (mapsize == WORLDSIZE_DUEL || mapsize == WORLDSIZE_TINY)
		iAveragePower = iTotalPower / std::max(1, GC.getGameINLINE().countCivTeamsAlive());
		else if (mapsize == WORLDSIZE_SMALL || mapsize == WORLDSIZE_STANDARD)
		iAveragePower = iTotalPower / (std::max(1, GC.getGameINLINE().countCivTeamsAlive())-2);
		else if (mapsize == WORLDSIZE_LARGE || mapsize == WORLDSIZE_HUGE)
		iAveragePower = iTotalPower / (std::max(1, GC.getGameINLINE().countCivTeamsAlive())-3);
Note, in-file line 1 is on the same column as line 2.
__________________
It'll all work out.

Last edited by Gooblah; Apr 24, 2009 at 02:33 PM.
Gooblah is offline   Reply With Quote
Old Apr 24, 2009, 03:59 PM   #3
phungus420
Deity
 
phungus420's Avatar
 
Join Date: Mar 2003
Posts: 6,296
You should bring this over to the better AI forums, especially if you have working code.
__________________
Do not PM me with questions about modding. I will not answer. If you want help with something, start a thread on it, or post in a related existing thread.
phungus420 is offline   Reply With Quote
Old Apr 24, 2009, 04:20 PM   #4
Gooblah
Heh...
 
Gooblah's Avatar
 
Join Date: Jun 2007
Posts: 4,282
Quote:
Originally Posted by phungus420 View Post
You should bring this over to the better AI forums, especially if you have working code.
Thanks! Sadly, I can't compile due my usage of a) Vista, b) VS 2009, and c) inability to find the libs folder for the program (and thus, can't insert the necessary libraries to make everything work).
__________________
It'll all work out.
Gooblah is offline   Reply With Quote
Old Apr 26, 2009, 09:43 AM   #5
Gooblah
Heh...
 
Gooblah's Avatar
 
Join Date: Jun 2007
Posts: 4,282
Okayy....got compiling to work.

However, there is an error. Apparently, I can't call CyMap::getWorldSize like that, meaning that I'm making a foolish error. It's probably simple, so....hmm.

this is the current code:

Code:
int mapsize = CyMap::getWorldSize;
and it gets this error:
Quote:
CvTeamAI.cpp|1594|error C3867: 'CyMap::getWorldSize': function call missing argument list; use '&CyMap::getWorldSize' to create a pointer to member||

Now, I tried adding the '&' symbol for the pointer, but i got another compiling error; apparently, getWorldSize() is a void, while my variable is an int. At the same time, I can't change my variable's type...rrgh. Any ideas? I ran through the CvMap and CyMap .cpp/.h to find otu if I was calling the function incorrectly...


Edit: WOOOOOOOOOOOOOOOOOOOOO! it compiled! fixed it after a few hours (really dumb mistake, messed with pointers/classes). Code I added/altered:

Code:
int iTotalPower = GC.getGameINLINE().countTotalCivPower();
		int iAveragePower, worldsize;
		CvMap i;
		worldsize = i.getWorldSize();
		if (worldsize == WORLDSIZE_DUEL || worldsize == WORLDSIZE_TINY)
		iAveragePower = iTotalPower / std::max(1, GC.getGameINLINE().countCivTeamsAlive());
		else if (worldsize == WORLDSIZE_SMALL || worldsize == WORLDSIZE_STANDARD)
		iAveragePower = iTotalPower / (std::max(1, GC.getGameINLINE().countCivTeamsAlive())-2);
		else if (worldsize == WORLDSIZE_LARGE || worldsize == WORLDSIZE_HUGE)
		iAveragePower = iTotalPower / (std::max(1, GC.getGameINLINE().countCivTeamsAlive())-3);
		int iMasterPower = GET_TEAM(eTeam).getPower(false);
		int iVassalPower = (getPower(true) * (iPowerMultiplier + iPersonalityModifier / std::max(1, iMembers))) / 100;
Edit 2: Dammit! Another problem. Compiler couldn't input 'release.obj'. No idea what this is...any clues?
__________________
It'll all work out.

Last edited by Gooblah; Apr 26, 2009 at 04:14 PM.
Gooblah is offline   Reply With Quote
Old Apr 26, 2009, 04:10 PM   #6
EmperorFool
Deity
 
EmperorFool's Avatar
 
Join Date: Mar 2007
Location: Mountain View, California
Posts: 9,624
The problem with your code is that you're creating a new map and asking it for its size, which probably defaults to STANDARD. What you want to do instead is ask the game for the map that's being used and get the size from it.

Code:
int iMapSize = GC.getMap().getWorldSize();
__________________
Monkeys killing monkeys killing monkeys over pieces of the ground.
Silly monkeys, give them thumbs they make a club and beat their brother down.


BUG Mod - BTS Unaltered Gameplay
[ Forum | Download | FAQ | Known Issues | Troubleshooting | Modding Tutorial ]

BAT 3.0.1 QuickFix™ released Oct 24th
EmperorFool is offline   Reply With Quote
Old Apr 26, 2009, 04:24 PM   #7
Gooblah
Heh...
 
Gooblah's Avatar
 
Join Date: Jun 2007
Posts: 4,282
Quote:
Originally Posted by EmperorFool View Post
The problem with your code is that you're creating a new map and asking it for its size, which probably defaults to STANDARD. What you want to do instead is ask the game for the map that's being used and get the size from it.

Code:
int iMapSize = GC.getMap().getWorldSize();
Oh. Thanks dude!

So, lemme get this straight:

GC references CvGlobals.h, right? so within the getmap() function of class CvGlobals, there's a getWorldSize()?

Edit: Weird, Codeblocks still can't compile....rrgh.
__________________
It'll all work out.

Last edited by Gooblah; Apr 26, 2009 at 04:28 PM.
Gooblah is offline   Reply With Quote
Old Apr 26, 2009, 04:35 PM   #8
EmperorFool
Deity
 
EmperorFool's Avatar
 
Join Date: Mar 2007
Location: Mountain View, California
Posts: 9,624
Quote:
Originally Posted by Gooblah View Post
GC references CvGlobals.h, right?
Essentially, yes. Technically, GC is a preprocessor macro defined in CvGlobals.h that calls a global function that returns the single CvGlobals object for the system.

Code:
GC.getMap()
is turned into

Code:
CvGlobals::getInstance().getMap()
by the C++ preprocessor using simple string replacement.

Quote:
Originally Posted by Gooblah View Post
Within the getmap() function of class CvGlobals, there's a getWorldSize()?
Not exactly. CvGlobals::getMap() returns the CvMap that the game is using. CvMap::getWorldSize() returns the size of that map.

I would recommend reading a brief introduction to Object Oriented Programming or OOP. This will explain the difference between the function CvMap::getMap() and calling this function on an instance of CvMap as happens in the code above.
__________________
Monkeys killing monkeys killing monkeys over pieces of the ground.
Silly monkeys, give them thumbs they make a club and beat their brother down.


BUG Mod - BTS Unaltered Gameplay
[ Forum | Download | FAQ | Known Issues | Troubleshooting | Modding Tutorial ]

BAT 3.0.1 QuickFix™ released Oct 24th
EmperorFool is offline   Reply With Quote
Old Apr 28, 2009, 05:14 PM   #9
Gooblah
Heh...
 
Gooblah's Avatar
 
Join Date: Jun 2007
Posts: 4,282
Yeah, I'm taking a course in C++ this semester, really useful.


Anywho, started working on my next 'project', for Kevinman's World History Mod. Quick conversion of CvTeamAI.cpp to make voluntary vassalage an option only if the vassal's power is 55% or less of the prospective master's power. Pretty easy, I guess, but since I'm a bit of a noob, I wanted to get some advice....

So, found the necessary function. Edited it to add a quick if statement comparing iTheirPower and iOurPower:

Code:
if ( ((55 * iOurPower)/100) <= iTheirPower)
then added (after all the for loop jazz) an else statement that returned DENIAL_ATTITUDE:

Code:
else
	{
		return DENIAL_ATTITUDE;
	}
Pretty straightforward. My problem is that I'm not sure if DENIAL_ATTITUDE is correct...I assumed so, since that's what's used in map trading when it refers to a rejection from another AI who's not their worst enemy. I think it looks right, and I'll play around with it...

Edit: nvm, realized I hadn't defined iOurPower/iTheirPower. Done.
__________________
It'll all work out.

Last edited by Gooblah; Apr 28, 2009 at 05:24 PM.
Gooblah is offline   Reply With Quote
Old Apr 28, 2009, 06:05 PM   #10
EmperorFool
Deity
 
EmperorFool's Avatar
 
Join Date: Mar 2007
Location: Mountain View, California
Posts: 9,624
Two suggestions for ya:

First, on game logic, how about using DENIAL_POWER_US for "We're doing fine on our own." DENIAL_ATTITUDE is for when they don't like you enough; you don't need to be their worst enemy for this one, by the way.

Second, on coding style, I would reverse your if test and move the "return" up to it:

Code:
if (55 * iOurPower /100 > iTheirPower)
{
	return DENIAL_POWER_US;
}
I think this is better because the result of not being powerful enough (returning a denial) is right next to the test that causes it. This is sometimes called "early return" in that you bail out of the function as soon as you determine that's what you want to do. Some people don't like having multiple exits from a function, and that can be confusing if there are multiple places in a long function.

However, I prefer to have effects near their causes. This way you don't have to read through the entire function to find out what happens in the "else" clause, nor do you see the else clause and have to scroll up to see what the if-test is.

A minor advantage is that it removes one level of indentation for everything that follows. While this is fairly trivial, as the function grows and gets more complicated, each level of nesting requires keeping a larger mental context which just makes it more difficult to understand at a glance what the function does.

Finally, note that I removed all but the outermost parentheses. This really is trivial, but if you memorize the few rules of operator precedence you will save yourself a lot of () typing and matching in the long run. In this case, * and / have the same precedence, so they are evaluated left-to-right, and the comparison operators have lower precedence, so > is evaluated last.

While the presence of () has no bearing on the compiler in this case, it forces me to match them to know what the expression does. Leaving them out allows me to read it more quickly by depending on the rules of operator precedence.
__________________
Monkeys killing monkeys killing monkeys over pieces of the ground.
Silly monkeys, give them thumbs they make a club and beat their brother down.


BUG Mod - BTS Unaltered Gameplay
[ Forum | Download | FAQ | Known Issues | Troubleshooting | Modding Tutorial ]

BAT 3.0.1 QuickFix™ released Oct 24th
EmperorFool is offline   Reply With Quote
Old Apr 29, 2009, 01:02 PM   #11
Gooblah
Heh...
 
Gooblah's Avatar
 
Join Date: Jun 2007
Posts: 4,282
Quote:
Originally Posted by EmperorFool View Post
Two suggestions for ya:

First, on game logic, how about using DENIAL_POWER_US for "We're doing fine on our own." DENIAL_ATTITUDE is for when they don't like you enough; you don't need to be their worst enemy for this one, by the way.

Second, on coding style, I would reverse your if test and move the "return" up to it:

Code:
if (55 * iOurPower /100 > iTheirPower)
{
	return DENIAL_POWER_US;
}
I think this is better because the result of not being powerful enough (returning a denial) is right next to the test that causes it. This is sometimes called "early return" in that you bail out of the function as soon as you determine that's what you want to do. Some people don't like having multiple exits from a function, and that can be confusing if there are multiple places in a long function.
Oh yeahhhh.....the program checks through each code block one at a time right? So if your object meets condition 1, then it'll go for that, even if it could have met condition 2.

Quote:
However, I prefer to have effects near their causes. This way you don't have to read through the entire function to find out what happens in the "else" clause, nor do you see the else clause and have to scroll up to see what the if-test is.
So, program checks the 'if' statement. if it doesn't meet the condition, it ignores it and heads to the next line of code - in this case a for loop.

Quote:
Finally, note that I removed all but the outermost parentheses. This really is trivial, but if you memorize the few rules of operator precedence you will save yourself a lot of () typing and matching in the long run. In this case, * and / have the same precedence, so they are evaluated left-to-right, and the comparison operators have lower precedence, so > is evaluated last.

While the presence of () has no bearing on the compiler in this case, it forces me to match them to know what the expression does. Leaving them out allows me to read it more quickly by depending on the rules of operator precedence.
This I know, but IMO it's easier. Well, thanks EmperorFool.
__________________
It'll all work out.
Gooblah is offline   Reply With Quote
Old Apr 29, 2009, 01:29 PM   #12
EmperorFool
Deity
 
EmperorFool's Avatar
 
Join Date: Mar 2007
Location: Mountain View, California
Posts: 9,624
Given that the code inside the if test exits the function with "return", there's no need to put the rest of the code following it inside an "else" block.
__________________
Monkeys killing monkeys killing monkeys over pieces of the ground.
Silly monkeys, give them thumbs they make a club and beat their brother down.


BUG Mod - BTS Unaltered Gameplay
[ Forum | Download | FAQ | Known Issues | Troubleshooting | Modding Tutorial ]

BAT 3.0.1 QuickFix™ released Oct 24th
EmperorFool is offline   Reply With Quote
Reply

Bookmarks

Go Back Civilization Fanatics' Forums > CIVILIZATION IV > Civ4 - Creation & Customization > Civ4 - SDK/Python > Capitulation Mechanics

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Capitulation Badhron Civ4 - General Discussions 11 Aug 28, 2008 09:34 PM
Capitulation galahadba Civ4 - General Discussions 6 Nov 19, 2007 06:37 AM
Capitulation Mechanics... vra379971 Civ4 - Strategy & Tips 4 Oct 04, 2007 01:29 PM
Capitulation itsnotmeee Civ4 - Strategy & Tips 35 Jun 01, 2007 01:48 AM
Capitulation wioneo Civ4 - General Discussions 9 Sep 26, 2006 06:43 PM


Advertisement

All times are GMT -6. The time now is 04:45 AM.


Powered by vBulletin®
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.
This site is copyright © Civilization Fanatics' Center.
Support CFC: Amazon.com | Amazon UK | Amazon DE | Amazon CA | Amazon FR