2048bot

Lie back and watch the dumb bot play!

  1. // ==UserScript==
  2. // @name 2048bot
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.9415
  5. // @description Lie back and watch the dumb bot play!
  6. // @author boynextdesk
  7. // @match https://play2048.co/*
  8. // @icon https://play2048.co/favicon.ico
  9. // @grant none
  10. // @license GNU General Public License v3.0
  11. // ==/UserScript==
  12.  
  13. /*
  14. * 128 64 32 16
  15. * 64 32 16 8
  16. * 32 16 8 4
  17. * 16 8 4 2
  18. *
  19. * */
  20.  
  21. (function() {
  22. // todo: inspect whether game is over
  23. // todo: train strategy after game-over
  24. // todo: set speed and strategy through page
  25. // todo: beautify layout
  26. // todo: everlasting game - auto retry until winning
  27. // todo: bundle direction-ava functinos into an object to global users
  28. 'use strict';
  29. const eventUp = new KeyboardEvent('keydown', {
  30. key: "w",
  31. keyCode: 87,
  32. which: 87,
  33. code: "KeyW",
  34. location: 0,
  35. description: "w"
  36. });
  37. const eventLeft = new KeyboardEvent('keydown', {
  38. key: "a",
  39. keyCode: 65,
  40. which: 65,
  41. code: "KeyA",
  42. location: 0,
  43. description: "a"
  44. });
  45. const eventRight = new KeyboardEvent('keydown', {
  46. key: "d",
  47. keyCode: 68,
  48. which: 68,
  49. code: "KeyD",
  50. location: 0,
  51. description: "d"
  52. });
  53. const eventDown = new KeyboardEvent('keydown', {
  54. key: "s",
  55. keyCode: 83,
  56. which: 83,
  57. code: "KeyS",
  58. location: 0,
  59. description: "s"
  60. });
  61.  
  62. // thanks to https://zeit.co/blog/async-and-await
  63. function sleep (time) {
  64. return new Promise((resolve) => setTimeout(resolve, time));
  65. }
  66. function lose() {
  67. return document.getElementsByClassName("game-message game-over")[0] != null
  68. }
  69. function win() {
  70. return document.getElementsByClassName("game-message game-win")[0] != null
  71. }
  72. function over() {
  73. return lose() || win()
  74. }
  75. function inspect() {
  76. const board = Array();
  77. for(let j = 1 ; j <= 4 ; j++) // row
  78. {
  79. const unit4 = Array();
  80. for(let i = 1 ; i <= 4 ; i++) //column
  81. {
  82. const className = "tile-position-"+i+"-"+j
  83. const tiles = document.getElementsByClassName(className)
  84. const len = tiles.length
  85. const tile = tiles[len - 1]
  86. /// console.log(className)
  87. let val = 0;
  88. if(tile != null){
  89. val = tile.firstChild.lastChild.nodeValue
  90. val = Number(val)
  91. /// console.log(val)
  92. }
  93. unit4[i] = val
  94. }
  95. board[j] = unit4
  96. }
  97. return board
  98. }
  99. const aboveBox = document.getElementsByClassName("above-game")[0];
  100. const btnTemplate = document.getElementsByClassName("restart-button")[0];
  101. let speed = 10;
  102. let speedIndex = 0;
  103. let switchU = true;
  104. aboveBox.appendChild(btnTemplate.cloneNode(false));
  105. aboveBox.appendChild(btnTemplate.cloneNode(false));
  106. aboveBox.appendChild(btnTemplate.cloneNode(false));
  107. //
  108. const btns = document.getElementsByClassName("restart-button");
  109. //
  110. const btnStartAuto = btns[1];
  111. const startText = document.createTextNode("Start Auto");
  112. btnStartAuto.appendChild(startText)
  113. //
  114. const btnStopAuto = btns[2];
  115. const stopText = document.createTextNode("Stop Auto");
  116. btnStopAuto.appendChild(stopText)
  117. //
  118. const btnSpeedAuto = btns[3];
  119. const speedText = document.createTextNode("Change Speed");
  120. btnSpeedAuto.appendChild(speedText)
  121. //
  122. let moveOn = false;
  123. let moveCnt = 0;
  124. let globalBoard = null;
  125. document.tagName = "not input"
  126. const strategy01 = function () {
  127. const num = Math.random();
  128. let dispatchee = null;
  129. moveCnt += 1
  130. const rate = 1 - Math.min(48 / moveCnt, 0.8)
  131. const downL = 0.02 * rate
  132. const rightL = downL + 0.02 * rate;
  133. if (num < downL) {
  134. dispatchee = eventDown;
  135. console.log("down");
  136. } else if (num < rightL) {
  137. dispatchee = eventRight;
  138. console.log("right");
  139. } else if (switchU) {
  140. dispatchee = eventLeft
  141. console.log("left")
  142. switchU = false
  143. } else {
  144. dispatchee = eventUp
  145. console.log("up")
  146. switchU = true
  147. }
  148. return dispatchee
  149. };
  150. const strategy02 = function () {
  151. const board = globalBoard
  152. if(board == null)
  153. return eventLeft
  154. const directionAvailable = function(offsetI, offsetJ){
  155. for(let i = 1 ; i <= 4 ; i++){
  156. for(let j = 1 ; j <= 4 ; j++){
  157. const ni = i + offsetI
  158. const nj = j + offsetJ
  159. if(ni < 1 || ni > 4) continue
  160. if(nj < 1 || nj > 4) continue
  161. if(board[i][j] === 0) continue;
  162. if(board[ni][nj] === board[i][j] || board[ni][nj] === 0)
  163. return true
  164. }
  165. }
  166. return false
  167. }
  168. const dir = [[0, -1], [-1, 0], [1, 0], [0, 1]]
  169. const msg = ["left", "up", "down", "right"]
  170. const funcArr = [eventLeft, eventUp, eventDown, eventRight]
  171. for(let i = 0 ; i < 4 ; i++){
  172. const con = directionAvailable(dir[i][0], dir[i][1])
  173. if(con){
  174. console.log(msg[i])
  175. return funcArr[i]
  176. }
  177. //console.log(msg[i] + " unavailable")
  178. }
  179. return funcArr[0]
  180. }
  181. const moveOneKey = function () {
  182. if (!moveOn) {
  183. console.log("Cancelled.")
  184. return
  185. }
  186. const dispatchee = strategy02();
  187. document.dispatchEvent(dispatchee)
  188. };
  189.  
  190. const startListener = async function () {
  191. console.log("start")
  192. moveOn = true;
  193. while (moveOn) {
  194. await sleep(10 * speed).then(() => {
  195. if(over()){
  196. moveOn = false
  197. console.log("Game over.")
  198. }
  199. const board = inspect();
  200. console.log(board)
  201. globalBoard = board
  202. })
  203. await sleep(70 * speed).then(moveOneKey)
  204. }
  205. };
  206.  
  207. const stopListener = function () {
  208. moveOn = false;
  209. moveCnt = 0
  210. }
  211. const speedListener = function () {
  212. const speeds = [10, 5, 1];
  213. const words = ["switch to low speed", "switch to fast speed", "switch to super fast speed"];
  214. const len = 3
  215. speedIndex = (speedIndex + 1) % len
  216. speed = speeds[speedIndex]
  217. console.log(words[speedIndex])
  218. }
  219.  
  220. btnStartAuto.addEventListener('click', startListener)
  221. btnStopAuto.addEventListener('click', stopListener)
  222. btnSpeedAuto.addEventListener('click', speedListener)
  223.  
  224. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址