Nature, to Be Commanded, Must Be Obeyed

June 08, 2014

Entity-component-system in Clojure

I have been working on this library, clecs, for a couple of months. It is an
entity-component-system (ECS for short) implementation in Clojure. And it is
definitely not production ready yet. This is not going to be a tutorial but I’d
like to go over some decisions/discoveries related to clecs and ECS in general.

One API Many Backends

I didn’t intend to support multiple implementations from the beginning. See,
this is one of the strengths of Clojure; it leads you to design your code for
extensibility by its design. Not long after I started writing the protocol,
there was just one in the beginning, I realized it wouldn’t be too much more
work to add support for multiple backends.

And multiple backends is not a bullet point feature either. I want to create a
library to make writing games in Clojure simple. But I don’t want to do this
by locking those games up with the trade-offs I have made. Or perhaps I should
say I don’t want only those few who are OK with the trade-off I have made to
use my library. It doesn’t take long to realize some open source software is
going to be a liability down the line.

So clecs support multiple backends, users get to choose what is important and
what can be sacrificed. A fast paced game can use an in-memory world and a
massively multiplayer online game can choose to persist its data in a
database cluster. The important point here is that there is one API. When
you are writing your application code you shouldn’t worry about the underlying
data structure or persistence scheme.

There is no hosted API documentation yet, but you can check out the API here.

Why the Rebellious License?

You have all heard the stories about the developer who refused to license his
Clojure software with EPL. How they are taken in black cars with black
tinted windows by mysterious men in black. Disappeared and never seen again.
Well, I am here to tell you all that you have heard is… none of it is true.

But it is true that licensing with EPL is encouraged in Clojure community.
Because it makes sense for components in a software ecosystem to use compatible
licenses. I had an issue with the following part of the EPL license:

This Agreement is governed by the laws of the State of New York and the
intellectual property laws of the United States of America.

I decided to go with the GPL license. I have added the exception mentioned
in section 7 for Clojure. This makes clecs’ license compatible with Clojure’s.
I am not planning to change the license, even to LGPL, anytime soon. But I
would be happy to add more exceptions if necessary/beneficial.

What’s Next?

There is one big and one relatively smaller task ahead, in the programming
department.

The latter is to refactor query sub-system. Currently you pass a filter
function which will be passed a seq of components for each entity. This works
well enough for the reference implementation. But it will definitely fail to
perform for worlds with many (millions?) entities. The function needs to be
replaced with some sort of data structure that defines the query. Then backends
can take this and do specific optimizations.

The bigger task is to create a generative test suite to test backends. The
idea is to treat worlds as black-boxes and run a series of randomly generated
operations on them and compare the results to expected results. This is going
to be tricky because there are actually three contextual levels… Wait, before
that, this is going to be tricky because worlds are mutable and we are
interested in how these data mutations interact with each other. So our tests
are not unit-tests. And there are three contextual levels. Think of atomic
transactions, and within a transaction you run something like a transaction
that you can only run within a transaction and then there are some commands
that are available only outside of a transaction. I know it sounds like mad
talk, but check out world.clj and you’ll see what I mean. I am not mad.

Critics and Comments Welcome!

There are no decent documentation yet. There is an example project but I
think it’s not enough and anyone interested still needs to check out the
source.

This is a phrase I used and have seen being used many times in communities of
3D artists speficically Blender community: critics and comments welcome. There
is not much to help with the project at this time but if you can take a look
and at least tell me about your first impressions it would be great. I have two
main questions:

Do you think having a game development library that is completely agnostic
about rendering, sound & inputs, i.e. doesn’t provide any of these, make
sense?

Do you think the API looks right? Is it idiomatic Clojure from a library
user’s perspective?

If you have any questions, suggestions or corrections feel free to drop me a line.