Browse Source

Implement bomb placement logic

Thomas Dy 8 years ago
parent
commit
6db604c3cd
2 changed files with 60 additions and 0 deletions
  1. 43 0
      src/bombnet/game.clj
  2. 17 0
      test/bombnet/game_test.clj

+ 43 - 0
src/bombnet/game.clj

@@ -91,6 +91,49 @@
         proposed-state
         (recur (assoc state :players valid-players))))))
 
+(def ^:const min-bomb-timer 1)
+(def ^:const max-bomb-timer 5)
+(def ^:const bomb-power 99)
+
+(defn ^:private clamp [a lbound ubound]
+  (max lbound (min ubound a)))
+
+(defn ^:private merge-by-key [k coll1 coll2]
+  (->> (merge
+         (group-by k coll1)
+         (group-by k coll2))
+       vals
+       (apply concat)))
+
+(defn perform-bomb-placement [state]
+  (let [{bombs :bombs players :players} state
+        get-bomb (fn [p]
+                   (let [pos (:pos p)
+                         power bomb-power
+                         params (:action p)
+                         timer (clamp
+                                 (:timer params)
+                                 min-bomb-timer
+                                 max-bomb-timer)
+                         diagonal? (boolean (:diagonal? params))]
+                     {:pos pos :power power :counter timer :diagonal? diagonal?}))
+        bombs-to-place (->> players
+                            (filter (with-action "bomb"))
+                            (map get-bomb))
+        new-bombs (merge-by-key :pos bombs-to-place bombs)
+        new-players (mapv-if
+                      (with-action "bomb")
+                      #(dissoc % :action)
+                      players)]
+    (-> state
+        (assoc :bombs new-bombs)
+        (assoc :players new-players))))
+
+(let [state {:board (new-board 5 5)
+             :players [{:pos [1 1] :action {:type "bomb" :timer 5}}]
+             :bombs []}]
+  (perform-bomb-placement state))
+
 (defn ^:private offset [pos dir] (mapv + pos dir))
 
 (with-test

+ 17 - 0
test/bombnet/game_test.clj

@@ -97,6 +97,23 @@
       (is (= [1 1] (get-in new-state [:players 0 :pos])))
       (is (= [2 1] (get-in new-state [:players 1 :pos]))))))
 
+(deftest bomb-place-test
+  (testing "Placing a bomb"
+    (let [state {:board (new-board 3 3)
+                 :players [{:id 1 :pos [1 1] :action {:type "bomb" :timer 5}}]
+                 :bombs []}
+          new-state (perform-bomb-placement state)]
+      (is (nil? (get-in new-state [:players 0 :action])))
+      (is (= [{:pos [1 1] :power 99 :counter 5 :diagonal? false}] (:bombs new-state)))))
+  (testing "Placing a bomb on a bomb (disallowed)"
+    (let [troll-bomb {:pos [1 1] :power 1 :counter 1 :diagonal? true}
+          state {:board (new-board 3 3)
+                 :players [{:id 1 :pos [1 1] :action {:type "bomb" :timer 5}}]
+                 :bombs [troll-bomb]}
+          new-state (perform-bomb-placement state)]
+      (is (= [troll-bomb] (:bombs new-state)))))
+  )
+
 (deftest bomb-test
   (testing "People die when they are killed"
     (let [troll-bomb {:pos [5 5] :counter 99 :power 0}