automatically enforces certain invariants, such as the fact that an aircraft should not leave if a person is boarding, because the location of the aircraft **is modified by** fly **and used in**
the precondition of board**. The TAL-C semantics used by TALplanner is more similar to**
PDDL2.1 level 3 (with durative actions), where such invariant conditions must be stated explicitly. This is done using prevail conditions, which are considered to be separate from true pre**-conditions. Note that in the STRIPS formalization** fly and zoom **take the same** amount of time, since only single-step actions are possible.

\#operator **board**(person, aircraft, city) :at t
:precond [t] at(person, city) ∧ at(aircraft, city) :prevail [t+1] at(aircraft, city)
:effects [t+1] at(person, city) := false, [t+1] in(person, aircraft) := true
\#operator **debark**(person, aircraft, city) :at t
:precond [t] in(person, aircraft) ∧ at(aircraft, city) :prevail [t+1] at(aircraft, city) :effects [t+1] in(person, aircraft) := false, [t+1] at(person, city) := true
\#operator fly(aircraft, city1, city2, flevel1, flevel2) :at t
:precond [t] at(aircraft, city1) ∧ fuel-level(aircraft, flevel1) ∧ next(flevel2, flevel1)
:effects [t+1] at(aircraft, city1) := false, [t+1] fuel-level(aircraft, flevel1) := false,
[t+1] at(aircraft, city2) := true, [t+1] fuel-level(aircraft, flevel2) := true
\#operator **zoom**(aircraft, city1, city2, flevel1, flevel2, flevel3) :at t
:precond [t] at(aircraft, city1) ∧ fuel-level(aircraft, flevel1) ∧
next(flevel2, flevel1) ∧ next(flevel3, flevel2)
:effects [t+1] at(aircraft, city1) := false, [t+1] fuel-level(aircraft, flevel1) := false,
[t+1] at(aircraft, city2) := true, [t+1] fuel-level(aircraft, flevel3) := true
\#operator **refuel**(aircraft, city, flevel, flevel1) :at t
:precond [t] fuel-level(aircraft, flevel) ∧ next(flevel, flevel1) ∧ at(aircraft, city)
:prevail [t+1] at(aircraft, city)
:effects [t+1] fuel-level(aircraft, flevel) := false, [t+1] fuel-level(aircraft, flevel1) := true After translating the operator definitions, it is time to create a set of control rules. There are basically two ways of doing this: First, one can sit down and think about suitable properties for a plan, and then write control rules that ensure that these properties will hold. Second, one can instruct the planner to show each branch that is explored in the search tree, and by observing the output one can identify "obviously stupid" choices made by the planner, such as choosing an action instance that inevitably leads to backtracking or performing actions that are useless given the goals. Control rules can then be written to prevent these branches of the tree from being explored. Both **of these approaches will be** covered here.

We begin with the first method, attempting to find a number of reasonable control rules simply by thinking about the properties of the ZenoTravel domain. Given some experience from other planning domains, this is in fact quite easy. For example, in many domains there are certain goals such that once they are satisfied, one **should never allow them to be** destroyed. In the ZenoTravel domain, people who are at their **destinations never need to**