Question

I am trying to replicate Conway's Game of Life and though my code seems to be kosher it appears not to behave like it should.

This is the basic meat of it:

  if (pressingSpace) { 
     running = true;
  } else {
    running = false;
  };

  if (running) {
    for (var i=0; i<tiles.length; i++) {
      var tile = tiles[i];
      if (tile.alive && (tile.neighborsAlive() < 2 || tile.neighborsAlive() > 3)) {
        tile.die();
      };
      if (!tile.alive && tile.neighborsAlive() == 3) {
        tile.comeToLife();
      }; 
    };
  };

  for (var i=0; i<tiles.length; i++) {
    var key = tiles[i];
    if (!key.alive && mouseDown && key.sprite.contains([cursorX,cursorY]) && cursorX != null) {
      key.comeToLife();
    }
  };

All the functions in play have been thoroughly tested and seem to work as expected. But when this is run, the "alive" squares seem to overrun the screen much more easily than they should. In particular when a column is made three tiles high, it vanishes on the next frame when it should, per the rules, produce two "alive" tiles on either side at the same time.

I suspect this has something to do with the order of operations. Do I need to "mark" appropriate tiles for a state change, instead of change them on the spot? I know there are a lot of implementations of Conway out there but I'm trying to develop this on my own-ish. That said, any nudges in the right direction would be greatly appreciated. Thanks!

You can see it in action here: http://www.eggborne.com/tiles

Was it helpful?

Solution

As far as I can see, it's because of you change tilemap while iterating over it.

E.g. I assume .comeToLife() method changes .alive field to true, and if .neighborsAlive() return non-cached value, but calculates .alive tiles around, you are essentially changing your playfield while iterating, and newly changed cells ruin the whole picture.

Easiest solution will be to create 'old' and 'new' tilemaps, and iterate over 'old' one, while bringing changes to 'new' only. Caching 'neighborsAlive' is essentially creating two arrays, just in different way — that way you're also creating a tilemap, with each tile holding a value of how many neighbors are alive at this moment — and you have to determine this value before everything else changes. If you don't, you will have the same issue, as you currently have.

For demonstration of your problem, make your playfield update with each tile change — you will see your problem animated :)

Hope this helps your issue.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top