--- a/2048.html Sun Sep 07 00:18:35 2014 +0300
+++ b/2048.html Sun Sep 07 00:19:00 2014 +0300
@@ -5,8 +5,10 @@
<meta name="viewport" content="width=device-width; initial-scale=1.0"/>
<meta charset="utf-8"/>
+ <script src="rule.js"></script>
<script src="board.js"></script>
<script src="perf.js"></script>
+ <script src="ai.js"></script>
<style>
body {
@@ -113,192 +115,6 @@
<script>
"use strict";
- var board = {};
- board.create = function() {
- var brd = [];
- for (var i = 0; i < 4; i++) {
- brd[i] = [];
- for (var j = 0; j < 4; j++) {
- brd[i][j] = 0;
- }
- }
- return brd;
- }
- board.copy = function(from, to) {
- for (var i = 0; i < 4; i++) {
- for (var j = 0; j < 4; j++) {
- to[i][j] = from[i][j];
- }
- }
- }
- board.freeCnt = function(brd) {
- var cnt = 0;
- for (var i = 0; i < 4; i++) {
- for (var j = 0; j < 4; j++) {
- if (brd[i][j] === 0)
- cnt++;
- }
- }
- return cnt;
- }
- board.gameOver = function(brd) {
- if (board.freeCnt(brd) > 0)
- return false;
- for (var i = 0; i < 4; i++) {
- for (var j = 0; j < 3; j++) {
- if (brd[i][j] === brd[i][j+1])
- return false;
- }
- }
- for (var j = 0; j < 4; j++) {
- for (var i = 0; i < 3; i++) {
- if (brd[i][j] === brd[i+1][j])
- return false;
- }
- }
- return true;
- }
- board.putRandom = function(brd) {
- var cnt = board.freeCnt(brd);
- cnt = Math.floor(Math.random() * cnt)+1;
- for (var i = 0; i < 4 && cnt > 0; i++) {
- for (var j = 0; j < 4 && cnt > 0; j++) {
- if (brd[i][j] !== 0)
- continue;
- if (cnt === 1)
- brd[i][j] = (Math.random() > .9) ? 2 : 1;
- cnt--;
- }
- }
- }
- /* http://www.reddit.com/r/2048/comments/214njx/highest_possible_score_for_2048_warning_math */
- var boardScoreTbl = [0];
- for (var i = 1, exp = 2; i < 16; i++, exp *= 2) {
- boardScoreTbl[i] = (i-1)*exp;
- }
- board.score = function(brd) {
- var score = 0;
- var max = 0;
- for (var i = 0; i < 4; i++) {
- for (var j = 0; j < 4; j++) {
- var val = brd[i][j];
- score += boardScoreTbl[val];
- if (max < val)
- max = val;
- }
- }
- return {score: score, max: Math.pow(2, max)};
- }
-
- board.row = {};
- board.row.init = function() {
- return {stack: [], curr: 0};
- }
- board.row.push = function(state, val) {
- if (val === 0)
- return;
- if (state.curr === 0) {
- state.curr = val;
- return;
- }
- if (state.curr === val) {
- state.stack.push(state.curr+1);
- state.curr = 0;
- } else {
- state.stack.push(state.curr);
- state.curr = val;
- }
- }
- board.row.finish = function(state) {
- if (state.curr !== 0)
- state.stack.push(state.curr);
- }
- board.move = {};
- board.move.up = function(brd) {
- var updated = false;
- for (var j = 0; j < 4; j++) {
- var state = board.row.init();
- for (var i = 0; i < 4; i++) {
- board.row.push(state, brd[i][j]);
- }
- board.row.finish(state);
- for (var i = 0; i < state.stack.length; i++) {
- if (brd[i][j] !== state.stack[i])
- updated = true;
- brd[i][j] = state.stack[i];
- }
- for (; i < 4; i++) {
- if (brd[i][j] !== 0)
- updated = true;
- brd[i][j] = 0;
- }
- }
- return updated;
- };
- board.move.down = function(brd) {
- var updated = false;
- for (var j = 0; j < 4; j++) {
- var state = board.row.init();
- for (var i = 3; i >= 0; i--) {
- board.row.push(state, brd[i][j]);
- }
- board.row.finish(state);
- for (var i = 0; i < state.stack.length; i++) {
- if (brd[3-i][j] !== state.stack[i])
- updated = true;
- brd[3-i][j] = state.stack[i];
- }
- for (; i < 4; i++) {
- if (brd[3-i][j] !== 0)
- updated = true;
- brd[3-i][j] = 0;
- }
- }
- return updated;
- };
- board.move.left = function(brd) {
- var updated = false;
- for (var i = 0; i < 4; i++) {
- var state = board.row.init();
- for (var j = 0; j < 4; j++) {
- board.row.push(state, brd[i][j]);
- }
- board.row.finish(state);
- for (var j = 0; j < state.stack.length; j++) {
- if (brd[i][j] !== state.stack[j])
- updated = true;
- brd[i][j] = state.stack[j];
- }
- for (; j < 4; j++) {
- if (brd[i][j] !== 0)
- updated = true;
- brd[i][j] = 0;
- }
- }
- return updated;
- };
- board.move.right = function(brd) {
- var updated = false;
- for (var i = 0; i < 4; i++) {
- var state = board.row.init();
- for (var j = 3; j >= 0; j--) {
- board.row.push(state, brd[i][j]);
- }
- board.row.finish(state);
- for (var j = 0; j < state.stack.length; j++) {
- if (brd[i][3-j] !== state.stack[j])
- updated = true;
- brd[i][3-j] = state.stack[j];
- }
- for (; j < 4; j++) {
- if (brd[i][3-j] !== 0)
- updated = true;
- brd[i][3-j] = 0;
- }
- }
- return updated;
- };
-
var boardDom = document.getElementById("board");
var ui = {};
ui.board = {};
@@ -407,12 +223,12 @@
}
var tmpBrd = board.create();
board.copy(board.current, tmpBrd);
- var fn = ai.current(tmpBrd);
- if (typeof fn === 'undefined') {
+ var move = ui.ai.analyse(tmpBrd);
+ if (typeof move === 'undefined') {
ui.message.set("I don't know how to move!");
return;
}
- var updated = board.move[fn].call(null, board.current);
+ var updated = board.move[move].call(null, board.current);
if (updated) {
board.putRandom(board.current);
ui.board.update(board.current);
@@ -430,12 +246,12 @@
while (!board.gameOver(board.current)) {
var tmpBrd = board.create();
board.copy(board.current, tmpBrd);
- var fn = ai.current(tmpBrd);
- if (typeof fn === 'undefined') {
+ var move = ui.ai.analyse(tmpBrd);
+ if (typeof move === 'undefined') {
ui.message.set("I don't know how to move!");
return;
}
- var updated = board.move[fn].call(null, board.current);
+ var updated = board.move[move].call(null, board.current);
if (updated) {
board.putRandom(board.current);
} else {
@@ -454,97 +270,19 @@
}
document.getElementById("finish").addEventListener("click", finish);
- var ai = {};
+ ////////////////////////////////////////////////////////////////
+ // Register AIs.
- ai.random = function(brd) {
- var tmpBrd = board.create();
- do {
- var action = ["up", "down", "left", "right"][Math.floor(Math.random()*4)];
- board.copy(brd, tmpBrd);
- } while (!board.move[action](tmpBrd));
- return action;
- }
- document.getElementById("ai-random").addEventListener("click", function() {
- ai.current = ai.random;
- });
+ ui.brdEngine = BoardArr2d; // TODO make user selectable
- ai.nextMaxScore = function(brd) {
- var tmpBrd = board.create();
- board.copy(brd, tmpBrd);
- var maxScore = -1;
- var action;
- if (board.move.up(tmpBrd)) {
- maxScore = board.score(tmpBrd).score;
- action = "up";
- }
- board.copy(brd, tmpBrd);
- if (board.move.left(tmpBrd)) {
- var score = board.score(tmpBrd).score;
- if (maxScore < score) {
- action = "left";
- maxScore = score;
- }
- }
- board.copy(brd, tmpBrd);
- if (board.move.down(tmpBrd)) {
- var score = board.score(tmpBrd).score;
- if (maxScore < score) {
- action = "down";
- maxScore = score;
- }
- }
- board.copy(brd, tmpBrd);
- if (board.move.right(tmpBrd)) {
- var score = board.score(tmpBrd).score;
- if (maxScore < score) {
- action = "right";
- maxScore = score;
- }
- }
- return action;
- }
- document.getElementById("ai-next-max-score").addEventListener("click", function() {
- ai.current = ai.nextMaxScore;
+ document.getElementById("ai-random").addEventListener("click", function() {
+ ui.ai = new ai.random(ui.brdEngine);
});
-
-
- ai.nextMaxValue = function(brd) {
- var tmpBrd = board.create();
- board.copy(brd, tmpBrd);
- var maxMax = -1;
- var action;
- if (board.move.up(tmpBrd)) {
- maxMax = board.score(tmpBrd).max;
- action = "up";
- }
- board.copy(brd, tmpBrd);
- if (board.move.left(tmpBrd)) {
- var max = board.score(tmpBrd).max;
- if (maxMax < max) {
- action = "left";
- maxMax = max;
- }
- }
- board.copy(brd, tmpBrd);
- if (board.move.down(tmpBrd)) {
- var max = board.score(tmpBrd).max;
- if (maxMax < max) {
- action = "down";
- maxMax = max;
- }
- }
- board.copy(brd, tmpBrd);
- if (board.move.right(tmpBrd)) {
- var max = board.score(tmpBrd).max;
- if (maxMax < max) {
- action = "right";
- maxMax = max;
- }
- }
- return action;
- }
+ document.getElementById("ai-next-max-score").addEventListener("click", function() {
+ ui.ai = new ai.nextMaxScore(ui.brdEngine);
+ });
document.getElementById("ai-next-max-value").addEventListener("click", function() {
- ai.current = ai.nextMaxValue;
+ ui.ai = new ai.nextMaxValue(ui.brdEngine);
});
</script>