The Interpolation of "not"

Discussion in 'Modding' started by Ftoomsh, Nov 18, 2019.

  1. Ftoomsh

    Ftoomsh Well-Known Member

    During one of the last big patches over a year ago, IIRC, a lot of expressions had "not" interpolated or added into them.

    For example an expression in a line of code like;

    and (gPlayer[plind].res[pricetype]>=price)

    would have to become

    and (not gPlayer[plind].res[pricetype]>=price)


    Why did this happen? What coding, logic or even language syntax change necessitated this change to so many lines?

    The full example of the above is;

    [*] = ; if (_misc_CanPlaceBuilding(goHnd, plind, usage, px, pz, gc_path_mincoldist, 0.26, 0.5, gc_path_minemincoldist, True)) and (gPlayer[plind].res[pricetype]>=price) then

    needing to become

    [*] = ; if (_misc_CanPlaceBuilding(goHnd, plind, usage, px, pz, gc_path_mincoldist, 0.26, 0.5, gc_path_minemincoldist, True)) and (not gPlayer[plind].res[pricetype]>=price) then


    Admittedly this example is from Wralth's Cossacks Annihilation. The second expression now works. The first does not. But since I will put this wall cost fix into OCMOD3 (now running again in a new version) it is still of interest, at least to me, to understand this logic change. It almost seems like a change in the syntax rules of the language or a change in some global definition in scripts. It has me a little baffled.
     
    Last edited: Nov 18, 2019
  2. Awar

    Awar Well-Known Member

    In the mod "state_vs_country" I did not add such changes in the logic. In my opinion this is a diversion for the creation of mods.:)
     
  3. Ftoomsh

    Ftoomsh Well-Known Member

    You may not have added such changes in logic (or syntax) but the vanilla certainly did, in many places somewhat over a year ago. These changes matter syntactically and logically.

    This line used to work in older mods more than a year ago.

    [*] = ; if (_misc_CanPlaceBuilding(goHnd, plind, usage, px, pz, gc_path_mincoldist, 0.26, 0.5, gc_path_minemincoldist, True)) and (gPlayer[plind].res[pricetype]>=price) then

    It does not work now. Instead it has to be coded as follows.

    [*] = ; if (_misc_CanPlaceBuilding(goHnd, plind, usage, px, pz, gc_path_mincoldist, 0.26, 0.5, gc_path_minemincoldist, True)) and (not gPlayer[plind].res[pricetype]>=price) then

    If it is not coded with the not now it does not work. If it is coded with the not it does work as intended. As I said, I am struggling to understand this.

    Essentially each line is saying "If CAN PLACE the wall block is TRUE and If CAN AFFORD the wall block is TRUE then (place and build the wall block). Yet one line has a not added which would normally alter the logic at that point to its inverse. I am wondering if the syntax of the script language underwent an update at that time such that for a statement using equal to, not equal to, greater than, less than etc, to return a TRUE / FALSE result it has to be prefaced by not. I don't know. I am grasping at straws here. Either that or the statement has to use if or brackets in different ways to avoid the need for the not.

    Would either of these work I wonder? I guess I should test them.

    [*] = ; if (_misc_CanPlaceBuilding(goHnd, plind, usage, px, pz, gc_path_mincoldist, 0.26, 0.5, gc_path_minemincoldist, True)) and if (gPlayer[plind].res[pricetype]>=price) then


    [*] = ; if ((_misc_CanPlaceBuilding(goHnd, plind, usage, px, pz, gc_path_mincoldist, 0.26, 0.5, gc_path_minemincoldist, True)) and (gPlayer[plind].res[pricetype]>=price)) then

    UPDATE: Nope neither of these work in tests. So it appears the "not" logic to "and" true statements in an if statement is unavoidable. What am I missing here? A decent brain probably. :confused:
     
    Last edited: Nov 18, 2019
  4. Which file you're talking about? I can not find such line in vanilla? writewall.inc? There's no price code there as far as I can see

    PS1: Nevertheless the language (which is practically dead) had not changed recently. I would rather look at the context of the line, i.e. condition in which this line is executed which could have become nagated after patch.
    PS2: the file must have changed before December 2017 (no changes afterwards)
     
  5. Ftoomsh

    Ftoomsh Well-Known Member

    Your PS1 is correct when you say "I would rather look at the context of the line, i.e. condition in which this line is executed which could have become negated after patch."

    Please follow the story below which proves your PS1 comment is correct. The question becomes why did they do this?

    I started talking about writewall.inc but not from vanilla. This writewall.inc is from the mod Cossacks Annihilation by Wralth. Since the initial cost of wall sections does not work in vanilla (you can test it in vanilla because it still does not work to this day), Wralth built a fix into his mod. He amended readwall.inc and writewall.inc to ensure the initial cost of wall sections (stone and wood) does get applied. In other words so that the player pays for putting up the walls. The ongoing maintenance costs of walls does work in vanilla by the way but not the initial cost.

    When this fix was created by Wralth the line worked as this;

    [*] = ; if (_misc_CanPlaceBuilding(goHnd, plind, usage, px, pz, gc_path_mincoldist, 0.26, 0.5, gc_path_minemincoldist, True)) and (gPlayer[plind].res[pricetype]>=price) then


    To make it work now in exactly the same way I had to render it as this;

    [*] = ; if (_misc_CanPlaceBuilding(goHnd, plind, usage, px, pz, gc_path_mincoldist, 0.26, 0.5, gc_path_minemincoldist, True)) and (not gPlayer[plind].res[pricetype]>=price) then


    I understand that adding not does a true/false logic reversal as in not true = false. But why is a reversal of logic now required unless somehow the result of the expression gPlayer[plind].res[pricetype] had suffered a logic reversal outcome in definition which then needed to be reversed in turn?

    Have a look at some cost processing in unit.script. The old unit.script before the big patch I am talking about had code like this in function _unit_CanApplyCountCostByID

    Result := ((gPlayer[plInd].res[gc_resource_type_food]>=food)
    and (gPlayer[plInd].res[gc_resource_type_wood]>=wood)
    and (gPlayer[plInd].res[gc_resource_type_stone]>=stone)
    and (gPlayer[plInd].res[gc_resource_type_gold]>=gold)
    and (gPlayer[plInd].res[gc_resource_type_iron]>=iron)
    and (gPlayer[plInd].res[gc_resource_type_coal]>=coal));
    end;

    The new unit.script after the big patch I am talking about had this coded as

    Result := ((not gPlayer[plInd].res[gc_resource_type_food]>=food)
    and (not gPlayer[plInd].res[gc_resource_type_wood]>=wood)
    and (not gPlayer[plInd].res[gc_resource_type_stone]>=stone)
    and (not gPlayer[plInd].res[gc_resource_type_gold]>=gold)
    and (not gPlayer[plInd].res[gc_resource_type_iron]>=iron)
    and (not gPlayer[plInd].res[gc_resource_type_coal]>=coal));


    Why this logic change?

    If we then search for applications of _unit_CanApplyCountCostByID we might find it has not added to reverse the reversal above. I will go and check this and then update this post.

    Update:

    It seems this is true. The old vanilla progresseconomicai.inc had;

    [*] = ; if (gPlayer[plind].res[gc_resource_type_gold] < 400) then
    [*] = ; begin
    [*] = ; if _ai_NationIsEurope(cid) then
    [*] = ; _ai_TryUnit(plind, cid, gc_ai_unit_minegold, 2, False)
    [*] = ; else
    [*] = ; _ai_TryUnit(plind, cid, gc_ai_unit_minegold, 1, False);
    [*] = ; end
    [*] = ; else
    [*] = ; _ai_TryUnit(plind, cid, gc_ai_unit_minegold, 1, False);
    [*] = ; if gPlayer[plind].res[gc_resource_type_iron] < 300 then
    [*] = ; _ai_TryUnit(plind, cid, gc_ai_unit_mineiron, 1, False);
    [*] = ; if gPlayer[plind].res[gc_resource_type_coal] < 300 then
    [*] = ; begin
    [*] = ; if (_ai_GetUnitCount(plind, cid, gc_ai_unit_mineiron)>=1) then
    [*] = ; _ai_TryUnit(plind, cid, gc_ai_unit_minecoal, 1, False)
    [*] = ; else
    [*] = ; if gPlayer[plind].res[gc_resource_type_iron] < 1000 then

    The new vanilla one has;


    [*] = ; if (not gPlayer[plind].res[gc_resource_type_gold] < 400) then
    [*] = ; begin
    [*] = ; if _ai_NationIsEurope(cid) then
    [*] = ; _ai_TryUnit(plind, cid, gc_ai_unit_minegold, 2, False)
    [*] = ; else
    [*] = ; _ai_TryUnit(plind, cid, gc_ai_unit_minegold, 1, False);
    [*] = ; end
    [*] = ; else
    [*] = ; _ai_TryUnit(plind, cid, gc_ai_unit_minegold, 1, False);
    [*] = ; if not gPlayer[plind].res[gc_resource_type_iron] < 300 then
    [*] = ; _ai_TryUnit(plind, cid, gc_ai_unit_mineiron, 1, False);
    [*] = ; if not gPlayer[plind].res[gc_resource_type_coal] < 300 then
    [*] = ; begin
    [*] = ; if (_ai_GetUnitCount(plind, cid, gc_ai_unit_mineiron)>=1) then
    [*] = ; _ai_TryUnit(plind, cid, gc_ai_unit_minecoal, 1, False)
    [*] = ; else
    [*] = ; if not gPlayer[plind].res[gc_resource_type_iron] < 1000 then

    This seems to fit the pattern of a true/false logic reversal in the original function definition and then a true/false logic reversal in the application of the function. These reversals cancel out and now the piece of coding immediately above does what the piece of coding above it used to do. But why program like this? Isn't it enormously confusing? Was this a kludge to fix a bug that required more re-coding if done another way? Surely it was not done just to confuse modders but it has certainly confused me.
     
    Last edited: Nov 18, 2019
  6. Awar

    Awar Well-Known Member

    Before the big patch I had an old version of the game.
    I month changed the code in the mod back to return to the old logic.
    I didn't see a visible reason why the developers did it.
    This is very strange, contrary to common sense.
     
  7. Ftoomsh

    Ftoomsh Well-Known Member

    It's almost like they wanted to trip modders up. I don't want to believe that so I hope there is some other explanation.
     
  8. Awar

    Awar Well-Known Member

    I had a similar thought, but I had no choice.
     
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice