Skip to content

Instantly share code, notes, and snippets.

@arthurmco
Created February 17, 2018 15:24
Show Gist options
  • Save arthurmco/43a3020ca22d65d8e395dd143856fe7f to your computer and use it in GitHub Desktop.
Save arthurmco/43a3020ca22d65d8e395dd143856fe7f to your computer and use it in GitHub Desktop.
simple pathfinder in clojure
(ns tribalia-pathfinder.core-test
(:require [clojure.test :refer :all]
[tribalia-pathfinder.core :refer :all]))
(defn- squared
[x]
(* x x))
(deftest test-path-euclidian
"Test the euclidian distance function"
(is (= (squared
(path-euclidian-distance {:xPos 1 :yPos 1} {:xPos 2 :yPos 2} )))
2.0))
(deftest test-path-taxicab
(is (= (path-taxicab-distance {:xPos 1 :yPos 1} {:xPos 2 :yPos 2} ))
2))
(def test-path
"The path to what we test"
{:start {:xPos 10 :yPos 20}
:end {:xPos 20 :yPos 40}})
(def test-start (test-path :start))
(def test-end (test-path :end))
(deftest test-calc-point
(is (= ((path-calc-point-score test-start test-start test-end) :f)
(float (path-taxicab-distance test-start test-end)))
"Test if :f is equal to the taxicab distance of starting-ending")
(is (= ((path-calc-point-score test-end test-start test-end) :f)
(path-euclidian-distance test-start test-end)) "Test if :f is equal to the euclidian distance of starting-ending"))
(deftest test-lower-score
(is (= (path-get-lower-score-point {:f 1.2} {:f 1.3} {:f 0.9} {:f 90} )
{:f 0.9}) "First test")
(is (= (path-get-lower-score-point
{:f 0.9912} {:f 0.9913} {:f 0.9909} {:f 0.9990} )
{:f 0.9909}) "Too next values test")
)
(def test-point {:xPos 2 :yPos 6})
(deftest test-path-neighbors
(is (= (count (path-generate-neighbors test-point)) 8))
(is (= (count (set (path-generate-neighbors test-point))) 8))
(is
(= ( count (take-while
#(reduce (fn [oldr pos]
(or oldr (= pos test-point)))
false
(path-generate-neighbors %))
(path-generate-neighbors test-point)))
8) "Check if all neighbors are neighbors of the original point too"))
(ns tribalia-pathfinder.core
(:gen-class))
;;; Help to improve Tribalia pathfinder
(def core-path
"The path to what we test"
{:start {:xPos 10 :yPos 21}
:end {:xPos 20 :yPos 40}})
(defn path-euclidian-distance
"Calculate the Euclidian distance between :pstart and :pend
Return the distance"
[pstart pend]
(Math/sqrt (+ (Math/pow (- (pend :xPos) (pstart :xPos)) 2)
(Math/pow (- (pend :yPos) (pstart :yPos)) 2))))
(defn path-taxicab-distance
"Calculate the taxicab/Manhattan distance between two points
Return the distance"
[pstart pend]
(+ (- (pend :xPos) (pstart :xPos))
(- (pend :yPos) (pstart :yPos))))
(defn path-calc-point-score
"Calculate the point score of a path. Returns the path, with the point score
The g prop is the known movement cost, from the starting point to here
The h prop is the estimated movement cost, from here to end
The f prop is the actual score of the point.
The slot with the lowest 'g' score wins and will be chosen
"
[point pstart pend]
( -> point
(assoc :g (path-euclidian-distance pstart point)
:h (path-taxicab-distance point pend))
(assoc :f (+ (path-euclidian-distance pstart point)
(path-taxicab-distance point pend)))))
(defn path-get-lower-score-point
"Get the point with the lower 'f' score"
[& args]
(reduce (fn [plow pact]
(if (< (plow :f) (pact :f))
plow
pact))
{:f 99999999}
(into () args)))
(defn path-generate-neighbors
"Generate neighbors for some point"
[point]
(let [px (point :xPos) py (point :yPos)]
[(assoc (dissoc point :xPos) :xPos (inc px))
(assoc (dissoc point :xPos) :xPos (dec px))
(assoc (dissoc point :xPos :yPos) :xPos (inc px) :yPos (inc py))
(assoc (dissoc point :xPos :yPos) :xPos (dec px) :yPos (dec py))
(assoc (dissoc point :xPos :yPos) :xPos (inc px) :yPos (dec py))
(assoc (dissoc point :xPos :yPos) :xPos (dec px) :yPos py)
(assoc (dissoc point :yPos) :yPos (inc py))
(assoc (dissoc point :yPos) :yPos (dec py))]
))
(defn -main
"I don't do a whole lot ... yet."
[& args]
(println (path-euclidian-distance (core-path :start) (core-path :end)))
(println (path-taxicab-distance (core-path :start) (core-path :end)))
(println "Hello, World!"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment