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

Modifying faction starting distances.

Discussion in 'Civ4 - SDK/Python' started by Lib.Spi't, May 24, 2014.

  1. Lib.Spi't

    Lib.Spi't Overlord of the Wasteland

    Joined:
    Feb 12, 2009
    Messages:
    3,707
    Location:
    UK
    So first of all I am wondering if this bit of code is the right bit of code to fiddle with, and second what should I fiddle with.

    I can sort understand it a little bit but then brain starts dripping from my ear...

    Spoiler :
    Code:
    void CvGame::normalizeStartingPlotLocations()
    {
    	CvPlot* apNewStartPlots[MAX_CIV_PLAYERS];
    	int* aaiDistances[MAX_CIV_PLAYERS];
    	int aiStartingLocs[MAX_CIV_PLAYERS];
    	int iI, iJ;
    
    	// Precalculate distances between all starting positions:
    	for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
    	{
    		if (GET_PLAYER((PlayerTypes)iI).isAlive())
    		{
    			gDLL->callUpdater();	// allow window to update during launch
    			aaiDistances[iI] = new int[iI];
    			for (iJ = 0; iJ < iI; iJ++)
    			{
    				aaiDistances[iI][iJ] = 0;
    			}
    			CvPlot *pPlotI = GET_PLAYER((PlayerTypes)iI).getStartingPlot();	
    			if (pPlotI != NULL)
    			{
    				for (iJ = 0; iJ < iI; iJ++)
    				{
    					if (GET_PLAYER((PlayerTypes)iJ).isAlive())
    					{
    						CvPlot *pPlotJ = GET_PLAYER((PlayerTypes)iJ).getStartingPlot();
    						if (pPlotJ != NULL)
    						{
    							int iDist = GC.getMapINLINE().calculatePathDistance(pPlotI, pPlotJ);
    							if (iDist == -1)
    							{
    								// 5x penalty for not being on the same area, or having no passable route
    								iDist = 5*plotDistance(pPlotI->getX_INLINE(), pPlotI->getY_INLINE(), pPlotJ->getX_INLINE(), pPlotJ->getY_INLINE());
    							}
    							aaiDistances[iI][iJ] = iDist;
    						}
    					}
    				}
    			}
    		}
    		else
    		{
    			aaiDistances[iI] = NULL;
    		}
    	}
    
    	for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
    	{
    		aiStartingLocs[iI] = iI; // each player starting in own location
    	}
    
    	int iBestScore = getTeamClosenessScore(aaiDistances, aiStartingLocs);
    	bool bFoundSwap = true;
    	while (bFoundSwap)
    	{
    		bFoundSwap = false;
    		for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
    		{
    			if (GET_PLAYER((PlayerTypes)iI).isAlive())
    			{
    				for (iJ = 0; iJ < iI; iJ++)
    				{
    					if (GET_PLAYER((PlayerTypes)iJ).isAlive())
    					{
    						int iTemp = aiStartingLocs[iI];
    						aiStartingLocs[iI] = aiStartingLocs[iJ];
    						aiStartingLocs[iJ] = iTemp;
    						int iScore = getTeamClosenessScore(aaiDistances, aiStartingLocs);
    						if (iScore < iBestScore)
    						{
    							iBestScore = iScore;
    							bFoundSwap = true;
    						}
    						else
    						{
    							// Swap them back:
    							iTemp = aiStartingLocs[iI];
    							aiStartingLocs[iI] = aiStartingLocs[iJ];
    							aiStartingLocs[iJ] = iTemp;
    						}
    					}
    				}
    			}
    		}
    	} 
    
    	for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
    	{
    		apNewStartPlots[iI] = NULL;
    	} 
    
    	for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
    	{
    		if (GET_PLAYER((PlayerTypes)iI).isAlive())
    		{
    			if (aiStartingLocs[iI] != iI)
    			{
    				apNewStartPlots[iI] = GET_PLAYER((PlayerTypes)aiStartingLocs[iI]).getStartingPlot();
    			}
    		}
    	}
    
    	for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
    	{
    		if (GET_PLAYER((PlayerTypes)iI).isAlive())
    		{
    			if (apNewStartPlots[iI] != NULL)
    			{
    				GET_PLAYER((PlayerTypes)iI).setStartingPlot(apNewStartPlots[iI], false);
    			}
    		}
    	}
    
    	for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
    	{
    		SAFE_DELETE_ARRAY(aaiDistances[iI]);
    	}
    }


    So the final goal here is to change it so that each faction starts about 7-8 tiles from at least 2 other factions (what i really want is for all the factions to start 'clustered together' so that very quickly borders are pressing against borders and everyone is looking for a way out to expand, and also generally causing mayhem in each others lands.
     
  2. Sto

    Sto Should i code today ...

    Joined:
    Dec 15, 2005
    Messages:
    1,144
    Location:
    Marseille (France)
    This code is to make team start together. Whatever you change in default starting location, most of map scripts override it. I'd advise you to make some custom map scripts with your starting location code.
     
  3. evertebrate

    evertebrate Chieftain

    Joined:
    Mar 30, 2009
    Messages:
    76
    Location:
    germany
    what you are looking for is in CvPlayerAI::AI_foundValue

    its this part mostly:

    Spoiler :
    Code:
    if (bStartingLoc)
    	{
    		if (pPlot->getMinOriginalStartDist() == -1)
    		{
    			iValue += (GC.getMapINLINE().maxStepDistance() * 100);
    		}
    		else
    		{
    			iValue *= (1 + 4 * pPlot->getMinOriginalStartDist());
    			iValue /= (1 + 2 * GC.getMapINLINE().maxStepDistance());
    		}
    		
    		//nice hacky way to avoid this messing with normalizer, use elsewhere?
    		if (!pPlot->isStartingPlot())
    		{
    			int iMinDistanceFactor = MAX_INT;
    			int iMinRange = startingPlotRange();
    			
    			iValue *= 100;
    			for (int iJ = 0; iJ < MAX_CIV_PLAYERS; iJ++)
    			{
    				if (GET_PLAYER((PlayerTypes)iJ).isAlive())
    				{
    					if (iJ != getID())
    					{
    						int iClosenessFactor = GET_PLAYER((PlayerTypes)iJ).startingPlotDistanceFactor(pPlot, getID(), iMinRange);
    						iMinDistanceFactor = std::min(iClosenessFactor, iMinDistanceFactor);
    						
    						if (iClosenessFactor < 1000)
    						{
    							iValue *= 2000 + iClosenessFactor;
    							iValue /= 3000;
    						}
    					}
    				}
    			}
    			
    			if (iMinDistanceFactor > 1000)
    			{
    				//give a maximum boost of 25% for somewhat distant locations, don't go overboard.
    				iMinDistanceFactor = std::min(1500, iMinDistanceFactor);
    				iValue *= (1000 + iMinDistanceFactor);				
    				iValue /= 2000;
    			}
    			else if (iMinDistanceFactor < 1000)
    			{
    				//this is too close so penalize again.
    				iValue *= iMinDistanceFactor;
    				iValue /= 1000;
    				iValue *= iMinDistanceFactor;
    				iValue /= 1000;
    			}
    			
    			iValue /= 10;
    			
                if (pPlot->getBonusType() != NO_BONUS)
                {
                    iValue /= 2;
                }
    		}
    	}


    when its normalizing, the starting plots are already chosen and just get shuffled around
     

Share This Page