/
board.clj
109 lines (88 loc) · 3.27 KB
/
board.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
(ns hulkure.board
(:require [clojure.data.json :as json])
(:use [hulkure.utils :only [filter-first
removev]]))
(defn make-board []
{:fields [], ; contains fields. The keys :x and :y are handled like unique keys
:figures [],
:round 0,
:current-player 0})
(defn load [path]
(json/read-str (slurp path) :key-fn keyword))
;; fields
(defn- get-field-with-index [board x y]
"returns [index field]"
(or (filter-first #(and (= x ((second %) :x))
(= y ((second %) :y)))
(map-indexed vector (board :fields)))
[nil nil]))
(defn- get-field-index [board x y]
(first (get-field-with-index board x y)))
(defn get-field
([board xy]
(get-field board (xy :x) (xy :y)))
([board x y]
(last (get-field-with-index board x y))))
(defn remove-field
"remove field at coordinates x and y. Warning: does not handle figures at specified coordinates."
([board xy]
(remove-field board (xy :x) (xy :y)))
([board x y]
(let [[index field] (get-field-with-index board x y)]
(if index
(assoc board :fields (removev (board :fields)
index))
board))))
(defn set-field [board field]
"Update or add field if it does not exist"
(let [index (or (get-field-index board (field :x) (field :y))
(count (board :fields)))]
(assoc-in board [:fields index] field)))
;; figures
(defn get-next-available-figure-id [board]
(if (empty? (board :figures))
0
(inc (apply max (map :id (board :figures))))))
(defn- get-figure-with-index [board id]
"returns [index field]"
(or (filter-first #(= id (% :id)) (board :figures))
[nil nil]))
(defn- get-figure-index [board id]
(second (get-figure-with-index board id)))
(defn get-figure [board id]
(first (get-figure-with-index board id)))
(defn next-available-figure-id [board]
(if (empty? (board :figures))
0
(inc (apply max (map :id (board :figures))))))
(defn set-figure [board figure]
"updates or adds a figure. If no :id is given the next available one will be associated with the figure"
(let [[index figure] (if (figure :id)
[(or (get-figure-index board (figure :id))
(count (board :figures)))
figure]
[(count (board :figures)) (assoc figure :id (next-available-figure-id board))])]
(assoc-in board [:figures index] figure)))
(defn get-figures-at [board x y]
(filterv (fn [figure] (= [x y]
(mapv figure [:x :y])))
(board :figures)))
;; movement related
(def movement-offset
{:forward [0 -1]
:backward [0 1]
:left [-1 0]
:right [ 1 0]
:forward-left [-1 -1]
:forward-right [ 1 -1]
:backward-left [-1 1]
:backward-right [ 1 1]})
(def rotation_matrix {:north [[ 1 0] [ 0 1]]
:west [[ 0 1] [-1 0]]
:east [[ 0 -1] [ 1 0]]
:south [[-1 0] [ 0 -1]]})
(def directions (keys movement-offset))
(defn- matrix-vector-mult [matrix vector]
(map (fn [row] (reduce + (map * row vector))) matrix))
(defn relative-movement-to-offset [movement heading]
(matrix-vector-mult (rotation_matrix heading) (movement-offset movement)))