var ready_done = false,
ready = function() {
if (ready_done)
return;
ready_done = true;
loadSol();
if (isChallenge)
challengeLoad();
}
if (document.readyState === 'complete')
ready();
else if (document.addEventListener) { // gecko, webkit, opera, IE 9
document.addEventListener("DOMContentLoaded", ready, false);
window.addEventListener("load", ready, false);
}
else if (document.attachEvent) { // IE 8-
document.attachEvent("onreadystatechange", ready);
window.attachEvent("onload", ready);
}
var wallColor = false;
var wallEmblem = false;
var wallOrientation = 0;
var isChallenge = false;
var isTutorial = false;
var solution = new Array();
var blocks = new Array();
var count = new Array();
var mapdata = new Array();
var mapjson = new Array();
var htmlnotification = '';
var jsonmapdata = new Object;
//var jsonmapdata.solutions = new Array();
var mapType; // 1 = simple, 2 = normal, ...; used for mixpanel tracking
var pressedGoTime = 0;
function loadSol(sol, moves) {
if (sol == null)
if (document.getElementById('mapsol') != undefined)
sol = document.getElementById('mapsol').innerHTML;
if (sol) {
tmp = sol.split(':');
position = tmp[1].split('.');
mapid = tmp[0];
clearwalls(mapid);
for(var i in position) {
if (document.getElementById(mapid+','+position[i]) != undefined) {
object = document.getElementById(mapid+','+position[i]);
grid_click(object);
}
}
}
if (moves && mapid) {
updateDsp(mapid, 'dspCount', moves+ " moves");
}
}
function showNotification(html) {
var div = document.createElement('div');
var pref = '
';
//var suff = '';
div.innerHTML = pref+html+suff;
document.body.appendChild(div.firstChild);
}
function changeWallColor(newColor) {
playerWallColor = newColor;
loadSol(null);
}
function changeWallEmblem(newEmblem) {
playerWallEmblem = newEmblem;
loadSol(null);
}
function linkEmblem(emblem, orientation) {
orientation = orientation - 0;
var url = 'images/marks/';
if (orientation == 0) return url+emblem;
return url+'rotate.php?r='+orientation+'&emblem='+emblem;
}
function setWallStyle(playerObject) {
if (typeof playerObject !== 'object') return;
wallColor = playerObject.wallColor;
wallEmblem = playerObject.wallEmblem;
wallOrientation = playerObject.wallOrientation;
}
function grid_click(obj) {
//Prepare data
tmp = obj.id.split(',');
mapid = tmp[0] - 0;
y = tmp[1];
x = tmp[2];
//The users solution - prepare it if it's not started
if (solution[mapid] == undefined) {
getmapdata(mapid);
}
//Is this placing a wall, or removing one?
var tmp = obj.id;
childdiv = document.getElementById('child_'+tmp);
if (obj.cv) {
//Removing a wall
obj.cv = false;
//Remove Customized Background Color & Image
obj.style.backgroundColor = '';
obj.style.backgroundImage = '';
obj.setAttribute("class", "o");
childdiv.setAttribute("class", "child");
blocks[mapid]++;
//Remove wall
solution[mapid] = solution[mapid].replace('.'+y+','+x+'.', '.');
} else {
//Placing a wall
if (blocks[mapid] < 1) {
updateDsp(mapid, 'dspWalls', "OUT!");
return;
}
obj.cv = true;
//Color goes on the bottom, Parent.
//Then the chosen emblem in the Parent.
// Then the emblem and color are smoothed with the faceted tile on top.
//childdiv.removeAttribute("class");
childdiv.setAttribute("class", "child w");
if (wallColor == false) setWallStyle(userObj);
obj.style.backgroundColor = wallColor;
if (wallEmblem) {
obj.style.backgroundImage="url("+linkEmblem(wallEmblem, wallOrientation)+")";
}
//Add Wall
solution[mapid] += y+','+x+'.';
blocks[mapid]--;
}
//document.getElementById('blocksdisplay').innerHTML = ""+blocks[mapid]+"";
if (isChallenge == true) {
challengeWall(mapid);
}
updateDsp(mapid, 'dspWalls', blocks[mapid]+" walls");
//document.getElementById(mapid+',dspWalls').innerHTML = " "+blocks[mapid]+" walls";
}
function updateDsp(mapid, element, data) {
//if (mapdata[mapid] == undefined)
// return;
//if (mapdata[mapid].example != true) {
if (document.getElementById(mapid+','+element) != undefined) {
handle = document.getElementById(mapid+','+element);
handle.innerHTML = data;
}
//}
}
function getmapdata(mapid) {
//console.log('getting data for mapID', mapid);
if (typeof(mapdata[mapid]) != 'object')
mapdata[mapid] = decryptJSON(jsonmapdata[mapid]);
blocks[mapid] = mapdata[mapid].walls;
solution[mapid] = '.';
updateDsp(mapid, 'dspWalls', blocks[mapid]+" walls");
}
function doSend(mapid) {
if (solution[mapid] == undefined) {
getmapdata(mapid);
}
pressedGoTime = new Date().getTime();
reqstr = "isChallenge="+isChallenge
reqstr += "&r=getpath"
reqstr += "&mapcode="+mapdata[mapid].code;
reqstr += "&mapid="+mapid;
reqstr += "&solution="+solution[mapid];
ajax.requestFile = "do.php?"+reqstr; //prepare strdata
ajax.onCompletion = request_path_done; // specify function to be executed on response
ajax.runAJAX();
}
function requestSol(mapID) {
ajax.requestFile = "do.php?r=getsol&mapID="+mapID; //prepare strdata
ajax.onCompletion = requestSolDone; // specify function to be executed on response
ajax.runAJAX();
}
function requestChallengeSolution(mapID, challengeID) {
ajax.requestFile = "do.php?r=getChallengeSolution&mapID="+mapID+'&challengeID='+challengeID; //prepare strdata
ajax.onCompletion = requestSolDone; // specify function to be executed on response
ajax.runAJAX();
}
function requestSolDone() {
var JO;
JO = decryptJSON(ajax.response);
if (JO.solution == 'undefined')
return;
//clearwalls(JO.mapid);
loadSol(JO.mapid + ":" + JO.solution, JO.moves);
}
function clearwalls(mapid) {
if (solution[mapid] == undefined) return;
walls = solution[mapid].split('.');
for(var i in walls) {
tmp = walls[i].split(',');
eid = mapid+','+tmp[0]+','+tmp[1];
if (document.getElementById(eid) != undefined) {
obj = document.getElementById(eid);
obj.cv = false;
childdiv = document.getElementById('child_'+obj.id);
//Reset childdiv to it's default.
childdiv.removeAttribute("class");
childdiv.setAttribute("class", "child");
//return the td obj back to it's default.
obj.style.backgroundColor = '';
obj.style.backgroundImage = '';
obj.setAttribute("class", "o");
}
}
solution[mapid] = undefined;
getmapdata(mapid);
}
//TODO:An undo button rather than confirm..
function resetwalls(mapid) {
answer = confirm("Remove walls and start fresh?");
if (answer) {
clearwalls(mapid);
}
}
function request_path_done() {
var JO = decryptJSON(ajax.response);
var mapid = JO.mapid;
mapjson[mapid] = JO;
var speedbox = document.getElementById(mapid+',speed'),
speed = speedbox.options[speedbox.selectedIndex].text,
mute = !checkSound(mapid);
nowTime = new Date().getTime();
var responseTime = nowTime - pressedGoTime;
mixpanel.track('click go', {
'speed': speed,
'mute': mute,
'mapid': mapid,
'type': mapType,
'response time': responseTime
});
for(var i in JO.error)
console.error('\n JO error ' + JO.error[i]);
if (JO.blocked) {
alert("The path is blocked!");
return;
}
var disptext = "Record: "+JO.best+" by "+JO.bestby;
if (isChallenge)
disptext = '';
updateDsp(JO.mapid, 'dspID', disptext);
mapdata[mapid].moveCount = new Object;
mapdata[mapid].usedTiles = new Array();
mapdata[mapid].restoreTiles = new Array();
mapdata[mapid].pathColor = new Object;
mapdata[mapid].pathsPending = JO.path.length;
mapdata[mapid].isMultiPath = (JO.path.length > 1);
for(i in JO.path) {
mapdata[mapid].moveCount[i] = 0;
mapdata[mapid].pathColor[i] = '#ffffff';
animatePath(JO.path[i].path, mapid, JO.path[i].start, i);
}
}
function decryptJSON(text) {
if (typeof(text) == 'undefined') return false;
var JO;
if (typeof(JSON) == 'undefined') {
JO = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(text.replace(/"(\\.|[^"\\])*"/g, ''))) && eval('(' + text + ')');
} else {
JO = JSON.parse(text);
}
return JO;
}
function animatePath(path, mapid, start, pathNumber) {
var tmp = start.split(',');
var y = tmp[0];
var x = tmp[1];
var p = path;
//Prepare the path
var c = p.substring(0, 1);
p = p.substring(1);
document.getElementById(mapid+',btn').disabled = true;
doanimate(x, y, p, c, mapid, pathNumber);
}
function animatePathDone(mapid) {
document.getElementById(mapid+',btn').disabled = false;
if (isChallenge == true) {
challengeGo(mapid);
}
if (typeof(currentPage) == "object") {
scoresRequestPage(mapid, currentPage[mapid]);
}
//Mark off challenges
//TODO: This hack is stupidd :(
if(isChallenge && isTutorial == false)
{
for(var i = 0; i < mapjson[mapid].completedChallenges.length; i++)
{
var challengeId = mapjson[mapid].completedChallenges[i];
var handle = document.getElementById("challenge_id_" + challengeId);
if (handle.className.indexOf('challenge_complete') < 0) {
handle.className = "challenge_complete";
flashelement("challenge_id_" + challengeId, 4);
}
}
}
}
function checkSound(mapid) {
if (getCookie('pref_mute') == 'true') {
return false;
}
if (typeof(soundManager) != 'object') {
return false;
}
return true;
}
function doanimate(x, y, p, c, mapid, pathNumber) {
//x, y position
//p path string being trunicated.
//c current target code.
//t next target code.
t = p.substring(0, 1);
//Animate current square, and move to next one.
if (count[mapid] == undefined) {
count[mapid] = 0;
}
//Set the color for the first target.
if (count[mapid] == 0 && !(c > 0))
mapdata[mapid].pathColor[pathNumber] = targetColor(c);
//Display movecount
if (mapdata[mapid].moveCount[1] > 0 && mapdata[mapid].moveCount[0] > 0) {
var colorScores = '' + mapdata[mapid].moveCount[0] + ' + ';
colorScores += '' + mapdata[mapid].moveCount[1] + ' = ' + count[mapid] + " moves";
updateDsp(mapid, 'dspCount', colorScores);
//updateDsp(mapid, 'dspCount', '' + mapdata[mapid].moveCount[0] + ' + ' + mapdata[mapid].moveCount[1] + ' = ' + count[mapid] + " moves");
} else {
updateDsp(mapid, 'dspCount', count[mapid]+ " moves");
}
//document.getElementById(mapid+',dspCount').innerHTML = count[mapid]+ " moves";
//Get a handle on the element.
eid = mapid+','+x+','+y;
//Verify.
if (document.getElementById(eid) == undefined) {
console.error("Path exited field...?");
animatePathDone(mapid);
return;
}
handle = document.getElementById(eid);
//Animate the first square in a path.
if (count[mapid] == 0 && !(c > 0)) {
count[mapid]--;
mapdata[mapid].moveCount[pathNumber]--;
c = t;
if (!(c > 0))
c = '2';
}
switch(c) {
//The path is moving to a new position
case '1': //1 - Up
case '2': //2 - Right
case '3': //3 - Down
case '4': //4 - Left
//Track move count
count[mapid]++;
mapdata[mapid].moveCount[pathNumber]++;
//Notify users on score levels;
switch(count[mapid]) {
case 100: case 200: case 300: case 400:
case 500: case 600: case 700: case 800:
case 900: case 1000:
if (checkSound(mapid)) {
soundManager.setVolume('charm', 40);
soundManager.setPan('charm', 75)
soundManager.play('charm');
}
//Flash
flashelement(mapid+',dspCount', 4);
break;
}
var childID = 'child_'+handle.id;
childdiv = document.getElementById(childID);
if (childdiv.className.indexOf('w') < 0) {
childdiv.setAttribute('class', 'transition path'+pathNumber+'-'+c);
handle.style.backgroundColor = mapdata[mapid].pathColor[pathNumber];
var string = "if (document.getElementById('"+'child_'+eid+"').className == 'transition path"+pathNumber+'-'+c+"')";
string += "document.getElementById('"+'child_'+eid+"').setAttribute('class', 'child');";
setTimeout(string, 855);
//Maintain disabled appearnce of checkpoints
if (handle.pressed == true) {
setTimeout("document.getElementById('"+eid+"').style.backgroundColor = '#dddddd';", 865);
} else {
string = "if (document.getElementById('"+childID+"').className.indexOf('w') < 0) ";
string += "document.getElementById('"+eid+"').style.backgroundColor = '';";
setTimeout(string, 865);
}
}
break;
//Teleports
case 't': case 'm': case 'g': case 'i': case 'k':
//Outs
case 'u': case 'n': case 'h': case 'j': case 'l':
case 'r':
if (mapdata[mapid].isMultiPath == false) {
handle.style.backgroundColor = '#dddddd';
setTimeout("document.getElementById('"+eid+"').style.backgroundColor = '#dddddd';", 865);
handle.pressed = true;
} else {
if (contains(mapdata[mapid].usedTiles, eid)) {
handle.style.backgroundColor = '#dddddd';
setTimeout("document.getElementById('"+eid+"').style.backgroundColor = '#dddddd';", 865);
handle.pressed = true;
} else {
//mapdata[mapid].usedTiles.push(eid);
//break;
}
}
if (contains(mapdata[mapid].usedTiles, eid) == false)
mapdata[mapid].usedTiles.push(eid);
//mapdata[mapid].restoreTiles.push("document.getElementById('"+eid+"').style.backgroundColor = '';");
//mapdata[mapid].restoreTiles.push("document.getElementById('"+eid+"').pressed = false;");
//alert(mapdata[mapid].pathColor[pathNumber]);
//break;
}
//Sound effects
if (t == 'r') {
if (checkSound(mapid)) {
soundManager.setVolume('bling', 40);
soundManager.setPan('bling', -75)
soundManager.setVolume('blingb', 40);
soundManager.setPan('blingb', 75)
if (pathNumber == 0)
soundManager.play('bling');
if (pathNumber == 1)
soundManager.play('blingb');
}
}
//Done messing with current target
//Now take pre-action regarding the next tile.
//Speaking of the next tile - does it exist?
//End of the line?
if (t == '') {
mapdata[mapid].pathsPending--;
//console.log('path pending', mapdata[mapid].pathsPending);
if (mapdata[mapid].pathsPending > 0)
return;
//console.log('path pending complete', mapdata[mapid].pathsPending);
//Did we beat or tie any records?
//Saw someone do this, thought it was clever.
//Switch for range result.
var disptext = ""
var improvedScore = (count[mapid] > mapjson[mapid].mybest && mapjson[mapid].mybest != "0");
switch (true) {
case (count[mapid] > mapjson[mapid].best):
disptext = "Beat "+mapjson[mapid].bestby+"'s record of "+mapjson[mapid].best+" with "+count[mapid]+"!";
break;
case (count[mapid] == mapjson[mapid].best):
disptext = "Tied "+mapjson[mapid].bestby+"'s record of "+mapjson[mapid].best;
break;
case (mapjson[mapid].mybest == "0"):
disptext = "You scored "+count[mapid]+"!";
break;
case (count[mapid] > mapjson[mapid].mybest):
disptext = "Improved score "+mapjson[mapid].mybest+ " to "+count[mapid];
break;
case (count[mapid] == mapjson[mapid].mybest):
disptext = "Tied personal best of "+count[mapid];
break;
case (count[mapid] < mapjson[mapid].mybest):
disptext = "You got "+count[mapid]+". Your best is "+mapjson[mapid].mybest;
break;
}
//if anything worth mentioning happend let them know.
if (disptext != "") {
if (checkSound(mapid) && improvedScore) {
soundManager.setVolume('charm', 50);
soundManager.setVolume('sc', 50);
soundManager.play('charm');
soundManager.play('sc');
}
updateDsp(mapid, 'dspID', disptext);
flashelement(mapid+',dspID', 8, "#FF3377");
}
//This is the end, lets reset stuff to defaults.
count[mapid] = 0;
mapdata[mapid].pathColor[pathNumber] = '#ffffff';
//Bring the color back to our checkpoints/teleports.
var eid;
for(var i in mapdata[mapid].usedTiles) {
//eval(mapdata[mapid].restoreTiles[i]);
//setTimeout((mapdata[mapid].restoreTiles[i]), 2000);
eid = mapdata[mapid].usedTiles[i];
setTimeout("document.getElementById('"+eid+"').style.backgroundColor = '';", 2500);
setTimeout("document.getElementById('"+eid+"').pressed = false;" , 2500);
}
//Clear
mapdata[mapid].usedTiles = new Array();
//We're done,
animatePathDone(mapid);
return;
}
//The next tile exists, how fast should we get there?
rs = 84;
//How fast should we be going?
selectbox = document.getElementById(mapid+',speed');
var selectedSpeed = selectbox.options[selectbox.selectedIndex].value;
switch (selectedSpeed) {
case '1':
rs =180;
break;
case '2':
rs =94;
break;
case '3':
rs =44;
break;
case '4':
rs =22;
break;
case '5':
rs =0;
break;
}
//The next path code.
switch(t) {
//Are we just moving someplace?
case '1':
x--;
break; //1 - Up
case '2':
y++;
break; //2 - Right
case '3':
x++;
break; //3 - Down
case '4':
y--;
break; //4 - Left
//Special codes within the path.
//Did we aquire a target?
//Checkpoint targets:
case 'a': case 'b': case 'c':
case 'd': case 'e': case 'f':
rs = rs + 410;
if (selectedSpeed <= 2) rs = rs + 200;
mapdata[mapid].pathColor[pathNumber] = targetColor(t);
break;
//Hey, we've ran into a teleport.
case 'u': //tp1
case 'n': //tp2
case 'h': //tp3
case 'j': //tp4
case 'l': //tp5
//Get teleport coords
tmp = p.split(t);
loc = tmp[1].split(',');
y = loc[0];
x = loc[1];
//Flash teleport-out
//Teleport Element ID
tpEid = mapid+','+x+','+y;
if (checkSound(mapid)) {
soundManager.setVolume('ufoblip', 30);
if (pathNumber == 0)
soundManager.setPan('ufoblip', 70);
else
soundManager.setPan('ufoblip', -70);
soundManager.play('ufoblip');
}
document.getElementById(tpEid).style.backgroundColor='';
flashelement(tpEid, 8, mapdata[mapid].pathColor[pathNumber]);
//The path once teleported - and an r to indicate to gray the teleport-out too.
p = 'q'+tmp[2];
//Slow down
rs = rs + 1200;
break;
}
//Remove move from p
p = p.substring(1);
//rs = (10 * p.length) + 40;
// if (mapdata[mapid].moveCount[1] < mapdata[mapid].moveCount[pathNumber] - 2
// || mapdata[mapid].moveCount[0] < mapdata[mapid].moveCount[pathNumber] - 2)
// rs = rs + 100;
if (count[mapid] % 2 == 1 && rs == 0) {
doanimate(x,y,p,t,mapid,pathNumber);
} else {
setTimeout("doanimate("+x+","+y+",'"+p+"','"+t+"','"+mapid+"','"+pathNumber+"')",rs);
}
}
function targetColor(target) {
var r = '#ccc';
switch(target) {
case 'a':
r = '#F777FF';
break;
case 'b':
r = '#FFFF11';
break;
case 'c':
r = '#FF4466';
break;
case 'd':
r = '#ff9911';
break;
case 'e':
r = '#00FFFF';
break;
case 'f':
r = '#ccc';
}
return r;
}
function flashelement(eid, times, color, speed) {
if (typeof(document.getElementById(eid)) == 'undefined') return;
var elementToFlash = document.getElementById(eid);
if (elementToFlash.isBeingFlashed == true) return;
elementToFlash.isBeingFlashed = true;
if (!color) {
color = "#FFFF44";
}
if (!speed) {
speed = 220;
}
speedon = speed * .5;
var currentclass = elementToFlash.className;
if (elementToFlash.classOrigName != undefined)
currentclass = elementToFlash.classOrigName;
var currentColor = elementToFlash.style.backgroundColor;
elementToFlash.className='no_transition '+currentclass;
elementToFlash.style.backgroundColor = '#000000';
for (var i=0; i
';
for (var y in map.tiles) {
for (var x in map.tiles[y]) {
var type = map.tiles[y][x][0];
var value = map.tiles[y][x][1];
if (!value) value = '';
//TODO: If we want to change this line to something that's not retarded _
// we'll need to do a TON of other work... See Blossom "Implement mapclass"
var oldy = (y*1)+1;
var idHandle = map.ID+','+oldy+','+x;
// GOAL WOULD BE THIS LINE INSTEAD.. As it's not retarded.
//var idHandle = map.ID+','+x+','+y;
//oldy is used for Position too... for now
if (mapEditor == true) {
mapgrid += "
";
mapgrid += "
";
} else if (type == 'o') {
mapgrid += "
";
mapgrid += "
";
} else {
mapgrid += "
";
mapgrid += "
";
}
}
}
mapgrid += '
';
if (mapEditor == true) return mapgrid;
var r = '';
//TODO: Track down where that 1 pixel is comingfrom, width-1 is a hack.
r += "
";
r += "
";
r += "
";
r += " MapID: "+map.ID;
r += "
";
r += "
";
r += "
";
r += " ";
r += " "+map.walls+" walls";
r += " ";
r += " ";
r += " ( Reset )";
r += " ";
r += "
";
r += mapgrid;
r += "
";
r += " ";
r += " Speed:";
r += getSpeedOptions(map.ID);
r += "
";
r += "
";
r += getMuteOption(map.ID);
r += "
";
r += "
";
r += "
";
r += " 0 moves";
r += "
";
r += "
";
r += "
";
return r;
}
function mapThumbnailHTML(map, targetWidth, isActive) {
if (!targetWidth) targetWidth = 120;
var scale = map.width / targetWidth;
var width = parseInt(map.width / scale);
var height = parseInt(map.height / scale);
var tileWidth = parseInt(width / map.width);
width = tileWidth * map.width;
height = tileWidth * map.height;
var mapgrid = '';
var r = '';
r += map.name;
mapgrid += '
';
for (var y in map.tiles) {
for (var x in map.tiles[y]) {
var type = map.tiles[y][x][0];
var value = map.tiles[y][x][1];
if (!value) value = '';
mapgrid += "
";
mapgrid += "
";
}
}
mapgrid += '
';
r += mapgrid;
return r;
}
function setMute(value)
{
var value = getCookie('pref_mute');
$('.mapMute').removeClass("mapMute_"+value);
if (value == 'true') {
value = 'false';
soundManager.setVolume('pit', 20);
soundManager.setPan('pit', -60)
soundManager.play('pit');
} else {
value = 'true';
}
savePref('mute', value);
$('.mapMute').addClass("mapMute_"+value);
}
function getMuteOption(mapID) {
var r = '';
var muted = 'false';
if (getCookie('pref_mute') == 'true') {
muted = "true";
}
r += "";
return r;
}
function getSpeedOptions(mapID) {
var listObj = new Object;
var selectedSpeed = 2;
if (getCookie('pref_speed')) {
selectedSpeed = getCookie('pref_speed');
}
listObj[1] = 'Slow';
listObj[2] = 'Med';
listObj[3] = 'Fast';
listObj[4] = 'Ultra';
if (userObj.hasInsaneSpeed) listObj[5] = 'Insane';
var r = '';
r += " ";
return r;
}
function savePref(pref, value) {
setCookie('pref_'+pref, value, 9999);
}
//Cookie functions from w3schools.com
function setCookie(c_name,value,exdays)
{
var exdate=new Date();
exdate.setDate(exdate.getDate() + exdays);
var c_value=escape(value) + ((exdays==null) ? "" : "; expires="+exdate.toUTCString());
document.cookie=c_name + "=" + c_value;
}
function getCookie(c_name)
{
var i,x,y,ARRcookies=document.cookie.split(";");
for (i=0;i