In eudplib one if compiles into two triggers: a branch trigger and a jump trigger. Why it needs two follows from what a trigger can do - it can run actions when its condition is true, and there is no way to make it do something when the condition is false.
brtrg = RawTrigger(nextptr = onfalse, conditions = ..., actions = SetNextPtr(brtrg, tjtrg)); tjtrg = RawTrigger(nextptr = ontrue, actions = SetNextPtr(brtrg, onfalse));
So the cost is asymmetric. The false path is 1 trigger and 0 actions; the true path is 2 triggers and 2 actions.
In classic triggers “do something when this is false” was the awkward side. In eudplib it inverts: write the condition so that the case that happens most often lands on the false branch. The same logic, with the condition turned around, costs less than half.
| EUDWhile + '아직 순환 중' | 2 triggers and 2 actions per live unit. |
|---|---|
| EUDWhileNot + '순환이 끝났음' | 1 trigger and 0 actions per live unit. |
| EUDIfNot + '유닛이 살아있음' | Filtered out only after spending 2 triggers and 2 actions. |
| EUDIf + '유닛이 죽었음' | Filtered out in 1 trigger and 0 actions. |
A unit is alive for its whole life and dead for one cycle, so in both pairs the second form is the right one - and the saving is per unit, per cycle, which is exactly where a unit loop's budget goes.
The rule is the same in any hot loop: state the rare case as the condition.
Everything is a trigger