Have you actually run this code? It seems to have a lot of bugs. Also, this is just a style issue, but you seem to be indenting 8 spaces. Lisp convention is to put indents at 2 spaces, because lisp code tends to nest much more than code in C-like languages.
This is unnecessarily complex in two ways, and inefficient in a third. First, [alive? _] is just alive? itself. Second, the length of a list is zero if and only if that list is nil, and nil is itself a false value, so testing (is (len x) 0) when x is a list can be replaced with just (no x). Hence a simpler version would be:
(def doomed (u) (no (keep alive? u)))
; with ssyntax we can simplify this even further:
(def doomed (u) (~keep alive? u))
However, as mentioned by pg, this is still not the most efficient version of the function. If there are several alive cells in u, then (keep alive? u) will find all of them before terminating, when really we want it to exit with failure upon the first live cell it finds in u. Hence any one of (~mem alive? u), (~some alive? u) or (~find alive? u) will be more efficient (it doesn't really matter which you choose in this case).
As far as I can tell, your 'cindex function seems to be meant to take two integers and return a unique index. However, (cindex a b) == b + b*(a-1) == b + ba - b = ab. This obviously collides, for example, with (cindex b a).
You seem to use infix dot for accessing the fields of a cell a lot. This won't work; or example "c.fellas" will expand to "(c fellas)", which will depend on the value that fellas happens to be bound to (if any). What you probably want is "c!fellas", which expands to (c 'fellas).
(def aliveneighbours c (map [isalive _] c.neighbours))
; did you mean this?
(def aliveneighbours (c) (keep alive? c!neighbours))