Caveman 2 Cosmos (ideas/discussions thread)

Does it limit all OR buildings in that set to have the same bool sets? I wonder if that would constrict design in multimap scenarios where something has OR prereqs that depend on which type of map we're on as to which building can fulfill the prereq. I may be wrong about this concern... maybe you can help me understand how that would be setup under this design.

Scratch that, my design is flawed. You're right about the possibility of two OR buildings having different requirements. I just assumed they are easily grouped together like we have currently. My idea of nesting a vector in a struct in a vector also complicates the code.
 
Don't forget that there are variables defined in the globals XML that are used to limit the number of elements in the AND/OR lists. They are there to help keep the memory as small as needed when arrays were used. If you are changing from arrays to vectors then you should probably also adjust the processing on those variables and comment them out (with why) in the XML so as to remove confusion later.
 
Scratch that, my design is flawed. You're right about the possibility of two OR buildings having different requirements. I just assumed they are easily grouped together like we have currently. My idea of nesting a vector in a struct in a vector also complicates the code.
I would recommend to do it similar to the BoolExpr tags, something like this:
Code:
<PrereqBuildings>
  <BuildingType>BUILDING_ROCK_GATHERER</BuildingType>
  <Or>
    <BuildingType>BUILDING_STORAGE_PIT</BuildingType>
    <BuildingType>BUILDING_BARTER_POST</BuildingType>
    <BuildingType>BUILDING_VIKING_TRADING_POST</BuildingType>
    <And>
      <BuildingType>BUILDING_WHATEVER</BuildingType>
      <BuildingType>BUILDING_WHATEVER2</BuildingType>
      <iNumberNeeded>3</iNumberNeeded>
      <bOnContinent>1</bOnContinent>
    </And>
  </Or>
</PrereqBuildings>
 
I would recommend to do it similar to the BoolExpr tags, something like this:
Code:
<PrereqBuildings>
  <BuildingType>BUILDING_ROCK_GATHERER</BuildingType>
  <Or>
    <BuildingType>BUILDING_STORAGE_PIT</BuildingType>
    <BuildingType>BUILDING_BARTER_POST</BuildingType>
    <BuildingType>BUILDING_VIKING_TRADING_POST</BuildingType>
    <And>
      <BuildingType>BUILDING_WHATEVER</BuildingType>
      <BuildingType>BUILDING_WHATEVER2</BuildingType>
      <iNumberNeeded>3</iNumberNeeded>
      <bOnContinent>1</bOnContinent>
    </And>
  </Or>
</PrereqBuildings>
Ok, but what would that mean exactly? You must have the Rock Gatherer or Storage Pit Or Barter Post Or Viking Trading post but if you have one of those three prereqs, you must also have Building Whatever and Building Whatever 2 and have 3 of each needed somewhere on the continent?

As an XML programmer, it's terribly confusing.
 
I have another idea, if we can use tag attributes to store numbers and true-false switches associated with a subject instead of having separate tags, XML modding will become easier.
For instance, let's reduce the following tags describing a person:
Code:
<person>
  <ID>4567</ID>
  <name>Joe</name>
  <age>31</age>
  <sex>Male</sex>
  <authoredbooks>
    <book>Introdutcion to Computer Science</book>
  </authoredbooks>
</person>

<person ID="4567" name="Joe" age="31" sex="Male">
  <authoredbooks>
    <book>Introdutcion to Computer Science</book>
  </authoredbooks>
</person>
See how we've reduced four tags to save the tag for a more meaningful use.
This is standard feature of the Document Object Model (DOM), which XML uses. The C++ XML parser we're using called xerces, would support the full feature of the DOM model too. I'll need to read the specs of DOM so as to add some code to read tag attributes in CvXMLLoadUtility using xerces' API. This will enable us to rewrite XMLs in a more compact form.

The BUG Mod uses python to read its config files in Assets/Config. These config XMLs use tag attributes throughout.
 
