Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

add clojure starter bot and fix the clojure support to add the local …

…directory to the classpath

Signed-off-by: Chris Granger <ibdknox@gmail.com>
  • Loading branch information...
commit a31a04d96964ba3cb4f0b34e717fd2d5293ced37 1 parent 2270c2c
Chris Granger authored July 04, 2011
13  ants/dist/starter_bots/clojure/MyBot.clj
... ...
@@ -0,0 +1,13 @@
  1
+(ns MyBot
  2
+  (:use ants))
  3
+
  4
+(def directions [:north :east :west :south])
  5
+
  6
+(defn simple-bot []
  7
+  (doseq [ant (my-ants)]
  8
+    (let [dir (first (filter #(unoccupied? (can-move? ant %)) directions))]
  9
+      (when dir
  10
+        (move ant dir)))))
  11
+
  12
+(start-game simple-bot)
  13
+
226  ants/dist/starter_bots/clojure/ants.clj
... ...
@@ -0,0 +1,226 @@
  1
+(ns ants
  2
+  (:require [clojure.string :as string]))
  3
+
  4
+;;****************************************************************
  5
+;; Constants and lookups
  6
+;;****************************************************************
  7
+
  8
+(declare *game-info*)
  9
+(declare *game-state*)
  10
+
  11
+(def init-state {:turn 0
  12
+                 :water #{}
  13
+                 :dead #{}
  14
+                 :enemies #{}
  15
+                 :ants #{}
  16
+                 :food #{}})
  17
+
  18
+(def dir-sym {:north "N"
  19
+              :south "S"
  20
+              :east "E"
  21
+              :west "W"})
  22
+
  23
+(def dir-offset {:north [-1 0]
  24
+                 :west [0 -1]
  25
+                 :south [1 0]
  26
+                 :east [0 1]})
  27
+
  28
+(def offset-dir {[-1 0] :north
  29
+                 [0 -1] :west
  30
+                 [1 0] :south
  31
+                 [0 1] :east})
  32
+
  33
+(def messages {:ready #"ready"
  34
+               :turn #"turn [0-9]+"
  35
+               :end #"end"
  36
+               :go #"go"
  37
+               :tile #"\w \d+ \d+"})
  38
+
  39
+(def map-tiles {"f" :food 
  40
+                "w" :water 
  41
+                "a" :ant 
  42
+                "d" :dead-ant})
  43
+
  44
+;;****************************************************************
  45
+;; Implementation functions
  46
+;;****************************************************************
  47
+
  48
+(defn- parse-tile [msg]
  49
+  (let [[tile row col player :as parts] (string/split (string/lower-case msg) #" ")
  50
+        player (when player
  51
+                     (Integer. player))]
  52
+    {:tile (map-tiles tile)
  53
+     :row (Integer. row)
  54
+     :col (Integer. col)
  55
+     :player player}))
  56
+
  57
+(defn- message? [msg-type msg]
  58
+  (re-seq (messages msg-type) (string/lower-case msg)))
  59
+
  60
+
  61
+(defn- build-game-info []
  62
+  (loop [cur (read-line)
  63
+         info {}]
  64
+    (if (message? :ready cur)
  65
+      info
  66
+      (let [[k v] (string/split cur #" ")
  67
+            neue (assoc info (keyword k) (Integer. v))]
  68
+        (recur (read-line) neue)))))
  69
+
  70
+(defn- get-turn [msg]
  71
+  (Integer. (or (second (string/split msg #" ")) 0)))
  72
+
  73
+(defn- update-tile [state {:keys [tile row col player]}]
  74
+  (let [loc [row col]
  75
+        ant (conj loc player)]
  76
+        (condp = tile
  77
+          :water (update-in state [:water] conj loc)
  78
+          :dead-ant (update-in state [:dead] conj ant)
  79
+          :ant (if (zero? player)
  80
+                 (update-in state [:ants] conj loc) 
  81
+                 (update-in state [:enemies] conj ant))
  82
+          :food (update-in state [:food] conj loc))))
  83
+
  84
+(defn- update-state [state msg]
  85
+  (cond
  86
+    (message? :turn msg) (merge init-state {:turn (get-turn msg) 
  87
+                                            :water (or (:water state) #{})})
  88
+    (message? :tile msg) (update-tile state (parse-tile msg))
  89
+    :else state))
  90
+
  91
+(defn- contains-ant? [ants cur]
  92
+  (some #(let [[r c p] %]
  93
+             (= [r c] cur))
  94
+          ants))
  95
+
  96
+(defn- move-ant 
  97
+  "Return the location defined by moving the given ant in the given
  98
+  direction."
  99
+  [ant dir]
  100
+  (let [dir-vector (dir-offset dir)
  101
+        rows (*game-info* :rows)
  102
+        cols (*game-info* :cols)
  103
+        [r c] (map + ant dir-vector)]
  104
+    [(cond 
  105
+       (< r 0) (+ rows r) 
  106
+       (>= r rows) (- r rows)
  107
+       :else r)
  108
+     (cond 
  109
+       (< c 0) (+ cols c) 
  110
+       (>= c cols) (- c cols)
  111
+       :else c)]))
  112
+
  113
+
  114
+;;****************************************************************
  115
+;; Public functions
  116
+;;****************************************************************
  117
+
  118
+;; TODO: if you want to collect the information and do something
  119
+;; with it at the end, do so here. Look at build-game-info as an
  120
+;; example
  121
+(defn- collect-stats []
  122
+  )
  123
+
  124
+(defn game-info
  125
+  "Get some value from the setup information of the game"
  126
+  [k]
  127
+  (*game-info* k))
  128
+
  129
+(defn move 
  130
+  "Issue a move command for the given ant, where the ant is [row col] and dir
  131
+  is [:north :south :east :west]"
  132
+  [[row col :as ant] dir]
  133
+  (println "o" row col (dir-sym dir)))
  134
+
  135
+(defn turn-num
  136
+  "Get the turn number"
  137
+  []
  138
+  (:turn *game-state*))
  139
+
  140
+(defn my-ants 
  141
+  "Get a set of all ants belonging to you"
  142
+  []
  143
+  (:ants *game-state*))
  144
+
  145
+(defn enemy-ants 
  146
+  "Get a set of all enemy ants where an enemy ant is [row col player-num]"
  147
+  []
  148
+  (:enemies *game-state*))
  149
+
  150
+(defn food 
  151
+  "Get a set of food locations"
  152
+  []
  153
+  (:food *game-state*))
  154
+
  155
+(defn passable? 
  156
+  "Deteremine if the given location can be moved to. If so, loc is returned."
  157
+  [loc]
  158
+  (when (not (contains? (*game-state* :water) loc))
  159
+    loc))
  160
+
  161
+(defn unit-distance 
  162
+  "Get the vector distance between two points on a torus. Negative deltas are 
  163
+  preserved."
  164
+  [loc loc2]
  165
+  (let [[dx dy] (map - loc2 loc)
  166
+        [adx ady] (map #(Math/abs %) [dx dy])
  167
+        [adx2 ady2] (map #(- (game-info %) %2) [:rows :cols] [adx ady])
  168
+        fx (if (<= adx adx2)
  169
+             dx
  170
+             (* adx2 (/ (- dx) adx)))
  171
+        fy (if (<= ady ady2)
  172
+             dy
  173
+             (* ady2 (/ (- dy) ady)))]
  174
+    [fx fy]))
  175
+
  176
+(defn distance 
  177
+  "Get the euclidean distance between two locations on a torus"
  178
+  [loc loc2]
  179
+  (let [[dx dy] (unit-distance loc loc2)]
  180
+    (Math/sqrt (+ (Math/pow dx 2) (Math/pow dy 2)))))
  181
+
  182
+
  183
+(defn can-move? 
  184
+  "Check if moving an ant in the given direction is passable. If so,
  185
+  return the location that the ant would then be in."
  186
+  [ant dir]
  187
+  (passable? (move-ant ant dir)))
  188
+
  189
+(defn unoccupied? 
  190
+  "If the given location does not contain an ant, return loc"
  191
+  [loc]
  192
+  (when (and (not (contains-ant? (my-ants) loc))
  193
+             (not (contains-ant? (enemy-ants) loc)))
  194
+    loc))
  195
+
  196
+(defn direction [loc loc2]
  197
+  "Determine the directions needed to move to reach a specific location.
  198
+  This does not attempt to avoid water. The result will be a collection
  199
+  containing up to two directions."
  200
+  (let [[dr dc] (unit-distance loc loc2)
  201
+        row (if-not (zero? dr)
  202
+            (/ dr (Math/abs dr))
  203
+            dr)
  204
+        col (if-not (zero? dc)
  205
+            (/ dc (Math/abs dc))
  206
+            dc)]
  207
+    (filter #(not (nil? %))
  208
+            [(offset-dir [row 0])
  209
+             (offset-dir [0 col])])))
  210
+
  211
+(defn start-game 
  212
+  "Play the game with the given bot."
  213
+  [bot]
  214
+  (when (message? :turn (read-line))
  215
+    (binding [*game-info* (build-game-info)]
  216
+      (println "go") ;; we're "setup" so let's start
  217
+      (loop [cur (read-line)
  218
+             state {}]
  219
+        (if (message? :end cur) 
  220
+          (collect-stats)
  221
+          (do
  222
+            (when (message? :go cur) 
  223
+              (binding [*game-state* state]
  224
+                (bot) (println "go")))
  225
+            (recur (read-line) (update-state state cur))))))))
  226
+
2  worker/compiler.py
@@ -274,7 +274,7 @@ def compile(self, bot_dir, globs, errors, timelimit):
274 274
         ]
275 275
     ),
276 276
     Language("Clojure", ".clj", "MyBot.clj",
277  
-        "java -Xmx%sm -cp /usr/share/java/clojure.jar clojure.main MyBot.clj" % (MEMORY_LIMIT,),
  277
+		"java -Xmx%sm -cp /usr/share/java/clojure.jar:. clojure.main MyBot.clj" % (MEMORY_LIMIT,),
278 278
         [],
279 279
         [(["*.clj"], ChmodCompiler("Clojure"))]
280 280
     ),

0 notes on commit a31a04d

Please sign in to comment.
Something went wrong with that request. Please try again.