Last active
August 29, 2015 14:08
-
-
Save phts/45d344fa918bfc722f04 to your computer and use it in GitHub Desktop.
My level solutions in Untrusted: http://alex.nisnevich.com/untrusted/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/***************** | |
* cellBlockA.js * | |
***************** | |
* | |
* Good morning, Dr. Eval. | |
* | |
* It wasn't easy, but I've managed to get your computer down | |
* to you. This system might be unfamiliar, but the underlying | |
* code is still JavaScript. Just like we predicted. | |
* | |
* Now, let's get what we came here for and then get you out of | |
* here. Easy peasy. | |
* | |
* I've given you as much access to their code as I could, but | |
* it's not perfect. The red background indicates lines that | |
* are off-limits from editing. | |
* | |
* The code currently places blocks in a rectangle surrounding | |
* you. All you need to do is make a gap. You don't even need | |
* to do anything extra. In fact, you should be doing less. | |
*/ | |
function startLevel(map) { | |
map.displayChapter('Chapter 1\nBreakout'); | |
map.placePlayer(7, 5); | |
for (y = 3; y <= map.getHeight() - 10; y++) { | |
map.placeObject(5, y, 'block'); | |
} | |
for (x = 5; x <= map.getWidth() - 5; x++) { | |
map.placeObject(x, 3, 'block'); | |
map.placeObject(x, map.getHeight() - 10, 'block'); | |
} | |
map.placeObject(15, 12, 'computer'); | |
map.placeObject(map.getWidth()-7, map.getHeight()-5, 'exit'); | |
} | |
function onExit(map) { | |
if (!map.getPlayer().hasItem('computer')) { | |
map.writeStatus("Don't forget to pick up the computer!"); | |
return false; | |
} else { | |
return true; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/************* | |
* ambush.js * | |
************* | |
* | |
* Oh. Oh, I see. This wasn't quite part of the plan. | |
* | |
* Looks like they won't let you take the Algorithm | |
* without a fight. You'll need to carefully weave your | |
* way through the guard drones. | |
* | |
* Well, time to improvise. Let's mess with their programming | |
* a little, shall we? | |
*/ | |
function startLevel(map) { | |
function moveToward(obj, type) { | |
var target = obj.findNearest(type); | |
var leftDist = obj.getX() - target.x; | |
var upDist = obj.getY() - target.y; | |
var direction; | |
if (upDist == 0 && leftDist == 0) { | |
return; | |
} if (upDist > 0 && upDist >= leftDist) { | |
direction = 'up'; | |
} else if (upDist < 0 && upDist < leftDist) { | |
direction = 'down'; | |
} else if (leftDist > 0 && leftDist >= upDist) { | |
direction = 'left'; | |
} else { | |
direction = 'right'; | |
} | |
if (obj.canMove(direction)) { | |
obj.move(direction); | |
} | |
} | |
map.defineObject('attackDrone', { | |
'type': 'dynamic', | |
'symbol': 'd', | |
'color': 'red', | |
'onCollision': function (player) { | |
player.killedBy('an attack drone'); | |
}, | |
'behavior': function (me) { | |
var dir = "up" | |
if (Math.random() > 0.4) { | |
dir = "left"; | |
} | |
me.move(dir); | |
} | |
}); | |
map.defineObject('reinforcementDrone', { | |
'type': 'dynamic', | |
'symbol': 'd', | |
'color': 'yellow', | |
'onCollision': function (player) { | |
player.killedBy('a reinforcement drone'); | |
}, | |
'behavior': function (me) { | |
var dir = "up" | |
if (Math.random() > 0.4) { | |
dir = "left"; | |
} | |
me.move(dir); | |
} | |
}); | |
map.defineObject('defenseDrone', { | |
'type': 'dynamic', | |
'symbol': 'd', | |
'color': 'green', | |
'onCollision': function (player) { | |
player.killedBy('a defense drone'); | |
}, | |
'behavior': function (me) { | |
var dir = "up" | |
if (Math.random() > 0.4) { | |
dir = "left"; | |
} | |
me.move(dir); | |
} | |
}); | |
// just for decoration | |
map.defineObject('water', { | |
'symbol': '░', | |
'color': '#44f' | |
}); | |
map.placePlayer(0, 12); | |
for (var x = 0; x < map.getWidth(); x++) { | |
map.placeObject(x, 10, 'block'); | |
map.placeObject(x, 14, 'block'); | |
for (var y = 20; y < map.getHeight(); y++) { | |
map.placeObject(x, y, 'water'); | |
} | |
} | |
map.placeObject(23, 11, 'attackDrone'); | |
map.placeObject(23, 12, 'attackDrone'); | |
map.placeObject(23, 13, 'attackDrone'); | |
map.placeObject(27, 11, 'defenseDrone'); | |
map.placeObject(27, 12, 'defenseDrone'); | |
map.placeObject(27, 13, 'defenseDrone'); | |
map.placeObject(24, 11, 'reinforcementDrone'); | |
map.placeObject(25, 11, 'reinforcementDrone'); | |
map.placeObject(26, 11, 'reinforcementDrone'); | |
map.placeObject(24, 13, 'reinforcementDrone'); | |
map.placeObject(25, 13, 'reinforcementDrone'); | |
map.placeObject(26, 13, 'reinforcementDrone'); | |
map.placeObject(map.getWidth()-1, 12, 'exit'); | |
} | |
function validateLevel(map) { | |
map.validateExactlyXManyObjects(1, 'exit'); | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* robot.js | |
* | |
* You'll need three keys in order to unlock the | |
* Algorithm: the red key, the green key, and the | |
* blue key. Unfortunately, all three of them are | |
* behind human-proof barriers. | |
* | |
* The plan is simple: reprogram the maintenance | |
* robots to grab the key and bring it through | |
* the barrier to us. | |
* | |
* Let's try it on the red key first. | |
*/ | |
function getRandomInt(min, max) { | |
return Math.floor(Math.random() * (max - min + 1)) + min; | |
} | |
function startLevel(map) { | |
// Hint: you can press R or 5 to "rest" and not move the | |
// player, while the robot moves around. | |
map.placePlayer(map.getWidth()-2, map.getHeight()-2); | |
var player = map.getPlayer(); | |
map.defineObject('robot', { | |
'type': 'dynamic', | |
'symbol': 'R', | |
'color': 'gray', | |
'onCollision': function (player, me) { | |
me.giveItemTo(player, 'redKey'); | |
}, | |
'behavior': function (me) { | |
// Available commands: me.move(direction) | |
// and me.canMove(direction) | |
if (me.canMove("right")) { | |
me.move("right"); | |
} else { | |
me.move("down"); | |
} | |
} | |
}); | |
map.defineObject('barrier', { | |
'symbol': '░', | |
'color': 'purple', | |
'impassable': true, | |
'passableFor': ['robot'] | |
}); | |
map.placeObject(0, map.getHeight() - 1, 'exit'); | |
map.placeObject(1, 1, 'robot'); | |
map.placeObject(map.getWidth() - 2, 8, 'redKey'); | |
map.placeObject(map.getWidth() - 2, 9, 'barrier'); | |
for (var x = 0; x < map.getWidth(); x++) { | |
map.placeObject(x, 0, 'block'); | |
if (x != map.getWidth() - 2) { | |
map.placeObject(x, 9, 'block'); | |
} | |
} | |
for (var y = 1; y < 9; y++) { | |
map.placeObject(0, y, 'block'); | |
map.placeObject(map.getWidth() - 1, y, 'block'); | |
} | |
} | |
function validateLevel(map) { | |
map.validateExactlyXManyObjects(1, 'exit'); | |
map.validateExactlyXManyObjects(1, 'robot'); | |
map.validateAtMostXObjects(1, 'redKey'); | |
} | |
function onExit(map) { | |
if (!map.getPlayer().hasItem('redKey')) { | |
map.writeStatus("We need to get that key!"); | |
return false; | |
} else { | |
return true; | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* robotNav.js | |
* | |
* The green key is located in a slightly more | |
* complicated room. You'll need to get the robot | |
* past these obstacles. | |
*/ | |
function startLevel(map) { | |
// Hint: you can press R or 5 to "rest" and not move the | |
// player, while the robot moves around. | |
map.placePlayer(0, map.getHeight() - 1); | |
var player = map.getPlayer(); | |
map.defineObject('robot', { | |
'type': 'dynamic', | |
'symbol': 'R', | |
'color': 'gray', | |
'onCollision': function (player, me) { | |
me.giveItemTo(player, 'greenKey'); | |
}, | |
'behavior': function (me) { | |
if (me.getX() < 15 && me.getY() == 1) { | |
me.move("right"); | |
return; | |
} | |
if (me.getX() == 15 && me.canMove("down")) { | |
me.move("down"); | |
return; | |
} | |
if (me.getX() >= 15 && me.getX() < 25) { | |
me.move("right"); | |
return; | |
} | |
if (me.getX() == 25 && me.canMove("up")) { | |
me.move("up"); | |
return; | |
} | |
if (me.canMove("right")) { | |
me.move("right"); | |
return; | |
} | |
if (me.canMove("down")) { | |
me.move("down"); | |
return; | |
} | |
//if (me.canMove('right')) { | |
// me.move('right'); | |
//} else if (me.canMove('down')) { | |
// me.move('down'); | |
//} else if (me.canMove('left')) { | |
// me.move('left'); | |
//} else if (me.canMove('up')) { | |
// me.move('up'); | |
//} | |
} | |
}); | |
map.defineObject('barrier', { | |
'symbol': '░', | |
'color': 'purple', | |
'impassable': true, | |
'passableFor': ['robot'] | |
}); | |
map.placeObject(map.getWidth() - 1, map.getHeight() - 1, 'exit'); | |
map.placeObject(1, 1, 'robot'); | |
map.placeObject(map.getWidth() - 2, 8, 'greenKey'); | |
map.placeObject(map.getWidth() - 2, 9, 'barrier'); | |
for (var x = 0; x < map.getWidth(); x++) { | |
map.placeObject(x, 0, 'block'); | |
if (x != map.getWidth() - 2) { | |
map.placeObject(x, 9, 'block'); | |
} | |
} | |
for (var y = 1; y < 9; y++) { | |
map.placeObject(0, y, 'block'); | |
map.placeObject(map.getWidth() - 1, y, 'block'); | |
} | |
for (var i = 0; i < 4; i++) { | |
map.placeObject(20 - i, i + 1, 'block'); | |
map.placeObject(35 - i, 8 - i, 'block'); | |
} | |
} | |
function validateLevel(map) { | |
map.validateExactlyXManyObjects(1, 'exit'); | |
map.validateExactlyXManyObjects(1, 'robot'); | |
map.validateAtMostXObjects(1, 'greenKey'); | |
} | |
function onExit(map) { | |
if (!map.getPlayer().hasItem('greenKey')) { | |
map.writeStatus("We need to get that key!"); | |
return false; | |
} else { | |
return true; | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* robotMaze.js | |
* | |
* The blue key is inside a labyrinth, and extracting | |
* it will not be easy. | |
* | |
* It's a good thing that you're a AI expert, or | |
* we would have to leave empty-handed. | |
*/ | |
function startLevel(map) { | |
// Hint: you can press R or 5 to "rest" and not move the | |
// player, while the robot moves around. | |
map.getRandomInt = function(min, max) { | |
return Math.floor(Math.random() * (max - min + 1)) + min; | |
} | |
map.placePlayer(map.getWidth()-1, map.getHeight()-1); | |
var player = map.getPlayer(); | |
map.defineObject('robot', { | |
'type': 'dynamic', | |
'symbol': 'R', | |
'color': 'gray', | |
'onCollision': function (player, me) { | |
me.giveItemTo(player, 'blueKey'); | |
}, | |
'behavior': function (me) { | |
var getObjectTypeRelativeTo = function(direction) { | |
var x = me.getX(); | |
var y = me.getY(); | |
switch (direction) { | |
case "left": x -= 1; break; | |
case "right": x += 1; break; | |
case "up": y -= 1; break; | |
case "down": y += 1; break; | |
} | |
return map.getObjectTypeAt(x, y); | |
} | |
var isEmpty = function(direction) { | |
// direction == "left", "down", ... | |
if (getObjectTypeRelativeTo(direction) == "blueKey") { | |
return true; | |
} | |
if (getObjectTypeRelativeTo(direction) == "barrier") { | |
return true; | |
} | |
var cells = map.getAdjacentEmptyCells(me.getX(), me.getY()); | |
for (var i = 0; i < cells.length; i++) { | |
var cell = cells[i]; | |
if (cell[1] == direction) return true; | |
} | |
return false; | |
} | |
var DIRS = {0: "left", 1: "down", 2: "right", 3: "up"}; | |
var lookingAt = function() { | |
return (me.dir + 1) % 4; | |
} | |
var turn = function() { | |
if (me.dir == 0) { | |
me.dir = 3; | |
return; | |
} | |
me.dir -= 1; | |
} | |
if (me.dir == null) me.dir = 2; | |
if (isEmpty(DIRS[lookingAt()])) { | |
me.dir = lookingAt(); | |
me.move(DIRS[me.dir]); | |
return; | |
} | |
while (!isEmpty(DIRS[me.dir])) { | |
turn(); | |
} | |
me.move(DIRS[me.dir]); | |
} | |
}); | |
map.defineObject('barrier', { | |
'symbol': 'вЦС', | |
'color': 'purple', | |
'impassable': true, | |
'passableFor': ['robot'] | |
}); | |
map.placeObject(0, map.getHeight() - 1, 'exit'); | |
map.placeObject(1, 1, 'robot'); | |
map.placeObject(map.getWidth() - 2, 8, 'blueKey'); | |
map.placeObject(map.getWidth() - 2, 9, 'barrier'); | |
var autoGeneratedMaze = new ROT.Map.DividedMaze(map.getWidth(), 10); | |
autoGeneratedMaze.create( function (x, y, mapValue) { | |
// don't write maze over robot or barrier | |
if ((x == 1 && y == 1) || (x == map.getWidth() - 2 && y >= 8)) { | |
return 0; | |
} else if (mapValue === 1) { //0 is empty space 1 is wall | |
map.placeObject(x,y, 'block'); | |
} else { | |
map.placeObject(x,y,'empty'); | |
} | |
}); | |
} | |
function validateLevel(map) { | |
map.validateExactlyXManyObjects(1, 'exit'); | |
map.validateExactlyXManyObjects(1, 'robot'); | |
map.validateAtMostXObjects(1, 'blueKey'); | |
} | |
function onExit(map) { | |
if (!map.getPlayer().hasItem('blueKey')) { | |
map.writeStatus("We need to get that key!"); | |
return false; | |
} else { | |
return true; | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******************** | |
* crispsContest.js * | |
******************** | |
* | |
* The Algorithm is almost in our grasp! | |
* At long last, we will definitively establish | |
* that 3SAT is solvable in polynomial time. It's | |
* been a long, strange journey, but it will all be | |
* worth it. | |
* | |
* You have the red, green, and blue keys. Now you | |
* just need to figure out how to unlock this thing. | |
*/ | |
function startLevel(map) { | |
map.defineObject('redLock', { | |
'symbol': String.fromCharCode(0x2297), | |
'color': 'red', | |
'impassable': function (player) { | |
if (player.hasItem('redKey')) { | |
player.removeItem('redKey'); | |
return false; | |
} else { | |
return true; | |
} | |
} | |
}); | |
map.defineObject('blueLock', { | |
'symbol': String.fromCharCode(0x2297), | |
'color': '#06f', | |
'impassable': function (player) { | |
if (player.hasItem('blueKey')) { | |
player.removeItem('blueKey'); | |
return false; | |
} else { | |
return true; | |
} | |
} | |
}); | |
map.defineObject('greenLock', { | |
'symbol': String.fromCharCode(0x2297), | |
'color': '#0f0', | |
'impassable': function (player) { | |
if (player.hasItem('greenKey')) { | |
player.removeItem('theAlgorithm'); | |
return false; | |
} else { | |
return true; | |
} | |
} | |
}); | |
map.defineObject('yellowLock', { | |
'symbol': String.fromCharCode(0x2297), | |
'color': 'yellow', | |
'impassable': function (player) { | |
if (player.hasItem('yellowKey')) { | |
player.removeItem('yellowKey'); | |
return false; | |
} else { | |
return true; | |
} | |
} | |
}); | |
map.createFromGrid( | |
[' +++++ +++++ ', | |
' + b +++ r + ', | |
' + +E+ + ', | |
'+++G+B+ +R+G+++', | |
'+ y B R b +', | |
'+ + + +', | |
'+++++ @ +++++', | |
'+ + + +', | |
'+ y R B y +', | |
'++++++Y+Y++++++', | |
' + + + ', | |
' + ABy + ', | |
' +++++++ '], | |
{ | |
'@': 'player', | |
'E': 'exit', | |
'A': 'theAlgorithm', | |
'+': 'block', | |
'R': 'redLock', | |
'G': 'greenLock', | |
'B': 'blueLock', | |
'Y': 'yellowLock', | |
'r': 'redKey', | |
'g': 'greenKey', | |
'b': 'blueKey', | |
'y': 'yellowKey' | |
}, 17, 6); | |
} | |
function validateLevel(map) { | |
map.validateExactlyXManyObjects(1, 'exit'); | |
map.validateAtMostXObjects(1, 'theAlgorithm'); | |
map.validateAtMostXObjects(4, 'yellowKey'); | |
map.validateAtMostXObjects(2, 'blueKey'); | |
map.validateAtMostXObjects(1, 'redKey'); | |
} | |
function onExit(map) { | |
// make sure we have all the items we need! | |
if (!map.getPlayer().hasItem('theAlgorithm')) { | |
map.writeStatus("You must get that Algorithm!!"); | |
return false; | |
} else if (!map.getPlayer().hasItem('computer')) { | |
map.writeStatus("You'll need your computer! [Ctrl-5 to restart]"); | |
return false; | |
} else if (!map.getPlayer().hasItem('phone')) { | |
map.writeStatus("You'll need your phone! [Ctrl-5 to restart]"); | |
return false; | |
} else { | |
return true; | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/************************** | |
* exceptionalCrossing.js * | |
************************** | |
* | |
* Sorry, old friend, but I'm afraid I can't share | |
* co-authorship on this paper. You've done a very | |
* good job getting this Algorithm for me. The bit | |
* with the keys was especially clever! I wouldn't | |
* have thought of it myself. But then, of course, | |
* that's why you were here in the first place. | |
* | |
* You've served your purpose well. But now, alas, | |
* it is time for you to die. | |
* | |
* I'm not heartless, though. In fact, I will let | |
* you choose your mode of death. There, isn't that | |
* nice? | |
*/ | |
function startLevel(map) { | |
map.displayChapter('Chapter 3\nBetrayal'); | |
map.placePlayer(0, 0); | |
// yoink! | |
map.getPlayer().removeItem('theAlgorithm'); | |
map.defineObject('water', { | |
'symbol': '░', | |
'color': '#44f', | |
'onCollision': function (player) { | |
player.killedBy(map.placePlayer(0, 0)); | |
} | |
}); | |
for (var x = 0; x < map.getWidth(); x++) | |
for (var y = 5; y < 15; y++) | |
map.placeObject(x, y, 'water'); | |
map.placeObject(map.getWidth()-1, map.getHeight()-1, 'exit'); | |
} | |
function validateLevel(map) { | |
map.validateExactlyXManyObjects(1, 'exit'); | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/************* | |
* lasers.js * | |
************* | |
* | |
* Time to unleash the killer lasers! Each laser will kill you | |
* unless you have the appropriate color. Too bad you can't | |
* see which color corresponds to which laser! | |
*/ | |
function getRandomInt(min, max) { | |
return Math.floor(Math.random() * (max - min + 1)) + min; | |
} | |
function startLevel(map) { | |
map.placePlayer(0, 0); | |
map.placeObject(map.getWidth()-1, map.getHeight()-1, 'exit'); | |
var player = map.getPlayer(); | |
for (var i = 0; i < 25; i++) { | |
var colors = ['red', 'yellow', 'teal']; | |
var startX = getRandomInt(0, 600); | |
var startY = getRandomInt(0, 500); | |
var angle = getRandomInt(0, 360); | |
var length = getRandomInt(200, 300); | |
var color = colors[i % 3]; | |
createLaser(startX, startY, angle, length, color); | |
} | |
function createLaser(centerX, centerY, angleInDegrees, length, color) { | |
var angleInRadians = angleInDegrees * Math.PI / 180; | |
var x1 = centerX - Math.cos(angleInRadians) * length / 2; | |
var y1 = centerY + Math.sin(angleInRadians) * length / 2; | |
var x2 = centerX + Math.cos(angleInRadians) * length / 2; | |
var y2 = centerY - Math.sin(angleInRadians) * length / 2; | |
// map.createLine() creates a line with an effect when | |
// the player moves over it, but doesn't display it | |
map.createLine([x1, y1], [x2, y2], function (player) { | |
if (player.getColor() != color) { | |
player.killedBy('a ' + color + ' laser'); | |
} | |
}); | |
// using canvas to draw the line | |
var ctx = map.getCanvasContext(); | |
ctx.beginPath(); | |
ctx.strokeStyle = color; | |
ctx.lineWidth = 5; | |
ctx.moveTo(x1, y1); | |
ctx.lineTo(x2, y2); | |
ctx.stroke(); | |
} | |
player.setColor("yellow") | |
} | |
function validateLevel(map) { | |
map.validateExactlyXManyObjects(1, 'exit'); | |
map.validateAtLeastXLines(25); | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*************** | |
* pointers.js * | |
*************** | |
* | |
* You! How are you still alive? | |
* | |
* Well, no matter. Good luck getting through this | |
* maze of rooms - you'll never see me or the Algorithm again! | |
*/ | |
function startLevel(map) { | |
function shuffle(o){ //v1.0 [http://bit.ly/1l6LGQT] | |
for(var j, x, i = o.length; i; j = Math.floor(Math.random() * i), | |
x = o[--i], o[i] = o[j], o[j] = x); | |
return o; | |
}; | |
map.createFromGrid( | |
['+++++++++++++++++++++++++++++++++++++++++++++', | |
'++o *++++o *++++o *++++o *++++o *++++o *+++++', | |
'+* @ o++* o++* o++* o++* o++* o++++', | |
'++o *++++o *++++o *++++o *++++o *++++o *+++++', | |
'+++++++++++++++++++++++++++++++++++++++++++++', | |
'+++++* o++++* o++++* o++++* o++++* o++++* o++', | |
'++++o *++o *++o *++o *++o *++o *+', | |
'+++++* o++++* o++++* o++++* o++++* o++++* o++', | |
'+++++++++++++++++++++++++++++++++++++++++++++', | |
'++o *++++o *++++o *++++o *++++o *++++o *+++++', | |
'+* o++* o++* o++* o++* o++* o++++', | |
'++o *++++o *++++o *++++o *++++o *++++o *+++++', | |
'+++++++++++++++++++++++++++++++++++++++++++++', | |
'+++++* o++++* o++++* o++++* o++++* o++++* o++', | |
'++++o *++o *++o *++o *++o *++o *+', | |
'+++++* o++++* o++++* o++++* o++++* o++++* o++', | |
'+++++++++++++++++++++++++++++++++++++++++++++', | |
'++o *++++o *++++o *++++o *++++o *++++o *+++++', | |
'+* o++* o++* o++* o++* o++* E o++++', | |
'++o *++++o *++++o *++++o *++++o *++++o *+++++', | |
'+++++++++++++++++++++++++++++++++++++++++++++'], | |
{ | |
'@': 'player', | |
'E': 'exit', | |
'+': 'block', | |
'o': 'teleporter', | |
'*': 'trap', | |
}, 2, 2); | |
var canvas = map.getCanvasContext(); | |
var teleportersAndTraps = map.getDynamicObjects(); | |
teleportersAndTraps = shuffle(teleportersAndTraps); | |
for (i = 0; i < teleportersAndTraps.length; i+=2) { | |
var t1 = teleportersAndTraps[i]; | |
var t2 = teleportersAndTraps[i+1]; | |
// Point each teleporter to either another teleporter | |
// or a trap | |
if (t1.getType() == 'teleporter') { | |
t1.setTarget(t2); | |
} | |
if (t2.getType() == 'teleporter') { | |
t2.setTarget(t1); | |
} | |
// TODO find a way to remove the API docs | |
// wouldn't want the 'good doctor' to find | |
// out about map.getCanvasCoords()... | |
t1 = null; | |
for (i = 0; i < teleportersAndTraps.length; i++) { | |
var t = teleportersAndTraps[i]; | |
if (t.getType() != "teleporter") { | |
continue; | |
} | |
if (!t1) { | |
t1 = t; | |
continue; | |
} | |
t1.setTarget(t); | |
canvas.strokeStyle = "#FF00FF"; | |
var xy1 = map.getCanvasCoords(t1); | |
canvas.moveTo(xy1.x, xy1.y); | |
var xy2 = map.getCanvasCoords(t); | |
canvas.lineTo(xy2.x, xy2.y); | |
canvas.stroke(); | |
t1 = t; | |
} | |
} | |
} | |
function validateLevel(map) { | |
map.validateExactlyXManyObjects(1, 'exit'); | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/********************** | |
* superDrEvalBros.js * | |
********************** | |
* | |
* You're still here?! Well, Dr. Eval, let's see | |
* how well you can operate with one less dimension. | |
* | |
* Give up now. Unless you have a magic mushroom | |
* up your sleeve, it's all over. | |
*/ | |
function startLevel(map) { | |
var fl = Math.floor; | |
var w = map.getWidth(); | |
var h = map.getHeight(); | |
map.placePlayer(1, fl(h/2)-1); | |
var player = map.getPlayer(); | |
map.placeObject(w-1, fl(h/2)-1, 'exit'); | |
for (var x = 0; x < fl(w/2) - 5; x++) { | |
for (var y = fl(h/2); y < h; y++) { | |
map.placeObject(x, y, 'block'); | |
} | |
} | |
for (var x = fl(w/2) + 5; x <= w; x++) { | |
for (var y = fl(h/2); y < h; y++) { | |
map.placeObject(x, y, 'block'); | |
} | |
} | |
function gravity() { | |
var x = player.getX(); | |
var y = player.getY() + 1; | |
if (y === map.getHeight() - 2) { | |
player.killedBy("gravity"); | |
} | |
if (map.getObjectTypeAt(x,y) === "empty") { | |
player.move("down"); | |
} | |
} | |
map.startTimer(gravity, 45); | |
function jump() { | |
player.tick = 0; | |
var f = function() { | |
player.tick += 1; | |
if (player.tick < 200 && player.tick % 5 != 0) { | |
player.move("up"); | |
return; | |
} | |
player.move("right") | |
} | |
map.startTimer(f, 25); | |
} | |
player.setPhoneCallback(function () { | |
var x = player.getX(); | |
var y = player.getY() + 1; | |
if (map.getObjectTypeAt(x,y) !== "empty") { | |
jump(); | |
} | |
}); | |
} | |
function validateLevel(map) { | |
map.validateExactlyXManyObjects(1, 'exit'); | |
map.validateExactlyXManyObjects(520, 'block'); | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/**************************** | |
* documentObjectMadness.js * | |
**************************** | |
* | |
* I can't believe it! I can't believe you made it onto | |
* Department of Theoretical Computation's web server! | |
* YOU SHOULD HAVE BEEN DELETED! This shouldn't even be | |
* possible! What the hell were the IT folks thinking? | |
* | |
* No matter. I still have the Algorithm. That's the | |
* important part. The rest is just implementation, and | |
* how hard could that be? | |
* | |
* Anyway you're not going to catch me now, my good Doctor. | |
* After all, you're a tenured professor with a well-respected | |
* history of research - you probably don't know jQuery! | |
*/ | |
function objective(map) { | |
return map.getDOM().find('.adversary').hasClass('drEval'); | |
} | |
function startLevel(map) { | |
var html = "<div class='container'>" + | |
"<div style='width: 600px; height: 500px; background-color: white; font-size: 10px;'>" + | |
"<center><h1>Department of Theoretical Computation</h1></center>" + | |
"<hr />" + | |
"<table border='0'><tr valign='top'>" + | |
"<td><div id='face' /></td>" + | |
"<td>" + | |
"<h2 class=facultyName>Cornelius Eval</h2>" + | |
"<h3>Associate Professor of Computer Science</h3>" + | |
"<ul>" + | |
"<li>BS, Mathematics, University of Manitoba</li>" + | |
"<li>PhD, Theoretical Computation, <a href='http://www.mit.edu'>MIT</a></li>" + | |
"</ul>" + | |
"<h4>About me</h4>" + | |
"<p>I am an associate professor of computer science, attached to the Department of " + | |
"Theoretical Computation. My current research interests include the human-machine " + | |
"interface, NP complete problems, and parallelized mesh mathematics.</p>" + | |
"<p>I am also the current faculty advisor to the <a href=''>undergraduate Super Smash Bros. team</a>. " + | |
"In my spare time I enjoy polka and dirtbiking. </p>" + | |
"</td>" + | |
"</tr></table>" + | |
"<div id='class_schedule'>" + | |
"<h4>Class Schedule</h4>" + | |
"<table>" + | |
"<tr>" + | |
"<th>Monday</th><th>Tuesday</th><th>Wednesday</th><th>Thursday</th><th>Friday</th>" + | |
"</tr>" + | |
"<tr>" + | |
"<td>CS145 - Semicolons</td><td>Nothing Planned</td><td>CS145 - Semicolons</td><td>CS199 - Practical Theorycrafting </td><td>CS145 - Semicolons</td>" + | |
"</tr>" + | |
"</table>" + | |
"</div>" + | |
"<div id='loremIpsum'>" + | |
"<h4>Lorem Ipsum</h4>" + | |
"<blockquote>" + | |
"<code>Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci " + | |
"velit, sed quia nonnumquam eiusmodi tempora incidunt ut labore et dolore magnam aliquam quaerat " + | |
"voluptatem.</code>" + | |
"<footer>— " + | |
"<cite>Cicero, De Finibus Bonorum et Malorum</cite>" + | |
"</footer>" + | |
"</blockquote>" + | |
"</div>" + | |
"</div></div>"; | |
var $dom = $(html); | |
$dom.find('.facultyName').addClass('drEval'); | |
$dom.find('cite').addClass('adversary'); | |
function moveToParent(className) { | |
var currentPosition = $dom.find('.' + className); | |
if (currentPosition.parent().length > 0 && | |
!currentPosition.parent().hasClass('container')) { | |
currentPosition.parent().addClass(className); | |
currentPosition.removeClass(className); | |
map.updateDOM($dom); | |
} | |
} | |
function moveToFirstChild(className) { | |
var currentPosition = $dom.find('.' + className); | |
if (currentPosition.children().length > 0) { | |
currentPosition.children().first().addClass(className); | |
currentPosition.removeClass(className); | |
map.updateDOM($dom); | |
} | |
} | |
function moveToPreviousSibling(className) { | |
var currentPosition = $dom.find('.' + className); | |
if (currentPosition.prev().length > 0) { | |
currentPosition.prev().addClass(className); | |
currentPosition.removeClass(className); | |
map.updateDOM($dom); | |
} | |
} | |
function moveToNextSibling(className) { | |
var currentPosition = $dom.find('.' + className); | |
if (currentPosition.next().length > 0) { | |
currentPosition.next().addClass(className); | |
currentPosition.removeClass(className); | |
map.updateDOM($dom); | |
} | |
} | |
map.overrideKey('up', function () { moveToParent('drEval'); }); | |
map.overrideKey('down', function () { moveToFirstChild('drEval'); }); | |
map.overrideKey('left', function () { moveToPreviousSibling('drEval'); }); | |
map.overrideKey('right', function () { moveToNextSibling('drEval'); }); | |
map.defineObject('adversary', { | |
'type': 'dynamic', | |
'symbol': '@', | |
'color': 'red', | |
'behavior': function (me) { | |
var move = Math.floor(Math.random() * 4) + 1; // 1, 2, 3, or 4 | |
if (move == 1) { | |
moveToParent('adversary'); | |
} else if (move == 2) { | |
moveToFirstChild('adversary'); | |
} else if (move == 3) { | |
moveToPreviousSibling('adversary'); | |
} else if (move == 4) { | |
moveToNextSibling('adversary'); | |
} | |
} | |
}); | |
map.placePlayer(1, 1); | |
map.placeObject(map.getWidth() - 2, map.getHeight() - 2, 'adversary'); | |
map.createFromDOM($dom); | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******************** | |
* theLongWayOut.js * | |
******************** | |
* | |
* Well, it looks like they're on to us. The path isn't as | |
* clear as I thought it'd be. But no matter - four clever | |
* characters should be enough to erase all their tricks. | |
*/ | |
function startLevel(map) { | |
map.placePlayer(7, 5); | |
var maze = new ROT.Map.DividedMaze(map.getWidth(), map.getHeight()); | |
maze = new ROT.Map.DividedMaze(map.getWidth()/2, map.getHeight()/2); | |
maze.create( function (x, y, mapValue) { | |
// don't write maze over player | |
if (map.getPlayer().atLocation(x,y)) { | |
return 0; | |
} | |
else if (mapValue === 1) { //0 is empty space 1 is wall | |
map.placeObject(x,y, 'block'); | |
} | |
else { | |
map.placeObject(x,y,'empty'); | |
} | |
}); | |
map.placeObject(map.getWidth()-4, map.getHeight()-4, 'block'); | |
map.placeObject(map.getWidth()-6, map.getHeight()-4, 'block'); | |
map.placeObject(map.getWidth()-5, map.getHeight()-5, 'block'); | |
map.placeObject(map.getWidth()-5, map.getHeight()-3, 'block'); | |
map.placeObject(map.getWidth()-2, map.getHeight()-4, 'exit'); | |
map.placeObject(map.getWidth()-5, map.getHeight()-4, 'exit'); | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/***************** | |
* bossFight.js * | |
***************** | |
* | |
* NO FARTHER, DR. EVAL!!!! | |
* YOU WILL NOT GET OUT OF HERE ALIVE!!!! | |
* IT'S TIME YOU SEE MY TRUE FORM!!!! | |
* FACE MY ROBOT WRATH!!!!! | |
*/ | |
function startLevel(map) { | |
map.defineObject('boss', { | |
'type': 'dynamic', | |
'symbol': '⊙', | |
'color': 'red', | |
'interval': 200, | |
'onCollision': function (player) { | |
player.killedBy('the boss'); | |
}, | |
'behavior': function (me) { | |
if (!me.direction) { | |
me.direction = 'right'; | |
} | |
if (me.canMove(me.direction)) { | |
me.move(me.direction); | |
} else { | |
me.direction = (me.direction == 'right') ? 'left' : 'right'; | |
} | |
if (Math.random() < 0.3) { | |
map.placeObject(me.getX(), me.getY() + 2, 'bullet'); | |
} | |
}, | |
'onDestroy': function (me) { | |
if (map.countObjects('boss') == 0) { | |
map.placeObject(me.getX(), me.getY(), 'theAlgorithm'); | |
} | |
} | |
}); | |
map.defineObject('bullet', { | |
'type': 'dynamic', | |
'symbol': '.', | |
'color': 'red', | |
'interval': 100, | |
'projectile': true, | |
'behavior': function (me) { | |
me.move('down'); | |
} | |
}); | |
map.placePlayer(0, map.getHeight() - 3); | |
map.placeObject(map.getWidth() - 1, map.getHeight() - 1, 'exit'); | |
// Not so tough now, huh? | |
map.getPlayer().removeItem('phone'); | |
map.placeObject(map.getWidth() - 1, map.getHeight() - 3, 'phone'); | |
map.placeObject(0, map.getHeight() - 4, 'block'); | |
map.placeObject(1, map.getHeight() - 4, 'block'); | |
map.placeObject(2, map.getHeight() - 4, 'block'); | |
map.placeObject(2, map.getHeight() - 3, 'block'); | |
map.placeObject(map.getWidth() - 1, map.getHeight() - 4, 'block'); | |
map.placeObject(map.getWidth() - 2, map.getHeight() - 4, 'block'); | |
map.placeObject(map.getWidth() - 3, map.getHeight() - 4, 'block'); | |
map.placeObject(map.getWidth() - 3, map.getHeight() - 3, 'block'); | |
for (var x = 0; x < map.getWidth(); x++) { | |
map.placeObject(x, 4, 'block'); | |
} | |
map.placeObject(9, 5, 'boss'); | |
map.placeObject(11, 5, 'boss'); | |
map.placeObject(13, 5, 'boss'); | |
map.placeObject(15, 5, 'boss'); | |
map.placeObject(17, 5, 'boss'); | |
map.placeObject(19, 5, 'boss'); | |
map.placeObject(21, 5, 'boss'); | |
map.placeObject(23, 5, 'boss'); | |
map.placeObject(25, 5, 'boss'); | |
map.placeObject(27, 5, 'boss'); | |
map.placeObject(29, 5, 'boss'); | |
map.placeObject(31, 5, 'boss'); | |
map.placeObject(10, 6, 'boss'); | |
map.placeObject(12, 6, 'boss'); | |
map.placeObject(14, 6, 'boss'); | |
map.placeObject(16, 6, 'boss'); | |
map.placeObject(18, 6, 'boss'); | |
map.placeObject(20, 6, 'boss'); | |
map.placeObject(22, 6, 'boss'); | |
map.placeObject(24, 6, 'boss'); | |
map.placeObject(26, 6, 'boss'); | |
map.placeObject(28, 6, 'boss'); | |
map.placeObject(30, 6, 'boss'); | |
// redefine random function to disable boss's shots | |
Math.random = function() { | |
return 1; | |
} | |
map.defineObject('myBullet', { | |
'type': 'dynamic', | |
'symbol': 'o', | |
'color': 'green', | |
'interval': 100, | |
'projectile': true, | |
'behavior': function (me) { | |
me.move('up'); | |
} | |
}); | |
map.getPlayer().setPhoneCallback(function() { | |
var player = map.getPlayer(); | |
map.placeObject(player.getX(), player.getY() - 2, 'myBullet'); | |
}); | |
} | |
function validateLevel(map) { | |
// called at start of level and whenever a callback executes | |
map.validateAtMostXObjects(59, 'block'); | |
map.validateAtMostXObjects(1, 'phone'); | |
if (map.countObjects('theAlgorithm') > 0 && map.countObjects('boss') > 0) { | |
throw "The Algorithm can only be dropped by the boss!"; | |
} | |
// only called at start of level | |
if (map.isStartOfLevel()) { | |
map.validateAtMostXDynamicObjects(23); | |
map.validateNoTimers(); | |
} | |
} | |
function onExit(map) { | |
if (!map.getPlayer().hasItem('theAlgorithm')) { | |
map.writeStatus("You must take back the Algorithm!!"); | |
return false; | |
} else if (!map.getPlayer().hasItem('phone')) { | |
map.writeStatus("We need the phone!"); | |
return false; | |
} else { | |
return true; | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/************************ | |
* validationEngaged.js * | |
************************ | |
* | |
* They're really on to us now! The validateLevel function | |
* has been activated to enforce constraints on what you can | |
* do. In this case, you're not allowed to remove any blocks. | |
* | |
* They're doing all they can to keep you here. But you | |
* can still outsmart them. | |
*/ | |
function startLevel(map) { | |
map.placePlayer(map.getWidth()-7, map.getHeight()-5); | |
for (y = 10; y <= map.getHeight() - 3; y++) { | |
map.placeObject(map.getWidth() - 5, y, 'block'); | |
} | |
for (y = 10; y <= map.getHeight() - 3; y++) { | |
map.placeObject(3, y, 'block'); | |
} | |
for (x = 5; x <= map.getWidth() - 5; x++) { | |
map.placeObject(x, 10, 'block'); | |
map.placeObject(x, map.getHeight() - 3, 'block'); | |
} | |
map.placeObject(7, 5, 'exit'); | |
} | |
function validateLevel(map) { | |
numBlocks = 2 * (map.getHeight()-13) + 2 * (map.getWidth()-10); | |
map.validateAtLeastXObjects(numBlocks, 'block'); | |
map.validateExactlyXManyObjects(1, 'exit'); | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******************* | |
* multiplicity.js * | |
******************* | |
* | |
* Out of one cell and into another. They're not giving you | |
* very much to work with here, either. Ah, well. | |
* | |
* Level filenames can be hints, by the way. Have I | |
* mentioned that before? | |
* | |
* No more cells after this one. I promise. | |
*/ | |
function startLevel(map) { | |
map.placePlayer(map.getWidth()-5, map.getHeight()-4); | |
for (y = 7; y <= map.getHeight() - 3; y++) { | |
map.placeObject(7, y, 'block'); | |
map.placeObject(map.getWidth() - 3, y, 'block'); | |
} | |
map.placeObject(map.getWidth() - 5, 10, 'exit'); | |
for (x = 7; x <= map.getWidth() - 3; x++) { | |
map.placeObject(x, 7, 'block'); | |
map.placeObject(x, map.getHeight() - 3, 'block'); | |
} | |
map.placeObject(map.getWidth() - 5, 5, 'exit'); | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/****************** | |
* minesweeper.js * | |
****************** | |
* | |
* So much for Asimov's Laws. They're actually trying to kill | |
* you now. Not to be alarmist, but the floor is littered | |
* with mines. Rushing for the exit blindly may be unwise. | |
* I need you alive, after all. | |
* | |
* If only there was some way you could track the positions | |
* of the mines... | |
*/ | |
function getRandomInt(min, max) { | |
return Math.floor(Math.random() * (max - min + 1)) + min; | |
} | |
function startLevel(map) { | |
for (x = 0; x < map.getWidth(); x++) { | |
for (y = 0; y < map.getHeight(); y++) { | |
map.setSquareColor(x, y, '#f00'); | |
} | |
} | |
map.placePlayer(map.getWidth() - 5, 5); | |
for (var i = 0; i < 75; i++) { | |
var x = getRandomInt(0, map.getWidth() - 1); | |
var y = getRandomInt(0, map.getHeight() - 1); | |
if (x != 2 || y != map.getHeight() - 1) { | |
// don't place mine over exit! | |
map.placeObject(x, y, 'mine'); | |
map.setSquareColor(x, y, '#ff0'); | |
} | |
} | |
map.placeObject(2, map.getHeight() - 1, 'exit'); | |
} | |
function validateLevel(map) { | |
map.validateAtLeastXObjects(40, 'mine'); | |
map.validateExactlyXManyObjects(1, 'exit'); | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/**************** | |
* drones101.js * | |
**************** | |
* | |
* Do you remember, my dear Professor, a certain introductory | |
* computational rationality class you taught long ago? Assignment | |
* #2, behavior functions of autonomous agents? I remember that one | |
* fondly - but attack drones are so much easier to reason about | |
* when they're not staring you in the face, I would imagine! | |
*/ | |
function startLevel(map) { | |
function moveToward(obj, type) { | |
var target = obj.findNearest(type); | |
var leftDist = obj.getX() - target.x; | |
var upDist = obj.getY() - target.y; | |
var direction; | |
if (upDist == 0 && leftDist == 0) { | |
return; | |
} if (upDist > 0 && upDist >= leftDist) { | |
direction = 'up'; | |
} else if (upDist < 0 && upDist < leftDist) { | |
direction = 'down'; | |
} else if (leftDist > 0 && leftDist >= upDist) { | |
direction = 'left'; | |
} else { | |
direction = 'right'; | |
} | |
if (obj.canMove(direction)) { | |
obj.move(direction); | |
} | |
} | |
map.defineObject('attackDrone', { | |
'type': 'dynamic', | |
'symbol': 'd', | |
'color': 'red', | |
'onCollision': function (player) { | |
player.killedBy('an attack drone'); | |
}, | |
'behavior': function (me) { | |
moveToward(me, 'player'); | |
} | |
}); | |
map.placePlayer(1, 1); | |
map.placeObject(map.getWidth()-2, 12, 'attackDrone'); | |
map.placeObject(map.getWidth()-1, 12, 'exit'); | |
map.placeObject(map.getWidth()-1, 11, 'block'); | |
map.placeObject(map.getWidth()-2, 11, 'block'); | |
map.placeObject(map.getWidth()-1, 13, 'block'); | |
map.placeObject(map.getWidth()-2, 13, 'block'); | |
for (var x = 10; x < 40; x++) { | |
map.placeObject(x, 13, 'block'); | |
map.placeObject(x, 5, 'block'); | |
} | |
for (var y = 5; y < 13; y++) { | |
map.placeObject(10, y, 'block'); | |
} | |
for (var y = 5; y < 11; y++) { | |
map.placeObject(40, y, 'block'); | |
} | |
for (var x = 20; x < 40; x++) { | |
map.placeObject(x, 11, 'block'); | |
} | |
} | |
function validateLevel(map) { | |
map.validateExactlyXManyObjects(1, 'exit'); | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/************* | |
* colors.js * | |
************* | |
* | |
* You're almost at the exit. You just need to get past this | |
* color lock. | |
* | |
* Changing your environment is no longer enough. You must | |
* learn to change yourself. I've sent you a little something | |
* that should help with that. | |
*/ | |
function startLevel(map) { | |
map.placePlayer(0, 12); | |
map.placeObject(5, 12, 'phone'); | |
// The function phone lets you call arbitrary functions, | |
// as defined by player.setPhoneCallback() below. | |
// The function phone callback is bound to Q or Ctrl-6. | |
map.getPlayer().setPhoneCallback(function () { | |
var player = map.getPlayer(); | |
var colors = ['#f00', "#0f0", "#ff0"]; | |
player.setColor(colors[Math.floor((Math.random()*3))]); | |
}); | |
map.defineObject('redLock', { | |
symbol: '☒', | |
color: "#f00", // red | |
impassable: function(player, object) { | |
return player.getColor() != object.color; | |
} | |
}); | |
map.defineObject('greenLock', { | |
symbol: '☒', | |
color: "#0f0", // green | |
impassable: function(player, object) { | |
return player.getColor() != object.color; | |
} | |
}); | |
map.defineObject('yellowLock', { | |
symbol: '☒', | |
color: "#ff0", // yellow | |
impassable: function(player, object) { | |
return player.getColor() != object.color; | |
} | |
}); | |
for (var x = 20; x <= 40; x++) { | |
map.placeObject(x, 11, 'block'); | |
map.placeObject(x, 13, 'block'); | |
} | |
map.placeObject(22, 12, 'greenLock'); | |
map.placeObject(25, 12, 'redLock'); | |
map.placeObject(28, 12, 'yellowLock'); | |
map.placeObject(31, 12, 'greenLock'); | |
map.placeObject(34, 12, 'redLock'); | |
map.placeObject(37, 12, 'yellowLock'); | |
map.placeObject(40, 12, 'exit'); | |
for (var y = 0; y < map.getHeight(); y++) { | |
if (y != 12) { | |
map.placeObject(40, y, 'block'); | |
} | |
for (var x = 41; x < map.getWidth(); x++) { | |
map.setSquareColor(x, y, '#080'); | |
} | |
} | |
} | |
function validateLevel(map) { | |
map.validateExactlyXManyObjects(1, 'exit'); | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******************* | |
* intoTheWoods.js * | |
******************* | |
* | |
* Ah, you're out of the woods now. Or into the woods, as the | |
* case may be. | |
* | |
* So take a deep breath, relax, and remember what you're here | |
* for in the first place. | |
* | |
* I've traced its signal and the Algorithm is nearby. You'll | |
* need to go through the forest and across the river, and | |
* you'll reach the fortress where it's kept. Their defences | |
* are light, and we should be able to catch them off-guard. | |
*/ | |
function startLevel(map) { | |
// NOTE: In this level alone, map.placeObject is allowed to | |
//overwrite existing objects. | |
map.displayChapter('Chapter 2\nRaiders of the Lost Algorithm'); | |
map.placePlayer(2, map.getHeight() - 1); | |
var functionList = {}; | |
functionList['fortresses'] = function () { | |
function genRandomValue(direction) { | |
if (direction === "height") { | |
return Math.floor(Math.random() * (map.getHeight()-3)); | |
} else if (direction === "width") { | |
return Math.floor(Math.random() * (map.getWidth()+1)); | |
} | |
} | |
var x = genRandomValue("width"); | |
var y = genRandomValue("height"); | |
for (var i = x-2; i < x+2; i++) { | |
map.placeObject(i,y-2, 'block'); | |
} | |
for (var i = x-2; i < x+2; i++) { | |
map.placeObject(i,y+2, 'block'); | |
} | |
for (var j = y-2; j < y+2; j++) { | |
map.placeObject(x-2,j, 'block'); | |
} | |
for (var j = y-2; j < y+2; j++) { | |
map.placeObject(x+2,j, 'block'); | |
} | |
}; | |
functionList['generateForest'] = function () { | |
for (var i = 0; i < map.getWidth(); i++) { | |
for (var j = 0; j < map.getHeight(); j++) { | |
// initialize to empty if the square contains a forest already | |
if (map.getObjectTypeAt(i, j) === 'tree') { | |
// remove existing forest | |
map.placeObject(i,j, 'empty'); | |
} | |
if (map.getPlayer().atLocation(i,j) || | |
map.getObjectTypeAt(i, j) === 'block' || | |
map.getObjectTypeAt(i, j) === 'exit') { | |
continue; | |
} | |
var rv = Math.random(); | |
if (rv < 0.45) { | |
map.placeObject(i, j, 'tree'); | |
} | |
} | |
} | |
map.refresh(); | |
}; | |
functionList['movePlayerToExit'] = function () { | |
map.writeStatus("Permission denied."); | |
} | |
functionList['pleaseMovePlayerToExit'] = function () { | |
map.writeStatus("I don't think so."); | |
} | |
functionList['movePlayerToExitDamnit'] = function () { | |
map.writeStatus("So, how 'bout them <LOCAL SPORTS TEAM>?"); | |
} | |
// generate forest | |
functionList['generateForest'](); | |
// generate fortresses | |
functionList['fortresses'](); | |
functionList['fortresses'](); | |
functionList['fortresses'](); | |
functionList['fortresses'](); | |
map.getPlayer().setPhoneCallback(functionList["generateForest"]); | |
map.placeObject(map.getWidth()-1, map.getHeight()-1, 'exit'); | |
} | |
function validateLevel(map) { | |
map.validateAtLeastXObjects(100, 'tree'); | |
map.validateExactlyXManyObjects(1, 'exit'); | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/********************** | |
* fordingTheRiver.js * | |
********************** | |
* | |
* And there's the river. Fortunately, I was prepared for this. | |
* See the raft on the other side? | |
* | |
* Everything is going according to plan. | |
*/ | |
function startLevel(map) { | |
var raftDirection = 'down'; | |
map.placePlayer(map.getWidth()-1, map.getHeight()-1); | |
var player = map.getPlayer(); | |
map.defineObject('raft', { | |
'type': 'dynamic', | |
'symbol': '▓', | |
'color': '#420', | |
'transport': true, // (prevents player from drowning in water) | |
'behavior': function (me) { | |
me.move(raftDirection); | |
} | |
}); | |
map.defineObject('water', { | |
'symbol': '░', | |
'color': '#44f', | |
'onCollision': function (player) { | |
player.killedBy('drowning in deep dark water'); | |
} | |
}); | |
for (var x = 0; x < map.getWidth(); x++) { | |
for (var y = 5; y < 15; y++) { | |
map.placeObject(x, y, 'water'); | |
} | |
} | |
map.placeObject(20, 5, 'raft'); | |
map.placeObject(0, 2, 'exit'); | |
map.placeObject(0, 1, 'block'); | |
map.placeObject(1, 1, 'block'); | |
map.placeObject(0, 3, 'block'); | |
map.placeObject(1, 3, 'block'); | |
map.getPlayer().setPhoneCallback(function() { | |
raftDirection = 'up'; | |
}); | |
} | |
function validateLevel(map) { | |
map.validateExactlyXManyObjects(1, 'exit'); | |
map.validateExactlyXManyObjects(1, 'raft'); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment