Advertisement
Guest User

Untitled

a guest
Apr 26th, 2018
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 59.32 KB | None | 0 0
  1. var SlitherBot = window.bot = (function (window) {
  2. return {
  3. id: 0,
  4. isBotRunning: false,
  5. isBotEnabled: true,
  6. isSelfCirclingEnabled: false,
  7. stage: 'grow',
  8. collisionPoints: [],
  9. collisionAngles: [],
  10. foodAngles: [],
  11. scores: [],
  12. kills: [],
  13. foodTimeout: undefined,
  14. sectorBoxSide: 0,
  15. defaultAccel: 0,
  16. sectorBox: {},
  17. currentFood: {},
  18. opt: {
  19. // target fps
  20. targetFps: 20,
  21. // size of arc for collisionAngles
  22. arcSize: Math.PI / 8,
  23. // radius multiple for circle intersects
  24. radiusMult: 10,
  25. // food size to trigger acceleration
  26. foodAccelerateSize: 200,
  27. // maximum angle of food to trigger acceleration
  28. foodAccelDa: Math.PI / 2,
  29. // how many frames per action
  30. actionFrames: 2,
  31. // how many frames to delay action after collision
  32. collisionDelay: 10,
  33. // base speed
  34. speedBase: 5.78,
  35. // front angle size
  36. frontAngle: Math.PI * 0.75,
  37. // percent of angles covered by same snake to be considered an encircle attempt
  38. enCircleThreshold: 0.5625,
  39. // percent of angles covered by all snakes to move to safety
  40. enCircleAllThreshold: 0.5625,
  41. // distance multiplier for enCircleAllThreshold
  42. enCircleDistanceMult: 20,
  43. // snake score to start circling on self
  44. followCircleLength: 5000,
  45. // direction for followCircle: +1 for counter clockwise and -1 for clockwise
  46. followCircleDirection: +1,
  47. //radius of cluster distance to calculate for food. WARNING: too high can cause performance issues.
  48. foodClusterRadius: 100,
  49. //weight to increment angle index
  50. weightAngleIndex: 2,
  51. //Weight for food that is clustered
  52. weightFoodClusterRatio: 5,
  53. //Weight for food that is closer to snake
  54. weightFoodDistance: 0.5,
  55. //Weight for food that is large
  56. weightFoodSize: 50
  57. },
  58. MID_X: 0,
  59. MID_Y: 0,
  60. MAP_R: 0,
  61. MAXARC: 0,
  62.  
  63. getSnakeWidth: function (sc) {
  64. if (sc === undefined) sc = window.snake.sc;
  65. return Math.round(sc * 29.0);
  66. },
  67.  
  68. quickRespawn: function () {
  69. window.dead_mtm = 0;
  70. window.login_fr = 0;
  71.  
  72. SlitherBot.isBotRunning = false;
  73. window.forcing = true;
  74. SlitherBot.connect();
  75. window.forcing = false;
  76. },
  77.  
  78. connect: function () {
  79. if (window.force_ip && window.force_port) {
  80. window.forceServer(window.force_ip, window.force_port);
  81. }
  82.  
  83. window.connect();
  84. },
  85.  
  86. // angleBetween - get the smallest angle between two angles (0-pi)
  87. angleBetween: function (a1, a2) {
  88. var r1 = 0.0;
  89. var r2 = 0.0;
  90.  
  91. r1 = (a1 - a2) % Math.PI;
  92. r2 = (a2 - a1) % Math.PI;
  93.  
  94. return r1 < r2 ? -r1 : r2;
  95. },
  96.  
  97. // Change heading to ang
  98. changeHeadingAbs: function (angle) {
  99. var cos = Math.cos(angle);
  100. var sin = Math.sin(angle);
  101.  
  102. window.goalCoordinates = {
  103. x: Math.round(
  104. window.snake.xx + (SlitherBot.headCircle.radius) * cos),
  105. y: Math.round(
  106. window.snake.yy + (SlitherBot.headCircle.radius) * sin)
  107. };
  108.  
  109. /*if (window.visualDebugging) {
  110. canvas.drawLine({
  111. x: window.snake.xx,
  112. y: window.snake.yy},
  113. window.goalCoordinates, 'yellow', '8');
  114. }*/
  115.  
  116. canvas.setMouseCoordinates(canvas.mapToMouse(window.goalCoordinates));
  117. },
  118.  
  119. // Change heading by ang
  120. // +0-pi turn left
  121. // -0-pi turn right
  122.  
  123. changeHeadingRel: function (angle) {
  124. var heading = {
  125. x: window.snake.xx + 500 * SlitherBot.cos,
  126. y: window.snake.yy + 500 * SlitherBot.sin
  127. };
  128.  
  129. var cos = Math.cos(-angle);
  130. var sin = Math.sin(-angle);
  131.  
  132. window.goalCoordinates = {
  133. x: Math.round(
  134. cos * (heading.x - window.snake.xx) -
  135. sin * (heading.y - window.snake.yy) + window.snake.xx),
  136. y: Math.round(
  137. sin * (heading.x - window.snake.xx) +
  138. cos * (heading.y - window.snake.yy) + window.snake.yy)
  139. };
  140.  
  141. canvas.setMouseCoordinates(canvas.mapToMouse(window.goalCoordinates));
  142. },
  143.  
  144. // Change heading to the best angle for avoidance.
  145. headingBestAngle: function () {
  146. var best;
  147. var distance;
  148. var openAngles = [];
  149. var openStart;
  150.  
  151. var sIndex = SlitherBot.getAngleIndex(window.snake.ehang) + SlitherBot.MAXARC / 2;
  152. if (sIndex > SlitherBot.MAXARC) sIndex -= SlitherBot.MAXARC;
  153.  
  154. for (var i = 0; i < SlitherBot.MAXARC; i++) {
  155. if (SlitherBot.collisionAngles[i] === undefined) {
  156. distance = 0;
  157. if (openStart === undefined) openStart = i;
  158. } else {
  159. distance = SlitherBot.collisionAngles[i].distance;
  160. if (openStart) {
  161. openAngles.push({
  162. openStart: openStart,
  163. openEnd: i - 1,
  164. sz: (i - 1) - openStart
  165. });
  166. openStart = undefined;
  167. }
  168. }
  169.  
  170. if (best === undefined ||
  171. (best.distance < distance && best.distance !== 0)) {
  172. best = {
  173. distance: distance,
  174. angleIndex: i
  175. };
  176. }
  177. }
  178.  
  179. if (openStart && openAngles[0]) {
  180. openAngles[0].openStart = openStart;
  181. openAngles[0].sz = openAngles[0].openEnd - openStart;
  182. if (openAngles[0].sz < 0) openAngles[0].sz += SlitherBot.MAXARC;
  183.  
  184. } else if (openStart) {
  185. openAngles.push({openStart: openStart, openEnd: openStart, sz: 0});
  186. }
  187.  
  188. if (openAngles.length > 0) {
  189. openAngles.sort(SlitherBot.sortSz);
  190. SlitherBot.changeHeadingAbs(
  191. (openAngles[0].openEnd - openAngles[0].sz / 2) * SlitherBot.opt.arcSize);
  192. } else {
  193. SlitherBot.changeHeadingAbs(best.angleIndex * SlitherBot.opt.arcSize);
  194. }
  195. },
  196.  
  197. // Avoid collision point by ang
  198. // ang radians <= Math.PI/2 (90deg)
  199. avoidCollisionPoint: function (point, ang) {
  200. if (ang === undefined || ang > (Math.PI / 2)) {
  201. ang = Math.PI;
  202. }
  203.  
  204. var end = {
  205. x: window.snake.xx + 2000 * SlitherBot.cos,
  206. y: window.snake.yy + 2000 * SlitherBot.sin
  207. };
  208.  
  209. if (window.visualDebugging) {
  210. canvas.drawLine(
  211. { x: window.snake.xx, y: window.snake.yy },
  212. end,
  213. 'orange', 5);
  214. canvas.drawLine(
  215. { x: window.snake.xx, y: window.snake.yy },
  216. { x: point.x, y: point.y },
  217. 'red', 5);
  218. }
  219.  
  220. if (canvas.isLeft(
  221. { x: window.snake.xx, y: window.snake.yy }, end,
  222. { x: point.x, y: point.y })) {
  223. SlitherBot.changeHeadingAbs(point.ang - ang);
  224. } else {
  225. SlitherBot.changeHeadingAbs(point.ang + ang);
  226. }
  227. },
  228.  
  229. // get collision angle index, expects angle +/i 0 to Math.PI
  230. getAngleIndex: function (angle) {
  231. var index;
  232.  
  233. if (angle < 0) {
  234. angle += SlitherBot.opt.weightAngleIndex * Math.PI;
  235. }
  236.  
  237. index = Math.round(angle * (1 / SlitherBot.opt.arcSize));
  238.  
  239. if (index === SlitherBot.MAXARC) {
  240. index = 0;
  241. }
  242. return index;
  243. },
  244.  
  245. // Add to collisionAngles if distance is closer
  246. addCollisionAngle: function (sp) {
  247. // window.log('SP:');
  248. // window.log(sp);
  249. var ang = canvas.fastAtan2(
  250. Math.round(sp.yy - window.snake.yy),
  251. Math.round(sp.xx - window.snake.xx));
  252. // window.log('Angle: ' + ang);
  253. var angleIndex = SlitherBot.getAngleIndex(ang);
  254. // window.log('Angle Index: ' + angleIndex);
  255. var actualDistance = Math.round(Math.pow(
  256. Math.sqrt(sp.distance) - sp.radius, 2));
  257. // window.log('Actual Distance: ' + actualDistance);
  258.  
  259. if (SlitherBot.collisionAngles[angleIndex] === undefined ||
  260. SlitherBot.collisionAngles[angleIndex].distance > sp.distance) {
  261. SlitherBot.collisionAngles[angleIndex] = {
  262. x: Math.round(sp.xx),
  263. y: Math.round(sp.yy),
  264. ang: ang,
  265. snake: sp.snake,
  266. distance: actualDistance,
  267. radius: sp.radius,
  268. angleIndex: angleIndex
  269. };
  270. }
  271. },
  272.  
  273. // Add and score foodAngles
  274. addFoodAngle: function (f) {
  275. var ang = canvas.fastAtan2(
  276. Math.round(f.yy - window.snake.yy),
  277. Math.round(f.xx - window.snake.xx));
  278.  
  279. var angleIndex = SlitherBot.getAngleIndex(ang);
  280.  
  281. canvas.getDistance2FromSnake(f);
  282.  
  283. if (SlitherBot.collisionAngles[angleIndex] === undefined ||
  284. Math.sqrt(SlitherBot.collisionAngles[angleIndex].distance) >
  285. Math.sqrt(f.distance) + SlitherBot.snakeRadius * SlitherBot.opt.radiusMult * SlitherBot.speedMult / 2) {
  286. if (SlitherBot.foodAngles[angleIndex] === undefined) {
  287. SlitherBot.foodAngles[angleIndex] = {
  288. x: Math.round(f.xx),
  289. y: Math.round(f.yy),
  290. ang: ang,
  291. da: Math.abs(SlitherBot.angleBetween(ang, window.snake.ehang)),
  292. distance: f.distance,
  293. sz: f.sz,
  294. score: ((f.sz * SlitherBot.opt.weightFoodSize) / (f.distance * SlitherBot.opt.weightFoodDistance) * (f.clusterRatio * SlitherBot.opt.weightFoodClusterRatio))
  295. };
  296. } else {
  297. SlitherBot.foodAngles[angleIndex].sz += Math.round(f.sz);
  298. // if (f.isSparse || f.isDense) {
  299. // window.log('Food\'s original score: ' + SlitherBot.foodAngles[angleIndex].score);
  300. // }
  301.  
  302. SlitherBot.foodAngles[angleIndex].score += ((f.sz * SlitherBot.opt.weightFoodSize) / (f.distance * SlitherBot.opt.weightFoodDistance) * (f.clusterRatio * SlitherBot.opt.weightFoodClusterRatio));
  303. // if (f.isSparse) {
  304. // window.log('Food is SPARSE.');
  305. // }
  306. // if (f.isDense) {
  307. // window.log('Food is DENSE.');
  308. // }
  309. // if (f.isDense || f.isSparse) {
  310. // window.log('Total Cluster Ratio of Food: ' + f.clusterRatio);
  311. // window.log('[Best] Original score to add: ' + (Math.pow(f.sz, 2) / f.distance));
  312. // // window.log('[Worst] New score to add (v1): ' + ((Math.pow(f.sz, 2) / f.distance) - f.clusterRatio));
  313. // // window.log('[Small Negative Number] New score to add (v2): ' + ((Math.pow(f.sz, 2) - f.clusterRatio) / f.distance));
  314. // // window.log('[Large Positive Number] New score to add (v3): ' + ((Math.pow(f.sz - f.clusterRatio, 2)) / f.distance));
  315. // // window.log('[TRYING] New score to add (v4): ' + (Math.pow(f.sz, 2) / f.distance / f.clusterRatio));
  316. // window.log('[TRYING] New score to add (v5): ' + ((f.sz * SlitherBot.opt.weightFoodSize) * (f.distance * SlitherBot.opt.weightFoodDistance) * (f.clusterRatio * SlitherBot.opt.weightFoodClusterRatio)));
  317. // }
  318.  
  319. if (SlitherBot.foodAngles[angleIndex].distance > f.distance) {
  320. SlitherBot.foodAngles[angleIndex].x = Math.round(f.xx);
  321. SlitherBot.foodAngles[angleIndex].y = Math.round(f.yy);
  322. SlitherBot.foodAngles[angleIndex].distance = f.distance;
  323. }
  324. }
  325. }
  326. },
  327.  
  328. // Get closest collision point per snake.
  329. getCollisionPoints: function () {
  330. var scPoint;
  331.  
  332. SlitherBot.collisionPoints = [];
  333. SlitherBot.collisionAngles = [];
  334.  
  335. window.log('Head Circle:');
  336. window.log(SlitherBot.headCircle);
  337. window.log('Snake:');
  338. window.log(window.snake);
  339.  
  340. for (var snake = 0, ls = window.snakes.length; snake < ls; snake++) {
  341. scPoint = undefined;
  342.  
  343. if (window.snakes[snake].id !== window.snake.id &&
  344. window.snakes[snake].alive_amt === 1) {
  345.  
  346. var s = window.snakes[snake];
  347. var sRadius = SlitherBot.getSnakeWidth(s.sc) / 2;
  348. var sSpMult = Math.min(1, s.sp / 5.78 - 1 );
  349.  
  350. scPoint = {
  351. xx: s.xx + Math.cos(s.ehang) * sRadius * sSpMult * SlitherBot.opt.radiusMult / 2,
  352. yy: s.yy + Math.sin(s.ehang) * sRadius * sSpMult * SlitherBot.opt.radiusMult / 2,
  353. snake: snake,
  354. radius: SlitherBot.headCircle.radius,
  355. head: true
  356. };
  357.  
  358. canvas.getDistance2FromSnake(scPoint);
  359. SlitherBot.addCollisionAngle(scPoint);
  360. SlitherBot.collisionPoints.push(scPoint);
  361.  
  362. if (window.visualDebugging) {
  363. canvas.drawCircle(canvas.circle(
  364. scPoint.xx,
  365. scPoint.yy,
  366. scPoint.radius),
  367. 'red', false);
  368. }
  369.  
  370. scPoint = undefined;
  371.  
  372. for (var pts = 0, lp = s.pts.length; pts < lp; pts++) {
  373. if (!s.pts[pts].dying &&
  374. canvas.pointInRect(
  375. {
  376. x: s.pts[pts].xx,
  377. y: s.pts[pts].yy
  378. }, SlitherBot.sectorBox)
  379. ) {
  380. var collisionPoint = {
  381. xx: s.pts[pts].xx,
  382. yy: s.pts[pts].yy,
  383. snake: snake,
  384. radius: sRadius
  385. };
  386.  
  387. if (window.visualDebugging && true === false) {
  388. canvas.drawCircle(canvas.circle(
  389. collisionPoint.xx,
  390. collisionPoint.yy,
  391. collisionPoint.radius),
  392. '#00FF00', false);
  393. }
  394.  
  395. canvas.getDistance2FromSnake(collisionPoint);
  396. SlitherBot.addCollisionAngle(collisionPoint);
  397.  
  398. if (collisionPoint.distance <= Math.pow(
  399. (SlitherBot.headCircle.radius)
  400. + collisionPoint.radius, 2)) {
  401. SlitherBot.collisionPoints.push(collisionPoint);
  402. if (window.visualDebugging) {
  403. canvas.drawCircle(canvas.circle(
  404. collisionPoint.xx,
  405. collisionPoint.yy,
  406. collisionPoint.radius
  407. ), 'red', false);
  408. }
  409. }
  410. }
  411. }
  412. }
  413. }
  414.  
  415. // WALL
  416. if (canvas.getDistance2(SlitherBot.MID_X, SlitherBot.MID_Y, window.snake.xx, window.snake.yy) >
  417. Math.pow(SlitherBot.MAP_R - 1000, 2)) {
  418. var midAng = canvas.fastAtan2(
  419. window.snake.yy - SlitherBot.MID_X, window.snake.xx - SlitherBot.MID_Y);
  420. scPoint = {
  421. xx: SlitherBot.MID_X + SlitherBot.MAP_R * Math.cos(midAng),
  422. yy: SlitherBot.MID_Y + SlitherBot.MAP_R * Math.sin(midAng),
  423. snake: -1,
  424. radius: SlitherBot.snakeWidth
  425. };
  426. canvas.getDistance2FromSnake(scPoint);
  427. SlitherBot.collisionPoints.push(scPoint);
  428. SlitherBot.addCollisionAngle(scPoint);
  429. if (window.visualDebugging) {
  430. canvas.drawCircle(canvas.circle(
  431. scPoint.xx,
  432. scPoint.yy,
  433. scPoint.radius
  434. ), 'yellow', false);
  435. }
  436. }
  437.  
  438.  
  439. SlitherBot.collisionPoints.sort(SlitherBot.sortDistance);
  440. if (window.visualDebugging) {
  441. for (var i = 0; i < SlitherBot.collisionAngles.length; i++) {
  442. if (SlitherBot.collisionAngles[i] !== undefined) {
  443. canvas.drawLine(
  444. { x: window.snake.xx, y: window.snake.yy },
  445. { x: SlitherBot.collisionAngles[i].x, y: SlitherBot.collisionAngles[i].y },
  446. 'red', 2);
  447. }
  448. }
  449. }
  450. },
  451.  
  452. // Is collisionPoint (xx) in frontAngle
  453. inFrontAngle: function (point) {
  454. var ang = canvas.fastAtan2(
  455. Math.round(point.y - window.snake.yy),
  456. Math.round(point.x - window.snake.xx));
  457.  
  458. if (Math.abs(SlitherBot.angleBetween(ang, window.snake.ehang)) < SlitherBot.opt.frontAngle) {
  459. return true;
  460. } else {
  461. return false;
  462. }
  463.  
  464. },
  465.  
  466. // Checks to see if you are going to collide with anything in the collision detection radius
  467. checkCollision: function () {
  468. var point;
  469.  
  470. SlitherBot.getCollisionPoints();
  471. if (SlitherBot.collisionPoints.length === 0) return false;
  472.  
  473. for (var i = 0; i < SlitherBot.collisionPoints.length; i++) {
  474. var collisionCircle = canvas.circle(
  475. SlitherBot.collisionPoints[i].xx,
  476. SlitherBot.collisionPoints[i].yy,
  477. SlitherBot.collisionPoints[i].radius
  478. );
  479.  
  480. // -1 snake is special case for non snake object.
  481. if ((point = canvas.circleIntersect(SlitherBot.headCircle, collisionCircle)) &&
  482. SlitherBot.inFrontAngle(point)) {
  483. if (SlitherBot.collisionPoints[i].snake !== -1 &&
  484. SlitherBot.collisionPoints[i].head &&
  485. window.snakes[SlitherBot.collisionPoints[i].snake].sp > 10) {
  486. window.setAcceleration(1);
  487. } else {
  488. window.setAcceleration(SlitherBot.defaultAccel);
  489. }
  490. SlitherBot.avoidCollisionPoint(point);
  491. return true;
  492. }
  493. }
  494.  
  495. window.setAcceleration(SlitherBot.defaultAccel);
  496. return false;
  497. },
  498.  
  499. checkEncircle: function () {
  500. var enSnake = [];
  501. var high = 0;
  502. var highSnake;
  503. var enAll = 0;
  504.  
  505. for (var i = 0; i < SlitherBot.collisionAngles.length; i++) {
  506. if (SlitherBot.collisionAngles[i] !== undefined) {
  507. var s = SlitherBot.collisionAngles[i].snake;
  508. if (enSnake[s]) {
  509. enSnake[s]++;
  510. } else {
  511. enSnake[s] = 1;
  512. }
  513. if (enSnake[s] > high) {
  514. high = enSnake[s];
  515. highSnake = s;
  516. }
  517.  
  518. if (SlitherBot.collisionAngles[i].distance <
  519. Math.pow(SlitherBot.snakeRadius * SlitherBot.opt.enCircleDistanceMult, 2)) {
  520. enAll++;
  521. }
  522. }
  523. }
  524.  
  525. if (high > SlitherBot.MAXARC * SlitherBot.opt.enCircleThreshold) {
  526. SlitherBot.headingBestAngle();
  527.  
  528. if (high !== SlitherBot.MAXARC && window.snakes[highSnake].sp > 10) {
  529. window.setAcceleration(1);
  530. } else {
  531. window.setAcceleration(SlitherBot.defaultAccel);
  532. }
  533.  
  534. if (window.visualDebugging) {
  535. canvas.drawCircle(canvas.circle(
  536. window.snake.xx,
  537. window.snake.yy,
  538. SlitherBot.opt.radiusMult * SlitherBot.snakeRadius),
  539. 'red', true, 0.2);
  540. }
  541. return true;
  542. }
  543.  
  544. if (enAll > SlitherBot.MAXARC * SlitherBot.opt.enCircleAllThreshold) {
  545. SlitherBot.headingBestAngle();
  546. window.setAcceleration(SlitherBot.defaultAccel);
  547.  
  548. if (window.visualDebugging) {
  549. canvas.drawCircle(canvas.circle(
  550. window.snake.xx,
  551. window.snake.yy,
  552. SlitherBot.snakeRadius * SlitherBot.opt.enCircleDistanceMult),
  553. 'yellow', true, 0.2);
  554. }
  555. return true;
  556. } else {
  557. if (window.visualDebugging) {
  558. canvas.drawCircle(canvas.circle(
  559. window.snake.xx,
  560. window.snake.yy,
  561. SlitherBot.snakeRadius * SlitherBot.opt.enCircleDistanceMult),
  562. 'yellow');
  563. }
  564. }
  565.  
  566. window.setAcceleration(SlitherBot.defaultAccel);
  567. return false;
  568. },
  569.  
  570. populatePts: function () {
  571. let x = window.snake.xx + window.snake.fx;
  572. let y = window.snake.yy + window.snake.fy;
  573. let l = 0.0;
  574. SlitherBot.pts = [{
  575. x: x,
  576. y: y,
  577. len: l
  578. }];
  579. for (let p = window.snake.pts.length - 1; p >= 0; p--) {
  580. if (window.snake.pts[p].dying) {
  581. continue;
  582. } else {
  583. let xx = window.snake.pts[p].xx + window.snake.pts[p].fx;
  584. let yy = window.snake.pts[p].yy + window.snake.pts[p].fy;
  585. let ll = l + Math.sqrt(canvas.getDistance2(x, y, xx, yy));
  586. SlitherBot.pts.push({
  587. x: xx,
  588. y: yy,
  589. len: ll
  590. });
  591. x = xx;
  592. y = yy;
  593. l = ll;
  594. }
  595. }
  596. SlitherBot.len = l;
  597. },
  598.  
  599. // set the direction of rotation based on the velocity of
  600. // the head with respect to the center of mass
  601. determineCircleDirection: function () {
  602. // find center mass (cx, cy)
  603. let cx = 0.0;
  604. let cy = 0.0;
  605. let pn = SlitherBot.pts.length;
  606. for (let p = 0; p < pn; p++) {
  607. cx += SlitherBot.pts[p].x;
  608. cy += SlitherBot.pts[p].y;
  609. }
  610. cx /= pn;
  611. cy /= pn;
  612.  
  613. // vector from (cx, cy) to the head
  614. let head = {
  615. x: window.snake.xx + window.snake.fx,
  616. y: window.snake.yy + window.snake.fy
  617. };
  618. let dx = head.x - cx;
  619. let dy = head.y - cy;
  620.  
  621. // check the sign of dot product of (SlitherBot.cos, SlitherBot.sin) and (-dy, dx)
  622. if (- dy * SlitherBot.cos + dx * SlitherBot.sin > 0) {
  623. // clockwise
  624. SlitherBot.opt.followCircleDirection = -1;
  625. } else {
  626. // couter clockwise
  627. SlitherBot.opt.followCircleDirection = +1;
  628. }
  629. },
  630.  
  631. // returns a point on snake's body on given length from the head
  632. // assumes that SlitherBot.pts is populated
  633. smoothPoint: function (t) {
  634. // range check
  635. if (t >= SlitherBot.len) {
  636. let tail = SlitherBot.pts[SlitherBot.pts.length - 1];
  637. return {
  638. x: tail.x,
  639. y: tail.y
  640. };
  641. } else if (t <= 0 ) {
  642. return {
  643. x: SlitherBot.pts[0].x,
  644. y: SlitherBot.pts[0].y
  645. };
  646. }
  647. // binary search
  648. let p = 0;
  649. let q = SlitherBot.pts.length - 1;
  650. while (q - p > 1) {
  651. let m = Math.round((p + q) / 2);
  652. if (t > SlitherBot.pts[m].len) {
  653. p = m;
  654. } else {
  655. q = m;
  656. }
  657. }
  658. // now q = p + 1, and the point is in between;
  659. // compute approximation
  660. let wp = SlitherBot.pts[q].len - t;
  661. let wq = t - SlitherBot.pts[p].len;
  662. let w = wp + wq;
  663. return {
  664. x: (wp * SlitherBot.pts[p].x + wq * SlitherBot.pts[q].x) / w,
  665. y: (wp * SlitherBot.pts[p].y + wq * SlitherBot.pts[q].y) / w
  666. };
  667. },
  668.  
  669. // finds a point on snake's body closest to the head;
  670. // returns length from the head
  671. // excludes points close to the head
  672. closestBodyPoint: function () {
  673. let head = {
  674. x: window.snake.xx + window.snake.fx,
  675. y: window.snake.yy + window.snake.fy
  676. };
  677.  
  678. let ptsLength = SlitherBot.pts.length;
  679.  
  680. // skip head area
  681. let start_n = 0;
  682. let start_d2 = 0.0;
  683. for ( ;; ) {
  684. let prev_d2 = start_d2;
  685. start_n ++;
  686. start_d2 = canvas.getDistance2(head.x, head.y,
  687. SlitherBot.pts[start_n].x, SlitherBot.pts[start_n].y);
  688. if (start_d2 < prev_d2 || start_n == ptsLength - 1) {
  689. break;
  690. }
  691. }
  692.  
  693. if (start_n >= ptsLength || start_n <= 1) {
  694. return SlitherBot.len;
  695. }
  696.  
  697. // find closets point in SlitherBot.pts
  698. let min_n = start_n;
  699. let min_d2 = start_d2;
  700. for (let n = min_n + 1; n < ptsLength; n++) {
  701. let d2 = canvas.getDistance2(head.x, head.y, SlitherBot.pts[n].x, SlitherBot.pts[n].y);
  702. if (d2 < min_d2) {
  703. min_n = n;
  704. min_d2 = d2;
  705. }
  706. }
  707.  
  708. // find second closest point
  709. let next_n = min_n;
  710. let next_d2 = min_d2;
  711. if (min_n == ptsLength - 1) {
  712. next_n = min_n - 1;
  713. next_d2 = canvas.getDistance2(head.x, head.y,
  714. SlitherBot.pts[next_n].x, SlitherBot.pts[next_n].y);
  715. } else {
  716. let d2m = canvas.getDistance2(head.x, head.y,
  717. SlitherBot.pts[min_n - 1].x, SlitherBot.pts[min_n - 1].y);
  718. let d2p = canvas.getDistance2(head.x, head.y,
  719. SlitherBot.pts[min_n + 1].x, SlitherBot.pts[min_n + 1].y);
  720. if (d2m < d2p) {
  721. next_n = min_n - 1;
  722. next_d2 = d2m;
  723. } else {
  724. next_n = min_n + 1;
  725. next_d2 = d2p;
  726. }
  727. }
  728.  
  729. // compute approximation
  730. let t2 = SlitherBot.pts[min_n].len - SlitherBot.pts[next_n].len;
  731. t2 *= t2;
  732.  
  733. if (t2 == 0) {
  734. return SlitherBot.pts[min_n].len;
  735. } else {
  736. let min_w = t2 - (min_d2 - next_d2);
  737. let next_w = t2 + (min_d2 - next_d2);
  738. return (SlitherBot.pts[min_n].len * min_w + SlitherBot.pts[next_n].len * next_w) / (2 * t2);
  739. }
  740. },
  741.  
  742. bodyDangerZone: function (
  743. offset, targetPoint, targetPointNormal, closePointDist, pastTargetPoint, closePoint) {
  744. var head = {
  745. x: window.snake.xx + window.snake.fx,
  746. y: window.snake.yy + window.snake.fy
  747. };
  748. const o = SlitherBot.opt.followCircleDirection;
  749. var pts = [
  750. {
  751. x: head.x - o * offset * SlitherBot.sin,
  752. y: head.y + o * offset * SlitherBot.cos
  753. },
  754. {
  755. x: head.x + SlitherBot.snakeWidth * SlitherBot.cos +
  756. offset * (SlitherBot.cos - o * SlitherBot.sin),
  757. y: head.y + SlitherBot.snakeWidth * SlitherBot.sin +
  758. offset * (SlitherBot.sin + o * SlitherBot.cos)
  759. },
  760. {
  761. x: head.x + 1.75 * SlitherBot.snakeWidth * SlitherBot.cos +
  762. o * 0.3 * SlitherBot.snakeWidth * SlitherBot.sin +
  763. offset * (SlitherBot.cos - o * SlitherBot.sin),
  764. y: head.y + 1.75 * SlitherBot.snakeWidth * SlitherBot.sin -
  765. o * 0.3 * SlitherBot.snakeWidth * SlitherBot.cos +
  766. offset * (SlitherBot.sin + o * SlitherBot.cos)
  767. },
  768. {
  769. x: head.x + 2.5 * SlitherBot.snakeWidth * SlitherBot.cos +
  770. o * 0.7 * SlitherBot.snakeWidth * SlitherBot.sin +
  771. offset * (SlitherBot.cos - o * SlitherBot.sin),
  772. y: head.y + 2.5 * SlitherBot.snakeWidth * SlitherBot.sin -
  773. o * 0.7 * SlitherBot.snakeWidth * SlitherBot.cos +
  774. offset * (SlitherBot.sin + o * SlitherBot.cos)
  775. },
  776. {
  777. x: head.x + 3 * SlitherBot.snakeWidth * SlitherBot.cos +
  778. o * 1.2 * SlitherBot.snakeWidth * SlitherBot.sin +
  779. offset * SlitherBot.cos,
  780. y: head.y + 3 * SlitherBot.snakeWidth * SlitherBot.sin -
  781. o * 1.2 * SlitherBot.snakeWidth * SlitherBot.cos +
  782. offset * SlitherBot.sin
  783. },
  784. {
  785. x: targetPoint.x +
  786. targetPointNormal.x * (offset + 0.5 * Math.max(closePointDist, 0)),
  787. y: targetPoint.y +
  788. targetPointNormal.y * (offset + 0.5 * Math.max(closePointDist, 0))
  789. },
  790. {
  791. x: pastTargetPoint.x + targetPointNormal.x * offset,
  792. y: pastTargetPoint.y + targetPointNormal.y * offset
  793. },
  794. pastTargetPoint,
  795. targetPoint,
  796. closePoint
  797. ];
  798. pts = canvas.convexHull(pts);
  799. var poly = {
  800. pts: pts
  801. };
  802. poly = canvas.addPolyBox(poly);
  803. return (poly);
  804. },
  805.  
  806. followCircleSelf: function () {
  807.  
  808. SlitherBot.populatePts();
  809. SlitherBot.determineCircleDirection();
  810. const o = SlitherBot.opt.followCircleDirection;
  811.  
  812.  
  813. // exit if too short
  814. if (SlitherBot.len < 9 * SlitherBot.snakeWidth) {
  815. return;
  816. }
  817.  
  818. var head = {
  819. x: window.snake.xx + window.snake.fx,
  820. y: window.snake.yy + window.snake.fy
  821. };
  822.  
  823. let closePointT = SlitherBot.closestBodyPoint();
  824. let closePoint = SlitherBot.smoothPoint(closePointT);
  825.  
  826. // approx tangent and normal vectors and closePoint
  827. var closePointNext = SlitherBot.smoothPoint(closePointT - SlitherBot.snakeWidth);
  828. var closePointTangent = canvas.unitVector({
  829. x: closePointNext.x - closePoint.x,
  830. y: closePointNext.y - closePoint.y});
  831. var closePointNormal = {
  832. x: - o * closePointTangent.y,
  833. y: o * closePointTangent.x
  834. };
  835.  
  836. // angle wrt closePointTangent
  837. var currentCourse = Math.asin(Math.max(
  838. -1, Math.min(1, SlitherBot.cos * closePointNormal.x + SlitherBot.sin * closePointNormal.y)));
  839.  
  840. // compute (oriented) distance from the body at closePointDist
  841. var closePointDist = (head.x - closePoint.x) * closePointNormal.x +
  842. (head.y - closePoint.y) * closePointNormal.y;
  843.  
  844. // construct polygon for snake inside
  845. var insidePolygonStartT = 5 * SlitherBot.snakeWidth;
  846. var insidePolygonEndT = closePointT + 5 * SlitherBot.snakeWidth;
  847. var insidePolygonPts = [
  848. SlitherBot.smoothPoint(insidePolygonEndT),
  849. SlitherBot.smoothPoint(insidePolygonStartT)
  850. ];
  851. for (let t = insidePolygonStartT; t < insidePolygonEndT; t += SlitherBot.snakeWidth) {
  852. insidePolygonPts.push(SlitherBot.smoothPoint(t));
  853. }
  854.  
  855. var insidePolygon = canvas.addPolyBox({
  856. pts: insidePolygonPts
  857. });
  858.  
  859. // get target point; this is an estimate where we land if we hurry
  860. var targetPointT = closePointT;
  861. var targetPointFar = 0.0;
  862. let targetPointStep = SlitherBot.snakeWidth / 64;
  863. for (let h = closePointDist, a = currentCourse; h >= 0.125 * SlitherBot.snakeWidth; ) {
  864. targetPointT -= targetPointStep;
  865. targetPointFar += targetPointStep * Math.cos(a);
  866. h += targetPointStep * Math.sin(a);
  867. a = Math.max(-Math.PI / 4, a - targetPointStep / SlitherBot.snakeWidth);
  868. }
  869.  
  870. var targetPoint = SlitherBot.smoothPoint(targetPointT);
  871.  
  872. var pastTargetPointT = targetPointT - 3 * SlitherBot.snakeWidth;
  873. var pastTargetPoint = SlitherBot.smoothPoint(pastTargetPointT);
  874.  
  875. // look for danger from enemies
  876. var enemyBodyOffsetDelta = 0.25 * SlitherBot.snakeWidth;
  877. var enemyHeadDist2 = 64 * 64 * SlitherBot.snakeWidth * SlitherBot.snakeWidth;
  878. for (let snake = 0, snakesNum = window.snakes.length; snake < snakesNum; snake++) {
  879. if (window.snakes[snake].id !== window.snake.id
  880. && window.snakes[snake].alive_amt === 1) {
  881. let enemyHead = {
  882. x: window.snakes[snake].xx + window.snakes[snake].fx,
  883. y: window.snakes[snake].yy + window.snakes[snake].fy
  884. };
  885. let enemyAhead = {
  886. x: enemyHead.x +
  887. Math.cos(window.snakes[snake].ang) * SlitherBot.snakeWidth,
  888. y: enemyHead.y +
  889. Math.sin(window.snakes[snake].ang) * SlitherBot.snakeWidth
  890. };
  891. // heads
  892. if (!canvas.pointInPoly(enemyHead, insidePolygon)) {
  893. enemyHeadDist2 = Math.min(
  894. enemyHeadDist2,
  895. canvas.getDistance2(enemyHead.x, enemyHead.y,
  896. targetPoint.x, targetPoint.y),
  897. canvas.getDistance2(enemyAhead.x, enemyAhead.y,
  898. targetPoint.x, targetPoint.y)
  899. );
  900. }
  901. // bodies
  902. let offsetSet = false;
  903. let offset = 0.0;
  904. let cpolbody = {};
  905. for (let pts = 0, ptsNum = window.snakes[snake].pts.length;
  906. pts < ptsNum; pts++) {
  907. if (!window.snakes[snake].pts[pts].dying) {
  908. let point = {
  909. x: window.snakes[snake].pts[pts].xx +
  910. window.snakes[snake].pts[pts].fx,
  911. y: window.snakes[snake].pts[pts].yy +
  912. window.snakes[snake].pts[pts].fy
  913. };
  914. while (!offsetSet || (enemyBodyOffsetDelta >= -SlitherBot.snakeWidth
  915. && canvas.pointInPoly(point, cpolbody))) {
  916. if (!offsetSet) {
  917. offsetSet = true;
  918. } else {
  919. enemyBodyOffsetDelta -= 0.0625 * SlitherBot.snakeWidth;
  920. }
  921. offset = 0.5 * (SlitherBot.snakeWidth +
  922. SlitherBot.getSnakeWidth(window.snakes[snake].sc)) +
  923. enemyBodyOffsetDelta;
  924. cpolbody = SlitherBot.bodyDangerZone(
  925. offset, targetPoint, closePointNormal, closePointDist,
  926. pastTargetPoint, closePoint);
  927.  
  928. }
  929. }
  930. }
  931. }
  932. }
  933. var enemyHeadDist = Math.sqrt(enemyHeadDist2);
  934.  
  935. // plot inside polygon
  936. if (window.visualDebugging) {
  937. for (let p = 0, l = insidePolygon.pts.length; p < l; p++) {
  938. let q = p + 1;
  939. if (q == l) {
  940. q = 0;
  941. }
  942. canvas.drawLine(
  943. {x: insidePolygon.pts[p].x, y: insidePolygon.pts[p].y},
  944. {x: insidePolygon.pts[q].x, y: insidePolygon.pts[q].y},
  945. 'orange');
  946. }
  947. }
  948.  
  949. // mark closePoint
  950. if (window.visualDebugging) {
  951. canvas.drawCircle(canvas.circle(
  952. closePoint.x,
  953. closePoint.y,
  954. SlitherBot.snakeWidth * 0.25
  955. ), 'white', false);
  956. }
  957.  
  958. // mark safeZone
  959. if (window.visualDebugging) {
  960. canvas.drawCircle(canvas.circle(
  961. targetPoint.x,
  962. targetPoint.y,
  963. SlitherBot.snakeWidth + 2 * targetPointFar
  964. ), 'white', false);
  965. canvas.drawCircle(canvas.circle(
  966. targetPoint.x,
  967. targetPoint.y,
  968. 0.2 * SlitherBot.snakeWidth
  969. ), 'white', false);
  970. }
  971.  
  972. // draw sample cpolbody
  973. if (window.visualDebugging) {
  974. let soffset = 0.5 * SlitherBot.snakeWidth;
  975. let scpolbody = SlitherBot.bodyDangerZone(
  976. soffset, targetPoint, closePointNormal,
  977. closePointDist, pastTargetPoint, closePoint);
  978. for (let p = 0, l = scpolbody.pts.length; p < l; p++) {
  979. let q = p + 1;
  980. if (q == l) {
  981. q = 0;
  982. }
  983. canvas.drawLine(
  984. {x: scpolbody.pts[p].x, y: scpolbody.pts[p].y},
  985. {x: scpolbody.pts[q].x, y: scpolbody.pts[q].y},
  986. 'white');
  987. }
  988. }
  989.  
  990. // TAKE ACTION
  991.  
  992. // expand?
  993. let targetCourse = currentCourse + 0.25;
  994. // enemy head nearby?
  995. let headProx = -1.0 - (2 * targetPointFar - enemyHeadDist) / SlitherBot.snakeWidth;
  996. if (headProx > 0) {
  997. headProx = 0.125 * headProx * headProx;
  998. } else {
  999. headProx = - 0.5 * headProx * headProx;
  1000. }
  1001. targetCourse = Math.min(targetCourse, headProx);
  1002. // enemy body nearby?
  1003. targetCourse = Math.min(
  1004. targetCourse, targetCourse + (enemyBodyOffsetDelta - 0.0625 * SlitherBot.snakeWidth) /
  1005. SlitherBot.snakeWidth);
  1006. // small tail?
  1007. var tailBehind = SlitherBot.len - closePointT;
  1008. var targetDir = canvas.unitVector({
  1009. x: SlitherBot.opt.followCircleTarget.x - head.x,
  1010. y: SlitherBot.opt.followCircleTarget.y - head.y
  1011. });
  1012. var driftQ = targetDir.x * closePointNormal.x + targetDir.y * closePointNormal.y;
  1013. var allowTail = SlitherBot.snakeWidth * (2 - 0.5 * driftQ);
  1014. // a line in the direction of the target point
  1015. if (window.visualDebugging) {
  1016. canvas.drawLine(
  1017. { x: head.x, y: head.y },
  1018. { x: head.x + allowTail * targetDir.x, y: head.y + allowTail * targetDir.y },
  1019. 'red');
  1020. }
  1021. targetCourse = Math.min(
  1022. targetCourse,
  1023. (tailBehind - allowTail + (SlitherBot.snakeWidth - closePointDist)) /
  1024. SlitherBot.snakeWidth);
  1025. // far away?
  1026. targetCourse = Math.min(
  1027. targetCourse, - 0.5 * (closePointDist - 4 * SlitherBot.snakeWidth) / SlitherBot.snakeWidth);
  1028. // final corrections
  1029. // too fast in?
  1030. targetCourse = Math.max(targetCourse, -0.75 * closePointDist / SlitherBot.snakeWidth);
  1031. // too fast out?
  1032. targetCourse = Math.min(targetCourse, 1.0);
  1033.  
  1034. var goalDir = {
  1035. x: closePointTangent.x * Math.cos(targetCourse) -
  1036. o * closePointTangent.y * Math.sin(targetCourse),
  1037. y: closePointTangent.y * Math.cos(targetCourse) +
  1038. o * closePointTangent.x * Math.sin(targetCourse)
  1039. };
  1040. var goal = {
  1041. x: head.x + goalDir.x * 4 * SlitherBot.snakeWidth,
  1042. y: head.y + goalDir.y * 4 * SlitherBot.snakeWidth
  1043. };
  1044.  
  1045.  
  1046. if (window.goalCoordinates
  1047. && Math.abs(goal.x - window.goalCoordinates.x) < 1000
  1048. && Math.abs(goal.y - window.goalCoordinates.y) < 1000) {
  1049. window.goalCoordinates = {
  1050. x: Math.round(goal.x * 0.25 + window.goalCoordinates.x * 0.75),
  1051. y: Math.round(goal.y * 0.25 + window.goalCoordinates.y * 0.75)
  1052. };
  1053. } else {
  1054. window.goalCoordinates = {
  1055. x: Math.round(goal.x),
  1056. y: Math.round(goal.y)
  1057. };
  1058. }
  1059.  
  1060. canvas.setMouseCoordinates(canvas.mapToMouse(window.goalCoordinates));
  1061. },
  1062.  
  1063. // Sorting by property 'score' descending
  1064. sortScore: function (a, b) {
  1065. return b.score - a.score;
  1066. },
  1067.  
  1068. // Sorting by property 'sz' descending
  1069. sortSz: function (a, b) {
  1070. return b.sz - a.sz;
  1071. },
  1072.  
  1073. // Sorting by property 'distance' ascending
  1074. sortDistance: function (a, b) {
  1075. return a.distance - b.distance;
  1076. },
  1077.  
  1078. //Set the snake ID of the current SlitherBot. Should only be called once.
  1079. setBotSnakeId: function () {
  1080. if (SlitherBot.id === 0) {
  1081. var id = window.snakes[0].id;
  1082. window.log('Setting bot snake ID to: ' + id);
  1083. SlitherBot.id = id;
  1084. }
  1085. },
  1086.  
  1087. computeFoodGoal: function () {
  1088. SlitherBot.foodAngles = [];
  1089.  
  1090. for (var i = 0; i < window.foods.length && window.foods[i] !== null; i++) {
  1091. var f = window.foods[i];
  1092. f.clusterRatio = 0.001; // Initialize cluster ratio to .001.
  1093. var totalClusterDistance = 0;
  1094. var numberOfFoodsInRadius = 0;
  1095.  
  1096. if (!f.eaten &&
  1097. !(
  1098. canvas.circleIntersect(
  1099. canvas.circle(f.xx, f.yy, 2),
  1100. SlitherBot.sidecircle_l) ||
  1101. canvas.circleIntersect(
  1102. canvas.circle(f.xx, f.yy, 2),
  1103. SlitherBot.sidecircle_r))
  1104.  
  1105. ) {
  1106. //calculate clustering index.
  1107. for (var j = 0; j < window.foods.length && window.foods[j] !== null; j++) {
  1108. var clusterFood = window.foods[j];
  1109. var distanceFromCurrentFood = Math.sqrt(Math.pow(f.xx - clusterFood.xx, 2) + Math.pow(f.yy - clusterFood.yy, 2));
  1110.  
  1111. //If food is close enough, then add distance to running tally and increment number of foods counted.
  1112. if (distanceFromCurrentFood <= SlitherBot.opt.foodClusterRadius && distanceFromCurrentFood > 0) {
  1113. totalClusterDistance += distanceFromCurrentFood;
  1114. numberOfFoodsInRadius++;
  1115.  
  1116. f.clusterRatio = (numberOfFoodsInRadius / totalClusterDistance);
  1117. }
  1118. }
  1119.  
  1120. if (f.clusterRatio > 0.18) {
  1121. f.isDense = true;
  1122. window.log('Number of foods in radius: ' + numberOfFoodsInRadius);
  1123. window.log('Total cluster distance: ' + totalClusterDistance);
  1124. window.log(f);
  1125. } else {
  1126. f.isDense = false;
  1127. }
  1128. if (f.clusterRatio <= 0.006 && f.clusterRatio > 0.001) {
  1129. f.isSparse = true;
  1130. window.log('Number of foods in radius: ' + numberOfFoodsInRadius);
  1131. window.log('Total cluster distance: ' + totalClusterDistance);
  1132. window.log(f);
  1133. } else {
  1134. f.isSparse = false;
  1135. }
  1136.  
  1137. SlitherBot.addFoodAngle(f);
  1138. }
  1139. }
  1140.  
  1141. SlitherBot.foodAngles.sort(SlitherBot.sortScore);
  1142.  
  1143. if (SlitherBot.foodAngles[0] !== undefined && SlitherBot.foodAngles[0].sz > 0) {
  1144. SlitherBot.currentFood = { x: SlitherBot.foodAngles[0].x,
  1145. y: SlitherBot.foodAngles[0].y,
  1146. sz: SlitherBot.foodAngles[0].sz,
  1147. da: SlitherBot.foodAngles[0].da };
  1148. } else {
  1149. SlitherBot.currentFood = { x: SlitherBot.MID_X, y: SlitherBot.MID_Y, sz: 0 };
  1150. }
  1151. },
  1152.  
  1153. foodAccel: function () {
  1154. var angleIndex = 0;
  1155.  
  1156. if (SlitherBot.currentFood.isDense || SlitherBot.currentFood.sz > SlitherBot.opt.foodAccelerateSize) {
  1157. angleIndex = SlitherBot.getAngleIndex(SlitherBot.currentFood.ang);
  1158. if (
  1159. SlitherBot.collisionAngles[angleIndex] && SlitherBot.collisionAngles[angleIndex].distance >
  1160. SlitherBot.currentFood.distance + SlitherBot.snakeRadius * SlitherBot.opt.radiusMult
  1161. && SlitherBot.currentFood.da < SlitherBot.opt.foodAccelDa) {
  1162. return 1;
  1163. }
  1164.  
  1165. if (SlitherBot.collisionAngles[angleIndex] === undefined
  1166. && SlitherBot.currentFood.da < SlitherBot.opt.foodAccelDa) {
  1167. return 1;
  1168. }
  1169. }
  1170.  
  1171. return SlitherBot.defaultAccel;
  1172. },
  1173.  
  1174. toCircle: function () {
  1175. for (var i = 0; i < window.snake.pts.length && window.snake.pts[i].dying; i++);
  1176. const o = SlitherBot.opt.followCircleDirection;
  1177. var tailCircle = canvas.circle(
  1178. window.snake.pts[i].xx,
  1179. window.snake.pts[i].yy,
  1180. SlitherBot.headCircle.radius
  1181. );
  1182.  
  1183. if (window.visualDebugging) {
  1184. canvas.drawCircle(tailCircle, 'blue', false);
  1185. }
  1186.  
  1187. window.setAcceleration(SlitherBot.defaultAccel);
  1188. SlitherBot.changeHeadingRel(o * Math.PI / 32);
  1189.  
  1190. if (canvas.circleIntersect(SlitherBot.headCircle, tailCircle)) {
  1191. SlitherBot.stage = 'circle';
  1192. }
  1193. },
  1194.  
  1195. every: function () {
  1196. SlitherBot.MID_X = window.grd;
  1197. SlitherBot.MID_Y = window.grd;
  1198. SlitherBot.MAP_R = window.grd * 0.98;
  1199. SlitherBot.MAXARC = (2 * Math.PI) / SlitherBot.opt.arcSize;
  1200.  
  1201. if (SlitherBot.opt.followCircleTarget === undefined) {
  1202. SlitherBot.opt.followCircleTarget = {
  1203. x: SlitherBot.MID_X,
  1204. y: SlitherBot.MID_Y
  1205. };
  1206. }
  1207.  
  1208. SlitherBot.sectorBoxSide = Math.floor(Math.sqrt(window.sectors.length)) * window.sector_size;
  1209. SlitherBot.sectorBox = canvas.rect(
  1210. window.snake.xx - (SlitherBot.sectorBoxSide / 2),
  1211. window.snake.yy - (SlitherBot.sectorBoxSide / 2),
  1212. SlitherBot.sectorBoxSide, SlitherBot.sectorBoxSide);
  1213. // if (window.visualDebugging) canvas.drawRect(SlitherBot.sectorBox, '#c0c0c0', true, 0.1);
  1214.  
  1215. SlitherBot.cos = Math.cos(window.snake.ang);
  1216. SlitherBot.sin = Math.sin(window.snake.ang);
  1217.  
  1218. SlitherBot.speedMult = window.snake.sp / SlitherBot.opt.speedBase;
  1219. SlitherBot.snakeRadius = SlitherBot.getSnakeWidth() / 2;
  1220. SlitherBot.snakeWidth = SlitherBot.getSnakeWidth();
  1221. SlitherBot.snakeLength = Math.floor(15 * (window.fpsls[window.snake.sct] + window.snake.fam /
  1222. window.fmlts[window.snake.sct] - 1) - 5);
  1223.  
  1224. // SlitherBot.headCircle = canvas.circle(
  1225. // window.snake.xx + SlitherBot.cos * Math.min(1, SlitherBot.speedMult - 1) *
  1226. // SlitherBot.opt.radiusMult / 2 * SlitherBot.snakeRadius,
  1227. // window.snake.yy + SlitherBot.sin * Math.min(1, SlitherBot.speedMult - 1) *
  1228. // SlitherBot.opt.radiusMult / 2 * SlitherBot.snakeRadius,
  1229. // SlitherBot.opt.radiusMult / 2 * SlitherBot.snakeRadius
  1230. // );
  1231. var angleIndex = SlitherBot.getAngleIndex(SlitherBot.currentFood.ang);
  1232. window.log('Current Food:');
  1233. window.log(SlitherBot.currentFood);
  1234. window.log('Angle Index: ' + angleIndex);
  1235. window.log('window.snake:');
  1236. window.log(window.snake);
  1237. SlitherBot.headCircle = canvas.arc(
  1238. //Snake X coord 15712.786069922688
  1239. window.snake.xx,
  1240. //Snake Y coord 21231.5666645047
  1241. window.snake.yy,
  1242. //Radius of Arc (10 / 2 * (1.0566037735849056 * 29 / 2)
  1243. SlitherBot.opt.radiusMult / 2 * SlitherBot.snakeRadius,
  1244. //Starting angle 0.22173166648125028
  1245. window.snake.eang * Math.PI,
  1246. //Ending angle 0.2699806186678728
  1247. window.snake.wang * Math.PI
  1248. );
  1249.  
  1250. SlitherBot.sidecircle_r = canvas.circle(
  1251. window.snake.lnp.xx -
  1252. ((window.snake.lnp.yy + SlitherBot.sin * SlitherBot.snakeWidth) -
  1253. window.snake.lnp.yy),
  1254. window.snake.lnp.yy +
  1255. ((window.snake.lnp.xx + SlitherBot.cos * SlitherBot.snakeWidth) -
  1256. window.snake.lnp.xx),
  1257. SlitherBot.snakeWidth * SlitherBot.speedMult
  1258. );
  1259.  
  1260. SlitherBot.sidecircle_l = canvas.circle(
  1261. window.snake.lnp.xx +
  1262. ((window.snake.lnp.yy + SlitherBot.sin * SlitherBot.snakeWidth) -
  1263. window.snake.lnp.yy),
  1264. window.snake.lnp.yy -
  1265. ((window.snake.lnp.xx + SlitherBot.cos * SlitherBot.snakeWidth) -
  1266. window.snake.lnp.xx),
  1267. SlitherBot.snakeWidth * SlitherBot.speedMult
  1268. );
  1269.  
  1270.  
  1271. if (window.visualDebugging) {
  1272. canvas.drawArc(SlitherBot.headCircle, 'blue', false);
  1273. canvas.drawCircle(SlitherBot.sidecircle_r, 'green', false);
  1274. canvas.drawCircle(SlitherBot.sidecircle_l, 'green', false);
  1275. }
  1276.  
  1277. },
  1278.  
  1279. // Main bot
  1280. go: function () {
  1281. var currentSnake = "";
  1282. var otherSnakes = "";
  1283. var allFood = "";
  1284. var allPrey = "";
  1285.  
  1286. if (window.snake) {
  1287. currentSnake = JSON.stringify(window.snake);
  1288. } else {
  1289. currentSnake = JSON.stringify({});
  1290. }
  1291.  
  1292. if (window.snakes) {
  1293. otherSnakes = JSON.stringify(window.snakes);
  1294. } else {
  1295. otherSnakes = JSON.stringify({});
  1296. }
  1297.  
  1298. if (window.foods) {
  1299. allFood = JSON.stringify(window.foods);
  1300. } else {
  1301. allFood = JSON.stringify({});
  1302. }
  1303.  
  1304. if (window.preys) {
  1305. allPrey = JSON.stringify(window.preys);
  1306. } else {
  1307. allPrey = JSON.stringify({});
  1308. }
  1309.  
  1310. // console.log('Current snake: ' + currentSnake);
  1311. // console.log('Other snakes: ' + otherSnakes);
  1312. // console.log('All food: ' + allFood);
  1313. // console.log('All prey: ' + allPrey);
  1314.  
  1315. var input = [ currentSnake, otherSnakes, allFood, allPrey ];
  1316. input = [ 1, 0, 1, 1 ];
  1317. var output = window.LSTM.activate(input);
  1318.  
  1319. console.log('Ouput:');
  1320. console.log(output);
  1321.  
  1322. SlitherBot.every();
  1323.  
  1324. if (SlitherBot.snakeLength < SlitherBot.opt.followCircleLength) {
  1325. SlitherBot.stage = 'grow';
  1326. }
  1327.  
  1328. if (SlitherBot.currentFood && SlitherBot.stage !== 'grow') {
  1329. SlitherBot.currentFood = undefined;
  1330. }
  1331.  
  1332. if (SlitherBot.stage === 'circle' && !SlitherBot.isSelfCirclingEnabled) {
  1333. window.setAcceleration(SlitherBot.defaultAccel);
  1334. SlitherBot.followCircleSelf();
  1335. } else if (SlitherBot.checkCollision() || SlitherBot.checkEncircle()) {
  1336. if (SlitherBot.actionTimeout) {
  1337. window.clearTimeout(SlitherBot.actionTimeout);
  1338. SlitherBot.actionTimeout = window.setTimeout(
  1339. SlitherBot.actionTimer, 1000 / SlitherBot.opt.targetFps * SlitherBot.opt.collisionDelay);
  1340. }
  1341. } else {
  1342. if (SlitherBot.snakeLength > SlitherBot.opt.followCircleLength) {
  1343. SlitherBot.stage = 'tocircle';
  1344. }
  1345. if (SlitherBot.actionTimeout === undefined) {
  1346. SlitherBot.actionTimeout = window.setTimeout(
  1347. SlitherBot.actionTimer, 1000 / SlitherBot.opt.targetFps * SlitherBot.opt.actionFrames);
  1348. }
  1349. window.setAcceleration(SlitherBot.foodAccel());
  1350. }
  1351. },
  1352.  
  1353. // Timer version of food check
  1354. actionTimer: function () {
  1355. if (window.playing && window.snake !== null && window.snake.alive_amt === 1) {
  1356. if (SlitherBot.stage === 'grow') {
  1357. SlitherBot.computeFoodGoal();
  1358. window.goalCoordinates = SlitherBot.currentFood;
  1359. canvas.setMouseCoordinates(canvas.mapToMouse(window.goalCoordinates));
  1360. } else if (SlitherBot.stage === 'tocircle') {
  1361. SlitherBot.toCircle();
  1362. }
  1363. }
  1364. SlitherBot.actionTimeout = undefined;
  1365. }
  1366. };
  1367. })(window);
  1368.  
  1369. //var exampleSnake = {
  1370. // alive_amt: 1
  1371. // ang: 2.3071071049800045
  1372. // antenna: false
  1373. // bb: 153
  1374. // cfl: 229.38530735245803
  1375. // chl: 0.4672818702008886
  1376. // cs: "#ff9499"
  1377. // cs04: "#663b3d"
  1378. // csw: "#ffcacc"
  1379. // cusk: true
  1380. // cv: 6
  1381. // dead_amt: 0
  1382. // dir: 0
  1383. // drez: false
  1384. // eac: false
  1385. // eang: 2.3071071049800045
  1386. // easp: 0.1
  1387. // ec: "#ffffff"
  1388. // eca: 0.75
  1389. // ed: 6
  1390. // edir: 0
  1391. // ehang: 2.2688820827748657
  1392. // ehl: 0.3
  1393. // eo: 0
  1394. // er: 6
  1395. // esp: 6
  1396. // fa: -0.017496943473815918
  1397. // fam: 0.7040646495857626
  1398. // fapos: 13
  1399. // fatg: 16
  1400. // fchl: -0.19521689414978027
  1401. // fdhc: null
  1402. // fdl: 0
  1403. // fdtc: null
  1404. // fl: -0.3104568421840668
  1405. // flpos: 70
  1406. // fltg: 128,
  1407. // fnfr: 0,
  1408. // fpos: 27,
  1409. // fsp: 6.746603773584905,
  1410. // ftg: 33,
  1411. // fx: 6.117638111114502,
  1412. // fy: -5.392940521240234,
  1413. // gg: 148,
  1414. // id: 63686,
  1415. // iiv: false,
  1416. // jyt: false,
  1417. // msl: 42,
  1418. // msp: 14,
  1419. // na: 1,
  1420. // nk: "wormhole ",
  1421. // one_eye: false,
  1422. // pma: 2.3,
  1423. // ppa: 1,
  1424. // ppc: "#000000",
  1425. // pr: 3.5,
  1426. // pts: (233) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, …],
  1427. // rcv: 0,
  1428. // rex: -1.5445855961481423,
  1429. // rey: 1.7041875883164055,
  1430. // rr: 255,
  1431. // sc: 3.141509433962264,
  1432. // scang: 0.48979211166488673,
  1433. // sct: 229,
  1434. // sep: 18.849056603773583,
  1435. // sfr: 0,
  1436. // slg: false,
  1437. // sp: 6.611111111111111,
  1438. // spang: 1,
  1439. // ssp: 6.646603773584905,
  1440. // swell: 0,
  1441. // tl: 229.70406464958577,
  1442. // tsp: 6.611111111111111,
  1443. // wang: 2.3071071049800045,
  1444. // wehang: 2.2688820827748657,
  1445. // wsep: 18.849056603773583,
  1446. // xx: 19870.620092376415,
  1447. // yy: 10961.9417871585
  1448. //};
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement