Building/Unit prereq obsoletion/replacement review

raxo2222

Time Traveller
Joined
Jun 10, 2011
Messages
9,733
Location
Poland
Sometimes building or unit might suddenly become unavailable, even if it wasn't obsoleted by tech.
This happens, if its requirements are obsoleted or replaced before building/unit itself obsoletes.
Or when suddenly you lose access to resources.

This issue is easily visible with Shipwright: it obsoletes with Coast Guard, but its building prereq - Carpenter's Workshop obsoletes at Manufacturing.

Effectively Shipwright obsoletes at Manufacturing.
In this case either Shipwright can be changed to obsolete at Manufacturing or Carpenter Workshop could obsolete at Coast Guard.
Or something else....
Spoiler :

Civ4BeyondSword 2018-06-28 17-58-48-50.jpg
 
Last edited:
I went and wrote a python script that automatically solve the related problem of identifying redudant technology prerequisits. With my measurement there are 194 technologies that has a total of 221 redudant prerequisits. Here redudant prerequisits are prerequisits that you would have if you have researched the rest of the prerequisits.

This script can in principle be extended to deal with the early obsoletion problem, but we are going to need a precise and thorough list of conditions we need to look for. This is because the script can answer the question of whether one technology needs to come before another, even though they may be several eras appart. A large part of programming the obsoletion problem is answering whether the time that one requirement for a building obsoletes before the tech where the building should have its effective end. The othter large part is identifying what those techs that needs to be compared are.

First is the actual python script file. Note that I just placed it in the .../Technologies folder, but the script can easily be adapted to run from somewhere else and load multiple files, as one only needs to describe the new load paths, the code can already handle it.
Spoiler techSearcher.py :

Code:
import xml.etree.ElementTree as ET
import re
import heapq



defaultData = ['CIV4TechInfos.xml']

class TechNode:

  def find(self,text):
    return self.ET.find('t:' + text,self.ns)
  def loadPreq(self):
    self.fullPreq = []
    self.partialPreq = []
    ands = self.find('AndPreReqs')
    if ands is not None:
      self.fullPreq = [preq.text for preq in ands]
    ors = self.find('OrPreReqs')
    if ors is not None:
      if len(ors) == 1:
        self.fullPreq.append(ors[0].text)
      else:
        self.partialPreq = [preq.text for preq in ors]

  def __init__(self, node):
    self.ET = node
    self.ns = {'t': re.search('\{(.*)\}\s*TechInfo',node.tag).group(1)}
    self.name = self.find('Type').text
    self.fullPreqOf = []
    self.partialPreqOf = []
    self.loadPreq()

    
 
def loadData(files, prefix = ''):
  trees = []
  for f in files:
    trees.append(ET.parse(f))
  return trees

def generateTechList(trees):
  techList = []
  for tree in trees:
    techList.extend([TechNode(tech) for tech in tree.getroot()[0]])
  return techList

def generateTechLookup(techList):
  return {techList[i].name : i for i in range(len(techList))}

def applyReverseConnections(tList, tDict):
  for tech in tList:
    for preq in tech.fullPreq:
      if preq in tDict:
        tList[tDict[preq]].fullPreqOf.append(tech.name)
    for preq in tech.partialPreq:
      if preq in tDict:
        tList[tDict[preq]].partialPreqOf.append(tech.name)

def updatePreqsOf(node, isFull, nodeDict, targets):
  updates = node.node.fullPreqOf if isFull else node.node.partialPreqOf
  for update in updates:
    node = nodeDict[update]
    if isFull:
      node.hasFullPreqs += 1
    else:
      node.hasPartialPreqs += 1
    if not node.represented:
      node.represented = True
      heapq.heappush(targets,node)

def nextNode(targets):
  while targets and targets[0].linksLeft() == 0:
    yield heapq.heappop(targets)

def toposort(tList, tDict):
  class TopoNode:
    def __init__(self, node):
      self.node = node
      self.represented = False
      self.hasFullPreqs = 0
      self.hasPartialPreqs = 0
    def fullPreqsLeft(self):
      return max(len(self.node.fullPreq) - self.hasFullPreqs,0)
    def partialPreqsLeft(self):
      preqs = len(self.node.partialPreq)
      return 0 if self.hasPartialPreqs else preqs
    def linksLeft(self):
      return self.fullPreqsLeft() + max(len(self.node.partialPreq) - self.hasPartialPreqs,0)#+ self.partialPreqsLeft()
    def getCompareValue(self):
      return (self.linksLeft(),self.node.find('iCost'),self.node.find('iGridX'),self.node.find('iGridY'))
    def __cmp__(self,other):
      return cmp(self.getCompareValue(),other.getCompareValue())
  nodeDict = {node.name : TopoNode(node) for node in tList}
  results = []
  targets = filter(lambda n: n.linksLeft() == 0, nodeDict.values())

  while targets:
    #print [target.node.name for target in targets]
    heapq.heapify(targets)
    temp = 0
    for targs in nextNode(targets):
      results.append(targs.node)
      updatePreqsOf(targs, True, nodeDict, targets)
      updatePreqsOf(targs, False, nodeDict, targets)
      temp += 1
    # escape even if tech is ill formed
    if temp == 0:
      print 'emergencyBreak'
      break
  #print [(target.node.name, target.fullPreqsLeft() , target.hasFullPreqs, target.node.fullPreq, target.hasPartialPreqs, target.node.partialPreq) for target in targets]
  return results


