Page 1 of 1
Python TUT: Conway's Game of Life
Posted: Wed Aug 06, 2014 8:59 pm
by Verahta
Found this pretty neat Python tutorial for
Conway's Game of Life (cellular automata):
http://stanford.edu/~cpiech/cs221/hando ... orial.html
You create mathematical patterns that seem to take on a life of their own:
Game of Life Overview
Our "Game of Life" board will be an n-by-n grid of square cells, each of which can be either "alive" or "dead". A given cell's neighbors are those cells directly above, below, left, or right of the cell, plus with the cells diagonally adjacent to it (the cells touching its diagonals). Each cell changes from one time step to the next according to the following rules:
Any living cell with fewer than two living neighbors dies.
Any living cell with exactly two or exactly three living neighbors remains alive.
Any living cell with more than three living neighbors dies.
Any dead cell with exactly three living neighbors becomes alive.
These extremely simple rules give rise to some incredibly complex and beautiful patterns, as illustrated here:
In fact, these rules are so powerful that they actually allow Conway's Game of Life to be Turing Complete, which roughly means that we could perform any computation within the game that a standard computer could (though they would be painfully slow). And to just get super meta for a second, a consequence of this is that Game of Life can simulate ITSELF! (#Conwayception)
[YouTube]
https://www.youtube.com/watch?v=D6aP9S9rEQk[/YouTube]
Re: Python TUT: Conway's Game of Life
Posted: Sun Aug 10, 2014 6:22 am
by Jackolantern
I have always had a strange fascination with Conway's Game of Life
Re: Python TUT: Conway's Game of Life
Posted: Mon Aug 18, 2014 7:51 pm
by Verahta
Re: Python TUT: Conway's Game of Life
Posted: Mon Aug 18, 2014 11:54 pm
by Chris
Cool! that inspired me to make this
See which color is most dominant
Code: Select all
<html>
<head>
<style type="text/css">
*{ padding: 0px; margin: 0px; background: #000; }
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="text/javascript">
lifeFormSquareSize = 5;
var Point = function(x,y) {
this.x = x || parseInt(Math.random() * (window.innerWidth/lifeFormSquareSize));
this.y = y || parseInt(Math.random() * (window.innerHeight/lifeFormSquareSize));
return this;
}
Point.prototype.constructor = Point;
Point.prototype = {
x : 0,
y : 0,
colidesWith : function(point) {
return point.x == this.x && point.y == this.y;
},
moveRandomly : function() {
var randomX = Math.random() * 10;
var randomY = Math.random() * 10;
var displaceX = parseInt(Math.random()*lifeFormSquareSize);
var displaceY = parseInt(Math.random()*lifeFormSquareSize);
this.x = parseInt(randomX > 7.5 ? (this.x+displaceX) : (randomX > 5 ? (this.x-displaceX) : this.x));
this.y = parseInt(randomY > 7.5 ? (this.y+displaceY) : (randomY > 5 ? (this.y-displaceY) : this.y));
}
}
var lifeFormList = [];
var LifeForm = function() {
lifeFormList.push(this);
this.point = new Point();
this.color = '#' +(Math.random()*0xFFFFFF<<0).toString(16);
return this;
}
LifeForm.prototype.contructor = LifeForm;
LifeForm.prototype = {
color : '#000000',
point : null,
takeTurn : function() {
for(var i in lifeFormList) {
if(lifeFormList[i] !== this) {
if(this.point.colidesWith(lifeFormList[i].point)) {
var choice = this.makeChoice();
if(choice == 1) {
if(!this.fight() && lifeFormList[i].fight()) {
this.die();
continue;
}
if(this.fight() && !lifeFormList[i].fight()) {
lifeFormList[i].die();
continue;
}
}
if(choice == 2) {
if(this.multiply() || lifeFormList[i].multiply()) {
var child = new LifeForm();
child.point = this.point;
child.color = this.color;
child.point.moveRandomly();
console.log('multiply');
break;
}
}
}
}
}
if(this.randomlyDie()) {
this.die();
}
this.point.moveRandomly();
},
/**
* 1 = fight
* 2 = multiply
* 3 = pass
*/
makeChoice : function() {
var choice = Math.random()*10;
return choice > 7.5 ? 1 : choice > 5 ? 2 : 3;
},
fight : function() {
return Math.random() * 10 > 5;
},
multiply : function() {
return Math.random()*10 > 8;
},
randomlyDie : function() {
return Math.random() * 1000000000 > 999999998;
},
die : function() {
console.log('die');
lifeFormList.pop(this);
}
}
//window.onload = function(){
var canvas = document.getElementById('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
context = canvas.getContext('2d');
for(var i = 0; i <= 200; i++) {
new LifeForm();
}
// life loop
setInterval(function(){
for(var i in lifeFormList) {
lifeFormList[i].takeTurn();
}
},1000/30);
// render loop
setInterval(function(){
context.clearRect(0,0,canvas.width,canvas.height);
for(var i in lifeFormList) {
context.fillStyle = lifeFormList[i].color;
context.fillRect(lifeFormList[i].point.x,lifeFormList[i].point.y,lifeFormSquareSize,lifeFormSquareSize);
}
},1000/30)
//}
</script>
</body>
</html>
Re: Python TUT: Conway's Game of Life
Posted: Tue Aug 19, 2014 12:15 am
by Verahta
Awesome! After I wrap my head around it some mi=ore I'm going to make one too. Changing the size is cool.
Re: Python TUT: Conway's Game of Life
Posted: Tue Aug 19, 2014 12:32 am
by Chris
Code: Select all
<html>
<head>
<style type="text/css">
*{ padding: 0px; margin: 0px; background: #000; }
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="text/javascript">
lifeFormSquareSize = 6;
var Point = function(x,y) {
this.x = x || parseInt(Math.random() * (window.innerWidth/6));
this.y = y || parseInt(Math.random() * (window.innerHeight/6));
return this;
}
Point.prototype.constructor = Point;
Point.prototype = {
x : 0,
y : 0,
colidesWith : function(point) {
return point.x == this.x && point.y == this.y;
},
moveRandomly : function() {
var randomX = Math.random() * 10;
var randomY = Math.random() * 10;
var displaceX = parseInt(Math.random()*lifeFormSquareSize);
var displaceY = parseInt(Math.random()*lifeFormSquareSize);
this.x = parseInt(randomX > 7.5 ? (this.x+displaceX) : (randomX > 5 ? (this.x-displaceX) : this.x));
this.y = parseInt(randomY > 7.5 ? (this.y+displaceY) : (randomY > 5 ? (this.y-displaceY) : this.y));
}
}
var lifeFormList = [];
var LifeForm = function() {
lifeFormList.push(this);
this.point = new Point();
this.color = '#' +(Math.random()*0xFFFFFF<<0).toString(16);
return this;
}
LifeForm.prototype.contructor = LifeForm;
LifeForm.prototype = {
color : '#000000',
point : null,
takeTurn : function() {
for(var i in lifeFormList) {
if(lifeFormList[i] !== this) {
if(this.point.colidesWith(lifeFormList[i].point)) {
var choice = this.makeChoice();
if(choice == 1) {
if(this.fight() && lifeFormList[i].fight()) {
if(Math.random() * 2 < 0.5 ) {
this.die();
} else if(Math.random() * 2 < 1 ) {
lifeFormList[i].die();
}
continue;
}
}
if(choice == 2) {
if(this.multiply() && lifeFormList[i].multiply()) {
var child = new LifeForm();
child.point = this.point;
child.color = this.color;
child.point.moveRandomly();
new Born(this.point);
console.log('multiply');
break;
}
}
if(choice == 3) {
this.color = '#' +(Math.random()*0xFFFFFF<<0).toString(16);
}
}
}
}
if(this.randomlyDie()) {
this.die();
}
this.point.moveRandomly();
},
/**
* 1 = fight
* 2 = multiply
* 3 = pass
*/
makeChoice : function() {
var choice = Math.random()*10;
return choice > 7.5 ? 1 : choice > 5 ? 2 : 3;
},
fight : function() {
return Math.random() * 10 > 5;
},
multiply : function() {
return Math.random()*10 > 8;
},
randomlyDie : function() {
return Math.random() * 1000000000 > 999999998;
},
die : function() {
console.log('die');
lifeFormList.pop(this);
new Die(this.point);
}
}
var dieList = [];
var Die = function(point) {
var _point = new Point(point.x,point.y);
this.point = _point;
dieList.push(this);
var _this = this;
var textInterval = setInterval(function(){
_this.point.y--;
},10);
setTimeout(function(){
clearInterval(textInterval);
dieList.pop(_this);
},500);
}
var bornList = []
var Born = function(point) {
var _point = new Point(point.x,point.y);
this.point = _point;
bornList.push(this);
var _this = this;
var textInterval = setInterval(function(){
_this.point.y--;
},10);
setTimeout(function(){
clearInterval(textInterval);
bornList.pop(_this);
},500);
}
//window.onload = function(){
var canvas = document.getElementById('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
context = canvas.getContext('2d');
for(var i = 0; i <= 500; i++) {
new LifeForm();
}
// life loop
setInterval(function(){
for(var i in lifeFormList) {
lifeFormList[i].takeTurn();
}
},10);
// render loop
setInterval(function(){
context.clearRect(0,0,canvas.width,canvas.height);
for(var i in lifeFormList) {
context.fillStyle = lifeFormList[i].color;
context.fillRect(lifeFormList[i].point.x,lifeFormList[i].point.y,lifeFormSquareSize,lifeFormSquareSize);
}
for(var i in bornList) {
context.fillStyle = '#00FF00';
context.font = '10pt Arial';
context.fillText('BORN', bornList[i].point.x,bornList[i].point.y);
}
for(var i in dieList) {
context.fillStyle = '#FF0000';
context.font = '10pt Arial';
context.fillText('DIED', dieList[i].point.x,dieList[i].point.y);
}
},1000/60)
//}
</script>
</body>
</html>