icfp15/js/gui.js

356 lines
9.7 KiB
JavaScript

var mineGui_mine = false, mineGui_curmap, mineGui_curndx, mineGui_moves = "", mineGui_mapname = '';
var mineGui_movesBackup = [];
var mineGui_customNdx = 1;
var mineGui_canvas = true;
var mineGui_imgSources = {
'sprites': 'sprites.png'
};
var mineGui_spriteOffset = {
'R': 5,
'#': 7,
'*': 6,
'\\': 2,
'L': 3,
'O': 4,
'.': 0,
' ': 1,
'A': 8,'B': 9,'C':10,'D':11,'E':12,'F':13,'G':14,'H':15,'I':16,
'1':17,'2':18,'3':19,'4':20,'5':21,'6':22,'7':23,'8':24,'9':25,
'W':26,
'!':27,
'@':30
};
var mineGui_spriteOffset_Lost = {
'R': 28,
'#': 7,
'*': 6,
'\\': 2,
'L': 3,
'O': 4,
'.': 0,
' ': 1,
'A': 8,'B': 9,'C':10,'D':11,'E':12,'F':13,'G':14,'H':15,'I':16,
'1':17,'2':18,'3':19,'4':20,'5':21,'6':22,'7':23,'8':24,'9':25,
'W':26,
'!':27,
'@':30
};
var mineGui_spriteOffset_Won = {
'R': 29,
'#': 7,
'*': 6,
'\\': 2,
'L': 3,
'O': 29,
'.': 0,
' ': 1,
'A': 8,'B': 9,'C':10,'D':11,'E':12,'F':13,'G':14,'H':15,'I':16,
'1':17,'2':18,'3':19,'4':20,'5':21,'6':22,'7':23,'8':24,'9':25,
'W':26,
'!':27,
'@':30
};
var mineGui_images = {};
var mineGui_imagesNeed = 0;
function mineGui_loadImg(key, src) {
var img;
++mineGui_imagesNeed;
mineGui_images[key] = img = new Image();
img.onload = function() {
if (0 == --mineGui_imagesNeed) {
mineGui_show();
}
};
img.src = src;
}
function mineGui_start() {
var div = document.getElementById("mineGui");
var selMap = document.getElementById("mineGui_selectMap");
var inpMoves = document.getElementById("mineGui_moves");
var customMapInput = document.getElementById("mineGui_data")
var validMoves = {L:1,U:1,R:1,D:1,A:1,W:1,S:1};
var k;
document.getElementById("mineGui_addData").onclick = mineGui_addCustomMap;
selMap.onchange = function() {
var k = selMap.options[selMap.selectedIndex].text;
mineGui_setMap(k, selMap.selectedIndex);
selMap.blur();
};
var inpValidate = function() {
if (inpMoves.value == mineGui_moves) return;
mineGui_moves = "";
var txt = inpMoves.value.toUpperCase(), i;
for (i = 0; i < txt.length; ++i) {
if (validMoves[txt[i]]) mineGui_moves += txt[i];
}
mineGui_updateMine();
};
var delayInpValidate = function(event) {
// console.log("input", event, event.type);
window.setTimeout(inpValidate, 0);
};
inpMoves.onchange = delayInpValidate;
inpMoves.onpaste = delayInpValidate;
inpMoves.onkeypress = delayInpValidate;
document.body.onkeydown = function (event) {
// console.log("body", event);
// console.log("isChar", event.isChar,
// "; char '"+String.fromCharCode(event.charCode)+
// "'; key '"+String.fromCharCode(event.keyCode)+"'")
if (document.activeElement === customMapInput) return;
if (event.ctrlKey || event.altKey || event.metaKey) return;
var handled = true;
// ascii keys are reported as uppercase ascii code
var cmd = String.fromCharCode(event.keyCode);
if (validMoves[cmd]) {
mineGui_move(cmd);
} else if (cmd == 'C') { // clear
mineGui_moves = "";
mineGui_updateMine();
} else if (cmd == 'T') { // toggle text/canvas
mineGui_canvas = !mineGui_canvas;
console.log("canvas show", mineGui_canvas);
mineGui_show();
} else switch (event.keyCode) {
case 8: // backspace -> undo
mineGui_moves = mineGui_moves.slice(0,-1);
mineGui_updateMine();
break;
case 33: // page up
if (selMap.selectedIndex > 0) {
selMap.selectedIndex--;
selMap.onchange();
}
break;
case 34: // page down
if (selMap.selectedIndex+1 < selMap.options.length) {
selMap.selectedIndex++;
selMap.onchange();
}
break;
case 37: // left
if (mineGui_mine.validMove('L')) mineGui_move('L');
break;
case 38: // up
if (mineGui_mine.validMove('U')) mineGui_move('U');
break;
case 39: // right
if (mineGui_mine.validMove('R')) mineGui_move('R');
break;
case 40: // down
if (mineGui_mine.validMove('D')) mineGui_move('D');
break;
default:
handled = false;
break;
}
if (handled) {
// console.log("body handled", event, event.type);
event.preventDefault();
return true;
}
};
for (k in mineGui_imgSources) {
if (mineGui_imgSources.hasOwnProperty(k)) {
mineGui_loadImg(k, mineGui_imgSources[k]);
}
}
var fragment = window.location.hash.slice(1).split(';');
var searchMap = fragment[0];
var loadMoves = '';
var selectIndex = 0;
for (k in mineMaps) {
if (mineMaps.hasOwnProperty(k)) {
var entry = document.createElement("option");
entry.textContent = k;
if (k === searchMap) {
// console.log("selected map " + k);
selectIndex = selMap.options.length;
if (fragment.length > 1) loadMoves = fragment[1];
}
selMap.appendChild(entry);
}
//entry.add
}
selMap.selectedIndex = selectIndex;
selMap.onchange();
if (loadMoves !== '') {
// console.log("preset moves: " + loadMoves);
inpMoves.value = loadMoves;
inpMoves.onchange();
}
}
function mineGui_addCustomMap() {
var map = document.getElementById("mineGui_data").value;
var mine;
var selMap = document.getElementById("mineGui_selectMap");
document.getElementById("mineGui_addDataResult").textContent = "";
try {
mine = new Mine(map);
} catch (e) {
document.getElementById("mineGui_addDataResult").textContent = "Adding map failed: " + e;
return;
}
mineMaps["custom" + mineGui_customNdx] = map;
var entry = document.createElement("option");
entry.textContent = "custom" + mineGui_customNdx;
selMap.appendChild(entry);
mineGui_customNdx++;
window.setTimeout(function() {
selMap.selectedIndex = selMap.options.length - 1;
selMap.onchange();
}, 0);
}
function mineGui_move(cmd) {
for (i = 0; i < cmd.length; ++i) {
if (mineGui_mine.state != Mine.ALIVE) break;
mineGui_moves += cmd[i];
mineGui_mine.move(cmd[i]);
}
mineGui_show();
}
function mineGui_setMap(map, ndx) {
mineGui_mapname = map;
mineGui_movesBackup[mineGui_curndx] = mineGui_moves;
mineGui_curmap = mineMaps[map];
mineGui_curndx = ndx;
mineGui_moves = mineGui_movesBackup[mineGui_curndx];
if (!mineGui_moves) mineGui_moves = "";
location.href = '#' + mineGui_mapname + ';' + mineGui_moves;
mineGui_updateMine();
}
function mineGui_updateMine() {
// redo moves
mineGui_mine = new Mine(mineGui_curmap);
var cmd = mineGui_moves;
mineGui_moves = "";
for (i = 0; i < cmd.length; ++i) {
if (mineGui_mine.state != Mine.ALIVE) break;
mineGui_moves += cmd[i];
mineGui_mine.move(cmd[i]);
}
mineGui_show();
}
var mineGui_drawQueued = false;
function mineGui_draw() {
if (!mineGui_drawQueued) {
mineGui_drawQueued = true;
window.setTimeout(mineGui_draw_queued, 0);
}
}
function mineGui_draw_queued() {
mineGui_drawQueued = false;
var spriteOffset = mineGui_spriteOffset;
switch (mineGui_mine.state) {
case Mine.ALIVE:
break;
case Mine.LOST:
spriteOffset = mineGui_spriteOffset_Lost;
break;
case Mine.ABORTED:
break;
case Mine.WON:
spriteOffset = mineGui_spriteOffset_Won;
break;
}
var waterLevel = Math.max(mineGui_mine.water_level, 0);
var map = mineGui_mine.toString().split(/\n/);
var canv = document.getElementById("mineGui_mineCanvas");
var mapNode = document.getElementById("mineGui_mineMap");
if (mineGui_canvas && 0 == mineGui_imagesNeed) {
canv.style.display = '';
canv.style.visibility = 'visible';
mapNode.style.display = 'none';
mapNode.style.visibility = 'hidden';
canv.width = 16*mineGui_mine.width;
canv.height = 16*mineGui_mine.height;
var ctx = canv.getContext("2d");
ctx.globalAlpha=1.0;
ctx.fillStyle = "black";
ctx.fillRect(0,0,canv.width, canv.height);
var sprites = mineGui_images.sprites;
for (var y = 0; y < mineGui_mine.height; ++y) {
for (var x = 0; x < mineGui_mine.width; ++x) {
ctx.drawImage(sprites, 0, spriteOffset[map[y][x]] * 16, 16, 16, 16*x, 16*y, 16, 16);
}
}
ctx.fillStyle = "#0000FF";
ctx.globalAlpha = 0.3;
y = 16*(mineGui_mine.height - waterLevel);
ctx.fillRect(0,y,canv.width, canv.height-y);
} else {
canv.style.display = 'none';
canv.style.visibility = 'hidden';
mapNode.style.display = '';
mapNode.style.visibility = 'visible';
}
}
var mineGui_fragmentQueued = false;
function mineGui_updateFragment() {
if (false !== mineGui_fragmentQueued) window.clearTimeout(mineGui_fragmentQueued);
mineGui_fragmentQueued = window.setTimeout(mineGui_updateFragment_queued, 100);
}
function mineGui_updateFragment_queued() {
mineGui_fragmentQueued = false;
location.href = '#' + mineGui_mapname + ';' + mineGui_moves;
}
function mineGui_show(queued) {
if (!mineGui_mine) return;
mineGui_updateFragment();
var state = "";
switch (mineGui_mine.state) {
case Mine.ALIVE:
state = "Still mining";
break;
case Mine.LOST:
state = "Robot broken - " + mineGui_mine.reason;
break;
case Mine.ABORTED:
state = "Aborted";
break;
case Mine.WON:
state = "Won - " + mineGui_mine.reason;
break;
}
var waterLevel = Math.max(mineGui_mine.water_level, 0);
var map = mineGui_mine.toString().split(/\n/);
mineGui_draw();
if (waterLevel > 0) {
document.getElementById("mineGui_mineMapWater").textContent = map.splice(-waterLevel).join("\n");
} else {
document.getElementById("mineGui_mineMapWater").textContent = "";
}
document.getElementById("mineGui_mineMapDry").textContent = map.join("\n");
document.getElementById("mineGui_moves").value = mineGui_moves;
document.getElementById("mineGui_meta").textContent = mineGui_mine.metaText();
document.getElementById("mineGui_state").textContent = state;
document.getElementById("mineGui_score").textContent = mineGui_mine.score;
document.getElementById("mineGui_scoreMoves").textContent = mineGui_mine.moves;
document.getElementById("mineGui_scoreLambdas").textContent = mineGui_mine.found_lambdas + "/" + (mineGui_mine.lambdas+mineGui_mine.found_lambdas);
document.getElementById("mineGui_razors").textContent = mineGui_mine.razors;
document.getElementById("mineGui_belowWater").textContent = mineGui_mine.moves_below_water;
}