The Expression System

Code:
  <Actions>
                <Action>
                    <MissionType>MISSION_POISON_ARROWS</MissionType>
                    <ActionOutcomes>                      
                      <Outcome>
                       <UnitCondition>
                             <Or>
                                <Has>
                                     <GOMType>GOM_UNITCOMBAT</GOMType>
                                    <ID>UNITCOMBAT_RECON</ID>
                                </Has>
                                <Has>
                                     <GOMType>GOM_UNITCOMBAT</GOMType>
                                    <ID>UNITCOMBAT_ARCHER</ID>
                                </Has>
                                <Has>
                                     <GOMType>GOM_UNITCOMBAT</GOMType>
                                    <ID>UNITCOMBAT_MELEE</ID>
                                </Has>
                            </Or>
                        </UnitCondition>
                            <OutcomeType>OUTCOME_POISON_ARROWS</OutcomeType>
                            <iChance>100</iChance>
                            <PromotionType>PROMOTION_POISON_ARROWS</PromotionType>
                        </Outcome>
                    </ActionOutcomes>
                </Action>
            </Actions>

Something like this AIAndy?
 
Little lessons like this really help in understanding the expression system. Especially for the uneducated/untrained modder like me. Thank you. :)
 
KillOutcomes and ActionOutcomes use the same code so in principle anything that works for one should work for the other.
Well, it didn't work for me with AO only with KO. Will try again.
 
Yet another question... or two:

1) Can this system check for eras? I'd like to create a building that you can build 1 copy in each era. Like a National Wonder that allows an extra copy in every era.

2) Can it check for tile revealing. I'm thinking of a new Great Explorer great person that accumulates GPs for every revealed black tile.
 
Yet another question... or two:

1) Can this system check for eras? I'd like to create a building that you can build 1 copy in each era. Like a National Wonder that allows an extra copy in every era.

2) Can it check for tile revealing. I'm thinking of a new Great Explorer great person that accumulates GPs for every revealed black tile.
Neither of those have been exposed to the expression system, for 1) you could use key techs instead as those can be queried or someone would have to add GOM_ERA.
 
Neither of those have been exposed to the expression system, for 1) you could use key techs instead as those can be queried or someone would have to add GOM_ERA.
We just setup the bottleneck gateway techs for each era this version so yeah, that would be the easiest way to achieve the result.
 
1) Well, I thought of key techs as well, so that's not the real question, rather the limit.
I'm thinking something like this:

can build IF [((building=0) AND (tech=alphabet)) OR ((building=1) AND (tech=literature)) OR etc.]

The problem is that that you always have at least 0 of a given building so it has to check for the exact number.
So the question is: Does it check for 'equal' or for 'equal or greater' ?

2) I guess it's also not possible to have certain units automatically generate :gp:/turn IF outside border, right?
Or units to automatically generate :gp:/turn at all, right?
 
1) Well, I thought of key techs as well, so that's not the real question, rather the limit.
I'm thinking something like this:

can build IF [((building=0) AND (tech=alphabet)) OR ((building=1) AND (tech=literature)) OR etc.]

The problem is that that you always have at least 0 of a given building so it has to check for the exact number.
So the question is: Does it check for 'equal' or for 'equal or greater' ?
There are several comparison operators available. So you can count the building number and compare it to the max number you get from if tech.
I don't have access to the source code at the moment so I can't give you the exact names of the tags. Or it would be even easier if the max building number was an IntExpr tag which I don't know if it is (probably not though).
 