Last edited:
I have another idea, if we can use tag attributes to store numbers and true-false switches associated with a subject instead of having separate tags, XML modding will become easier.
For instance, let's reduce the following tags describing a person:
Code:
<person>
  <ID>4567</ID>
  <name>Joe</name>
  <age>31</age>
  <sex>Male</sex>
  <authoredbooks>
    <book>Introdutcion to Computer Science</book>
  </authoredbooks>
</person>

<person ID="4567" name="Joe" age="31" sex="Male">
  <authoredbooks>
    <book>Introdutcion to Computer Science</book>
  </authoredbooks>
</person>
See how we've reduced four tags to save the tag for a more meaningful use.
This is standard feature of the Document Object Model (DOM), which XML uses. The C++ XML parser we're using called xerces, would support the full feature of the DOM model too. I'll need to read the specs of DOM so as to add some code to read tag attributes in CvXMLLoadUtility using xerces' API. This will enable us to rewrite XMLs in a more compact form.

The BUG Mod uses python to read its config files in Assets/Config. These config XMLs use tag attributes throughout.
This strikes me as complicating the manner in which information is called, maybe making it slower to call for specific info. I would have thought the struct is basically already doing pretty much this, then enabling the calling of any of the nested tag information by calling the index of the tag with the proper . extension. If you're talking about a way to rewrite the XML, it would be helpful for the XML programmers to not break from their usual expectations lest we have to teach new tricks. This also strikes me as something that then only works if you assume all tags in the nested block are going to be defined and not just left to default by not expressing them, which is a handy thing to be able to do. XML seems easier to read when all tags are clearly delineated.

Just my thoughts. It's quite fascinating to think it's possible to express XML in this manner since I've not been shown this - but is there really a gain here? I find the copying and pasting of XML lines after hard returns to often be handy and efficient. Easier to select a whole line for copying than surgically selecting a portion of a line.
 
This will make the XML document easier to read. Let's take the barracks for example, what used to be 45 lines can be reduced to 10 lines. Isn't this impressive?

Code:
<!-- Obsolescence -->
<ReplaceBuildings>
    <ReplaceBuilding>
        <BuildingClassType>BUILDINGCLASS_GARRISON</BuildingClassType>
        <bReplace>1</bReplace>
    </ReplaceBuilding>
    <ReplaceBuilding>
        <BuildingClassType>BUILDINGCLASS_MILITARY_BASE</BuildingClassType>
        <bReplace>1</bReplace>
    </ReplaceBuilding>
</ReplaceBuildings>
<!-- Construction cost -->
<iCost>216</iCost>
<ProductionTraits>
    <ProductionTrait>
        <ProductionTraitType>TRAIT_AGGRESSIVE</ProductionTraitType>
        <iProductionTrait>100</iProductionTrait>
    </ProductionTrait>
</ProductionTraits>
<NewCityFree>
    <Has>
        <GOMType>GOM_TECH</GOMType>
        <ID>TECH_COLONIALISM</ID>
    </Has>
</NewCityFree>
<!-- Unit effects -->
<UnitCombatFreeExperiences>
    <UnitCombatFreeExperience>
        <UnitCombatType>UNITCOMBAT_MELEE</UnitCombatType>
        <iExperience>3</iExperience>
    </UnitCombatFreeExperience>
    <UnitCombatFreeExperience>
        <UnitCombatType>UNITCOMBAT_RECON</UnitCombatType>
        <iExperience>3</iExperience>
    </UnitCombatFreeExperience>
    <UnitCombatFreeExperience>
        <UnitCombatType>UNITCOMBAT_ANIMAL</UnitCombatType>
        <iExperience>2</iExperience>
    </UnitCombatFreeExperience>
    <UnitCombatFreeExperience>
        <UnitCombatType>UNITCOMBAT_MOUNTED</UnitCombatType>
        <iExperience>2</iExperience>
    </UnitCombatFreeExperience>
    <UnitCombatFreeExperience>
        <UnitCombatType>UNITCOMBAT_SIEGE</UnitCombatType>
        <iExperience>1</iExperience>
    </UnitCombatFreeExperience>
</UnitCombatFreeExperiences>
Code:
<!-- Obsolescence -->
<ReplaceBuilding BuildingClassType="BUILDINGCLASS_GARRISON" />
<ReplaceBuilding BuildingClassType="BUILDINGCLASS_MILITARY_BASE" />
<!-- Construction cost -->
<iCost>216</iCost>
<ProductionTrait TraitType="TRAIT_AGGRESSIVE" iPercents="100" />
<NewCityFree TechType="TECH_COLONIALISM" />
<!-- Unit effects -->
<UnitCombatFreeExperience UnitCombatType="UNITCOMBAT_MELEE" iAmount="3" />
<UnitCombatFreeExperience UnitCombatType="UNITCOMBAT_RECON" iAmount="3" />
<UnitCombatFreeExperience UnitCombatType="UNITCOMBAT_ANIMAL" iAmount="2" />
<UnitCombatFreeExperience UnitCombatType="UNITCOMBAT_MOUNTED" iAmount="2" />
<UnitCombatFreeExperience UnitCombatType="UNITCOMBAT_SIEGE" iAmount="1" />
This drastically reduces meaningless lines occupied by closing tags such as </ReplaceBuilding>.
Some specifications of this design:
  • Type-value pairs are stated in one line, in an empty-element tag. Note that empty-element tags need to end with a forward slash. " />"
  • The attribute that points to an info-type ID is named after the info-type, so I use TraitType= instead of ProductionTraitType=.
  • True-false values (booleans) can be either 0 or 1. I doubt there is any place to use a false value, if anything is mentioned. I assume anything mentioned will just be true. If we want to disable something, we just comment it out. There is no place to use boolean unless we intend to make a series of switches that applies to a single element (tag) that mean differently in different combinations.
  • Numbers can be a fixed amount or a percentage. When the meaning is clear, we can just use short general names iPercents and iAmount. When the meaning can be ambiguous, we use full names like iAmountPerTurn for PropertyManipulators.
  • If anyone is concerned, we don't need to put quotation marks around identifiers and values if they contain no space.
  • There must be quotation marks around the value of an attribute, either a pair of single or double quotes. I suggest using double quotes throughout. Single quotes may look smaller but in monospace typefaces they're the same width as double quotes. Also, it's easier to spot double quotes around a long word.
  • There's no need to have a separate grouping tag if the same tags are already grouped in vicinity. The traversal time by the parser will remain the same.
but is there really a gain here? I find the copying and pasting of XML lines after hard returns to often be handy and efficient. Easier to select a whole line for copying than surgically selecting a portion of a line.
You were concerned that it will be harder to select a text, but if you double-click on a word in a decent editor, it will quickly select one word, where words are delineated by space, dash, punctuation marks, equation mark and slashes, but characters containing underscores are considered one word. If you double-click and drag to select, it will select by a unit of words.
This strikes me as complicating the manner in which information is called, maybe making it slower to call for specific info.
Adopting tag attributes will not alter the inner representation in machine memory, and the time it takes to access information from attributes will be comparable to the time taken to access from children tags.
 
Last edited:
I had been wondering why the python handled xml's found in \Assets\Config\ were so radically different from the dll handled xml's elsewhere in C2C.
This strikes me as complicating the manner in which information is called, maybe making it slower to call for specific info.
I don't think it makes much of a difference, and it may even be faster this way.
This also strikes me as something that then only works if you assume all tags in the nested block are going to be defined and not just left to default by not expressing them, which is a handy thing to be able to do.
In the python xml's, which are like that it, is fully possible to omit some of them and default values will be used.
e.g. from Anq's example: <person ID="4567" name="Joe" age="31" sex="Male"> could be written up as <person ID="4567"> where name then is set to "Jane" Age set to 0 and sex set to female. The defaults would be defined in pretty much the same way as it currently is in the dll code.
 
<NewCityFree>
<Has>
<GOMType>GOM_TECH</GOMType>
<ID>TECH_COLONIALISM</ID>​
</Has>​
</NewCityFree>

<NewCityFree TechType=TECH_COLONIALISM />
I don't think it would be that easy to change tags that uses the expression system to this format...

What if this had been the case:

<NewCityFree>
<And>
<Has>
<GOMType>GOM_TECH</GOMType>
<ID>TECH_HUMANISM</ID>​
</Has>
<Or>
<Has>
<GOMType>GOM_BUILDING</GOMType>
<ID>BUILDING_JSBACH_CATHEDRAL</ID>​
</Has>
<Has>
<GOMType>GOM_TECH</GOMType>
<ID>TECH_COLONIALISM</ID>​
</Has>​
</Or>​
</And>​
</NewCityFree>

How would this be written in the other format?

@Anq: You really don't want to mess with the xml tags that use the expression system. ^^
 
Last edited:
@Toffer90, I think there may be some way to get logic groups together, like

<NewCityFree newlogicgroup="" TechType="TECH_HUMANISM" next="And" />
<NewCityFree newlogicgroup="" BuildingType="BUILDING_JSBACH_CATHEDRAL" next="Or" />
<NewCityFree TechType="TECH_COLONIALISM" endlogicgroup="" />

This will be interpreted as (Humanism and (JSBachCathedral or Colonialism) ).
The newlogicgroup keyword will open a parenthesis, while endlogicgroup closes it. The "next" attribute (or whatever is more accurate) gives the logical operator following an option.
We may adapt the expression system to this syntax, if AIAndy agrees with this. (But I need to lay down the getAttribute utility function first.)

Regarding <Not> found in <PropertyPropagator>:
  • <TargetCondition><Not><Is>TAG_PEAK</Is></Not></TargetCondition> would reduce to <TargetCondition not="" TagTypes="TAG_PEAK" />
  • Code:
    <Active>
      <Not>
        <Or>
          <Has>
            <GOMType>GOM_TERRAIN</GOMType>
             <ID>TERRAIN_OCEAN</ID>
          </Has>
          <Has>
            <GOMType>GOM_TERRAIN</GOMType>
            <ID>TERRAIN_OCEAN_TROPICAL</ID>
          </Has>
          <Has>
            <GOMType>GOM_TERRAIN</GOMType>
            <ID>TERRAIN_OCEAN_POLAR</ID>
          </Has>
        </Or>
      </Not>
    </Active>
    will reduce to
    <Active newlogicgroup="" not="" TerrainType="TERRAIN_OCEAN" next="And" />
    <Active not="" TerrainType="TERRAIN_OCEAN_TROPICAL" next="And" />
    <Active not="" TerrainType="TERRAIN_OCEAN_POLAR" endlogicgroup="" />
    (You need to negate the logical operators. Not(A Or B) is equivalent to Not(A) And Not(B). )
 
Last edited:
@Anq: the current format for expressions are far easier for xml modders to use.

What about...
<NewCityFree>
<IntegrateOr>
<RelationType>RELATION_SAME_PLOT</RelationType>
<GameObjectType>GAMEOBJECT_UNIT</GameObjectType>
<Has>
<GOMType>GOM_PROMOTION</GOMType>
<ID>PROMOTION_CULTURE_AFRICAN</ID>​
</Has>​
</IntegrateOr>​
</NewCityFree>
... which was something I had in the "my take on stuff" modmod some versions ago, how would that look like?

Yes, I am trying to discourage you from thinking about changing the xml formatting for these type of tags. ^^
 
