init commit
This commit is contained in:
24
src/minibaldur/core.clj
Normal file
24
src/minibaldur/core.clj
Normal file
@@ -0,0 +1,24 @@
|
||||
(ns minibaldur.core
|
||||
(:gen-class)
|
||||
(:require [minibaldur.ecs :refer :all]
|
||||
[minibaldur.engine :refer :all]))
|
||||
|
||||
(defcomponent goblin-ai :void)
|
||||
|
||||
(defentity
|
||||
(name "Goblin")
|
||||
(position {:x 0 :y 0 :z 0})
|
||||
(health 10)
|
||||
(attack "1d4 + 2")
|
||||
(goblin-ai))
|
||||
|
||||
(defentity
|
||||
(:name "Adventurer")
|
||||
(:position {:x 0 :y 0 :z 0})
|
||||
(:health 20)
|
||||
(:attack "1d6 + 3"))
|
||||
|
||||
(defn -main
|
||||
"I don't do a whole lot ... yet."
|
||||
[& args]
|
||||
(println "Hello, World!"))
|
||||
42
src/minibaldur/ecs.clj
Normal file
42
src/minibaldur/ecs.clj
Normal file
@@ -0,0 +1,42 @@
|
||||
(ns minibaldur.ecs
|
||||
(:require [clojure.string :as str]))
|
||||
|
||||
(defonce next-entity (atom 1))
|
||||
(defonce ^:dynamic *components* (atom {}))
|
||||
|
||||
(defmacro defcomponent
|
||||
[comp-name]
|
||||
`(do
|
||||
(swap! *components* assoc ~(keyword comp-name) {})
|
||||
(defn ~comp-name
|
||||
([entity#] (get-in @*components* [~(keyword comp-name) entity#]))
|
||||
([entity# value#] (swap! *components* assoc-in [~(keyword comp-name) entity#] value#)))))
|
||||
|
||||
(defmacro defentity
|
||||
[& components]
|
||||
(let [entity (gensym)]
|
||||
`(let [~entity (first (swap-vals! next-entity inc))]
|
||||
~@(for [[comp-name comp-value] components]
|
||||
`(~comp-name ~entity ~comp-value)))))
|
||||
|
||||
(defn query-e
|
||||
"Return known entitys matching a query"
|
||||
[query]
|
||||
(if (keyword? query)
|
||||
(some-> (query @*components*) keys)
|
||||
(loop [ents (query-e (first query))
|
||||
fils (next query)]
|
||||
(if (nil? fils)
|
||||
ents
|
||||
(recur (filter (set ents) (query-e (first fils))) (next fils))))))
|
||||
|
||||
(defn run-e
|
||||
"Run system on all entities matching query"
|
||||
[f query & args]
|
||||
(doseq [entity (query-e query)]
|
||||
(apply f entity args)))
|
||||
|
||||
(defn find-entity-by
|
||||
[component value]
|
||||
(some #(and (= value (val %)) (key %))
|
||||
(@*components* component)))
|
||||
30
src/minibaldur/engine.clj
Normal file
30
src/minibaldur/engine.clj
Normal file
@@ -0,0 +1,30 @@
|
||||
(ns minibaldur.engine)
|
||||
|
||||
(defn diceroll
|
||||
[x]
|
||||
(re-find #"(\d+)d(\d+)" x))
|
||||
|
||||
(defn diceval
|
||||
[x]
|
||||
(if-let [[_ a b] (diceroll x)]
|
||||
(apply + (repeat (Integer/parseInt a)
|
||||
(+ (rand-int (Integer/parseInt b)) 1)))
|
||||
(Integer/parseInt x)))
|
||||
|
||||
(defn roll
|
||||
"Takes a standard ttrpg roll specifier and returns a vector, starting with the sum, and
|
||||
then each roll in the order listed in the specifier"
|
||||
[specifier]
|
||||
(let [dies-and-ops (clojure.string/split specifier #"\s+")
|
||||
first-die-val (diceval (first dies-and-ops))
|
||||
first-die-roll? (diceroll (first dies-and-ops))]
|
||||
(loop [sum first-die-val
|
||||
rolls (if first-die-roll? [first-die-val] [])
|
||||
tail (next dies-and-ops)]
|
||||
(if-let [[op die] tail]
|
||||
(let [roll? (diceroll die)
|
||||
val (diceval die)]
|
||||
(case op
|
||||
"+" (recur (+ sum val) (if roll? (conj rolls val) rolls) (nnext tail))
|
||||
"-" (recur (- sum val) (if roll? (conj rolls val) rolls) (nnext tail))))
|
||||
(into [sum] rolls)))))
|
||||
Reference in New Issue
Block a user