User:Peterwhy/common.js

/* User:Peterwhy/BSiconTooltips */ importScript( 'User:Peterwhy/BSiconTooltips.js' );// Backlink: User:Peterwhy/BSiconTooltips /* User:Peterwhy/BSiconTooltips */ //importScript( 'User:Peterwhy/BSiconTooltips/sandbox.js' );// Backlink: User:Peterwhy/BSiconTooltips importScript( 'User:Joeytje50/JWB.js/load.js' ); // Backlink: User:Joeytje50/JWB.js/load.js

(function {	var replaceImgWith2x = function  {		// Test forcing page width		//document.getElementsByTagName("body")[0].style.width = "980px";		//document.getElementById("mw-head").style.width="980px";		//document.getElementById("mw-head").style.left="0px";		// Detect device pixel ratio		var dpr = 1;		if(window.devicePixelRatio !== undefined) {			dpr = window.devicePixelRatio;		}

// Replace all images that can upscale var bodyContent = document.getElementById("bodyContent"); var bodyContentImgs = bodyContent.getElementsByTagName("img"); for (var i in bodyContentImgs) { var imgSrc = bodyContentImgs[i].getAttribute("src"); var imgSrcParts = imgSrc.split("/"); var imgSrcPartsLen = imgSrcParts.length; var imgSrcPx = parseInt(imgSrcParts[imgSrcPartsLen-1], 10); if (imgSrcParts[imgSrcPartsLen-5] != "thumb" || isNaN(imgSrcPx)) { continue; }			var imgSrcNewPx = imgSrcPx * 2; imgSrcParts[imgSrcPartsLen-1] = imgSrcParts[imgSrcPartsLen-1].replace(imgSrcPx+"px-", imgSrcNewPx+"px-"); var imgSrcRetinaSize = imgSrcParts.join("/");

imgSrcParts.splice(imgSrcPartsLen-1,1); imgSrcParts.splice(imgSrcPartsLen-5,1); var imgSrcFullSize = imgSrcParts.join("/");

bodyContentImgs[i].setAttribute("width",imgSrcPx); bodyContentImgs[i].setAttribute("src",imgSrcRetinaSize); bodyContentImgs[i].setAttribute("onerror", "this.setAttribute(\"src\", \""+imgSrcFullSize+"\");this.removeAttribute(\"onerror\");"); }	};	//setTimeout(replaceImgWith2x, 0); //window.addEventListener("DOMContentLoaded", replaceImgWith2x); window.addEventListener("load", replaceImgWith2x); //replaceImgWith2x; var replaceLogo = function { // Modify main logo var logo = document.getElementById("p-logo").getElementsByTagName("a")[0]; logo.style.backgroundImage = "url(\"//upload.wikimedia.org/wikipedia/commons/thumb/b/b3/Wikipedia-logo-v2-en.svg/270px-Wikipedia-logo-v2-en.svg.png\")"; logo.style.backgroundSize = "135px"; };	//window.addEventListener("load", replaceLogo); var adjustViewport = function { // Define viewport for iOS if ((window.screen.width >= 640 || window.screen.height >= 640) && (window.orientation !== undefined)) { var meta = document.getElementById("meta_viewport"); if (meta === null) { meta = document.createElement("meta"); meta.setAttribute("id","meta_viewport"); document.getElementsByTagName("head")[0].appendChild(meta); }			meta.name="viewport"; switch (window.orientation) { case 0: case 180: meta.content="width=device-width, initial-scale=1.0"; break; case 90: case -90: meta.content="width=device-height"; break; }			//meta.content="initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"; }	};	window.addEventListener("DOMContentLoaded", adjustViewport); window.addEventListener("orientationchange", adjustViewport); });

(function {	var Player = function (symbol, color) {		this.symbol = symbol.charAt(0);		this.color = color;	};	Player.prototype.inviteMove = function (board, opponent, callback, display) {		if (board.getResult !== false) {			throw new Error("Game already ended");		}		var callbacks = new Array(board.columns.length);		for (var i = 0; i < board.columns.length; i++) {			if (board.columns[i].isFull) {				callbacks[i] = null;			} else {				callbacks[i] = function (response) {					return function  {						display.removeControls;						callback(response);						return false;					}				} (i);			}		}		display.addControls(callbacks);		display.setBusy(false);	};	var Bot = function (symbol, color) {		//throw new Error("Bot not ready");		Player.call(this, symbol, color);		this.heuristicLib = new Array;	}	Bot.prototype = new Player("-");	Bot.prototype.constructor = Bot;	Bot.prototype.getRandomResponse = function (board) { var emptyCellIds = new Array; for (var i = 0; i < board.columns.length; i++) { if (!board.columns[i].isFull) { emptyCellIds.push(i); }		}		return emptyCellIds[Math.floor(Math.random*emptyCellIds.length)]; };	Bot.prototype.getResponse = function (board, opponent) { //return this.getRandomResponse(board); // check if game already ended if (board.getResult !== false) { throw new Error("Game already ended"); }		// finding best move var bestScore = Number.NEGATIVE_INFINITY; var scores = new Array(board.columns.length); var moves = [0, 1, 2, 3, 4, 5, 6] for (var i = moves.shift; i !== undefined; i = moves.shift) { if (!board.columns[i].isFull) { board.columns[i].addCell(this); scores[i] = -this.evaluateState(board, opponent, this, 7, Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY); board.columns[i].undoAddCell; bestScore = Math.max(bestScore, scores[i]); document.writeln("Move " + (i+1) + ": score = " + scores[i]); }		}		// randomly choose from one of the best moves var bestMoves = new Array; for (var i = 0; i < scores.length; i++) { if (scores[i] === bestScore) { bestMoves.push(i); }		}		return bestMoves[Math.floor(Math.random * bestMoves.length)]; }	Bot.prototype.inviteMove = function (board, opponent, callback) { // check if game already ended if (board.getResult !== false) { throw new Error("Game already ended"); }		// finding best move var bestScore = Number.NEGATIVE_INFINITY; var scores = new Array(board.columns.length); var moves = board.toValidMoveString.replace(/\t/g, "").replace(/\s/g, "").split(""); for (var i = 0; i < moves.length; i++) { moves[i] -= 1; }		document.writeln(moves); for (var i = moves.shift; i !== undefined; i = moves.shift) { if (!board.columns[i].isFull) { board.columns[i].addCell(this); scores[i] = -this.evaluateState(board, opponent, this, 7, Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY); board.columns[i].undoAddCell; bestScore = Math.max(bestScore, scores[i]); document.writeln("Move " + (i+1) + ": score = " + scores[i]); }		}		// randomly choose from one of the best moves var bestMoves = new Array; for (var i = 0; i < scores.length; i++) { if (scores[i] === bestScore) { bestMoves.push(i); }		}		var out = bestMoves[Math.floor(Math.random * bestMoves.length)]; setTimeout(function (response) {			return function {				callback(response);			}		} (out), 0); }	Bot.prototype.evaluateState = function (board, player, opponent, depth, alpha, beta) { //document.writeln(board.toString); // check whether game ended var result = board.getResult; if (result === true) { return 0; } else if (result === player) { return 1000; } else if (result === opponent) { return -1000; } else if (depth <= 0) { return this.heuristic(board, player, opponent); }		// if game not ended var moves = [3, 4, 2, 5, 1, 6, 0] for (var i = moves.shift; i !== undefined; i = moves.shift) { if (!board.columns[i].isFull) { board.columns[i].addCell(player); var score = -this.evaluateState(board, opponent, player, depth-1, -beta, -alpha); board.columns[i].undoAddCell; alpha = Math.max(alpha, score); /*if (depth == 8) { document.writeln("\tMove " + (i+1) + ": score = " + score); }*/				if (beta <= alpha) { break; }			}		}		// return the score from perspective of player return alpha; }	Bot.prototype.heuristic = function (board, player, opponent) { // load from library var boardStr = board.toString; if (this.heuristicLib[boardStr] !== undefined) { return this.heuristicLib[boardStr]; }		// getting the true opponent object relative to this var trueOpponent = (this != player) ? player : opponent; var out = 0; // calculate winning lines for (var i = 0; i < board.columns[0].cells.length; i++) { var botCount = 0; var opponentCount = 0; for (var j = 0; j < board.columns.length; j++) { if (board.columns[j].cells[i].owner == this) { botCount++; } else if (board.columns[j].cells[i].owner) { opponentCount++; }			}			if (botCount > 0 && opponentCount == 0) { out+=2; } else if (botCount == 0 && opponentCount > 0) { out--; } else if (botCount == 0 && opponentCount == 0) { break; }		}		// calculate threats var maxNextEmptyCellId = 0; for (var i = 0; i < board.columns.length; i++) { maxNextEmptyCellId = Math.max(maxNextEmptyCellId, board.columns[i].nextEmptyCellId); }		for (var i = 0; i < board.columns.length; i++) { for (var j = board.columns[i].nextEmptyCellId; j <= maxNextEmptyCellId && j < board.columns[i].cells.length; j++) { board.columns[i].cells[j].owner = this; if (board.getResult(i, j) == this) { out += 10; }				board.columns[i].cells[j].owner = trueOpponent; if (board.getResult(i,j) == trueOpponent) { out -= 10; }				board.columns[i].cells[j].owner = null; }		}		this.heuristicLib[boardStr] = out; return out; };	var Cell = function { this.owner = null; };	var Column = function { this.cells = new Array(6); for (var i = 0; i < this.cells.length; i++) { this.cells[i] = new Cell; }		this.nextEmptyCellId = 0; };	Column.prototype.isFull = function { return this.nextEmptyCellId >= this.cells.length; };	Column.prototype.addCell = function (owner) { if (!this.isFull) { this.cells[this.nextEmptyCellId++].owner = owner; } else { throw new Error("Cannot add into a full column"); }	};	Column.prototype.undoAddCell = function { if (this.nextEmptyCellId > 0) { this.cells[--this.nextEmptyCellId].owner = null; } else { throw new Error("Cannot undo an empty Column"); }	};	var Board = function { this.columns = new Array(7); for (var i = 0; i < this.columns.length; i++) { this.columns[i] = new Column; }	};	Board.prototype.getResult = function (lastColumn, lastRow) { // case when last step made is not obvious if (lastColumn === undefined) { var isDraw = true; for (var i = 0; i < this.columns.length; i++) { var result = this.getResult(i); if (result !== true && result !== false) { return result; }				isDraw = isDraw && result; }			return isDraw; }		// case when last step row is not given if (lastRow === undefined) { lastRow = this.columns[lastColumn].nextEmptyCellId - 1; }		if (lastRow < 0) { return false; }		// check if last move makes a win var dx = [1, 1, 0, -1, -1, -1, 0, 1]; var dy = [0, 1, 1, 1, 0, -1, -1, -1]; var extensions = [0, 0, 0, 0, 0, 0, 0, 0]; var lastCell = this.columns[lastColumn].cells[lastRow]; var owner = lastCell.owner; for (var direction = 0; direction < extensions.length; direction++) { for (var x = lastColumn, y = lastRow; (x >= 0 && x < this.columns.length && y >= 0 && y < this.columns[x].cells.length) && this.columns[x].cells[y].owner == owner; x += dx[direction], y += dy[direction]) { extensions[direction]++; }		}		for (var direction = 0; direction < extensions.length/2; direction++) { if (extensions[direction] - 1 + extensions[direction+4] == 4) { return owner; }		}		// return boolean if board is draw for (var i = 0; i < this.columns.length; i++) { if (!this.columns[i].isFull) { return false; }		}		return true; };	Board.prototype.toFormattedString = function { var out = ""; for (var i = this.columns[0].cells.length-1; i >= 0; i--) { for (var j = 0; j < this.columns.length; j++) { if (j) { out += "\t"; }				var owner = this.columns[j].cells[i].owner; if (owner) { out += owner.symbol; } else { out += " "; }			}			if (i) { out += "\n"; }		}		return out; };	Board.prototype.toValidMoveString = function { var out = ""; for (var i = 0; i < this.columns.length; i++) { if (!this.columns[i].isFull) { out += i + 1; } else { out += " "; }			out += "\t"; }		return out; };	Board.prototype.toString = function { var out = ""; for (var i = 0; i < this.columns.length; i++) { for (var j = 0; j < this.columns[i].cells.length; j++) { if (this.columns[i].cells[j].owner === null) { out += " "; } else { out += this.columns[i].cells[j].owner.symbol; }			}		}		return out; };	var Game = function (isComputer1, isComputer2) { this.players = new Array; this.players.push((isComputer1) ? new Bot("O", "Red") : new Player("O", "Red")); this.players.push((isComputer2) ? new Bot("X", "Gold") : new Player("X", "Gold")); this.currentPlayerId = 0; this.nextPlayerId = 1; this.board = new Board; this.display = new Display(this); }	Game.prototype.newRound = function { // display log message document.writeln("-" + this.players[this.currentPlayerId].symbol); document.writeln(this.board.toFormattedString); // display board this.display.display; this.display.setBusy(true); // obj closure reqired to store "this" object reference var callback = function (obj) { return function (response) { obj.move(response); }		} (this); setTimeout(function (obj) {			return function {				obj.players[obj.currentPlayerId].inviteMove(obj.board, obj.players[obj.nextPlayerId], callback, obj.display);			}		} (this), 100); //this.players[this.currentPlayerId].inviteMove(this.board, this.players[this.nextPlayerId], callback, this.display); };	Game.prototype.move = function (response) { document.writeln("Response = " + (response+1)); // modify game this.board.columns[response].addCell(this.players[this.currentPlayerId]); // check if game ended var result = this.board.getResult(response); if (result !== false) { this.display.display; this.display.setBusy(false); if (result === true) { alert("Draw"); } else { alert("Winner = " + result.color); }		} else { this.currentPlayerId = this.nextPlayerId; this.nextPlayerId = (this.nextPlayerId + 1) % this.players.length; this.newRound; }	};	Game.prototype.load = function (array) { for (var i = 0; i < array.length; i++) { for (var j = array[i].shift; j !== undefined; j = array[i].shift) { this.board.columns[i].addCell(this.players[j]); }		}	}	var Display = function (game, parentDOM) { if (!parentDOM) { parentDOM = document.getElementsByTagName("body")[0]; }		this.game = game; if (Display.singletonDiv) { this.div = Display.singletonDiv; } else { this.div = Display.singletonDiv = document.createElement("div"); parentDOM.appendChild(this.div); var table = document.createElement("table"); this.div.appendChild(table); table.style.borderLeft = table.style.borderRight = table.style.borderBottom = "3px double red"; table.style.cursor = "default"; table.style.borderCollapse = "collapse"; var tbody = document.createElement("tbody"); table.appendChild(tbody); for (var i = this.game.board.columns[0].cells.length-1; i >= 0 ; i--) { var tr = document.createElement("tr"); tbody.appendChild(tr); for (var j = 0; j < this.game.board.columns.length; j++) { var td = document.createElement("td"); td.id = "c" + j + "r" + i;					td.style.textAlign = "center"; td.style.width = td.style.height = "2em"; td.style.fontWeight = "900"; td.style.fontFamily = "\"Century Gothic\", Verdana, sans-serif"; td.appendChild(document.createTextNode("\u00a0")); if (j) { td.style.borderLeft = "1px solid silver"; }					tr.appendChild(td); }			}			//alert(document.getElementsByTagName("table")[0].style.display); }	}	Display.prototype.display = function { var board = this.game.board; var tds = this.div.getElementsByTagName("td"); for (var i = board.columns[0].cells.length-1; i >= 0; i--) { for (var j = 0; j < board.columns.length; j++) { var tdId = j + (board.columns[0].cells.length - 1 - i) * board.columns.length; var td = tds[tdId]; while (td.hasChildNodes) { td.removeChild(td.firstChild); }				if (board.columns[j].cells[i].owner) { td.style.color = board.columns[j].cells[i].owner.color; td.appendChild(document.createTextNode("\u25CE")); //td.appendChild(document.createTextNode("\u235F")); } else { }			}		}	}	Display.prototype.addControls = function (callbacks) { var board = this.game.board; var tds = this.div.getElementsByTagName("td"); for (var i = 0; i < board.columns.length; i++) { var isFull = board.columns[i].isFull; for (var j = board.columns[0].cells.length-1; j >= 0; j--) { var tdId = i + (board.columns[0].cells.length - 1 - j) * board.columns.length; var td = tds[tdId]; if (isFull) { td.onclick = null; td.style.cursor = "default"; } else { td.onclick = callbacks[i]; td.style.cursor = "pointer"; }			}		}	}	Display.prototype.removeControls = function { var tds = this.div.getElementsByTagName("td"); for (var i = 0; i < tds.length; i++) { tds[i].onclick = null; tds[i].style.cursor = "default"; }	}	Display.prototype.setBusy = function (isBusy) { document.body.style.cursor = (isBusy) ? "wait" : "auto"; }	startGame = function { document.getElementById("output").innerHTML = ""; var oldWriteln = document.writeln; document.writeln = function (element) { return function (str) { //element.appendChild(document.createTextNode("\n" + str)); };		} (document.getElementById("output")); var game = new Game(true, false); game.newRound; return false; }	//startGame; var button = document.createElement("input"); button.type = "button"; button.value = "Start fun"; if (window.attachEvent) { button.attachEvent("onclick", startGame); } else { button.addEventListener("click", startGame, false); }	document.body.appendChild(button); var div = document.createElement("pre"); div.id = "output"; document.body.appendChild(div); })