   (for [i (range 9)]
     (math/expt 2 i)))
 
-(defn pick-move [state]
+(defn valid-moves [state]
   (let [occupied (bit-or (:p1 state) (:p2 state))]
-    (rand-nth (keep identity (map-indexed (fn [i pos]
-                              (if (zero? (bit-and occupied pos))
-                                i))
-                            possible-moves)))))
+    (filter #(zero? (bit-and occupied %))
+                      possible-moves)))
+
 
 (def winning-positions
   [2r111000000                                              ;horizontals

(ns ulam.tictactoe
  (require [ulam.core :as ulam]
           [clojure.math.numeric-tower :as math]))

(defn init []

                        (= winning-pos (bit-and board winning-pos)))
                      winning-positions)))


(defn format-stats [stats]
  (println "===============================")
  (doseq [[move stats] (sort stats)]
    (println move (format "%.5f" (try (double (/ (:total stats) (:n stats)))
                                      (catch Exception e 0.0))))))

(defn perform-move [state move]
  (-> state
      (update-in [(:active state)] #(bit-or % move))
      (assoc :active (if (= :p1 (:active state)) :p2 :p1))))

(perform-move (init) 2r000010000)

(defn simulate [state]
  (let [valids (valid-moves state)]
    (loop [n 0
           stats (into {}
                  (for [move valids]
                    [move {:total 0 :n 0}]))]
      (if (= 1 (mod n 100000))
        (format-stats stats))
      (let [random-move (rand-nth valids)
            result (simulate-step (perform-move state random-move))]
        (recur (inc n)
               (-> stats
                   (update-in [random-move :n] inc)
                   (update-in [random-move :total] #(+ % result))))))))



(defn simulate-step [state]
  (cond (check-win (:p1 state)) 1
        (check-win (:p2 state)) -1
        (= 2r111111111 (bit-or (:p1 state) (:p2 state))) 0
        :else (let [move (rand-nth (valid-moves state))]
                (recur (perform-move state move)))))

(simulate (init))
(simulate {:p1 2r000110100 :p2 2r101000000 :active :p2})

(crit/quick-bench (simulate-step (init)))