@Toffer90, the current format confuses TB as he argues the statement <Or>A,B,C<And>D,E</And></Or> could be easily misinterpreted as ( A Or B Or C And ( D And E ) ). I came up with this linear format that can be interpreted sequentially. The nested statement becomes
( A Or
  B Or
  C Or
( D And
  E ).

Each line is one tag entity. Open parenthesis is indicated with a keyword newlogicgroup, or whatever, and close parenthesis with endlogicgroup. The outermost parenthesis is automatically closed if there is no more tag to consume.

When Not is introduced in the statement, it only negates the option on the line it belongs to, and won't apply to other members of a parenthesis:
( Not(A) Or
  B Or
  C Or
( D And
  Not(E) ).
And we need to be careful with it.
If we want to negate the ( D And E ) group, we would write the equivalent (and disband/merge the group when appropriate):
( A Or
  B Or
  C Or
  Not(D) Or
  Not(E) ).

What about... <NewCityFree> <IntegrateOr> [...] how would that look like?
Wow, does this example mean "Grant the free building if an African unit preexists on the tile we're about to settle on this turn"? Anyway, how about this:

<NewCityFree PromotionType="PROMOTION_CULTURE_AFRICAN" RelationType="RELATION_SAME_PLOT" />

Do we see a second potential interpretation about this line?
The GameObject will resolve to the GameObjectUnit, inferred from the PromotionType we've declared. This is a feature I'd like to add too. It may not be able to resolve the GameObject type in some cases, where we'll need to specify.

The example in the doc, making a building available to any city connected to our capital, can be shortened to this:
Spoiler Example and the link to the doc :
https://forums.civfanatics.com/threads/the-expression-system.460236/page-2#post-11598257
Code:
<ConstructCondition>
  <IntegrateOr>
    <RelationType>RELATION_TRADE</RelationType>
    <GameObjectType>GAMEOBJECT_CITY</GameObjectType>
    <Has>
      <GOMType>GOM_BUILDING</GOMType>
      <ID>BUILDING_PALACE</ID>
    </Has>
  </IntegrateOr>
</ConstructCondition>
<ConstructCondition BuildingType="BUILDING_PALACE" RelationType="RELATION_TRADE" />

It infers from the RELATION_TRADE that it's going to query the City GameObjects.


Edit: I haven't read through the documentation on the expression system, and didn't know about the <IntegrateOr> tag. Thought it was a new invention and took your question differently.

Edit: Reordered the open parenthesis keyword before the identifier.
The DOM does not enforce strict order of attributes, but it's helpful if we follow the order we would interpret it.

<Tag newlogicgroup="" not="" InfoType="ID" iNum="N" next="AndOr" endlogicgroup="" />

If "[new/end]logicgroup" is too long, what's an appropriate keyword shorthand we would agree upon? Please suggest a more specific keyword for "next" as well.

Edit: In an afterthought, we might just use RELATION_SAME_PLOT for a building prerequisite that has to exist in the city. We can add new enums such as RELATION_SAME_CONTINENT, RELATION_SAME_PLANET, etc. But short keywords like inThisCity, onContinent, onPlanet, etc, will be better.
  • <PrereqBuilding BuildingType="BUILDING_MONUMENT" iNum="2" byPlayer="" inThisCity="" /> (2 by the current player, and needed in city, like in vanilla Civ. Do NOT use RELATION_SAME_PLOT because it confuses a lot.)
  • <PrereqBuilding BuildingType="BUILDING_MONUMENT" iNum="4" byTeam="" inThisCity="" />
  • <PrereqBuilding BuildingType="BUILDING_MONUMENT" iNum="6" byAllPlayers="" scalesWithMapSize="" onPlanet="" inThisCity="" />
  • Code:
    <PrereqBuilding newlogicgroup="" BuildingType="BUILDING_CASTLE" inThisCity="" next="Or">
      <PrereqBuilding newlogicgroup="" iNum="2" byPlayer="" onContinent="" next="Or" />
      <PrereqBuilding iNum="6" byAllPlayers="" scalesWithMapSize="" endlogicgroup="" />
    </PrereqBuilding>
    <PrereqBuilding newlogicgroup="" BuildingType="BUILDING_CATHEDRAL" iNum="2" byPlayer="" next="And" />
    <PrereqBuilding iNum="1" byPlayer="" onContinent="" endlogicgroup="" />
In the last example, if we omit BuildingType, it means ditto, but we don't necessarily nest the ditto lines. When we nest these tags, it implies a middle layer of logic group: ( Parent And ( Children's group ) ). When we don't nest ditto lines, we need to explicitly create a logic group. This example can be translated as: We're entitled to build this Wonder if we have a castle here and either one in somewhere else on the continent, or a total of six by all players including us if we are on a Standard-sized map; we could also just build a cathedral on this continent and another anywhere and still be entitled the blueprint. How cool is that.
 
