increpare / PuzzleScript

Open Source HTML5 Puzzle Game Engine
MIT License
903 stars 159 forks source link

early-outing of rulegroup applciation if you've completed a full cycle #740

Closed increpare closed 3 years ago

increpare commented 3 years ago

cf https://github.com/increpare/PuzzleScript/issues/731

increpare commented 3 years ago

So I implemented this but I had to construct a really artifical example to get any kind of measurable performance boost

A level with lots of players, and

right [ action player | crate ] -> [ left player | crate ]
+ right [  crate | ...| left player ] -> [ | ... | ] (repeated ~300 times)

https://www.puzzlescript.net/editor.html?hack=49afed3131fb639d3324d50cfa7acc33

goes from 100ms to ~90ms

Given the tenuous benefits vs increased complexity, I guess I shouldn't implement this optimisation?

For future reference for future increpare, here's how I did it (though maybe clement's approach is better, it's probably much of a muchness):

function applyRuleGroup(ruleGroup) {
    if (ruleGroup[0].isRandom) {
        return applyRandomRuleGroup(ruleGroup);
    }

    var loopPropagated=false;
    var propagated=true;
    var loopcount=0;
    var nothing_happened_counter = -1;
    while(propagated) {
        loopcount++;
        if (loopcount>200) 
        {
            logErrorCacheable("Got caught looping lots in a rule group :O",ruleGroup[0].lineNumber,true);
            break;
        }
        propagated=false;

        var last_applied = null
        for (var ruleIndex=0;ruleIndex<ruleGroup.length;ruleIndex++) {
            var rule = ruleGroup[ruleIndex];     
            if (rule.tryApply()){
                propagated=true;
                nothing_happened_counter=0;//why am I resetting to 1 rather than 0? because I've just verified that applications of the current rule are exhausted
            } else {
                nothing_happened_counter++;
            }
            if ( nothing_happened_counter === ruleGroup.length)
                break;
            skip_from = last_applied;
        }
        if (propagated) {
            loopPropagated=true;

            if (verbose_logging){
                debugger_turnIndex++;
                addToDebugTimeline(level,-2);//pre-movement-applied debug state
            }
        }
    }

    return loopPropagated;
}

I'll mull it over and decide what to do later