15
\$\begingroup\$

I am applying to a university to study Computational Linguistics, and as I read, it would be recommended to have a background in Artificial Intelligence.

The Admission board asked me to prepare a portfolio of my works, and I am considering to add this solution to the portfolio.

I have been lazy to develop an AI to bypass the default obstacles, so I added mine to ease the movement of the robot.

 /*
 * robotNav.js
 *
 * The green key is located in a slightly more
 * complicated room. You'll need to get the robot
 * past these obstacles.
 */

function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

function startLevel(map) {
    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) {
            for(i = 2; i<9; i++){
                map.placeObject(map.getWidth() - 20, i, 'block');
            }
            for(i = 2; i<9; i++){
                map.placeObject(map.getWidth() - 3, i, 'block');
            }
            if(me.canMove('down') && !me.canMove('left')){
                me.move('down');
            }else{
                if(me.canMove('right') && !me.canMove('down')){
                    me.move('right');
                }
                if(me.canMove('up') && !me.canMove('right')){
                    if(me.canMove('left')){
                        me.move('up');
                    }else{
                        me.move('down');
                    }

                }
                if(!me.canMove('up') && me.canMove('right')){
                    me.move('right');
                }
                if(!me.canMove('up') && !me.canMove('right')){
                    me.move('down');
                }
            }
        }
    });

    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 Solution is to the quiz #12 in Chapter 2 of Untrusted Game.

What I mean by ethical is that am I allowed to cheat my way out in the AI world, or am I required to solve the problem as it is without additions (the additions here are the two added walls).

EDIT:

Here is the default setup of the scene:

default scene

And here are my changes:

my solution

The '@' is the player, the small blue rectangle in the bottom-right corner is the goal, 'R' is the robot that must be programmed (it moves once the player moves), 'K' is the goal for the robot it also is the key that allows the player to open his goal, the robot must reach the key and move through the portal under it (no human is allowed to pass it) and provide the key to the player so he can win the quiz.

Another thing is that I am only allowed to edit the behaviour of the 'robot' object (at line 24).

'behavior': function (me) {....}
\$\endgroup\$
9
  • 3
    \$\begingroup\$ Re ethics: this game encourages cheating. I very much like the idea of placing additional barriers to guide the robot. This game requires creative thinking, but it's not good material for a resume: you didn't solve the problem with any kind of AI. \$\endgroup\$
    – amon
    Apr 8, 2014 at 17:38
  • \$\begingroup\$ @amon would you please guide me to an article/resource that would help me create the AI with only two variables from the environment ? possible directions are : up down left right, and I am only allowed to use canMove(direction) and move(direction), also for each step the player moves, the AI moves one step also (can't use move(left) and move(up) in the same step) \$\endgroup\$
    – SAFAD
    Apr 8, 2014 at 17:43
  • \$\begingroup\$ No, you can figure out the pathfinding yourself – this is Code Review, not a place for implementation help. Tips: You can use the player variable to store arbitrary state, e.g. via an object. The robot can erect barriers to seal off dead ends. \$\endgroup\$
    – amon
    Apr 8, 2014 at 18:02
  • \$\begingroup\$ You are forgetting how js works... all you need to do is create a closure and you can have all the variables you want, you just need one place to store it and you have that. \$\endgroup\$
    – Hogan
    Apr 8, 2014 at 19:22
  • 1
    \$\begingroup\$ Heh, I just set the robot to duplicate my movements keeping a bit of y distance. No AI of any kind, just I :) \$\endgroup\$
    – Flambino
    Apr 8, 2014 at 19:27

8 Answers 8

23
\$\begingroup\$

I'm one of the developers of Untrusted (neunenak). Your solution is completely ethical/fair/okay. The whole idea behind the game was that the player could write whatever code they needed to be able to progress to the next level. We do have a lot of code in the game's framework designed to make really easy and uncreative solutions impossible, but that's just to try to force the player to think creatively - if the code you wrote lets you get Dr. Eval to the next level, it's all good. After all, in the real world you don't get more points for writing a complicated AI when a shell script solves your actual problem just as well!

Thanks for playing the game by the way! We're glad you're enjoying it :)

\$\endgroup\$
1
  • 10
    \$\begingroup\$ I have played many javascript games like this (Javascript RPG anyone?), but I was never attached and emotionally involved to any of them like this one, I have spent hours reading the code and solving my way out. Sir, you deserve a beer, and a high five :) \$\endgroup\$
    – SAFAD
    Apr 8, 2014 at 20:52
5
\$\begingroup\$

From a quick review:

  • As @Amon said, I would not use this for your portfolio, especially if you are cheating
  • You have 0 comments in your code, even for a fake AI that is not good enough
  • Instead of all the ifs and else I would build a rules table, the logic would go through each entry, see if a condition evaluates to true, and then perform the action.
  • I don't see any style problems, so that's good

I got out with this:

    this.direction = this.direction || 'down';

    var moves = {
      'down' : [ 'left' , 'down' , 'right' , 'up' ],
      'right': [ 'down' , 'right' , 'up'   , 'left' ],
      'left' : [ 'up' , 'left' , 'down' , 'right' ],
      'up'   : [ 'right' , 'up' , 'left' , 'down' ]

    }, 
    move = moves[this.direction];

    if( me.canMove( move[0] ) )
      this.direction = move[0];
    else if ( me.canMove( move[1] ) )
      this.direction = move[1];  
    else if ( me.canMove( move[2] ) )
      this.direction = move[2];            
    else  
      this.direction = move[3];


    me.move( this.direction )

Obviously the access to each movement option could have been handled with a loop, but you get the gist.

\$\endgroup\$
2
  • \$\begingroup\$ I mostly use arrays to store the logic for bigger programs, but as these took less than a minute to solve, I just stick to if else :) \$\endgroup\$
    – SAFAD
    Apr 8, 2014 at 19:58
  • \$\begingroup\$ Sure, but I think your portfolio deserves better ;) \$\endgroup\$
    – konijn
    Apr 9, 2014 at 13:07
4
\$\begingroup\$

Right hand wall walk is not that hard to code (kept it simple so my son could understand it):

    if(me.vars === undefined)
    {
        me.vars = 1;
        me.facing = 0;    
        me.direction = Array ('up','right','down','left','up');            
    }

    if(me.canMove(me.direction[me.facing+1]))
    {
        me.facing++;
    }
    else if(me.canMove(me.direction[me.facing]))
    {

    }
    else
    {
        me.facing--;
    }


    if(me.facing < 0)
    {
        me.facing = 0;
    }
    if(me.facing > 3)
    {
        me.facing = 0;
    }

    me.move(me.direction[me.facing]);
\$\endgroup\$
2
\$\begingroup\$

There is better 'unethical' solution - works for 12th and 13th level

        map.defineObject('xxx', 
        {
            'type': 'static',
            'symbol': 'X',
            'color': '#0f0',
            'onCollision': function (player, game) {
                game.addToInventory('greenKey');
            }
        });
        if(!me.xx){
            map.placeObject(20, map.getHeight() - 1, 'xxx');
            me.xx=true;
        } 
\$\endgroup\$
1
\$\begingroup\$

I knew my solution was not the expected one, but it worked for several stages before this one, so the code was written and just had to change the directions. The solution was to trigger set directions with the phone, using player color swaps.

var player = map.getPlayer();
player.setPhoneCallback( function(){
    if(player.getColor()=='#0f0'){
        player.setColor('#f0f');
    }else if(player.getColor()=='#f0f'){
        player.setColor('#00f');
    }else if(player.getColor()=='#00f'){
        player.setColor('#0ff');
    }else{
        player.setColor('#f00');
    }
});
if(player.getColor()=='#0f0'){ me.move('down'); }
if(player.getColor()=='#f0f'){ me.move('right'); }
if(player.getColor()=='#00f'){ me.move('up'); }
if(player.getColor()=='#0ff'){ me.move('right'); }
if(player.getColor()=='#f00'){ me.move('down'); }
\$\endgroup\$
1
\$\begingroup\$

My solution for robots is control them by player position like this:

       if(  player.atLocation(3, map.getHeight() - 2))
         me.move('left');
       if(  player.atLocation(5, map.getHeight() - 2))
         me.move('right');
       if(  player.atLocation(4, map.getHeight() - 3))
         me.move('up');
       if(  player.atLocation(4, map.getHeight() - 1))
         me.move('down');
\$\endgroup\$
1
\$\begingroup\$

Yeah, for this level it's up to you.

For instance, you made an AI for your robot. I did a remote control for mine.

        if (player.getX() == 0) {
        me.move('left');
        } else if (player.getX() == 1) {
        me.move('right');
        } else if (player.getX() == 2) {
        me.move('down');
        } else if (player.getX() == 3) {
        me.move('up');
        }

Choose your robot direction with player's X position. Move your robot by walking player along Y axis.

\$\endgroup\$
0
\$\begingroup\$

I can't reply to the answer itself, but https://codereview.stackexchange.com/a/46978/41528 doesn't actually solve the problem; it moves the Robot in a square (right, down, left, up) because:

1) 'up' and 'down' were reversed.

2) The direction was improperly reset when it went past the array bounds.

A working wall-walk for lefties AND it delivers the key to the player (for this particular puzzle):

if(me.vars === undefined)
{
    me.vars = 1;
    me.facing = 0;    
    me.direction = Array ('down','right','up','left','down');            
}

if(me.canMove(me.direction[me.facing+1]))
{
    me.facing++;
}
else if(me.canMove(me.direction[me.facing]))
{

}
else
{
    me.facing--;
}


if(me.facing < 0)
{
    me.facing = 3;
}
if(me.facing > 3)
{
    me.facing = 0;
}

me.move(me.direction[me.facing]);
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.