add beard extension
@ -1,5 +1,6 @@
|
||||
|
||||
MAPS=
|
||||
MAPS+=$(wildcard ../maps/beard*.map)
|
||||
MAPS+=$(wildcard ../maps/trampoline*.map)
|
||||
MAPS+=$(wildcard ../maps/flood*.map)
|
||||
MAPS+=$(wildcard ../maps/contest?.map ../maps/contest10.map)
|
||||
@ -12,9 +13,10 @@ maps.js: FORCE
|
||||
./mapsToJson.js $(MAPS) > maps.js.new
|
||||
@if test ! -e maps.js || ! diff maps.js maps.js.new > /dev/null; then echo "new maps"; mv maps.js.new maps.js; else rm maps.js.new; fi
|
||||
|
||||
SPRITES=earth.png empty.png lambda.png liftclosed.png liftopen.png robot.png rock.png wall.png
|
||||
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.png: $(SPRITES)
|
||||
convert -background "#000000" -append $(SPRITES) tmp_sprites.png
|
||||
|
BIN
js/beard.png
Normal file
After Width: | Height: | Size: 109 B |
BIN
js/bricks.png
Normal file
After Width: | Height: | Size: 119 B |
@ -16,7 +16,9 @@ var mineGui_spriteOffset = {
|
||||
'.': 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
|
||||
'1':17,'2':18,'3':19,'4':20,'5':21,'6':22,'7':23,'8':24,'9':25,
|
||||
'W':26,
|
||||
'!':27
|
||||
};
|
||||
|
||||
var mineGui_images = {};
|
||||
@ -39,7 +41,7 @@ function mineGui_start() {
|
||||
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};
|
||||
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() {
|
||||
@ -256,5 +258,6 @@ function mineGui_show() {
|
||||
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;
|
||||
}
|
||||
|
2
js/gui.min.js
vendored
@ -24,7 +24,8 @@
|
||||
<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)
|
||||
found <b style="font:monospace" id="mineGui_scoreLambdas">0</b> Lambdas,
|
||||
have <b style="font:monospace" id="mineGui_razors">0</b> razors)
|
||||
</span>
|
||||
</div>
|
||||
<div>Status: <b style="font:monospace" id="mineGui_state">0</b></div>
|
||||
@ -34,7 +35,7 @@
|
||||
<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.
|
||||
(<b>L</b>)eft/(<b>U</b>)p/(<b>R</b>)ight/(<b>D</b>)own work as expected (letter and arrow keys), (<b>S</b>)have, (<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>T</b>)oggle text mode
|
||||
Be careful: a reload looses all custom maps and saved moves.
|
||||
Listed highscore can be outdated.
|
||||
|
BIN
js/lambda.png
Before Width: | Height: | Size: 592 B After Width: | Height: | Size: 139 B |
BIN
js/lift.png
Normal file
After Width: | Height: | Size: 139 B |
Before Width: | Height: | Size: 603 B |
BIN
js/liftopen.png
Before Width: | Height: | Size: 558 B |
2
js/maps.min.js
vendored
111
js/mine.js
@ -46,12 +46,21 @@ var Mine = function() {
|
||||
this.lift = this.robot = false;
|
||||
this.trampoline = {
|
||||
sources: { }, // x, y and target
|
||||
targets: { }, // x, y and sources
|
||||
targets: { } // x, y and sources
|
||||
};
|
||||
this.trampoline.targets = {};
|
||||
this.beard = {
|
||||
growth: 25,
|
||||
razors: 0
|
||||
};
|
||||
map.splice(height, 0, repeat('#', width));
|
||||
map.splice(0, 0, repeat('#', width), repeat('#', width));
|
||||
height = height + 3;
|
||||
width = width + 2;
|
||||
for (i = 0; i < height; ++i) {
|
||||
// padding
|
||||
if (map[i].length < width) map[i] += repeat(' ', width - map[i].length);
|
||||
if (map[i].length < width-2) map[i] += repeat(' ', width - map[i].length - 2);
|
||||
// extra # padding:
|
||||
map[i] = '#' + map[i] + '#';
|
||||
line = map[i] = map[i].split('');
|
||||
|
||||
// scan
|
||||
@ -61,6 +70,8 @@ var Mine = function() {
|
||||
case '*':
|
||||
case '#':
|
||||
case '.':
|
||||
case 'W':
|
||||
case '!':
|
||||
break;
|
||||
case '\\':
|
||||
this.lambdas++;
|
||||
@ -82,7 +93,7 @@ var Mine = function() {
|
||||
if (this.trampoline.targets[line[x]]) throw "Can have only one trampoline target " + line[x];
|
||||
this.trampoline.targets[line[x]] = { x: x, y: i, sources: [] };
|
||||
} else {
|
||||
throw "Invalid character in map: '" + line[x] + "'";
|
||||
throw "Invalid character in map: '" + line[x] + "'" + x;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -99,13 +110,13 @@ var Mine = function() {
|
||||
var words = lines[i].split(/ +/);
|
||||
switch (words[0]) {
|
||||
case 'Water':
|
||||
this.water.level = words[1];
|
||||
this.water.level = parseInt(words[1]);
|
||||
break;
|
||||
case 'Flooding':
|
||||
this.water.flooding = words[1];
|
||||
this.water.flooding = parseInt(words[1]);
|
||||
break;
|
||||
case 'Waterproof':
|
||||
this.water.proof = words[1];
|
||||
this.water.proof = parseInt(words[1]);
|
||||
break;
|
||||
case 'Trampoline':
|
||||
if (words.length !== 4 || words[2] !== 'targets')
|
||||
@ -120,6 +131,12 @@ var Mine = function() {
|
||||
this.trampoline.sources[words[1]].target = words[3];
|
||||
this.trampoline.targets[words[3]].sources.push(words[1]);
|
||||
break;
|
||||
case 'Growth':
|
||||
this.beard.growth = parseInt(words[1]);
|
||||
break;
|
||||
case 'Razors':
|
||||
this.beard.razors = parseInt(words[1]);
|
||||
break;
|
||||
default:
|
||||
this.meta[words[0]] = words.splice(1).join(" ");
|
||||
break;
|
||||
@ -136,6 +153,8 @@ var Mine = function() {
|
||||
}
|
||||
}
|
||||
this.water_level = this.water.level;
|
||||
this.razors = this.beard.razors;
|
||||
this.beard_growth = this.beard.growth;
|
||||
this.state = ALIVE;
|
||||
};
|
||||
|
||||
@ -152,19 +171,16 @@ var Mine = function() {
|
||||
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;
|
||||
c = this.map[this.robot.y][this.robot.x+n];
|
||||
switch (c) {
|
||||
case '#': return false;
|
||||
case ' ':
|
||||
case '.':
|
||||
case '!':
|
||||
case '\\': return true;
|
||||
case 'L': return false;
|
||||
case 'O': return true;
|
||||
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;
|
||||
default:
|
||||
if (this.trampoline.sources.hasOwnProperty(c)) return true;
|
||||
@ -174,13 +190,12 @@ var Mine = function() {
|
||||
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;
|
||||
c = this.map[this.robot.y+n][this.robot.x];
|
||||
switch (c) {
|
||||
case '#': return false;
|
||||
case ' ':
|
||||
case '.':
|
||||
case '!':
|
||||
case '\\': return true;
|
||||
case 'L': return false;
|
||||
case 'O': return true;
|
||||
@ -191,6 +206,8 @@ var Mine = function() {
|
||||
}
|
||||
break;
|
||||
case 'W':
|
||||
case 'S':
|
||||
return this.razors > 0;
|
||||
case 'A':
|
||||
return true;
|
||||
}
|
||||
@ -200,22 +217,26 @@ var Mine = function() {
|
||||
Mine.prototype.move = function(command) {
|
||||
if (this.state != ALIVE) return false;
|
||||
var n, c, s, t;
|
||||
var newMap, x, y, i, j, below, map = this.map, growBeard;
|
||||
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] = ' ';
|
||||
c = this.map[this.robot.y][this.robot.x+n];
|
||||
map[this.robot.y][this.robot.x] = ' ';
|
||||
c = map[this.robot.y][this.robot.x+n];
|
||||
switch (c) {
|
||||
case '*':
|
||||
this.map[this.robot.y][this.robot.x+2*n] = '*';
|
||||
map[this.robot.y][this.robot.x+2*n] = '*';
|
||||
break;
|
||||
case '\\':
|
||||
this.lambdas--;
|
||||
this.found_lambdas++;
|
||||
break;
|
||||
case '!':
|
||||
this.razors++;
|
||||
break;
|
||||
case 'O':
|
||||
this._foundLift();
|
||||
break;
|
||||
@ -225,7 +246,7 @@ var Mine = function() {
|
||||
t = this.trampoline.targets[s.target];
|
||||
for (n = 0; n < t.sources.length; ++n) {
|
||||
s = this.trampoline.sources[t.sources[n]];
|
||||
this.map[s.y][s.x] = ' ';
|
||||
map[s.y][s.x] = ' ';
|
||||
}
|
||||
this.robot.x = t.x;
|
||||
this.robot.y = t.y;
|
||||
@ -233,18 +254,21 @@ var Mine = function() {
|
||||
}
|
||||
}
|
||||
this.robot.x += n;
|
||||
this.map[this.robot.y][this.robot.x] = 'R';
|
||||
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] = ' ';
|
||||
c = this.map[this.robot.y+n][this.robot.x];
|
||||
map[this.robot.y][this.robot.x] = ' ';
|
||||
c = map[this.robot.y+n][this.robot.x];
|
||||
switch (c) {
|
||||
case '\\':
|
||||
this.lambdas--;
|
||||
this.found_lambdas++;
|
||||
break;
|
||||
case '!':
|
||||
this.razors++;
|
||||
break;
|
||||
case 'O':
|
||||
this._foundLift();
|
||||
break;
|
||||
@ -254,7 +278,7 @@ var Mine = function() {
|
||||
t = this.trampoline.targets[s.target];
|
||||
for (n = 0; n < t.sources.length; ++n) {
|
||||
s = this.trampoline.sources[t.sources[n]];
|
||||
this.map[s.y][s.x] = ' ';
|
||||
map[s.y][s.x] = ' ';
|
||||
}
|
||||
this.robot.x = t.x;
|
||||
this.robot.y = t.y;
|
||||
@ -262,7 +286,13 @@ var Mine = function() {
|
||||
}
|
||||
}
|
||||
this.robot.y += n;
|
||||
this.map[this.robot.y][this.robot.x] = 'R';
|
||||
map[this.robot.y][this.robot.x] = 'R';
|
||||
break;
|
||||
case 'S':
|
||||
--this.razors;
|
||||
for (var i = -1; i <= 1; ++i) for (var j = -1; j <= 1; ++j) {
|
||||
if ('W' == map[this.robot.y+i][this.robot.x+j]) map[this.robot.y+i][this.robot.x+j] = ' ';
|
||||
}
|
||||
break;
|
||||
case 'A':
|
||||
this._abort();
|
||||
@ -276,35 +306,44 @@ var Mine = function() {
|
||||
}
|
||||
}
|
||||
|
||||
var newMap = [], x, y, below;
|
||||
for (y = 0; y < this.height; ++y) { newMap[y] = this.map[y].slice(); }
|
||||
newMap = [];
|
||||
growBeard = false;
|
||||
if (0 > --this.beard_growth) {
|
||||
this.beard_growth = this.beard.growth;
|
||||
growBeard = true;
|
||||
}
|
||||
for (y = 0; y < map.length; ++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);
|
||||
for (y = 2; y < 2+this.height; ++y) {
|
||||
for (x = 1; x <= this.width; ++x) {
|
||||
if ('*' == map[y][x]) {
|
||||
below = map[y-1][x];
|
||||
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]) {
|
||||
if ('R' == map[y-2][x]) this._crushed();
|
||||
} else if ((below == '*' || below == '\\') && ' ' == map[y-1][x+1] && ' ' == 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]) {
|
||||
if ('R' == map[y-2][x+1]) this._crushed();
|
||||
} else if ((below == '*') && ' ' == map[y-1][x-y] && ' ' == map[y][x-1]) {
|
||||
// fall left
|
||||
newMap[y-1][x-1] = '*';
|
||||
newMap[y][x] = ' ';
|
||||
if ('R' == this.get(x-1, y-2)) this._crushed();
|
||||
if ('R' == map[y-2][x-1]) this._crushed();
|
||||
}
|
||||
} else if (growBeard && 'W' == map[y][x]) {
|
||||
for (i = -1; i <= 1; ++i) for (j = -1; j <= 1; ++j) {
|
||||
if (' ' == map[y+i][x+j]) newMap[y+i][x+j] = 'W';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.map = newMap;
|
||||
|
||||
if (this.robot.y < this.water_level) {
|
||||
if (this.robot.y < this.water_level + 2) {
|
||||
this.moves_below_water++;
|
||||
if (this.moves_below_water > this.water.proof) this._drown();
|
||||
} else {
|
||||
@ -357,7 +396,7 @@ var Mine = function() {
|
||||
};
|
||||
|
||||
Mine.prototype.toString = function() {
|
||||
return this.map.map(function(l) { return l.join(''); }).reverse().join("\n");
|
||||
return this.map.slice(2,-1).map(function(l) { return l.slice(1,-1).join(''); }).reverse().join("\n");
|
||||
};
|
||||
|
||||
Mine.prototype.metaText = function() {
|
||||
@ -372,6 +411,8 @@ var Mine = function() {
|
||||
for (k = 0; k < keys.length; ++k) {
|
||||
lines.push("Trampoline " + keys[k] + " targets " + this.trampoline.sources[keys[k]].target);
|
||||
}
|
||||
if (this.beard.growth != 25) lines.push("Growth " + this.beard.growth);
|
||||
if (this.beard.razors != 0) lines.push("Razors " + this.beard.razors);
|
||||
|
||||
keys = [];
|
||||
for (k in this.meta) {
|
||||
|
2
js/mine.min.js
vendored
BIN
js/miner.png
Normal file
After Width: | Height: | Size: 180 B |
BIN
js/openlift.png
Normal file
After Width: | Height: | Size: 139 B |
BIN
js/razor.png
Normal file
After Width: | Height: | Size: 128 B |
BIN
js/rock.png
Before Width: | Height: | Size: 741 B After Width: | Height: | Size: 170 B |
BIN
js/sprites.png
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 808 B |
BIN
js/target.png
Before Width: | Height: | Size: 675 B After Width: | Height: | Size: 170 B |
BIN
js/target1.png
Before Width: | Height: | Size: 663 B After Width: | Height: | Size: 181 B |
BIN
js/target2.png
Before Width: | Height: | Size: 650 B After Width: | Height: | Size: 180 B |
BIN
js/target3.png
Before Width: | Height: | Size: 651 B After Width: | Height: | Size: 188 B |
BIN
js/target4.png
Before Width: | Height: | Size: 664 B After Width: | Height: | Size: 186 B |
BIN
js/target5.png
Before Width: | Height: | Size: 639 B After Width: | Height: | Size: 181 B |
BIN
js/target6.png
Before Width: | Height: | Size: 659 B After Width: | Height: | Size: 186 B |
BIN
js/target7.png
Before Width: | Height: | Size: 658 B After Width: | Height: | Size: 183 B |
BIN
js/target8.png
Before Width: | Height: | Size: 654 B After Width: | Height: | Size: 193 B |
BIN
js/target9.png
Before Width: | Height: | Size: 653 B After Width: | Height: | Size: 181 B |
Before Width: | Height: | Size: 609 B After Width: | Height: | Size: 148 B |
Before Width: | Height: | Size: 610 B After Width: | Height: | Size: 156 B |
Before Width: | Height: | Size: 600 B After Width: | Height: | Size: 153 B |
Before Width: | Height: | Size: 599 B After Width: | Height: | Size: 148 B |
Before Width: | Height: | Size: 600 B After Width: | Height: | Size: 148 B |
Before Width: | Height: | Size: 597 B After Width: | Height: | Size: 153 B |
Before Width: | Height: | Size: 604 B After Width: | Height: | Size: 156 B |
Before Width: | Height: | Size: 598 B After Width: | Height: | Size: 152 B |
Before Width: | Height: | Size: 600 B After Width: | Height: | Size: 153 B |
Before Width: | Height: | Size: 599 B After Width: | Height: | Size: 148 B |
13
maps/beard1.map
Normal file
@ -0,0 +1,13 @@
|
||||
##########
|
||||
#** \\\\#
|
||||
#.R.. #
|
||||
# \ ..*\#
|
||||
#! ..*!#
|
||||
#### # #
|
||||
#\\... # L
|
||||
#\\.W... #
|
||||
#\\. #
|
||||
##########
|
||||
|
||||
Growth 15
|
||||
Razors 0
|
19
maps/beard2.map
Normal file
@ -0,0 +1,19 @@
|
||||
##############################
|
||||
#R...........................#
|
||||
#.........................W..#
|
||||
#..\\\\\\\\\\\\\\\\\\\\\\\\..#
|
||||
#............................#
|
||||
#..*****.*\...*...*...*****..#
|
||||
#..*\....*\....*\*..*.\\*\\..#
|
||||
#..*\....****..!*!......*....#
|
||||
#..*\....*\....*\*..*...*....#
|
||||
#..*\....*\...*...*.....*....#
|
||||
#............................#
|
||||
#..\\\\\\\\\\\\\\\\\\\\\\\\..#
|
||||
#................ ..... .....#
|
||||
#................ W....L#
|
||||
##############################
|
||||
|
||||
Growth 25
|
||||
Razors 10
|
||||
Flooding 20
|
16
maps/beard3.map
Normal file
@ -0,0 +1,16 @@
|
||||
################
|
||||
#*****#!! 1 #
|
||||
#..\..# #
|
||||
#########\\\\ # .\\\. #
|
||||
#.............# * #
|
||||
#.. .\\\#..!..#\** #
|
||||
#.. LW\\#W ..##### ####
|
||||
#..R\\\\#.. ..*\*\*W...#
|
||||
#.......A.. ...\.\...\\#
|
||||
#.......... ** #
|
||||
############....\.######
|
||||
#.....!#
|
||||
########
|
||||
|
||||
Growth 10
|
||||
Trampoline A targets 1
|
16
maps/beard4.map
Normal file
@ -0,0 +1,16 @@
|
||||
####################
|
||||
#W\\!#\\\**.\#W\\\W#
|
||||
##*######..###..\\\#
|
||||
#.......\.R ###...\#
|
||||
#####.###.#.......##
|
||||
#.......#.#\####.###
|
||||
#\\##\###\#\\#...#.L
|
||||
#\##\.###.####.#.#.#
|
||||
#\W#####.....###.W.#
|
||||
####\\...\\\...#.#.#
|
||||
#W*######.######.#.#
|
||||
#\\\\\\\\\.........#
|
||||
############\###\###
|
||||
#\\.. *..........\\#
|
||||
#W... #.........##W#
|
||||
####################
|
BIN
specs/beards.pdf
Normal file
BIN
specs/images/beard.bmp
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
specs/images/razor.bmp
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
specs/images/target.bmp
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
specs/images/trampoline.bmp
Normal file
After Width: | Height: | Size: 1.1 KiB |