Guest User

Untitled

a guest
May 25th, 2016
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 52.12 KB | None | 0 0
  1. /*
  2. The MIT License (MIT)
  3. Copyright (c) 2016 Jesse Miller <jmiller@jmiller.com>
  4. Copyright (c) 2016 Ermiya Eskandary & Théophile Cailliau and other contributors
  5. https://jmiller.mit-license.org/
  6. */
  7. // ==UserScript==
  8. // @name Slither.io Bot Championship Edition
  9. // @namespace https://github.com/j-c-m/Slither.io-bot
  10. // @version 1.8.7
  11. // @description Slither.io Bot Championship Edition
  12. // @author Jesse Miller
  13. // @match http://slither.io/
  14. // @updateURL https://github.com/j-c-m/Slither.io-bot/raw/master/bot.user.js
  15. // @downloadURL https://github.com/j-c-m/Slither.io-bot/raw/master/bot.user.js
  16. // @supportURL https://github.com/j-c-m/Slither.io-bot/issues
  17. // @grant none
  18. // ==/UserScript==
  19.  
  20.  
  21. const TARGET_FPS = 30;
  22. window.doDefense = false;
  23.  
  24. // Custom logging function - disabled by default
  25. window.log = function () {
  26. if (window.logDebugging) {
  27. console.log.apply(console, arguments);
  28. }
  29. };
  30.  
  31. window.getSnakeLength = function () {
  32. return (Math.floor(
  33. 150 *
  34. (window.fpsls[window.snake.sct] + window.snake.fam / window.fmlts[window.snake.sct] - 1) -
  35. 50) / 10);
  36. };
  37. window.getSnakeWidth = function (sc) {
  38. if (sc === undefined) sc = window.snake.sc;
  39. return Math.round(sc * 29.0);
  40. };
  41.  
  42. var canvas = window.canvas = (function () {
  43. return {
  44. // Ratio of screen size divided by canvas size.
  45. canvasRatio: {
  46. x: window.mc.width / window.ww,
  47. y: window.mc.height / window.hh
  48. },
  49.  
  50. // Spoofs moving the mouse to the provided coordinates.
  51. setMouseCoordinates: function (point) {
  52. window.xm = point.x;
  53. window.ym = point.y;
  54. },
  55.  
  56. // Convert snake-relative coordinates to absolute screen coordinates.
  57. mouseToScreen: function (point) {
  58. var screenX = point.x + (window.ww / 2);
  59. var screenY = point.y + (window.hh / 2);
  60. return { x: screenX, y: screenY };
  61. },
  62.  
  63. // Convert screen coordinates to canvas coordinates.
  64. screenToCanvas: function (point) {
  65. var canvasX = window.csc *
  66. (point.x * canvas.canvasRatio.x) - parseInt(window.mc.style.left);
  67. var canvasY = window.csc *
  68. (point.y * canvas.canvasRatio.y) - parseInt(window.mc.style.top);
  69. return { x: canvasX, y: canvasY };
  70. },
  71.  
  72. // Convert map coordinates to mouse coordinates.
  73. mapToMouse: function (point) {
  74. var mouseX = (point.x - window.snake.xx) * window.gsc;
  75. var mouseY = (point.y - window.snake.yy) * window.gsc;
  76. return { x: mouseX, y: mouseY };
  77. },
  78.  
  79. // Map cordinates to Canvas cordinate shortcut
  80. mapToCanvas: function (point) {
  81. var c = canvas.mapToMouse(point);
  82. c = canvas.mouseToScreen(c);
  83. c = canvas.screenToCanvas(c);
  84. return c;
  85. },
  86.  
  87. // Map to Canvas coordinate conversion for drawing circles.
  88. // Radius also needs to scale by .gsc
  89. circleMapToCanvas: function (circle) {
  90. var newCircle = canvas.mapToCanvas(circle);
  91. return canvas.circle(
  92. newCircle.x,
  93. newCircle.y,
  94. circle.radius * window.gsc
  95. );
  96. },
  97.  
  98. // Constructor for point type
  99. point: function (x, y) {
  100. var p = {
  101. x: Math.round(x),
  102. y: Math.round(y)
  103. };
  104.  
  105. return p;
  106. },
  107.  
  108. // Constructor for rect type
  109. rect: function (x, y, w, h) {
  110. var r = {
  111. x: Math.round(x),
  112. y: Math.round(y),
  113. width: Math.round(w),
  114. height: Math.round(h)
  115. };
  116.  
  117. return r;
  118. },
  119.  
  120. // Constructor for circle type
  121. circle: function (x, y, r) {
  122. var c = {
  123. x: Math.round(x),
  124. y: Math.round(y),
  125. radius: Math.round(r)
  126. };
  127.  
  128. return c;
  129. },
  130.  
  131. // Fast atan2
  132. fastAtan2: function (y, x) {
  133. const QPI = Math.PI / 4;
  134. const TQPI = 3 * Math.PI / 4;
  135. var r = 0.0;
  136. var angle = 0.0;
  137. var abs_y = Math.abs(y) + 1e-10;
  138. if (x < 0) {
  139. r = (x + abs_y) / (abs_y - x);
  140. angle = TQPI;
  141. } else {
  142. r = (x - abs_y) / (x + abs_y);
  143. angle = QPI;
  144. }
  145. angle += (0.1963 * r * r - 0.9817) * r;
  146. if (y < 0) {
  147. return -angle;
  148. }
  149.  
  150. return angle;
  151. },
  152.  
  153. // Adjusts zoom in response to the mouse wheel.
  154. setZoom: function (e) {
  155. // Scaling ratio
  156. if (window.gsc) {
  157. window.gsc *= Math.pow(0.9, e.wheelDelta / -120 || e.detail / 2 || 0);
  158. window.desired_gsc = window.gsc;
  159. }
  160. },
  161.  
  162. // Restores zoom to the default value.
  163. resetZoom: function () {
  164. window.gsc = 0.9;
  165. window.desired_gsc = 0.9;
  166. },
  167.  
  168. // Maintains Zoom
  169. maintainZoom: function () {
  170. if (window.desired_gsc !== undefined) {
  171. window.gsc = window.desired_gsc;
  172. }
  173. },
  174.  
  175. // Sets background to the given image URL.
  176. // Defaults to slither.io's own background.
  177. setBackground: function (url) {
  178. url = typeof url !== 'undefined' ? url : '/s/bg45.jpg';
  179. window.ii.src = url;
  180. },
  181.  
  182. // Draw a rectangle on the canvas.
  183. drawRect: function (rect, color, fill, alpha) {
  184. if (alpha === undefined) alpha = 1;
  185.  
  186. var context = window.mc.getContext('2d');
  187. var lc = canvas.mapToCanvas({ x: rect.x, y: rect.y });
  188.  
  189. context.save();
  190. context.globalAlpha = alpha;
  191. context.strokeStyle = color;
  192. context.rect(lc.x, lc.y, rect.width * window.gsc, rect.height * window.gsc);
  193. context.stroke();
  194. if (fill) {
  195. context.fillStyle = color;
  196. context.fill();
  197. }
  198. context.restore();
  199. },
  200.  
  201. // Draw a circle on the canvas.
  202. drawCircle: function (circle, color, fill, alpha) {
  203. if (alpha === undefined) alpha = 1;
  204. if (circle.radius === undefined) circle.radius = 30;
  205.  
  206. var context = window.mc.getContext('2d');
  207. var drawCircle = canvas.circleMapToCanvas(circle);
  208.  
  209. context.save();
  210. context.globalAlpha = alpha;
  211. context.beginPath();
  212. context.strokeStyle = color;
  213. context.arc(drawCircle.x, drawCircle.y, drawCircle.radius, 0, Math.PI * 2);
  214. context.stroke();
  215. if (fill) {
  216. context.fillStyle = color;
  217. context.fill();
  218. }
  219. context.restore();
  220. },
  221.  
  222. // Draw an angle.
  223. // @param {number} start -- where to start the angle
  224. // @param {number} angle -- width of the angle
  225. // @param {bool} danger -- green if false, red if true
  226. drawAngle: function (start, angle, color, fill, alpha) {
  227. if (alpha === undefined) alpha = 0.6;
  228.  
  229. var context = window.mc.getContext('2d');
  230.  
  231. context.save();
  232. context.globalAlpha = alpha;
  233. context.beginPath();
  234. context.moveTo(window.mc.width / 2, window.mc.height / 2);
  235. context.arc(window.mc.width / 2, window.mc.height / 2, window.gsc * 100, start, angle);
  236. context.lineTo(window.mc.width / 2, window.mc.height / 2);
  237. context.closePath();
  238. context.stroke();
  239. if (fill) {
  240. context.fillStyle = color;
  241. context.fill();
  242. }
  243. context.restore();
  244. },
  245.  
  246. // Draw a line on the canvas.
  247. drawLine: function (p1, p2, color, width) {
  248. if (width === undefined) width = 5;
  249.  
  250. var context = window.mc.getContext('2d');
  251. var dp1 = canvas.mapToCanvas(p1);
  252. var dp2 = canvas.mapToCanvas(p2);
  253.  
  254. context.save();
  255. context.beginPath();
  256. context.lineWidth = width * window.gsc;
  257. context.strokeStyle = color;
  258. context.moveTo(dp1.x, dp1.y);
  259. context.lineTo(dp2.x, dp2.y);
  260. context.stroke();
  261. context.restore();
  262. },
  263.  
  264. // Given the start and end of a line, is point left.
  265. isLeft: function (start, end, point) {
  266. return ((end.x - start.x) * (point.y - start.y) -
  267. (end.y - start.y) * (point.x - start.x)) > 0;
  268.  
  269. },
  270.  
  271. // Get distance squared
  272. getDistance2: function (x1, y1, x2, y2) {
  273. var distance2 = Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2);
  274. return distance2;
  275. },
  276.  
  277. getDistance2FromSnake: function (point) {
  278. point.distance = canvas.getDistance2(window.snake.xx, window.snake.yy,
  279. point.xx, point.yy);
  280. return point;
  281. },
  282.  
  283. // Check if point in Rect
  284. pointInRect: function (point, rect) {
  285. if (rect.x <= point.x && rect.y <= point.y &&
  286. rect.x + rect.width >= point.x && rect.y + rect.height >= point.y) {
  287. return true;
  288. }
  289. return false;
  290. },
  291.  
  292. // Check if circles intersect
  293. circleIntersect: function (circle1, circle2) {
  294. var bothRadii = circle1.radius + circle2.radius;
  295.  
  296. // Pretends the circles are squares for a quick collision check.
  297. // If it collides, do the more expensive circle check.
  298. if (circle1.x + bothRadii > circle2.x &&
  299. circle1.y + bothRadii > circle2.y &&
  300. circle1.x < circle2.x + bothRadii &&
  301. circle1.y < circle2.y + bothRadii) {
  302.  
  303. var distance2 = canvas.getDistance2(circle1.x, circle1.y, circle2.x, circle2.y);
  304.  
  305. if (distance2 < bothRadii * bothRadii) {
  306. if (window.visualDebugging) {
  307. var collisionPointCircle = canvas.circle(
  308. ((circle1.x * circle2.radius) + (circle2.x * circle1.radius)) /
  309. bothRadii,
  310. ((circle1.y * circle2.radius) + (circle2.y * circle1.radius)) /
  311. bothRadii,
  312. 5
  313. );
  314. canvas.drawCircle(circle2, 'red', true);
  315. canvas.drawCircle(collisionPointCircle, 'cyan', true);
  316. }
  317. return true;
  318. }
  319. }
  320. return false;
  321. }
  322. };
  323. })();
  324.  
  325. var bot = window.bot = (function () {
  326. return {
  327. isBotRunning: false,
  328. isBotEnabled: true,
  329. lookForFood: false,
  330. collisionPoints: [],
  331. collisionAngles: [],
  332. scores: [],
  333. foodTimeout: undefined,
  334. sectorBoxSide: 0,
  335. defaultAccel: 0,
  336. sectorBox: {},
  337. currentFood: {},
  338. MID_X: 0,
  339. MID_Y: 0,
  340. MAP_R: 0,
  341.  
  342. quickRespawn: function () {
  343. window.dead_mtm = 0;
  344. window.login_fr = 0;
  345.  
  346. bot.isBotRunning = false;
  347. window.forcing = true;
  348. window.connect();
  349. window.forcing = false;
  350. },
  351.  
  352. // angleBetween - get the smallest angle between two angles (0-pi)
  353. angleBetween: function (a1, a2) {
  354. var r1 = 0.0;
  355. var r2 = 0.0;
  356.  
  357. r1 = (a1 - a2) % Math.PI;
  358. r2 = (a2 - a1) % Math.PI;
  359.  
  360. return r1 < r2 ? -r1 : r2;
  361. },
  362.  
  363. // Avoid headPoint
  364. avoidHeadPoint: function (collisionPoint) {
  365. var cehang = canvas.fastAtan2(
  366. collisionPoint.yy - window.snake.yy, collisionPoint.xx - window.snake.xx);
  367. var diff = bot.angleBetween(window.snake.ehang, cehang);
  368.  
  369. // var dir = diff > 0 ? -Math.PI / 2 : Math.PI / 2;
  370. // bot.changeHeading(dir);
  371. // return;
  372.  
  373. if (Math.abs(diff) > 3 * Math.PI / 4) {
  374. var dir = diff > 0 ? -Math.PI / 2 : Math.PI / 2;
  375. bot.changeHeading(dir);
  376. } else {
  377. bot.avoidCollisionPoint(collisionPoint);
  378. }
  379. },
  380.  
  381. // Change heading by ang
  382. // +0-pi turn left
  383. // -0-pi turn right
  384.  
  385. changeHeading: function (angle) {
  386. var heading = {
  387. x: window.snake.xx + 500 * window.snake.cos,
  388. y: window.snake.yy + 500 * window.snake.sin
  389. };
  390.  
  391. var cos = Math.cos(-angle);
  392. var sin = Math.sin(-angle);
  393.  
  394. window.goalCoordinates = {
  395. x: Math.round(
  396. cos * (heading.x - window.snake.xx) -
  397. sin * (heading.y - window.snake.yy) + window.snake.xx),
  398. y: Math.round(
  399. sin * (heading.x - window.snake.xx) +
  400. cos * (heading.y - window.snake.yy) + window.snake.yy)
  401. };
  402.  
  403. canvas.setMouseCoordinates(canvas.mapToMouse(window.goalCoordinates));
  404. },
  405.  
  406. // Avoid collison point by ang
  407. // ang radians <= Math.PI (180deg)
  408. avoidCollisionPoint: function (collisionPoint, ang) {
  409. if (ang === undefined || ang > Math.PI) {
  410. ang = Math.PI;
  411. }
  412.  
  413. var end = {
  414. x: window.snake.xx + 2000 * window.snake.cos,
  415. y: window.snake.yy + 2000 * window.snake.sin
  416. };
  417.  
  418. if (window.visualDebugging) {
  419. canvas.drawLine(
  420. { x: window.snake.xx, y: window.snake.yy },
  421. end,
  422. 'orange', 5);
  423. canvas.drawLine(
  424. { x: window.snake.xx, y: window.snake.yy },
  425. { x: collisionPoint.xx, y: collisionPoint.yy },
  426. 'red', 5);
  427. }
  428.  
  429. var cos = Math.cos(ang);
  430. var sin = Math.sin(ang);
  431.  
  432. if (canvas.isLeft(
  433. { x: window.snake.xx, y: window.snake.yy }, end,
  434. { x: collisionPoint.xx, y: collisionPoint.yy })) {
  435. sin = -sin;
  436. }
  437.  
  438. window.goalCoordinates = {
  439. x: Math.round(
  440. cos * (collisionPoint.xx - window.snake.xx) -
  441. sin * (collisionPoint.yy - window.snake.yy) + window.snake.xx),
  442. y: Math.round(
  443. sin * (collisionPoint.xx - window.snake.xx) +
  444. cos * (collisionPoint.yy - window.snake.yy) + window.snake.yy)
  445. };
  446.  
  447. canvas.setMouseCoordinates(canvas.mapToMouse(window.goalCoordinates));
  448. },
  449.  
  450. // Sorting by property 'distance'
  451. sortDistance: function (a, b) {
  452. return a.distance - b.distance;
  453. },
  454.  
  455. // get collision angle index, expects angle +/i 0 to Math.PI
  456. getAngleIndex: function (angle) {
  457. const ARCSIZE = Math.PI / 4;
  458. var index;
  459.  
  460. if (angle < 0) {
  461. angle += 2 * Math.PI;
  462. }
  463.  
  464. index = Math.round(angle * (1 / ARCSIZE));
  465.  
  466. if (index === (2 * Math.PI) / ARCSIZE) {
  467. return 0;
  468. }
  469. return index;
  470. },
  471.  
  472. // Add to collisionAngles if distance is closer
  473. addCollisionAngle: function (sp) {
  474. var ang = canvas.fastAtan2(
  475. Math.round(sp.yy - window.snake.yy),
  476. Math.round(sp.xx - window.snake.xx));
  477. var aIndex = bot.getAngleIndex(ang);
  478.  
  479. var actualDistance = Math.round(
  480. sp.distance - (Math.pow(sp.radius, 2) / 2));
  481.  
  482. if (bot.collisionAngles[aIndex] === undefined) {
  483. bot.collisionAngles[aIndex] = {
  484. x: Math.round(sp.xx),
  485. y: Math.round(sp.yy),
  486. ang: ang,
  487. snake: sp.snake,
  488. distance: actualDistance
  489. };
  490. } else if (bot.collisionAngles[aIndex].distance > sp.distance) {
  491. bot.collisionAngles[aIndex].x = Math.round(sp.xx);
  492. bot.collisionAngles[aIndex].y = Math.round(sp.yy);
  493. bot.collisionAngles[aIndex].ang = ang;
  494. bot.collisionAngles[aIndex].snake = sp.snake;
  495. bot.collisionAngles[aIndex].distance = actualDistance;
  496. }
  497. },
  498.  
  499. // Get closest collision point per snake.
  500. getCollisionPoints: function () {
  501. var scPoint;
  502.  
  503. bot.collisionPoints = [];
  504. bot.collisionAngles = [];
  505.  
  506.  
  507. for (var snake = 0, ls = window.snakes.length; snake < ls; snake++) {
  508. scPoint = undefined;
  509.  
  510. if (window.snakes[snake].id !== window.snake.id &&
  511. window.snakes[snake].alive_amt === 1) {
  512.  
  513. scPoint = {
  514. xx: window.snakes[snake].xx,
  515. yy: window.snakes[snake].yy,
  516. snake: snake,
  517. radius: window.getSnakeWidth(window.snakes[snake].sc) / 2
  518. };
  519. canvas.getDistance2FromSnake(scPoint);
  520. bot.addCollisionAngle(scPoint);
  521. if (window.visualDebugging) {
  522. canvas.drawCircle(canvas.circle(
  523. scPoint.xx,
  524. scPoint.yy,
  525. scPoint.radius),
  526. 'red', false);
  527. }
  528.  
  529. for (var pts = 0, lp = window.snakes[snake].pts.length; pts < lp; pts++) {
  530. if (!window.snakes[snake].pts[pts].dying &&
  531. canvas.pointInRect(
  532. {
  533. x: window.snakes[snake].pts[pts].xx,
  534. y: window.snakes[snake].pts[pts].yy
  535. }, bot.sectorBox)
  536. ) {
  537. var collisionPoint = {
  538. xx: window.snakes[snake].pts[pts].xx,
  539. yy: window.snakes[snake].pts[pts].yy,
  540. snake: snake,
  541. radius: window.getSnakeWidth(window.snakes[snake].sc) / 2
  542. };
  543.  
  544. if (window.visualDebugging && true === false) {
  545. canvas.drawCircle(canvas.circle(
  546. collisionPoint.xx,
  547. collisionPoint.yy,
  548. collisionPoint.radius),
  549. '#00FF00', false);
  550. }
  551.  
  552. canvas.getDistance2FromSnake(collisionPoint);
  553. bot.addCollisionAngle(collisionPoint);
  554.  
  555. if (scPoint === undefined ||
  556. scPoint.distance > collisionPoint.distance) {
  557. scPoint = collisionPoint;
  558. }
  559. }
  560. }
  561. }
  562. if (scPoint !== undefined) {
  563. bot.collisionPoints.push(scPoint);
  564. if (window.visualDebugging) {
  565. canvas.drawCircle(canvas.circle(
  566. scPoint.xx,
  567. scPoint.yy,
  568. scPoint.radius
  569. ), 'red', false);
  570. }
  571. }
  572. }
  573.  
  574. // WALL
  575. if (canvas.getDistance2(bot.MID_X, bot.MID_Y, window.snake.xx, window.snake.yy) >
  576. Math.pow(bot.MAP_R - 1000, 2)) {
  577. var midAng = canvas.fastAtan2(
  578. window.snake.yy - bot.MID_X, window.snake.xx - bot.MID_Y);
  579. scPoint = {
  580. xx: bot.MID_X + bot.MAP_R * Math.cos(midAng),
  581. yy: bot.MID_Y + bot.MAP_R * Math.sin(midAng),
  582. snake: -1,
  583. radius: window.getSnakeWidth()
  584. };
  585. canvas.getDistance2FromSnake(scPoint);
  586. bot.collisionPoints.push(scPoint);
  587. bot.addCollisionAngle(scPoint);
  588. if (window.visualDebugging) {
  589. canvas.drawCircle(canvas.circle(
  590. scPoint.xx,
  591. scPoint.yy,
  592. scPoint.radius
  593. ), 'yellow', false);
  594. }
  595. }
  596.  
  597.  
  598. bot.collisionPoints.sort(bot.sortDistance);
  599. if (window.visualDebugging) {
  600. for (var i = 0; i < bot.collisionAngles.length; i++) {
  601. if (bot.collisionAngles[i] !== undefined) {
  602. canvas.drawLine(
  603. { x: window.snake.xx, y: window.snake.yy },
  604. { x: bot.collisionAngles[i].x, y: bot.collisionAngles[i].y },
  605. '#99ffcc', 2);
  606. }
  607. }
  608. }
  609. },
  610.  
  611. // Checks to see if you are going to collide with anything in the collision detection radius
  612. checkCollision: function (r) {
  613. if (!window.collisionDetection) return false;
  614.  
  615. r = Number(r);
  616. var xx = Number(window.snake.xx.toFixed(3));
  617. var yy = Number(window.snake.yy.toFixed(3));
  618.  
  619. window.snake.cos = Math.cos(window.snake.ang).toFixed(3);
  620. window.snake.sin = Math.sin(window.snake.ang).toFixed(3);
  621.  
  622. const speedMult = window.snake.sp / 5.78;
  623. const widthMult = window.getSnakeWidth();
  624.  
  625. var headCircle = canvas.circle(
  626. xx, yy,
  627. speedMult * r / 2 * widthMult / 2
  628. );
  629.  
  630. var fullHeadCircle = canvas.circle(
  631. xx, yy,
  632. r * widthMult / 2
  633. );
  634.  
  635. var sidecircle_r = canvas.circle(
  636. window.snake.lnp.xx -
  637. ((window.snake.lnp.yy + window.snake.sin * window.getSnakeWidth()) -
  638. window.snake.lnp.yy),
  639. window.snake.lnp.yy +
  640. ((window.snake.lnp.xx + window.snake.cos * window.getSnakeWidth()) -
  641. window.snake.lnp.xx),
  642. window.getSnakeWidth() * speedMult
  643. );
  644.  
  645. var sidecircle_l = canvas.circle(
  646. window.snake.lnp.xx +
  647. ((window.snake.lnp.yy + window.snake.sin * window.getSnakeWidth()) -
  648. window.snake.lnp.yy),
  649. window.snake.lnp.yy -
  650. ((window.snake.lnp.xx + window.snake.cos * window.getSnakeWidth()) -
  651. window.snake.lnp.xx),
  652. window.getSnakeWidth() * speedMult
  653. );
  654.  
  655. window.snake.sidecircle_r = sidecircle_r;
  656. window.snake.sidecircle_l = sidecircle_l;
  657.  
  658. if (window.visualDebugging) {
  659. canvas.drawCircle(fullHeadCircle, 'red');
  660. canvas.drawCircle(headCircle, 'blue', false);
  661. // canvas.drawCircle(sidecircle_r, 'orange', true, 0.3);
  662. // canvas.drawCircle(sidecircle_l, 'orange', true, 0.3);
  663. }
  664.  
  665. bot.getCollisionPoints();
  666. if (bot.collisionPoints.length === 0) return false;
  667.  
  668. for (var i = 0; i < bot.collisionPoints.length; i++) {
  669. // -1 snake is special case for non snake object.
  670.  
  671. var collisionCircle = canvas.circle(
  672. bot.collisionPoints[i].xx,
  673. bot.collisionPoints[i].yy,
  674. bot.collisionPoints[i].radius
  675. );
  676.  
  677. if (canvas.circleIntersect(headCircle, collisionCircle)) {
  678. window.setAcceleration(bot.defaultAccel);
  679. bot.avoidCollisionPoint(bot.collisionPoints[i]);
  680. return true;
  681. }
  682.  
  683. if (bot.collisionPoints[i].snake !== -1) {
  684. var eHeadCircle = canvas.circle(
  685. window.snakes[bot.collisionPoints[i].snake].xx,
  686. window.snakes[bot.collisionPoints[i].snake].yy,
  687. bot.collisionPoints[i].radius
  688. );
  689.  
  690.  
  691. if (canvas.circleIntersect(fullHeadCircle, eHeadCircle)) {
  692. if (window.snakes[bot.collisionPoints[i].snake].sp > 10) {
  693. window.setAcceleration(1);
  694. } else {
  695. window.setAcceleration(bot.defaultAccel);
  696. }
  697. bot.avoidHeadPoint({
  698. xx: window.snakes[bot.collisionPoints[i].snake].xx,
  699. yy: window.snakes[bot.collisionPoints[i].snake].yy
  700. });
  701. return true;
  702. }
  703. }
  704. }
  705. window.setAcceleration(bot.defaultAccel);
  706. return false;
  707. },
  708.  
  709. sortScore: function (a, b) {
  710. return b.score - a.score;
  711. },
  712.  
  713. // 2.546 ~ 1 / (Math.PI / 8) - round angle difference up to nearest 22.5 degrees.
  714. // Round food up to nearest 5, square for distance^2
  715. scoreFood: function (f) {
  716. f.score = Math.pow(Math.ceil(f.sz / 5) * 5, 2) /
  717. f.distance / (Math.ceil(f.da * 2.546) / 2.546);
  718. },
  719.  
  720. computeFoodGoal: function () {
  721. var foodClusters = [];
  722. var foodGetIndex = [];
  723. var fi = 0;
  724. var sw = window.getSnakeWidth();
  725.  
  726. for (var i = 0; i < window.foods.length && window.foods[i] !== null; i++) {
  727. var a;
  728. var da;
  729. var distance;
  730. var sang = window.snake.ehang;
  731. var f = window.foods[i];
  732.  
  733. if (!f.eaten &&
  734. !(
  735. canvas.circleIntersect(
  736. canvas.circle(f.xx, f.yy, 2),
  737. window.snake.sidecircle_l) ||
  738. canvas.circleIntersect(
  739. canvas.circle(f.xx, f.yy, 2),
  740. window.snake.sidecircle_r))) {
  741.  
  742. var cx = Math.round(Math.round(f.xx / sw) * sw);
  743. var cy = Math.round(Math.round(f.yy / sw) * sw);
  744. var csz = Math.round(f.sz);
  745.  
  746. if (foodGetIndex[cx + '|' + cy] === undefined) {
  747. foodGetIndex[cx + '|' + cy] = fi;
  748. a = canvas.fastAtan2(cy - window.snake.yy, cx - window.snake.xx);
  749. da = Math.min(
  750. (2 * Math.PI) - Math.abs(a - sang), Math.abs(a - sang));
  751. distance = Math.round(
  752. canvas.getDistance2(cx, cy, window.snake.xx, window.snake.yy));
  753. foodClusters[fi] = {
  754. x: cx, y: cy, a: a, da: da, sz: csz, distance: distance, score: 0.0
  755. };
  756. fi++;
  757. } else {
  758. foodClusters[foodGetIndex[cx + '|' + cy]].sz += csz;
  759. }
  760. }
  761. }
  762.  
  763. foodClusters.forEach(bot.scoreFood);
  764. foodClusters.sort(bot.sortScore);
  765.  
  766. for (i = 0; i < foodClusters.length; i++) {
  767. var aIndex = bot.getAngleIndex(foodClusters[i].a);
  768. if (bot.collisionAngles[aIndex] === undefined ||
  769. (bot.collisionAngles[aIndex].distance - Math.pow(window.getSnakeWidth(), 2) >
  770. foodClusters[i].distance && foodClusters[i].sz > 10)
  771. ) {
  772. bot.currentFood = foodClusters[i];
  773. return;
  774. }
  775. }
  776. bot.currentFood = { x: bot.MID_X, y: bot.MID_Y };
  777. },
  778.  
  779. foodAccel: function () {
  780. var aIndex = 0;
  781.  
  782. if (bot.currentFood && bot.currentFood.sz > 60) {
  783. aIndex = bot.getAngleIndex(bot.currentFood.a);
  784.  
  785. if (
  786. bot.collisionAngles[aIndex] && bot.collisionAngles[aIndex].distance >
  787. bot.currentFood.distance * 2 && bot.currentFood.da < Math.PI / 3) {
  788. return 1;
  789. }
  790.  
  791. if (bot.collisionAngles[aIndex] === undefined) {
  792. return 1;
  793. }
  794. }
  795.  
  796. return bot.defaultAccel;
  797. },
  798.  
  799. // Loop version of collision check
  800. collisionLoop: function () {
  801. bot.MID_X = window.grd;
  802. bot.MID_Y = window.grd;
  803. bot.MAP_R = window.grd * 0.98;
  804.  
  805. bot.sectorBoxSide = Math.floor(Math.sqrt(window.sectors.length)) * window.sector_size;
  806. bot.sectorBox = canvas.rect(
  807. window.snake.xx - (bot.sectorBoxSide / 2),
  808. window.snake.yy - (bot.sectorBoxSide / 2),
  809. bot.sectorBoxSide, bot.sectorBoxSide);
  810. // if (window.visualDebugging) canvas.drawRect(bot.sectorBox, '#c0c0c0', true, 0.1);
  811.  
  812. if (bot.checkCollision(window.collisionRadiusMultiplier)) {
  813. bot.lookForFood = false;
  814. if (bot.foodTimeout) {
  815. window.clearTimeout(bot.foodTimeout);
  816. bot.foodTimeout = window.setTimeout(bot.foodTimer, 1000 / TARGET_FPS * 4);
  817. }
  818. } else {
  819. bot.lookForFood = true;
  820. if (bot.foodTimeout === undefined) {
  821. bot.foodTimeout = window.setTimeout(bot.foodTimer, 1000 / TARGET_FPS * 4);
  822. }
  823. window.setAcceleration(bot.foodAccel());
  824. }
  825. },
  826.  
  827. // Timer version of food check
  828. foodTimer: function () {
  829. if (window.playing && bot.lookForFood &&
  830. window.snake !== null && window.snake.alive_amt === 1) {
  831. bot.computeFoodGoal();
  832. window.goalCoordinates = bot.currentFood;
  833. canvas.setMouseCoordinates(canvas.mapToMouse(window.goalCoordinates));
  834. }
  835. bot.foodTimeout = undefined;
  836. },
  837.  
  838. doDefenseCircle: function () {
  839. if (window.doDefense && window.playing && window.snake !== null){
  840.  
  841. if(window.defenseIndex === undefined){
  842. window.defenseIndex = 0;
  843. }
  844.  
  845. if(window.defenseCurrentGoalCoordinate === undefined){
  846. window.defenseCurrentGoalCoordinate = [];
  847. for(angle = 180;-180 <= angle;angle = angle - 30){
  848. var angleX = window.defenseCircle.xx + (window.defenseCircle.radius * Math.sin(angle * Math.PI / 180));
  849. var angleY = window.defenseCircle.yy + (window.defenseCircle.radius * Math.cos(angle * Math.PI / 180));
  850. var angleDistance = canvas.getDistance2FromSnake({xx:angleX, yy:angleY});
  851. window.defenseCurrentGoalCoordinate.push({x:angleDistance.xx, y:angleDistance.yy, distance:angleDistance.distance});
  852. }
  853. }
  854. var isAtX = (window.snake.xx >= window.defenseCurrentGoalCoordinate[defenseIndex].x - 5 &&
  855. window.snake.xx <= window.defenseCurrentGoalCoordinate[defenseIndex].x + 5);
  856.  
  857. var isAtY = (window.snake.yy >= window.defenseCurrentGoalCoordinate[defenseIndex].y - 5 &&
  858. window.snake.yy <= window.defenseCurrentGoalCoordinate[defenseIndex].y + 5);
  859.  
  860. //if(isAtX && isAtY) {
  861. if (defenseIndex == window.defenseCurrentGoalCoordinate.length - 1){
  862. defenseIndex = 0;
  863. } else {
  864. defenseIndex++;
  865. }
  866. //}
  867. canvas.drawCircle(window.defenseCurrentGoalCoordinate[defenseIndex],'yellow', true);
  868. window.goalCoordinates = window.defenseCurrentGoalCoordinate[defenseIndex];
  869. canvas.setMouseCoordinates(canvas.mapToMouse(window.defenseCurrentGoalCoordinate[defenseIndex]));
  870. setTimeout(bot.doDefenseCircle, 500);
  871. } else {
  872. window.defenseIndex = undefined;
  873. window.defenseCurrentGoalCoordinate = undefined;
  874. }
  875. }
  876. };
  877. })();
  878.  
  879. var userInterface = window.userInterface = (function () {
  880. // Save the original slither.io functions so we can modify them, or reenable them later.
  881. var original_keydown = document.onkeydown;
  882. var original_onmouseDown = window.onmousedown;
  883. var original_oef = window.oef;
  884. var original_redraw = window.redraw;
  885. var original_onmousemove = window.onmousemove;
  886.  
  887. window.oef = function () { };
  888. window.redraw = function () { };
  889.  
  890. return {
  891. overlays: {},
  892.  
  893. initOverlays: function () {
  894. var botOverlay = document.createElement('div');
  895. botOverlay.style.position = 'fixed';
  896. botOverlay.style.right = '5px';
  897. botOverlay.style.bottom = '112px';
  898. botOverlay.style.width = '150px';
  899. botOverlay.style.height = '85px';
  900. // botOverlay.style.background = 'rgba(0, 0, 0, 0.5)';
  901. botOverlay.style.color = '#C0C0C0';
  902. botOverlay.style.fontFamily = 'Consolas, Verdana';
  903. botOverlay.style.zIndex = 999;
  904. botOverlay.style.fontSize = '14px';
  905. botOverlay.style.padding = '5px';
  906. botOverlay.style.borderRadius = '5px';
  907. botOverlay.className = 'nsi';
  908. document.body.appendChild(botOverlay);
  909.  
  910. var serverOverlay = document.createElement('div');
  911. serverOverlay.style.position = 'fixed';
  912. serverOverlay.style.right = '5px';
  913. serverOverlay.style.bottom = '5px';
  914. serverOverlay.style.width = '160px';
  915. serverOverlay.style.height = '14px';
  916. serverOverlay.style.color = '#C0C0C0';
  917. serverOverlay.style.fontFamily = 'Consolas, Verdana';
  918. serverOverlay.style.zIndex = 999;
  919. serverOverlay.style.fontSize = '14px';
  920. serverOverlay.className = 'nsi';
  921. document.body.appendChild(serverOverlay);
  922.  
  923. var prefOverlay = document.createElement('div');
  924. prefOverlay.style.position = 'fixed';
  925. prefOverlay.style.left = '10px';
  926. prefOverlay.style.top = '75px';
  927. prefOverlay.style.width = '260px';
  928. prefOverlay.style.height = '210px';
  929. // prefOverlay.style.background = 'rgba(0, 0, 0, 0.5)';
  930. prefOverlay.style.color = '#C0C0C0';
  931. prefOverlay.style.fontFamily = 'Consolas, Verdana';
  932. prefOverlay.style.zIndex = 999;
  933. prefOverlay.style.fontSize = '14px';
  934. prefOverlay.style.padding = '5px';
  935. prefOverlay.style.borderRadius = '5px';
  936. prefOverlay.className = 'nsi';
  937. document.body.appendChild(prefOverlay);
  938.  
  939. var statsOverlay = document.createElement('div');
  940. statsOverlay.style.position = 'fixed';
  941. statsOverlay.style.left = '10px';
  942. statsOverlay.style.top = '295px';
  943. statsOverlay.style.width = '140px';
  944. statsOverlay.style.height = '210px';
  945. // statsOverlay.style.background = 'rgba(0, 0, 0, 0.5)';
  946. statsOverlay.style.color = '#C0C0C0';
  947. statsOverlay.style.fontFamily = 'Consolas, Verdana';
  948. statsOverlay.style.zIndex = 998;
  949. statsOverlay.style.fontSize = '14px';
  950. statsOverlay.style.padding = '5px';
  951. statsOverlay.style.borderRadius = '5px';
  952. statsOverlay.className = 'nsi';
  953. document.body.appendChild(statsOverlay);
  954.  
  955. userInterface.overlays.botOverlay = botOverlay;
  956. userInterface.overlays.serverOverlay = serverOverlay;
  957. userInterface.overlays.prefOverlay = prefOverlay;
  958. userInterface.overlays.statsOverlay = statsOverlay;
  959. },
  960.  
  961. toggleOverlays: function () {
  962. Object.keys(userInterface.overlays).forEach(function (okey) {
  963. var oVis = userInterface.overlays[okey].style.visibility !== 'hidden' ?
  964. 'hidden' : 'visible';
  965. userInterface.overlays[okey].style.visibility = oVis;
  966. window.visualDebugging = oVis === 'visible';
  967. });
  968. },
  969.  
  970. // Save variable to local storage
  971. savePreference: function (item, value) {
  972. window.localStorage.setItem(item, value);
  973. userInterface.onPrefChange();
  974. },
  975.  
  976. // Load a variable from local storage
  977. loadPreference: function (preference, defaultVar) {
  978. var savedItem = window.localStorage.getItem(preference);
  979. if (savedItem !== null) {
  980. if (savedItem === 'true') {
  981. window[preference] = true;
  982. } else if (savedItem === 'false') {
  983. window[preference] = false;
  984. } else {
  985. window[preference] = savedItem;
  986. }
  987. window.log('Setting found for ' + preference + ': ' + window[preference]);
  988. } else {
  989. window[preference] = defaultVar;
  990. window.log('No setting found for ' + preference +
  991. '. Used default: ' + window[preference]);
  992. }
  993. userInterface.onPrefChange();
  994. return window[preference];
  995. },
  996.  
  997. // Saves username when you click on "Play" button
  998. playButtonClickListener: function () {
  999. userInterface.saveNick();
  1000. userInterface.loadPreference('autoRespawn', false);
  1001. userInterface.onPrefChange();
  1002. },
  1003.  
  1004. // Preserve nickname
  1005. saveNick: function () {
  1006. var nick = document.getElementById('nick').value;
  1007. userInterface.savePreference('savedNick', nick);
  1008. },
  1009.  
  1010. // Hide top score
  1011. hideTop: function () {
  1012. var nsidivs = document.querySelectorAll('div.nsi');
  1013. for (var i = 0; i < nsidivs.length; i++) {
  1014. if (nsidivs[i].style.top === '4px' && nsidivs[i].style.width === '300px') {
  1015. nsidivs[i].style.visibility = 'hidden';
  1016. bot.isTopHidden = true;
  1017. window.topscore = nsidivs[i];
  1018. }
  1019. }
  1020. },
  1021.  
  1022. // Store FPS data
  1023. framesPerSecond: {
  1024. fps: 0,
  1025. fpsTimer: function () {
  1026. if (window.playing && window.fps && window.lrd_mtm) {
  1027. if (Date.now() - window.lrd_mtm > 970) {
  1028. userInterface.framesPerSecond.fps = window.fps;
  1029. }
  1030. }
  1031. }
  1032. },
  1033.  
  1034. onkeydown: function (e) {
  1035. // Original slither.io onkeydown function + whatever is under it
  1036. original_keydown(e);
  1037. if (window.playing) {
  1038. // Letter `T` to toggle bot
  1039. if (e.keyCode === 84) {
  1040. bot.isBotEnabled = !bot.isBotEnabled;
  1041. }
  1042. // Letter 'U' to toggle debugging (console)
  1043. if (e.keyCode === 85) {
  1044. window.logDebugging = !window.logDebugging;
  1045. console.log('Log debugging set to: ' + window.logDebugging);
  1046. userInterface.savePreference('logDebugging', window.logDebugging);
  1047. }
  1048. // Letter 'Y' to toggle debugging (visual)
  1049. if (e.keyCode === 89) {
  1050. window.visualDebugging = !window.visualDebugging;
  1051. console.log('Visual debugging set to: ' + window.visualDebugging);
  1052. userInterface.savePreference('visualDebugging', window.visualDebugging);
  1053. }
  1054. // Letter 'I' to toggle autorespawn
  1055. if (e.keyCode === 73) {
  1056. window.autoRespawn = !window.autoRespawn;
  1057. console.log('Automatic Respawning set to: ' + window.autoRespawn);
  1058. userInterface.savePreference('autoRespawn', window.autoRespawn);
  1059. }
  1060. // Letter 'H' to toggle hidden mode
  1061. if (e.keyCode === 72) {
  1062. userInterface.toggleOverlays();
  1063. }
  1064. // Letter 'O' to change rendermode (visual)
  1065. if (e.keyCode === 79) {
  1066. userInterface.toggleMobileRendering(!window.mobileRender);
  1067. }
  1068. // Letter 'C' to toggle Collision detection / enemy avoidance
  1069. if (e.keyCode === 67) {
  1070. window.collisionDetection = !window.collisionDetection;
  1071. console.log('collisionDetection set to: ' + window.collisionDetection);
  1072. userInterface.savePreference('collisionDetection', window.collisionDetection);
  1073. }
  1074. // Letter 'A' to increase collision detection radius
  1075. if (e.keyCode === 65) {
  1076. window.collisionRadiusMultiplier++;
  1077. console.log(
  1078. 'collisionRadiusMultiplier set to: ' + window.collisionRadiusMultiplier);
  1079. userInterface.savePreference(
  1080. 'collisionRadiusMultiplier', window.collisionRadiusMultiplier);
  1081. }
  1082. // Letter 'S' to decrease collision detection radius
  1083. if (e.keyCode === 83) {
  1084. if (window.collisionRadiusMultiplier > 1) {
  1085. window.collisionRadiusMultiplier--;
  1086. console.log(
  1087. 'collisionRadiusMultiplier set to: ' +
  1088. window.collisionRadiusMultiplier);
  1089. userInterface.savePreference(
  1090. 'collisionRadiusMultiplier', window.collisionRadiusMultiplier);
  1091. }
  1092. }
  1093. // Letter 'Z' to reset zoom
  1094. if (e.keyCode === 90) {
  1095. canvas.resetZoom();
  1096. }
  1097. // Letter 'Q' to quit to main menu
  1098. if (e.keyCode === 81) {
  1099. window.autoRespawn = false;
  1100. userInterface.quit();
  1101. }
  1102. // 'ESC' to quickly respawn
  1103. if (e.keyCode === 27) {
  1104. bot.quickRespawn();
  1105. }
  1106. // Save nickname when you press "Enter"
  1107. if (e.keyCode === 13) {
  1108. userInterface.saveNick();
  1109. }
  1110. // 'ESC' to quickly respawn
  1111. if (e.keyCode === 80) {
  1112. window.doDefense = !window.doDefense;
  1113.  
  1114. if (window.doDefense && window.playing && window.snake !== null){
  1115. window.defenseCircle = {xx:window.snake.xx, yy:window.snake.yy, radius:window.getSnakeLength()*.3};
  1116. }
  1117. }
  1118. userInterface.onPrefChange();
  1119. }
  1120. },
  1121.  
  1122. onmousedown: function (e) {
  1123. if (window.playing) {
  1124. switch (e.which) {
  1125. // "Left click" to manually speed up the slither
  1126. case 1:
  1127. bot.defaultAccel = 1;
  1128. if (!bot.isBotEnabled) {
  1129. original_onmouseDown(e);
  1130. }
  1131. break;
  1132. // "Right click" to toggle bot in addition to the letter "T"
  1133. case 3:
  1134. bot.isBotEnabled = !bot.isBotEnabled;
  1135. break;
  1136. }
  1137. } else {
  1138. original_onmouseDown(e);
  1139. }
  1140. userInterface.onPrefChange();
  1141. },
  1142.  
  1143. onmouseup: function () {
  1144. bot.defaultAccel = 0;
  1145. },
  1146.  
  1147. // Manual mobile rendering
  1148. toggleMobileRendering: function (mobileRendering) {
  1149. window.mobileRender = mobileRendering;
  1150. window.log('Mobile rendering set to: ' + window.mobileRender);
  1151. userInterface.savePreference('mobileRender', window.mobileRender);
  1152. // Set render mode
  1153. if (window.mobileRender) {
  1154. canvas.setBackground(
  1155. 'data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs');
  1156. window.render_mode = 1;
  1157. window.want_quality = 0;
  1158. window.high_quality = false;
  1159. } else {
  1160. canvas.setBackground();
  1161. window.render_mode = 2;
  1162. window.want_quality = 1;
  1163. window.high_quality = true;
  1164. }
  1165. },
  1166.  
  1167. // Update stats overlay.
  1168. updateStats: function () {
  1169. var oContent = [];
  1170.  
  1171. if (bot.scores.length === 0) return;
  1172.  
  1173. oContent.push('games played: ' + bot.scores.length);
  1174. oContent.push('avg score: ' + Math.round(
  1175. bot.scores.reduce(function (a, b) { return a + b; }) / (bot.scores.length)));
  1176.  
  1177. for (var i = 0; i < bot.scores.length && i < 10; i++) {
  1178. oContent.push(i + 1 + '. ' + bot.scores[i]);
  1179. }
  1180.  
  1181. userInterface.overlays.statsOverlay.innerHTML = oContent.join('<br/>');
  1182. },
  1183.  
  1184. onPrefChange: function () {
  1185. // Set static display options here.
  1186. var oContent = [];
  1187. var ht = userInterface.handleTextColor;
  1188.  
  1189. oContent.push('version: ' + GM_info.script.version);
  1190. oContent.push('[T] bot: ' + ht(bot.isBotEnabled));
  1191. oContent.push('[C] collision detection: ' + ht(window.collisionDetection));
  1192. oContent.push('[O] mobile rendering: ' + ht(window.mobileRender));
  1193. oContent.push('[A/S] radius multiplier: ' + window.collisionRadiusMultiplier);
  1194. oContent.push('[I] auto respawn: ' + ht(window.autoRespawn));
  1195. oContent.push('[Y] visual debugging: ' + ht(window.visualDebugging));
  1196. oContent.push('[U] log debugging: ' + ht(window.logDebugging));
  1197. oContent.push('[Mouse Wheel] zoom');
  1198. oContent.push('[Z] reset zoom');
  1199. oContent.push('[ESC] quick respawn');
  1200. oContent.push('[Q] quit to menu');
  1201.  
  1202. userInterface.overlays.prefOverlay.innerHTML = oContent.join('<br/>');
  1203. },
  1204.  
  1205. onFrameUpdate: function () {
  1206. // Botstatus overlay
  1207. var oContent = [];
  1208.  
  1209. if (window.playing && window.snake !== null) {
  1210. oContent.push('fps: ' + userInterface.framesPerSecond.fps);
  1211.  
  1212. // Display the X and Y of the snake
  1213. oContent.push('x: ' +
  1214. (Math.round(window.snake.xx) || 0) + ' y: ' +
  1215. (Math.round(window.snake.yy) || 0));
  1216.  
  1217. if (window.goalCoordinates) {
  1218. oContent.push('target');
  1219. oContent.push('x: ' + window.goalCoordinates.x + ' y: ' +
  1220. window.goalCoordinates.y);
  1221. if (window.goalCoordinates.sz) {
  1222. oContent.push('sz: ' + window.goalCoordinates.sz);
  1223. }
  1224. }
  1225.  
  1226. if (window.bso !== undefined && userInterface.overlays.serverOverlay.innerHTML !==
  1227. window.bso.ip + ':' + window.bso.po) {
  1228. userInterface.overlays.serverOverlay.innerHTML =
  1229. window.bso.ip + ':' + window.bso.po;
  1230. }
  1231. }
  1232.  
  1233. userInterface.overlays.botOverlay.innerHTML = oContent.join('<br/>');
  1234.  
  1235.  
  1236. if (window.playing && window.visualDebugging) {
  1237. // Only draw the goal when a bot has a goal.
  1238. if (window.goalCoordinates && bot.isBotEnabled) {
  1239. var headCoord = { x: window.snake.xx, y: window.snake.yy };
  1240. canvas.drawLine(
  1241. headCoord,
  1242. window.goalCoordinates,
  1243. 'green');
  1244. canvas.drawCircle(window.goalCoordinates, 'red', true);
  1245. }
  1246. }
  1247. },
  1248.  
  1249. oefTimer: function () {
  1250. var start = Date.now();
  1251. canvas.maintainZoom();
  1252. original_oef();
  1253. original_redraw();
  1254.  
  1255. if (window.playing && bot.isBotEnabled && window.snake !== null){
  1256. window.onmousemove = function () { };
  1257. bot.isBotRunning = true;
  1258. if (!window.doDefense){
  1259. bot.collisionLoop();
  1260. } else {
  1261. bot.doDefenseCircle();
  1262. }
  1263.  
  1264. } else if (bot.isBotEnabled && bot.isBotRunning) {
  1265. bot.isBotRunning = false;
  1266. if (window.lastscore && window.lastscore.childNodes[1]) {
  1267. bot.scores.push(parseInt(window.lastscore.childNodes[1].innerHTML));
  1268. bot.scores.sort(function (a, b) { return b - a; });
  1269. userInterface.updateStats();
  1270. }
  1271.  
  1272. if (window.autoRespawn) {
  1273. window.connect();
  1274. }
  1275. }
  1276.  
  1277. if (!bot.isBotEnabled || !bot.isBotRunning) {
  1278. window.onmousemove = original_onmousemove;
  1279. }
  1280.  
  1281. userInterface.onFrameUpdate();
  1282. setTimeout(userInterface.oefTimer, (1000 / TARGET_FPS) - (Date.now() - start));
  1283. },
  1284.  
  1285. // Quit to menu
  1286. quit: function () {
  1287. if (window.playing && window.resetGame) {
  1288. window.want_close_socket = true;
  1289. window.dead_mtm = 0;
  1290. if (window.play_btn) {
  1291. window.play_btn.setEnabled(true);
  1292. }
  1293. window.resetGame();
  1294. }
  1295. },
  1296.  
  1297. // Update the relation between the screen and the canvas.
  1298. onresize: function () {
  1299. window.resize();
  1300. // Canvas different size from the screen (often bigger).
  1301. canvas.canvasRatio = {
  1302. x: window.mc.width / window.ww,
  1303. y: window.mc.height / window.hh
  1304. };
  1305. },
  1306.  
  1307. handleTextColor: function (enabled) {
  1308. return '<span style=\"color:' +
  1309. (enabled ? 'green;\">enabled' : 'red;\">disabled') + '</span>';
  1310. }
  1311. };
  1312. })();
  1313.  
  1314. // Main
  1315. (function () {
  1316. window.play_btn.btnf.addEventListener('click', userInterface.playButtonClickListener);
  1317. document.onkeydown = userInterface.onkeydown;
  1318. window.onmousedown = userInterface.onmousedown;
  1319. window.addEventListener('mouseup', userInterface.onmouseup);
  1320. window.onresize = userInterface.onresize;
  1321.  
  1322. // Hide top score
  1323. userInterface.hideTop();
  1324.  
  1325. // Overlays
  1326. userInterface.initOverlays();
  1327.  
  1328. // Load preferences
  1329. userInterface.loadPreference('logDebugging', false);
  1330. userInterface.loadPreference('visualDebugging', false);
  1331. userInterface.loadPreference('autoRespawn', false);
  1332. userInterface.loadPreference('mobileRender', false);
  1333. userInterface.loadPreference('collisionDetection', true);
  1334. userInterface.loadPreference('collisionRadiusMultiplier', 10);
  1335. window.nick.value = userInterface.loadPreference('savedNick', 'Slither.io-bot');
  1336.  
  1337. // Listener for mouse wheel scroll - used for setZoom function
  1338. document.body.addEventListener('mousewheel', canvas.setZoom);
  1339. document.body.addEventListener('DOMMouseScroll', canvas.setZoom);
  1340.  
  1341. // Set render mode
  1342. if (window.mobileRender) {
  1343. userInterface.toggleMobileRendering(true);
  1344. } else {
  1345. userInterface.toggleMobileRendering(false);
  1346. }
  1347.  
  1348. // Unblocks all skins without the need for FB sharing.
  1349. window.localStorage.setItem('edttsg', '1');
  1350.  
  1351. // Remove social
  1352. window.social.remove();
  1353.  
  1354. // Maintain fps
  1355. setInterval(userInterface.framesPerSecond.fpsTimer, 80);
  1356.  
  1357. // Start!
  1358. userInterface.oefTimer();
  1359. })();
Add Comment
Please, Sign In to add comment