Give every scan a stopping rule

A bounded scan needs a quantity that moves toward an end, plus a separate way out when an action fails. Count completed work after success; counting attempts can hide a failed scan, while never updating progress can make the same step repeat forever.

Define the job before the loop

For a four-target teaching example, the job is “process these four targets once.” Start with remaining = 4. After confirmed work, subtract one. The normal end is remaining = 0; an unsuccessful action goes to a recovery branch instead of silently pretending to finish.

This is a model of loop reasoning, not a DLC command listing. The game’s actual action result and failure signal must come from its current documentation.

A useful progress measure has three properties: it starts with a bound, it changes after meaningful success, and it cannot decrease forever. “The program is still running” is not progress.

Remaining work 43210 Failed actionstill 2 Recoverdo not count it An attempt alone is not progress
In this four-target model, only confirmed success advances the count. An unchanged failed attempt takes the recovery branch.

Trace four successful steps

Original four-target example: success reduces remaining work
TurnBeforeObserved resultAfter
14 remainingTarget 1 completed3 remaining
23 remainingTarget 2 completed2 remaining
32 remainingTarget 3 completed1 remaining
41 remainingTarget 4 completed0 — stop

The next condition check sees zero and does not start a fifth action. Position and completion may be related, but they are not interchangeable: arriving at a target does not prove the intended work happened there.

For a visible route with a different end condition, compare 16 visited cells reached by 15 moves.

Handle a failed move without losing the truth

Now suppose the second attempt fails. You still have three targets remaining, and the next intended target is still pending. Do not subtract one and do not advance a stored position unless movement actually occurred.

  1. Keep the last confirmed position and remaining-work count.
  2. Record which target or action failed.
  3. Leave the repeating path, or enter a deliberately bounded recovery attempt.
  4. Resume only when a changed condition can make the next attempt different.

Retrying the same failed move forever is not a recovery strategy. A retry limit prevents endless execution; it does not make the underlying path valid. At the limit, stop with enough state to diagnose the problem.

Three stopping mistakes to look for

The condition never changes.
A loop checks “remaining is above zero” but updates a different variable. Trace the value used by the condition, not the similarly named value you meant to update.
A skip bypasses progress.
A continue-style branch can return to the condition before the update. Decide whether that branch completed work, changed the next target or needs to stop.
An inner exit is mistaken for a whole-program exit.
Leaving an inner loop can let the outer loop start it again. Write down which loop owns the job’s completion state.

When the program repeats, reduce it to the smallest repeated sequence and inspect its condition, state update and failure branch. Follow the first incorrect state before changing the whole routine.

Sources and further reading