Last edited:
You were concerned that it will be harder to select a text, but if you double-click on a word in a decent editor, it will quickly select one word, where words are delineated by space, dash, punctuation marks, equation mark and slashes, but characters containing underscores are considered one word. If you double-click and drag to select, it will select by a unit of words.
And if you go to an end of a line and select up to the end of the next, you have much quicker selected the whole line. I don't see any good reason to care what the length of the XML file really is... this just seems like it reduces the ease of application and makes it harder to read since it is extra condensed. I could be wrong in practice and I'm just not liking the foreign look of it. Not even delineating by commas or anything also makes it... what... whitespace matters delineation? *shudder* There's a reason I hate python.

No matter, really... I'd adapt after a while. Just not sure how it's an improvement since I don't think it does anything but condense the space XML takes up, which won't make much of an impact on memory or even time to download the mod. If y'all think there's good enough cause, I can adjust.

<NewCityFree newlogicgroup TechType=TECH_HUMANISM next=And />
<NewCityFree newlogicgroup BuildingType=BUILDING_JSBACH_CATHEDRAL next=Or />
<NewCityFree TechType=TECH_COLONIALISM endlogicgroup />
This, however, does make more sense to me. So far. I'm able to see and reply in a brief moment here then I'll be back to unavailability for a while.
 
@Toffer90, the current format confuses TB as he argues the statement <Or>A,B,C<And>D,E</And></Or> could be easily misinterpreted as ( A Or B Or C And ( D And E ) ). I came up with this linear format that can be interpreted sequentially. The nested statement becomes
( A Or
  B Or
  C Or
( D And
  E ).

Each line is one tag entity. Open parenthesis is indicated with a keyword newlogicgroup, or whatever, and close parenthesis with endlogicgroup. The outermost parenthesis is automatically closed if there is no more tag to consume.

When Not is introduced in the statement, it only negates the option on the line it belongs to, and won't apply to other members of a parenthesis:
( Not(A) Or
  B Or
  C Or
( D And
  Not(E) ).
And we need to be careful with it.
If we want to negate the ( D And E ) group, we would write the equivalent (and disband/merge the group when appropriate):
( A Or
  B Or
  C Or
  Not(D) Or
  Not(E) ).


Wow, does this example mean "Grant the free building if an African unit preexists on the tile we're about to settle on this turn"? Anyway, how about this:

<NewCityFree PromotionType=PROMOTION_CULTURE_AFRICAN RelationType=RELATION_SAME_PLOT />

Do we see a second potential interpretation about this line?
The GameObject will resolve to the GameObjectUnit, inferred from the PromotionType we've declared. This is a feature I'd like to add too. It may not be able to resolve the GameObject type in some cases, where we'll need to specify.

The example in the doc, making a building available to any city connected to our capital, can be shortened to this:
Spoiler Example and the link to the doc :
https://forums.civfanatics.com/threads/the-expression-system.460236/page-2#post-11598257
Code:
<ConstructCondition>
  <IntegrateOr>
    <RelationType>RELATION_TRADE</RelationType>
    <GameObjectType>GAMEOBJECT_CITY</GameObjectType>
    <Has>
      <GOMType>GOM_BUILDING</GOMType>
      <ID>BUILDING_PALACE</ID>
    </Has>
  </IntegrateOr>
</ConstructCondition>
<ConstructCondition BuildingType=BUILDING_PALACE RelationType=RELATION_TRADE />

It infers from the RELATION_TRADE that it's going to query the City GameObjects.


Edit: I haven't read through the documentation on the expression system, and didn't know about the <IntegrateOr> tag. Thought it was a new invention and took your question differently.

Edit: Reordered the open parenthesis keyword before the identifier.
The DOM does not enforce strict order of attributes, but it's helpful if we follow the order we would interpret it.

<Tag newlogicgroup not InfoType=ID iNum=N next=AndOr endlogicgroup />

If "[new/end]logicgroup" is too long, what's an appropriate keyword shorthand we would agree upon? Please suggest a more specific keyword for "next" as well.

Edit: In an afterthought, we might just use RELATION_SAME_PLOT for a building prerequisite that has to exist in the city. We can add new enums such as RELATION_SAME_CONTINENT, RELATION_SAME_PLANET, etc. But short keywords like inThisCity, onContinent, onPlanet, etc, will be better.
  • <PrereqBuilding BuildingType=BUILDING_MONUMENT iNum=2 byPlayer inThisCity /> (2 by the current player, and needed in city, like in vanilla Civ. Do NOT use RELATION_SAME_PLOT because it confuses a lot.)
  • <PrereqBuilding BuildingType=BUILDING_MONUMENT iNum=4 byTeam inThisCity />
  • <PrereqBuilding BuildingType=BUILDING_MONUMENT iNum=6 byAllPlayers scalesWithMapSize onPlanet inThisCity />
  • Code:
    <PrereqBuilding newlogicgroup BuildingType=BUILDING_CASTLE inThisCity next=Or>
      <PrereqBuilding newlogicgroup iNum=2 byPlayer onContinent next=Or />
      <PrereqBuilding iNum=6 byAllPlayers scalesWithMapSize endlogicgroup />
    </PrereqBuilding>
    <PrereqBuilding newlogicgroup BuildingType=BUILDING_CATHEDRAL iNum=2 byPlayer next=And />
    <PrereqBuilding iNum=1 byPlayer onContinent endlogicgroup />
In the last example, if we omit BuildingType, it means ditto, but we don't necessarily nest the ditto lines. When we nest these tags, it implies a middle layer of logic group: ( Parent And ( Children's group ) ). When we don't nest ditto lines, we need to explicitly create a logic group. This example can be translated as: We're entitled to build this Wonder if we have a castle here and either one in somewhere else on the continent, or a total of six by all players including us if we are on a Standard-sized map; we could also just build a cathedral on this continent and another anywhere and still be entitled the blueprint. How cool is that.

