[MOD] More Naval AI

Just glancing at the code, it does not seem like a Lanun civ generated later through a revolution or through initNewEmpire on would be granted its unique Seafaring tech unless it was brought into the game by another Lanun player.

(Edit: I just tested this by changing CIVILIZATION_INFERNAL to CIVILIZATION_LANUN in the Infernal Pact code. Hyborem of the Lanun did not stat with Seafaring, but was able to research it within a turn.)

I think that in order to fix that the initNewEmpire should probably be more like this:

Code:
PlayerTypes CvPlayer::initNewEmpire(LeaderHeadTypes eNewLeader, CivilizationTypes eNewCiv)
	{
	FAssert(eNewLeader != NO_LEADER);
	FAssert(eNewCiv != NO_CIVILIZATION);
	
	PlayerTypes eNewPlayer = getOpenPlayer();
	FAssert(eNewPlayer != NO_PLAYER);
	FAssert(!GET_TEAM(GET_PLAYER(eNewPlayer).getTeam()).isAlive());
	
	if (eNewPlayer != NO_PLAYER)
	{
		// remove leftover culture from old recycled player
		for (int iPlot = 0; iPlot < GC.getMapINLINE().numPlotsINLINE(); ++iPlot)
		{
			CvPlot* pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iPlot);
			
			pLoopPlot->setCulture(eNewPlayer, 0, false, false);
		}
		
		GC.getGameINLINE().addPlayer(eNewPlayer, eNewLeader, eNewCiv);
		GC.getInitCore().setLeaderName(eNewPlayer, GC.getLeaderHeadInfo(eNewLeader).getTextKeyWide());
		
		CvTeam& kNewTeam = GET_TEAM(GET_PLAYER(eNewPlayer).getTeam());
		for (int i = 0; i < GC.getNumTechInfos(); ++i)
		{
			[COLOR="Red"]if ((GC.getCivilizationInfo(eNewCiv).isCivilizationFreeTechs((TechTypes)i))) 
			{
				kNewTeam.setHasTech((TechTypes)i, true, eNewPlayer, false, false);
			}
			elif (GET_TEAM(getTeam()).isHasTech((TechTypes)i) && GET_PLAYER(eNewPlayer).canEverResearch((TechTypes)i))[/COLOR]
			{
				kNewTeam.setHasTech((TechTypes)i, true, eNewPlayer, false, false);
				if (GET_TEAM(getTeam()).isNoTradeTech((TechTypes)i) || GC.getGameINLINE().isOption(GAMEOPTION_NO_TECH_BROKERING))
					{
					kNewTeam.setNoTradeTech((TechTypes)i, true);
					}
			}
		}
		
		ReligionTypes eFavorite = getFavoriteReligion();
		ReligionTypes eNewFavorite = GET_PLAYER(eNewPlayer).getFavoriteReligion();
		
		if (eFavorite != NO_RELIGION)
		{
			if (eNewFavorite == NO_RELIGION)
			{
				GET_PLAYER(eNewPlayer).setFavoriteReligion(eFavorite);
			}
		}
		
		for (int iTeam = 0; iTeam < GC.getMAX_TEAMS(); iTeam++)
		{
			CvTeam& kLoopTeam = GET_TEAM((TeamTypes)iTeam);
			
			if (kLoopTeam.isAlive())
			{
				kNewTeam.setEspionagePointsAgainstTeam((TeamTypes)iTeam, GET_TEAM(getTeam()).getEspionagePointsAgainstTeam((TeamTypes)iTeam));
				kLoopTeam.setEspionagePointsAgainstTeam(GET_PLAYER(eNewPlayer).getTeam(), kLoopTeam.getEspionagePointsAgainstTeam(getTeam()));
			}
		}
		kNewTeam.setEspionagePointsEver(GET_TEAM(getTeam()).getEspionagePointsEver());
		
		AI_updateBonusValue();
	}
	
	return eNewPlayer;

