js/website simulator
This commit is contained in:
parent
9378156ac9
commit
8512ef94f1
8
js/Makefile
Normal file
8
js/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
MAPS=$(wildcard ../maps/contest*.map ../maps/flood*.map)
|
||||
|
||||
all: maps.js
|
||||
|
||||
|
||||
maps.js: mapsToJson.js $(MAPS)
|
||||
./mapsToJson.js $(MAPS) > maps.js
|
184
js/gui.js
Normal file
184
js/gui.js
Normal file
@ -0,0 +1,184 @@
|
||||
var mineGui_mine, mineGui_curmap, mineGui_curndx, mineGui_moves = "";
|
||||
var mineGui_movesBackup = [];
|
||||
var mineGui_customNdx = 1;
|
||||
|
||||
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_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};
|
||||
document.getElementById("mineGui_addData").onclick = mineGui_addCustomMap;
|
||||
selMap.onchange = function() {
|
||||
var k = selMap.options[selMap.selectedIndex].text;
|
||||
mineGui_setMap(mineMaps[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];
|
||||
}
|
||||
inpMoves.blur();
|
||||
mineGui_updateMine();
|
||||
};
|
||||
var delayInpValidate = function() { window.setTimeout(inpValidate, 0); };
|
||||
inpMoves.onchange = delayInpValidate;
|
||||
inpMoves.onpaste = delayInpValidate;
|
||||
inpMoves.onkeypress = delayInpValidate;
|
||||
document.onkeypress = function (event) {
|
||||
if (document.activeElement === customMapInput) return;
|
||||
if (event.ctrlKey || event.altKey || event.metaKey) return;
|
||||
var handled = true;
|
||||
if (event.keyCode == 8 || event.charCode == 8) {
|
||||
// backspace -> undo
|
||||
mineGui_moves = mineGui_moves.slice(0,-1);
|
||||
mineGui_updateMine();
|
||||
} else if (event.which === 0 && event.keyCode) {
|
||||
switch (event.keyCode) {
|
||||
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
|
||||
mineGui_move('L');
|
||||
break;
|
||||
case 38: // up
|
||||
mineGui_move('U');
|
||||
break;
|
||||
case 39: // right
|
||||
mineGui_move('R');
|
||||
break;
|
||||
case 40: // down
|
||||
mineGui_move('D');
|
||||
break;
|
||||
default:
|
||||
handled = false;
|
||||
break;
|
||||
}
|
||||
} else if (event.charCode) {
|
||||
console.log(event.charCode);
|
||||
cmd = String.fromCharCode(event.charCode).toUpperCase();
|
||||
if (validMoves[cmd]) {
|
||||
mineGui_move(cmd);
|
||||
} else if (cmd == 'R') { // redraw
|
||||
mineGui_updateMine();
|
||||
} else if (cmd == 'C') { // clear
|
||||
mineGui_moves = "";
|
||||
mineGui_updateMine();
|
||||
} else {
|
||||
handled = false;
|
||||
}
|
||||
} else {
|
||||
handled = false;
|
||||
}
|
||||
if (handled) event.preventDefault();
|
||||
};
|
||||
for (k in mineMaps) {
|
||||
if (mineMaps.hasOwnProperty(k)) {
|
||||
var entry = document.createElement("option");
|
||||
entry.textContent = k;
|
||||
selMap.appendChild(entry);
|
||||
}
|
||||
//entry.add
|
||||
}
|
||||
selMap.selectedIndex = 0;
|
||||
selMap.onchange();
|
||||
}
|
||||
|
||||
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_movesBackup[mineGui_curndx] = mineGui_moves;
|
||||
mineGui_curmap = map;
|
||||
mineGui_curndx = ndx;
|
||||
mineGui_moves = mineGui_movesBackup[mineGui_curndx];
|
||||
if (!mineGui_moves) 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();
|
||||
}
|
||||
|
||||
function mineGui_show() {
|
||||
var waterLevel = Math.max(mineGui_mine.meta.Water, 0);
|
||||
var map = mineGui_mine.toString().split(/\n/);
|
||||
if (waterLevel > 0) {
|
||||
document.getElementById("mineGui_mineMapWater").textContent = map.splice(-waterLevel).join("\n");
|
||||
} else {
|
||||
document.getElementById("mineGui_mineMapWater").textContent = "";
|
||||
}
|
||||
document.getElementById("mineGui_mineMap").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;
|
||||
document.getElementById("mineGui_scoreMoves").textContent = mineGui_mine.moves;
|
||||
document.getElementById("mineGui_scoreLambdas").textContent = mineGui_mine.found_lambdas;
|
||||
document.getElementById("mineGui_belowWater").textContent = mineGui_mine.moves_below_water;
|
||||
}
|
49
js/index.html
Normal file
49
js/index.html
Normal file
@ -0,0 +1,49 @@
|
||||
<html><head>
|
||||
<script type="text/javascript" src="maps.js"></script>
|
||||
<script type="text/javascript" src="mine.js"></script>
|
||||
<script type="text/javascript" src="gui.js"></script>
|
||||
<title>ICFP Contest 2012 Simulator</title>
|
||||
</head><body>
|
||||
<h2>ICFP Contest 2012 Simulator</h2>
|
||||
Links: <a href="http://icfpcontest2012.wordpress.com/">contest page</a>.<br>
|
||||
<i>This simulator may or may not perform according to specs, who knows...</i><br/>
|
||||
|
||||
<br/>
|
||||
|
||||
<div id="mineGui">
|
||||
Select Map: <select id="mineGui_selectMap"></select>
|
||||
<div style="white-space: pre">Moves: <input type="text" id="mineGui_moves" value="" style="width: 80%; font-weight: bold; border: 1px solid"></input></div>
|
||||
<table align=top><tr><td style="padding-right: 50px;vertical-align:top">
|
||||
<pre id="mineGui_mineMap" style="margin-bottom: 0px"></pre>
|
||||
<pre id="mineGui_mineMapWater" style="margin-top: 0px; background: lightblue"></pre>
|
||||
</td><td style="vertical-align:top">
|
||||
<pre id="mineGui_meta"></pre>
|
||||
</td></tr></table>
|
||||
<div>Score: <b style="font:monospace" id="mineGui_score">0</b>
|
||||
<span style="font-size:80%">
|
||||
(<b style="font:monospace" id="mineGui_scoreMoves">0</b> moves,
|
||||
found <b style="font:monospace" id="mineGui_scoreLambdas">0</b> Lambdas)
|
||||
</span>
|
||||
</div>
|
||||
<div>Status: <b style="font:monospace" id="mineGui_state">0</b></div>
|
||||
<div>For <b style="font:monospace" id="mineGui_belowWater">0</b> moves under water</div>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
<pre>Help:
|
||||
(<b>L</b>)eft/(<b>U</b>)p/(<b>R</b>)ight/(<b>D</b>)own work as expected (letter and arrow keys), (<b>A</b>)bort and (<b>W</b>)ait too.
|
||||
Special keys: PageUp/PageDown for map select, Backspace for undo, (<b>C</b>)lear and (<b>R</b>)edraw
|
||||
Be careful: a reload looses all custom maps and saved moves.
|
||||
</pre>
|
||||
|
||||
Build custom map: <button id="mineGui_addData">Add Map</button><br>
|
||||
<pre id="mineGui_addDataResult" style="color:red; font-weight: bold"></pre>
|
||||
<textarea id="mineGui_data" rows=15 cols=80></textarea>
|
||||
|
||||
<div>© 2012 Stefan Bühler. Please do not use my code in contest submissions :)</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
mineGui_start();
|
||||
</script>
|
||||
</body></html>
|
2
js/maps.js
Normal file
2
js/maps.js
Normal file
@ -0,0 +1,2 @@
|
||||
var mineMaps = {"contest10":"#############################\n#..........................\\#\n#..\\\\###...#.... ###.#\n#..\\*\\\\\\.. #.... ..##\\\\..\\#.#\n#..\\*\\.... #.... ..#\\#....#.#\n#...\\###.. #.... ....#....#.#\n#... ..... ..... .####......#\n#\\\\. #.... .......#\n#... #..#. .....*\\ ##.......#\n#.#....... ...#.. ....######\n#. ...#... ...#.\\ ....#..* #\n##........ ...#.. #....#.#\\\\#\n#.....*... .....*\\#\\\\.....*.#\n#.***.* .......*\\****.....#.#\n#.\\\\\\.. ................ .#\n#.##### .###### ##### #\n#....\\\\.................... #\n#....****...#.##.....\\\\\\\\..\\#\n#....\\\\\\\\...#.........*....\\#\n#....\\\\\\\\...#.\\\\. #\\###.\\#\n#.... ..#.... ...#\\\\\\\\. #\n#........ ..#.... ...#..... #\n#........ ........#R#\n###########################L#\n","contest1":"######\n#. *R#\n# \\.#\n#\\ * #\nL .\\#\n######\n","contest2":"#######\n#..***#\n#..\\\\\\#\n#...**#\n#.*.*\\#\nLR....#\n#######\n","contest3":"########\n#..R...#\n#..*...#\n#..#...#\n#.\\.\\..L\n####**.#\n#\\.....#\n#\\..* .#\n########\n","contest4":"#########\n#.*..#\\.#\n#.\\..#\\.L\n#.R .##.#\n#.\\ ...#\n#..\\ ..#\n#...\\ ##\n#....\\ \\#\n#########\n","contest5":"############\n#..........#\n#.....*....#\n#..\\\\\\\\\\\\..#\n#. ....#\n#..\\\\\\\\\\\\\\.#\n#..\\.. .#\n#..\\.. ....#\n#..... ..* #\n#..### ### #\n#...R#\\#\\\\.#\n######L#####\n","contest6":"###############\n#\\\\\\.......** #\n#\\\\#.#####...##\n#\\\\#.....*##. #\n#\\#####\\...## #\n#\\......####* #\n#\\.######* #.\\#\n#\\.#. *...##.##\n#\\##. .. *...#\n#\\...... L#.#.#\n###########.#.#\n#\\..........#.#\n##.##########.#\n#R.#\\.........#\n###############\n","contest7":" #######\n ## *#\n ##R *##\n ##\\\\\\\\##\n ##....##\n ##..\\ . ##\n ## . L . ##\n ##\\\\\\# #\\\\\\\\##\n ###### #######\n","contest8":"##############\n#\\\\... ......#\n###.#. ...*..#\n #.#. ... ..#\n### #. \\ ..#\n#. .#..... **#######\n#.#\\#..... ..\\\\\\*. #\n#*\\\\#.###. ####\\\\\\ #\n#\\\\.#. ...## \\ #\n#\\#.#..... ....# \\ # \n###.#..... ....# ##\n#\\\\.#..... ....#\\ # \n########.. ..###*####\n#......... .........#\n#......... ....***..#\n#..\\\\\\\\\\ # ####.....#\n#........*R..\\\\\\ .#\n##########L##########\n","contest9":" #L#######\n #*** \\\\ #\n #\\\\\\ .. #\n#########.## ##########\n#.......\\ ..........* .#\n#*******\\......#....#\\\\ .#\n###\\.\\\\\\...**..#....... *#\n#*****\\\\ .\\\\..## #\\.#\n######### .... ##########\n # #\n ####*#### \n #.......#\n######### \\\\\\\\*##########\n#*\\\\ **# *..*\\ \\\\\\\\\\#\n#.\\**\\*** .....**.# \\\\##\\#\n#\\R...... .\\\\.. \\\\\\\\\\#\n##########################\n","flood1":"###########\n#....R....#\n#.*******.#\n#.\\\\\\\\\\\\\\.#\n#. .#\n#..*\\\\\\*..#\n#.#*\\\\\\*#.#\n#########L#\n\nWater 1\nFlooding 8 \nWaterproof 5\n","flood2":"#######\n#..***#\n#..\\\\\\#\n#...**#\n#.*.*\\#\nLR....#\n#######\n\nFlooding 5\nWaterproof 3\n","flood3":"############\n#..........#\n#.....*....#\n#..\\\\\\\\\\\\..#\n#. ....#\n#..\\\\\\\\\\\\\\.#\n#..\\.. .#\n#..\\.. ....#\n#..... ..* #\n#..### ### #\n#...R#\\#\\\\.#\n######L#####\n\nWaterproof 10 \nFlooding 10\nWater 2\n","flood4":"########################\n#.....................\\#\n#......*\\ ...........#\n#......*... ......* ...#\n#.. \\\\... .*..... ...#\n#.. ....... ....... ...#\n#.. ....... .\\\\.... ...# ######\n#. .... .....\\...# #\\\\\\\\#\n#\\\\\\......... .........# #....#\n########### R ########*#####\n #.......... ........***\\\\\\#\n #.......... ............**#\n #.......... ......... *.*\\#\n #....\\\\.... ....\\\\..... ..L\n #.....................****#\n #........\\*...............#\n #........... .........#\n #.........................#\n ###########################\n\nWater 1\nFlooding 20\nWaterproof 10\n","flood5":"#########\n#.*..#\\.#\n#.\\..#\\.L\n#.R .##.#\n#.\\ ...#\n#..\\ ..#\n#...\\ ##\n#....\\ \\#\n#########\n\nWater 2\nFlooding 11\nWaterproof 5\n"};
|
||||
if (typeof exports !== "undefined") {exports.maps = mineMaps;}
|
14
js/mapsToJson.js
Executable file
14
js/mapsToJson.js
Executable file
@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
var i, map, maps = {}, fname;
|
||||
for (i = 2; i < process.argv.length; ++i) {
|
||||
fname = process.argv[i];
|
||||
map = fs.readFileSync(fname, 'utf-8');
|
||||
maps[path.basename(fname, '.map')] = map;
|
||||
}
|
||||
|
||||
process.stdout.write("var mineMaps = " + JSON.stringify(maps) + ";\n");
|
||||
process.stdout.write('if (typeof exports !== "undefined") {exports.maps = mineMaps;}' + "\n");
|
287
js/mine.js
Normal file
287
js/mine.js
Normal file
@ -0,0 +1,287 @@
|
||||
|
||||
var Mine = function() {
|
||||
var ALIVE = 0, LOST = 1, ABORTED = 2, WON = 3;
|
||||
|
||||
function defaultMeta() {
|
||||
return {
|
||||
Water: 0,
|
||||
Flooding: 0,
|
||||
Waterproof: 10,
|
||||
}
|
||||
}
|
||||
|
||||
function repeat(str, n) {
|
||||
return new Array(n+1).join(str);
|
||||
}
|
||||
|
||||
function Mine(map) {
|
||||
this.parse(map)
|
||||
};
|
||||
Mine.ALIVE = ALIVE;
|
||||
Mine.LOST = LOST;
|
||||
Mine.ABORTED = ABORTED;
|
||||
Mine.WON = WON;
|
||||
|
||||
Mine.prototype.parse = function(map) {
|
||||
var lines, i, width, height, pair, x, line;
|
||||
this.orig_map = map;
|
||||
lines = map.split(/\r\n?|\r?\n/);
|
||||
|
||||
width = 0;
|
||||
height = lines.length;
|
||||
for (i = 0; i < lines.length; ++i) {
|
||||
if (0 == lines[i].length) {
|
||||
height = i;
|
||||
lines.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
width = Math.max(width, lines[i].length);
|
||||
}
|
||||
this.height = height;
|
||||
this.width = width;
|
||||
this.map = map = lines.splice(0, height).reverse();
|
||||
this.lambdas = 0;
|
||||
this.found_lambdas = 0;
|
||||
this.moves = 0;
|
||||
this.score = 0;
|
||||
this.moves_below_water = 0;
|
||||
this.lift = this.robot = false;
|
||||
for (i = 0; i < height; ++i) {
|
||||
// padding
|
||||
if (map[i].length < width) map[i] += repeat(' ', width - map[i].length);
|
||||
line = map[i] = map[i].split('');
|
||||
|
||||
// scan
|
||||
for (x = 0; x < width; ++x) {
|
||||
switch (line[x]) {
|
||||
case ' ':
|
||||
case '*':
|
||||
case '#':
|
||||
case '.':
|
||||
break;
|
||||
case '\\':
|
||||
this.lambdas++;
|
||||
break;
|
||||
case 'L':
|
||||
if (this.lift !== false) throw "Only one lift is allowed";
|
||||
this.lift = { x: x, y: i };
|
||||
break;
|
||||
case 'R':
|
||||
if (this.robot !== false) throw "Only one robot is allowed";
|
||||
this.robot = { x: x, y: i };
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if (this.lift === false) throw "Need a lift";
|
||||
if (this.robot === false) throw "Need a robot";
|
||||
|
||||
// meta data
|
||||
this.meta = defaultMeta();
|
||||
for (i = 0; i < lines.length; ++i) {
|
||||
if (0 == lines[i].length) continue;
|
||||
pair = lines[i].split(/ +/);
|
||||
this.meta[pair[0]] = pair.splice(1).join(" ");
|
||||
}
|
||||
this.state = ALIVE;
|
||||
};
|
||||
|
||||
Mine.prototype.get = function (x, y) {
|
||||
if (x < 0 || y < 0 || x >= this.width || y >= this.height) return '#';
|
||||
return this.map[y][x];
|
||||
}
|
||||
|
||||
Mine.prototype.validMove = function (command) {
|
||||
if (this.state != ALIVE) return false;
|
||||
var n;
|
||||
command = command.toUpperCase();
|
||||
switch (command) {
|
||||
case 'L':
|
||||
case 'R':
|
||||
n = (command == 'L' ? -1 : 1);
|
||||
if (this.robot.x + n < 0) return false;
|
||||
if (this.robot.x + n >= this.width) return false;
|
||||
switch (this.map[this.robot.y][this.robot.x+n]) {
|
||||
case '#': return false;
|
||||
case ' ':
|
||||
case '.':
|
||||
case '\\': return true;
|
||||
case 'L': return 0 == this.lambdas;
|
||||
case '*':
|
||||
if (this.robot.x + 2*n < 0) return false;
|
||||
if (this.robot.x + 2*n >= this.width) return false;
|
||||
if (' ' == this.map[this.robot.y][this.robot.x+2*n]) return true;
|
||||
}
|
||||
break;
|
||||
case 'U':
|
||||
case 'D':
|
||||
n = (command == 'D' ? -1 : 1);
|
||||
if (this.robot.y + n < 0) return false;
|
||||
if (this.robot.y + n >= this.height) return false;
|
||||
switch (this.map[this.robot.y+n][this.robot.x]) {
|
||||
case '#': return false;
|
||||
case ' ':
|
||||
case '.':
|
||||
case '\\': return true;
|
||||
case 'L': return 0 == this.lambdas;
|
||||
case '*': return false;
|
||||
" style="}
|
||||
break;
|
||||
case 'W':
|
||||
case 'A':
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
Mine.prototype.move = function(command) {
|
||||
if (this.state != ALIVE) return false;
|
||||
var n;
|
||||
command = command.toUpperCase();
|
||||
if (this.validMove(command)) {
|
||||
switch (command.toUpperCase()) {
|
||||
case 'L':
|
||||
case 'R':
|
||||
n = (command == 'L' ? -1 : 1);
|
||||
this.map[this.robot.y][this.robot.x] = ' ';
|
||||
switch (this.map[this.robot.y][this.robot.x+n]) {
|
||||
case '*':
|
||||
this.map[this.robot.y][this.robot.x+2*n] = '*';
|
||||
break;
|
||||
case '\\':
|
||||
this.lambdas--;
|
||||
this.found_lambdas++;
|
||||
break;
|
||||
case 'L':
|
||||
this._foundLift();
|
||||
break;
|
||||
}
|
||||
this.robot.x += n;
|
||||
this.map[this.robot.y][this.robot.x] = 'R';
|
||||
break;
|
||||
case 'U':
|
||||
case 'D':
|
||||
n = (command == 'D' ? -1 : 1);
|
||||
this.map[this.robot.y][this.robot.x] = ' ';
|
||||
switch (this.map[this.robot.y+n][this.robot.x]) {
|
||||
case '\\':
|
||||
this.lambdas--;
|
||||
this.found_lambdas++;
|
||||
break;
|
||||
case 'L':
|
||||
this._foundLift();
|
||||
break;
|
||||
}
|
||||
this.robot.y += n;
|
||||
this.map[this.robot.y][this.robot.x] = 'R';
|
||||
break;
|
||||
case 'A':
|
||||
this._abort();
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.moves++;
|
||||
|
||||
var newMap = [], x, y, below;
|
||||
for (y = 0; y < this.height; ++y) { newMap[y] = this.map[y].slice(); }
|
||||
|
||||
for (y = 0; y < this.height; ++y) {
|
||||
for (x = 0; x < this.width; ++x) {
|
||||
if ('*' == this.map[y][x]) {
|
||||
below = this.get(x, y-1);
|
||||
if (' ' == below) {
|
||||
// fall down
|
||||
newMap[y-1][x] = '*';
|
||||
newMap[y][x] = ' ';
|
||||
if ('R' == this.get(x, y-2)) this._crushed();
|
||||
} else if ((below == '*' || below == '\\') && ' ' == this.get(x+1, y-1) && ' ' == this.map[y][x+1]) {
|
||||
// fall right
|
||||
newMap[y-1][x+1] = '*';
|
||||
newMap[y][x] = ' ';
|
||||
if ('R' == this.get(x+1, y-2)) this._crushed();
|
||||
} else if ((below == '*') && ' ' == this.get(x-1, y-1) && ' ' == this.map[y][x-1]) {
|
||||
// fall left
|
||||
newMap[y-1][x-1] = '*';
|
||||
newMap[y][x] = ' ';
|
||||
if ('R' == this.get(x-1, y-2)) this._crushed();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.map = newMap;
|
||||
|
||||
if (this.robot.y < this.meta['Water']) {
|
||||
this.moves_below_water++;
|
||||
if (this.moves_below_water > this.meta['Waterproof']) this._drown();
|
||||
} else {
|
||||
this.moves_below_water = 0;
|
||||
}
|
||||
if (this.meta['Flooding'] > 0 && 0 == (this.moves % this.meta['Flooding'])) {
|
||||
this.meta['Water']++;
|
||||
}
|
||||
|
||||
switch (this.state) {
|
||||
case LOST:
|
||||
this.score = 25*this.found_lambdas - this.moves;
|
||||
break;
|
||||
case WON:
|
||||
this.score = 75*this.found_lambdas - this.moves;
|
||||
break;
|
||||
case ALIVE:
|
||||
case ABORTED:
|
||||
this.score = 50*this.found_lambdas - this.moves;
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
Mine.prototype._drown = function() {
|
||||
if (this.state < LOST) {
|
||||
this.state = LOST;
|
||||
this.reason = "Drowned";
|
||||
}
|
||||
};
|
||||
|
||||
Mine.prototype._crushed = function() {
|
||||
if (this.state < LOST) {
|
||||
this.state = LOST;
|
||||
this.reason = "Crushed by rock";
|
||||
}
|
||||
};
|
||||
|
||||
Mine.prototype._foundLift = function() {
|
||||
if (this.state < WON) {
|
||||
this.state = WON;
|
||||
this.reason = "Found lift";
|
||||
}
|
||||
};
|
||||
|
||||
Mine.prototype._abort = function() {
|
||||
if (this.state < ABORTED) {
|
||||
this.state = ABORTED;
|
||||
this.reason = "Aborted";
|
||||
}
|
||||
};
|
||||
|
||||
Mine.prototype.toString = function() {
|
||||
return this.map.map(function(l) { return l.join(''); }).reverse().join("\n");
|
||||
};
|
||||
|
||||
Mine.prototype.metaText = function() {
|
||||
var k, keys = [], lines = [];
|
||||
for (k in this.meta) {
|
||||
if (this.meta.hasOwnProperty(k)) keys.push(k);
|
||||
}
|
||||
keys.sort();
|
||||
for (k = 0; k < keys.length; ++k) {
|
||||
lines[k] = keys[k] + " " + this.meta[keys[k]];
|
||||
}
|
||||
return lines.join("\n");
|
||||
};
|
||||
|
||||
return Mine;
|
||||
}();
|
||||
|
||||
if (typeof exports !== "undefined") {
|
||||
exports.Mine = Mine;
|
||||
}
|
9
js/test.js
Normal file
9
js/test.js
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
var Mine = require('./mine').Mine;
|
||||
var maps = require('./maps').maps;
|
||||
|
||||
console.log(maps);
|
||||
|
||||
var m = new Mine(maps['flood1']);
|
||||
|
||||
console.log(m);
|
Loading…
Reference in New Issue
Block a user