Come posso convincere questo robot a finire il labirinto?

Al livello 13, il robot si trova in alto a sinistra in un labirinto generato casualmente. Come posso fargli get la chiave blu e darmela?

La mia soluzione era ancora un'altra: ho creato una mappa di riempimento di piena nella prima posizione mappando le posizioni nella direzione verso l'output.

In questo modo, si ottiene solo un ritardo di calcolo sulla prima mossa e tutte le mosse successive sono veloci e il robot è garantito per farlo senza wherer rigenerare il labirinto.

 function getMove(me) { if (me.getY() > 9) return ''; return me.floodPath[[me.getX(), me.getY()]]; } if (!me.floodPath) { me.floodPath = {}; var rcol = map.getWidth() - 2; var directions = ['up', 'down', 'left', 'right']; var opposites = { up: 'down', down: 'up', left: 'right', right: 'left' }; var diffs = { up: [0, -1], down: [0, 1], left: [-1, 0], right: [1, 0] }; // Init floodPath with a path across the barrier me.floodPath[[rcol, 10]] = 'down'; me.floodPath[[rcol, 9]] = 'down'; me.floodPath[[rcol, 8]] = 'down'; var iterEdges; // Init edges with the key var edges = [[rcol, 8]]; function addDiff(pos, dir) { var dif = diffs[dir]; return [pos[0] + dif[0], pos[1] + dif[1]]; } console.log('hi'); // This will terminate as soon as the flood-fill reaches the starting position while (!getMove(me)) { iterEdges = edges.slice(0); // edges.clone(); edges = edges.slice(edges.length); // edges.clear(); iterEdges.forEach(function(pos) { directions.forEach(function(dir) { var nextPos = addDiff(pos, dir); if (me.floodPath[nextPos]) return; if (map.getObjectTypeAt(nextPos[0], nextPos[1]) != 'empty') return; edges.push(nextPos); me.floodPath[nextPos] = opposites[dir]; }); }); } console.log(me.floodPath); } me.move(getMove(me)); 

Piuttosto che creare una IA semplice, è molto più semplice fare in modo che il robot rispecchi i tuoi movimenti usando il seguente codice:

 if(me.getY()>map.getPlayer().getY()-9) me.move('up'); else if(me.getY()<map.getPlayer().getY()-9) me.move('down'); else if(me.getX()>map.getPlayer().getX()) me.move('left'); else if(me.getX()<map.getPlayer().getX()) me.move('right'); 

Quindi spostati verso l'alto e verso sinistra finché il robot non rispecchia i tuoi movimenti. Guidalo attraverso il labirinto come se lo controllassi. Una volta che ha la chiave ed è fuori, muovi a destra, e vai fino in fondo per scontrarti con la R e prendi la chiave.

Il labirinto *

* Nota che il tuo labirinto sarà probabilmente diverso, ma guidare il robot è semplice quando i suoi controlli corrispondono ai tuoi.

Non hai bisogno di un'intelligenza artificiale per risolvere il problema. Usa semplicemente una semplice strategia "abbraccia il muro alla tua destra" e puoi sfuggire a qualsiasi labirinto. Ci vuole semplicemente un po 'di più.

  var dirs = ['left', 'up', 'right', 'down']; if(map.rdir === undefined) map.rdir = 0; // The good old hug-the-wall-to-your-right algorithm var trythese = [map.rdir + 1, map.rdir, map.rdir - 1, map.rdir + 2]; for(var i=0; i<4; i++) { var d = (trythese[i] + 4) % 4; if(me.canMove(dirs[d])) { me.move(dirs[d]) map.rdir = d; break; } } 

Nota che sto memorizzando una properties; extra sulla map ( map.rdir ) per fare ciò. Ciò è totalmente consentito poiché JavaScript consente l'uso di properties; arbitrarie sugli oggetti.

Ho pensato che sarebbe stato molto più divertente scrivere un'intelligenza artificiale, così l'ho fatto. Ecco un semplice algorithm di individuazione dei routes che completerà tutti i labirinti dei robot.

 var getMoveToward = function(x, y) { var pointsEqual = function(p1, p2) { return p1[0] == p2[0] && p1[1] == p2[1]; } var curPoint = [me.getX(), me.getY()]; var targetPoint = [x, y]; var marks = {}; var pointString = function(p) { return p[0].toString() + ',' + p[1].toString(); } var markPoint = function(p) { marks[pointString(p)] = true; } var isPointMarked = function(p) { return marks[pointString(p)] == true; } var getUnmarkedMoves = function(d, p) { var offsetList = { 'left' : [-1, 0], 'right' : [1, 0], 'up' : [0, -1], 'down' : [0, 1] } var unmarkedMoves = [] for (var dir in offsetList) { var offset = offsetList[dir]; var movePoint = [p[0] + offset[0], p[1] + offset[1]]; if (map.getObjectTypeAt(movePoint[0], movePoint[1]) != 'block' && !isPointMarked(movePoint)) { unmarkedMoves.push([d == null ? dir : d, movePoint]); markPoint(movePoint); } } return unmarkedMoves; } markPoint(curPoint); var moveStack = [[null, curPoint]]; while (moveStack.length > 0) { var move = moveStack[0]; moveStack.shift(); if (pointsEqual(move[1], targetPoint)) { return move[0]; } else { moveStack = moveStack.concat(getUnmarkedMoves(move[0], move[1])); } } return null; } var move = getMoveToward(map.getWidth()-2, 10); if (move != null) { me.move(move); } 

Disclaimer: Probabilmente è molto lontano dalla soluzione prevista, ma è ancora uno.

Approfitta del fatto che un labirinto viene generato casualmente.

Grazie al modo in cui il labirinto viene generato, c'è una possibilità molto affidabile che riavviando il labirinto solo poche volte, in uno di quei labirinti, il codice semplice

 if(me.canMove('down')) me.move('down'); else me.move('right'); 

è abbastanza per far uscire il robot dal labirinto.

Avevo fatto praticamente la stessa soluzione di nneonneo, solo un po 'diversa nella formattazione:

 // Implement the right-hand rule for maze solving. if (me.facing === undefined) me.facing = 'right'; var dirs = { 'right' : ['down', 'right', 'up', 'left'], 'down' : ['left', 'down', 'right', 'up'], 'left' : ['up', 'left', 'down', 'right'], 'up' : ['right', 'up', 'left', 'down'] } var choices = dirs[me.facing]; for (var i = 0; i < 4; i++) if (me.canMove(choices[i])) { me.move(choices[i]); me.facing = choices[i]; } 

Invece di gestire il labirinto, perché non eliminarlo del tutto? Ho chiuso la chiamata defineObject , quindi ROT.Map.DividedMaze ridefinito ROT.Map.DividedMaze modo che la create non facesse nulla.

 map.defineObject('robot', { 'type': 'dynamic', 'symbol': 'R', 'color': 'gray', 'onCollision': function (player, me) { me.giveItemTo(player, 'blueKey'); }, 'behavior': function (me) { // user code begins } }); ROT.Map.DividedMaze = function() { this.create = function(){} }; (function () {{ // end of user code } }); 

Facciamo hacker e non disturbare il labirinto …

  player.hasItem = function(item) { return true; } ; 

È anche ansible ridefinire defineObject per rendere passabile la barriera prima di call l'originale, quindi andare a prendere la chiave da soli.

Ho usato il field come controller

 if(player.atLocation(1, 24)) { me.move('down'); } if(player.atLocation(1, 23)) { me.move('up'); } if(player.atLocation(1,22)) { me.move('right'); } 

vai all'output e a destra. 3 ° dal basso è righ, 2 ° è alto e il più basso è giù.

AI? Ha!

  'behavior': function (me) { me.move(robodir); } }); var robodir = "right" player.setPhoneCallback( function () { if (robodir=="right") { robodir="down"; } else if (robodir=="down") { robodir="left"; } else if (robodir=="left") { robodir="up"; } else if (robodir=="up") { robodir="right"; } }) map.defineObject('null', { 'behavior' : function () { 

Il behiavor del robot ora lo sposta lungo la direzione memorizzata in robodir each volta. L'triggerszione del telefono cambia quella direzione. Banale!

semplicemente, basta che il robot lo trovi, puoi sempre valutare prima il path e poi camminare, ma questo percorre solo il robot:

 if(!me.g){ me.g=0; me.dir=[['right',0,-1],['up',-1,0],['left',0,1],['down',1,0]]; } move=function(){ x = me.getX()+me.dir[me.g][1]; y = me.getY()+me.dir[me.g][2]; if(map.getObjectTypeAt(x, y)!='block')me.g=(me.g+1)%4; else if(!me.canMove(me.dir[me.g][0]))me.g=(me.g+3)%4; me.move(me.dir[me.g][0]); } if(me.getY()<10)move(); 

la cosa divertente è che puoi eseguire qualsiasi metodo, anche quelli bloccati, basta usarlo, questo probabilmente verrà risolto in futuro ma per ora sembra che abbiano lasciato una backdoor per tutti:

 map._display.game._setPlayerCodeRunning(false); map._display.game.map._removeItemFromMap(map.getWidth() - 2, 9,'barrier'); 

HAHAHA

 'behavior': function (me) { player.setPhoneCallback(function() { color = player.getColor(); if (color == "#0f0") { player.setColor("#f00"); } else if (color == "#f00") { player.setColor("#00f"); } else if (color == "#00f") { player.setColor("#ff0"); } else if (color == "#ff0") { player.setColor("#0f0"); } }); color = player.getColor(); if (color == "#0f0") { me.move("right"); } else if (color == "#f00") { me.move("left"); } else if (color == "#00f") { me.move("up"); } else if (color == "#ff0") { me.move("down"); }