Using something like the expression system for Building requirements is a really really bad idea. There must be a fixed set of possible requirements otherwise caching the buildings a city can construct won't be possible anymore and good luck adapting the ai.
 
If you are going to change the structure of the XML will you also be changing the C2CXmlValidator.exe to work with it? Or is this suggested structure still a match for the definitions in the Schema files?
 
@alberts2, Then I do not wish to tackle this, unless I figure out the cheap way to evaluate all possible expressions. Thanks for the head up.
@Dancing Hoskuld,
I googled for "urn:schemas-microsoft-com:xml-data" found in the header of schema files and this is likely the schema structure to use attributes:
In best cases, the C2CXmlValidator.exe will recognize this structure and do validation against it.
Code:
<ElementType name="ProductionTrait" content="eltOnly">
  <AttributeType name="TraitType" />
  <AttributeType name="iPercents"  dt:type="int" />
  <attribute type="TraitType" />
  <attribute type="iPercents" />
</ElementType>

I apologize, the attribute values MUST always be quoted for the XML to pass validation.
The single word switches are illegal too. Nothing like <input readonly /> in HTML is valid in XML. They should be given value, but then even empty quotes "" will do. I'll make it treat empty values as true and absence of mention as false for these switches. Empty attributes are still mapped out by the DOM parser, and there are two API functions, one to get the attribute node, the other the value of the attribute node. The first function will return something for an empty attribute, and nothing if it's not mapped at all. In my design so far I only use these switches for things that go through the expression system which I do not wish to tackle because they are expensive to evaluate and cache and will break the AI.
 
Last edited:
The schema used for validating by C2CXmlValidator an XML file is the one defined at the top of the file. This is why it can be used by any Civ IV mod no matter how different to C2C they are.
 
Wow, does this example mean "Grant the free building if an African unit preexists on the tile we're about to settle on this turn"?
It does, but after I got TB to add the unit that settles the city as an argument to the python function call event that happens every time a city is built, I switched out the xml implementation with a python implementation that looks like this:
for iPromo, iBuilding in gCultureList:
if -1 in (iPromo, iBuilding): continue
if CyUnit.isHasPromotion(iPromo):
CyCity.setNumRealBuilding(iBuilding, 1)​

