1. We have added a Gift Upgrades feature that allows you to gift an account upgrade to another member, just in time for the holiday season. You can see the gift option when going to the Account Upgrades screen, or on any user profile screen.
    Dismiss Notice

Technical documentation

Discussion in 'Rhye's and Fall: The Sword of Islam' started by embryodead, Jun 28, 2011.

  1. embryodead

    embryodead Caliph

    Joined:
    Jan 1, 2003
    Messages:
    5,179
    Location:
    basement
    Sorry, I missed this post. Nothing changed, this part wasn't in CvRhyes, it was in CvEnums already. The code you posted, both solutions are fine, and this part cannot really be moved to Python.
     
  2. embryodead

    embryodead Caliph

    Joined:
    Jan 1, 2003
    Messages:
    5,179
    Location:
    basement
    From what you write it seems that you're not saving the value in setPersecutionReligions to scriptData properly. Remember to pickle & save and then load & unpickle, if you haven't switched to my less pickly method. Also remember to put lPersecutionData & lPersecutionReligions into the dictionary up top.
     
  3. AbsintheRed

    AbsintheRed Deity

    Joined:
    Jul 27, 2009
    Messages:
    8,288
    Location:
    Szeged, Hungary
    This is how the functions look like in the RFCUtils.py:
    Code:
    def getPersecutionData(self):
                    scriptDict = pickle.loads( gc.getGame().getScriptData() )
                    return scriptDict['lPersecutionData'][0], scriptDict['lPersecutionData'][1], scriptDict['lPersecutionData'][2]
    
            def setPersecutionData(self, iPlotX, iPlotY, iUnitID):
                    scriptDict = pickle.loads( gc.getGame().getScriptData() )
                    scriptDict['lPersecutionData'] = [iPlotX, iPlotY, iUnitID]
    
            def getPersecutionReligions(self):
                    scriptDict = pickle.loads( gc.getGame().getScriptData() )
                    return scriptDict['lPersecutionReligions']
    
            def setPersecutionReligions(self, val):
                    scriptDict = pickle.loads( gc.getGame().getScriptData() )
                    scriptDict['lPersecutionReligions'] = val
    I put the lPersecutionData and lPersecutionReligions as last entries into the storeddata.py
    I'm not sure what do you mean by moving them up top in the dictionary...

    EDIT: Oh I see what I missed from unpickle
    gc.getGame().setScriptData( pickle.dumps(scriptDict) )

    EDIT2: Thanks, the popup seems to work fine now :)
     
  4. AbsintheRed

    AbsintheRed Deity

    Joined:
    Jul 27, 2009
    Messages:
    8,288
    Location:
    Szeged, Hungary
    Another question regarding inquisitors:

    The popup works perfectly for the human, and I realize that you added a religion 'choice' for the AI based on the con.tPersecutionOrder in the doPersecution function
    But how do you actually call the doPersecution for the AI?
    I'm afraid I don't understand your code in the CvUnitAI.cpp

    In RFCE the actual function to purge is defined in the dll (in the CvCity.cpp: canPurgeReligion and doPurgeReligion), not in the RFCUtils.py
    I guess exactly because the call from CvUnitAI.cpp
    What's more straightforward to do:
    move the function to python, like in SoI?
    or update the dll function there, and somehow get the religion choice based on the python popup?
     
  5. embryodead

    embryodead Caliph

    Joined:
    Jan 1, 2003
    Messages:
    5,179
    Location:
    basement
    The CvUnitAI part only does one thing: it redirects the AI logic for Persecutor unit to AI_unitUpdate method in CvGameUtils.py

    In CvGameUtils: AI_unitUpdate calls doInquisitorCore_AI, which moves the Inquisitor to a city to persecute, based on the Leader's tolerance and religion, then if at the city, it calls doPersecution.

    My implementation is not straightforward or pretty and 3Miro probably won't like it ;) but it offers more functionality that I wouldn't easily do in C++. With the amount of AI Persecutors in the game, it's not hurting performance at all, it's just not straightforward.
     
  6. AbsintheRed

    AbsintheRed Deity

    Joined:
    Jul 27, 2009
    Messages:
    8,288
    Location:
    Szeged, Hungary
    Well, if I want to remove only one religion at a time, I have to do something like this anyway
    3Miro's dll code currently removes all religion (expect state religion)
    If I want to put that in line with the chooseable religion for the human player, I would need at least one python callback anyway
    So I guess it's more convenient to use your method... I just feel bad to remove 3Miro's code

    Btw, your code for the AI actually building persecutors (CvCityAI.cpp) is totally separated from this, right?
    Also, I saw you based that part on 3Miro's, how is it improved?
     
  7. embryodead

    embryodead Caliph

    Joined:
    Jan 1, 2003
    Messages:
    5,179
    Location:
    basement
    Yes, it is separate. IIRC 3Miro's code added a chance for the AI to switch to building of Persecutor whenever it decided to build a Missionary. When I tested it, it didn't work well because the AI builds Missionaries only if it has a holy city, or (very rarely) if it still has cities without religion. With the original code the persecutor was almost never built, so I added the same chance to the Spy.

    I also added a check to skip the whole thing if there are no non-state religions in AI's empire (at least I think that part was mine), and the probability is not fixed but based on leader's buildPersecutorProb stat.

    Persecutor unit type is also determined by the unit ability in the XML, rather than by constant.
     
  8. AbsintheRed

    AbsintheRed Deity

    Joined:
    Jul 27, 2009
    Messages:
    8,288
    Location:
    Szeged, Hungary
    Minor questions connected to your dopersecution code:

    1;
    here you loop through the religions' order in the consts.py based on the statereligion
    but what happens if the AI civ doesn't have a state religion?
    or the AI will never persecute without a state religion?

    2;
    you use the pCity.getReligionCount() function
    AFAIK it was exposed to python, and RFCE already uses the function in a couple places (in c++ at least)
    why is it needed then to add these lines in cycity.cpp?

    3;
    you added the new AttitudeExtra diplomacy modifier
    (IIRC I already asked this earlier, but didn't found your answer)
    Is it possible to add memory decays to this attitude too?
    Is it possible to lose the attitude modifier when the other civ switches from that state religion?


    4;
    I think you made a typo here
    Didn't you want to add min(25, pPlayer.getFaith()/2) ?


    5;
    Another possible mistake here
    Your code:

    Shouldn't it be this?
    I'm not sure, you may have it intentionally that way
    I just wanted to mention, that currently your code always kills only one population (if it's at least 4 of course)
     
  9. embryodead

    embryodead Caliph

    Joined:
    Jan 1, 2003
    Messages:
    5,179
    Location:
    basement
    1. There would be a Pyton exception, but that can't really happen because you need a state religion to build a Religious Persecutor (also in RFCE, I believe I borrowed that part from you - the state religion requirement that is). Moreover, it's impossible to switch to non-state religion in SoI, but you might want to add some sanity check in RFCE.

    2. Err, these lines is what exposes it to Python.

    3. I answered that earlier actually: I didn't add the Attitude Extra, it's part of BTS and already has memory decay (EVENT_BAD_TO_US). I only renamed the negative text from "Past events have drawn our people apart" (something like that) to the current persecution text, as it wasn't used by anything.

    4-5. Yeah, thanks! (although considering the price of a persecutor, maybe I should update the comment instead...)

    P.S. Update your sig ;)
     
  10. AbsintheRed

    AbsintheRed Deity

    Joined:
    Jul 27, 2009
    Messages:
    8,288
    Location:
    Szeged, Hungary
    Hey edead!
    I think there is a small mistake in the CvCity.cpp, when is the city allowed to produce persecutors
    Code:
    if (!((GET_PLAYER(getOwnerINLINE()).getStateReligion() == NO_RELIGION) || (isHasReligion(GET_PLAYER(getOwnerINLINE()).getStateReligion()))))
    You want them to be buildable only if your civ has a state religion, and the state religion is spread to the actual city, right?
    Currently your code allows persecutors in cities without the state religion too
    (because no religion is always not true if the second part can be true)

    This is what I currently use in RFCE:
    Code:
    if ( !( (GET_PLAYER(getOwnerINLINE()).getStateReligion() != NO_RELIGION) && (isHasReligion( GET_PLAYER(getOwnerINLINE()).getStateReligion())) ) )
    EDIT: Tried it out in SoI, works correctly
    But then I'm not sure why is the first part of the code needed in your version
    I don't see the point in !(GET_PLAYER(getOwnerINLINE()).getStateReligion() == NO_RELIGION)
     
  11. AbsintheRed

    AbsintheRed Deity

    Joined:
    Jul 27, 2009
    Messages:
    8,288
    Location:
    Szeged, Hungary
    One more thing: I think you forgot to deal with holy cities in the doInquisitorCore_AI function
    So if a religion's holy city is the next city when looping through the city list, the AI won't move on
    Even if there are many "good" candidates for persecution after this city (in the cities order)


    Also, the AI will always choose a city based on tReligiousTolerance, so they will almost never move to the correct cities

    For example even if a civ has a hated religion all over it's cities, Persecutors will go to the first city which has Zoroastrianism or Judaism, and will purge there
    The purge is based on the tPersecutionOrder though, so it will purge the hated religion first (correctly).
    But the problem is that it won't move on to the next city before Zoroastrianism or Judaism is removed from this city, so these religions basically have priority over the hated religions
    If a catholic hater civ has 2 jewish and 10 catholic cities, it won't purge at least 8 of those catholic cities before the 2 jewish cities are purged

    Probably it would be better if the PersecutionOrder was also used when choosing the target city
     
  12. embryodead

    embryodead Caliph

    Joined:
    Jan 1, 2003
    Messages:
    5,179
    Location:
    basement
    Well, like you said, it works correctly, and that's what counts ;) There are several ways to check for the same thing and it's hard to tell why I did it this way... I probably added the first statement because checking for state religion in a city always returns true if state religion is NO_RELIGION.
     
  13. embryodead

    embryodead Caliph

    Joined:
    Jan 1, 2003
    Messages:
    5,179
    Location:
    basement
    Yeah, thanks. Fixed.

    Yeah, just change range(con.iNumReligions) to con.tPersecutionOrder[iOwner]
     
  14. AbsintheRed

    AbsintheRed Deity

    Joined:
    Jul 27, 2009
    Messages:
    8,288
    Location:
    Szeged, Hungary
    Really? I can't find what did you change regarding this
    What was your fix for it?

    Yeah, I had done the same initially (but you meant con.tPersecutionOrder[iStateReligion] I guess)
    Btw, I switched the pCity and iReligion loops. So it won't check each city in the specific order and look for target religion(s) in it (until the city only has state religion), but look for the most hated religion, and loop through the cities to check if any of them has it.

    A couple thoughts: pCity in apCityList puts your cities in an order based on foundation date? Or based on coordinates on the map?
    Anyway, I was thinking of randomizing the city order a little bit.
    Maybe somehow base it on religion number as well.

    I was also thinking about adding a check, that the AI skips religions in a city not only when it's a holy city of that religion, but also when there is a wonder tied to that religion
    I don't see too many cases where the AI should remove a wonder (in RFCE it's good for the player for a couple UHVs, but otherwise wonders worth to keep)
     
  15. embryodead

    embryodead Caliph

    Joined:
    Jan 1, 2003
    Messages:
    5,179
    Location:
    basement
    Err, right, I thought I did, but I fixed something else. I did fix it now, though.

    Oops yeah.

    Based on C++ array order, which should correspond to foundation dates and/or acquisition dates (i.e. with conquered cities appended at the end, but I'm not 100% sure).

    The result has to be the same every turn so it can't be random, but if you use modulo religion index, I guess that should work fine.

    Well, I don't think wonders should be removed at all - religious "wonders" were at worst converted to the new religion, but still remained, like Hagia Sophia.
     
  16. AbsintheRed

    AbsintheRed Deity

    Joined:
    Jul 27, 2009
    Messages:
    8,288
    Location:
    Szeged, Hungary
    Maybe it would be better if you also switched the two loops
    Cycling primarly based on the religion hate order makes more sense IMO

    Yeah, it can't be totally random of course. Will see if I implement something like this in the end. Probably not that important

    It makes sense to enable it for human players in RFCE, for a couple UHVs
    I did make a little addition to the persecution function though:
    Code:
    		# count the number of religious buildings and wonders (for the chance)
    		if iReligion > -1:
    			lReligionBuilding = []
    			lReligionWonder = 0
    			for iBuilding in xrange(gc.getNumBuildingInfos()):
    				if city.getNumRealBuilding(iBuilding):
    					BuildingInfo = gc.getBuildingInfo(iBuilding)
    					if BuildingInfo.getPrereqReligion() == iReligion:
    						lReligionBuilding.append(iBuilding)
    						if isWorldWonderClass(BuildingInfo.getBuildingClassType()) or isNationalWonderClass(BuildingInfo.getBuildingClassType()):
    							lReligionWonder += 1
    		else:
    			return False	# when there is no available religion to purge
    
    		# base chance to work: about 50-90, based on faith:
    		## iChance = 60 + max(-10, min(30, pPlayer.getFaith()/3))
    		iChance = 55 + pPlayer.getFaith()/3
    		# lower chance for purging any religion from Jerusalem:
    		if (iPlotX == con.iJerusalem[0] and iPlotY == con.iJerusalem[1]):
    			iChance -= 25
    		# lower chance if the city has the chosen religion's buildings/wonders:
    		iChance -= (len(lReligionBuilding) * 8 + lReligionWonder * 17)		# the wonders have an extra chance reduction (in addition to the first reduction)
    
    		if gc.getGame().getSorenRandNum(100, "purge chance") < iChance:
    So religious buildings (and religious wonders to a much bigger amount) decrease the chance of a successful persecution
    But as I said, I have to add a check to the AI here (to skip cities with religious wonders) in the doInquisitorCore_AI
    Otherwise it won't get to the next city in the loop, only after the persecution finally succeeds and the wonder is removed.
    If you want to have it impossible in SoI to remove wonders, then it's unnecessary for you of course
     
  17. embryodead

    embryodead Caliph

    Joined:
    Jan 1, 2003
    Messages:
    5,179
    Location:
    basement
    there was a bug in my code in case you used that (isHolyCity -> isHolyCityByType)
     
  18. AbsintheRed

    AbsintheRed Deity

    Joined:
    Jul 27, 2009
    Messages:
    8,288
    Location:
    Szeged, Hungary
    Thanks, but I used a different code here
     
  19. AbsintheRed

    AbsintheRed Deity

    Joined:
    Jul 27, 2009
    Messages:
    8,288
    Location:
    Szeged, Hungary
    I have some assert failures with the mainscreen mercenary manager button
    So I tried to add a new controltype for it, like you did in SoI (cvmaininterface.py, line 300)
    I added the corresponding lines into cvgameinterface.cpp, cvenums.h and cvenumsinterface.cpp
    But I still get a python exception on game start: "AttributeError: 'NoneType' object has no attribute 'getActionInfoIndex'"
    Do you have any ideas what did I miss?
     
  20. srpt

    srpt Deist

    Joined:
    May 10, 2010
    Messages:
    2,038
    Location:
    Toronto
    I'm curious to know how much of K-mod is in this version. everything you thought was worth it?
     

Share This Page