       (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)))
+
+
+
 
 
 

  env/FactoredEnv
    (goal-map      [e] g-map))

;; TODO: add assertions on precond var = effect var
;; Recall: greedy helps the most when, e.g., lots of passengers and not much room.
(defn make-asplan-env
  "Make an actino-set planning environment.  Switches are:
    check-deadlock?: check for cycles in precedence graph above and beyond lack of sources

          :when (and (= s cur-val) (not (contains? (backward-sets t) s)))]
      t)))

(defn make-possible-actions-fn [dtgs]
  (let [simple-dtgs   (util/map-vals (fn [dtg] (for [[pval emap] dtg, [eval _] emap] [pval eval])) dtgs)
        acyclic-succ-fn (partial possibly-acyclic-successors (HashMap.) simple-dtgs)]
    (fn [var cur-val dst-val]
      (for [nxt-val (acyclic-succ-fn var cur-val dst-val),
            a       (get-in dtgs [var cur-val nxt-val])]
        a))))




(defn greedy-action? [s a effect-var]
  (assert (= effect-var (action-effect-var a)))
  (and (state/state-matches-map? s (:precond-map a))
       (every? #(contains? (state/get-var s (possible-children-var %)) effect-var)
               (keys (dissoc (:precond-map a) effect-var)))))





;; return a list of actions, or nil if no greedy possibilities.
(defn greedy-actions [s v cvm possible-actions-fn]
  (let [actions (state/get-var s (possible-actions-var v))
        [greedy not-greedy]    (when-not (= :wait actions) (util/separate #(greedy-action? s % v) actions))]
    (when (seq greedy)
      (concat
       (when (seq not-greedy) [(make-assign-actions-action v (set not-greedy))])
       (for [a greedy] (make-greedy-fire-action s a v cvm possible-actions-fn))))))

;; TODO: treat happy same as concerned?
;; Split based on:
;;  split out actions that don't care about p or want current value of p.
;;  no reservation of p (if remaining vals)
;;  reserve p, split on target-val for p.
(defn refinement-actions [s p c possible-actions-fn]
  (let [actions (state/get-var s (possible-actions-var c))
        children (state/get-var s (possible-children-var p))
        cur-val  (state/get-var s p)
        [concerned indifferent] (util/separate #(contains? (:precond-map %) p) actions)
        [happy unhappy]         (util/separate #(= (get (:precond-map %) p) cur-val) concerned)
        lazy-set                (set (concat happy indifferent))]
    (assert (not-any? #(greedy-action? s % c) actions))
    (assert (seq unhappy))
    (assert (contains? children c))
    (assert (= :wait (state/get-var s (target-var p))))
    (concat
     (when-not (empty? lazy-set)
       [(make-assign-actions-action c lazy-set)])
     (when (> (count children) 1)
       [(make-assign-children-action p (disj children c))])
     (for [[dst-val wanting-actions] (group-by #((:precond-map %) p) unhappy)]
       (make-commitment-action p c cur-val dst-val (set wanting-actions) possible-actions-fn)))))

(defn var-precondition-choices [s v]
  (let [actions (state/get-var s (possible-actions-var v))]
    (when-not (= actions :wait)
      (filter
       (fn [p] (and (= :wait (state/get-var s (target-var p)))
                    (contains? (state/get-var s (possible-children-var p)) v)
                    (some #(when-let [v (get (:precond-map %) p)] (not (= (state/get-var s p) v))) actions)))       
       (distinct (apply concat (map (comp keys :precond-map) actions)))))))




;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Actions fn, actual env ;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defrecord ASPlanEnv [base-sas-env init actions-fn g-map]
  env/Env 
    (initial-state [e] init)
    (actions-fn    [e] actions-fn)
