always peace


Jul 7, 2017
I wanted to know if there was a way, either in phyton or in xml modifications, to make a single civilization always at peace with everyone, and therefore unassailable - I play the relaism invictu mod, there is an allways pitch option there, but it applies to all civilizations. thank you.

I found a script already ready but not for mod bugs, so I tried to adapt it
Last edited:
I started from this

I made these changes
created 2 file in folder contrib:

## Sid Meier's Civilization 4
from CvPythonExtensions import *
import BugUtil

import WarNPeaceUtil
gc = CyGlobalContext()

def onLoadGame(self, argsList):
###WarNPeace part 2 start###
WarNPeaceUtil.loadEvents("Mods/Realism Invictus/Assets/XML/CustomXML/WarNPeace.xml")
###WarNPeace part 2 end###

def onGameStart(self, argsList):
'Called at the start of the game'
###WarNPeace part 3 start###
WarNPeaceUtil.loadEvents("Mods/Realism Invictus/Assets/XML/CustomXML/WarNPeace.xml")
###WarNPeace part 3 end###

def onBeginGameTurn(self, argsList):
'Called at the beginning of the end of each turn'
iGameTurn = argsList[0]
###WarNPeace part 4 start###
###WarNPeace part 4 end###

ant this WarNPeace:
###You do not have to change anything in this file
###all changes have to be done in the CvEventManager.
###This file just has to be in the same folder like the

from CvPythonExtensions import *
import sys
import Popup as PyPopup
import CvUtil
gc = CyGlobalContext()
lEvents = []

def triggerEvents(iTurn):
iTurn += 1
iYear = CyGame().getTurnYear(iTurn)
lRemove = []
for item in lEvents:
if iYear < item[0]:
if item[1] <= iTurn:
for iAttacker in item[2]:
pAttacker = gc.getTeam(iAttacker)
for iDefender in item[3]:
if iAttacker == iDefender: continue
pDefender = gc.getTeam(iDefender)
if item[4]:
if item[6] or pAttacker.canDeclareWar(iDefender):
if not pAttacker.isAtWar(iDefender):
pAttacker.declareWar(iDefender, True, -1)
if item[7] != "NONE":
doPopup(item[7], iAttacker, iDefender)
if item[5] and pAttacker.isAtWar(iDefender):
if pAttacker.isAtWar(iDefender):
if item[7] != "NONE":
doPopup(item[7], iAttacker, iDefender)
if item[5]:
for iRemove in lRemove:

def doPopup(sText, iAttacker, iDefender):
for iPlayer in xrange(gc.getMAX_CIV_PLAYERS()):
pPlayer = gc.getPlayer(iPlayer)
if pPlayer.isHuman():
if pPlayer.getTeam() == iAttacker or pPlayer.getTeam() == iDefender:
popupInfo = CyPopupInfo()
szText = CyTranslator().getText(sText, ())

def loadEvents(sFilePath):
del lEvents[:]
CurEvent = []
for sCurrent in MyFile.readlines():
if "#" in sCurrent:
if "Attacker" in sCurrent:
CurEvent = []
lAttacker = getTeamID(CutString(sCurrent))
if len(lAttacker) > 0:
## iDate, iTurn, lAttacker, lDefender, sWar, bPermanent, bForce, sMessage]
CurEvent = [- 9999999, -1, lAttacker, (), 0, 0, 0, ""]

if len(CurEvent) == 0:
if "Defender" in sCurrent:
lDefender = getTeamID(CutString(sCurrent))
if len(lDefender) == 0:
CurEvent = []
CurEvent[3] = lDefender
elif "bWar" in sCurrent:
CurEvent[4] = int(CutString(sCurrent))
elif "sTriggerMap" in sCurrent:
sMap = CutString(sCurrent)
if not bMapCheck(sMap, True):
CurEvent = []
elif "sIgnoreMap" in sCurrent:
sMap = CutString(sCurrent)
if not bMapCheck(sMap, False):
CurEvent = []
elif "iDate" in sCurrent:
sDate = CutString(sCurrent)
if sDate != "NONE":
iDate = int(sDate)
if iDate < CyGame().getGameTurnYear():
CurEvent = []
CurEvent[0] = iDate
elif "iTurn" in sCurrent:
iTurn = int(CutString(sCurrent))
if iTurn > -1:
if iTurn < CyGame().getGameTurn():
CurEvent = []
CurEvent[1] = iTurn
CurEvent[0] = CyGame().getTurnYear(iTurn)
elif "bPermanentWar" in sCurrent:
CurEvent[5] = int(CutString(sCurrent))
elif "bForceWar" in sCurrent:
CurEvent[6] = int(CutString(sCurrent))
elif "Message" in sCurrent:
CurEvent[7] = CutString(sCurrent)

def bMapCheck(sMap, bTrigger):
if sMap == "NONE":
return True
MapName = CyMap().getMapScriptName ()
if ".civ" in MapName:
MapName = MapName[:MapName.find(".civ")]
if ".Civ" in MapName:
MapName = MapName[:MapName.find(".Civ")]
if bTrigger:
return sMap == MapName
return sMap != MapName

def getTeamID(sName):
lTeams = []
if gc.getInfoTypeForString(sName) == -1 and sName != "ALL":
return lTeams
for i in xrange(gc.getMAX_CIV_PLAYERS()):
pPlayer = gc.getPlayer(i)
if pPlayer.isAlive():
iTeam = pPlayer.getTeam()
if iTeam in lTeams: continue
if sName == "ALL":
elif "CIVILIZATION" in sName and pPlayer.getCivilizationType() == gc.getInfoTypeForString(sName):
elif "LEADER" in sName and pPlayer.getLeaderType() == gc.getInfoTypeForString(sName):
return lTeams

def CutString(string):
string = string[string.find(">") + 1:]
string = string[:string.find("<")]
return string

and in customxml this for try

<Map>RI World map Huge Scenario</Map>
<Map>RI World map Huge Scenario</Map>
<Map>RI World map Huge Scenario</Map>

Now I get no errors when starting a game, but nothing happens, if anyone can help me figure out what I'm doing wrong. Thank you
Last edited:
Regarding the WarNPeace mod component, let me link to the thread in the BUG subforum.

There is USE_CAN_DECLARE_WAR_CALLBACK in PythonCallbackDefines.xml and the corresponding Python function canDeclareWar in If the peace civ is always going to be in the same player slot, e.g. in the 5th (i.e. player ID 4), then this should suffice (not tested):
	def canDeclareWar(self,argsList):
		iAttackingTeam, iDefendingTeam = argsList
		if iDefendingTeam == 4 or iAttackingTeam == 4:
			return False
		return True
If Realism Invictus doesn't dispatch to CvGameUtils, then the code could be moved to EntryPoints\, without the self argument and replacing the canDeclareWar function there. (Or more properly to some BUG module, but I don't know how to do that off the top of my head. Edit: But it's been easy to figure out: link) If none of this has any apparent effect, then verifying through some print statement (e.g. print "canDeclareWar call has occurred") that the Python function is actually reached would be a good first step. print writes to \My Games\Beyond the Sword\Logs\PythonDbg.log if LoggingEnabled is set in \My Games\Beyond the Sword\CivilizationIV.ini. Edit2: Rather than bother with the log file, just always returning False should also be a reliable way to check whether canDeclareWar is reached. It should then be impossible to declare any wars.
Last edited:
i try in CvGameUtils,
but nothing happens, I can declare war on team 4, I copied what it says into the .dbg file, searching for the word "canDeclareWar" this comes up
19:12:07 DEBUG: BugGameUtils - canDeclareWar - setting default to True-
CvGameUtils is probably no use in a BUG-based mod. What you've copied always gets written, I think. So I assume that your canDeclareWar function and print statement aren't reached. Well, at least the log file itself works.
Top Bottom