Last active
October 4, 2023 09:17
-
-
Save Bloody-Badboy/b956cbcacd337252548cb80fc55213cc to your computer and use it in GitHub Desktop.
https://sui8192.ethoswallet.xyz game solver
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function () { | |
"use strict"; | |
if (window.Solver) { | |
return; | |
} | |
var Solver = (window.Solver = {}); | |
Solver.LEFT = 37; | |
Solver.UP = 38; | |
Solver.RIGHT = 39; | |
Solver.DOWN = 40; | |
Solver.DIRECTIONS = [Solver.LEFT, Solver.UP, Solver.RIGHT, Solver.DOWN]; | |
Solver.init = function () { | |
Solver.initUI(); | |
Solver.initLookup(); | |
}; | |
Solver.initUI = function () { | |
if (document.getElementById("solver-buttons")) { | |
return; | |
} | |
var divStyle = [ | |
"margin-bottom: 12px", | |
"display: flex", | |
"justify-content: center", | |
"align-items: center", | |
"gap: 12px", | |
].join(";"); | |
var div = document.createElement("div"); | |
div.id = "solver-buttons"; | |
div.style.cssText = divStyle; | |
var buttonStyle = [ | |
"padding: 9px 18px", | |
"border-radius: 18px", | |
"border: none", | |
"cursor: pointer", | |
"text-decoration: none", | |
"background-color: black", | |
"color: white", | |
"line-height: 18px", | |
"font-size: 14px", | |
].join(";"); | |
div.innerHTML = [ | |
`<button onclick="Solver.start()" style="${buttonStyle}">Start</button>`, | |
`<button onclick="Solver.stop()" style="${buttonStyle}">Stop</button>`, | |
].join(""); | |
var board = document.getElementById("board"); | |
board.parentNode.insertBefore(div, board); | |
}; | |
function fireKeyboardEvent(type, code) { | |
var evt = document.createEvent("KeyboardEvent"); | |
if (evt.initKeyEvent) { | |
evt.initKeyEvent( | |
type, | |
true, | |
true, | |
document.defaultView, | |
false, | |
false, | |
false, | |
false, | |
code, | |
code | |
); | |
} else if (evt.initKeyboardEvent) { | |
evt.initKeyboardEvent( | |
type, | |
true, | |
true, | |
document.defaultView, | |
code, | |
code, | |
false, | |
false, | |
false, | |
false, | |
false | |
); | |
} | |
Object.defineProperty(evt, "keyCode", { | |
get: function () { | |
return code; | |
}, | |
}); | |
Object.defineProperty(evt, "which", { | |
get: function () { | |
return code; | |
}, | |
}); | |
document.documentElement.dispatchEvent(evt); | |
} | |
function setRandomInterval(intervalFunction, minDelay, maxDelay) { | |
let timeout; | |
const runInterval = () => { | |
const timeoutFunction = () => { | |
intervalFunction(); | |
runInterval(); | |
}; | |
const delay = | |
Math.floor(Math.random() * (maxDelay - minDelay + 1)) + minDelay; | |
console.log("Delay: " + delay + "ms"); | |
timeout = setTimeout(timeoutFunction, delay); | |
}; | |
runInterval(); | |
return { | |
clear() { | |
clearTimeout(timeout); | |
}, | |
}; | |
} | |
Solver.move = function (dir) { | |
fireKeyboardEvent("keydown", dir); | |
fireKeyboardEvent("keyup", dir); | |
}; | |
Solver.readTile = function (x, y) { | |
const board = document.querySelector(`#board`); | |
const row = board.querySelector(`.row-${y + 1}`); | |
const tiles = row.querySelectorAll(".tile"); | |
const tile = tiles[x].querySelector(".value"); | |
if (!tile) return 0; | |
var table = { | |
0: 0, | |
2: 1, | |
4: 2, | |
8: 3, | |
16: 4, | |
32: 5, | |
64: 6, | |
128: 7, | |
256: 8, | |
512: 9, | |
1024: 10, | |
2048: 11, | |
4096: 12, | |
8192: 13, | |
16384: 14, | |
32768: 15, | |
}; | |
return table[parseInt(tile.innerHTML, 10)]; | |
}; | |
Solver.readBoard = function () { | |
var tiles = []; | |
for (var i = 0; i < 16; ++i) { | |
tiles[i] = Solver.readTile(i % 4, Math.floor(i / 4)); | |
} | |
console.log(tiles); | |
return tiles; | |
}; | |
Solver.transformLineLeft = function (line) { | |
var merged = []; | |
for (var i = 1; i < 4; ++i) { | |
var pos = i; | |
while (line[pos] !== 0 && pos > 0) { | |
if (line[pos - 1] === 0) { | |
line[pos - 1] = line[pos]; | |
line[pos] = 0; | |
--pos; | |
continue; | |
} | |
if (!merged[pos - 1] && line[pos - 1] === line[pos]) { | |
++line[pos - 1]; | |
line[pos] = 0; | |
merged[pos - 1] = true; | |
} | |
break; | |
} | |
} | |
}; | |
Solver.getLookupIndex = function (a, b, c, d) { | |
return 4096 * a + 256 * b + 16 * c + d; | |
}; | |
Solver.initLookup = function () { | |
Solver.lineLookup = []; | |
for (var i = 0; i < 1 << 16; ++i) { | |
var a = (i >> 12) & 0xf, | |
b = (i >> 8) & 0xf, | |
c = (i >> 4) & 0xf, | |
d = i & 0xf; | |
var line = [a, b, c, d]; | |
Solver.transformLineLeft(line); | |
if (line[0] !== a || line[1] !== b || line[2] !== c || line[3] !== d) { | |
var index = Solver.getLookupIndex(a, b, c, d); | |
Solver.lineLookup[index] = line; | |
} | |
} | |
}; | |
Solver.getTransformOrder = function (dir) { | |
switch (dir) { | |
case Solver.LEFT: | |
return [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; | |
case Solver.RIGHT: | |
return [3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12]; | |
case Solver.UP: | |
return [0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15]; | |
case Solver.DOWN: | |
return [12, 8, 4, 0, 13, 9, 5, 1, 14, 10, 6, 2, 15, 11, 7, 3]; | |
} | |
}; | |
Solver.transform = function (board, dir) { | |
var changed = false, | |
src, | |
dst; | |
var order = Solver.getTransformOrder(dir); | |
for (var i = 0; i < 16; i += 4) { | |
src = Solver.getLookupIndex( | |
board[order[i]], | |
board[order[i + 1]], | |
board[order[i + 2]], | |
board[order[i + 3]] | |
); | |
dst = Solver.lineLookup[src]; | |
if (dst) { | |
changed = true; | |
board[order[i]] = dst[0]; | |
board[order[i + 1]] = dst[1]; | |
board[order[i + 2]] = dst[2]; | |
board[order[i + 3]] = dst[3]; | |
} | |
} | |
return changed; | |
}; | |
Solver.calculateScore = function (board) { | |
var distances = [0, 1, 1, 0, 1, 2, 2, 1, 1, 2, 2, 1, 0, 1, 1, 0]; | |
var score = 0; | |
var max = Math.max.apply(null, board); | |
for (var i = 0; i < board.length; ++i) { | |
var scale = board[i] / max; | |
score = score + (board[i] === 0 ? 1 : 0) - scale * distances[i]; | |
} | |
// monotonicity | |
function isMonotone(a, b, c, d) { | |
return (a <= b && b <= c && c <= d) || (a >= b && b >= c && c >= d); | |
} | |
var mono = 0; | |
for (var o = 0; o < 4; ++o) { | |
if (isMonotone(board[o], board[o + 4], board[o + 8], board[o + 12])) { | |
++mono; | |
} | |
var y = o * 4; | |
if (isMonotone(board[y], board[y + 1], board[y + 2], board[y + 3])) { | |
++mono; | |
} | |
} | |
score += mono / 4; | |
return score; | |
}; | |
Solver.pickDirection = function (board, levels) { | |
var result = { direction: Solver.LEFT, score: -Infinity }; | |
Solver.DIRECTIONS.forEach(function (dir) { | |
var b = board.slice(); | |
var changed = Solver.transform(b, dir); | |
if (!changed) { | |
return; | |
} | |
var score = Solver.calculateScore(b); | |
if (levels > 0) { | |
score += Solver.pickDirection(b, levels - 1).score * 0.5; | |
} | |
if (score > result.score) { | |
result.direction = dir; | |
result.score = score; | |
} | |
}); | |
return result; | |
}; | |
Solver.next = function () { | |
var result = Solver.pickDirection(Solver.readBoard(), 6); | |
Solver.move(result.direction); | |
}; | |
var intval = null; | |
Solver.start = function () { | |
if (!intval) { | |
intval = setRandomInterval(Solver.next, 3000, 5000); | |
} | |
}; | |
Solver.stop = function () { | |
if (intval) { | |
intval.clear(); | |
} | |
intval = null; | |
}; | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment