RevolutionDCM for BTS

glider when you release the next RevDCM version, please remember to include the debug makefile.
 
Jdog did a lot of hard work to merge in BTS 3.19 over the weekend!

The prototype build is on sourceforge and we are applying ointments to it and singing opera at it to see if it will explode in rage and show us any weaknesses. So far so good....

I will endeavor to release on civfanatics with enough time before next weekend, for all to play with and redress as we see fit. Warning: just don't sing opera at it.

Cheers.
 
Hi JujuLautre
It will be fixed no question, it is more the question whether I can find the fundamental reason as to why it happened in the first place, so that the creature bug does not re-emerge. This is like cockroaches in my food cupboard. I can limit them to some degree with cockroach poisons, or I can find the tiny crevise through which they creep in and close the crack. BTS comprises a significant slab of the food of my mind, and so I do not want digital cockroaches crawling over it. :)

Cheers.
 
It's pretty easy to just pop open the python file and remove some units, and lower the values in Revolutions.ini.
While this is trivial task for us modders, it's not so easy task for players who use our mods. I was trying to say that the mod's default settings might need slight tweaking on how many units will be spawned when minor civs turn into full civs (or rebels).
 
There are actual XML values in the CivicInfos file that revolutions adds. I plan on adding this info into gametextmanager.cpp. Should be easy enough to do, in fact I bet it will be easier then using a python hack to display the inforamtion (I also plan an getting gametextmanager to recognize and display max collateral damage and effected units in the civilopedia). The thing is though, this doesn't really achieve my goal. My main issue is that revolution effects aren't properly displayed in the city screen, in the RevIdx bar. Everything that is adding to or decreasing the RevIdx in a city should be displayed, the player should have that information available to him. Best way to get that done would be to have jdog incorporate this into revolutions. So far though, I've been the only one asking for it. So to increase the priority of this, more people need to post/complain/discuss.

I second that request. The collateral damage thing and more information for Revolution displayed in the city screen!
 
At this late stage before release of 2.5, if anyone wants specific things built into RevDCM, you'll have to submit actual code/and or files so I can check them out. At this stage, it's really about getting the basics right under 3.19 and fixing well known bugs and lots of automated testing.

There will be more releases of RevDCM down the track to pick up some of the other stuff you want and I try to take notes of what people want for later inclusion. Jdog is working through Phungus's distance effects sooner rather than later because Phungus supplied actual code at one point. Whether it makes it into this release or next, dunno.

This is what will be in 2.5:
1) BTS 3.19
2) Apollo fixed
3) Bomb shelters fixed
4) Latest better bts ai
5) Range bombard collateral damage double check
6) Inquisitor AI build limit double check
7) Random events already fixed as of 2.1

Cheers.
 
Thanks for keeping us updated. Also please remember to upload a debug makefile when you release the 3.19 compatible RevDCM source.

As far as code requests, these would be great to add:

The first is City Distance (which you mention jdog is taking a look at), found in the revolution.py file (there was a minor bug in the first one I uploaded, had it check isWrapX() when it should have called isWrapY() though I'm sure jdog probably found that anyway)
Commented with # phungus -City Distance
Spoiler :
Code:
            # phungus -City Distance start
            # Distance to capital City Distance modified by communication techs and structures
            cityDistModifier = 0
            map = CyMap()
            deltaX = abs(pCity.getX() - capital.getX())
            if map.isWrapX():
                deltaX = min(deltaX, map.getGridWidth() - deltaX)
            deltaY = abs(pCity.getY() - capital.getY())
            if map.isWrapY():
                deltaY = min(deltaY, map.getGridWidth() - deltaY)
            cityDistRaw = ( deltaX**2 + deltaY**2 )**0.5
            cityDistMapModifier = ( map.getGridWidth()**2 + map.getGridHeight()**2 )**0.5
            cityDistCommBonus = 0
            pTeam = gc.getTeam(pPlayer.getTeam())
            bCanTradeOverCoast = False
            bCanTradeOverOcean = False
            iTerrainCoast = gc.getInfoTypeForString("TERRAIN_COAST")
            iTerrainOcean = gc.getInfoTypeForString("TERRAIN_OCEAN")
            for i in range(gc.getNumTechInfos()):
                tech = gc.getTechInfo(i)
                if tech.isTerrainTrade(iTerrainCoast):
                    if pTeam.isHasTech(i):
                        bCanTradeOverCoast = True
                if tech.isTerrainTrade(iTerrainOcean):
                    if pTeam.isHasTech(i):
                        bCanTradeOverOcean = True
            if bCanTradeOverOcean :
                cityDistCommBonus += 50
            iCityTradeRoutes = pCity.getTradeRoutes()
            if(iCityTradeRoutes > 1 ) :
                cityDistCommBonus += (iCityTradeRoutes - 1)*25
            iTradeRouteModifier = pCity.getTradeRouteModifier()
            cityDistCommBonus += iTradeRouteModifier
            bCityIsConnected = pCity.isConnectedTo(capital)
            if bCityIsConnected :
                bTechRouteModifier = False
                for i in range(gc.getNumTechInfos()):
                    for j in range(gc.getNumRouteInfos()):
                        tech = gc.getTechInfo(i)
                        if(gc.getRouteInfo(j).getTechMovementChange(i) != 0 and pTeam.isHasTech(i)):
                            bTechRouteModifier = True
                            break
                    if bTechRouteModifier:
                        break
                if bTechRouteModifier:
                    cityDistCommBonus += 100 - (gc.getRouteInfo(pCity.plot().getRouteType()).getFlatMovementCost() + gc.getRouteInfo(pCity.plot().getRouteType()).getTechMovementChange(i))*1.67
                else:
                    cityDistCommBonus += 100 - (gc.getRouteInfo(pCity.plot().getRouteType()).getFlatMovementCost())*1.67
                if( pCity.isCoastal(-1) ) :
                    if bCanTradeOverOcean :
                        cityDistCommBonus += 50
                    elif bCanTradeOverCoast :
                        cityDistCommBonus += 25
                iCityCulterModifier = pCity.getCommerceRateModifier(CommerceTypes.COMMERCE_CULTURE)
                iCityGoldModifier = pCity.getCommerceRateModifier(CommerceTypes.COMMERCE_GOLD)
                cityDistCommBonus += iCityCulterModifier
                cityDistCommBonus += iCityGoldModifier            
            iCityMaintenanceModifier = pCity.getMaintenanceModifier()
            cityDistCommBonus -= iCityMaintenanceModifier
            bCityisPower = pCity.isPower()
            if bCityisPower :
                cityDistCommBonus += 50
            iCityAirlift = pCity.getMaxAirlift()            
            cityDistCommBonus += 100*iCityAirlift
            if( pPlayer.hasTrait(gc.getInfoTypeForString("TRAIT_IMPERIALIST")) ):
                cityDistCommBonus += 50
            cityDistModifier = ( 307.0*cityDistRaw / cityDistMapModifier ) / ( 1.0 + ( cityDistCommBonus / 100.0 ) )
            cityDistModifier -= int(500 / cityDistMapModifier)

            distMod = 1.0 + RevUtils.getCivicsDistanceMod( iPlayer )
            distMod *= self.distToCapModifier
            if( pCity.isGovernmentCenter() ) :
                distMod *= 0.5

            locationRevIdx = 0

            if( civSizeRawVal > 2.0 ) :
                locationRevIdx += int(math.floor(2.0*cityDistModifier*distMod + .5))
                if( bIsRevWatch and cityDistModifier > 1.5 ) :
                    negList.append( (locationRevIdx, localText.getText("TXT_KEY_REV_WATCH_DISTANT",())) )
            elif( civSizeRawVal > 1.6 ) :
                locationRevIdx += int(math.floor(1.65*cityDistModifier*distMod + .5))
                if( bIsRevWatch and cityDistModifier > 1.6 ) :
                    negList.append( (locationRevIdx, localText.getText("TXT_KEY_REV_WATCH_DISTANT",())) )
            elif( civSizeRawVal > 1.4 ) :
                locationRevIdx += int(math.floor(1.45*cityDistModifier*distMod + .5))
                if( bIsRevWatch and cityDistModifier > 1.7 ) :
                    negList.append( (locationRevIdx, localText.getText("TXT_KEY_REV_WATCH_DISTANT",())) )
            elif( civSizeRawVal > 1.2 ) :
                locationRevIdx += int(math.floor(1.25*cityDistModifier*distMod + .5))
                if( bIsRevWatch and cityDistModifier > 1.8 ) :
                    negList.append( (locationRevIdx, localText.getText("TXT_KEY_REV_WATCH_DISTANT",())) )
            elif( civSizeRawVal > 1.0 ) :
                locationRevIdx += int(math.floor(cityDistModifier*distMod + .5))
                if( bIsRevWatch and cityDistModifier > 1.9 ) :
                    negList.append( (locationRevIdx, localText.getText("TXT_KEY_REV_WATCH_DISTANT",())) )
            elif( civSizeRawVal > .7 ) :
                locationRevIdx += int(math.floor(.75*cityDistModifier*distMod + .5))
                if( bIsRevWatch and cityDistModifier > 2.2 ) :
                    negList.append( (locationRevIdx, localText.getText("TXT_KEY_REV_WATCH_DISTANT",())) )
            else :
                locationRevIdx += int(math.floor(.5*cityDistModifier*distMod + .5))
                if( bIsRevWatch and cityDistModifier > 3.0 ) :
                    negList.append( (locationRevIdx, localText.getText("TXT_KEY_REV_WATCH_DISTANT",())) )

            locationRevIdx = int(math.floor( locationRevIdx + .5 ))
            localRevIdx += locationRevIdx
            revIdxHist['Location'] = [locationRevIdx] + revIdxHist['Location'][0:RevDefs.revIdxHistLen-1]
            # phungus -City Distance end

Second is in the same file (revolution.py), regarding a taxes Revolution code overhaul. Rather then basing the economic RevIdx penalty on the gold rate which has the effect of pigeonholing novel game strategies; this code bases the economic Rev penalty on government spending and waste. It takes the Total expenditures of the empire (city maintenance, unit supply, etc), and devides this by the total earned commerce types (gold, culture, espionage, science). This seriously works infinitely better then the current setup, please take a look at it.
Commented with #phungus -taxes
Spoiler :
Code:
        #phungus -taxes start
        totalUnitCost = pPlayer.calculateUnitCost()
        totalUnitSupply = pPlayer.calculateUnitSupply()
        totalMaintenance = pPlayer.getTotalMaintenance()
        totalCivicUpkeep = pPlayer.getCivicUpkeep([], False)
        totalPreInflatedCosts = pPlayer.calculatePreInflatedCosts()
        totalInflatedCosts = pPlayer.calculateInflatedCosts()
        iInflation = totalInflatedCosts - totalPreInflatedCosts
        goldFromCivs = pPlayer.getGoldPerTurn()
        goldRate = pPlayer.getCommerceRate(CommerceTypes.COMMERCE_GOLD)
        researchRate = pPlayer.calculateResearchRate(-1)
        cultureRate = pPlayer.getCommerceRate(CommerceTypes.COMMERCE_CULTURE)
        espionageRate = pPlayer.getCommerceRate(CommerceTypes.COMMERCE_ESPIONAGE)
        igoldRate = pPlayer.calculateGoldRate()
        iGold = pPlayer.getGold()

        iGDP = goldFromCivs + goldRate + researchRate + cultureRate + espionageRate + pPlayer.calculateTotalImports(YieldTypes.YIELD_COMMERCE)
        #CyInterface().addImmediateMessage("iGDP = %d" % (iGDP), "")
        iwaste = totalUnitCost + totalUnitSupply + totalMaintenance + totalCivicUpkeep + iInflation + pPlayer.calculateTotalExports(YieldTypes.YIELD_COMMERCE)
        #CyInterface().addImmediateMessage("iwaste = %d" % (iwaste), "")
        taxBurden = (100*iwaste) / iGDP - 10
        #CyInterface().addImmediateMessage("taxBurden = %d" % (taxBurden), "")
        if( pPlayer.hasTrait(gc.getInfoTypeForString("TRAIT_ORGANIZED")) ):
            taxBurden /= 1.5
        sciPerc = pPlayer.getCommercePercent( CommerceTypes.COMMERCE_RESEARCH )
        cultPerc = pPlayer.getCommercePercent( CommerceTypes.COMMERCE_CULTURE )
        if( pPlayer.hasTrait(gc.getInfoTypeForString("TRAIT_CREATIVE")) ):
            cultPerc *= 1.5
        taxBurden -= cultPerc

        cultIdx = 0
        if( cultPerc > 0 ) :
            cultIdx += int(pow(cultPerc, 0.5))
            if( bIsRevWatch ) : posList.append( (cultIdx, localText.getText("TXT_KEY_REV_WATCH_CULTURE_SPENDING",())) )

        if( taxBurden > 50 ) :
        # At peace, stronger penalties for taxes and financial trouble
        # Taxes
            taxesIdx -= (taxBurden - 15)/2
            if( bIsRevWatch ) :
                if(taxesIdx < 0):
                    abs(taxesIdx)
                    negList.append( (taxesIdx, localText.getText("TXT_KEY_REV_WATCH_TAXES",())) )
                else :
                    taxesIdx = 0 - taxesIdx
                    posList.append( (taxesIdx, localText.getText("TXT_KEY_REV_WATCH_TAXES",())) )
            taxesIdx = 0 - (taxBurden - 15)/2
            # Finances
            finIdx += (taxBurden - 12)/1.5
            if( igoldRate > 2 + 5*pPlayer.getCurrentEra() ) :
                finIdx /=2
            if( iGold > 100 + 100*pPlayer.getCurrentEra() ) :
                finIdx /=2
            elif( iGold < ( 25 + 10*pPlayer.getCurrentEra() ) and igoldRate < 0 ) :
                finIdx *=2
            if(finIdx > 0):
                if( bIsRevWatch ) :
                    negList.append( (finIdx, localText.getText("TXT_KEY_REV_WATCH_FINANCIAL",())) )
            else:
                if( bIsRevWatch ) :
                    posList.append( (finIdx, localText.getText("TXT_KEY_REV_WATCH_FINANCIAL",())) )
            finIdx2 -= finIdx
            revIdxHistEvents += finIdx

        elif( taxBurden > 33 and taxBurden <= 50 ) :
            # Taxes
            taxesIdx -= (taxBurden - 15)/3
            if( bIsRevWatch ) :
                if(taxesIdx < 0):
                    abs(taxesIdx)
                    negList.append( (taxesIdx, localText.getText("TXT_KEY_REV_WATCH_TAXES",())) )
                else :
                    taxesIdx = 0 - taxesIdx
                    posList.append( (taxesIdx, localText.getText("TXT_KEY_REV_WATCH_TAXES",())) )
            taxesIdx = 0 - (taxBurden - 15)/3
            # Finances
            finIdx += (taxBurden - 12)/2
            if( igoldRate > 2 + 5*pPlayer.getCurrentEra() ) :
                finIdx /=2
            if( iGold > 100 + 100*pPlayer.getCurrentEra() ) :
                finIdx /=2
            elif( iGold < ( 25 + 10*pPlayer.getCurrentEra() ) and igoldRate < 0 ) :
                finIdx *=2
            if(finIdx > 0):
                if( bIsRevWatch ) :
                    negList.append( (finIdx, localText.getText("TXT_KEY_REV_WATCH_FINANCIAL",())) )
            else:
                if( bIsRevWatch ) :
                    posList.append( (finIdx, localText.getText("TXT_KEY_REV_WATCH_FINANCIAL",())) )
            finIdx2 -= finIdx
            revIdxHistEvents += finIdx

        elif( taxBurden > 15 and taxBurden <= 33 ) :
            # Taxes
            taxesIdx -= (taxBurden - 15)/4
            if( bIsRevWatch ) :
                if(taxesIdx < 0):
                    abs(taxesIdx)
                    negList.append( (taxesIdx, localText.getText("TXT_KEY_REV_WATCH_TAXES",())) )
                else :
                    taxesIdx = 0 - taxesIdx
                    posList.append( (taxesIdx, localText.getText("TXT_KEY_REV_WATCH_TAXES",())) )
            taxesIdx = 0 - (taxBurden - 15)/4
            # Finances
            finIdx += (taxBurden - 12)/3
            if( igoldRate > 2 + 5*pPlayer.getCurrentEra() ) :
                finIdx /=2
            if( iGold > 100 + 100*pPlayer.getCurrentEra() ) :
                finIdx /=2
            elif( iGold < ( 25 + 10*pPlayer.getCurrentEra() ) and igoldRate < 0 ) :
                finIdx *=2
            if(finIdx > 0):
                if( bIsRevWatch ) :
                    negList.append( (finIdx, localText.getText("TXT_KEY_REV_WATCH_FINANCIAL",())) )
            else:
                if( bIsRevWatch ) :
                    posList.append( (finIdx, localText.getText("TXT_KEY_REV_WATCH_FINANCIAL",())) )
            finIdx2 -= finIdx
            revIdxHistEvents += finIdx

        elif( taxBurden < 0) :
            taxesIdx += min([( abs(taxBurden / 2) + cultPerc / 5 )/3,10])
            if( bIsRevWatch ) : posList.append( (taxesIdx, localText.getText("TXT_KEY_REV_WATCH_LOW_TAXES",())) )

        #CyInterface().addImmediateMessage("taxesIdx = %d" % (taxesIdx), "")
        #CyInterface().addImmediateMessage("finIdx = %d" % (finIdx), "")
        #CyInterface().addImmediateMessage("finIdx2 = %d" % (finIdx2), "")
        #phungus -taxes end
The commented out CyInterface() calls are so that the ammount was printed for me in the events window. This was essential in balancing the numbers, but is no longer needed (which is why it's commented out


Finaly is the Game Option Barbarian World. This is taken from the assimilation mod by Kael. Adds in a game start option where the game generates an equal ammount of preexisting barbarian cities on the map as starting players when the map is generated. It's optional, and is a cool option. Have had no complaints from it, and alot of people really seem to enjoy this option.
Found in CvEnums.h, CvGame.cpp, CvGame.h and CyEnumsInterface.cpp
Also obviously need to add in the game option in the XML, but this is trivial.
Commented with //Ass
Spoiler :
In CvEnums.h
Code:
//Ass: Added by Kael 07/02/2008
	GAMEOPTION_CHALLENGE_BARBARIAN_WORLD,
//Ass: End Add
In CvGame.h
Code:
//Ass: Added by Kael 10/13/2008
    void foundBarbarianCity();
//FfH: End Add
In CvGame.cpp
Code:
//Ass: Added by Kael 10/13/2008void CvGame::foundBarbarianCity()
void CvGame::foundBarbarianCity()
{
    bool bValid = true;
	int iBestValue = 0;
	int iDist = 0;
	int iValue = 0;
	CvPlot* pPlotI = NULL;
	CvPlot* pBestPlot = NULL;
	CvPlot* pLoopPlot = NULL;
	for (int iPlot = 0; iPlot < GC.getMapINLINE().numPlotsINLINE(); iPlot++)
	{
		pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iPlot);
		bValid = true;
		iValue = 0;
		if (pLoopPlot->isWater())
		{
		    bValid = false;
		}
		else if (pLoopPlot->isImpassable())
		{
		    bValid = false;
		}
		else if (pLoopPlot->isCity())
		{
		    bValid = false;
		}
		else if (pLoopPlot->getImprovementType() != NO_IMPROVEMENT)
		{
		    bValid = false;
		}
		else for (int iI = 0; iI < MAX_CIV_PLAYERS; iI++)
        {
            if (GET_PLAYER((PlayerTypes)iI).isAlive())
            {
                pPlotI = GET_PLAYER((PlayerTypes)iI).getStartingPlot();
                if (pPlotI != NULL)
                {
                    iDist = GC.getMapINLINE().calculatePathDistance(pPlotI, pLoopPlot);
                    if (iDist == -1)
                    {
                        iValue += 100;
                    }
                    else if (iDist < 5)
                    {
                        bValid = false;
                    }
                    else
                    {
                        iValue += iDist * 10;
                    }
                }
            }
		}
        if (bValid)
        {
            iValue += GET_PLAYER(BARBARIAN_PLAYER).AI_foundValue(pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE(), GC.getDefineINT("MIN_BARBARIAN_CITY_STARTING_DISTANCE"));
            iValue += pLoopPlot->area()->getNumOwnedTiles() + 10;
            iValue += getSorenRandNum(250, "Barb City Found");
			if (iValue > iBestValue)
			{
				iBestValue = iValue;
				pBestPlot = pLoopPlot;
			}
		}
	}
	if (pBestPlot != NULL)
	{
		GET_PLAYER(BARBARIAN_PLAYER).found(pBestPlot->getX_INLINE(), pBestPlot->getY_INLINE());
	}
}
//Ass: End Add
In CyEnumsInterface.cpp
Code:
//Ass: Added by Kael 07/02/2008
		.value("GAMEOPTION_CHALLENGE_BARBARIAN_WORLD", GAMEOPTION_CHALLENGE_BARBARIAN_WORLD)
//Ass: End

I have more SDK stuff I'd love for you to add, as it would make my life easier, but not sure if others would find it useful. It's some pretty simple code that adds in Leonardo's Workshop functionality to the SDK, but done in a way so it's softcoded, Ie it allows the modder to define the values in the XML in buildinginfos, rather then hardcoding any specific attribute into the SDK. Also have another XML tag which allows a leadership trait to grant culture from non state religion. The code of both of these functions is clean and bug free. I'll see if there is any interest in having these tags before uploading them though.
 
What about adding these little mods:

1.) http://forums.civfanatics.com/downloads.php?do=file&id=7867 (zRoutes)
3.) http://forums.civfanatics.com/showthread.php?t=239144 (AirForcesMod) --> not the units, only the sdk, means the new features *EDIT*: recon mission can be intercepted (50% evasion probability) --> this option I miss very much in RevDCM
I like #3. I wol't use #1, but if it's stable, I don't see the harm in it.