def lookup(dic):
  return lambda keys: map(lambda key: dic[key],keys)
def iterDic(dic):
  for key in dic.keys():
    yield (key, dic[key])
class TechTree:
  def __init__(self, xmlFiles = defaultData, prefix = ''):
    self.techList = generateTechList(loadData(xmlFiles,prefix))
    self.techLookup = generateTechLookup(self.techList)
    applyReverseConnections(self.techList, self.techLookup)
    self.orderedTech = toposort(self.techList, self.techLookup)
    self.orderDict = {self.orderedTech[i].name : i for i in range(len(self.orderedTech))}
  def orderDifference(self, firstName, secondName):
    return self.orderDict[secondName] - self.orderDict[firstName]
  def strictDependance(self, firstName, secondName):
    diff = self.orderDifference(firstName, secondName)
    if self.orderDifference(firstName, secondName) < 0:
      return 0
    base = self.orderDict[firstName]
    deps = [0] * (diff + 1)
    deps[0] = 1 #represent the source
    for i in range(diff+1)[1:]:
      j = i + base
      node = self.orderedTech[j]
      test =  lambda f,l: f( preqs >= base and preqs - base < diff and deps[preqs-base] for preqs in lookup(self.orderDict)(l))
      if test(any,node.fullPreq) or (test(all,node.partialPreq) and len(node.partialPreq) > 0):
        deps[i] = 1
    return deps[-1]
  def dependance(self, firstName, secondName):
    if self.orderDifference(firstName, secondName) < 0:
      return self.dependance(secondName,firstName)
    else:
      return self.strictDependance(firstName,secondName)
  def listRedudantDependanciesOf(self, baseTech):
    fulls = sorted(lookup(self.orderDict)(baseTech.fullPreq))
    partials = sorted(lookup(self.orderDict)(baseTech.partialPreq))
    gName = lambda i: self.orderedTech[i].name
    redundantPartials = set(filter(lambda s: any(map(lambda o: o < s and
           self.strictDependance(gName(o),gName(s)),
           partials)),partials))
    partials = list(set(partials) - redundantPartials)
    alls = sorted(fulls + partials)
    return map(gName, list(set(
           filter(lambda s: any(map(lambda o: o > s and
           self.strictDependance(gName(s),gName(o)),
           fulls)),alls)).union(
           set(filter(lambda s: len(partials) > 0 and all(map(lambda o: o > s and
           self.strictDependance(gName(s),gName(o)),
           partials)),fulls))). union(redundantPartials)))
  def listRedudantDependancies(self):
    def dictCons():
       for baseTech in self.orderedTech:
         yield (baseTech.name, self.listRedudantDependanciesOf(baseTech))
    return { k: v for k, v in dictCons() if len(v) > 0}     

with open('techOut.txt','w') as f:
  tree = TechTree()
  for k, v in iterDic(tree.listRedudantDependancies()):
    f.write(k + ': ' + ''.join([v[0]] + map(lambda s: ', ' + s, v[1:])) + '\n')


Next up is the output I got. Note that I ran it on a half year old version (v38), which I have moded even more, though I have not touched the technology files. It comes in the format of Technology : redudantdant tech, redudant tech \n
Spoiler techOut.txt :