Does this look good?
Code:
<ConstructCondition>
    <Or>
        <And>
            <Has>
                <GOMType>GOM_TECH</GOMType>
                <ID>tech_1</ID>
            </Has>
            <Equal>
                <IntegrateCount>
                    <RelationType>RELATION_ASSOCIATED</RelationType>
                    <GameObjectType>GAMEOBJECT_PLAYER</GameObjectType>
                    <Has>
                        <GOMType>GOM_BUILDING</GOMType>
                        <ID>building</ID>
                    </Has>
                </IntegrateCount>
                <Constant>0</Constant>
            </Equal>
        </And>       
        <And>
            <Has>
                <GOMType>GOM_TECH</GOMType>
                <ID>tech_2</ID>
            </Has>
            <Equal>
                <IntegrateCount>
                    <RelationType>RELATION_ASSOCIATED</RelationType>
                    <GameObjectType>GAMEOBJECT_PLAYER</GameObjectType>
                    <Has>
                        <GOMType>GOM_BUILDING</GOMType>
                        <ID>building</ID>
                    </Has>
                </IntegrateCount>
                <Constant>1</Constant>
            </Equal>
        </And>       
    </Or>
</ConstructCondition>
To my understanding this would allow a maximal 2 instances of that building:
The 1st tech_1, the 2nd with tech_2 and than no 3rd one allowed.
 
Does this look good?
Code:
<ConstructCondition>
    <Or>
        <And>
            <Has>
                <GOMType>GOM_TECH</GOMType>
                <ID>tech_1</ID>
            </Has>
            <Equal>
                <IntegrateCount>
                    <RelationType>RELATION_ASSOCIATED</RelationType>
                    <GameObjectType>GAMEOBJECT_PLAYER</GameObjectType>
                    <Has>
                        <GOMType>GOM_BUILDING</GOMType>
                        <ID>building</ID>
                    </Has>
                </IntegrateCount>
                <Constant>0</Constant>
            </Equal>
        </And>      
        <And>
            <Has>
                <GOMType>GOM_TECH</GOMType>
                <ID>tech_2</ID>
            </Has>
            <Equal>
                <IntegrateCount>
                    <RelationType>RELATION_ASSOCIATED</RelationType>
                    <GameObjectType>GAMEOBJECT_PLAYER</GameObjectType>
                    <Has>
                        <GOMType>GOM_BUILDING</GOMType>
                        <ID>building</ID>
                    </Has>
                </IntegrateCount>
                <Constant>1</Constant>
            </Equal>
        </And>      
    </Or>
</ConstructCondition>
To my understanding this would allow a maximal 2 instances of that building:
The 1st tech_1, the 2nd with tech_2 and than no 3rd one allowed.
Close. The IntegrateCount would not quite work like that as you need to count the cities that have that building of the same player and like this it would count players.
So the Integrate part should first move from the city (on which the ConstructCondition is evaluated) to the owning player and from there count the cities. IntegrateSum will help with the first part (it will not actually sum up anything as there is only one related player).
Code:
<IntegrateSum>
    <RelationType>RELATION_ASSOCIATED</RelationType>
    <GameObjectType>GAMEOBJECT_PLAYER</GameObjectType>
    <IntegrateCount>
        <RelationType>RELATION_ASSOCIATED</RelationType>
        <GameObjectType>GAMEOBJECT_CITY</GameObjectType>
        <Has>
            <GOMType>GOM_BUILDING</GOMType>
            <ID>building</ID>
        </Has>
    </IntegrateCount>
</IntegrateSum>
The integrate part is a bit expensive as it actually iterates over all cities of the player, so it should only be present once in the expression. That is why I would change it to something like that:
Code:
<ConstructCondition>
    <Greater>
        <If>
            <Has>
                <GOMType>GOM_TECH</GOMType>
                <ID>tech_2</ID>
            </Has>
            <Constant>2</Constant>
            <If>
                <Has>
                    <GOMType>GOM_TECH</GOMType>
                    <ID>tech_1</ID>
                </Has>
                <Constant>1</Constant>
                <Constant>0</Constant>
            </If>
        </If>
        Add the integrate stuff here
    </Greater>
</ConstructCondition>
 
Can this system count the number of trade routes a city has? If so, how?
I'd like to have buildings that require a number of trade routes in a city, which can obviously come from different sources.
 
