#
# life.jako
#
# Play Conway's (no, not *him*. The other Conway) game of life.
#
# Based on life.pasm, Hacked by Leon Brocard <acme@astray.com> to use curses.
#
# The original version of 2002-12-05 can be found here:
#
#     http://archive.develooper.com/perl6-internals@perl.org/msg13935.html
#

use sys;
use string;
use Curses;

var int foo; # Store result from above functions here.

const int G = 5000; # Generation count.

const int WIDTH  = 15;
const int HEIGHT = 15;

const str r00 = "               ";
const str r01 = "               ";
const str r02 = "               ";
const str r03 = "               ";
const str r04 = "   **          ";
const str r05 = " *    *        ";
const str r06 = "       *       ";
const str r07 = " *     *       ";
const str r08 = "  ******       ";
const str r09 = "               ";
const str r10 = "               ";
const str r11 = "               ";
const str r12 = "               ";
const str r13 = "               ";
const str r14 = "               ";


#
# at()
#
# Return 1 if the cell at row, col is alive, otherwise 0.
#

sub int at (str cells, int row, int col)
{
  var str temp;
  var int offset;

  row += HEIGHT; # In case they are slightly negative.
  col += WIDTH;

  row %= HEIGHT;
  col %= WIDTH;

  offset = row * WIDTH;
  offset += col;

  var int len;
  len = string::length(cells);
  foo = Curses::move(0, 19);
  foo = Curses::addstr("length(cells) == $len");
  foo = Curses::move(0, 20);
  foo = Curses::addstr("substr(cells, $offset, 1)");
  foo = Curses::move(0, 25);
  foo = Curses::refresh();
  temp = string::substr(cells, offset, 1);

  return 1 if (temp == "*");
  return 0;
}


#
# generate()
#

sub str generate (str cells)
{
  var str temp = "";

  var int row = 0;

  while (row < HEIGHT) {
    var int col = 0;

    while (col < WIDTH) {
      var int count = 0;
      var int r, c;
      var int cell;

      r = row - 1; c = col - 1; cell = at(cells, r, c); count += cell; # NW
      r = row - 1; c = col    ; cell = at(cells, r, c); count += cell; # N
      r = row - 1; c = col + 1; cell = at(cells, r, c); count += cell; # NE

      r = row    ; c = col - 1; cell = at(cells, r, c); count += cell; # W
      r = row    ; c = col + 1; cell = at(cells, r, c); count += cell; # E

      r = row + 1; c = col - 1; cell = at(cells, r, c); count += cell; # SW
      r = row + 1; c = col    ; cell = at(cells, r, c); count += cell; # S
      r = row + 1; c = col + 1; cell = at(cells, r, c); count += cell; # SE

      var int current;
      current = at(cells, row, col);

      var str ch;
      if (current != 0) {
        foo = Curses::move(0, 21);
        foo = Curses::addstr("substr(\"   *     \", $count, 1)");
        foo = Curses::move(0, 25);
        foo = Curses::refresh();

        ch = string::substr("   *     ", count, 1);
      }
      else {
        foo = Curses::move(0, 21);
        foo = Curses::addstr("substr(\"  **     \", $count, 1)");
        foo = Curses::move(0, 25);
        foo = Curses::refresh();

        ch = string::substr("  **     ", count, 1);
      }

      string::concat(temp, ch);

      col++;
    }

    row++;
  }

  return temp;
}


#
# dump()
#

sub dump(str cells, int g)
{
  foo = Curses::move(0, 0);
  foo = Curses::addstr("Generation $g of $G:");

  var int row = 0;
  while (row < HEIGHT) {
    var int col = 0;
    while (col < WIDTH) {
      var int current;
      current = at(cells, row, col);

      if (current == 1) {
        Curses::addstr("*");
      }
      else {
        Curses::addstr(" ");
      }
    }
    Curses::addstr("\n");
  }

  foo = Curses::move(0, 25);
  foo = Curses::refresh();
}


foo = Curses::initscr();
foo = Curses::curs_set(0);

var num start;
start = sys::timen();

var str cells = "";

string::concat(cells, r00);
string::concat(cells, r01);
string::concat(cells, r02);
string::concat(cells, r03);
string::concat(cells, r04);
string::concat(cells, r05);
string::concat(cells, r06);
string::concat(cells, r07);
string::concat(cells, r08);
string::concat(cells, r09);
string::concat(cells, r10);
string::concat(cells, r11);
string::concat(cells, r12);
string::concat(cells, r13);
string::concat(cells, r14);

dump(cells, 0);

var int g = 0; # Number of generations so far.

while (g < G) {
  cells = generate(cells);
  dump(cells, g);
  sys::sleep(1);
}

foo = Curses::curs_set(1);
foo = Curses::endwin();

