[adventofcode2019.intcode :as i]
[clojure.string :as str]
[clojure.core.match :refer [match]]
- [clojure.math.combinatorics :as combo]])
+ [clojure.math.combinatorics :as combo]
+ [lanterna.terminal :as ts]])
+
+(def term (ts/get-terminal :text))
+
+(defn find-bounds [tiles]
+ (let [x-list (map first (keys tiles))
+ y-list (map second (keys tiles))
+ min-x (reduce min x-list)
+ max-x (reduce max x-list)
+ min-y (reduce min y-list)
+ max-y (reduce max y-list)]
+ [[min-x max-x] [min-y max-y]]))
+
+(defn make-field [[dx dy]]
+ (let [line (vec (repeat dx \space))]
+ (mapv (constantly line) (range dy))))
+
+(defn draw-tiles [tiles term]
+ (let [to-text #(case %
+ 0 \space
+ 1 \|
+ 2 \-
+ 3 \_
+ 4 \O)
+ paint-tile (fn [[[x y] tile]]
+ (ts/move-cursor term x y)
+ (ts/put-character term (to-text tile)))]
+ (doall (map paint-tile tiles))))
+
+(defn print-field [field score]
+ (run! (comp println str/join) field)
+ (println score)
+ (flush))
+
+(defn run-game [game [[min-x max-x] [min-y max-y]]]
+ (let [wait-for-output #(= (count (:output %)) 3)
+ get-next-ic-output (partial i/intcode-until wait-for-output)
+ new-game (assoc game :input [0])
+ field (ts/get-terminal :swing)]
+ (ts/start field)
+ (ts/put-character field \a)
+ (loop [program-state (get-next-ic-output new-game)
+ score 0
+ framerate 0
+ ctr 0]
+ (Thread/sleep framerate)
+ (if (:exit program-state)
+ (do (ts/stop field)
+ score)
+ (let [[x y t] (:output program-state)
+ [new-score new-screen] (if (and (= x -1) (= y 0))
+ [t {}]
+ [score {[x y] t}])
+ input (case (ts/get-key-blocking field {:interval 1 :timeout framerate})
+ \a -1
+ \d 1
+ 0)]
+ (draw-tiles new-screen field)
+ (recur (get-next-ic-output (assoc program-state
+ :output []
+ :input [input]))
+ new-score (if (> ctr 814) 100 0) (inc ctr)))))))
(defn day13 []
(let [input (i/get-program (input-file))
output (:output (i/intcode (i/build-state input)))
draw-tiles (fn [screen [x y t]] (assoc screen [x y] t))
- screen (reduce draw-tiles {} (partition 3 output))]
- (part1 (count (filter #(= % 4) (vals screen))))
- #_(part2)))
+ screen (reduce draw-tiles {} (partition 3 output))
+ game (assoc-in (i/build-state input {:step true}) [:memory 0] 2)]
+ (part1 (count (filter #(= % 2) (vals screen))))
+ (part2 (run-game game (find-bounds screen)))))