Zen and the art of...

2010-02-22

Redesigning ClojureQL's Frontend

I've not updated this blog in a while as I've been pretty busy for the past few weeks. I've got many projects on the table and one of them is starting to get really interesting. I'm obviously talking about the subject of this post, ClojureQL. I've mainly been working on the backend since the end of last year. In the meantime, Meikel has started a rework of the frontend to provide a cleaner API, free from the magical artifacts introduced by using macros like in the current (0.9.7) version. This rework have been triggered by a post carefully explaining the issue, courtesy of Zef.

I won't go further than a linkfest so here are the important links for those interested in the future of ClojureQL:

We're also ready to receive your suggestions on the brand new clojureql group. Please, visit the Wiki pages and tell us about what you think.

2010-02-07

Google AI Challenge in Clojure

These days, the web have been noisy about the brand new Google sponsored AI Challenge organized by the University of Waterloo Computer Science Club. I find that it's a great initiative and is a good occasion for amateur AI researchers like me to do something else than web development or database related coding. Being fond of Clojure, I've taken on the task of making a starter package for this language and making it available on a GitHub repository. It's not an official package yet, but it shouldn't be a problem as the organizers seems really open.

The code has been translated from the Java starter package. I've tried to keep the map code close to the original, so it may not be the most idiomatic Clojure code. There's four global refs containing the state of the game: width, height, walls and players. The two first are simple integers, walls is an hash map keyed with points (which are vectors) and the last one a vector of points. There's some convenient functions to access that data, wall? to tell if a wall is found at the given coordinates and two others to get each players position, you and them. To move your bike you must call make-move with one of :north, :east, :south or :west. The map code end up being nearly half the size of the Java version.

With this code we can rewrite the sample random bot in Clojure, I'll spare you any more explanation and only show the code.

(load "map")

(defn valid-moves [x y]
  [(when-not (wall? x (- y 1)) :north)
   (when-not (wall? (+ x 1) y) :east)
   (when-not (wall? x (+ y 1)) :south)
   (when-not (wall? (- x 1) y) :west)])

(defn compact [coll]
  (filter identity coll))

(defn choose-at-random [coll]
  (let [size (count coll)]
    (when (< 0 size)
      (nth coll (rand-int size)))))

(defn next-move []
  (choose-at-random
   (compact
    (apply valid-moves (you)))))

(defn game-loop []
  (loop []
    (initialize)
    (make-move (next-move))
    (recur)))

(game-loop)

Hack and be mery!

Update: I've updated the GitHub repository with some improvements and instructions on how to compile your entry. While discussing with one of the contest organizer over their forum, I realized that even though Clojure is more than fast enough for this kind of task, the Clojure jar loading time take a good chunk of the first turn time, so be careful. By the way, it's now an official package.

About Me

My photo
Quebec, Canada
Your humble servant.