Missing values
Why a rule silently never fires — null loses every comparison, including <.
This page exists because it is the single most common way a correct-looking rule does nothing at all, forever, with no error anywhere.
A stat is 0. A field is null.
$.stat('nonsense') // 0
$.field('nonsense') // null
That difference is the whole page.
null loses every comparison
Including the ones you would expect it to win:
null < 5 // false
null > 5 // false
null == 0 // false
So a character with no infection field does not satisfy infection < 5.
That is usually what you want — it is what stops a cure-the-infected rule from firing on every healthy person in the world. But if you wrote that rule expecting it to catch everyone, it fires on nobody and looks broken.
The symptom
A rule that never fires, no error, nothing in any log. Because:
- reading a missing path gives
undefined conditionSatisfiedtreatsundefinedas "the gate does not open"- an expression that throws evaluates to nothing, and the caller uses its default
Three separate mechanisms, all of which turn a mistake into silence. Editor completion only offers paths that exist, which is your first defence — if you typed a path by hand and it is not in the completion list, that is the bug.
Getting it right
Ask whether the field exists, when "nobody has this yet" should count:
!$.hasField('infection') || $.field('infection') < 5
Give it a floor, when you want a missing field to read as zero:
($.field('infection') || 0) + 1
Check the plugin is installed, when the field belongs to someone else:
$.hasPlugin('hunger') && $.field('satiety') < 20
Why not just make missing fields 0?
Because 0 is a real value with real meaning. A satiety of 0 means starving; a satiety
of null means this game has no hunger system. Collapsing those would make every
character in a game without hunger permanently starving, which is exactly the bug that
$.hasPlugin() exists to prevent.
Next
Conditions — where these checks live.