Code:
TECH_MARXISM: TECH_STOCK_EXCHANGING
TECH_PLANETARY_ECONOMICS: TECH_FUSION
TECH_FLORISTRY: TECH_GARDENING
TECH_UNMANNEDSEA: TECH_DEEP_SEA_EXPLORATION
TECH_ASTROIMPERIALISM: TECH_INTERSTELLAR_COMMUNICATION
TECH_ANCESTOR_WORSHIP: TECH_CELEBRATION
TECH_FIBER_OPTICS: TECH_LASER, TECH_MICROPROCESSOR, TECH_COMPUTER_NETWORKS
TECH_DECRYPTION_MACHINES: TECH_PROPAGANDA
TECH_CSPACECRAFT: TECH_INTERSTELLAR_TRAVEL, TECH_UNMANNED_AIR_VEHICLES
TECH_BOTANICAL_ALCHEMY: TECH_APHOTOSYNTHESIS, TECH_ENVIRONMENTAL_ECONOMICS, TECH_VERTICAL_FARMING
TECH_MECHANIZED_WARFARE: TECH_RADIO
TECH_PROPAGANDA: TECH_PSYCHOLOGY
TECH_OPTRONICS: TECH_HYPERMAGNETICS
TECH_POLYTHEISM: TECH_STARGAZING
TECH_MODERN_ART: TECH_MODERN_LIFESTYLE
TECH_CANDLE_MAKING: TECH_APICULTURE
TECH_WIRELESS_ELECTRICITY: TECH_NANOGENERATOR
TECH_INVISIBILITY: TECH_RAPID_PROTOTYPING
TECH_SOLAR_ORDNANCE: TECH_SOLAR_PROPULSION
TECH_SEMI_AUTOMATIC_WEAPONS: TECH_RIFLING
TECH_HERALDRY: TECH_FEUDALISM
TECH_WEATHER_CONTROL: TECH_CLIMATE_MODELLING
TECH_GALACTIFORMING: TECH_GALACTIC_ECOLOGY
TECH_SALT_PROCESSING: TECH_DRYING
TECH_MEDICINE: TECH_BIOLOGY
TECH_TRAPPING: TECH_DECEPTION
TECH_ELECTRONICS: TECH_RADIO
TECH_LUNAR_MEGASTRUCTURES: TECH_LUNAR_TOURISM, TECH_FRICTIONLESS_FLIGHT, TECH_LUNAR_LUNAR_MANUFACTURING, TECH_ORBITAL_MEGASTRUCTURES
TECH_TELEPORTATION: TECH_QUANTUM_COMPUTING
TECH_MOLECULAR_BIOLOGY: TECH_ORGANIC_CHEMISTRY
TECH_DRAMA: TECH_LITERATURE, TECH_ORATORY
TECH_RADIO_ASTRONOMY: TECH_COSMOLOGY
TECH_EXOPLANETDISCOVERY: TECH_RADIO_ASTRONOMY
TECH_ECONOMICS: TECH_MERCANTILISM
TECH_EMANCIPATION: TECH_ECONOMICS
TECH_ANCIENT_BALLISTICS: TECH_OIL_LAMPS
TECH_NANOTECHNOLOGY: TECH_3D_MODELLING
TECH_OMEGA_MINUS_ENGINEERING: TECH_DARK_MATTER_ENGINEERING
TECH_FIRE_SUPPRESSION: TECH_FIREFIGHTING
TECH_SUPERCONDUCTORS: TECH_INFORMATION_LIFESTYLE, TECH_REFRIGERATION
TECH_GEOMETRY: TECH_SUNDIAL
TECH_WILDERNESSC: TECH_NATIONALISM
TECH_PHILOSOPHY: TECH_MATHEMATICS
TECH_NAVAL_WARFARE: TECH_SAILING
TECH_COMMUNICATION_NETWORKS: TECH_SATELLITES, TECH_GLOBALIZATION, TECH_MICROWAVES
TECH_JUDAISM: TECH_MONOTHEISM
TECH_BOAT_BUILDING: TECH_DRYING
TECH_INTERCLUSTER_TRAVEL: TECH_INTERGALACTIC_EMPIRE
TECH_SPICE_TRADE: TECH_CUISINE
TECH_NANOMORPHICS: TECH_ANIMA_MATERIALS
TECH_MODERN_HEALTH_CARE: TECH_REFRIGERATION
TECH_AGERMINATION: TECH_ECOLOGICAL_ENGINEERING
TECH_PHOTOVALTICGLASS: TECH_PLASTIC_ELECTRONICS
TECH_MUSIC: TECH_MATHEMATICS
TECH_MILITARY_TRAINING: TECH_LINGUISTICS, TECH_BOARDGAMES
TECH_NITROGLYCERIN: TECH_EXPLOSIVES
TECH_INTERSTELLAR_TRAVEL: TECH_SATELLITES
TECH_PLANET_COLONIZATION: TECH_PLANET_EXPLORATION
TECH_THEFT: TECH_COOPERATION, TECH_SCAVENGING
TECH_REFINING: TECH_EXPLOSIVES
TECH_ROMANTICISM: TECH_GRAND_WAR
TECH_CALENDAR: TECH_SAILING
TECH_VIRTUALSOCIETY: TECH_FSYSTEMS
TECH_POTTERY: TECH_EARTH_OVEN
TECH_MODERNPHYSICS: TECH_COMPULSORY_EDUCATION
TECH_COAST_GUARD: TECH_CRIMINOLOGY, TECH_FIREFIGHTING
TECH_ELECTROMAGNETIC_FIELD_SHIELDING: TECH_MESH_NETWORKS
TECH_JOURNALISM: TECH_REPRESENTATIVE_DEMOCRACY
TECH_ELIXIRS: TECH_MICROBIOLOGY
TECH_MEGALITH_CONSTRUCTION: TECH_ARITHMETIC
TECH_FOLK_MUSIC: TECH_PREHISTORIC_MUSIC
TECH_THERMODYNAMICS: TECH_WEATHER_FORECASTING
TECH_ANTIGRAV: TECH_AMPLIFIED_WAVELENGTHS, TECH_PHOTON_THERMODYNAMICS, TECH_AICITY
TECH_NAVAL_AVIATION: TECH_RADIO
TECH_ALPHABET: TECH_LINGUISTICS
TECH_SCRIPTURES: TECH_PRIESTHOOD
TECH_ZEPTOTECHNOLOGY: TECH_WAVE_MOTION_GUN
TECH_SPACE_TOURISM: TECH_TOURISM, TECH_COMMUNICATION_NETWORKS
TECH_WINDMILLS: TECH_WATERWHEELS
TECH_HINDUISM: TECH_FOLK_DANCE
TECH_ELECTROMAGNETIC_VOLTAGE: TECH_LENGINE
TECH_PERSONAL_ROBOTS: TECH_PLASTIC_ELECTRONICS, TECH_ANDROIDS
TECH_BOTANY: TECH_AGRICULTURAL_TOOLS
TECH_BREAD_MAKING: TECH_EARTH_OVEN
TECH_SANITATION: TECH_LEAD_WORKING
TECH_FUEL_CELLS: TECH_SPACE_FLIGHT
TECH_GUERRILLA_WARFARE: TECH_RADIO
TECH_ORBITAL_FLIGHT: TECH_ADVANCED_COMPUTERS
TECH_LOGISTICS: TECH_MASS_TRANSIT
TECH_INTERSTELLAR_VOYAGE: TECH_PLANETARY_MEGASTRUCTURES
TECH_ASTROBIOLOGY: TECH_ASTROGEOLOGY
TECH_PERSPECTIVE: TECH_ARCHITECTURE
TECH_ANTIMATTER_PRODUCTION: TECH_MOLECULAR_SCANNING
TECH_LUNAR_BASES: TECH_LUNAR_EXPLORATION
TECH_HORSE_BREEDING: TECH_EQUINE_DOMESTICATION
TECH_ANDROIDS: TECH_BIOMIMETICS
TECH_FRESPONSE: TECH_FIRE_SUPPRESSION
TECH_GLASS_BLOWING: TECH_MASONRY
TECH_SOLAR_PROPULSION: TECH_NANOTECHNOLOGY
TECH_WORMHOLE_TRAVERSAL: TECH_TELEPORTATION
TECH_ASTROECOLOGY: TECH_ARTIFICIAL_LIFE
TECH_MASS_TRANSIT: TECH_CIVIL_ENGINEERING
TECH_SIEGE_WARFARE: TECH_MILITARY_TRAINING
TECH_MICROWAVES: TECH_RADAR
TECH_CUISINE: TECH_FERMENTATION
TECH_PLANET_EXPLORATION: TECH_ROBOTICS
TECH_ECOLOGICAL_ENGINEERING: TECH_FIRE_SUPPRESSION
TECH_HYPERSTRUCTURE_ENGINEERING: TECH_COSMIC_ENGINEERING
TECH_QUANTUM_COMPUTING: TECH_ADVANCED_COMPUTERS
TECH_SOLAR_POWER: TECH_HYDROELECTRICITY
TECH_BIONICS: TECH_NANOGENERATOR
TECH_COSMIC_ENGINEERING: TECH_INTERCLUSTER_TRAVEL
TECH_INTERGROUP_TRAVEL: TECH_DIRECTED_PANSPERMIA
TECH_MELECTRONICS: TECH_AUGMENTEDREALITY
TECH_WEAPONIZED_ANTIMATTER: TECH_WEAPONIZED_DISINTEGRATION
TECH_PLANETARY_TRADE: TECH_MAGNETIC_SAILS
TECH_WOMENS_SUFFRAGE: TECH_JOURNALISM
TECH_PLANETARY_MEGASTRUCTURES: TECH_PLANET_COLONIZATION
TECH_GASTRONOMY: TECH_SPACE_FLIGHT
TECH_CONSUMERISM: TECH_INDUSTRIALISM
TECH_CYBERNETICS: TECH_BIONICS
TECH_MEGAWORMHOLES: TECH_INTERGALACTIC_EMPIRE, TECH_INTERGROUP_TRAVEL
TECH_ARISTOCRACY: TECH_CASTE_SYSTEM
TECH_CHIVALRY: TECH_HERALDRY
TECH_ONTOLOGICALENGINEERING: TECH_VIRTUALSOCIETY
TECH_DEMOCRACY: TECH_ALPHABET
TECH_FORENSICS: TECH_GENETICS
TECH_ATTOMETER_NANOMORPHISM: TECH_NANOTROIDS
TECH_PURE_INFORMATION_SOCIETY: TECH_DARK_MATTER_ENGINEERING
TECH_BIOMATHMATICS: TECH_BIOFUELS
TECH_CONTROLLED_INFLATION: TECH_COSMIC_ENGINEERING
TECH_FUNDAMENTALISM: TECH_RESURRECTION
TECH_ARMORED_VEHICLES: TECH_ARTILLERY
TECH_GALACTIC_WARFARE: TECH_GALACTIC_FEDERATION
TECH_COMPULSORY_EDUCATION: TECH_CRIMINOLOGY
TECH_SKYROADS: TECH_WIRELESS_ELECTRICITY
TECH_MATHEMATICS: TECH_BOARDGAMES
TECH_DERIVATIVES: TECH_LEGALIZED_GAMBLING
TECH_MARTIAL_ARTS: TECH_PHILOSOPHY, TECH_COMBAT_SPORTS
TECH_BIOMECHANICALHARVESTING: TECH_EXTREME_SPORTS
TECH_CONSCIOUSNESS: TECH_CELEBRATION
TECH_NEURON_ENGINEERING: TECH_ACYBERIMM
TECH_LASER: TECH_MINIATURIZATION
TECH_ZERO_POINT_ENERGY: TECH_WAVE_MOTION_GUN
TECH_COGNITIVE_ROBOTICS: TECH_ROBOTICS
TECH_EXTREME_SPORTS: TECH_TOURISM
TECH_COLONY_ARCOLOGY: TECH_ORGANIC_CITIES, TECH_SHIELDING
TECH_GUIDED_WEAPONS: TECH_LASER
TECH_MONOTHEISM: TECH_MASONRY
TECH_IDEOGRAMS: TECH_PICTOGRAPHS
TECH_CONSTRUCTION: TECH_MONARCHY
TECH_FSYSTEMS: TECH_MEDIAPSYCOLOGY
TECH_CYBERSOCIOLOGY: TECH_ANDROIDS
TECH_UNIFICATION_PHYSICS: TECH_SUPERSTRONG_ALLOYS
TECH_PLANETARY_TERRAFORMING: TECH_PLANETARY_MEGASTRUCTURES
TECH_LAUNCH_ARCOLOGY: TECH_SUPERFLUOUS_MANUFACTURING, TECH_ADVANCED_SHIELDING
TECH_WEAPONIZED_DISINTEGRATION: TECH_SOLAR_ORDNANCE
TECH_MODERN_SANITATION: TECH_SANITATION
TECH_TELEVISION: TECH_MOTION_PICTURES
TECH_ANTI_AGING_MEDICINE: TECH_NANOGENERATOR
TECH_SUBTERRANEAN_EXPLORATION: TECH_ASTRO_ENVIRONMENTAL_SYSTEMS, TECH_VOLCANOLOGY
TECH_CONCRETE: TECH_ROAD_BUILDING
TECH_ARTIFICIAL_LIFE: TECH_HOMO_SUPERIOR
TECH_SOAP_MAKING: TECH_FERMENTATION
TECH_MAIL: TECH_LINGUISTICS
TECH_BOARDGAMES: TECH_IDEOGRAMS
TECH_FOLK_DANCE: TECH_PREHISTORIC_DANCE
TECH_TRANSHUMAN_LIFESTYLE: TECH_UNIVERSAL_TRANSLATOR
TECH_PICOTECHNOLOGY: TECH_TELEPORTATION
TECH_REALISM: TECH_PHOTOGRAPHY
TECH_DRYING: TECH_SKINNING
TECH_ZOOLOGY: TECH_ANATOMY, TECH_FELINE_DOMESTICATION
TECH_DYSTOPIA_PATHOGENS: TECH_REGENERATIVE_MEDICINE
TECH_WATERWORKS: TECH_IRRIGATION
TECH_QUANTUM_TELEPORTATION: TECH_FIBER_OPTICS
TECH_WEAPONIZED_GRAVITY_FIELDS: TECH_ADVANCED_WARMACHINES
TECH_LUNAR_TOURISM: TECH_LUNAR_COLONIZATION
TECH_SHIP_BUILDING: TECH_SEAFARING
TECH_SENTIENT_EARTH: TECH_MYTHOLOCIAL_BEASTIARY
TECH_UNMANNED_AIR_VEHICLES: TECH_ROBOTICS
TECH_METEOROLOGY: TECH_WEATHER_FORECASTING
TECH_NEURAL_NETWORK: TECH_GENETICS
TECH_FOODP: TECH_GRAND_WAR
TECH_DRUG_TRADE: TECH_LAW_ENFORCEMENT
TECH_EXTRATERRESTRIAL_AGRICULTURE: TECH_PLANET_COLONIZATION
TECH_LUNAR_TRADE: TECH_SOLAR_PROPULSION, TECH_MASS_DRIVER
TECH_AESTHETICS: TECH_GEOMETRY
TECH_MAGLEV: TECH_FIBER_OPTICS
TECH_LENGINE: TECH_LIQUIDMETAL, TECH_FUSION
TECH_SEAFARING: TECH_PIRACY
TECH_ROCKETRY: TECH_ADVANCED_METALLURGY
TECH_CRITICAL_THOUGHT: TECH_CLOCKWORKS
TECH_PIRACY: TECH_NAVAL_WARFARE
TECH_MULTIVERSE_TRAVERSAL: TECH_ENDLESS_EXPLORATION

Note that the site doesnt seem to allow uploading of .py files.
I hope this will be of use.
 
This one is irrelevant - I removed tech redundancies in techs before V38.5 release.
Also I removed tech redundancies in units and buildings at some SVN revision.

I was talking about buildings/units prereqs getting obsoleted or replaced before building/unit itself obsoletes.
 
It is nice that tech redundancies have been fxed in the newer version, though the script can hopefull be used in the future as a quick test.
That said, I did plan on extending it toward solving the obsoletion problem later on. Solving redundancy can also be considered an early fruit of the work, as the code needed for the redudancy problem is only about 15% of the script, with the rest being part of what is needed to solve the obsoletion problem.
The thing is, that to continue on I am going to need to both figure out where all the files that needs to be checked are (there are a lot of building files), the methods that can obsolete a building prematurely, and any special algorithms that need might arise of to solve the problem.
 
Does Sweat Lodge count? It requires Sage's Hut, which is obsolete at Democracy. But it itself is not obsolete until Medicine. But it's not an important building (it just provides +1 health and-1 disease) and is not replaced by another building. Sweat Lodge is and by the time you hit Democracy, there are more options for disease control.

Realism Invictus has a thing where some buildings are "discontinued" when a certain tech is researched, meaning they cannot be built after that tech but existing instances of the building function until another tech obsoletes the building. Sage's Hut obsoleting is kind of like discontinuing Sweat Lodge at Democracy. Might be okay in this case.
 
