  var maze;
  var timer; 

	var colors = [];
	colors.walking = 'rgba(60, 60, 255, 1)';
	colors.deadend = 'rgba(200, 80, 80, 1)';
	colors.endpoint = '255,0,0,255';

	var winds = [];
	winds.north = 0;
	winds.east  = 1;
	winds.south = 2;
	winds.west  = 3;

	// some values from the image
  var wall = 2;
  var street = 5;
  var margin = 8;

  // keep track of our tracks
  var _path = [];

  // let's start at the very beginning
  _path.push([0, 0]);

	function currentPixel(direction) {
		direction = direction || false;
		if ('x' == direction) {
			return margin + _path[_path.length - 1][0] * (wall + street);
		} else if ('y' == direction) {
			return margin + _path[_path.length - 1][1] * (wall + street);
		} else {
			return [margin + _path[_path.length - 1][0] * (wall + street),
							margin + _path[_path.length - 1][1] * (wall + street)];
		}
	}

	function isWhite(_color) {
		var result = true;
		jQuery(_color).each( function(_i, _v) {
			if (255 != _v) {
				result = false;
			}
		});
		return result;
	}

	function isEndpoint() {
		// todo: determine endpoint from image ;-)
		return ('119,118' == _path[_path.length - 1]);
	}

  function whereCanIGo() {
  	var _x = currentPixel('x');
  	var _y = currentPixel('y');

  	var result = [];
  	// north
  	if ((_y > margin + wall) && isWhite(maze.getImageData(_x, _y - street, 1, street - 1).data)) { result.push(winds.north); }
  	// east
  	if (isWhite(maze.getImageData(_x + street, _y, street - 1, 1).data)) { result.push(winds.east); }
  	// south
  	if (isWhite(maze.getImageData(_x, _y + street, 1, street - 1).data)) { result.push(winds.south); }
  	// west
  	if ((_x > margin + wall) && isWhite(maze.getImageData(_x - street, _y, street - 1, 1).data)) { result.push(winds.west); }
  	return result;
  }
  
  function leaveFootprint(_spot, _color) {
  	maze.fillStyle = _color;
  	maze.fillRect(_spot[0], _spot[1], street, street);
	}

  function walk() {
		var _c = [];
		_c[0] = _path[_path.length - 1][0];
		_c[1] = _path[_path.length - 1][1];
  	var wcig = whereCanIGo();
  	// todo: remember other directions in case we come back here
		var go = wcig.shift();
		if (undefined == go) {
		  // dead end, go back
		  while (0 == whereCanIGo().length) {
	  		leaveFootprint(currentPixel(), colors.deadend);
	  		_path.pop();
	  	}
		} else {
	  	if (go === winds.north) { _c[1]--; }
	  	else if (go === winds.east) { _c[0]++; }
			else if (go == winds.south) { _c[1]++; }
			else if (go == winds.west) { _c[0]--; }
			else {
			}
			_path.push(_c);
			leaveFootprint(currentPixel(), colors.walking);
		}
  }

  function findYourWay() {
  	if (false === timer) {
  		while (!isEndpoint()) {
  			walk();
  		}
  	} else {
  		walk();
  		if (!isEndpoint()) {
  			timer = setTimeout("findYourWay()",3);
  		}
  	}
  }

  jQuery(document).ready( function() {
 		// set canvas
 		jQuery("<canvas width=853 height=853></canvas>").attr('id', 'cv').appendTo(jQuery("body"));

  	// button to start at high speed
  	jQuery("<div>").text("go fast").click( function() {
  		timer = false;
  		findYourWay();
  	}).appendTo("#buttons");
  	jQuery("<br>").appendTo("#buttons");

  	// button to go with a delay to see what's happening (beats watching Knight Rider)
  	jQuery("<div>").text("tip toe").click( function() {
  		timer = setTimeout("findYourWay()",3);
  	}).appendTo("#buttons");
  	jQuery("<br>").appendTo("#buttons");

 		maze = document.getElementById('cv').getContext('2d');
		var mazePng = jQuery("<img />").attr('src', '37s-maze-big.png').load( function() {
 		  maze.drawImage(this, 0, 0);
		});
  });