"or" at check_requirement_met does not work (it is using the "and" logic)

At stonehearth/services/server/game_master/controllers/node.lua

There is the function Node:check_requirement_met(ctx, name, rule)

Inside it there is this code snippet:

   elseif item == 'or' then
      local and_rules = rule.value
      local passes = true
      for _, rule in pairs(and_rules) do
         passes = false
         if self:_all_rules_pass(ctx, rule) then
            passes = true
            break
         end
      end

      lhs = true
      rhs = passes

If you check that code logic, you will see that it is the same from the “and” rule. Both are calling the function Node:_all_rules_pass(ctx, can_start_rules)

In that function, only when all requirements are met it returns true. This makes it impossible for this piece of code to work (my .json encounter)

{
   "type": "encounter",
   "encounter_type": "wait_for_requirements_met",
   "in_edge"  : "wait_first_soldier",
   "out_edge" : "miranda_before_selling_clay",
   "wait_for_requirements_met_info": {
      "requirements": {
         "or": {
            "item": "or",
            "type":"deny_if_not",
            "value": {
               "value": {
                  "has_soldier": {
                     "item": "script",
                     "type": "deny_if_less_than",
                     "value": 1,
                     "script": "file(has_soldier.lua)"
                  },
                  "is_peaceful": {
                     "item": "game_mode",
                     "type": "deny_if_not",
                     "value": "stonehearth:game_mode:peaceful"
                  }
               }
            }
         }
      }
   }
}

The logic of my encounter is:
Go to the next encounter only if you have a soldier. If you are in peaceful (which does not require that job) progress anyway even without the soldier.

You might be right (I haven’t actually tested this), but the code is slightly different for AND and OR.
I think _all_rules_pass is called for every rule individually.
For the AND snippet, it verifies that at least one of them is false.
For the OR snippet, it verifies that at least one of them is true.

Did you try removing the second “value” so that the rules are directly inside the first “value”?

It actually requires both values (it can have any name though, I repeated by laziness), because in the all_rules_pass it is looking one more step deeper into the structure. At first I did like you suggested, and it was not working, reading the code I understood that that structures is required…

The problem is that there is a loop there that checks for at least one true value, like you mentioned, but there is another loop inside checking for all rules… There is a lot of problems in that code.

1 Like

Ok, will file a report for this.
Thanks for reporting! :slight_smile:

Thanks!
For now, I think I can replace all this by using a custom script encounter where the script itself would check if any of the requirements are met.

Thanks the for helpfully detailed bug report! I’ve fixed that and restructured the way the tests are iterated over, so the new structure will look like:

   "wait_for_requirements_met_info": {
      "requirements": {
         "or": {
            "item": "or",
            "type":"deny_if_not",
            "value": true,
            "tests": {
               "and": {
                  "item": "and",
                  "type": "deny_if_not",
                  "value": true,
                  "tests": {
                     "military_score": {
                        "item": "score",
                        "score_type": "military_score",
                        "type": "deny_if_less_than",
                        "value": 5
                     },
                     "net_worth_requirement": {
                        "item": "net_worth",
                        "type": "deny_if_less_than",
                        "value": 10000
                     }
                  }
               },
               "is_peaceful": {
                  "item": "game_mode",
                  "type": "deny_if_not",
                  "value": "stonehearth:game_mode:peaceful"
               }
            }
         }
      },
      "recheck_delay": "8h"
   }
}

the tests are put under “tests” instead of value, and you no longer need to double nest the “value” field.

Though this probably won’t be included until our push to A21 unstable.

  • Linda
3 Likes

Thanks Linda! :jubilant:

1 Like