(ns challenge-0155.core
(:require [clojure.string :refer [split]]
[clojure.java.io :refer [reader]]))
(def initial-positions {:a {:1 :rook, :2 :pawn, :7 :pawn :8 :rook}
:b {:1 :knight, :2 :pawn, :7 :pawn :8 :knight}
:c {:1 :bishop, :2 :pawn, :7 :pawn :8 :bishop}
:d {:1 :queen, :2 :pawn, :7 :pawn :8 :queen}
:e {:1 :king, :2 :pawn, :7 :pawn :8 :king}
:f {:1 :bishop, :2 :pawn, :7 :pawn :8 :bishop}
:g {:1 :knight, :2 :pawn, :7 :pawn :8 :knight}
:h {:1 :rook, :2 :pawn, :7 :pawn :8 :rook}})
(def initial-score 39)
(def piece-values {:pawn 1, :knight 3, :bishop 3, :rook 5, :queen 9})
(def piece-name {"K" :king, "N" :knight, "Q" :queen, "R" :rook, "B" :bishop, "" :pawn})
(defn other-player [player]
(case player
:white :black
:black :white))
(defn board-position
"Translates a move (e.g. e5) to a board position (e.g. [:e :5])"
[move]
(map #(-> % str keyword) move))
(defn score-capture [player move board scores]
(update-in scores [(other-player player)] - (piece-values (get-in board move))))
(defn score-en-passant [player scores]
(update-in scores [(other-player player)] - 1))
(defn analyze-move [player move board scores]
(let [[_ piece capture move promotion en-passant]
(re-find #"([KNQRB]?)[a-h1-8]?(x?)([a-h][1-8])([KNQRB]?)((?:e.p.)?)" move)
position (board-position move)
piece (if (and (= "" piece) (not= "" promotion)) promotion piece)
new-scores (or (when-not (= "" en-passant)
(score-en-passant player scores))
(when-not (= "" capture)
(score-capture player position board scores))
scores)]
{:board (assoc-in board position (piece-name piece))
:scores new-scores}))
(defn process-move [player move board scores]
(cond
(= move "O-O") (let [rank (if (= player :white) :1 :8)]
{:board (assoc-in (assoc-in board [:g rank] :king) [:f rank] :rook)
:scores scores})
(= move "O-O-O") (let [rank (if (= player :white) :1 :8)]
{:board (assoc-in (assoc-in board [:c rank] :king) [:d rank] :rook)
:scores scores})
:else (analyze-move player move board scores)))
(defn process-round [round board scores]
(let [[_ wmove bmove] (split round #" ")
{:keys [board scores]} (process-move :white wmove board scores)]
(process-move :black bmove board scores)))
(defn process-input [lines]
(loop [line (first lines)
xs (next lines)
board initial-positions
scores {:white initial-score :black initial-score}]
(let [{:keys [scores board]} (process-round line board scores)]
(if xs
(recur (first xs) (next xs) board scores)
{:board board :scores scores}))))
(let [{:keys [scores]} (process-input (line-seq (reader *in*)))]
(println (format "%d-%d" (:white scores) (:black scores))))