Skip to content

Instantly share code, notes, and snippets.

@Untrusted-Game
Created March 25, 2019 10:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Untrusted-Game/70038d1464d11ac27046611f48ec18ab to your computer and use it in GitHub Desktop.
Save Untrusted-Game/70038d1464d11ac27046611f48ec18ab to your computer and use it in GitHub Desktop.
Solution to level 20 in Untrusted: http://alex.nisnevich.com/untrusted/
/*****************
* 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');
var player = map.getPlayer();
var color = 'yellow';
var canon;
var canvas = map.getCanvasContext();
var img = new Image(); // Create new img element
var src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA';
src = src + 'ACAAAAAgCAMAAABEpIrGAAAABGdBTUEAALGPC/xhBQAA';
src = src + 'AAFzUkdCAK7OHOkAAALTUExURQAAAF5eXqysrL6+vlJS';
src = src + 'UrKysm9vbxAQEHBwcAAAAJCQkE9PT46OjlJSUkxMTEZG';
src = src + 'RkpKSi8vL1hYWAoKCnV1dRcXFz4+Pn19fXd3d3p6elhY';
src = src + 'WISEhDg4OKWlpRkZGW9vbzQ0NCYmJkNDQ1tbW56enmho';
src = src + 'aGdnZ2RkZIaGhlBQUExMTJ+fn2JiYlBQUEFBQSkpKWpq';
src = src + 'aoGBgaenp2VlZUlJSUhISHl5eYeHhzc3N01NTXNzc1JS';
src = src + 'UktLSxUVFaysrGJiYiIiImZmZhkZGWdnZ3l5eZ6enqSk';
src = src + 'pIqKil9fX6CgoDY2NpWVlURERDg4OH5+fmNjY2BgYHh4';
src = src + 'eAAAAM7OzpSUlNra2peXl9PT0////66urt3d3dLS0ouL';
src = src + 'i/T09N/f38bGxsTExMHBwcvLy7CwsKioqA0NDbu7u6Ki';
src = src + 'ogkJCeDg4LS0tMnJyd7e3tnZ2dTU1GdnZ9jY2OTk5Kam';
src = src + 'piEhIejo6L29vbOzswsLC8rKypGRkcDAwJKSklFRUcjI';
src = src + 'yHFxcTIyMikpKfj4+Nzc3JaWluHh4aCgoMPDw7q6upyc';
src = src + 'nFdXV+Pj4xUVFevr66qqqlhYWM/Pz4iIiNDQ0IaGhhwc';
src = src + 'HK2trYWFhWFhYampqYCAgKurq7m5uff39/Pz83d3dx4e';
src = src + 'HhkZGUFBQWxsbKWlpdbW1jU1NYKCgpqamsXFxaGhoVlZ';
src = src + 'WUZGRtfX14eHh2JiYry8vOLi4vr6+jo6OpmZme7u7k5O';
src = src + 'TpCQkEtLS+fn5/39/TQ0NO3t7WlpaXx8fJ6ennV1dUxM';
src = src + 'TIyMjMfHx6ysrLKysgQEBAcHB0dHR4SEhLi4uDg4OBMT';
src = src + 'EzY2NigoKF5eXoqKiqSkpF1dXaenpz8/P8zMzM3Nzerq';
src = src + '6tXV1VBQUL6+vrW1tTw8PENDQyQkJDk5OURERGhoaFRU';
src = src + 'VCsrK1paWmBgYHl5efDw8Pn5+SIiImZmZr+/v21tbX5+';
src = src + 'fmpqakhISGVlZY2NjSwsLCb+waEAAABSdFJOUwBauPgx';
src = src + '+YMCkZjTKcMGFh5CKYkJkRNR6MmdZfAPtL6vpX18H7bE';
src = src + '0ZXmlY35h3MLoJjZulBnKnn1Pzkzyidn/UIFcPRpn4Lh';
src = src + '5zboE6AxRZ2ZUr2kfWatAAACIElEQVQ4y2NgoC6wd/Vg';
src = src + 'CfDBLe/g4u7tF+jv64Vd2tLRbc3+6ph3lVsPeDpjkTcL';
src = src + 'TlmR8n7P0uSwmjelyznQpdmNamemVKVvWlaz5e2H1/sa';
src = src + 'blmjKZDN7CjqvThpz+MlGQ3bNj66HXRaF0WeLzi5PWxp';
src = src + 'TF39vZU79z95uPNMULkSigKB4NLm/CWpxd2T+6ZVli1a';
src = src + 'OTnjqCKKApHWkGnFQfO3XDo5aWLc4vDwkCNBcigK5Gs6';
src = src + '52UEzauLqc4tLOhPCl7eF6SAokDr2KnU8jsPYmqrFq+P';
src = src + 'zk5IS+7t1kdRYLIgqPxuTEhkcFzo9ujL/UknqlZxoiiw';
src = src + 'aAhKXdCxPTb2WWNUfEXmtYSJF1AVMDgFZezueTpn18u6';
src = src + 'fdMTZ87NX7PQFkXeijV1fnhEdNju+uer0pPqg4KKX9ug';
src = src + 'KDCODtuYsyF076u1Lw4U7Lq/7fpCO1MUBcpxJ0KubJ4d';
src = src + 'sbl23er1sTc3Fa1j1UN1g0rJ7JyoktgdjTu6QhsrIqOT';
src = src + 'tGVQFfBHzMkNjYoqLIkP3hARVVSWJc2LFp1XI5pyQisS';
src = src + 'p6Td2BoZNiOsUhw9QTAyZcYV5JW2l7Skneuc2jpdAjNJ';
src = src + 'MXeFhxbmnV+RPmHt2SnxQpgK2Fris/OCZ2WFzM0/XhYi';
src = src + 'iKmAnetg5LLE2Nzk6o7IEE2s6ZrncEpieFvaovQsNRwZ';
src = src + 'g+NQYkLo6oRsDWFcWYdF0tB8wlJVUdyZi1tKx0BdjKr5';
src = src + 'GQA6rNASyrJygwAAAABJRU5ErkJggg==';
img.src = src;
canvas.canvas.style.display = "block";
map.defineObject('canon', {
'type': 'dynamic',
'symbol': 'U',
'impassable': true,
'color': color,
'interval': 250,
'behavior': function (me) {
if (player.getX() > me.getX()) {
me.move('right');
} else if (player.getX() < me.getX()) {
me.move('left');
}
canvas.clearRect(0, 0, canvas.canvas.width, canvas.canvas.height);
},
'onDestroy': function () {
canon = undefined;
}
});
map.defineObject('photon_torpedo', {
'type': 'dynamic',
'symbol': 'X',
'color': color,
'interval': 100,
'projectile': true,
'behavior': function (me) {
var objs = map.getDynamicObjects();
var enemy;
for (var i = 0; i < objs.length; i++) {
var o = objs[i];
if (o.getType() == 'boss') {
enemy = o;
}
}
if (enemy !== undefined) {
if (enemy.getX() < me.getX()) {
me.move('left');
} else if (enemy.getX() > me.getX()) {
me.move('right');
} else if (enemy.getY() < me.getY()) {
me.move('up');
} else if (enemy.getY() > me.getY()) {
me.move('down');
}
}
},
'onDestroy': function (me) {
var coords = map.getCanvasCoords(me);
canvas.drawImage(img, coords.x - 32, coords.y - 32, 64, 64);
}
});
player.setPhoneCallback(function () {
var objs = map.getDynamicObjects();
if (canon === undefined) {
map.placeObject(player.getX(), map.getHeight() - 5, 'canon');
for (var i = 0; i < objs.length; i++) {
var o = objs[i];
if (o.getType() == 'canon') {
canon = o;
}
}
} else {
var enemy;
for (var i = 0; i < objs.length; i++) {
var o = objs[i];
if (o.getType() == 'boss') {
enemy = o;
}
}
if (enemy !== undefined) {
map.placeObject(enemy.getX(), enemy.getY(), 'photon_torpedo');
var coordsA = map.getCanvasCoords(canon);
var coordsB = map.getCanvasCoords(enemy);
var ctx = map.getCanvasContext();
ctx.beginPath();
ctx.strokeStyle = color;
ctx.lineWidth = 3;
ctx.moveTo(coordsA.x, coordsA.y);
ctx.lineTo(coordsB.x, coordsB.y);
ctx.stroke();
ctx.closePath();
}
}
});
map.defineObject('wall', {
'symbol': '=',
'color': 'green',
'impassable': true
});
map.defineObject('trench', {
'symbol': '-',
'color': 'green',
'impassable': true
});
for (var x = 4; x < map.getWidth() - 4; x++) {
map.placeObject(x, map.getHeight() - 6, 'wall');
map.placeObject(x, map.getHeight() - 4, 'trench');
}
}
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;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment