diff --git a/js/Makefile b/js/Makefile index ffa5748..7e40926 100644 --- a/js/Makefile +++ b/js/Makefile @@ -16,7 +16,7 @@ maps.js: FORCE SPRITES=earth.png empty.png lambda.png lift.png openlift.png miner.png rock.png bricks.png SPRITES+=$(wildcard trampoline?.png) SPRITES+=$(wildcard target?.png) -SPRITES+=beard.png razor.png +SPRITES+=beard.png razor.png deadminer.png minerlift.png sprites.png: $(SPRITES) convert -background "#000000" -append $(SPRITES) tmp_sprites.png diff --git a/js/deadminer.png b/js/deadminer.png new file mode 100644 index 0000000..0c3b44d Binary files /dev/null and b/js/deadminer.png differ diff --git a/js/gui.js b/js/gui.js index a3f9279..fd49ba1 100644 --- a/js/gui.js +++ b/js/gui.js @@ -1,4 +1,4 @@ -var mineGui_mine = false, mineGui_curmap, mineGui_curndx, mineGui_moves = ""; +var mineGui_mine = false, mineGui_curmap, mineGui_curndx, mineGui_moves = "", mineGui_mapname = ''; var mineGui_movesBackup = []; var mineGui_customNdx = 1; var mineGui_canvas = true; @@ -20,6 +20,34 @@ var mineGui_spriteOffset = { 'W':26, '!':27 }; +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 +}; +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 +}; var mineGui_images = {}; var mineGui_imagesNeed = 0; @@ -46,7 +74,7 @@ function mineGui_start() { document.getElementById("mineGui_addData").onclick = mineGui_addCustomMap; selMap.onchange = function() { var k = selMap.options[selMap.selectedIndex].text; - mineGui_setMap(mineMaps[k], selMap.selectedIndex); + mineGui_setMap(k, selMap.selectedIndex); selMap.blur(); }; var inpValidate = function() { @@ -129,16 +157,30 @@ function mineGui_start() { 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 = 0; + selMap.selectedIndex = selectIndex; selMap.onchange(); + if (loadMoves !== '') { +// console.log("preset moves: " + loadMoves); + inpMoves.value = loadMoves; + inpMoves.onchange(); + } } function mineGui_addCustomMap() { @@ -174,10 +216,12 @@ function mineGui_move(cmd) { } function mineGui_setMap(map, ndx) { + mineGui_mapname = map; mineGui_movesBackup[mineGui_curndx] = mineGui_moves; - mineGui_curmap = map; + mineGui_curmap = mineMaps[map]; mineGui_curndx = ndx; mineGui_moves = mineGui_movesBackup[mineGui_curndx]; + location.href = '#' + mineGui_mapname + ';' + mineGui_moves; if (!mineGui_moves) mineGui_moves = ""; mineGui_updateMine(); } @@ -197,6 +241,27 @@ function mineGui_updateMine() { function mineGui_show() { if (!mineGui_mine) return; + + location.href = '#' + mineGui_mapname + ';' + mineGui_moves; + var state = ""; + var spriteOffset = mineGui_spriteOffset; + switch (mineGui_mine.state) { + case Mine.ALIVE: + state = "Still mining"; + break; + case Mine.LOST: + state = "Robot broken - " + mineGui_mine.reason; + spriteOffset = mineGui_spriteOffset_Lost; + break; + case Mine.ABORTED: + state = "Aborted"; + break; + case Mine.WON: + state = "Won - " + mineGui_mine.reason; + 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"); @@ -216,7 +281,7 @@ function mineGui_show() { for (var y = 0; y < mineGui_mine.height; ++y) { for (var x = 0; x < mineGui_mine.width; ++x) { - ctx.drawImage(sprites, 0, mineGui_spriteOffset[map[y][x]] * 16, 16, 16, 16*x, 16*y, 16, 16); + ctx.drawImage(sprites, 0, spriteOffset[map[y][x]] * 16, 16, 16, 16*x, 16*y, 16, 16); } } ctx.fillStyle = "#0000FF"; @@ -238,21 +303,6 @@ function mineGui_show() { document.getElementById("mineGui_mineMapDry").textContent = map.join("\n"); document.getElementById("mineGui_moves").value = mineGui_moves; - 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; - } document.getElementById("mineGui_meta").textContent = mineGui_mine.metaText(); document.getElementById("mineGui_state").textContent = state; document.getElementById("mineGui_score").textContent = mineGui_mine.score; diff --git a/js/gui.min.js b/js/gui.min.js index f5e1250..a10a705 100644 --- a/js/gui.min.js +++ b/js/gui.min.js @@ -1 +1 @@ -var mineGui_mine=false,mineGui_curmap,mineGui_curndx,mineGui_moves="";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};var mineGui_images={};var mineGui_imagesNeed=0;function mineGui_loadImg(b,c){var a;++mineGui_imagesNeed;mineGui_images[b]=a=new Image();a.onload=function(){if(0==--mineGui_imagesNeed){mineGui_show()}};a.src=c}function mineGui_start(){var b=document.getElementById("mineGui");var e=document.getElementById("mineGui_selectMap");var c=document.getElementById("mineGui_moves");var a=document.getElementById("mineGui_data");var f={L:1,U:1,R:1,D:1,A:1,W:1,S:1};var d;document.getElementById("mineGui_addData").onclick=mineGui_addCustomMap;e.onchange=function(){var l=e.options[e.selectedIndex].text;mineGui_setMap(mineMaps[l],e.selectedIndex);e.blur()};var g=function(){if(c.value==mineGui_moves){return}mineGui_moves="";var k=c.value.toUpperCase(),l;for(l=0;l0){e.selectedIndex--;e.onchange()}break;case 34:if(e.selectedIndex+10){document.getElementById("mineGui_mineMapWater").textContent=b.splice(-c).join("\n")}else{document.getElementById("mineGui_mineMapWater").textContent=""}document.getElementById("mineGui_mineMapDry").textContent=b.join("\n");document.getElementById("mineGui_moves").value=mineGui_moves;var a="";switch(mineGui_mine.state){case Mine.ALIVE:a="Still mining";break;case Mine.LOST:a="Robot broken - "+mineGui_mine.reason;break;case Mine.ABORTED:a="Aborted";break;case Mine.WON:a="Won - "+mineGui_mine.reason;break}document.getElementById("mineGui_meta").textContent=mineGui_mine.metaText();document.getElementById("mineGui_state").textContent=a;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;document.getElementById("mineGui_razors").textContent=mineGui_mine.razors;document.getElementById("mineGui_belowWater").textContent=mineGui_mine.moves_below_water}; \ No newline at end of file +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};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};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};var mineGui_images={};var mineGui_imagesNeed=0;function mineGui_loadImg(b,c){var a;++mineGui_imagesNeed;mineGui_images[b]=a=new Image();a.onload=function(){if(0==--mineGui_imagesNeed){mineGui_show()}};a.src=c}function mineGui_start(){var b=document.getElementById("mineGui");var e=document.getElementById("mineGui_selectMap");var c=document.getElementById("mineGui_moves");var a=document.getElementById("mineGui_data");var f={L:1,U:1,R:1,D:1,A:1,W:1,S:1};var d;document.getElementById("mineGui_addData").onclick=mineGui_addCustomMap;e.onchange=function(){var p=e.options[e.selectedIndex].text;mineGui_setMap(p,e.selectedIndex);e.blur()};var j=function(){if(c.value==mineGui_moves){return}mineGui_moves="";var k=c.value.toUpperCase(),p;for(p=0;p0){e.selectedIndex--;e.onchange()}break;case 34:if(e.selectedIndex+11){o=h[1]}}e.appendChild(n)}}e.selectedIndex=l;e.onchange();if(o!==""){c.value=o;c.onchange()}}function mineGui_addCustomMap(){var d=document.getElementById("mineGui_data").value;var f;var c=document.getElementById("mineGui_selectMap");document.getElementById("mineGui_addDataResult").textContent="";try{f=new Mine(d)}catch(b){document.getElementById("mineGui_addDataResult").textContent="Adding map failed: "+b;return}mineMaps["custom"+mineGui_customNdx]=d;var a=document.createElement("option");a.textContent="custom"+mineGui_customNdx;c.appendChild(a);mineGui_customNdx++;window.setTimeout(function(){c.selectedIndex=c.options.length-1;c.onchange()},0)}function mineGui_move(a){for(i=0;i0){document.getElementById("mineGui_mineMapWater").textContent=a.splice(-d).join("\n")}else{document.getElementById("mineGui_mineMapWater").textContent=""}document.getElementById("mineGui_mineMapDry").textContent=a.join("\n");document.getElementById("mineGui_moves").value=mineGui_moves;document.getElementById("mineGui_meta").textContent=mineGui_mine.metaText();document.getElementById("mineGui_state").textContent=b;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;document.getElementById("mineGui_razors").textContent=mineGui_mine.razors;document.getElementById("mineGui_belowWater").textContent=mineGui_mine.moves_below_water}; \ No newline at end of file diff --git a/js/mine.js b/js/mine.js index e912441..53038ba 100644 --- a/js/mine.js +++ b/js/mine.js @@ -154,7 +154,6 @@ var Mine = function() { } this.water_level = this.water.level; this.razors = this.beard.razors; - this.beard_growth = this.beard.growth; this.state = ALIVE; }; @@ -301,15 +300,17 @@ var Mine = function() { } this.moves++; if (0 == this.lambdas) { - if (false !== this.lift && 'L' == this.map[this.lift.y][this.lift.x]) { + if (false !== this.lift) { + /* skip 'L' == this.map[this.lift.y][this.lift.x] - official validator replaces + * 'R' with 'O' after the last move too + */ this.map[this.lift.y][this.lift.x] = 'O'; } } newMap = []; growBeard = false; - if (0 > --this.beard_growth) { - this.beard_growth = this.beard.growth; + if (this.beard.growth > 0 && 0 == (this.moves % this.beard.growth)) { growBeard = true; } for (y = 0; y < map.length; ++y) { newMap[y] = this.map[y].slice(); } diff --git a/js/mine.min.js b/js/mine.min.js index 80689e5..1ac4286 100644 --- a/js/mine.min.js +++ b/js/mine.min.js @@ -1 +1 @@ -var Mine=function(){var b=0,f=1,a=2,d=3;function e(g,h){return new Array(h+1).join(g)}function c(g){this.parse(g)}c.ALIVE=b;c.LOST=f;c.ABORTED=a;c.WON=d;c.prototype.parse=function(g){var o,k,h,n,j,m,p;this.orig_map=g;o=g.split(/\r\n?|\r?\n/);h=0;n=o.length;for(k=0;k="A"&&p[m]<="I"){if(this.trampoline.sources[p[m]]){throw"Can have only one trampoline "+p[m]}this.trampoline.sources[p[m]]={x:m,y:k,target:false};this.trampoline.fromSources}else{if(p[m]>="1"&&p[m]<="9"){if(this.trampoline.targets[p[m]]){throw"Can have only one trampoline target "+p[m]}this.trampoline.targets[p[m]]={x:m,y:k,sources:[]}}else{throw"Invalid character in map: '"+p[m]+"'"+m}}break}}}if(this.robot===false){throw"Need a robot"}this.meta={};for(k=0;k"I"){throw"Invalid trampoline source '"+l[1]+"'"}if(l[3].length!=1||l[3]<"1"||l[3]>"9"){throw"Invalid trampoline target '"+l[3]+"'"}if(!this.trampoline.sources[l[1]]){throw"Trampoline "+l[1]+" not defined"}if(!this.trampoline.targets[l[3]]){throw"Trampoline target "+l[3]+" not defined"}if(this.trampoline.sources[l[1]].target){throw"Trampoline "+l[1]+" already has a target"}this.trampoline.sources[l[1]].target=l[3];this.trampoline.targets[l[3]].sources.push(l[1]);break;case"Growth":this.beard.growth=parseInt(l[1]);break;case"Razors":this.beard.razors=parseInt(l[1]);break;default:this.meta[l[0]]=l.splice(1).join(" ");break}}for(k in this.trampoline.sources){if(this.trampoline.sources.hasOwnProperty(k)){if(!this.trampoline.sources[k].target){throw"Trampoline "+k+" has no target"}}}for(k in this.trampoline.targets){if(this.trampoline.targets.hasOwnProperty(k)){if(0==this.trampoline.targets[k].sources.length){throw"Trampoline target "+k+" has no sources"}}}this.water_level=this.water.level;this.razors=this.beard.razors;this.beard_growth=this.beard.growth;this.state=b};c.prototype.get=function(g,h){if(g<0||h<0||g>=this.width||h>=this.height){return"#"}return this.map[h][g]};c.prototype.validMove=function(g){if(this.state!=b){return false}var i,h;g=g.toUpperCase();switch(g){case"L":case"R":i=(g=="L"?-1:1);h=this.map[this.robot.y][this.robot.x+i];switch(h){case"#":return false;case" ":case".":case"!":case"\\":return true;case"L":return false;case"O":return true;case"*":if(" "==this.map[this.robot.y][this.robot.x+2*i]){return true}default:if(this.trampoline.sources.hasOwnProperty(h)){return true}break}break;case"U":case"D":i=(g=="D"?-1:1);h=this.map[this.robot.y+i][this.robot.x];switch(h){case"#":return false;case" ":case".":case"!":case"\\":return true;case"L":return false;case"O":return true;case"*":return false;default:if(this.trampoline.sources.hasOwnProperty(h)){return true}break}break;case"W":case"S":return this.razors>0;case"A":return true}return false};c.prototype.move=function(l){if(this.state!=b){return false}var k,p,z,w;var g,r,q,o,m,u,h=this.map,v;l=l.toUpperCase();if(this.validMove(l)){switch(l.toUpperCase()){case"L":case"R":k=(l=="L"?-1:1);h[this.robot.y][this.robot.x]=" ";p=h[this.robot.y][this.robot.x+k];switch(p){case"*":h[this.robot.y][this.robot.x+2*k]="*";break;case"\\":this.lambdas--;this.found_lambdas++;break;case"!":this.razors++;break;case"O":this._foundLift();break;default:if(this.trampoline.sources.hasOwnProperty(p)){z=this.trampoline.sources[p];w=this.trampoline.targets[z.target];for(k=0;k--this.beard_growth){this.beard_growth=this.beard.growth;v=true}for(q=0;qthis.water.proof){this._drown()}}else{this.moves_below_water=0}if(this.water.flooding>0&&0==(this.moves%this.water.flooding)){++this.water_level}switch(this.state){case f:this.score=25*this.found_lambdas-this.moves;break;case d:this.score=75*this.found_lambdas-this.moves;break;case b:case a:this.score=50*this.found_lambdas-this.moves;break}};c.prototype._drown=function(){if(this.state="A"&&p[m]<="I"){if(this.trampoline.sources[p[m]]){throw"Can have only one trampoline "+p[m]}this.trampoline.sources[p[m]]={x:m,y:k,target:false};this.trampoline.fromSources}else{if(p[m]>="1"&&p[m]<="9"){if(this.trampoline.targets[p[m]]){throw"Can have only one trampoline target "+p[m]}this.trampoline.targets[p[m]]={x:m,y:k,sources:[]}}else{throw"Invalid character in map: '"+p[m]+"'"+m}}break}}}if(this.robot===false){throw"Need a robot"}this.meta={};for(k=0;k"I"){throw"Invalid trampoline source '"+l[1]+"'"}if(l[3].length!=1||l[3]<"1"||l[3]>"9"){throw"Invalid trampoline target '"+l[3]+"'"}if(!this.trampoline.sources[l[1]]){throw"Trampoline "+l[1]+" not defined"}if(!this.trampoline.targets[l[3]]){throw"Trampoline target "+l[3]+" not defined"}if(this.trampoline.sources[l[1]].target){throw"Trampoline "+l[1]+" already has a target"}this.trampoline.sources[l[1]].target=l[3];this.trampoline.targets[l[3]].sources.push(l[1]);break;case"Growth":this.beard.growth=parseInt(l[1]);break;case"Razors":this.beard.razors=parseInt(l[1]);break;default:this.meta[l[0]]=l.splice(1).join(" ");break}}for(k in this.trampoline.sources){if(this.trampoline.sources.hasOwnProperty(k)){if(!this.trampoline.sources[k].target){throw"Trampoline "+k+" has no target"}}}for(k in this.trampoline.targets){if(this.trampoline.targets.hasOwnProperty(k)){if(0==this.trampoline.targets[k].sources.length){throw"Trampoline target "+k+" has no sources"}}}this.water_level=this.water.level;this.razors=this.beard.razors;this.state=b};c.prototype.get=function(g,h){if(g<0||h<0||g>=this.width||h>=this.height){return"#"}return this.map[h][g]};c.prototype.validMove=function(g){if(this.state!=b){return false}var i,h;g=g.toUpperCase();switch(g){case"L":case"R":i=(g=="L"?-1:1);h=this.map[this.robot.y][this.robot.x+i];switch(h){case"#":return false;case" ":case".":case"!":case"\\":return true;case"L":return false;case"O":return true;case"*":if(" "==this.map[this.robot.y][this.robot.x+2*i]){return true}default:if(this.trampoline.sources.hasOwnProperty(h)){return true}break}break;case"U":case"D":i=(g=="D"?-1:1);h=this.map[this.robot.y+i][this.robot.x];switch(h){case"#":return false;case" ":case".":case"!":case"\\":return true;case"L":return false;case"O":return true;case"*":return false;default:if(this.trampoline.sources.hasOwnProperty(h)){return true}break}break;case"W":case"S":return this.razors>0;case"A":return true}return false};c.prototype.move=function(l){if(this.state!=b){return false}var k,p,z,w;var g,r,q,o,m,u,h=this.map,v;l=l.toUpperCase();if(this.validMove(l)){switch(l.toUpperCase()){case"L":case"R":k=(l=="L"?-1:1);h[this.robot.y][this.robot.x]=" ";p=h[this.robot.y][this.robot.x+k];switch(p){case"*":h[this.robot.y][this.robot.x+2*k]="*";break;case"\\":this.lambdas--;this.found_lambdas++;break;case"!":this.razors++;break;case"O":this._foundLift();break;default:if(this.trampoline.sources.hasOwnProperty(p)){z=this.trampoline.sources[p];w=this.trampoline.targets[z.target];for(k=0;k0&&0==(this.moves%this.beard.growth)){v=true}for(q=0;qthis.water.proof){this._drown()}}else{this.moves_below_water=0}if(this.water.flooding>0&&0==(this.moves%this.water.flooding)){++this.water_level}switch(this.state){case f:this.score=25*this.found_lambdas-this.moves;break;case d:this.score=75*this.found_lambdas-this.moves;break;case b:case a:this.score=50*this.found_lambdas-this.moves;break}};c.prototype._drown=function(){if(this.state