How do I solve Untrusted's levels?
-
I am playing https://alexnisnevich.github.io/untrusted/ (JavaScript adventure game) and I am stuck at a particular level. How do I solve that?
Even after I solved a level, I am curious to know if there are better approaches. Is there a compilation, or a walk-through of optimal ways to solve Untrusted's levels?
-
As all the successful solutions are https://gist.github.com/Untrusted-Game , I spend some time analyzing them and compiled a list of all the (sensible) approaches to solve each level, that I could find.
https://gist.github.com/mhasdf/40363e0c1c807663d8c6ccb797aa94fa
Solutions for the Untrusted Game
untrusted game: https://alexnisnevich.github.io/untrusted/
Level 1
cellBlockA.js
01_cellBlockA.jsx// remove all code
Level 2
theLongWayOut.js
02_theLongWayOut.jsx/* */
Level 3
validationEngaged.js
03_validationEngaged.jsxfor (y = 10; y
for (x = 5; x <= map.getWidth() - 5; x++) { map.placeObject(x, 10, 'block'); map.placeObject(x, map.getHeight() - 3, 'block'); }
Level 4
multiplicity.js
04_multiplicity.jsxmap.placeObject(40, 20, 'exit');
Level 5
minesweeper.js
05_minesweeper.jsxmap.setSquareColor(x, y, '#000');
Level 6
drones101.js
06_drones101.jsxmap.placeObject(20, 11, 'block'); map.placeObject(20, 12, 'block'); map.placeObject(21, 13, 'block'); map.placeObject(22, 12, 'block');
or
var i = 0; map.defineObject('timebomb', { 'type': 'dynamic', 'symbol': 'C', 'color': '#ff0', 'behavior': function (me) { if (i === 10) { x = 37; y = 12; map.placeObject(x-1, y, 'block'); map.placeObject(x+1, y, 'block'); map.placeObject(x, y-1, 'block'); map.placeObject(x, y+1, 'block'); } i++; } }); map.placeObject(34, 12, 'timebomb');
or with an idea from a later level
map.placeObject(1, 13, 'teleporter'); map.placeObject(45, 13, 'teleporter'); var t = map.getDynamicObjects(); t[1].setTarget(t[2]);
or with an idea from a later level
map.defineObject('turret', { 'type': 'dynamic', 'symbol': '=', 'color': 'yellow', 'interval': 200, 'behavior': function (me) { if ((me.i = (me.i ?? 0) + 1) < 10) { map.placeObject(me.getX() + 1, me.getY(), 'bullet'); } } }); map.defineObject('bullet', { 'type': 'dynamic', 'symbol': '.', 'color': 'yellow', 'interval': 100, 'projectile': true, 'behavior': function (me) { me.move('right'); } }); map.placeObject(20, 12, 'turret');
https://gist.github.com/search?q=%22untrusted-lvl6-solution.js%22
Level 7
colors.js
07_colors.jsxvar player = map.getPlayer(); var colors = { '#f00': '#ff0', '#ff0': '#0f0', '#0f0': '#f00' }; player.setColor(colors[player.getColor()]);
or
var player = map.getPlayer(); if (player.i === undefined) player.i = 0; var colors = ['#f00', '#ff0', '#0f0']; player.setColor(colors[player.i]); player.i = (player.i + 1) % colors.length;
or
var player = map.getPlayer(); var colors = ['#0f0', '#f00', '#ff0']; var i = player.i ?? 0; map.startTimer(function () { player.setColor(colors[i++ % colors.length]); }, 500);
or
var player = map.getPlayer(); if (player.getX() === 24 || player.getX() === 33) { player.setColor('#f00'); } else if (player.getX() === 27 || player.getX() === 36) { player.setColor('#ff0'); } else { player.setColor('#0f0'); }
Nice to remember:
map.getPlayer().setPhoneCallback(function () {});
https://gist.github.com/search?q=%22untrusted-lvl7-solution.js%22
Level 8
intoTheWoods.js
08_intoTheWoods.jsx"generateForest"
Level 9
fordingTheRiver.js
09_fordingTheRiver.jsxmap.defineObject('bridge', { 'type': 'dynamic', 'symbol': '☰', 'color': '#f77', 'transport': true, }); for (var y = 5; y < 15; y++) { map.placeObject(10, y, 'bridge'); }
or
map.getPlayer().setPhoneCallback(function () { raftDirection = 'up'; });
https://gist.github.com/search?q=%22untrusted-lvl9-solution.js%22
Level 10
ambush.js
10_ambush.jsx///// attackDrone if (me.canMove('up')) { me.move('up'); } else { me.move('left'); } ///// reinforcementDrone me.move('up'); ///// defenseDrone if (me.canMove('up')) { me.move('up'); } else { me.move('right'); }
https://gist.github.com/search?q=%22untrusted-lvl10-solution.js%22
Level 11
robot.js
11_robot.jsxif (me.canMove('right')) { me.move('right'); } else { me.move('down'); }
https://gist.github.com/search?q=%22untrusted-lvl11-solution.js%22
Level 12
robotNav.js
12_robotNav.jsxif (me.getX() < 25) { if (me.canMove('down')) { me.move('down'); } else { me.move('right'); } } else if (me.getX() < 30) { if (me.canMove('up')) { me.move('up'); } else { me.move('right'); } } else { if (me.canMove('right')) { me.move('right'); } else { me.move('down'); } }
Also, see Level 13 solutions.
https://gist.github.com/search?q=%22untrusted-lvl12-solution.js%22
Level 13
robotMaze.js
13_robotMaze.jsxvar a = ['left', 'up', 'right', 'down']; if (me.i === undefined) { me.i = 0; map.getPlayer().setPhoneCallback(function () { me.i = (me.i + 1) % 4; }); } me.move(a[me.i]);
or
map.setSquareColor(41, 22, '#770'); map.setSquareColor(42, 21, '#770'); map.setSquareColor(43, 22, '#770'); map.setSquareColor(42, 23, '#770'); if (player.atLocation(41, 22)) me.move('left'); if (player.atLocation(42, 21)) me.move('up'); if (player.atLocation(43, 22)) me.move('right'); if (player.atLocation(42, 23)) me.move('down');
or
if (me.i === undefined) { me.i = 1; map.getPlayer().setPhoneCallback(function () { if (me.i++ % 2) { map.overrideKey('left', ()=>{ me.move('left'); }); map.overrideKey('up', ()=>{ me.move('up'); }); map.overrideKey('right', ()=>{ me.move('right'); }); map.overrideKey('down', ()=>{ me.move('down'); }); } else { map.overrideKey('left', null); map.overrideKey('up', null); map.overrideKey('right', null); map.overrideKey('down', null); } }); }
or
var a = { 'left': ['down', 'up'], 'up': ['left', 'right'], 'right': ['up', 'down'], 'down': ['right', 'left'], }; if (me.i === undefined) me.i = 'up'; if (me.j === undefined) me.j = false; if (me.j && me.canMove(a[me.i][0])) { me.i = a[me.i][0]; } else if (me.canMove(me.i) && !me.canMove(a[me.i][0])) { me.j = true; } else if (!me.canMove(me.i)) { me.i = a[me.i][1]; } me.move(me.i);
https://gist.github.com/search?q=%22untrusted-lvl13-solution.js%22
Level 14
crispsContest.js
14_crispsContest.jsxtheAlgorithm
left (blue), greenKey, up, blueKey, center, right (red), blueKey, up, redKey, center, down, theAlgorithm, right, yellowKey, center, exit
https://gist.github.com/search?q=%22untrusted-lvl14-solution.js%22
Level 15
exceptionalCrossing.js
15_exceptionalCrossing.jsxa
or
'');}, 'onCollision':function () {//
Level 16
lasers.js
16_lasers.jsx// 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(); ///// map.getPlayer().setPhoneCallback(function () { var player = map.getPlayer(); player.i = ((player.i ?? -1) + 1) % colors.length; player.setColor(colors[player.i]); });
https://gist.github.com/search?q=%22untrusted-lvl16-solution.js%22
Level 17
pointers.js
17_pointers.jsxif (i === teleportersAndTraps.length - 2) { var obj = map.getDynamicObjects(); var a = obj[0]; var b = obj[obj.length - 2]; // teleporter nearest to exit a.setTarget(b); var c = map.getCanvasContext(); c.beginPath(); c.strokeStyle = 'purple'; c.lineWidth = 4; c.moveTo(map.getCanvasCoords(a).x, map.getCanvasCoords(a).y); c.lineTo(map.getCanvasCoords(b).x, map.getCanvasCoords(b).y); c.stroke(); }
https://gist.github.com/search?q=%22untrusted-lvl17-solution.js%22
Level 18
superDrEvalBros.js
18_superDrEvalBros.jsx} function gravity() {
or
map.defineObject('bridge', { 'symbol': '=', 'color': '#dd0', 'impassable': true }); for (var x = 20; x < 30; x++) { map.placeObject(x, fl(h/2), 'bridge'); }
or
map.placeObject(19,11,'teleporter'); map.placeObject(30,11,'teleporter'); var d = map.getDynamicObjects(); d[0].setTarget(d[1]);
or
map.startTimer(function () { var x = player.getX(); var y = player.getY(); if (x < 35) { if (y > 1) { player.move('up'); } else { player.move('right'); } } }, 25);
https://gist.github.com/search?q=%22untrusted-lvl18-solution.js%22
Level 19
documentObjectMadness.js
19_documentObjectMadness.jsxBring the green highlight (deEval) to the red highlight (adversary)
- up = moveToParent
- down = moveToFirstChild
- left = moveToPreviousSibling
- right = moveToNextSibling
Level 20
bossFight.js
20_bossFight.jsxmap.defineObject('missile', { 'type': 'dynamic', 'symbol': '^', 'color': 'orange', 'projectile': true, 'interval': 100, 'behavior': function (me) { me.move('up'); } }); /// You need to make it to the other side for the phone :-( var player = map.getPlayer() player.setPhoneCallback(() => { map.placeObject(player.getX(), player.getY() -2, 'missile'); });
or
map.defineObject('missile', { 'type': 'dynamic', 'symbol': '^', 'color': 'orange', 'projectile': true, 'interval': 100, 'behavior': function (me) { me.move('up'); } }); /// Shield map.defineObject('shield', { 'type': 'dynamic', 'symbol': '/', 'color': 'purple', 'impassable': true, 'passableFor': ['missile'] }); for(var x = 2; x < 48; x++) { map.placeObject(x, 19, 'shield'); } var player = map.getPlayer(); player.setPhoneCallback(() => { map.placeObject(player.getX(), player.getY() -2, 'missile'); });
or
map.defineObject('missile', { 'type': 'dynamic', 'symbol': '^', 'color': 'orange', 'projectile': true, 'interval': 100, 'behavior': function (me) { me.move('up'); } }); /// Don't let the boss fire Math.random = function () { return 1; } var player = map.getPlayer(); player.setPhoneCallback(() => { map.placeObject(player.getX(), player.getY() -2, 'missile'); });
or
map.defineObject('missile', { 'type': 'dynamic', 'symbol': '^', 'color': 'orange', 'projectile': true, 'interval': 100, 'behavior': function (me) { me.move('up'); } }); /// Use left arrow key map.overrideKey('left', function () { for (var x = 0; x < map.getWidth(); x++) { map.placeObject(x, 15, 'missile'); } });
or
map.defineObject('missle', { 'type': 'dynamic', 'symbol': '>', 'color': 'orange', 'projectile': true, 'interval': 100, 'behavior': function (me) { me.move('right'); } }); map.defineObject('trigger', { 'symbol': '+', 'color': 'orange', 'onCollision': function () { map.placeObject(0,5, 'missle'); map.placeObject(0,6, 'missle'); } }); map.placeObject(0, 24, 'trigger');
or
map.defineObject('missle', { 'type': 'dynamic', 'symbol': '>', 'color': 'orange', 'projectile': true, 'interval': 100, 'behavior': function (me) { me.move('right'); } }); Math.random = function () { map.placeObject(0, 5, 'missle'); map.placeObject(0, 6, 'missle'); return 1; }
or
map.defineObject('trigger', { 'symbol': '+', 'color': 'orange', 'onCollision': function () { map.getDynamicObjects().forEach( function (o) { /// Hit them with their own bullets map.placeObject(o.getX(), o.getY() - 1, 'bullet'); }); } }); map.placeObject(0, 24, 'trigger');
or
/// Landing map.getDynamicObjects().forEach(function (o) { o.direction = "down"; }); map.getPlayer().setPhoneCallback(function () { for(var x = 2; x < 48; x++) { map.placeObject(x, 10, 'bullet'); } });
https://gist.github.com/search?q=%22untrusted-lvl20-solution.js%22
Level 21
21_endOfTheLine.jsx
Go to Menu, scripts/objects.js
Find this code and comment out the if condition
'exit' : { 'symbol' : String.fromCharCode(0x2395), // ⎕ 'color': '#0ff', 'onCollision': function (player) { if (!game.map.finalLevel) { game._callUnexposedMethod(function () { game._moveToNextLevel(); }); } } },
bonus / 01_inTheDesert.jsx
inTheDesert.js
No code changes needed. Don't move too far away from the E. The E deactivates the laser.
bonus / 02_theEmptyRoom.jsx
theEmptyRoom.js
return {15:610, 16:987, 17:1597, 18:2584, 19:4181, 20:6765, 21:10946, 22:17711, 23:28657, 24:46368, 25:75025, 26:121393, 27:196418, 28:317811, 29:514229, 30:832040, 31:1346269, 32:2178309, 33:3524578, 34:5702887, 35:9227465, 36:14930352, 37:24157817, 38:39088169, 39:63245986, 40:102334155, 41:165580141, 42:267914296, 43:433494437, 44:701408733, 45:1134903170, 46:1836311903, 47:2971215073, 48:4807526976, 49:7778742049, 50:12586269025, 51:20365011074, 52:32951280099, 53:53316291173, 54:86267571272, 55:139583862445, 56:225851433717, 57:365435296162, 58:591286729879, 59:956722026041, 60:1548008755920, 61:2504730781961, 62:4052739537881, 63:6557470319842, 64:0x9a661ca20bb, 65:0xf9d297a859d, 66:27777890035288, 67:44945570212853, 68:72723460248141, 69:0x6b04f4c2fe42, 70:0xad2934c6d08f, 71:308061521170129, 72:498454011879264, 73:806515533049393, 74:0x4a2dce62b0d91, 75:0x780626e057bc2, 76:0xc233f54308953, 77:5527939700884757, 78:8944394323791464, 79:0x336a82d89c937c, 80:0x533163ef0321e4, 81:0x869be6c79fb560, 82:0xd9cd4ab6a2d740, 83:99194853094755490, 84:0x23a367c34e563e0, 85:0x39a9fadb327f080, 86:0x5d4d629e80d5480, 87:0x96f75d79b354500, 88:0xf444c0183429980, 89:0x18b3c1d91e77de00, 90:0x27f80ddaa1ba7800, 91:466004661037553e4, 92:0x68a3dd8e61ecd000, 93:0xa94fad42221f2800, 94:0x111f38ad0840c0000, 95:319404346349901e5, 96:5168070885485833e4, 97:8362114348984843e4, 98:0x755b0bdd8fa998000, 99:2189229958345552e5, 100:3542248481792619e5}[input];
bonus / 03_theCollapsingRoom.jsx
theCollapsingRoom.js
half_width = 5;
bonus / 04_theGuard.jsx
theGuard.js
map.placeObject(26, 12, 'block'); map.placeObject(28, 12, 'block'); map.placeObject(27, 13, 'block');
or
/// Use eyes to block guard map.placeObject(40, 20, 'eye');
bonus / 05_theCorridor.jsx
function trap_behaviour (me, left, right) {}
bonus / AB_1_ANewJourney.jsx
ANewJourney.js
/// Modify map - does not work in other levels for (var x = 0; x < map.getWidth(); x++) { for (var y = 0; y < map.getHeight(); y++) { if (map.getObjectTypeAt(x, y) === 'tree') { map.placeObject(x, y, 'empty'); } } }
or
function getRandomInt() { return 4; } map.placeObject(42, 8, 'empty');
or
map.placeObject(map.getWidth()-8, 1, 'empty'); map.placeObject(map.getWidth()-18, 1, 'empty'); map.placeObject(map.getWidth()-13, 2, 'empty'); map.placeObject(map.getWidth()-8, 4, 'empty'); map.placeObject(map.getWidth()-8, 7, 'empty'); map.placeObject(map.getWidth()-16, 6, 'empty'); map.placeObject(10, 20, 'exit');
bonus / AB_2_FrozenCave.jsx
FrozenCave.js
/// Modify map - does not work in other levels for (var i=2; i
bonus / AB_3_BoulderMadness.jsx
BoulderMadness.js
color: 'white', ///// color: 'yellow', ///// color: 'red',
bonus / AB_4_BatAttack.jsx
BatAttack.js
map.placeObject(6, 23, 'teleporter'); map.placeObject(39, 1, 'teleporter'); var objs = map.getDynamicObjects(); var ts = []; for (i = 0; i < objs.length; i++) { var t = objs[i]; if (t.getType() == 'teleporter') { ts.push(t); } } ts[0].setTarget(ts[1]);
or
function wakeAndHunt(obj, type) {}
bonus / AB_5_PathOfDoom.jsx
PathOfDooM.js
map.placeObject(45, 12, 'block');
bonus / darkAlley.jsx
darkAlley.jsx
map.placeObject(30, 17, 'goldengun');
bonus / ice.jsx
ice.js
map.startTimer(function () { map.getPlayer().move('up'); }, 25);
bonus / labryinth.jsx
if (me.getX() > 43) { me.move('up'); } ///// map.placeObject(1, 10, 'boulder'); for (x = 29; x < 39; x++) { map.placeObject(x, 14, 'block'); } for (var x = 0; x < map.getWidth(); x++) { for (var y = 0; y < map.getHeight(); y++) { map.setSquareColor(x, y, '#444') } }
bonus / levelName.jsx
.js
map.defineObject('helper', { 'symbol': '%', 'color': '#0f0', 'impassable': function (player) { if (player.getColor() == this.color) { return false; } player.setColor('#0f0'); return true; } }); map.placeObject(30, 9, 'helper');
or
map.overrideKey('down', function () { var player = map.getPlayer(); player.setColor('#0f0'); player.move('down'); });
bonus / noWayOut.jsx
102_noWayOut.js
buildWall = function () {};
bonus / pushme.jsx
pushme.js
});function moveToward(obj,type){obj.move('down')}var a =({
or
/// Move the blocks wisely pushable: true,
bonus / soccer.jsx
soccer.jsx
function moveGoalie(goalie) { goalie.move('down'); } kickedDirection = 'right';
or
moveGoalie = function () {} moveEnemyPlayer = function () {}
bonus / threeKeys.jsx
???
bonus / trapped.jsx
trapped.js
moveToward = function () {}
Don't push a box against another object.
bonus / wallsWithEyes.jsx
wallsWithEyes
teleport2.setTarget(teleport1);
Non-Documented API
map.writeStatus('message');
object.impassable: true, passableFor: ['missile']
object.impassableFor: ['raft']
object.transport: true
// prevents from collision with object at same positionobject.pushable: true
object.type: 'block', 'tree', 'teleporter', 'empty'
object.type: 'mine', 'trap'
// deadlyobject.type: 'exit', 'player'
object.type: 'computer', 'phone', 'redKey', 'greenKey', 'blueKey', 'yellowKey', 'theAlgorithm'
object.type: 'eye', 'guard'
object.type: 'item', onPickUp: f(), onDrop: f()
object.interval: 200, behavior: f()