This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defn- start-game-loop | |
"Manage transitions between player moves, ai moves, and generic game events" | |
[] | |
(let [play-events (chan 1 (filter #(not @store/ai-player?))) | |
game-events (chan 1)] | |
(go | |
(while true | |
(let [play-chan (if @store/ai-player? | |
(ai-computation @store/game) | |
play-events)] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defn- handle-game-event! | |
[msg] | |
(store/swap-game! | |
(case msg | |
:new-game (fn [_] (game/new-game)) | |
:restart game/restart-game | |
:undo game/undo-player-move))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defonce game-loop (start-game-loop)) | |
(defn send-play-event! [e] (put! (game-loop :play-events) e)) | |
(defn send-game-event! [e] (put! (game-loop :game-events) e)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defn minimax-step | |
"One stage of the minimax algorithm: | |
* Apply the maximizing or mininizing step to all transitions of the turn | |
* Evaluate the lower level using the on-transition function" | |
[ai turn open-recur | |
& {:keys [max-fn min-fn] | |
:or {max-fn max, min-fn min}}] | |
(apply | |
(if (maximizing? ai turn) max-fn min-fn) | |
(map |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defn- eval-next-score-of | |
"Perform a last minimax step on the next scores following the turn | |
* Allows to see one level deeper for simple scoring strategies | |
* While being fast (the transition does not need to be followed)" | |
[ai {:keys [scores] :as turn} players] | |
(minimax/minimax-step ai turn | |
(fn [_ transition] | |
(let [scores (scores/update-scores scores transition)] | |
(apply + (map #(get scores %) players))) | |
))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defn optimize-own-score-ai | |
"Create an AI strategy to optmize its own score: good late game play" | |
[player] | |
(reify minimax/AIStrategy | |
(eval-turn [this turn] (eval-next-score-of this turn [player])) | |
(maximizing? [_ turn] (= (:player turn) player)) | |
)) | |
(defn optmize-ai-scores-ai | |
"Create an AI strategy to optmize the AI scores: good cheat when the player wins" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defn optimize-own-choices-ai | |
"Create an AI strategy to optmize the AI choices: avoid being trapped with no moves left" | |
[player] | |
(reify minimax/AIStrategy | |
(eval-turn [_ turn] | |
(count (get (transition/all-transitions (:board turn)) player))) | |
(maximizing? [_ turn] (= (:player turn) player)) | |
)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defn- game-tree-search | |
"The top level of the minimax algorithm | |
* Trigger sub-game-trees minimax evaluations | |
* Remember the transition that led to the max" | |
[ai turn depth] | |
(first | |
(ai-algo/minimax-step-by | |
second ai turn | |
(fn [coord transition] | |
(let [new-turn (turn/next-turn turn transition)] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defn- high-level-ai | |
"High level AI: choose the right evaluation function to play" | |
[{:keys [player scores] :as turn}] | |
(cond | |
(human-player-winning? scores) (strategies/optmize-ai-scores-ai) | |
(in-late-game? scores) (strategies/optimize-own-score-ai player) | |
(limited-move-options? turn) (strategies/optimize-own-choices-ai player) | |
:else (strategies/optimize-own-score-ai player) | |
)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defn find-best-move | |
"Find the best available move for the current player" | |
[game] | |
(let [turn (game/current-turn game) | |
ai (high-level-ai turn)] | |
(game-tree-search ai turn 1))) |