function randInt(mn,mx) {
return mn + (Math.floor(Math.random()*(mx+1-mn)));
}



function Nim() {
    this.easyMode = false;
}
Nim.prototype.randomGame = function() {
this.numPiles = randInt(3, 7);
this.pileHeights = [];
this.locked = 0;
this.maxInitialHeight = 0;
for (var i = 0; i < this.numPiles; i++) {
var h = randInt(1,5);
this.pileHeights[i] = h;
if (h > this.maxInitialHeight) this.maxInitialHeight = h;
}
}

Nim.prototype.onClick = function(col, row) {
    if (this.locked > 0) return;
    this.locked++;
    var m = [col, row];
    var self = this;
    this.executeMove(true, m, function() {
	    var m = self.easyMode ? self.randomMove() : self.xorMove();
	    self.executeMove(false, m, null);
	    self.locked--;
	});
}

Nim.prototype.pileRemove = function(col, row, cb) {
var take = this.pileHeights[col] - row;
this.pileHeights[col] -= take;
var self = this;
for (var r = this.maxInitialHeight-1; r >= row; r--) {
    function onFadeOut(elts, c, r, cb) {
	return function() { elts.remove();
	    if (cb) { cb(); }}
    }

    $("#cell_"+col+"_"+r).fadeOut('slow', onFadeOut($(this), col, r,
						    r==row?cb:null));
}
}

Nim.prototype.pilesLeft = function() {
var ret = 0;
for (var i = 0; i < this.numPiles; i++) {
if (this.pileHeights[i] > 0) { ret++; }
}
return ret;
}
Nim.prototype.columnLabel = function(c) {
    return String.fromCharCode(65+c);
}
    Nim.prototype.takeToMove = function(c, take) {
	return [c, this.pileHeights[c]-take];
    }
Nim.prototype.moveToTake = function(move) {
 return this.pileHeights[move[0]] - move[1];
}
Nim.prototype.clearLog = function() {
//$("#log").html("");
//	var elt = $("#log").get(0);
//elt.scrollTop = elt.scrollHeight;
}
    Nim.prototype.log = function(s) {
//$("#log").append(s+"<br/>\n");
//	var elt = $("#log").get(0);
//elt.scrollTop = elt.scrollHeight;
    }

Nim.prototype.executeMove = function(user, move, cb) {
    if (this.isDone()) {
	if (cb) cb();
	return;
    }
    var take = this.moveToTake(move);
    var who = user ? "You":"I";
    var stone = "stone"+(take==1?"":"s");
    this.log(who+" take " + take + " "+stone+" from pile " + this.columnLabel(move[0]) + "");
    var self = this;
    this.pileRemove(move[0], move[1], function() {
	    if (self.isDone()) {
		var s = who+" took the last "+stone+"...\n... so you " + (user?"won":"lost") + " the game!";
		self.log(s);
		alert(s);
	    }
	    if (cb) cb();
	});
}
    Nim.prototype.isDone = function() {
  for (var i = 0; i < this.numPiles; i++) {
      if (this.pileHeights[i] > 0) { return false;
      }
  }
	return true;
    }
Nim.prototype.xorMove = function() {
  // x = "XOR of all piles"
  var x = 0;
  for (var i = 0; i < this.numPiles; i++) {
    x ^= this.pileHeights[i];
  }
  if (x == 0) {
    // We're loosing, struggle
    for (var i = 0; i < this.numPiles; i++) {
      if (this.pileHeights[i] > 0) { return [i, this.pileHeights[i]-1]; }
    }
  }
  else
    {
// Find pile that contributes to msb of X
var m = 0;
for (var i = 1; i < this.numPiles; i++) {
if ((this.pileHeights[i] & x) > (this.pileHeights[m] & x)) {
m = i;
}
}
// X becomes XOR of all piles except pile M
x ^= this.pileHeights[m];
return this.takeToMove(m, this.pileHeights[m]-x);
}
}
    Nim.prototype.randomMove = function() {
	var pl = this.pilesLeft();
	var c = randInt(0, this.numPiles-1);
	for (var i = 0; i < this.numPiles; i++) {
	    var ci = (c+i) % this.numPiles;
	    var ph = this.pileHeights[ci];
	    if (ph > 0) {
		var take = randInt(1, ph);
		// Do not take all if only 2 piles left
		if (pl <= 2 && take == ph && ph != 1) {
		    take--;
		}
		return this.takeToMove(ci, take);
	    }
	}
    }

	Nim.prototype.start = function() {
        this.clearLog();
	    this.log("We start a new game, click within a pile to remove stones...");
	    this.randomGame();
	    this.initHtml();
	}

Nim.prototype.setEasyMode = function(enabled) {
this.easyMode = enabled;
}

Nim.prototype.initHtml = function() {
var s = '<table class="nim">';
for (var r = this.maxInitialHeight-1; r>=0; r--) {
s += "<tr>";
s += '<th class="rowlabel">'+(r+1)+'</th>';
for (var c = 0; c < this.numPiles; c++) {
var empty=(r >= this.pileHeights[c]);
s += '<td class="nimcell">';
id = "cell_"+c+"_"+r;
var click = 'onclick="game.onClick('+c+','+r+')"';
s += '<div '+click+'id="'+id+'">';
if (empty) s+="";
else s+='<img src="'+(r==0?IMG_BOTTOM_STONE:IMG_STONE)+'" alt="O"/>';
s += "</div></td>";
}
s += "</tr>";
}
s += "<tr><th></th>";
for (var c = 0; c < this.numPiles; c++) {
    s += '<th class="collabel">'+this.columnLabel(c)+'</th>';
}
s += "</tr>";
s += "</table>";
$("#canvas").html(s);
}

