Hacker News new | past | comments | ask | show | jobs | submit login
2048 Solver (github.com/felixneutatz)
165 points by dubbel on March 26, 2014 | hide | past | favorite | 38 comments



I could be wrong here, but from my reading of the source this doesn't look like an A* search algorithm. For starters, the search space is nondeterministic, and since you can only explore in one direction, you're not really performing a search space exploration as much as choosing a direction and going with it.

Secondly, the implementation doesn't perform the combination of current state score and proposed state score that lies at the heart of the A* algorithm. Instead it takes the current state for granted (which, again, it must given the inability to backtrack) and chooses the available move with the largest score.

Thirdly, and I'm reaching a little here, I can't find any place where any heuristic is used to optimize search performance by pruning the search tree. The search space is brute forced on each iteration, and the entire tree is scored.

At the expense of seeming pedantic I suggest this is a greedy play algorithm rather than A*. You can be even more precise and call it a single-ply minimax.

Now that that's out of the way, I should temper my criticism with the fact that this implementation works. It's not algorithmically complicated because it doesn't have to be. It doesn't use any of the typical performance tricks because it doesn't need to. What it lacks in sophistication it makes up in "good enough."


Yes, true. I had the A* Algorithm in mind when I have implemented it, but the outcome really differs from that.


My first reaction was that Monte Carlo would be the way to go.


Seems like a great application for Monte Carlo tree search.


Check my AI for 2048 https://news.ycombinator.com/item?id=7474909

Only reach 8192, but with the game implemented in the right way :)


Show us your better solution! Thanks!



I forked the main 2048 repo and modified it so that you can write your own "brain" for it:

https://github.com/loisaidasam/2048

Essentially it communicates via an API to a webserver where you write your "brain" logic and respond to the API requests with which move to choose next:

https://github.com/loisaidasam/2048/blob/master/js/autonomou...

Since it's over web, you can write your webserver in the language of your choosing. I wrote a small dumb Python webserver using the Flask microframework:

https://github.com/loisaidasam/2048/blob/master/py/webserver...

And it simply returns a random direction:

https://github.com/loisaidasam/2048/blob/master/py/game.py

This can be adapted obviously for whatever logic you choose. The reason I forked this version and not a totally server-side one (which would be better for performance obviously) is that you can actually watch the moves this one makes as it chooses them, which makes it kinda fun.

Enjoy!


This is the most efficient version I was able to get: https://news.ycombinator.com/item?id=7475031


Hello everyone, I am currently taking a course in Artificial Intelligence and have been planning to implement the A* algorithm towards 2048. But seeing here that people believe that this isnt a "true" A* implementation, would the hackerNews community be interested in an actual working Javascript implementation of multiple AI methods? (i.e. having a dropdown selector for the method to use and implementation via a button)


This would be cool. Please don't just post the code though... Have a working, interactive 2048 game that runs your algorithm so I can watch it without doing anything. Not everyone here is a coding guy...


Yes, that'd be kind of cool.


Let me start by saying that I'm glad you ported this game to Java, it certainly increases the reach of the game and the number of people who can hack on it. You're also a really organized Java programmer, which makes it a lot easier for other people to build on what you made.

With that said, this Java implementation needs a lot of performance improvement. I made some trivial changes on it and benchmarked it at a significant speed boost, I'll send you my revisions on GitHub so you can take a look. Also, as another commenter mentioned, this isn't true A*, but good work nonetheless.

Here's a simple performance improvement: Java's ArrayList is just a wrapped array with two fields:

  private transient Object[] elementData;
  private int size;
When you initialize it, it initializes elementData to a null array of size of 10. When you put the 11th thing into the list, it creates a new array of size 15 (in general, a 50% increase), and copies references from the old array. This means that in your search, a board with 11 or more open tiles will trigger a resize. This is easily prevented by initializing the list with

  new ArrayList <Tile> (15)
