From a5d49832d97e0cd599d6b4ad0a9ac962028bdf96 Mon Sep 17 00:00:00 2001 From: Dane Johnson Date: Thu, 14 Sep 2023 11:18:37 -0500 Subject: [PATCH] Simple combat --- src/minibaldur/core.clj | 57 +++++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/src/minibaldur/core.clj b/src/minibaldur/core.clj index 0a58a7d..f62c3aa 100644 --- a/src/minibaldur/core.clj +++ b/src/minibaldur/core.clj @@ -7,34 +7,69 @@ (defcomponent position) (defcomponent health) (defcomponent attack) +(defcomponent player-character) +(defcomponent goblin-ai) +(defcomponent armor-class) + +(def combat-log println) (defentity (name "Goblin") (position {:x 0 :y 0 :z 0}) (health 10) - (attack "1d4 + 2")) + (attack "1d4 + 2") + (armor-class 13) + (goblin-ai nil)) (defentity (name "Adventurer") (position {:x 0 :y 0 :z 0}) (health 20) - (attack "1d6 + 3")) + (attack "1d6 + 3") + (armor-class 15) + (player-character nil)) -(defn battle-system - [entity] - (let [opponent (if (= (name entity) "Goblin") - (find-by :name "Adventurer") - (find-by :name "Goblin"))] - (health opponent (max 0 (- (health opponent) (first (roll (attack entity)))))))) +(def alive? (comp pos? health)) + +(defn do-attack + [entity target] + (let [[to-hit] (roll "1d20")] + (if (>= to-hit (armor-class target)) + (let [[dmg] (roll (attack entity))] + (combat-log (str (name entity) " hit " (name target) " for " dmg " damage")) + (health target (max (- (health target) dmg) 0))) + (combat-log (str (name entity) " missed " (name target)))))) + +(defn goblin-attack + [goblin] + (when-let [adventurer (first (filter alive? (query-e [:player-character + :health + :armor-class])))] + (do-attack goblin adventurer))) + +(defn adventurer-attack + [adventurer] + (let [targets (vec (filter alive? (query-e [:health :armor-class])))] + (println "Choose a target:") + (doseq [[i target] (map-indexed vector targets)] + (println (str "\t" (inc i) ". " (name target)))) + (let [target-i (dec (Integer/parseInt (read-line))) + target (get targets target-i)] + (do-attack adventurer target)))) (defn do-battle [] (let [goblin (find-by :name "Goblin") adventurer (find-by :name "Adventurer")] - (while (every? pos? [(health goblin) (health adventurer)]) - (run-e battle-system [:name :health])))) + (loop [turn adventurer] + (when (every? alive? [goblin adventurer]) + (if (= turn adventurer) + (do (adventurer-attack adventurer) + (recur goblin)) + (do (goblin-attack goblin) + (recur adventurer))))))) (defn -main "I don't do a whole lot ... yet." [& args] - (println "Hello, World!")) + (do-battle))