I ran the script on the 38.5 release, and while you got rid of almost all the redudancies, the script still detected 6:
Spoiler tech redudancis :

Code:
TECH_INTERCLUSTER_TRAVEL: TECH_INTERGALACTIC_EMPIRE
TECH_PLANETARY_TRADE: TECH_MAGNETIC_SAILS
TECH_DYSTOPIA_PATHOGENS: TECH_REGENERATIVE_MEDICINE
TECH_ELIXIRS: TECH_MICROBIOLOGY
TECH_BOAT_BUILDING: TECH_DRYING
TECH_MULTIVERSE_TRAVERSAL: TECH_ENDLESS_EXPLORATION

Note that if there are optional redundancies, then they arent completly redudant, as they still reduce tech cost, and there are some other effects that can mean the effect is slightly different. For instance if you always have to get optional requirement A, then optional requirement B is partially redundant, since you dont need it, but A is also redudant, since listing you would have to get it anyway. The script would then list A. There are barely any such techs in the game through (animal riding + some lifestile ones), and none of them are on the above list, so this shouldnt be a problem.

On another note, I have been working some on the obsoletion problem, and while I am not far off for a partial solution with only some simpler cases handled proprly, the full solution is going to need a good deal more work. I am currently looking at: building A requires building B, B obsolete by tech before A (by direct dependance), and A does not get replaced. The example above with shipwright should fall into this catagory.
 
