 (def simul-steps 100) ; Steps to allow the robot to make in a simulation.
 (def tiles [\w \p \g]) ; Tiles that populate the map: wall, path, and gold.
 (def actions [\u \d \l \r \x \p]) ; Actions the robot can take: up, down, left, right, pick up.
-(def dir-vects ['(0 -1) '(0 1) '(-1 0) '(1 0) '(0 0)]) ; Direction vectors, corresponding to the actions.
+(def dir-vects ['(0 -1) '(0 1) '(-1 0) '(1 0) '(0 0)]) ; Direction vectors, corresponding to the 4 actions.
 
 (def mutation-prob 5) ; Probability in 100 that a gene will mutate.
 (def action-penalty 5) ; How many points robot loses when hitting the wall or picking up when it shouldn't.


(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]

  "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."
  (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."
  (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
