Over the weekend I did some work to get Ironclad running with Clojure 1.4 and uploaded it to Github as an open source project. I though that this would be a good milestone to reflect upon the work so far – and in particular I thought I’d share some of the learnings / interesting aspects of developing the game.

Clojure enthusiasts may find it interesting since it is a semi-complete game written in Clojure in a (mostly) functional style.

Functional programming for games

One of the interesting challenge in creating Ironclad was programming a game in a functional style. I actually wrote Ironclad to teach myself Clojure, so was determined to adopt a proper FP style for the core game engine in order to have a good learning experience.

This proved to have a few interesting implications:

The entire game state is immutable – this was a fun challenge, as games tend to have relatively complex nested data structures (including things like indexes for fast lookup of unit locations etc.). A significant part of the work in the core engine was making a library of functions that manipulate the game state and return a new immutable game state.

– this was a fun challenge, as games tend to have relatively complex nested data structures (including things like indexes for fast lookup of unit locations etc.). A significant part of the work in the core engine was making a library of functions that manipulate the game state and return a new immutable game state. I used some Immutable Java data structures for performance. In particular, I wanted a fast map of (x,y) co-ordinate -> Object . I could have used Clojure data structures for this but my tests showed they were a little too slow, particularly when used for the AI routines which do a lot of seaching over these kinds of data structures. So I decided to roll my own. Worked well – Clojure makes it fairly easy to introduce new immutable data structures from the Java world.

for performance. In particular, I wanted a fast map of . I could have used Clojure data structures for this but my tests showed they were a little too slow, particularly when used for the AI routines which do a lot of seaching over these kinds of data structures. So I decided to roll my own. Worked well – Clojure makes it fairly easy to introduce new immutable data structures from the Java world. Testing was delightfully easy – there is something about immutable data that just makes it very easy to test. Partly this is due to the general ease of “programming with values” but I think it also forces to structure your functions / code in a way that is inherently very easy to test.

– there is something about immutable data that just makes it very easy to test. Partly this is due to the general ease of “programming with values” but I think it also forces to structure your functions / code in a way that is inherently very easy to test. Long parameter lists – I struggled a bit with this, and still don’t have a great solution. Because you are using immutable objects and don’t have reference graphs that you can easily traverse to discover context, you often have to pass a lot of arguments. Stuff like “(defn try-fire [ ability unit target game sx sy tx ty aps apcost] ….)”. I still haven’t found a totally satisfactory way to avoid or simplify this – you can do it with higher order functions but IMHO that makes the complexity of the code even worse. Alternatively you can compute all the “context” parameters over and over again but that can kill performance.

Overall I think that the use of FP in games is entirely reasonable and I’d count the Ironclad implementation as a reasonably decent success (at least for my first serious FP game project!). You just have to spend a bit of time bending your head around the new paradigm and adapting to its various advantages and disadvantages.

Prototype-based game objects

This was one of the aspects of the game architecture / codebase that I was most satified with. The combination of Clojure and prototype-based programming using Clojure maps/records as data structures is ideal for game development.

It made implementation of new units trivially easy. Here is the *entire* set of code required to implement the Riflemen, for example:

(make-unit-type {:name "Rifles" :value 40 :size 2 :description "...." :unit-type UNITTYPE_INFANTRY :move-type MOVETYPE_INFANTRY :ix 0 :iy 1 :can-capture true :apsmax 3 :hpsmax 5 :armour 60 :abilities [ (make-move-ability MOVETYPE_INFANTRY) (make-attack-ability { :name "0.303 Rifle" :attack-type ATTACKTYPE_SMALL :max-range 1 :power 60 :cost 1 :consume-all-aps true})] })

As you can see, it’s all very declarative and there is essentially zero boilerplate. What’s more, since the resulting data structure is immutable it not only serves as a decription (prototype) for units in the game it can also be coped directly into the appropriate game data structure to create a new unit. You have no mutability worries (which is frequently the case in OOP-based prototype systems that have references to mutable prototype objects).

Having this combination of conciseness, immutability and declarative power makes it extremely easy to tweak the game balance and experiment with new unit features – work that is essential if you want to create a really great and balanced game.

You can even use this hack together new unit designs at runtime in the REPL – a nice way to test ideas without restarting the whole game to see the effect of each change.

Procedurally generated graphics

One of the interesting concepts in Ironclad was the use of the POVRay renderer to create the game graphics. I did this for a few reasons:

I’m a coder first and foremost. Drawing images is not my forte, but I can write code to generate images pretty fast…..

pretty fast….. I wanted to be able to experiment with the visual look of the game, but not have to redraw new graphics every time. This was a massive benefit – the ability to experiment without significant rework is enormous in terms of unleashing creative potential.

the ability to experiment without significant rework is enormous in terms of unleashing creative potential. You can generate a lot of permutations – in particular each unit requires at a minimum six different rotations and four colours for the different armies. Would be very tedious to do this all by hand, but in POVRay it’s just a simple macro…..

Overall I think I rather like this approach. It’s not a panacea – you still need a lot of attention to detail and hard work to get the graphics generation to look right. But it certainly is a feasible option for lone-coder game developers.

Ideally, I’d like to replace the dependency on POVRay with a Clojure-based raytracer. Apart from the fact that I think Clojure syntax would be idea for a raytracer scene description, it would open up some extra interesting options like having certain graphics elements be rendered on-the-fly during the execution of the game. Hopefully one day Enlight will develop to a point where it can play this role.

Embracing Swing

I made a conscious decision to use the Java-based Swing library as the graphics toolkit. Reasons were as follows:

The Java Swing library is mature and provided in all Java distributions (no extra dependencies)

Clojure’s ability to interoperate with Java is very good

2D graphics in Swing was a good fit for a simple strategy game (I didn’t need anything like OpenGL)

I wanted to use standard UI components, but needed a custom look and feel to get the Steampunk effect. Swing seemed well suited to this task since it has a very flexible look-and-feel mechanism.

Miglayout is an excellent layout manager that takes away much of the pain for creating Java GUI layouts in code. This gave me some comfort that the layout code would be manageable.

As a result I build my own custom look and feel for Swing (steampunk-laf) which contains just about the minimum number of features you need to get a fully customised Swing GUI. This proved to be a more complex task than I thought as the logic of how Swing components behave can get quite complicated, and your custom look and feel needs to accommodate this. Nevertheless I think I got something reasonable decent working. It certainly is a big change from your classic business-oriented Swing GUI….

At the time I wrote Ironclad (2010) the Clojure Swing wrappers weren’t very mature, so I used Swing directly via Java interop. Still the code was pretty reasonable – I ended up with lots of stuff like:

(def bottom-button-panel (let [outer-panel (JPanel.) panel (JPanel.)] (doto outer-panel (.add panel)) (doto panel (.setLayout (GridLayout. 1 3))) (.add panel (JPanel.)) (.add panel button-next-turn) (.add panel button-exit) outer-panel))

The above is probably not ideal – it is a bit too imperative for my tastes and still requires a fair bit of fiddling with Swing internals. But it worked well enough for my purposes. If I was doing it again now I’d probably use Seesaw or something similar to give a more declarative, idiomatic Clojure wrapper to Swing code.

The future

I’m planning to continue to update Ironclad as I think it has the potential to develop into a pretty decent, well-rounded strategy game. Progress will probably be slow as it’s just a hobby project.