| 
									
										
										
										
											2011-03-09 16:14:08 +03:00
										 |  |  | var DEBUG = true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function log(text){ | 
					
						
							|  |  |  | 	document.getElementById('log').innerHTML += text + '<br>' | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var Field = function(field_id){ | 
					
						
							|  |  |  | 	return ({ | 
					
						
							|  |  |  | 		// XXX HACK: get this from CSS...
 | 
					
						
							|  |  |  | 		APPLE_COLOR: 'red', | 
					
						
							|  |  |  | 		WALL_COLOR: 'gray', | 
					
						
							|  |  |  | 		FIELD_COLOR: 'white', | 
					
						
							|  |  |  | 		TICK: 200, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// interface...
 | 
					
						
							|  |  |  | 		init: function(field_id, on_kill, on_apple_eaten){ | 
					
						
							|  |  |  | 			this.field = document.getElementById(field_id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// this depends on topology...
 | 
					
						
							|  |  |  | 			// NOTE: we consider that the field may not change during operation...
 | 
					
						
							|  |  |  | 			this.cells = this.field.getElementsByTagName("td") | 
					
						
							|  |  |  | 			this.height = this.field.getElementsByTagName("tr").length | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			this.cell_count = this.cells.length | 
					
						
							|  |  |  | 			this.width = this.cell_count / this.height | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			this.on_kill = on_kill | 
					
						
							|  |  |  | 			this.on_apple_eaten = on_apple_eaten | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			this._timer = null | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			this.reset() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// rotation tables...
 | 
					
						
							|  |  |  | 			this._cw = { | 
					
						
							|  |  |  | 				'n': 'e',  | 
					
						
							|  |  |  | 				's': 'w', | 
					
						
							|  |  |  | 				'e': 's', | 
					
						
							|  |  |  | 				'w': 'n' | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			this._ccw = { | 
					
						
							|  |  |  | 				'n': 'w',  | 
					
						
							|  |  |  | 				's': 'e', | 
					
						
							|  |  |  | 				'e': 'n', | 
					
						
							|  |  |  | 				'w': 's' | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return this | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		// setup/reset the field to it's original state.
 | 
					
						
							|  |  |  | 		reset: function(){ | 
					
						
							|  |  |  | 			this._snakes = {} | 
					
						
							|  |  |  | 			this._tick = 0 | 
					
						
							|  |  |  | 			this.stop() | 
					
						
							|  |  |  | 			for(var i=0; i < this.cells.length; i++){ | 
					
						
							|  |  |  | 				var cell = this.Cell(i) | 
					
						
							|  |  |  | 				cell.o.style.backgroundColor = this.FIELD_COLOR | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// do a single step...
 | 
					
						
							|  |  |  | 		step: function(){ | 
					
						
							|  |  |  | 			var cells = this.cells | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			for(var i=0; i < cells.length; i++){ | 
					
						
							|  |  |  | 				var cell = this.Cell(i) | 
					
						
							|  |  |  | 				// identify the object...
 | 
					
						
							|  |  |  | 				if(this.is_snake(cell)){ | 
					
						
							|  |  |  | 					this.Snake(cell.o.style.backgroundColor, cell).step() | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			this._tick += 1 | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		start: function(tick){ | 
					
						
							|  |  |  | 			var that = this | 
					
						
							|  |  |  | 			if(tick === null){ | 
					
						
							|  |  |  | 				tick = this.TICK | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if(this._timer === null){ | 
					
						
							|  |  |  | 				this._timer = setInterval(function(){that.step()}, tick) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		stop: function(){ | 
					
						
							|  |  |  | 			if(this._timer === null){ | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			clearInterval(this._timer) | 
					
						
							|  |  |  | 			this._timer = null | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// get a cell helper...
 | 
					
						
							|  |  |  | 		Cell: function(n){ | 
					
						
							|  |  |  | 			var that = this | 
					
						
							|  |  |  | 			var cells = this.cells | 
					
						
							|  |  |  | 			return ({ | 
					
						
							|  |  |  | 				// NOTE: this will be null if a cell does not exist.
 | 
					
						
							|  |  |  | 				o: cells[n], | 
					
						
							|  |  |  | 				index: n, | 
					
						
							|  |  |  | 				// NOTE: these are cyclic...
 | 
					
						
							|  |  |  | 				n: function(){ | 
					
						
							|  |  |  | 					var t = n - that.width | 
					
						
							|  |  |  | 					if(t < 0) | 
					
						
							|  |  |  | 						t = that.cells.length + t | 
					
						
							|  |  |  | 					return that.Cell(t) | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				s: function(){ | 
					
						
							|  |  |  | 					var t = n + that.width | 
					
						
							|  |  |  | 					if(t > that.cells.length-1) | 
					
						
							|  |  |  | 						t = t - that.cells.length | 
					
						
							|  |  |  | 					return that.Cell(t) | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				e: function(){ | 
					
						
							|  |  |  | 					var t = n + 1 | 
					
						
							|  |  |  | 					if(Math.floor(t/that.width) > Math.floor(n/that.width)) | 
					
						
							|  |  |  | 						t = t - that.width | 
					
						
							|  |  |  | 					return that.Cell(t) | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				w: function(){ | 
					
						
							|  |  |  | 					var t = n - 1 | 
					
						
							|  |  |  | 					if(Math.floor(t/that.width) < Math.floor(n/that.width)) | 
					
						
							|  |  |  | 						t = t + that.width | 
					
						
							|  |  |  | 					return that.Cell(t) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		// get a cell by it's coordinates...
 | 
					
						
							|  |  |  | 		cell: function(x, y){ | 
					
						
							|  |  |  | 			return this.Cell(x + (y-1) * this.width) | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// add a snake to the field...
 | 
					
						
							|  |  |  | 		// XXX BUG: size of 1 makes the snake endless...
 | 
					
						
							|  |  |  | 		Snake: function(color, cell, direction, size){ | 
					
						
							|  |  |  | 			var that = this | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// draw the snake if it does not exist...
 | 
					
						
							|  |  |  | 			if(this._snakes[color] == null){ | 
					
						
							|  |  |  | 				cell.o.style.backgroundColor = color | 
					
						
							|  |  |  | 				cell.o.age = size | 
					
						
							|  |  |  | 				this._snakes[color] = { | 
					
						
							|  |  |  | 					'direction':direction, | 
					
						
							|  |  |  | 					'size': size | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// NOTE: the only things this uses from the above scope is color and that.
 | 
					
						
							|  |  |  | 			// NOTE: color is the onlu thing that can't change in a snake.
 | 
					
						
							|  |  |  | 			return ({ | 
					
						
							|  |  |  | 				// XXX BUG: the last cell of a dead snake lives an extra tick...
 | 
					
						
							|  |  |  | 				kill: function(){ | 
					
						
							|  |  |  | 					// this will disable moving and advancing the snake...
 | 
					
						
							|  |  |  | 					that._snakes[color].size = 0 | 
					
						
							|  |  |  | 					if(that.on_kill != null){ | 
					
						
							|  |  |  | 						that.on_kill(that) | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				step: function(){ | 
					
						
							|  |  |  | 					var direction = that._snakes[color].direction | 
					
						
							|  |  |  | 					var size = that._snakes[color].size | 
					
						
							|  |  |  | 					var target = cell[direction]() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// skip a cell if it's already handled at this step.
 | 
					
						
							|  |  |  | 					if(cell.o.moved_at == that._tick){ | 
					
						
							|  |  |  | 						return | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// do this only for the head...
 | 
					
						
							|  |  |  | 					if(parseInt(cell.o.age) == size){ | 
					
						
							|  |  |  | 						// handle field bounds...
 | 
					
						
							|  |  |  | 						if(target.o == null){ | 
					
						
							|  |  |  | 							alert('out of bounds!') | 
					
						
							|  |  |  | 							return | 
					
						
							|  |  |  | 						}  | 
					
						
							|  |  |  | 						// kill conditions: walls and other snakes...
 | 
					
						
							|  |  |  | 						if(that.is_snake(target) || that.is_wall(target)){ | 
					
						
							|  |  |  | 							// XXX move this to a separate action
 | 
					
						
							|  |  |  | 							this.kill() | 
					
						
							|  |  |  | 							return | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						// apple... 
 | 
					
						
							|  |  |  | 						if(that.is_apple(target)){ | 
					
						
							|  |  |  | 							// grow the snake by one...
 | 
					
						
							|  |  |  | 							// XXX move this to a separate action
 | 
					
						
							|  |  |  | 							that._snakes[color].size += 1 | 
					
						
							|  |  |  | 							size = that._snakes[color].size | 
					
						
							|  |  |  | 							if(that.on_apple_eaten != null){ | 
					
						
							|  |  |  | 								that.on_apple_eaten(that) | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						// all clear, do the move...
 | 
					
						
							|  |  |  | 						target.o.style.backgroundColor = color | 
					
						
							|  |  |  | 						target.o.age = size | 
					
						
							|  |  |  | 						target.o.moved_at = that._tick | 
					
						
							|  |  |  | 						cell.o.age = size - 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					} else {  | 
					
						
							|  |  |  | 						if(cell.o.age <= 1) { | 
					
						
							|  |  |  | 							cell.o.style.backgroundColor = that.FIELD_COLOR | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						cell.o.age = parseInt(cell.o.age) - 1 | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// user interface...
 | 
					
						
							|  |  |  | 				left: function(){ | 
					
						
							|  |  |  | 					that._snakes[color].direction = that._ccw[that._snakes[color].direction] | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				right: function(){ | 
					
						
							|  |  |  | 					that._snakes[color].direction = that._cw[that._snakes[color].direction] | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		is_snake: function(cell){ | 
					
						
							|  |  |  | 			var snakes = this._snakes | 
					
						
							|  |  |  | 			var color = cell.o.style.backgroundColor | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			for(var c in snakes){ | 
					
						
							|  |  |  | 				if(c == color) | 
					
						
							|  |  |  | 					return true | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return false | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Apple: function(cell){ | 
					
						
							|  |  |  | 			cell.o.style.backgroundColor = this.APPLE_COLOR | 
					
						
							|  |  |  | 			return cell | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		is_apple: function(cell){ | 
					
						
							|  |  |  | 			return cell.o.style.backgroundColor == this.APPLE_COLOR | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Wall: function(cell){ | 
					
						
							|  |  |  | 			cell.o.style.backgroundColor = this.WALL_COLOR | 
					
						
							|  |  |  | 			return cell | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		is_wall: function(cell){ | 
					
						
							|  |  |  | 			return cell.o.style.backgroundColor == this.WALL_COLOR | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		is_empty: function(cell){ | 
					
						
							|  |  |  | 			return cell.o.style.backgroundColor == this.FIELD_COLOR | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}).init(field_id) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // this defines the basic game logic and controls the rules and levels...
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  | 	NOTE: it is recommended to create game objects in the folowing order: | 
					
						
							|  |  |  | 		1) walls | 
					
						
							|  |  |  | 		2) apples | 
					
						
							|  |  |  | 		3) players | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function JSSnakeGame(field){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var game = { | 
					
						
							|  |  |  | 		field: field, | 
					
						
							|  |  |  | 		TICK: 300, | 
					
						
							| 
									
										
										
										
											2011-03-17 15:28:43 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// this enables snakes of the same colors...
 | 
					
						
							|  |  |  | 		SIMILAR_COLORS: false, | 
					
						
							|  |  |  | 		used_colors: function(){ | 
					
						
							|  |  |  | 			// this is a workaround the inability to directly create an object
 | 
					
						
							|  |  |  | 			// with field names not a literal identifier or string...
 | 
					
						
							|  |  |  | 			var res = {} | 
					
						
							|  |  |  | 			res[field.FIELD_COLOR] = true | 
					
						
							|  |  |  | 			res[field.WALL_COLOR] = true | 
					
						
							|  |  |  | 			res[field.APPLE_COLOR] = true | 
					
						
							|  |  |  | 			return res | 
					
						
							|  |  |  | 		}(), | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-09 16:14:08 +03:00
										 |  |  | 		// utility methods...
 | 
					
						
							|  |  |  | 		_random_empty_cell: function(){ | 
					
						
							|  |  |  | 			// NOTE: if we are really unlucky, this will take 
 | 
					
						
							|  |  |  | 			//       really long, worse, if we are infinitely unlucky
 | 
					
						
							|  |  |  | 			//       this will take an infinite amount of time... (almost)
 | 
					
						
							|  |  |  | 			var field = this.field | 
					
						
							|  |  |  | 			var i = field.cells.length-1 | 
					
						
							|  |  |  | 			var l = i | 
					
						
							|  |  |  | 			while(true){ | 
					
						
							|  |  |  | 				var c = field.Cell(Math.round(Math.random()*l)) | 
					
						
							|  |  |  | 				if(field.is_empty(c)) | 
					
						
							|  |  |  | 					return c | 
					
						
							|  |  |  | 				i-- | 
					
						
							|  |  |  | 				if(i == 0) | 
					
						
							|  |  |  | 					return null | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2011-03-17 15:28:43 +03:00
										 |  |  | 		// key handler...
 | 
					
						
							|  |  |  | 		// functions:
 | 
					
						
							|  |  |  | 		// 	- control snake - dispatch player-specific keys to player-specific snake
 | 
					
						
							|  |  |  | 		// 	- create player - two unused keys pressed within timeout, random color 
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							|  |  |  | 		// modes:
 | 
					
						
							|  |  |  | 		// 	- player add
 | 
					
						
							|  |  |  | 		// 	- game control
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							|  |  |  | 		// NOTE: modes can intersect...
 | 
					
						
							|  |  |  | 		// NOTE: modes are game state dependant...
 | 
					
						
							| 
									
										
										
										
											2011-07-02 19:00:11 +04:00
										 |  |  | 		key_time_frame: 0.5, | 
					
						
							|  |  |  | 		pending_key: null, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-17 15:28:43 +03:00
										 |  |  | 		_keyHandler: function(evt){ | 
					
						
							| 
									
										
										
										
											2011-07-02 19:00:11 +04:00
										 |  |  | 			var name, color | 
					
						
							| 
									
										
										
										
											2011-03-17 15:28:43 +03:00
										 |  |  | 			var key = window.event ? event.keyCode : evt.keyCode | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-02 19:00:11 +04:00
										 |  |  | 			// find a target registered for key...
 | 
					
						
							|  |  |  | 			// XXX
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// no one is registered...
 | 
					
						
							|  |  |  | 			// if wait time set and is not exceeded create a player and register keys
 | 
					
						
							|  |  |  | 			if(!this.pending_key || Date().getTime() - this.pending_key['time'] > this.key_time_frame ){ | 
					
						
							|  |  |  | 				// if no wait time is set, set it and remember the key...
 | 
					
						
							|  |  |  | 				this.pending_key = {time: Date().getTime(), key: key} | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				// get name...
 | 
					
						
							|  |  |  | 				// XXX
 | 
					
						
							|  |  |  | 				// get color...
 | 
					
						
							|  |  |  | 				// XXX
 | 
					
						
							|  |  |  | 				this.Player(name, this.pending_key['key'], key, color) | 
					
						
							|  |  |  | 				this.pending_key = null | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-03-17 15:28:43 +03:00
										 |  |  | 			return true | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2011-03-09 16:14:08 +03:00
										 |  |  | 		// create a new player...
 | 
					
						
							|  |  |  | 		// NOTE: direction and position are optional...
 | 
					
						
							|  |  |  | 		// XXX BUG: players should not get created facing a wall directly...
 | 
					
						
							|  |  |  | 		Player: function(name, ccw_button, cw_button, color, cell, direction, size){ | 
					
						
							| 
									
										
										
										
											2011-03-17 15:28:43 +03:00
										 |  |  | 			if(!this.SIMILAR_COLORS && this.used_colors[color] == true){ | 
					
						
							|  |  |  | 				// error: that the color is already used...
 | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-07-02 19:00:11 +04:00
										 |  |  | 			// register controls...
 | 
					
						
							|  |  |  | 			// XXX 
 | 
					
						
							| 
									
										
										
										
											2011-03-09 16:14:08 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if(direction == null){ | 
					
						
							|  |  |  | 				direction = ['n', 's', 'e', 'w'][Math.round(Math.random()*3)] | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if(cell === null){ | 
					
						
							|  |  |  | 				cell = this._random_empty_cell() | 
					
						
							|  |  |  | 				if(cell === null) | 
					
						
							|  |  |  | 					return | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			// create a snake...
 | 
					
						
							| 
									
										
										
										
											2011-03-17 15:28:43 +03:00
										 |  |  | 			this.used_colors[color] = true | 
					
						
							| 
									
										
										
										
											2011-03-09 16:14:08 +03:00
										 |  |  | 			return this.field.Snake(color, cell, direction, size) | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		// NOTE: position is optional...
 | 
					
						
							|  |  |  | 		Apple: function(cell){ | 
					
						
							|  |  |  | 			// place an apple at a random and not occupied position...
 | 
					
						
							| 
									
										
										
										
											2011-07-02 19:00:11 +04:00
										 |  |  | 			var c = cell? cell: this._random_empty_cell() | 
					
						
							| 
									
										
										
										
											2011-03-09 16:14:08 +03:00
										 |  |  | 			if(c === null) | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			return this.field.Apple(c) | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		// NOTE: all arguments are optional...
 | 
					
						
							|  |  |  | 		Wall: function(cell, len, direction){ | 
					
						
							|  |  |  | 			// generate random data for arguments that are not given...
 | 
					
						
							|  |  |  | 			if(cell == null){ | 
					
						
							|  |  |  | 				cell = this._random_empty_cell() | 
					
						
							|  |  |  | 				if(cell === null) | 
					
						
							|  |  |  | 					return | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if(direction == null){ | 
					
						
							|  |  |  | 				direction = ['n', 's', 'e', 'w'][Math.round(Math.random()*3)] | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if(len == null){ | 
					
						
							|  |  |  | 				if(direction == 'n' || direction == 's') | 
					
						
							|  |  |  | 					var max = this.field.height  | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 					var max = this.field.width  | 
					
						
							|  |  |  | 				len = Math.round(Math.random()*(max-1)) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			// place a wall...
 | 
					
						
							|  |  |  | 			for(var i=0; i < len; i++){ | 
					
						
							|  |  |  | 				field.Wall(cell) | 
					
						
							|  |  |  | 				cell = cell[direction]() | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// level generators and helpers...
 | 
					
						
							|  |  |  | 		levels: { | 
					
						
							|  |  |  | 			dotted: function(n){ | 
					
						
							|  |  |  | 				for(var i=0; i < n; i++) | 
					
						
							|  |  |  | 					game.Wall(null, 1, null) | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			dashed: function(n, length){ | 
					
						
							|  |  |  | 				if(length == null) | 
					
						
							|  |  |  | 					length = 3 | 
					
						
							|  |  |  | 				for(var i=0; i < n; i++) | 
					
						
							|  |  |  | 					game.Wall(null, length, null) | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			// specific level styles...
 | 
					
						
							|  |  |  | 			sand: function(){ | 
					
						
							|  |  |  | 				this.dotted(Math.round(game.field.cells.length/20)) | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			walls: function(){ | 
					
						
							|  |  |  | 				this.dashed( | 
					
						
							|  |  |  | 					Math.round(game.field.cells.length/90),  | 
					
						
							|  |  |  | 					Math.min( | 
					
						
							|  |  |  | 						game.field.width,  | 
					
						
							|  |  |  | 						game.field.height)-2) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		start: function(){ | 
					
						
							|  |  |  | 			// start the game...
 | 
					
						
							|  |  |  | 			field.start(this.TICK) | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		stop: function(){ | 
					
						
							|  |  |  | 			field.stop() | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	field.on_apple_eaten = function(){game.Apple()} | 
					
						
							| 
									
										
										
										
											2011-03-17 15:28:43 +03:00
										 |  |  | 	field.on_kill = function(snake){game.used_colors[snake.color] = false} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	//document.onkeyup = function(evt){return game._keyHandler(evt)}
 | 
					
						
							| 
									
										
										
										
											2011-03-09 16:14:08 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return game | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // vim:set ts=4 sw=4 spell :
 |