Barbarians

Shoobs

Prince
Joined
Mar 31, 2010
Messages
498
Everyone knows that barbarians tend to drop like flies as the game goes on. Has anyone figured out how to make barbarians constantly spawn and be a real threat to both AIs and players alike?
 
This is configured in two places:

1 - CvEraInfos - bNoBarbUnits tag turns this on and off barbarians completely
2 - CvHandicapInfo - iUnownedTilesPerBarbarianUnit. This is used as a divisor for the number of unowned tiles in each area to determine how many barb units there should be. The number of existing barb units is subtracted to get how many should be created. This is then divided by 4 and 1 added. This makes the formula for the number of barb units to create in each area:

( ( (<area #tiles> / <HandicapInfo iUnownedTilesPerBarbarianUnit>) - <area existing # barbs> ) / 4) + 1

This is calculated every turn for each area
 
Yeah.... thats the entire issue. As the game goes on, barbarians spawn less because more tiles are owned. I want this to scale up as eras go on.
 
You could reduce the iUnownedTilesPerBarbarianUnit divisor that I mentioned in my previous reply, but as the game goes on there are less unowned tiles so the barbarians spawn less. Just spotted a typo in the formula where the first part should be <area # unowned tiles> not the total number of tiles (hence the name of the divisor)

If you want to control this yourself you will need to either modify the CvGame::createBarbarianUnits() method in the dll or write some Python that creates the units for you.
 
In my mod, the barbarian activity gradually increases until 60% of a continent is settled. Depending on the map size and iUnownedTilesPerBarbarianUnit, barbarians may remain a threat into the Medieval era this way. Civ places no barbarian units in Renaissance and beyond (this can be changed in the EraInfos XML file).

I don't have a separate mod component containing only the changes to barbarian spawning. For whatever it's worth, here's the modified C++ code. It only affects Raging Barbarians. The SPAWNING-PEAK parameter is set to 60 via XML.
Spoiler :
Code:
/* Based on code cut-and-pasted from createBarbarianUnits,
   but extensively modified. */
int CvGame::numBarbariansToSpawn(int tilesPerUnit, int nTiles,
    int nUnowned, int nUnitsPresent, int nBarbarianCities) {

  double divisor = tilesPerUnit; // Floating point to curb rounding errors
  if(isOption(GAMEOPTION_RAGING_BARBARIANS)) {
    int nOwned = nTiles - nUnowned;
    int peakPercent = std::max(0, std::min(100,
        GC.getDefineINT("ADVRI_RAGE-SPAWNING-PEAK_PERCENT")));
    if(peakPercent > 0 && nOwned > 0) { /* i.e. full "Rage" immediately
                                           if none owned */
      double peakQuotient = peakPercent / 100.0;
      /* When barbarians first appear, at most quintuple the divisor, i.e.
         use at least one fifth of the peak spawn rate. This lower bound
         for barbarian activity increases over time to make sure that e.g. an
         isolated civ that doesn't expand comes under pressure eventually. */
      divisor *= std::min<double>(
           (5.0 * turnsElapsedForBarbarianCreation()) / getElapsedGameTurns(),
           std::max(1.0, (nTiles * peakQuotient) / nOwned));
    }
    // Double spawn rate for Rage (no change here)
    divisor = std::max(1.0, (divisor / 2));
  }
  int r = 0;
  if (divisor > 0) {
    int initialDefenders = GC.getHandicapInfo(getHandicapType()).
        getBarbarianInitialDefenders();
    r = (int)(((nUnowned / divisor) - nUnitsPresent)
        + nBarbarianCities * std::max(0, initialDefenders - 1));
  }
  if(r > 0)
    r = (r / 4) + 1;
  return std::max(r, 0);
}

// Cut-and-pasted from createBarbarianUnits
int CvGame::turnsElapsedForBarbarianCreation() {

  return ((GC.getHandicapInfo(getHandicapType()).
      getBarbarianCreationTurnsElapsed() *
      GC.getGameSpeedInfo(getGameSpeedType()).
      getBarbPercent()) / 100);
}
 
Top Bottom