// Javascript code to display a Sokoban level.
// By Scott Lindhurst, <ScottL@alumni.Princeton.edu>
// See <http://members.aol.com/SokobanMac/levels.html>

preImages = new Array;
function preloadImg (name) {
	var i = preImages.length;
	preImages[i] = new Image(16,16);
	preImages[i].src = name;
}
//preloadImg("center.gif");
//preloadImg("E.gif");
//preloadImg("EW.gif");
//preloadImg("goal.gif");
//preloadImg("ground.gif");
//preloadImg("lone.gif");
//preloadImg("N.gif");
//preloadImg("NE.gif");
//preloadImg("NEne.gif");
//preloadImg("NEW.gif");
//preloadImg("NEWne.gif");
//preloadImg("NEWnenw.gif");
//preloadImg("NEWnw.gif");
//preloadImg("NS.gif");
//preloadImg("NSE.gif");
//preloadImg("NSEne.gif");
//preloadImg("NSEnese.gif");
//preloadImg("NSEse.gif");
//preloadImg("NSEW.gif");
//preloadImg("NSEWne.gif");
//preloadImg("NSEWnenw.gif");
//preloadImg("NSEWnenwse.gif");
//preloadImg("NSEWnenwsw.gif");
//preloadImg("NSEWnese.gif");
//preloadImg("NSEWnesesw.gif");
//preloadImg("NSEWnesw.gif");
//preloadImg("NSEWnw.gif");
//preloadImg("NSEWnwse.gif");
//preloadImg("NSEWnwsesw.gif");
//preloadImg("NSEWnwsw.gif");
//preloadImg("NSEWse.gif");
//preloadImg("NSEWsesw.gif");
//preloadImg("NSEWsw.gif");
//preloadImg("NSW.gif");
//preloadImg("NSWnw.gif");
//preloadImg("NSWnwsw.gif");
//preloadImg("NSWsw.gif");
//preloadImg("NW.gif");
//preloadImg("NWnw.gif");
//preloadImg("player.gif");
//preloadImg("playergoal.gif");
//preloadImg("S.gif");
//preloadImg("SE.gif");
//preloadImg("SEse.gif");
//preloadImg("SEW.gif");
//preloadImg("SEWse.gif");
//preloadImg("SEWsesw.gif");
//preloadImg("SEWsw.gif");
//preloadImg("spacer.gif");
//preloadImg("stone.gif");
//preloadImg("stonegoal.gif");
//preloadImg("SW.gif");
//preloadImg("SWsw.gif");
//preloadImg("W.gif");


currLev = 0;
wall = "#";
ground = " ";
maxNumRows = 0;
maxNumCols = 0;

levels = new Array;

writeImages = false;  // Do we draw new images or reuse?
openDoc = false; // Do we open/close drawWin.document?
drawWin = null;  // Window to draw into
formWin = null;  // Window containing form controlling level disp.

function setSquare (row, col, img) {
// Draw one square of a Sokoban board.
	if (writeImages) {
		drawWin.document.write ('<img src="',img,'">');
	} else {
		var imgName = "r" + row + "c" + col;
		document.images[imgName].src = img;
	}
}

function endRow () {
	if (writeImages)
		drawWin.document.writeln ('<BR>');
}

function startDraw () {
	if (openDoc)
		drawWin.document.open();
//	window.status = "Drawing level "+currLev+" of "+levels.length-1;
}

function endDraw () {
	if (openDoc)
		drawWin.document.close();
//	window.status = "";
}

function getSquare (row, col) {
// Get value of square at given row and column.
// "ground" if undefined
	var val = ground;
	if (row >= 0 && row < this.numRows) {
		currRow = this.rows[row];
		cols = currRow.length;
		if (col >=0 && col < cols)
			val = currRow.charAt(col);
	}
	return val;
}

function numCols () {
// Find maximum width of this level
	var max = 0;
	for (var i=0; i<this.numRows; i++) {
		var currLen = this.rows[i].length;
		if (currLen > max)
			max = currLen;
	}
	return (max);
}

function isWall (row, col) {
	return (this.getSquare (row, col) == wall);
}