Hmm boat building redundancy means I have shift techs in Prehistoric era around Y grid again :p
As for others no idea how they got past.
I reviewed tech tree thrice.
I guess those were masked behind tangled arrows.

As for Dystopia Pathogens it just got ugly - I guess I have to move it +1 X grid and recost earthly buildings, where Dystopia Pathogens is latest prereqs, there are only few such buildings though.
Three prereqs were in same column and other one was in beginning of era :p

Buildings: Urban Depollenizer and Climate Geoengineering will be recosted - those are only Earth building requiring this tech.
Those were in Pepper module.

Techs done:
TECH_INTERCLUSTER_TRAVEL: TECH_INTERGALACTIC_EMPIRE
TECH_PLANETARY_TRADE: TECH_MAGNETIC_SAILS
TECH_DYSTOPIA_PATHOGENS: TECH_REGENERATIVE_MEDICINE
TECH_ELIXIRS: TECH_MICROBIOLOGY
TECH_BOAT_BUILDING: TECH_DRYING
TECH_MULTIVERSE_TRAVERSAL: TECH_ENDLESS_EXPLORATION

And redundancies are cleaned in SVN.
 
Last edited:
I managed to get the scrip to check for the simplest case of obsoletion by required building obsoleting before itself. I can tweek it to catch things that are not only on direct dependencies, but the current list requires one obsoletion tech to be a prerequisit of the other and not the same, and the current building not to be replaced, since the logic for replaceable buildings is more complex.
Here is the list of the current hits, it takes the form BuildingClass @ tech: (BuildingClass @ tech)+, where the first building is the one being obsoleted to early, and the list is the source of those obsoletions. I have only loaded Regular_CIV4BuildingInfos.xml and SpecialBuildings_CIV4BuildingInfos.xml, so there may more buildings with this type of obsoletion elsewhere.
Spoiler simple early obsoletions :

