   "Adds 2 vectors"
   (map + v1 v2))
 
-
 (defn simulate [dna the-map]
   "Simulates the DNA on a map. Evaluates to the score the robot achieved in simul-steps."
-  (defn make-step [[current-map pos score]]
-    "Makes a single step on the map, according to the DNA sequence."
-    ;(print pos)
-    (defn get-situation []
-      "Returns the tile situation at the current pos."
-      (def nearby-tiles (map (fn[v] (get-tile the-map (add-vec pos v))) dir-vects))
-      (map get-tile-index nearby-tiles))
-    (defn get-action [tile-situation]
-      "Returns the index of action to take when faced with a given tile situation."
-      (def multipliers (map (fn [n] (** (count tiles) n)) (range (count actions))))
-      (reduce + (map * tile-situation multipliers)))
-    (def action (nth dna (get-action (get-situation))))
-    (case action
-      (\l \r \u \d)
-      (do
-        (def new-pos (add-vec pos (nth dir-vects (get-action-index action))))
-        (if (not= \w (get-tile current-map new-pos))
-          [current-map new-pos score]
-          [current-map pos (- score action-penalty)]))
-      \x
-      (do
-        (def new-pos (add-vec pos (rand-nth (take 4 dir-vects))))
-        (if (not= \w (get-tile current-map new-pos))
-          [current-map new-pos score]
-          [current-map pos (- score action-penalty)]))
-      \p
-      (do
-        (if (= \g (get-tile current-map pos))
-          [(set-tile current-map pos \p) pos (+ score gold-value)]
-          [current-map pos (- score action-penalty)]))))
-  (def final-state (nth (iterate make-step [the-map '(1 1) 0]) simul-steps))
-  (nth final-state 2))
+  (let [multipliers (map (fn [n] (** (count tiles) n)) (range (count actions)))
+        make-step
+        (fn [[current-map pos score]]
+          "Makes a single step on the map, according to the DNA sequence."
+          (let [situation (map (fn[v] (get-tile current-map (add-vec pos v))) dir-vects)
+                action-idx (reduce + (map * (map get-tile-index situation) multipliers))
+                action (nth dna action-idx)
+                step-to 
+                  (fn [the-pos]
+                    (if (not= \w (get-tile current-map the-pos))
+                      [current-map the-pos score]
+                      [current-map pos (- score action-penalty)]))]
+            ;(print pos)
+            (case action
+              (\l \r \u \d)
+              (let [new-pos (add-vec pos (nth dir-vects (get-action-index action)))]
+                (step-to new-pos))
+              \x
+              (let [new-pos (add-vec pos (rand-nth (take 4 dir-vects)))]
+                (step-to new-pos))
+              \p
+              (if (= \g (get-tile current-map pos))
+                [(set-tile current-map pos \p) pos (+ score gold-value)]
+                [current-map pos (- score action-penalty)]))))
+        [_ final-pos final-score] (nth (iterate make-step [the-map '(1 1) 0]) simul-steps)]
+    final-score))
 
 
 ; Evolution functions
 (defn evolve [individuals]
   "Takes a bunch of individuals (DNAs) and cross-breeds by fitness."
-  (def the-map (rand-map))
-  (def to-drop (/ (count individuals) 2))
-  (def ordered (drop to-drop (sort-by (fn[dna] (simulate dna the-map)) individuals)))
-  (println (simulate (last ordered) the-map))
-  (let [breed (fn [dna] (cross dna (rand-nth ordered)))]
+  (let [the-map (rand-map)
+        to-drop (/ (count individuals) 2)
+        ordered (drop to-drop (sort-by (fn[dna] (simulate dna the-map)) individuals))
+        breed (fn [dna] (cross dna (rand-nth ordered)))]
+    (println (simulate (last ordered) the-map))
     (map mutate (concat (map breed ordered) (map breed ordered)))))
 
 (defn -main


(defn set-tile [the-map pos tile]
  "Returns a copy of the map where the tile on pos has been replaced."
  (let [[x y] (vec pos)]
    (def new-row (assoc (nth the-map y) x tile))
    (assoc the-map y new-row)))

(defn get-tile-index [t]



; DNA functions
(defn rand-gene []
  "Returns a random gene."
  (rand-nth actions))

(defn rand-dna []
  "Initializes a vector of random DNA."
  (vec (repeatedly (** (count tiles) 5) rand-gene)))

(defn cross [a b]
  "Crosses two vectors of DNA."
  (let [choose-rand (fn [x y] (if (< (rand-int 100) 50) x y))]
    (mapv choose-rand a b)))

(defn mutate [dna]
  "Randomly replace some genes in the DNA."
  (let [mutate-gene (fn [gene] (if (< (rand-int 100) mutation-prob) (rand-gene) gene))]
    (mapv mutate-gene dna)))


; Fitness evaluation functions
(defn rand-map []
  "Initializes a map with walls at the boundaries and randomly positioned gold."
  (let [last-coord (- map-size 1)
        map-coords (vec (range map-size))
        gen-tile (fn[x y]
                   (if (or (= x 0) (= y 0) (= x last-coord) (= y last-coord))
                     \w
                     (if (< (rand-int 100) gold-prob) \g \p)))]
    (mapv (fn [y] (mapv (fn [x] (gen-tile x y)) map-coords)) map-coords)))

(defn get-tile [the-map pos]
  "Given a map and coordinates, evaluates to what is on the map at the position."
