Python TUT: Conway's Game of Life

Post all your tuts or request for tuts here.
Post Reply
User avatar
Verahta
Posts: 441
Joined: Wed Aug 24, 2011 1:50 am

Python TUT: Conway's Game of Life

Post 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:

Image
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:
Image
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]
"In order to understand recursion, one must first understand recursion".
User avatar
Jackolantern
Posts: 10893
Joined: Wed Jul 01, 2009 11:00 pm

Re: Python TUT: Conway's Game of Life

Post by Jackolantern »

I have always had a strange fascination with Conway's Game of Life 8-)
The indelible lord of tl;dr
User avatar
Verahta
Posts: 441
Joined: Wed Aug 24, 2011 1:50 am

Re: Python TUT: Conway's Game of Life

Post by Verahta »

"In order to understand recursion, one must first understand recursion".
User avatar
Chris
Posts: 1580
Joined: Wed Sep 30, 2009 7:22 pm

Re: Python TUT: Conway's Game of Life

Post by Chris »

Cool! that inspired me to make this :D

See which color is most dominant :D

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>
Fighting for peace is declaring war on war. If you want peace be peaceful.
User avatar
Verahta
Posts: 441
Joined: Wed Aug 24, 2011 1:50 am

Re: Python TUT: Conway's Game of Life

Post 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.
"In order to understand recursion, one must first understand recursion".
User avatar
Chris
Posts: 1580
Joined: Wed Sep 30, 2009 7:22 pm

Re: Python TUT: Conway's Game of Life

Post 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>
Fighting for peace is declaring war on war. If you want peace be peaceful.
Post Reply

Return to “Tutorials”