Code:
BUILDINGCLASS_ACTORS_SCHOOL @ None : (BUILDINGCLASS_THEATRE @ TECH_WEARABLE_ELECTRONICS), (BUILDINGCLASS_VIKING_TRADING_POST @ TECH_APPLIED_ECONOMICS)
BUILDINGCLASS_HOLOGRAPHICA_APPAREL_SHOP @ None : (BUILDINGCLASS_HOLOGRAPHIC_NETWORKS @ TECH_MIND_UPLOADING)
BUILDINGCLASS_ANIMAL_LAB @ TECH_SPECIES_UPLIFTING : (BUILDINGCLASS_PET_SHOP @ TECH_REPLACEMENT_ORGANS)
BUILDINGCLASS_BLOGS @ None : (BUILDINGCLASS_SOCIAL_NETWORKS @ TECH_EXOCORTEXNETWORKS)
BUILDINGCLASS_SWEAT_LODGE @ TECH_MEDICINE : (BUILDINGCLASS_SHAMANHUT @ TECH_DEMOCRACY)
BUILDINGCLASS_FRESCO @ TECH_MASS_MEDIA : (BUILDINGCLASS_ROCK_ART @ TECH_LITERATURE)
BUILDINGCLASS_LUXURY_FURNITURE_WORKSHOP @ None : (BUILDINGCLASS_TERRACOTTA_WORKSHOP @ TECH_GLOBALIZATION)
BUILDINGCLASS_MAMMALIAN_HUT @ TECH_MEDICINE : (BUILDINGCLASS_CHILDBIRTH_HUT @ TECH_ANCIENT_MEDICINE)
BUILDINGCLASS_ROMAN_FORUM @ None : (BUILDINGCLASS_AGORA @ TECH_LEADERSHIP)
BUILDINGCLASS_MUSICIAN_SCHOOL @ None : (BUILDINGCLASS_THEATRE @ TECH_WEARABLE_ELECTRONICS)
BUILDINGCLASS_TRAFFIC_CAMERAS @ None : (BUILDINGCLASS_TRAFFIC_SIGNALS @ TECH_TELEPORTATION)
BUILDINGCLASS_ROCK_ART @ TECH_LITERATURE : (BUILDINGCLASS_ROCK_GATHERER @ TECH_IRON_WORKING)
BUILDINGCLASS_SPY_HIDEOUT @ None : (BUILDINGCLASS_MEETING_HALL @ TECH_RADAR)
BUILDINGCLASS_LYCEUM @ None : (BUILDINGCLASS_GRAMMATICUS @ TECH_COMPUTERS)
BUILDINGCLASS_BRANDING_HUT @ TECH_MEDICINE : (BUILDINGCLASS_FIREPIT @ TECH_FIRE_BRIGADES)
BUILDINGCLASS_ANTIGRAV_VEHICLE_DEALERSHIP @ None : (BUILDINGCLASS_SKYROAD_STATION @ TECH_TELEPORTATION), (BUILDINGCLASS_INTELLIGENT_PAVEMENT @ TECH_TELEPORTATION)
BUILDINGCLASS_TOURIST_TRAP @ None : (BUILDINGCLASS_ASPHALT_ROADS @ TECH_TELEPORTATION)
BUILDINGCLASS_MEGATOWER_HOLOGRAM_ADVERTISING @ None : (BUILDINGCLASS_HOLOGRAPHIC_NETWORKS @ TECH_MIND_UPLOADING)
BUILDINGCLASS_ACUPUNCTURISTS_SHOP @ TECH_MODERN_HEALTH_CARE : (BUILDINGCLASS_VIKING_TRADING_POST @ TECH_APPLIED_ECONOMICS)
BUILDINGCLASS_MOTORCYCLE_CLUB @ None : (BUILDINGCLASS_AUTOREPAIR_SHOP @ TECH_TELEPORTATION)
BUILDINGCLASS_NATIVE_AMERICA_TOTEM @ TECH_ASTRONOMY : (BUILDINGCLASS_WOODCARVERS_HUT @ TECH_GUILDS)
BUILDINGCLASS_BRAHMIN_LIBRARY @ TECH_LIBERALISM : (BUILDINGCLASS_SCHOOL_OF_SCRIBES @ TECH_PRINTING_PRESS)

I expect that some of the above (especially those with @ None) are by design.
If you want me to run the data over more files, or apply the more aggresive test (I test for 1-iCost(A)/iCost(B), where A obsoletionc tech of the required building, and B the actual building), just say so. I can also give you the code if you want to run it yourself, but it needs some rewriting to tackle some of the more complicated test, at least if I want to avoid too much redudant code.
 
Does Sweat Lodge count? It requires Sage's Hut, which is obsolete at Democracy. But it itself is not obsolete until Medicine. But it's not an important building (it just provides +1 health and-1 disease) and is not replaced by another building. Sweat Lodge is and by the time you hit Democracy, there are more options for disease control.

Realism Invictus has a thing where some buildings are "discontinued" when a certain tech is researched, meaning they cannot be built after that tech but existing instances of the building function until another tech obsoletes the building. Sage's Hut obsoleting is kind of like discontinuing Sweat Lodge at Democracy. Might be okay in this case.
I do use this sort of thing on purpose and intend to more. Building X (obsolete at Steam Engine) requires building Building Y (obsolete at Metal Casting). I have a set of wonders which will follow this pattern. They are only wonders if made before Metal Casting and remain wondrous even though they would be simple to make with Metal Casting techniques.
 
I do use this sort of thing on purpose and intend to more. Building X (obsolete at Steam Engine) requires building Building Y (obsolete at Metal Casting). I have a set of wonders which will follow this pattern. They are only wonders if made before Metal Casting and remain wondrous even though they would be simple to make with Metal Casting techniques.
What is purpose of building/unit obsoleting later than its prereqs?
 
What is purpose of building/unit obsoleting later than its prereqs?
It means that you need to build it early. There is a cost but there is long lasting benefits if you build it. Making it after a certain point becomes trivial but the fact that it was made before that point increases its value eg The Book of Kells in the real world. It is the work and quality of the work that went into making it that makes it so important. Invention of the printing press means that it wont be done after that point but it is still important. To achieve such a mechanism means that you need the prereq to build the building to go obsolete at printing press whereas the actual building does not go obsolete until much later.
 
It means that you need to build it early. There is a cost but there is long lasting benefits if you build it. Making it after a certain point becomes trivial but the fact that it was made before that point increases its value eg The Book of Kells in the real world. It is the work and quality of the work that went into making it that makes it so important. Invention of the printing press means that it wont be done after that point but it is still important. To achieve such a mechanism means that you need the prereq to build the building to go obsolete at printing press whereas the actual building does not go obsolete until much later.
From what I read in pedia such buildings are still here after all, and just provide only cultural/defensive role after obsoletion.

I think it would be good test to verify it:
Make two buildings, X would be prereq of Y.
Y wouldn't obsolete but X would. No tech for unlocking, and X would obsolete early in prehistoric era, so other things don't flood building list yet.
 
What is purpose of building/unit obsoleting later than its prereqs?

This is something I argued for in Realism Invictus. A building does not stop working when a more efficient method is found. The old building should keep working until it is replaced. But you should not be able to build the old building.

An example (from RI):

Building A gives +10% hammers.
Replacement building B gives +15% hammers and discontinues building A. You can now know longer build A. But existing building A's still give 10% hammers.
Replacement building C gives +20% hammers, discontinues building B. You can now know longer build B. But existing building B's still give 15% hammers. At this point building A is made obsolete. If you have not replaced it you lose the 10% hammers.

My argument was that it was unrealistic, for example: if all forges suddenly stopped working when the Foundry could be built. With the loss of production.
 
Agree with Harrier.
Obsolescence is sometimes a bug problem, like when you research Education, you will have a big loss in Education because of this.

I will go even further. because some tech can negate bonuses (with some -1 Culture with X tech or the like), we can get rid of nearly all obsolescences. Buildings are just replaced by better buildings, or non-functioning because of a civics change/lost ressource.
 
  • Like
Reactions: tmv
Indeed, I prefer buildings to be replaced by their upgrades and not go obsolete due to tech. However doing so is not always easy eg the security buildings, or was not possible when multiple lines of development were happening at the same time eg story buildings. In both those cases doing something is difficult and may not be possible with the currently available XML tags.

There are lots of +x due :)commerce:,:culture:,:espionage:,:food:,:hammers:,:science:,...) to techs so why not -x as well? miss read comment. Yes -x is part of the solution as would be increasing maintence costs, but does the AI understand this. Or even the player.

I made a mod which made the city more and more unhappy if the basics the people would want were not met but had to remove it because providing those buildings did not show, in the "actuals" that they also improved happiness. The "actuals" are not calculated based on the city but on the nation. Changing it to be city based would greatly increase city display times. Interestingly the "actuals" do show somewhat the city based :hammers:, :science: and :gold: changes.
 
From what I read in pedia such buildings are still here after all, and just provide only cultural/defensive role after obsoletion.
True. The use of the tags that include the term 'safeobsolete' (as well as a few others) is an indicator that even if the building goes obsolete, the effect of this tag will live on after. Still can't be built afterwards.

Indeed, I prefer buildings to be replaced by their upgrades and not go obsolete due to tech.
I agree except to say that an era down the road, they should be obsoleted to ensure you don't build anachronistically as a strategy.
 
I agree except to say that an era down the road, they should be obsoleted to ensure you don't build anachronistically as a strategy.
Once we have volumetric resources this will no longer be a problem, I think. Because the factories can then do what they are doing in the real world, that is producing a lot more goods than former producers ever could. At this point these measures could be removed again, because once in a while this might be a viable strategy even in the real world (whenever a product is sufficiently extraodinary or requires extremely rare resources).

Another option could be that people simply don't like that kind of work anymore beyond a certain point, so some old buildings might give :mad: with advanced lifestyles.
 
I'm not sure that volumetric resources is an inevitable part of C2C. My gut feeling says it'll be a lot of added micromanagement with little addition to strategic depth, and hard to balance (also for the AI). Even if somebody starts on such a system, there's a non-zero chance it will eventually fail due to being rejected for making the game less fun.
 
Things should be going obsolete later than they are. And buildings shouldn't have so many prerequisites, maybe none from among structures that can go obsolete, except in meaningful cases like Printing Press.

If there is an issue with having buildings treated as modern in anachronistic situations (e.g., ancient library still good after cosmic consciousness), then use a disjunctive for prerequisites, seeking any version of the prerequisite structure. The versions would replace their predecessors or possibly co-exist, case-by-case.

Definitely there isn't a reason for an upgrade to require an anterior version of itself. I hope that doesn't happen.

Case of Forge and Foundry. A forge is relevant even if something better exists. A forge might not be allowed to co-exist with its upgrade. The possibility of building another forge can potentially exist even when something superior is available. The only relationship we know is absolute is that, at the point the building "isn't doing anything measurable" (in-context) , that is, when it's obsolete, is the same point when a player should not be allowed to build another one.

The problem isn't complicated hierarchical logic. It's that the obsolescence is too eager. Widen the windows, by double, even.

-----
One other thing I thought I'd highlight is the larger need in C2C development to represent the structural Design decisions as separate from the Mechanical, interpreted product of game files. When we figure out how to accomplish a Design goal - e.g., use an out-of-fashion structure to quicken production of an upgrade; specify all techs have costs dictated by their column; make buildings have costs dictated by their tech column - we put those mechanics in the game files - e.g., set a Building_BuildingModifier to something nonzero; set 929 <Cost> fields in an XML file - but we lose the coherency of the Design decision.
One place that is less spreadsheet-ible of this problem, is with technologies. We might know that technologies should be in certain relations to each other, like being Definitely After another one, but the current form of the tree makes the Requires relationship redundant. This is where optimizing the game files loses Design information.

The missing information can be recovered either with documentation, or metaprogramming. I know there's been a renaissance of documentation and spreadsheets, which is great, but I wonder. Just saying.
 
Top Bottom