Freeciv requirements and formal logic
Posted: Wed Mar 05, 2014 11:52 am
Freeciv rule set concepts can be translated to formal logic. Formal logic can easily be transformed using the laws of logic or using software that use them. This is useful when you need to convert a rule set since it allow you to express the rules that Freeciv understands can be transformed into another way of expressing the rules that Freeciv understands via something Freeciv don't understands.
Based on Murphy's law I'm sure that this post about logic contains logical mistakes.
Introduction to logic
A statement can be true or false. Examples of statements are and . A statement can be named. is a way of saying that when you see think . Just like you can add and multiply numbers you can create new statements from existing statements. is a way of saying that X is true if both X and Y are true. If one of them or both are false X is false too. is a way of saying that X is true if one of Y or Z are true. If both Y and Z are true X is true too. is a way of saying that X is true if Y is false and false if Y is true.
Simple requirements
The Freeciv requirement vector translated to logic is since both must be true for the requirement vector to be true.
The requirement vector is A Freeciv requirement vector in it self can only represent && (and) and ! (not).
More than one requirement vector
Some effect typed only care if their value is above 0 or not. Unless the rule set author have used negative numbers as effect values translating an effect like that to logic is simple. Say that there are two effects of the same type. The requirement vector of the first is and the requirement vector of the second is . Since the effect will be triggered as long as one of them is true their translation to logic is If the rule set autor did use negative numbers more math is required to translate the effect.
How to use this for conversion
An effect, let us call it No_Incite, makes it impossible to incide a city to change side. The action enabler "Incite City" has target requirements that test if a city can be incited. The goal is to make the action enabler behave like the effect.
The first step is to transform all No_Incite effects to logic. Say that there are two effects that both have exactly one requirement. The requirement of the first effect is Republic. The requirement of the second is Democracy. The result is.
The second step is to translate the action enabler to formal logic. Since this effect was about the target city and not the attacker only the target requirement vector need translation. Say it is. In logic that is
The third step is to combine them. Remember that the target requirement on the action enabler is to enable the action while the requirements on the effect is to disable it. The action can be done if it isn't true that the effect is active. In logic this is .
The final step is to convert everything back to something Freeciv understands. I will here do it by hand.
Insert the statements of the names target and No_Incite:
In logic (A && B) && C is the same as A && B && C:
!(A || B) is the same as !A && !B:
Since only && (and) and ! (not) is used here this can be translated to the requirement vector:
Had there been an || (or) in the end result, something that more than one requirement in the vector for an effect of the No_incite type would cause, one action enabler wouldn't have been enough.
Based on Murphy's law I'm sure that this post about logic contains logical mistakes.
Introduction to logic
A statement can be true or false. Examples of statements are
Code: Select all
Socrates is a man
Code: Select all
"MinSize", "2", "City"
Code: Select all
X = "MinSize", "2", "City"
Code: Select all
X
Code: Select all
"MinSize", "2", "City"
Code: Select all
X = Y && Z
Code: Select all
X = Y || Z
Code: Select all
X = !Y
Simple requirements
The Freeciv requirement vector
Code: Select all
{ "type", "name", "range"
"DiplRel", "War", "Local"
"UnitFlag", "Spy", "Local"
}
Code: Select all
("DiplRel", "War", "Local") && ("UnitFlag", "Spy", "Local")
The requirement vector
Code: Select all
{ "type", "name", "range", "present"
"DiplRel", "War", "Local", TRUE
"UnitFlag", "Spy", "Local", FALSE
}
Code: Select all
("DiplRel", "War", "Local") && !("UnitFlag", "Spy", "Local")
More than one requirement vector
Some effect typed only care if their value is above 0 or not. Unless the rule set author have used negative numbers as effect values translating an effect like that to logic is simple. Say that there are two effects of the same type. The requirement vector of the first is
Code: Select all
{ "type", "name", "range"
"Gov", "Republic", "Player"
}
Code: Select all
{ "type", "name", "range", "present"
"Gov", "Democracy", "Player", TRUE
"DiplRel", "War", "Local", FALSE
}
Code: Select all
("Gov", "Republic", "Player") || (("Gov", "Democracy", "Player") && !("DiplRel", "War", "Local"))
How to use this for conversion
An effect, let us call it No_Incite, makes it impossible to incide a city to change side. The action enabler "Incite City" has target requirements that test if a city can be incited. The goal is to make the action enabler behave like the effect.
The first step is to transform all No_Incite effects to logic. Say that there are two effects that both have exactly one requirement. The requirement of the first effect is Republic. The requirement of the second is Democracy. The result is
Code: Select all
No_Incite = ("Gov", "Republic", "Player") || ("Gov", "Democracy", "Player")
The second step is to translate the action enabler to formal logic. Since this effect was about the target city and not the attacker only the target requirement vector need translation. Say it is
Code: Select all
{ "type", "name", "range", "present"
"DiplRel", "Alliance", "Local", FALSE
"DiplRel", "Team", "Local", FALSE
}
Code: Select all
target = (!("DiplRel", "Alliance", "Local") && !("DiplRel", "Team", "Local", FALSE))
Code: Select all
merged_target = target && !No_Incite
The final step is to convert everything back to something Freeciv understands. I will here do it by hand.
Code: Select all
merged_target = target && !No_Incite
Code: Select all
merged_target = (!("DiplRel", "Alliance", "Local") && !("DiplRel", "Team", "Local", FALSE)) && !(("Gov", "Republic", "Player") || ("Gov", "Democracy", "Player"))
Code: Select all
merged_target = !("DiplRel", "Alliance", "Local") && !("DiplRel", "Team", "Local", FALSE) && !(("Gov", "Republic", "Player") || ("Gov", "Democracy", "Player"))
Code: Select all
merged_target = !("DiplRel", "Alliance", "Local") && !("DiplRel", "Team", "Local", FALSE) && !("Gov", "Republic", "Player") && !("Gov", "Democracy", "Player")
Code: Select all
{ "type", "name", "range", "present"
"DiplRel", "Alliance", "Local", FALSE
"DiplRel", "Team", "Local", FALSE
"Gov", "Democracy", "Player", FALSE
"Gov", "Republic", "Player", FALSE
}