       (get-in [sas/goal-var-name sas/goal-false-val sas/goal-true-val])
       util/safe-singleton))
 
-(defn target-var [v] [:target v])
-(defn possible-parent-var [p c]  [:parent? p c])
-(defn possible-actions-var [v]  [:actions v])
+(defn target-var [v] [:target v]) ; a value for v, :wait if no target.
+(defn possible-children-var [v]  [:children v]) ; a set of child vars
+(defn possible-actions-var [v]  [:actions v]) ; a set of actions, :wait if no target.
 
 (defn expand-initial-state 
   "Expand the initial state with lots more stuff.  Each var can be free, OR
    have a child (in which case it must eventually be used to fire an active action on
    that var), AND in such a case, it can also have an active action to help achieve that val.
    (which changes only that var)."
-  [init child-var-map]
-  (let [vars (state/list-vars init)]
-    (state/set-vars init
+  [init child-var-map goal-action]
+  (let [vars (keys child-var-map)]
+    (into {}
       (concat 
-       (for [var vars] [(target-var v) nil])
-       (for [[p cs] child-var-map, c cs] [(possible-parent-var p c) true])
-       [[(target-var sas/goal-var-name) sas/goal-true-val]]))))
-
-
-
-
-(defn action-effect-var [a] (util/safe-singleton (keys (:precond-map a))))
-
-
-
-
-
-(defn make-add-action-action [{:keys [name precond-map effect-map reward] :as factored-primitive}]
-  (util/sref-set! *add-count* (inc (util/sref-get *add-count*)))
-  (let [[evar eval] (util/safe-singleton (seq effect-map))]
-    (env-util/make-factored-primitive
-     [::AddAction name]
-     {(action-var evar) nil, evar (precond-map evar)}
-     {(action-var evar) factored-primitive}
-     reward)))
-
-(defn make-set-parent-var-action [p-var c-var]
-  (env-util/make-factored-primitive 
-   [::SetParent p-var c-var] 
-   {(free-var p-var) true} 
-   {(free-var p-var) false (parent-var p-var c-var) true} 
+       (for [v vars] [v (state/get-var init v)])
+       (for [v vars] [(target-var v) :wait])
+       (for [v vars] [(possible-children-var v) (child-var-map v)])
+       (for [v vars] [(possible-actions-var v) :wait])
+       [[(target-var sas/goal-var-name) sas/goal-true-val]]
+       [[(possible-actions-var sas/goal-var-name) #{goal-action}]]))))
+
+(defn action-effect-var [a] (util/safe-singleton (keys (:effect-map a))))
+
+
+
+
+(defn make-assign-actions-action [v actions]
+  (assert (set? actions))
+  (env-util/make-factored-primitive
+   [::AssignActions v actions]
+   {}
+   {(possible-actions-var v) actions}
    0))
 
-
-(defn make-fire-action
-  "Simple version of greedy-fire, used for exhaustive action list. (No add-parent)."
-  [{:keys [name precond-map effect-map reward] :as factored-primitive}]
-  (let [effect-var (key (util/safe-singleton (seq effect-map)))
-        precond-vars (keys (dissoc precond-map effect-var))]
-    (env-util/make-factored-primitive
-     [::Fire name]
-     (into precond-map 
-           (concat [[(action-var effect-var) factored-primitive]]
-                   (for [v precond-vars] [(parent-var v effect-var) true])
-                   (for [v precond-vars] [(action-var v) :frozen])))
-     (into effect-map 
-           (concat [[(action-var effect-var) nil]]
-                   (for [v precond-vars] [(free-var v)              true])
-                   (for [v precond-vars] [(parent-var v effect-var) false])
-                   (for [v precond-vars] [(action-var v) nil])))
-     0)))
-
-
-;; TODO: should fail if I own parent, it has right value, but an action. (right now, we assert)...
-;; Try to make an action that greedily fires the action scheduled on effect-var,
-;; effectively representing a composition of set-parent and fire-action actions.
-;; Note that this avoids some (unnecessary) branching on children of parent vars.
-;; Assumes this will always be called on a "source", and asserts correspondingly.
-(defn make-greedy-fire-action [s effect-var]
-  (let [{:keys [name precond-map effect-map reward] :as factored-primitive}
-        (->> effect-var action-var (state/get-var s))
-        precond-vars (keys (dissoc precond-map effect-var))
-        [free-pv unfree-pv] (util/separate #(state/get-var s (free-var %)) precond-vars)]
-    (assert (every? #(contains? #{nil :frozen} (state/get-var s (action-var %))) precond-vars))
-#_    (util/assert-is (every? #(contains? #{nil :frozen} (state/get-var s (action-var %))) precond-vars)
-                    "%s" [name precond-map effect-map s])    
-    (env-util/make-factored-primitive
-     [::Fire name]
-     (into precond-map 
-           (concat [[(action-var effect-var) factored-primitive]]
-                   (for [v free-pv]   [(free-var v)              true])
-                   (for [v unfree-pv] [(parent-var v effect-var) true])
-                   (for [v precond-vars] [(action-var v) (state/get-var s (action-var v))])))           
-     (into effect-map 
-           (concat [[(action-var effect-var) nil]]
-                   (for [v unfree-pv] [(free-var v)              true])
-                   (for [v unfree-pv] [(parent-var v effect-var) false])
-                   (for [v precond-vars] [(action-var v) nil])))
-     0)))
-
-
-
-(defn make-greedy-fire-action [s firing-seq]
-  (doseq [[a1 a2] (partition 2 1 firing-seq)]
-    (let [v1 (action-effect-var a1)]
-      (assert (= (state/get-var s v1) (state/get-var s (target-var v1)) ((:precond-map a2) v1)))))
-  (assert (env/state-matches-map? s (apply util/merge-agree (map :precond-map firing-seq))))  
-  (env-util/make-factored-primitive
-   (vec (cons ::Fire (map :name firing-seq)))
-   (apply util/merge-agree (map :precond-map firing-seq))
-   (into precond-map 
-         (concat [[(action-var effect-var) factored-primitive]]
-                 (for [v free-pv]   [(free-var v)              true])
-                 (for [v unfree-pv] [(parent-var v effect-var) true])
-                 (for [v precond-vars] [(action-var v) (state/get-var s (action-var v))])))           
-   (into effect-map 
-         (concat [[(action-var effect-var) nil]]
-                 (for [v unfree-pv] [(free-var v)              true])
-                 (for [v unfree-pv] [(parent-var v effect-var) false])
-                 (for [v precond-vars] [(action-var v) nil])))
-   0)
-
-  
-  (let [{:keys [name precond-map effect-map reward] :as factored-primitive}
-        (->> effect-var action-var (state/get-var s))
-        precond-vars (keys (dissoc precond-map effect-var))
-        [free-pv unfree-pv] (util/separate #(state/get-var s (free-var %)) precond-vars)]
-    (assert (every? #(contains? #{nil :frozen} (state/get-var s (action-var %))) precond-vars))
-#_    (util/assert-is (every? #(contains? #{nil :frozen} (state/get-var s (action-var %))) precond-vars)
-                    "%s" [name precond-map effect-map s])    
-))
-
-
-(defn make-fire-action-type [s edge-rule effect-var]
-  (doto (case edge-rule
-          :naive (make-fire-action (->> effect-var action-var (state/get-var s)))
-          :greedy (make-greedy-fire-action s effect-var)
-          (:sloppy :extra-sloppy) (make-sloppy-fire-action s effect-var))
-     #_ (-> (env/applicable? s) assert)))
+(defn make-assign-children-action [p children]
+  (assert (set? children))
+  (env-util/make-factored-primitive
+   [::AssignChildren p children]
+   {}
+   {(possible-children-var p) children}
+   0))
+
+(defn make-commitment-action [p c cur-val dst-val wanting-actions possible-actions-fn]
+  (assert (not (= cur-val dst-val)))
+  (assert (set? wanting-actions))
+  (env-util/make-factored-primitive
+   [::Commit p c dst-val wanting-actions]
+   {}
+   {(possible-children-var p) #{c}
+    (possible-actions-var c) wanting-actions
+    (target-var p) dst-val
+    (possible-actions-var p) (possible-actions-fn p cur-val dst-val)}
+   0))
+
+(defn make-greedy-fire-action [s a effect-var cvm possible-actions-fn]
+  (doseq [[pvar pval] (dissoc (:precond-map a) effect-var)]
+    (assert (= (state/get-var s pvar) pval))
+    (assert (= (state/get-var s (possible-actions-var pvar)) :wait)))  
+  (env-util/make-factored-primitive
+   [::Fire a]
+   {}
+   (into (:effect-map a)
+         (cons
+          [(possible-actions-var effect-var)
+           (let [cur-val (get (:effect-map a) effect-var)
+                 dst-val (state/get-var s (target-var effect-var))]
+             (assert (not (= dst-val :wait)))
+             (if (= cur-val dst-val) :wait (possible-actions-fn effect-var cur-val dst-val)))]           
+          (apply concat
+                 (for [[pvar pval] (dissoc (:precond-map a) effect-var)]
+                   [[(possible-children-var pvar) (cvm pvar)]
+                    [(possible-actions-var pvar) :wait]
+                    [(target-var pvar) :wait]]))))
+   (:reward a)))
+
+
+
 
 
 




;; (use 'angelic.env 'angelic.hierarchy 'angelic.search.textbook 'angelic.domains.taxi-infinite 'angelic.search.action-set.asplan  'angelic.domains.sas-problems 'angelic.sas 'angelic.sas.analysis 'angelic.util 'angelic.sas.hm-heuristic)

;; (let [e (make-random-infinite-taxi-sas2 4 4 4 2)] (println (time (run-counted #(uniform-cost-search e)))) (println (time (run-counted #(asplan-solution-pair-name (uniform-cost-search (make-asplan-env e)))))))

;; (let [i 25] (let [e (make-random-infinite-taxi-sas2 3 3 3 i) ae (make-asplan-env e)]  (println (time (run-counted #(uniform-cost-search e)))) (println (time (run-counted (fn [] (a*-search e (h-max (:actions e))))))) (println (time (run-counted #(asplan-solution-pair-name (uniform-cost-search ae))))) (println (time (run-counted #(asplan-solution-pair-name (a*-search ae (h-max (:actions ae))))))) (println (time (run-counted #(asplan-solution-pair-name (a*-search ae (let [h (h-max (:actions ae))] (fn [s] (- (h s) (unrealized-reward s)))))))))))

; (let [e (force (nth ipc2-logistics 3)) ] #_ (println (time (run-counted #(uniform-cost-search e)))) (println (time (run-counted #(asplan-solution-pair-name (uniform-cost-search (make-asplan-env e)))))))


 ; (doseq [[alg sp]  [[make-asplan-env asplan-solution-pair-name] [angelic.search.action-set.asplan-broken/make-asplan-env angelic.search.action-set.asplan-broken/asplan-solution-pair-name]] ] (println (time (run-counted #(sp (uniform-cost-search (alg (make-random-infinite-taxi-sas2 3 3 3 3))))))))

; (-> (nth (vals (sas-sample-files 1)) 5) make-sas-problem-from-pddl unarize make-asplan-env interactive-search)


       Greedy means we forget about reserving preconditions when free and we can fire right now (less branching).
       Sloppy means we ignore if preconditions are free, but require no action on them.
       Extra-sloppy means anything goes -- if you can execute ignoring commitments, go for it."
  ([sas-problem]
     (let [causal-graph  (remove #(apply = %) (sas-analysis/standard-causal-graph sas-problem))
           vars          (graphs/ancestor-set causal-graph [sas/goal-var-name])
           causal-graph  (filter (fn [[v1 v2]] (and (vars v1) (vars v2))) causal-graph)
           tsi           (graphs/df-topological-sort-indices causal-graph) ;; TODO: doesn't seem to matter...
           child-var-map (assoc (util/map-vals #(set (map second %)) (group-by first causal-graph))
                           sas/goal-var-name #{})
           dtgs          (sas-analysis/domain-transition-graphs sas-problem)
           possible-actions-fn (make-possible-actions-fn dtgs)]
;       (assert (graphs/dag? causal-graph))    
       (assert (sas-analysis/unary? sas-problem))
;       (println child-var-map)
       
       (ASPlanEnv.
        sas-problem
        (expand-initial-state (env/initial-state sas-problem) child-var-map (goal-action dtgs))

        (fn asplan-actions [s]
;          (println "\n"(:act-seq (meta s)))
          (identity #_ util/prln (or (some #(greedy-actions s % child-var-map possible-actions-fn) vars)
               (let [choices (for [v vars, p (var-precondition-choices s v)]
                               (refinement-actions s p v possible-actions-fn))]
;                 (when (empty? choices) (clojure.inspector/inspect-tree (state/as-map s)) #_ (assert nil))
;                 (println (map count choices))
                 (assert (not-any? empty? choices))
                 (if (seq choices)
                   (apply min-key count choices)
                   #_ (println "is a dead end"))))))
        (env/goal-map sas-problem)))))
;; TODO: assert no top-down.

(defn asplan-solution-name [sol]
  (map second (filter #(= (first %) ::Fire) sol)))
