2048

Fri 18 July 2014
By exco
  • Solved by: exco, ttb
  • Writeup Author: exco

Introduction

The task was to connect to some ip port 2048 with nc $ nc 2048 and solve 2048, the game in less than 6 minutes. The time was later reduced to 3.5 minutes.

2048 on that server looked roughly like this:

2048 bash example

u = up d = down l = left r = right

My first thought was to go find some code that solved 2048 and then either port it to bash or think about it some more.

So what google threw at me was http://ov3y.github.io/2048-AI/ and the repository: https://github.com/ov3y/2048-AI

nice

Some more googling and I found a node netcat package: https://www.npmjs.org/package/node-netcat

Almost done ;-)

ttb then joined me and like 5 hours later we had our automatic 2048 solver. In our defense - we both never used node before and ended up just dumping all the functions from 2048-AI in a single file (not knowing how to properly load js files with node).

Coding/Automation:

start:

put all returned data in the my2048 variable

    my2048 = data;

split the lines at \n (newline)

my2048_lines = my2048.toString('ascii').split('\n');

work some more (ugly) magic to get a 2-dim my2048arr with all the numbers

for (i=my2048_lines.length-6; i<my2048_lines.length-2; i++) {
 my2048arr [i - my2048_lines.length+6] = my2048_lines[i].trim().split(' ');
 for (j=0; j<4; j++) {
  if (my2048arr [i - my2048_lines.length+6][j] == '.') {
  my2048arr [i - my2048_lines.length+6][j] = '0'}
 my2048arr [i - my2048_lines.length+6][j] = parseInt(my2048arr [i - my2048_lines.length+6][j], 10);
 }
}

Instantiate a grid for the 2048-AI and fill it with our 2048 array.

this.grid = new Grid(4);

for (i=0; i<4; i++) {
 for (j=0; j<4; j++) {
 var tile = new Tile(this.grid.randomAvailableCell(), my2048arr[i][j]);
 tile.x = i;
 tile.y = j;
 if (my2048arr [i][j] > 0) {
  this.grid.insertTile(tile);
 }
}

Start the solver

this.ai = new AI(this.grid);

What we bruteforced was the transformation from our 2048 matrix to the 2048-AI one - because when we first got the script to do what we wanted we always got stuck after a while but without the game being lost - so we figured the AI was working with a different matrix orientation.

//  0: { x: 0,  y: -1 }, // up
//  1: { x: 1,  y: 0 },  // right
//  2: { x: 0,  y: 1 },  // down
//  3: { x: -1, y: 0 }   // left

var myMove = ['l', 'd', 'r', 'u'];

get the best move from the AI:

var nowMove = this.ai.getBest().move;

send that move to the server:

client.send(myMove[nowMove] + '\n');

The whole dirty solution can be found here: 2048 automatic bash solver