2.) http://forums.civfanatics.com/showthread.php?t=277940 (Random Invisibility Mod)

-Please don't add this :trouble:
 
Definately agree with phungus:
#3 is the best.
Bunch of awesome stuff like this:

ability to sink ships for unitclass with iAirCombatLimit >= 70
 
Personally I want to see these things in mods based on RevDCM I'm playing

http://forums.civfanatics.com/showthread.php?t=311211 (Mountain)
http://forums.civfanatics.com/showthread.php?t=290694 (Culturally linked start)
http://forums.civfanatics.com/showthread.php?t=302649 (Global Warming)

But I know these things are not that suitable for RevDCM itself. :rolleyes:
(I think RevDCM as a "base" of mod and these things are out of its boundary...)

I would also love to see the mods Culturally Linked Starts and Global Warming here!
 
I would have been better just shutting up on requests because I am maxed out in the function CvGlider::finalTesting(timeLimited, maxedOut = true); :)

Had a chat with Jdog and there's some more important stuff to check through on the AI side of things. Planned release is Wednesday midnight PST. This will give everyone time to merge all of it in for the weekend it is hoped. The basics will be there as per previous list plus sources/makefile and addon's.

EDIT: However addon requests have been noted.
Cheers.
 
As far as code requests, these would be great to add:

The first is City Distance ...

Thanks for pointing that out!

Second is in the same file (revolution.py), regarding a taxes Revolution code overhaul.

That's a very good point ... your method fits much better with the intention of the economic penalty. The prior model always bothered me a little, hence the tweaks for when you had lots of gold in the bank.

Finaly is the Game Option Barbarian World.

Sounds quite interesting and certain fits the mod well. Won't make it in to 2.5 because of timing, but definitely will be added for the next version.

Thanks for the post, some good ideas.
 
Does the DCM Opportunity Fire component work for archery units as well? I'd love to see something like keldath's (+rep to keldath, BTW) Defensive Strike from FfH2 (percentage chance to get a free strike at attacking units) implemented for archery/gun units in RevDCM.

I'm so excited for the new update, despite the amount of work it will no doubt take to refound HephMod on the RevDCM base!
 
Back
Top Bottom