Pull to refresh

Игра Жизнь на LiveScript в 30 строк

Reading time3 min
Views8.5K
В продолжение 30-ти строчного мема, выкладываю реализацию известной игры Жизнь на LiveScript (язык, транслируемый в Javascript).

Игра жизнь — это клеточный автомат с простыми правилами:
  • Имеется поле с клетками, которые могут быть в двух состояниях: живая и мертвая
  • Если у мертвой клетки ровно три живых соседа, то она оживает
  • Если у живой клетки два или три живых соседа, то она продолжает жить, в противном случае она умирает от перенаселенности или одиночества

Для начала, сам код:
stopped=true

document.body.onkeyup = (e) -> e.keyCode==13 && stopped := !stopped

change = (div, a) -> 
    div.setAttribute(\class, a  and "cell active" or "cell")
    div.ac=a
    
window.activate = (div) ->
    div.ac ?= false
    change div, !div.ac
    
setInterval ->
    unless stopped
        arr=document.getElementById("board").children
        newarr=[[false for _ to arr[0].children.length-1] for _ to arr.length-1]
        c=0
        
        for i in [0 to arr.length-1]
            for j in [0 to arr[i].children.length-1]
                for sx in [i-1 to i+1]
                    for sy in [j-1 to j+1] when not (sy == j and sx ==i)
                        arr[(sx+newarr.length)%newarr.length].children[(sy+newarr[0].length)%newarr[0].length].ac and ++c
                (c == 3 or (c == 2 and arr[i].children[j].ac)) and newarr[i][j]=true
                c=0
                
        for i in [0 to newarr.length-1]
            for j in [0 to newarr[i].length-1]
                    change arr[i].children[j], newarr[i][j] 
, 1000/15

Как видно, код простой и лаконичный. Отсутствие фигурных скобок позволяет сократить размер кода.
И ссылка на jsfiddle. Вначале задайте изначальное состояние поля (которое закольцовано), после чего нажмите enter и игра начнется.

А вот результат трансляции:
// Generated by LiveScript 1.2.0
(function(){
  var stopped, change;
  stopped = true;
  document.body.onkeyup = function(e){
    return e.keyCode === 13 && (stopped = !stopped);
  };
  change = function(div, a){
    div.setAttribute('class', a && "cell active" || "cell");
    return div.ac = a;
  };
  window.activate = function(div){
    div.ac == null && (div.ac = false);
    return change(div, !div.ac);
  };
  setInterval(function(){
    var arr, newarr, res$, i$, to$, _, lresult$, j$, to1$, c, ref$, len$, i, ref1$, len1$, j, k$, ref2$, len2$, sx, l$, ref3$, len3$, sy, lresult1$, results$ = [];
    if (!stopped) {
      arr = document.getElementById("board").children;
      res$ = [];
      for (i$ = 0, to$ = arr.length - 1; i$ <= to$; ++i$) {
        _ = i$;
        lresult$ = [];
        for (j$ = 0, to1$ = arr[0].children.length - 1; j$ <= to1$; ++j$) {
          _ = j$;
          lresult$.push(false);
        }
        res$.push(lresult$);
      }
      newarr = res$;
      c = 0;
      for (i$ = 0, len$ = (ref$ = (fn$())).length; i$ < len$; ++i$) {
        i = ref$[i$];
        for (j$ = 0, len1$ = (ref1$ = (fn1$())).length; j$ < len1$; ++j$) {
          j = ref1$[j$];
          for (k$ = 0, len2$ = (ref2$ = (fn2$())).length; k$ < len2$; ++k$) {
            sx = ref2$[k$];
            for (l$ = 0, len3$ = (ref3$ = (fn3$())).length; l$ < len3$; ++l$) {
              sy = ref3$[l$];
              if (!(sy === j && sx === i)) {
                arr[(sx + newarr.length) % newarr.length].children[(sy + newarr[0].length) % newarr[0].length].ac && ++c;
              }
            }
          }
          (c === 3 || (c === 2 && arr[i].children[j].ac)) && (newarr[i][j] = true);
          c = 0;
        }
      }
      for (i$ = 0, len$ = (ref$ = (fn4$())).length; i$ < len$; ++i$) {
        i = ref$[i$];
        lresult1$ = [];
        for (j$ = 0, len1$ = (ref1$ = (fn5$())).length; j$ < len1$; ++j$) {
          j = ref1$[j$];
          lresult1$.push(change(arr[i].children[j], newarr[i][j]));
        }
        results$.push(lresult1$);
      }
      return results$;
    }
    function fn$(){
      var i$, to$, results$ = [];
      for (i$ = 0, to$ = arr.length - 1; i$ <= to$; ++i$) {
        results$.push(i$);
      }
      return results$;
    }
    function fn1$(){
      var i$, to$, results$ = [];
      for (i$ = 0, to$ = arr[i].children.length - 1; i$ <= to$; ++i$) {
        results$.push(i$);
      }
      return results$;
    }
    function fn2$(){
      var i$, to$, results$ = [];
      for (i$ = i - 1, to$ = i + 1; i$ <= to$; ++i$) {
        results$.push(i$);
      }
      return results$;
    }
    function fn3$(){
      var i$, to$, results$ = [];
      for (i$ = j - 1, to$ = j + 1; i$ <= to$; ++i$) {
        results$.push(i$);
      }
      return results$;
    }
    function fn4$(){
      var i$, to$, results$ = [];
      for (i$ = 0, to$ = newarr.length - 1; i$ <= to$; ++i$) {
        results$.push(i$);
      }
      return results$;
    }
    function fn5$(){
      var i$, to$, results$ = [];
      for (i$ = 0, to$ = newarr[i].length - 1; i$ <= to$; ++i$) {
        results$.push(i$);
      }
      return results$;
    }
  }, 1000 / 15);
}).call(this);



Также проведу небольшой обзор языка, может кто и заинтересуется.
LiveScript похож на уже ставший известным CoffeeScript, но также имеет элементы функциональных языков, синтаксический сахар для многих конструкций.
Рассмотрим базовые элементы синтаксиса:

Определение функции:
add = (x, y) -> x+y

Вызов функции:
add 5 6
add(5, 6)
add 5, 6

Циклы:
for i in [0 to 10]
    console.log i

Строки без пробелов можно записывать в таком виде:
a = \string
alert \str

Определение класса:
class Accumulator
  (num) ->
    @acc = num
  sum:8
  add: (n) ->
    @acc+=n
    @acc+@sum  #returns

a = new Accumulator 1
a.sum # 8
a.acc  # 1
a.add 9 # @acc now 10; return 18


На этом всё. Спасибо за внимание.
Tags:
Hubs:
Total votes 43: ↑14 and ↓29-15
Comments9

Articles