玩过坑爹的两个大冒险之后再玩这种既不正常也不坑的游戏简直神清气爽,加上游戏本身独特的设计,真是停不下来……听到推荐后晚上9点40搞到凌晨2点50弄完睡觉
基本玩法就是通过修改右侧黑底部分的代码(红底不能修改)来达到修改左侧游戏局面,最终目标是让玩家控制的@顺利走到方块门上面
语死早?地址在这里玩一下就都知道了,自备翻墙 http://alexnisnevich.github.io/untrusted/
01.cellBlockA
说好的右侧代码在哪?首先在围墙里面捡起来电脑⌘,右边会出现这关的代码,显然黑底部分就是画得围墙嘛,全都删掉再按Execute重新生成一遍……好了直接走吧,注意不拿电脑是过不了关的,代码中提到关于携带电脑的判定……
02.theLongWayOut
可修改的黑色部分有上下两块,但是不能删掉创建墙的部分啊……一种办法是两块分别写/* */把中间注释掉,还有一种就是再在玩家附近创建一个出口……
map.placeObject(7,3, 'exit');
生成的时候可能会报错,因为已经有墙了,没关系反复点几次就好
03.validationEngaged
函数validateLevel(map)限定了只有一个出口,并且规定了墙砖数量的下限,拆墙是不可能了,但还可以移动一下,把上面围墙移到紧贴下面就好了
for (y = 10; y <= map.getHeight() - 3; y++) {
map.placeObject(5, y, 'block');
map.placeObject(map.getWidth() - 5, y, 'block');
}
for (x = 5; x <= map.getWidth() - 5; x++) {
map.placeObject(x, map.getHeight() - 2, 'block');
map.placeObject(x, map.getHeight() - 3, 'block');
}
04.multiplicity
额……题目名都说了,再看一眼发现没限定出口数量,那就直接在围墙里面造一个呗……
map.placeObject(map.getWidth() - 5, 15, 'exit');
05.minesweeper
哦~啥都没有为毛走两步就死了?看看程序发现地上有一堆东西叫mine的,创建mine的下一行就可以自由写点什么,而且是同层循环……仿照给屏幕变色改改把地雷标记出来
map.setSquareColor(x, y, '#ff0');
之后就绕着走吧
06.drones101
比较容易想到应该是弄个啥东西把d卡住的,想卡住d就要先看d的行动方式:优先向左移动弥补水平位置的差距,当水平距离小于竖直距离时向上,这两条就保证了只要@在d的上方,d就只会向左和向上运动。那么建一个横墙卡住它就行了,开口靠近出口这样水平相同时向右运动追不上我们。
for (var i=1; i<=map.getWidth()-4; i++) map.placeObject(i, 11,'block');
07.colors
从三种☒的定义看,只允许同色@通过,那么就要考虑给@变色。这关多了一个新物品——电话,拿到电话后按Q键可以执行动作,从API表中查到player.setPhoneCallback()可以定义打电话后的动作,这一关对于player.setPhoneCallback()的框架都有了,就是个教学嘛……变色顺序来就是了
var player = map.getPlayer();
if (player.getColor()=='#0f0') player.setColor('#f00');
else if (player.getColor()=='#f00') player.setColor('#ff0');
else if (player.getColor()=='#ff0') player.setColor('#0f0');
08.intoTheWoods
填空题,就只能填一个函数名,那几个带move的怎么看怎么坑,肯定不填。fortresses是生成几个墙方块的,generateForest生成随机森林。考虑一下就是generateForest没错了,走几步走不动了就打电话重建一个森林……生成过程判断过玩家位置所以不会出现附加关那种原地生成一个方块秒人的蛋疼问题……
09.fordingTheRiver
走进水里会淹死,除非在那个raft上面……前几步这货会自己走过来倒是不错,问题是咋回去呢?可以看到raftDirection控制方向,默认为down,可以在上船之后打个电话把它变成up,这样就可以跟着我们走啦
map.getPlayer().setPhoneCallback(function () {
raftDirection='up';
});
10.ambush
要控制三种d让路……最好是让开中缝,这样黄色d不用处理直接删干净,红绿d是对称的比较好搞。以红色d为例,让开中缝,不妨向上up移动,但是不能向上呢,只好向左left走给后面的d让开最上面一行
map.defineObject('attackDrone', {
'type': 'dynamic',
'symbol': 'd',
'color': 'red',
'onCollision': function (player) {
player.killedBy('an attack drone');
},
'behavior': function (me) {
if (me.canMove('up')) me.move('up');
else me.move('left');
}
});
map.defineObject('reinforcementDrone', {
'type': 'dynamic',
'symbol': 'd',
'color': 'yellow',
'onCollision': function (player) {
player.killedBy('a reinforcement drone');
},
'behavior': function (me) {
}
});
map.defineObject('defenseDrone', {
'type': 'dynamic',
'symbol': 'd',
'color': 'green',
'onCollision': function (player) {
player.killedBy('a defense drone');
},
'behavior': function (me) {
if (me.canMove('up')) me.move('up');
else me.move('right');
}
});
完整点就这么个东西
11.robot
这个barrier只有R可以通过,R可以把k捡起来也可以交给玩家。那么问题就是控制R走到k再走到下半场……整体路线就是优先向下,不能走了再向右靠
<span style="font-family:Courier New;"> if (me.canMove('down')) me.move('down');
else me.move('right');</span>
12.robotNav
差不多,路线复杂了点……整体是右->下->右->上->右->下->左。猥琐点的办法,利用玩家@的坐标值做档位控制R的移动,注意提到的原地不动按R键机器人也会走
var player=map.getPlayer();
if (player.getX()==0) me.move('down');
else if (player.getX()==1) me.move('right');
else if (player.getX()==2) me.move('up');
else me.move('left');
13.robotMaze
这次是随机迷宫,只能用走迷宫的摸墙大法了:左手永远贴住墙,顺着走就能出去。实践起来控制方向就是两个原则:左侧有缺口就左转,撞墙就右转。等等,没全局变量怎么控制方向?额……把@的颜色当成变量好了,#f01 #f02 #f03 #f04当做四个方向,走起来看不出颜色变化所以不会花眼>_<
var player=map.getPlayer();
if (player.getColor()=='#0f0') player.setColor('#f01');
var dir;
if (player.getColor()=='#f01') dir='right';
if (player.getColor()=='#f02') dir='down';
if (player.getColor()=='#f03') dir='left';
if (player.getColor()=='#f04') dir='up';
if (dir=='right' && me.canMove('up')) {
player.setColor('#f04'); dir='up';
} else if (dir=='down' && me.canMove('right')) {
player.setColor('#f01'); dir='right';
} else if (dir=='left' && me.canMove('down')) {
player.setColor('#f02'); dir='down';
} else if (dir=='up' && me.canMove('left')) {
player.setColor('#f03'); dir='left';
} else if (!me.canMove(dir)) {
if (dir=='right') {player.setColor('#f02'); dir='down';}
else if (dir=='down') {player.setColor('#f03'); dir='left';}
else if (dir=='left') {player.setColor('#f04'); dir='up';}
else if (dir=='up') {player.setColor('#f01'); dir='right';}
}
me.move(dir);
后来想了一下,貌似前两关也可以写一个这玩意啊
14.crispsContest
玩了半天机器人拿到三把钥匙就为做这个解密游戏?我不看代码都知道规则,不就是对应颜色开门拿了A再进出口……唉?貌似无解?仔细看看代码发现又是填空题……
大体路径是左上->上左->上右->右上->下右->下左->回中场,过关,发现绿钥匙不够,刚好我们可以在开绿门的时候扔掉其它东西……什么颜色的钥匙呢?其实,这种连算法都被扔掉了的填空题就是脑筋急转弯而已——哪种钥匙都不扔,就扔掉算法theAlgorithm好了……反正最后才拿在手里
15.exceptionalCrossing
淹死是注定的么……只能选死法?如果能让我选一个死掉的姿势,一定要选一个最最最奇葩根本摆不出来的造型,这样是不是就能免死了呢?
把各种重复创建违背数量限制的语句往里塞,填入map.placePlayer(0,0)的时候,发现没办法重复创建玩家所以函数崩了……player.killedBy()不能正常运行……
16.lasers
又是走两步挂掉的节奏,看这次定义了啥?线,激光,不同颜色的激光,@和非同色激光碰撞就会挂掉。可以看到绘制激光线的语句没有调整颜色,改一下
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();
if (player.getColor()=='red') player.setColor('teal');
else if (player.getColor()=='teal') player.setColor('yellow');
else player.setColor('red');
});
17.pointers
乱死了,一堆传送门和陷阱,传送门要么成对互相直达,要么单向送到一个陷阱上带你走……空白留在了两个物体建立传送关系的循环里,结合上一关很容易想到给每一对传送画一条连线……
额,实际结果是图乱的要死,而且不一定有从起点到终点的通路,不是不行,只是我们还有更好(坑爹)的方法:
利用object.getX()和object.getY()可以直接确定每一个门的……因为位置可以数格子输出来。直接循环所有的动态物体,找出位于@出生点附近和出口附近的一对传送门,直接把它们连起来就好。什么?重复循环低效?循环不是干这个的?反正这样省人力省眼睛,程序让它慢慢跑吧
var p1,p2;
for (var j=0; j < teleportersAndTraps.length; j++) {
var tmp=teleportersAndTraps[j];
if (tmp.getX()==4 && tmp.getY()==3) p1=tmp;
}
for (var j=0; j < teleportersAndTraps.length; j++) {
var tmp=teleportersAndTraps[j];
if (tmp.getX()==42 && tmp.getY()==20) p2=tmp;
}
p1.setTarget(p2); p2.setTarget(p1);
18.superDrEvalBros
超级玛丽……有重力下落所以要做一个按Q的跳跃函数,至少书面看起来是这样的。实际做的时候发现timer很难用,简单的45ms一次向上移动变成了原地抽搐而且不接受前进指令……一气之下直接按Q打电话造了对传送门……哦听说你喜欢玩重力是吧?我传送到出口正上方然后掉下来给你点存在感如何?
var y=fl(h/2)-1;
map.placeObject(5,y,'teleporter');
map.placeObject(49,y-10,'teleporter');
var tp=map.getDynamicObjects();
tp[0].setTarget(tp[1]);
tp[1].setTarget(tp[0]);
19.documentObjectMadness
额好吧,没明白左边是干啥的,右边也没看。乱搞按住上箭头保持若干秒,下一关……
20.bossFight
打boss了,还是弹幕游戏……注意到子弹有个projectile属性是之前没出现过的,查API发现这个属性的物体可以摧毁所有dynamic类型的物体却不能摧毁其它物体——这就是子弹无法穿墙的原因。看出口条件是要携带算法A和电话,A是boss掉落,而且有判断不能创建……那么要想一个办法把boss干掉,仿照子弹做一个projectile属性的物体比如从左到右发射就可以给boss制造一波团灭了。发弹要用到电话,那么首先要去拿,扭过子弹去拿是不现实的,这里要利用子弹不摧毁非dynamic物体的特性,在中央空旷区域弄一个屏障(墙的数量被限制了可以自己定义新墙,也可以用之前出现过的tree),注意不要封死。
map.defineObject('kb', {
'type': 'dynamic',
'symbol': '.',
'color': '#00f',
'interval': 100,
'projectile': true,
'behavior': function (me) {
me.move('right');
}
});
for (var x = 3; x < map.getWidth()-3; x++) {
map.placeObject(x, 9, 'tree');
}
map.getPlayer().setPhoneCallback(function () {
map.placeObject(1, 5, 'kb');
map.placeObject(1, 6, 'kb');
});
好吧其实我想吐槽,这关真正的难点不是画盾打boss啊,按一下键半分钟之后才开始移动玩个蛋……卡的飞起,这么简单的流程走走就要5分钟……
21.endOfTheLine
这个……怎么说呢,menu旁边多了个加号,点开发现啥都可以改>_<关卡程序不能改什么的已经不能阻止我们了……因为多了一个map.finalLevel = true使得出口失效,去翻翻出口定义发现一个失效特判,删掉就行了
游戏挺好的……//通了还有几个bonus关,有点不明所以,挖个坑等填好了……
bonus关也不好评价难度吧,还是挺有意思
01.inTheDesert
不允许修改T_T看看就发现那个激光-会被眼球E无效化,所以要先了解E的行动方式。menu已经可以看全部代码了,翻翻发现objects.js中写出来离E太远会挂掉(8格),同时E的行动函数followAndKeepDistance规定了@在左右3格上下1格的范围内时不进行移动,换言之就是有个追踪盲区
总之嘛眼球E的智商超级低在它身边平移的时候各种发呆,溜着玩两圈把它带到激光上再带出来溜两圈自己进去就过了
02.theEmptyRoom
门口作机智问答,答对才给通过,很容易发现生成答案的方法,那么第一反应就是应答函数复制答案的生成方法。可惜,也许是游戏bug也许是有意为之,花括号一大长串的东西每次只能复制很短一段出来,那么要复制全就要NNN次,即使只需要15-65这些下标复制的工作量也很多……观察发现下花括号里面的数字满足斐波那契数列的加和关系(是否是斐波那契数列的项没有验证也不需要关注),所以重新构造一次数组再输出就好了
var f={0:987,1:610}; input-=14;
for (var i=3; i<=input; i++) f[i&1]+=f[(i&1)^1];
return f[input&1];
03.theCollapsingRoom
空旷的房间越走墙砖越多,还经常一块砖刷脸上直接挂掉……粗略看一下是那个rainmaker在(1,1)乱搞,想个办法弄没它,没有删除函数就只能借助特性了:dynamic类型的物体会被带有projectile属性的东西摧毁。定义一个rainkiller具有projectile,也放左上角让它走过去把rainmaker秒掉就行了(其实是一换一,应该起名叫7的)
map.defineObject('rainkiller', {
'type': 'dynamic',
'symbol': 'k ',
'projectile': true,
'behavior': function(me) {
me.move('left');
}
});
map.placeObject(2, 1, 'rainkiller');
04.theGuard
这个不需要修改代码,利用风骚的走位即可过关……让低智商的E卡住d就成,具体流程如下:
先向左上走几步,到这样(类似这样,离E不要太远):
d
@
E
先走到E靠上一条线,d会追着自己:
d
@
E
然后平移到E右侧线上,E会发呆:
d
@
E
向下走两步再向右走1步,E发呆,d被E卡住之后只能向右移动1步
d
E
@
向左走3步,会被d贴到但是不会挂
E
@d
再向上走1步,E不动d被卡也不动
@E
d
这时候相对位置变成了@在出口和d之间,只要不作死就一定能安全走到出口
pushme
推到我呀>_<只能添加一个属性……就填个'pushable': true之后各种拆墙穿墙各种浪把d全引出来再穿墙甩掉它们进去过关……多试几次吧
trapped
自己走走发现有的箱子可以推动,有的是陷阱,因为留空太自由了所以根本没看代码开了一对传送门……
map.placeObject(3,12,'teleporter');
map.placeObject(45,12,'teleporter');
var dy=map.getDynamicObjects();
var p1,p2;
for (var i=0; i<dy.length; i++) {
if (dy[i].getX()==3 && dy[i].getY()==12) p1=dy[i];
if (dy[i].getX()==45 && dy[i].getY()==12) p2=dy[i];
}
p1.setTarget(p2);