In that modmod I have changed how cultures spread a lot, so if you for example is playing an African civ and conquer an European city where you then train a settler, the new city that settler found will gain the European culture instead of the African culture.
Several cultures can accompany a settler from the city it is trained in, but only cultures that exist locally in that city. Spreading new local cultures to a city requires the new culture to be adopted by your civ nationally, then you will be able to construct the local culture in a city that doesn't have it, each local culture built in your nation increase the hammer cost of building another local culture in a city, and building one European local culture increase the cost of the next European local culture less than it increases the cost for a different culture group like African.
When you get enough foreign local cultures a specific autobuild will appear that signifies that that new culture has been adopted, the amount needed scales by the map size.
It's all a bit complex though, there's a local culture building that can be built if the culture is active in your civ, a native culture building, an adopted culture building, and an active culture building, as well as a special version of the native culture building that follows the palace around based on what civ you started your game with. One of each of those buildings exist per native culture type in the game. ^^

@Anq: I'm still not convinced that it's a good idea to use the DOM format for any tags that use the expression system...
Is it possible to mix the current format and the DOM format so that some tags use DOM while others, like those with the expression system, keep the current format?
Some of them can be quite complex like this one:
Spoiler example from C2C :
Code:
                <PropertyPropagator>
                    <PropertyPropagatorType>PROPERTYPROPAGATOR_DIFFUSE</PropertyPropagatorType>
                    <PropertyType>PROPERTY_WATER_POLLUTION</PropertyType>
                    <GameObjectType>GAMEOBJECT_PLOT</GameObjectType>
                    <TargetObjectType>GAMEOBJECT_PLOT</TargetObjectType>
                    <TargetRelationType>RELATION_NEAR</TargetRelationType>
                    <iTargetDistance>1</iTargetDistance>
                    <iPercent>4</iPercent>
                    <TargetCondition>
                        <Or>
                            <Is>TAG_WATER</Is>
                            <Is>TAG_FRESH_WATER</Is>
                            <Is>TAG_CITY</Is>
                        </Or>
                    </TargetCondition>
                    <Active>
                        <Not>
                            <Or>
                                <Has>
                                    <GOMType>GOM_TERRAIN</GOMType>
                                    <ID>TERRAIN_OCEAN</ID>
                                </Has>
                                <Has>
                                    <GOMType>GOM_TERRAIN</GOMType>
                                    <ID>TERRAIN_OCEAN_TROPICAL</ID>
                                </Has>
                                <Has>
                                    <GOMType>GOM_TERRAIN</GOMType>
                                    <ID>TERRAIN_OCEAN_POLAR</ID>
                                </Has>
                                <Has>
                                    <GOMType>GOM_TERRAIN</GOMType>
                                    <ID>TERRAIN_TRENCH</ID>
                                </Has>
                                <Has>
                                    <GOMType>GOM_TERRAIN</GOMType>
                                    <ID>TERRAIN_TRENCH_POLAR</ID>
                                </Has>
                                <Has>
                                    <GOMType>GOM_TERRAIN</GOMType>
                                    <ID>TERRAIN_TRENCH_TROPICAL</ID>
                                </Has>
                            </Or>
                        </Not>
                    </Active>
                </PropertyPropagator>
Condensing that stuff too much will be horrific to work with, both to read and to write.
 
Last edited:
  • Like
Reactions: Anq
@Dancing Hoskuld, If it's a good validator, it will compare against everything from the schema that's standard to the specification on the schema's header,
Code:
<Schema xmlns="urn:schemas-microsoft-com:xml-data" xmlns:dt="urn:schemas-microsoft-com:datatypes">
So that it will automatically validate the tag attributes if we supply with correct schema information (see previous post).
This is why it can be used by any Civ IV mod no matter how different to C2C they are.
I guess then, our mod components would not be easily graft-able to other mod projects, and so do the mod components outside C2C that we want to integrate. This is a serious hit. Unless the new system gets broadly adopted across the Civ4 community ...

Some of them can be quite complex like this one: [...]
I suggest to break the negator onto individual statements, that Not(Any) becomes All(Not), see my previous example. But then, it's better at this stage to not get the expression system involved.
 
Last edited:
Top Bottom