Bam! One optional parameter, 9% runtime improvement. As the performance gets optimized you can search larger trees in less time.


If you're interested, I wrote a page to let you script your own AI for 2048 in javascript: xuanji.appspot.com/2048/


Thanks for your help! I will try it out :)


I would be curious to see a more detailed writeup of this, as I haven't understood how this algorithm is applied.

Question that I didn't understand the answer to:

> There are implemented 3 cost functions:

> 1. sum of all tiles in the playing field

is this a useful cost function at all? Surely the sum of the tiles is not affected by strategy played, only by whether a 2 or 4 was randomly received.

> 2. number of all unassigned tiles in the playing field

> 3. average value of an occupied tile

Then, for similar reason, I would be surprised if these were not equivalent.


You are right, the first cost function doesn't make a lot of sense, but I didn't divide by the number of leafs - so it basically also was based on the number of unassigned tiles.

So in the end you are right these approaches are more or less the same.


I'm afraid the implementation of the game here has a bug which makes it much easier than the original.

http://pastebin.com/VwwGCYYy


I will fix that, thanks for the info


Interesting work. I'd be curious to see this algorithm applied to the original game. Since this is a re-implementation of the game in Java, it may be solving a completely different game.


And indeed it is. A much easier game, unfortunately.


Question for AI people: is 2048 and interesting game to try different algorithms on and if so, why?


I'm not really an AI person, but I think it's interesting, yes:

Each individual decision is simple (choose from 4 directions), but the overall strategy is difficult (the arrival of each new piece has a random element).

The game tree[0] is awkward to draw in full, because of this random element. If we can draw it out well enough to analyse it, we can come up with a perfect play algorithm that wins as often as possible. Tic-tac-toe is 'solved' in this sense: we always know what the best play is.

Since 2048 remains unsolved (for now), AI algorithms which simplify and try to approximate that process come into play. As long as nobody has come up with perfect play, it's still interesting to see who can come up with the best play.

2048 is relatively simple game to remain unsolved, so it's nice and accessible to apply algorithms to (and still relevant to do so).

[0]https://en.wikipedia.org/wiki/Game_tree


FYI, for some reason your follow up question is hellbanned. Thought you'd like to know.


Thanks for sharing this. I may have missed this answer between all of the threads related to 2048, but has anyone found if there is a limit for the 4x4 tile size?


The highest tile you can get is 2^17, 131072. Each doubling of the tile size requires another extra space, as you have to construct two of the previous tile, and once you construct one, it has to go somewhere. In the end, the final board will have a string of every power of two from 2^16 to 4, and then another 4 in the last empty space. The 4s then combine, then the 8s, and so on, rippling up like binary addition until you get 2^17. Hope that makes sense, I thought about this for a while but it's not the easiest concept to put to words.


If he got 32768, that would seem to be the highest unless you could get the following 16 squares which would collapse to 65536:

2, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768

You could theoretically beat that if you happened to get a 4 just when you needed it (starting with 4, 4, 8, 16, etc.)


Any remarks on average number of rounds to get to 2048?


I run 100 games - the algorithm needs 949 rounds in average to reach the 2048 tile


Thanks. Good to know The Game is beatable in 10-15 minutes ;)


That does not depend much on the solution, mostly it depends at the speed at which numbers are generated (which you can approximate constant to 20.8 + 40.2).


From the op: "But level=2 is enough to win 100% of all games!"

So I think it can win all games?


That does not answer how many moves it takes to get to 2048 though.


Oh. Was that what was meant by "rounds"? I assumed how many times does the game have to be played.


I must say that the game itself is implemented in the wrong way! The AI here is just playing another much simpler game here.


Given the number of straight 2048 implementations out there now that appear to have slightly different rules making the game easier, perhaps it would be a great idea for the definitive 2048 rules to be published.


The definitive 2048 rules can be gathered by decomposing the original source, bugs and all.


Ugh no another one of these.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: