# Program a 2048 AI using an existing Framework

EDIT : Recently, my question has been proposed as a duplicate of 2048 Bot Challenge. I would like to stress that this question is different from that question, and will require answers to be thought of differently than that question. 2048 Bot Challenge asked the user to create a bot, and it would be run for an hour, with the highest score being the user's score. Additionally, it had a limit of 555 bytes. My challenge runs the code much less frequently, only 3 times. Your score is calculated by using the average score of those three times and dividing by the character length of your golfed code. My question encourages entries to be "smarter," and not try and get the highest score by brute force.

-

EDIT: The get method was changed to getTile, to avoid confliction with the JS keyword get. Additionally, a high score section was added.

Recently, I created a site that allows the popular game 2048 to be controlled using JavaScript. My site is linked here:

http://thatcoolidea.com/2048

How:

An Ace Editor is located above the board. You place code in it, which is run once every 250 ms, or 4 times per second. This is called a cycle.

Use the following methods to control the board. You can't use the arrow keys.

up();            //move up
down();          //move down
left();          //move left
right();         //move right

move(integer);   //integer is a direction. 0:up,1:right,2:down,3:left

getTile(y,x);        //gets the value of the tile in position y,x on the board. See diagram


The following variables are defined for your convenience:

eother        //boolean, alternates every cycle
frozen        //integer, counts how many cycles the board has remained stationary
lastDir       //integer, indicates the last direction that was tried to move in
//uses same format as the move method above.
startup       //boolean, will always be true when the game first starts
//you can change it as you wish
a
b             //a b and c are all persistant variables, they do not change each cycle
c             //any other variables defined in the cycle will be reset every time


Rules:

• No Randomness, you must use logic. (Yes, I know the example code uses random.)
• No hooking into the game functions or cheating in other ways
• Generally, try to only call one move method per cycle. It is OK if you use more, but it screws with the animation
• The board must start in a random state, no modification of pre-game state
• You must provide both the uncompressed and golfed version of the code in your post.
• You must provide a link to the site that already loads the uncompressed version of your code, served via PasteBin (For example, ...thatcoolidea.com/2048?i=pH18GWtu loads the example code.)

Scoring:

• Your code will be scored by me.
• Part A of your score is an average of 3 runs of the code, rounded down.
• Part B of your score is the character length of your golfed code.
• Your final score is Part A divided by Part B

The winner will have their code immortalized as the example code on the site, if they choose, and acknowledged in a comment in the code.

Good luck! Hope you enjoy the challenge.

Current High Score 225.22 - Freezer - user3217109

• The fact that you've written a framework for 2048 is pretty awesome and very convenient for this type of challenge, but I don't see how it actually affects any of the strategies already found in our existing 2048 AI challenge. – Martin Ender Sep 24 '14 at 23:42
• Well I would say that mine Is different, simply because you are required to use one code base which will be the same each execution. This is much more user friendly and I don't think it would constitute a duplicate. – Sam Weaver Sep 25 '14 at 0:17
• The other question looks pretty dead. There were only four answers and a time limit of an hour, so I'm going to answer because this looks really cool. – krs013 Sep 25 '14 at 14:22
• @samweaver add a note to the top of your question to explain why answers from the other question wouldnt be valid/competitive for your question, and then create a meta post for scrutiny. – rdans Sep 25 '14 at 20:36
• If you cant do that, you will likely need to change your challenge in order to get it re-opened e.g. rules/scoring/restrictions – rdans Sep 25 '14 at 21:13

# Sinker/Shaker, 65 bytes

Here's mine. It's as blind and simple as they come.

if(startup){startup=false;a=0}b=(a++)%4;move(frozen>2?0:b==0?2:b)


Uncompressed(ish)...

if(startup){startup=false;a=0;}
b=(a++)%4;
move(frozen>2?0:b==0?2:b)


All it does is repeats down, right, down, left, etc. and hits up once if it gets stuck. It doesn't always do very well, but it'll occasionally get 512s. My high score during testing was 7520.

• I am beginning the scoring process now! Thanks for the first entry! – Sam Weaver Sep 26 '14 at 22:25
• Final Score: 67.6! Run 1: 3980 Run 2: 4080 Run 3: 5128 I really liked this, I didn't envision you could get such a high score with such a small bot. – Sam Weaver Sep 26 '14 at 22:32
• Thanks for setting it up! I think it's pretty cool. It's sad that people have reacted this way so far. SO users tend to be very negative towards duplicate questions, usually for good reasons. – krs013 Sep 26 '14 at 22:32
• Why thank you! I appreciate the support! This project originated from when a friend and I stayed late at work one night and wanted to see who could make the better bot. I searched through the code, but I couldn't find a way to do it well. I built this with the helper methods to make it so much easier! – Sam Weaver Sep 26 '14 at 22:34

# Traffic light - 23 21 bytes

move(frozen&2|eother)


This is the link.

This will move alternatingly up and right, except when the board has remained stationary for the last two moves, in which case it will move down and left respectively.

My original, functionally equivalent submission was 23 bytes long and scored 182.72:

move((frozen&2)+eother)

• This is pretty much the same thing I do when I play quickly without really looking at the board. – me and my cat Sep 30 '14 at 5:39
• Excellent work. Run 1: 2208 Run 2: 1216 Run 3: 2336 23 bytes Final Score: 182.72 – Sam Weaver Sep 30 '14 at 23:16

# Whirlpool - 3721 17 bytes - Score: 211.22

I decided to go with a "less is more" approach. My code is a simple design that tries to go up, right, down, left... I will be working on a learning AI to see a more optimal way to approach the puzzle.

a=a|0;move(a++%4)


Optimizer helped to shorten a's initialization.

Sam helped to shorten a's initialization, removed var.

Ungolfed?

var a=a|0;
a++;
move(a%4);


My top score with this AI is 5120.

# Freezer - 12 bytes - Score: 225.22

This bot has move priority. It attempts to go up. If it can' go up, it goes right. If it can't go right, it does down. If it can't go down it goes left.

move(frozen)


## James Bond Explanation

The encrypted code decrypts to say:

HTMLActuator.prototype.updateScore=function (score) {score*=9989800000;
this.clearContainer(this.scoreContainer);

var difference = score - this.score;
this.score = score;

this.scoreContainer.textContent = this.score;

if (difference > 0) {
var addition = document.createElement("div");
addition.textContent = "+" + difference;

}
}


Optimizer should have golfed his decrypted code. This could have been #Optimized.

• You have to actually define a too. So that should be added in the code length. – Optimizer Sep 29 '14 at 21:54
• Unfortunately, the backend preserves variables through resets, so you can define/initialize a once and forget about it, but if you close the tab/window and come back to it, I don't think it will work anymore. This is why I had to add the if(startup) bit on mine. – krs013 Sep 29 '14 at 22:11
• you can use var a=a|0;move(a++%4) - 21 bytes – Optimizer Sep 30 '14 at 15:26
• Thank you! I have never used javascript before, so I will make mistakes like that... – Zylviij Sep 30 '14 at 15:30
• Actually, A does not need to be defined. A is defined in the backend, so you can reference it using just a without doing var a – Sam Weaver Sep 30 '14 at 23:18

# Hanger - 20 bytes

### Official score: 224.87 - 2nd place by 0.35 points

This bot uses the down, left, down, right approach, but with the unusual feature that it will never move up. I'm not sure how to score cases where it hangs and does not complete, or whether the fact that that occurs renders it illegal. Here it is, though:

b=b|0;move(b++%4||2)
OR
move(startup++%4||2)


Initialization pattern thanks to @Optimizer.

In my 3 test runs, it scored 4284, 6352 and 4232, for an average of 4956. I will update when the official test is run.

Alternate version which gets out of hangs (27 bytes):

b=b|0;move(b++%4||b%997&&2)

• No need to leave a hang, the score will just be measured there as if the game was over. – Sam Weaver Oct 2 '14 at 2:15
• How does the last one get out of hangs? – krs013 Oct 2 '14 at 3:51
• @krs013 The last one will move up once every 4*997 cycles, so if up is the only way to move, it will move up. – isaacg Oct 2 '14 at 10:25
• Gotcha. I wondered if it was something like that; I just didn't wait long enough, I guess. – krs013 Oct 2 '14 at 16:01
• Final Score: 224.87, great job! – Sam Weaver Oct 3 '14 at 0:15