I can't code javascript, so I stole your answer.
//bind into new tile function and change m(ove) variable when a tile was moved
b = a.addRandomTile.bind(a);
m = !1;
a.addRandomTile = function() { m = !0; b(); };
//number of move fails
mfs = 0;
c=1;
setInterval(function() {
//set global moved tracking variable to false
m = !1;
a.move(c)
c++
if (c>3) {c=1}
m || mfs++;
//restart after 10 moves failed
10 < mfs && (mfs = 0, a.restart());
}, 250);
It uses the strategy I also use.
EDIT: Nice, it just beat your score after about 5 minutes on my machine :D
EDIT:
Forgot to move down twice instead of just once, this is the code you should use:
a = new GameManager(4, KeyboardInputManager, HTMLActuator, LocalStorageManager);
//bind into new tile function and change m(ove) variable when a tile was moved
b = a.addRandomTile.bind(a);
m = !1;
a.addRandomTile = function() { m = !0; b(); };
//number of move fails
mfs = 0;
c=1;
setInterval(function() {
//set global moved tracking variable to false
m = !1;
if (c<=3) {n=c}
else {n=2}
a.move(n)
c++
if (c>4) {c=1}
m || mfs++;
//restart after 10 moves failed
10 < mfs && (mfs = 0, a.restart());
}, 250);
Also, there's a bug in it that it restarts when it's not needed, but I'm not sure how to fix this.
EDIT: It currently has a highscore of 3116 (after 3 minutes). I think it's safe to say this algoritm is better than just doing random moves.
EDIT Newer version:
a = new GameManager(4, KeyboardInputManager, HTMLActuator, LocalStorageManager);
//bind into new tile function and change m(ove) variable when a tile was moved
b = a.addRandomTile.bind(a);
m = !1;
a.addRandomTile = function() { m = !0; mfs=0; b(); };
//number of move fails
mfs = 0;
c=1;
setInterval(function() {
//set global moved tracking variable to false
m = !1;
if (c<=3) {n=c}
else {n=2}
a.move(n)
c++
if (c>4) {c=1}
m || mfs++;
//up after 5 moves
5 < mfs && (a.move(0));
//restart after 10 moves failed
10 < mfs && (mfs = 0, a.restart());
}, 250);
EDIT: Another new version, this one moves down directly after moving up.
a = new GameManager(4, KeyboardInputManager, HTMLActuator, LocalStorageManager);
//bind into new tile function and change m(ove) variable when a tile was moved
b = a.addRandomTile.bind(a);
m = !1;
a.addRandomTile = function() { m = !0; mfs=0; b(); };
//number of move fails
mfs = 0;
c=1;
setInterval(function() {
//set global moved tracking variable to false
m = !1;
if (c<=3) {n=c}
else {n=2}
a.move(n)
c++
if (c>4) {c=1}
m || mfs++;
//up after 5 moves
5 < mfs && (a.move(0), c=4);
//restart after 10 moves failed
10 < mfs && (mfs = 0, a.restart());
}, 250);
EDIT: Update: it just broke my personal record with a pretty crazy score of 12596.
EDIT: Hey, I'm bottomstacker :D
Also:
b=a.addRandomTile.bind(a);m=!1;a.addRandomTile=function(){m=!0;mfs=0;b()};mfs=0;c=1;setInterval(function(){m=!1;n=3>=c?c:2;a.move(n);c++;4<c&&(c=1);m||mfs++;5<mfs&&(a.move(0),c=4);10<mfs&&(mfs=0,a.restart())},250);
(Not actually a change, just compressed.)
5th time's a charm? Not sure. Anyways:
//bind into new tile function and change m(ove) variable when a tile was moved
b = a.addRandomTile.bind(a);
m = !1;
a.addRandomTile = function() { m = !0; mfs=0; b(); };
//number of move fails
mfs = 0;
c=1;
setInterval(function() {
//set global moved tracking variable to false
m = !1;
if (c<=3) {n=c}
else {n=2}
a.move(n)
c++
if (c>4) {c=1}
if (c==0) {c=4}
m || mfs++;
//up after 5 moves
5 < mfs && (c=0);
//restart after 10 moves failed
10 < mfs && (mfs = 0, a.restart());
}, 250);
and:
b=a.addRandomTile.bind(a);m=!1;a.addRandomTile=function(){m=!0;mfs=0;b()};mfs=0;c=1;setInterval(function(){m=!1;n=3>=c?c:2;a.move(n);c++;4<c&&(c=1);0==c&&(c=4);m||mfs++;5<mfs&&(c=0);10<mfs&&(mfs=0,a.restart())},250);
Another new version:
a = new GameManager(4, KeyboardInputManager, HTMLActuator, LocalStorageManager);
//bind into new tile function and change m(ove) variable when a tile was moved
b = a.addRandomTile.bind(a);
m = !1;
a.addRandomTile = function() { m = !0; mfs=0; b(); };
//number of move fails
mfs = 0;
c=1;
setInterval(function() {
//set global moved tracking variable to false
m = !1;
if (c<=3) {n=c}
else {n=2}
a.move(n)
c++
if (c>4) {c=1}
if (c==0) {c=4}
m || mfs++;
//up after 5 moves
5 < mfs && (c=0);
//Found this in the source, as the criteria for a gameover. Might as well reset then ;)
if (!a.movesAvailable()) {
a.restart()
}
}, 250);
and:
a=new GameManager(4,KeyboardInputManager,HTMLActuator,LocalStorageManager);b=a.addRandomTile.bind(a);m=!1;a.addRandomTile=function(){m=!0;mfs=0;b()};mfs=0;c=1;setInterval(function(){m=!1;n=3>=c?c:2;a.move(n);c++;4<c&&(c=1);0==c&&(c=4);m||mfs++;5<mfs&&(c=0);a.movesAvailable()||a.restart()},250);
(I hope it's not too much of a problem that this continues behind the gameover screen? I think you could add an a.over=0
somewhere that gets executed often. I'll figure it out someday.)
EDIT (again):
I dropped the standard gameover way and reverted to the old way of doing things. I'm now testing out an addition that'll always merge if there are 2 tiles of 16 or more together:
a = new GameManager(4, KeyboardInputManager, HTMLActuator, LocalStorageManager);
b = a.addRandomTile.bind(a);
m = !1;
a.addRandomTile = function() {
m = !0;
mfs = 0;
b();
};
mfs = 0;
c = 1;
setInterval(function() {
m = !1;
l = 8;
for (x = 0;x < 4;x++) {
for (y = 0;y < 4;y++) {
t1 = a.grid.cellContent({x:x, y:y});
t2 = a.grid.cellContent({x:x, y:y + 1});
t3 = a.grid.cellContent({x:x + 1, y:y + 1});
if (t1 & t2) {
if (t1.value == t2.value) {
if (t1.value > l) {
l = t1.value;
c = 2;
}
}
if (t1 & t3) {
if (t1.value == t2.value) {
if (t1.value > l) {
l = t1.value;
}
}
}
}
}
}
if (c <= 3) {
n = c;
} else {
n = 2;
}
a.move(n);
c++;
if (c > 4) {
c = 1;
}
if (c == 0) {
c = 4;
}
m || mfs++;
5 < mfs && (c = 0);
10 < mfs && (mfs = 0, a.restart());
}, 250);
3
This seems like it will just end up being a bunch of JavaScript implementations of the best algorithm from here, no?
– Jason C – 2014-04-02T16:14:06.6902-1 for
...best score after an hour will count...
Why just an hour? – user80551 – 2014-04-02T16:18:34.240And further, if all the most competitive answers are just ports of the same algorithms from the page, the "objective" winner is just determined by random chance. So this questions seems to translate to: Port one or all of the algorithms from the SO post to JavaScript, then after an hour, a random winner will be chosen. – Jason C – 2014-04-02T16:22:13.327
@JasonC Perhaps. If I do submit, though, I won't be pulling from those answers. Part of the fun of these challenges for me isn't winning, it's exploring the algorithms and approaches available to come up with a good solution, with an eye towards invention/new learning. I doubt that applies for everyone, but that's my philosophy for games in code. – ProgrammerDan – 2014-04-02T16:25:21.133
+1 for pointing out how easy this is to interface! Looking forward to watching the answers here – Claudiu – 2014-04-02T16:33:49.070
3In any case, I suggest, in the name of fairness, seeding the random number generator the same for every answer's test run, and also running a hard (1 hour / 250 ms =) 14,400 moves per run to eliminate variations of that count due to timing inaccuracies. At least the results could be somewhat more deterministic and worthy of a KotH. – Jason C – 2014-04-02T16:34:34.677
1750 bytes or 550 bytes? – Peter Taylor – 2014-04-02T16:51:31.547
2Too restrictive. 750 bytes, 1 hour, JavaScript. – TheDoctor – 2014-04-02T17:11:15.653
My internet stopped working the past hour, and I have to accede that I wasn't aware that question existed. None the less I believe the fairly low character limit should prevent the more complex algorithms from being doable and a fair amount of creativity should still be required. – David Mulder – 2014-04-02T17:42:07.813
@user80551 and @ Jason C: I considered building a seeded fork of 2048 to do exactly that, but the beauty of the simplicity of the interface and challenge would be lost that way, so I decided (after running a couple of simulations) that an hour should be able to differentiate between different algorithms even if the differences are quite minimal. – David Mulder – 2014-04-02T17:47:24.757
@PeterTaylor: Shame on me, discussed this on chat couple of days ago and changed it from 750 to 555 back then, but forgot changing both. – David Mulder – 2014-04-02T17:48:54.293
1@DavidMulder I think a sacrifice of some simplicity is warranted to make this a proper, deterministic challenge. 14,400 moves (and again: actual move count, don't rely on 250ms intervals being consistent) is not enough to ensure that every user gets equally serendipitous sets of moves (and equally avoids unlucky sets of moves). With your "maximum" rule, it only takes one extremely lucky set of moves to have an otherwise poor algorithm dominate the results. This is simply not fair or balanced that way. Note also that the winner should always be the winner no matter how many retests are run. – Jason C – 2014-04-02T18:08:42.890
1I wonder if the [ai-player] tag is a better fit for this since the entries will not be playing directly against each other? – Gareth – 2014-04-02T18:11:57.253
@Gareth [tag:ai-player] does not currently seem to signify a challenge style, but I'm sure nobody would have a problem if you examined questions that currently have that tag, updated the tag wiki, and edited this if it is appropriate and beneficial. You may wish to start a discussion of possible good uses for [tag:ai-player] on meta. The current [tag:king-of-the-hill] description doesn't preclude contests where the programs don't directly interact (I think I saw some related discussion in chat recently; ask Chris Jester-Young, I believe he was involved). – Jason C – 2014-04-02T18:14:54.223
@JasonC: Already made clear in my answer that 1) I am aware that
randombot
could have won in theory (with which I am fine) and 2) the fun factor of being able to watch each-others bots counts a lot for me (the reason why I set the rule that 250ms should be between turns, rather than a limit on the moves). If you dislike it that much downvote and don't join, as far as I am concerned the only valid point you raised was that question on SO which I (nor the people on chat) were aware of. – David Mulder – 2014-04-02T18:31:09.1601@DavidMulder At minimum at least use a hard count of 14,400 moves; that shouldn't affect your interface. You are not guaranteed to get
1 hour / 250 ms
moves in an interval-based test. As for the randomness, the fact that a different winner can result from multiple retests of all the answers is a valid point and pretty clearly puts a major hole in this challenge (which otherwise isn't a particularly bad challenge). In theory, challenges here should have distinct deterministic criteria, and results should be repeatable. – Jason C – 2014-04-02T19:49:32.337@DavidMulder It's worth noting, by the way, that 14,400 moves and 250 ms between moves are not mutually exclusive. – Jason C – 2014-04-05T15:52:00.793
@JasonC: Wasn't planning on replying, but let me point out something which it seems I have not made clear regarding the randomness: by seeding the random function the difference will be that a certain bot would win deterministic, it would however in no way make that bot better or anything like that at all. The result is in that sense just as random. Additionally challenges here should have an objective criteria, not necessarily a deterministic one as far as I can tell. Either way, I agree that a fixed amount of moves wouldn't have been a bad idea, but it would open an entire set of – David Mulder – 2014-04-05T16:08:08.440
different discussions regarding whether a move that doesn't move anything is a move, and lots of similar things whereas in my humble opinion a time limit works quite nicely as well. Especially as execution times comes into play a bit as well (no matter how insignificant for the feels it's quite nice). I built myself a piece of code that counts the execution time and then can run at 25ms per second still fairly simulating the hour limit taking into account the execution time. – David Mulder – 2014-04-05T16:14:53.700
Oh well, whatever. I have had a terrible amount of fun with this challenge though I would have loved seeing more submissions, so I am happy the way it ran and can't really bother making a deal out of the determinism and time constraint rules. If they would cause loopholes (like the seeded system could do) you would have me up in arms, but like this I can't really be bothered. – David Mulder – 2014-04-05T16:16:17.223
Many games which are not deterministic admit measuring the average performance of entries by running each many times. – dmckee --- ex-moderator kitten – 2014-04-13T23:57:04.293
Re KotH: "True, my bad, best tag to describe the type of the competition." I think a simple [code-challenge] would be the appropriate tag here. – Martin Ender – 2014-05-16T17:36:51.117