function drawWall (row, col) {
// Pick the right image for the wall
	var North = this.isWall (row-1, col);
	var South = this.isWall (row+1, col);
	var East = this.isWall (row, col+1);
	var West = this.isWall (row, col-1);
	var NE = this.isWall (row-1, col+1);
	var NW = this.isWall (row-1, col-1);
	var SE = this.isWall (row+1, col+1);
	var SW = this.isWall (row+1, col-1);

	var img = "";
	if (North) img += "N";
	if (South) img += "S";
	if (East) img += "E";
	if (West) img += "W";
	if (North && East && NE) img += "ne";
	if (North && West && NW) img += "nw";
	if (South && East && SE) img += "se";
	if (South && West && SW) img += "sw";
	if (! (North || South || East || West)) img = "lone";

	img = img + ".gif";
	setSquare (row, col, img);
}

function drawLevel () {
// Method for Level object
	var nRowsToDraw = writeImages ? this.numRows : maxNumRows;
	var nColsToDraw = writeImages ? this.numCols() : maxNumCols;
	
	startDraw();
	for (var row=0; row<nRowsToDraw; row++) {
		for (var col=0; col<nColsToDraw; col++) {
			var piece = this.getSquare (row, col);
			if (piece == wall)
				this.drawWall (row, col);
			else
				setSquare (row, col, myImages[piece]);
		}
		endRow();
	}
	endDraw();
}

function Level (levText) {
	this.rows = levText.split ('|');
	this.numRows = this.rows.length;
	this.draw = drawLevel;
	this.getSquare = getSquare;
	this.drawWall = drawWall;
	this.isWall = isWall;
	this.numCols = numCols;	
}

function computeMaxNums () {
// Compute the maximum width of the array of Levels.
	for (var i=1; i<levels.length; i++) {
		if (levels[i].numRows > maxNumRows)
			maxNumRows = levels[i].numRows;
		if (levels[i].numCols() > maxNumCols)
			maxNumCols = levels[i].numCols();
	}
}

myImages = new Array;
myImages[wall] = "lone.gif";
myImages["$"] = "stone.gif";
myImages[ground] = "ground.gif";
myImages["."] = "goal.gif";
myImages["@"] = "player.gif";
myImages["+"] = "playergoal.gif";
myImages["*"] = "stonegoal.gif";

function fillCurrentLevOptions () {
// Fill in currentLev menu in the form.
	for (var i=1; i<levels.length; i++) {
		formWin.document.levelControls.currentLev.options[i-1]= new Option("Level "+i);
	}
}

function makeSpaces (rows, cols) {
// Write an array of rows x cols blank images to the current
// document (to be filled in by draw routines)
	for (var row=0; row<rows; row++) {
		for (var col=0; col<cols; col++) {
			var imgName = "r" + row + "c" + col;
			drawWin.document.write ('<img src="ground.gif" name="' + imgName + '">');
		}
		drawWin.document.writeln('<BR>');
	}
}

function goToLev (num) {
	if (num < 1) {
		num = levels.length - 1;
	}
	if (num >= levels.length) {
		num = 1;
	}
	currLev = num;
	levels[num].draw();
	formWin.document.levelControls.currentLev.selectedIndex = num - 1;	
}

function goPrevLev () {
	goToLev (currLev - 1);
}

function goNextLev () {
	goToLev (currLev + 1);
}

function initLevelDrawing (theFormWin, theDrawWin) {
// Prepare to draw levels.
// The array "levels" should have been filled in already.
// buttonWin has the form controlling display
// drawWin is null for noframes or has window for level frame
	formWin = theFormWin;
	drawWin = theDrawWin;
	computeMaxNums();

	if (!theFormWin) {
	// Drawing all levels to theDrawWin in one fell swoop
		writeImages = true;
		openDoc = false;
		for (var i=1; i<levels.length; i++) {
			usingFrames = true;
			currLev = i;
			drawWin.document.writeln("<H2>Level ", i, "</H2>");
			levels[i].draw();
		}
	} else if (!theDrawWin) {
	// xxxDraw.html: draw without frames
		writeImages = false;
		openDoc = false;
		drawWin = theFormWin;
		makeSpaces (maxNumRows, maxNumCols);
		fillCurrentLevOptions();
		goToLev (1);
	} else {
	// Draw levels to a separate frame (theDrawWin)
		writeImages = true;
		openDoc = true;
		fillCurrentLevOptions();
		goToLev (1);
	}
}