And the revolutions code more like this:
Code:
def giveTechs( toPlayer, fromPlayer, expensiveVars = [1,3], doTakeAway = True ) :

		# Give all techs known by fromPlayer, except a few of the most expensive
		knownTechs = list()
		mostExpensive = list()
		minMostExpensive = 0
		numMostExpensive = expensiveVars[0] + game.getSorenRandNum(expensiveVars[1],'Rev: Pick num techs')

		fromPlayerTeam = gc.getTeam( fromPlayer.getTeam() )
		toPlayerTeam = gc.getTeam( toPlayer.getTeam() )

		for techID in range(0,gc.getNumTechInfos()) :
		[COLOR="Red"]
			if gc.getCivilizationInfo(toPlayer.getCivilizationType()).isCivilizationFreeTechs(techID):
				knownTechs.append( techID )
			elif toPlayer.canEverResearch( techID):[/COLOR]
				if( fromPlayerTeam.isHasTech( techID ) ) :
					knownTechs.append( techID )
					if( gc.getTechInfo( techID ).getResearchCost() > minMostExpensive ) :
						if( len(mostExpensive) < numMostExpensive ) :
							mostExpensive.append( techID )
						else :
							for j in range(0,len(mostExpensive)) :
								if( gc.getTechInfo( mostExpensive[j] ).getResearchCost() == minMostExpensive ) :
									mostExpensive.remove( mostExpensive[j] )
									break
							mostExpensive.append( techID )
							minMostExpensive = gc.getTechInfo( mostExpensive[0] ).getResearchCost()
							for j in range(0,len(mostExpensive)) :
								if( gc.getTechInfo( mostExpensive[j] ).getResearchCost() < minMostExpensive ) :
									minMostExpensive = gc.getTechInfo( mostExpensive[j] ).getResearchCost()

			if( doTakeAway and toPlayerTeam.isHasTech(techID) and toPlayerTeam.getNumMembers() == 1 ) :
				# take away all techs
				#if( LOG_DEBUG ) : CvUtil.pyPrint("  Revolt - Taking away %s"%(PyInfo.TechnologyInfo(techID).getDescription()))
				toPlayerTeam.setHasTech(techID,False,toPlayer.getID(),False,False)

		if( doTakeAway ) :
			if( not toPlayer.getTechScore() == 0 ) :
				# Shouldn't have to do this, but tech scores never came out to zero for reincarnated civs ...
				if( LOG_DEBUG ) : CvUtil.pyPrint("  Revolt - Resetting tech score ...")
				toPlayer.changeTechScore( -toPlayer.getTechScore() )

		for techID in knownTechs :
			if( not techID in mostExpensive ) :
				#if( LOG_DEBUG ) : CvUtil.pyPrint("  Revolt - Giving rev %s"%(PyInfo.TechnologyInfo(techID).getDescription()))
				toPlayerTeam.setHasTech(techID,True,toPlayer.getID(),False,False)
			else :
				if( LOG_DEBUG ) : CvUtil.pyPrint("  Revolt - NOT giving rev all of %s"%(PyInfo.TechnologyInfo(techID).getDescription()))
				techCost = toPlayerTeam.getResearchCost( techID )
				maxFreeResearch = techCost*0.75
				toPlayerTeam.setResearchProgress( techID, game.getSorenRandNum(int(maxFreeResearch),'RevUtils: free research'), toPlayer.getID() )


You could then ensure that the Infernals start with the Infernal Pact technology by adding thsi to their CIV4CivilizationInfox.xml define:

Code:
			<FreeTechs>
				<FreeTech>
					<TechType>TECH_INFERNAL_PACT</TechType>
					<bFreeTech>1</bFreeTech>
				</FreeTech>
			</FreeTechs>


It is possible that that could create a problem in games that start out with the Infernals present (which would pretty much only be scenarios unless someone edits the game to make the playable from the start). The game could try to create a second copy of the Infernals when the first copy is given Infernal Pact before anyone else.


You could easily prevent that by editing CvEventManager.py and placing either if pPlayer.getCivilizationType() != gc.getInfoTypeForString('CIVILIZATION_INFERNAL'): or if not CyGame().isCivEverActive(gc.getInfoTypeForString('CIVILIZATION_INFERNAL')): around line 1742.


(Edit: I just tested a game after giving the Infernals this starting tech and making them playable. A duplicate Hyborem was indeed spawned at the start of the game.

I also tested and found that both of the suggestions to prevent this do indeed work.)