There is RELATION_TRADE which can be used to count the cities that have RELATION_TRADE (a trade route) with the current one. To get the count you can use IntegrateSum (sums up an integer value for each related city, so with the constant 1 as value you just count) or IntegrateCount (counts related cities for which a boolean expression is true, so with 1 meaning true you count all related cities).

Code:
<IntegrateCount>
  <RelationType>RELATION_TRADE</RelationType>
  <GameObjectType>GAMEOBJECT_CITY</GameObjectType>
  <Constant>1</Constant>
</IntegrateCount>

You can then use Greater or similar.
 
Last edited:
There is RELATION_TRADE which can be used to count the cities that have RELATION_TRADE (a trade route) with the current one. To get the count you can use IntegrateSum (sums up an integer value for each related city, so with the constant 1 as value you just count) or IntegrateCount (counts related cities for which a boolean expression is true, so with 1 meaning true you count all related cities).

You can then use Greater or similar.
I was aware of RELATION_TRADE but was clueless whether it can do what I wish or not. I searched through C2C files but found nothing related. :)
So the code would be this if I wanted the building to have at least 2 Trade Routes as a requirement? Or something else is missing/wrong?
Code:
<ConstructCondition>
<GreaterEqual>
<IntegrateCount>
  <RelationType>RELATION_TRADE</RelationType>
  <GameObjectType>GAMEOBJECT_CITY</GameObjectType>
  <Constant>2</Constant>
</IntegrateCount>
</GreaterEqual>
</ConstructCondition>
 
I was aware of RELATION_TRADE but was clueless whether it can do what I wish or not. I searched through C2C files but found nothing related. :)
So the code would be this if I wanted the building to have at least 2 Trade Routes as a requirement? Or something else is missing/wrong?
Close, but this needs an additional Constant. The Constant in the IntegrateCount is actually the condition if this trade route target city should be counted or not.
So it should be like this:
Code:
<ConstructCondition>
  <GreaterEqual>
    <IntegrateCount>
      <RelationType>RELATION_TRADE</RelationType>
      <GameObjectType>GAMEOBJECT_CITY</GameObjectType>
      <Constant>1</Constant>
    </IntegrateCount>
    <Constant>2</Constant>
  </GreaterEqual>
</ConstructCondition>
 
Ahaaa... I think I start to understand the maths of it:
The first constant is a multiplier, right?
The above code means:
[:traderoute:*1] >= 2 Right?
Understanding the code may help in the future :)
Great thx for the help :goodjob:
 
Ahaaa... I think I start to understand the maths of it:
The first constant is a multiplier, right?
The above code means:
[:traderoute:*1] >= 2 Right?
Understanding the code may help in the future :)
Great thx for the help :goodjob:
In the case of IntegrateCount, the constant is actually a condition. You could put anything there that you could put in ConstructCondition and only if the condition evaluates to true, the city is counted.
So if instead of the Constant you put a Has building Palace there, you would only count all trade routes to capitals.
 
In the case of IntegrateCount, the constant is actually a condition. You could put anything there that you could put in ConstructCondition and only if the condition evaluates to true, the city is counted.
So if instead of the Constant you put a Has building Palace there, you would only count all trade routes to capitals.
Great! In the first pages I saw something like that.
One more thing. Or two:
  1. Can it check if your city is connected to a foreign unhappy city? I think I so something "foreign" related but nothing "happiness/unhappiness" related.
  2. These stuff can only do a "can build it" thing but not an "activate/inactivate the building" like the regular civic or resource requirements, right?
 
Great! In the first pages I saw something like that.
One more thing. Or two:
  1. Can it check if your city is connected to a foreign unhappy city? I think I so something "foreign" related but nothing "happiness/unhappiness" related.
  2. These stuff can only do a "can build it" thing but not an "activate/inactivate the building" like the regular civic or resource requirements, right?
1 would need something like RELATION_TRADE_FOREIGN which does not exist and while you can get the number of happy people and population number, the number of unhappy people is not exposed.
2 would need something like an ActiveCondition, but something similar can be done by having autobuilt buildings with the correct ConstructCondition.
 
Top Bottom