;; problem code

(defn local-dijkstra
  ([a center radius]
     (local-dijkstra a (find-walls a) {center 0} center radius))
  ([a ent center radius]
     (local-dijkstra a (dissoc (merge (find-walls a) (find-monsters @monsters)) (:pos @ent)) {center 0} center radius))
  ([a closed open-cells center radius]
     (loop [open open-cells result (transient {}) ctr 0]
       
       (if (and (seq open) (< ctr radius))
         (recur (reduce (fn [newly-open [i v]]
                          (reduce (fn [acc dir]
                                    (if (or (closed dir) (open dir)
                                            ;(> 0 (get result dir 22222.0))
                                            )
                                      acc
                                      (do (assoc! result dir (inc v))
                                          (println (count result) " " ctr " " (str open) " " (str newly-open))
                                          (assoc acc dir (inc v)))))
                                  newly-open, [(- i wide)
                                               (+ i wide)
                                               (- i 1)
                                               (+ i 1)]))
                        {}, open) result (inc ctr))
         (persistent! result)))
     ))

;;utility functions

(defn find-cells [^doubles a cell-kind]
    (persistent! (areduce ^doubles a i ret (transient {})
                          (if (= (aget ^doubles a i) cell-kind) (assoc! ret i cell-kind) ret))))

(defn find-goals [^doubles a]
  (find-cells a GOAL))

(defn find-walls [^doubles a]
    (persistent! (areduce ^doubles a i ret (transient {})
                          (if (>= (aget ^doubles a i) wall) (assoc! ret i wall) ret))))

(defn find-floors [^doubles a]
  (find-cells a floor))

(defn find-lowest [^doubles a]
  (let [low-val (hiphip/amin a)]
    (find-cells a low-val)))

(defn find-monsters [m]
  (into {} (for [mp (map #(:pos @%) m)] [mp wall])))


;; working code by amalloy
(defn dijkstra
  ([a]
     (dijkstra a (find-walls a) (find-lowest a)))
  ([a ent]
     (dijkstra a (dissoc (merge (find-walls a) (find-monsters @monsters)) (:pos @ent)) (find-lowest a)))
  ([a closed open-cells]
     (loop [open open-cells]
       (when (seq open)
         (recur (reduce (fn [newly-open [i v]]
                          (reduce (fn [acc dir]
                                    (if (or (closed dir) (open dir)
                                            (>= (inc v) (hiphip/aget a dir)))
                                      acc
                                      (do (hiphip/aset a dir (inc v))
                                          (assoc acc dir (inc v)))))
                                  newly-open, [(- i wide)
                                               (+ i wide)
                                               (- i 1)
                                               (+ i 1)]))
                        {}, open))))
     a))