Personally would suggest you simplify the code like this:
Code:
		if not gc.getGame().isOption(GameOptionTypes.GAMEOPTION_NO_HYBOREM_OR_BASIUM):
			if (iTechType == gc.getInfoTypeForString('TECH_INFERNAL_PACT') and iPlayer != -1):
				# iCount = 0
				# for iTeam in range(gc.getMAX_TEAMS()):
					# pTeam = gc.getTeam(iTeam)
					# if pTeam.isHasTech(gc.getInfoTypeForString('TECH_INFERNAL_PACT')):
						# iCount = iCount + 1
				# if iCount == 1:
				if not CyGame().isCivEverActive(gc.getInfoTypeForString('CIVILIZATION_INFERNAL')):
 
OK. I'll check out your code.

Ok :)

OK. I'll put in a request now and see what the mods say.

Great :D

I think that in order to fix that the initNewEmpire should probably be more like this:

...

Thank you for the pointers, MagisterCultuum :)

I can confirm that MagisterCultuum's solution for issue #3593005 works (changes to CvPlayer.cpp, CIV4CivilizationInfos.xml and CvEventManager.py). I tested the following scenarios:

Lanun summons Hyborem of the Infernals (Hyborem gets Infernal pact but he does not get Seafaring).
Lanun summons Hyborem of the Lanun (Hyborem gets Seafaring)
Sidar summons Hyborem of the Infernals (Hyborem gets Infernal pact)
Sidar summons Hyborem of the Lanun (Hyborem gets Seafaring)

I did not test the Revolutions part of the issue at all (one of these days I'll start a game with it to get to know how it works :) ). Because of this, the code I'm attaching to this issue does not include MagisterCultuum's suggested fix for the giveTechs functions in the revolutions code.

I also have a bug to report. In the Civilopedia pages for traits, the mouseover text for leaders always show the Amurite world spell and hero, regardless of the leader's real civilization.

EDIT: I forgot to attach the file.
 

Attachments

I'm not seeing this issue.

The bug was present with the code I posted in the previous issue. I just checked again with a clean compilation of More Naval AI r1247 to be sure and the issue is still there. The mouseover text for leaders is correct in other screens such as when you select a specific civilization in the civilopedia, but it is wrong when you select a trait and check the mouseover text of one of the leaders with that trait.
 
I just discovered that a dropped piece of equipment is sufficient to garrison a fort and have it upgrade.

I tend to think that no unit with 0 strength should be able to do that.
 
Regarding bug 3574171 (If I understood it correctly:)): I copied attached file (from LoR; I remembered it was fixed there) to \My Games\Beyond the Sword\FFH - More Naval AI\Settings\CustomRevAdv\CustomRevAdv.txt, and it looks better now.
The file is loaded in \Screens\RevolutionWatchAdvisor.py

EDIT: Offtopic: did you consider to announce your mod here, to show the community FfH modding is alive (apart from MoM)?
 

Attachments

The bug was present with the code I posted in the previous issue. I just checked again with a clean compilation of More Naval AI r1247 to be sure and the issue is still there. The mouseover text for leaders is correct in other screens such as when you select a specific civilization in the civilopedia, but it is wrong when you select a trait and check the mouseover text of one of the leaders with that trait.

Still not seeing it. Checked on two different computers. I haven't done anything recently that would affect the Sevopedia.

I just discovered that a dropped piece of equipment is sufficient to garrison a fort and have it upgrade.

Added to the bug list.

Regarding bug 3574171 (If I understood it correctly:)): I copied attached file (from LoR; I remembered it was fixed there) to \My Games\Beyond the Sword\FFH - More Naval AI\Settings\CustomRevAdv\CustomRevAdv.txt, and it looks better now.
The file is loaded in \Screens\RevolutionWatchAdvisor.py

Great! Now we just need to have that file auto-generated by the game (all of the other .ini files in that directory are) since the installer doesn't do that part.

EDIT: Offtopic: did you consider to announce your mod here, to show the community FfH modding is alive (apart from MoM)?

I have considered it. I'll probably wait until the new forum is approved.
 
RE: 'Psychotic AI' at high difficulty levels.

