Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /////////////////////
- // Key press Logic //
- /////////////////////
- var code_map = {
- "L" : 37,
- "U" : 38,
- "R" : 39,
- "D" : 40
- };
- function press(key) {
- var code = code_map[key];
- var eventObj = document.createEvent("Events");
- eventObj.initEvent("keydown", true, true);
- eventObj.which = code;
- document.body.dispatchEvent(eventObj);
- }
- ///////////////
- // Board ADT //
- ///////////////
- var length = 4;
- // The Board class
- var Board = function () {
- var i, j;
- this.table = new Array(length);
- for (i = 0; i < length; i++) {
- this.table[i] = new Array(length);
- for (j = 0; j < length; j++) {
- this.table[i][j] = 0;
- }
- }
- this.score = 0;
- };
- Board.prototype.clone = function() {
- var i, j, newBoard = new Board();
- for (i = 0; i < length; i++) {
- for (j = 0; j < length; j++) {
- newBoard.table[i][j] = this.table[i][j];
- }
- }
- newBoard.score = this.score;
- return newBoard;
- }
- Board.prototype.print = function () {
- var i, j, result;
- for (i = 0; i < length; i++) {
- result = "";
- for (j = 0; j < length; j++) {
- result += this.table[j][i] + " ";
- }
- // console.log(result);
- }
- };
- Board.prototype.get = function(x, y) {
- if (x >= 0 && x < length && y >= 0 && y < length) {
- return this.table[x][y];
- }
- }
- Board.prototype.addPiece = function(x, y, value) {
- if (this.table[x][y] !== 0) {
- this.print();
- throw "Added new piece to non-empty square " + x + "," + y;
- }
- this.table[x][y] = value;
- };
- Board.prototype.movePiece = function(oldx, oldy, newx, newy) {
- this.table[newx][newy] = this.table[oldx][oldy];
- this.table[oldx][oldy] = 0;
- };
- Board.prototype.playMove = function(direction) {
- var newBoard, start, step, end, i, j, freePos, merged, change = false;
- newBoard = new Board();
- newBoard.score = this.score;
- var is_horizontal = (direction === "L" || direction === "R");
- if (direction === "U" || direction === "L") {
- start = 0;
- end = length;
- step = 1;
- } else {
- start = length - 1;
- end = -1;
- step = -1;
- }
- for (i = 0; i < length; i++) {
- freePos = start;
- merged = false;
- for (j = start; j !== end; j += step) {
- if (is_horizontal) {
- if (this.table[j][i] !== 0) {
- if (freePos !== start && this.table[j][i] === this.table[freePos - step][i] && !merged) {
- change = true;
- merged = true;
- newBoard.table[freePos - step][i] *= 2;
- newBoard.score += newBoard.table[freePos - step][i];
- } else {
- if (freePos !== j) {
- change = true;
- }
- merged = false;
- newBoard.addPiece(freePos, i, this.table[j][i]);
- freePos += step;
- }
- }
- } else {
- if (this.table[i][j] !== 0) {
- if (freePos !== start && this.table[i][j] === this.table[i][freePos - step] && !merged) {
- change = true;
- merged = true;
- newBoard.table[i][freePos - step] *= 2;
- } else {
- if (freePos !== j) {
- change = true;
- }
- merged = false;
- newBoard.addPiece(i, freePos, this.table[i][j]);
- freePos += step;
- }
- }
- }
- }
- }
- if (change) {
- return newBoard;
- }
- };
- /////////////////////
- // Reading the DOM //
- /////////////////////
- // board must be a newly created, empty board.
- function read_board(board) {
- var tiles, properties, value, position, x, y, scoreDiv;
- tiles = document.getElementsByClassName("tile");
- for (var i = 0; i < tiles.length; i++) {
- properties = tiles[i].className.split(" ");
- value = parseInt(properties[1].split("-")[1]);
- position = properties[2].split("-");
- x = parseInt(position[2]) - 1;
- y = parseInt(position[3]) - 1;
- // There could be multiple tiles with the same position, but
- // the last one is the one that matters.
- board.table[x][y] = value;
- }
- scoreDiv = document.getElementsByClassName("score-container")[0]
- board.score = parseInt(scoreDiv.innerHTML)
- }
- ////////////////
- // Expectimax //
- ////////////////
- var SCORE_FACTOR = 2;
- var SAME_TILE_FACTOR = 10;
- // var NEXT_TILE_FACTOR = 3;
- var EMPTY_FACTOR = 20;
- var CORNER_FACTOR = 5;
- var EDGE_FACTOR = 1;
- var SMOOTHNESS_FACTOR = 3;
- var MONOTONICITY_FACTOR = 1;
- var LOSE_SCORE = -999999999;
- var DEPTH = 2;
- var actions = ["L", "U", "R", "D"];
- function choose_action(board) {
- var i, bestAction, bestScore = LOSE_SCORE - 1;
- for (i = 0; i < actions.length; i++) {
- nextBoard = board.playMove(actions[i]);
- if (nextBoard === undefined) {
- continue;
- }
- nextScore = expectizer(nextBoard, DEPTH);
- delete nextBoard;
- if (nextScore > bestScore) {
- bestScore = nextScore;
- bestAction = actions[i];
- }
- }
- return bestAction;
- }
- function maximizer(board, depth) {
- var i, nextBoard, bestScore = LOSE_SCORE + board.score;
- for (i = 0; i < actions.length; i++) {
- nextBoard = board.playMove(actions[i]);
- if (nextBoard === undefined) {
- continue;
- }
- bestScore = Math.max(bestScore, expectizer(nextBoard, depth - 1));
- delete nextBoard;
- }
- return bestScore;
- }
- function expectizer(board, depth) {
- var i, j, nextBoard, score = 0, numMoves = 0;
- if (depth == 0) {
- return evaluate(board);
- }
- for (i = 0; i < length; i++) {
- for (j = 0; j < length; j++) {
- if (board.table[i][j] === 0) {
- numMoves++;
- nextBoard = board.clone();
- nextBoard.table[i][j] = 2;
- score += 0.9 * maximizer(nextBoard, depth);
- nextBoard.table[i][j] = 4;
- score += 0.1 * maximizer(nextBoard, depth);
- delete nextBoard;
- }
- }
- }
- return score / numMoves;
- }
- function evaluate(board) {
- var i, j, x, y, corners, tileMap, value, tile, numEmpty = 0, maxCorner = -1, maxTile = 2;
- value = SCORE_FACTOR * board.score;
- for (i = 0; i < length; i++) {
- for (j = 0; j < length; j++) {
- tile = board.table[i][j];
- if (tile === 0) {
- numEmpty++;
- continue;
- }
- maxTile = Math.max(maxTile, tile);
- var m, n, neighbor;
- for (m = i - 1; m <= i + 1; m += 2) {
- for (n = j - 1; n <= j + 1; n += 2) {
- neighbor = board.get(m, n);
- if (neighbor === tile) {
- value += SAME_TILE_FACTOR;
- }
- }
- }
- }
- }
- var prev_row, prev_col, curr_row, curr_col, monotonicity = 0;
- for (i = 0; i < length; i++) {
- prev_row = board.table[0][i] < board.table[1][i];
- prev_col = board.table[i][0] < board.table[i][1];
- for (j = 2; j < length; j++) {
- curr_row = board.table[j-1][i] < board.table[j][i];
- if (prev_row !== curr_row) {
- monotonicity += Math.max(board.table[j-2][i], board.table[j-1][i], board.table[j][i]);
- }
- prev_row = curr_row;
- curr_col = board.table[i][j-1] < board.table[i][j];
- if (prev_col !== curr_col) {
- monotonicity += Math.max(board.table[i][j-2], board.table[i][j-1], board.table[i][j]);
- }
- prev_col = curr_col;
- }
- }
- value -= MONOTONICITY_FACTOR * monotonicity;
- value += EMPTY_FACTOR * numEmpty;
- x = 0;
- y = 0;
- for (i = 0; i < length; i += length - 1) {
- for (j = 0; j < length; j += length - 1) {
- if (board.table[i][j] > maxCorner) {
- maxCorner = board.table[i][j];
- x = i;
- y = j;
- }
- }
- }
- if (board.table[x][y] === maxTile) {
- value += CORNER_FACTOR * maxTile;
- }
- for (i = 0; i < length; i++) {
- value += EDGE_FACTOR * board.table[0][i];
- value += EDGE_FACTOR * board.table[i][0];
- value += EDGE_FACTOR * board.table[length-1][i];
- value += EDGE_FACTOR * board.table[i][length-1];
- }
- // Smoothness
- var smoothness = 0;
- for (i = 0; i < length; i++) {
- for (j = 1; j < length; j++) {
- smoothness += Math.abs(board.table[i][j] - board.table[i][j-1]);
- smoothness += Math.abs(board.table[j][i] - board.table[j-1][i]);
- }
- }
- value -= SMOOTHNESS_FACTOR * smoothness;
- return value;
- }
- ///////////////
- // Main Loop //
- ///////////////
- function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }
- var max, min;
- var interval, interval2;
- function start()
- {
- var action, board = new Board();
- read_board(board);
- action = choose_action(board);
- delete board;
- if (action !== undefined) {
- press(action);
- }
- }
- function start2()
- {
- if (document.getElementsByClassName("game-over").length > 0)
- {
- document.getElementsByClassName("restart-button")[0].click();
- }
- else if (document.getElementsByClassName("game-won").length > 0)
- {
- if (document.getElementsByClassName("keep-playing-button").length > 0)
- {
- document.getElementsByClassName("keep-playing-button")[0].click();
- }else{
- clearInterval(interval);
- }
- }
- }
- min = getRandomInt(350, 660);
- max = getRandomInt(661, 1206);
- interval = setInterval(start, getRandomInt(min, max));
- interval2 = setInterval(start2, 3000);
Advertisement
Add Comment
Please, Sign In to add comment