Send me a save game (ver 2.4) from right before a civ declares war on you which you think is inappropriate for the AI in that situation and I'll look at it.

I've played several games, and it's not so much that it's a bad decision for the AI to attack (Cassiel with 20 CR3 axes, or Sandalphon with 20 invisible CII axes, were easily able to cut their way through my so-called empire). The AI gets so many advantages at the higher difficulty levels that the human has to be left alone to build up a bit before having any chance against them. If the AIs decide to fight each other instead of me (which seems to require an isolated start and no contact before turn 80 or so), then I can still win an Immortal game. If one or more of my neighbor AIs attacks, though, it's just game over. Even in the unlikely event I was able to withstand the attack, building an early army means that any AI that builds an economy instead of infinite numbers of axes will move into an insurmountable lead.
 
It does seem like it would be better if the power ratios mattered a bit less and the diplomatic relations between players mattered a bit more. It is rather frustrating when a neighbor who has "Friendly" relations with you decided to declare war on you rather than on another player with whom he was "Furious."

I seem to recall reading that the AI will not decide to go to war when it has friendly relations, but that the decision to go to war happens long before the actual declaration. Many things can change in the intervening time, including a formerly weak enemy becoming a strong ally. It would probably be better for the AI to reevaluate its war decisions closer to the time of declaring war.

I vaguely I recall one game where I believe I not only had friendly relations with another player, but also had a defensive pact that had lasted almost long enough to get a permanent alliance when he decided to declare war on me.

(Personally I would very much prefer it if the AI was not blocked from making permanent alliances before having a common war or defensive pact for such a long and arbitrary number of consecutive turns, and if diplomatic relations between players mattered more in that decision too. It is also rather annoying that the AI won't consider peace treaties for the first several turns of war, regardless of how the war is going or how much you wish to offer. You may not want to change such things like that which have been in place since Vanilla Civ IV though.)


I tend to think that the AI should only very rarely declare war on another player at random. It would be better for them to leverage their power by making more arrogant demands (even demanding that you give up your best cities or become their vassal if the power difference is great enough) when they know that the other player is too weak to wish to risk a war.
 
I just discovered that a dropped piece of equipment is sufficient to garrison a fort and have it upgrade.

I tend to think that no unit with 0 strength should be able to do that.

Was Advanced Tactics on? All the XML tags that Super Forts adds only do something if AT is on. This was done so that gameplay wouldn't change when AT is off. I just want to be sure before I go chasing down the bug.

I uploaded a fix for hidden nationality units. They shouldn't be able to claim forts in the next version.
 
Yes, Advanced Tactics was on. I first noticed it in a custom version of the Lord of the Balors scenario where I had activated that game option. I just now confirmed it in a quick game on the smallest size map and made sure that the game option was on first.
 
Tholal: While trying to merge the avoid unhappy citizens button, I found out that the emphasize infos EMPHASIZE_AVOID_ANGRY_CITIZENS and EMPHASIZE_AVOID_UNHEALTHY_CITIZENS are already there and working. I suppose you included them when you merged parts of wildmana. Is there any reason why you don't want them in the city screen? I actually managed to get it working in just half an hour, just some changes in MainInterface.py (I just wanted to try out the interface, and was very surprised to see it was already working!)

I merged your changes to CvMainInterface.py and I dont see those buttons on the city screen.
Edit: Nevermind. I found them.


Speaking of HN, I noticed in a recent game as Jonas that I was able to use an HN unit to kill my own units when those units were in a barbarian city.

Unable to replicate this issue.
 
It doesn't seem to be happening with be anymore either.

The combat odds information still shows my own unit as the opponent, but when my HN unit tries to attack it only attacks barbarian units in the city and is unable to attack or enter the city if no such unit exists.

I'm was pretty sure that I had managed to destroy my own unit that way before, but maybe I actually just destroyed a barbarian warrior and thought it was my unit because of what the combat odds said I would be attacking.

edit:

I just captured a Citadel using a Fireball, which of course exploded in combat and could not hold the court. I don't think that units with <bExplodeInCombat>1 <bSuicide>1 should be able to capture forts either.

It was also rather annoying that capturing the fort changed the ownership of the plot on which the caster and other units were standing (from the Ljosalfar, with which I was at war, to the Amurites, with whom I did not have an open borders agreement) and pushed them further away so that they could not enter the Citadel to guard it that turn. The enemy had no units nearby, but if they had this would have let them easily recapture their superfort.
 
I just discovered that a dropped piece of equipment is sufficient to garrison a fort and have it upgrade.

I tend to think that no unit with 0 strength should be able to do that.

Except for Corlindale right? :D
 
I just discovered that a dropped piece of equipment is sufficient to garrison a fort and have it upgrade.

I tend to think that no unit with 0 strength should be able to do that.

Was Advanced Tactics on? All the XML tags that Super Forts adds only do something if AT is on. This was done so that gameplay wouldn't change when AT is off. I just want to be sure before I go chasing down the bug.

Except for Corlindale right? :D

I took care of this bug this morning by adding a canDefend() check to the code when it's checking for fort defenders. This excludes objects, Workers and Corlindale (and some other units)

I uploaded a fix for hidden nationality units. They shouldn't be able to claim forts in the next version.

Yep. I verified that your code works and it will be included with the 2.41 release.


MagisterCultuum said:
I just captured a Citadel using a Fireball, which of course exploded in combat and could not hold the court. I don't think that units with <bExplodeInCombat> should be able to capture forts either.

<bExplodeInCombat> include Pyre Zombies. That tag isnt the issue as it only fires when the unit dies. The fireball captures the fort when it wins a combat, but then it dies. I think what we want to look for is the <bSuicide> tag instead, which also includes Meteors. I'll add it to the bug list.
 
Tholal, is it intended ( v2.4 ) that the scoreboard won't show power ratio even after I enable it in the BUG options? I think the issue is because it wants me to have an embassy, which I can't have cause I'm not using advanced tactics. that line of code should only run if you're using the suitable gameoption.

also, is there any issue with advanced combat odds? I think it should come enabled by default due to sheer awesomeness :D
 
I took care of this bug this morning by adding a canDefend() check...

Yep. I verified that your code works and it will be included with the 2.41 release.

Good to hear.

<bExplodeInCombat> include Pyre Zombies. That tag isnt the issue as it only fires when the unit dies. The fireball captures the fort when it wins a combat, but then it dies. I think what we want to look for is the <bSuicide> tag instead, which also includes Meteors. I'll add it to the bug list.

I'll fix this. I think I will also organize the code better, so we can easily prevent things from capturing forts and the AI will be aware of it. Adding some sort of function like canCapture() that checks all the cases like suicide or hidden nationality should be sufficient. Perhaps I should just use and modify the isNoCapture() function in CvUnit.cpp? Would it be ok for me to make isNoCapture() return true for units with bSuicide? (isNoCapture() already returns true for hidden nationality units)
 
I'll fix this. I think I will also organize the code better, so we can easily prevent things from capturing forts and the AI will be aware of it. Adding some sort of function like canCapture() that checks all the cases like suicide or hidden nationality should be sufficient. Perhaps I should just use and modify the isNoCapture() function in CvUnit.cpp? Would it be ok for me to make isNoCapture() return true for units with bSuicide? (isNoCapture() already returns true for hidden nationality units)

The units in question are already set to noCapture in UnitInfos.xml. I think the issue is that Super Forts isn't checking for noCapture when deciding who can move into the fort plot?
 
[to_xp]Gekko;12116273 said:
Tholal, is it intended ( v2.4 ) that the scoreboard won't show power ratio even after I enable it in the BUG options?

Yes. If you read the mouseover description for that option you will see that it states that it's used for Advanced Tactics only.

also, is there any issue with advanced combat odds? I think it should come enabled by default due to sheer awesomeness :D

Nothing major that I'm aware of, though I don't think it takes into account all of the FFH-specific combat stuff.
 
The units in question are already set to noCapture in UnitInfos.xml. I think the issue is that Super Forts isn't checking for noCapture when deciding who can move into the fort plot?

Yes that is the problem. I should have used it before. :wallbash: This will be easy to fix. I just need to replace all the "!isHiddenNationality()" checks I added in rev. 1250 to "!isNoCapture()".
 
Back
Top Bottom