Tweaking

just 4 smth

当前为 2023-07-20 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/scripts/471295/1222883/Tweaking.js

  1. // ==UserScript==
  2. // @name Tweaking
  3. // @namespace https://github.com/longkidkoolstar
  4. // @version 0.0.1
  5. // @author longkidkoolstar
  6. // @description just 4 smth
  7. // @icon https://images.chesscomfiles.com/uploads/v1/images_users/tiny_mce/SamCopeland/phpmeXx6V.png
  8. // @match https://www.chess.com/*
  9. // @run-at document-end
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. "use strict";
  14. let playerIsWhiteCache = false;
  15. const playerIsWhite = () => {
  16. if (playerIsWhiteCache)
  17. return playerIsWhiteCache;
  18. const firstCoordinateIsEight = document.querySelector(".coordinates").childNodes[0].textContent === "8";
  19. playerIsWhiteCache = firstCoordinateIsEight;
  20. return firstCoordinateIsEight;
  21. };
  22. const init$1 = () => {
  23. playerIsWhite();
  24. };
  25. const configService = { playerIsWhite, init: init$1 };
  26. const createElement = ({
  27. type,
  28. classes
  29. }) => {
  30. const element = document.createElement(type);
  31. classes.forEach((c) => element.classList.add(c));
  32. return element;
  33. };
  34. const getBoard = () => {
  35. const board = document.querySelector("chess-board");
  36. if (!board)
  37. return null;
  38. return board;
  39. };
  40. const domService = { createElement, getBoard };
  41. const chessMoves = {
  42. pawn: [
  43. {
  44. x: 0,
  45. y: 1,
  46. condition: ["base"]
  47. },
  48. {
  49. x: 0,
  50. y: 2,
  51. condition: ["isFirstMove"]
  52. },
  53. {
  54. y: 1,
  55. x: 1,
  56. condition: ["canAttack"]
  57. },
  58. {
  59. y: 1,
  60. x: -1,
  61. condition: ["canAttack"]
  62. }
  63. ],
  64. rook: [
  65. {
  66. y: "n",
  67. x: 0
  68. },
  69. {
  70. y: 0,
  71. x: "n"
  72. }
  73. ],
  74. bishop: [
  75. {
  76. y: "n1",
  77. x: "n1"
  78. }
  79. ],
  80. queen: [
  81. {
  82. y: "n1",
  83. x: "n1"
  84. },
  85. {
  86. y: "n",
  87. x: 0
  88. },
  89. {
  90. y: 0,
  91. x: "n"
  92. }
  93. ],
  94. knight: [
  95. {
  96. y: 2,
  97. x: 1,
  98. condition: ["always"]
  99. },
  100. {
  101. y: 2,
  102. x: -1,
  103. condition: ["always"]
  104. },
  105. {
  106. y: -2,
  107. x: 1,
  108. condition: ["always"]
  109. },
  110. {
  111. y: -2,
  112. x: -1,
  113. condition: ["always"]
  114. },
  115. {
  116. y: 1,
  117. x: 2,
  118. condition: ["always"]
  119. },
  120. {
  121. y: 1,
  122. x: -2,
  123. condition: ["always"]
  124. },
  125. {
  126. y: -1,
  127. x: 2,
  128. condition: ["always"]
  129. },
  130. {
  131. y: -1,
  132. x: -2,
  133. condition: ["always"]
  134. }
  135. ],
  136. king: [
  137. {
  138. y: 1,
  139. x: 0,
  140. condition: ["isSafe"]
  141. },
  142. {
  143. y: 1,
  144. x: 1,
  145. condition: ["isSafe"]
  146. },
  147. {
  148. y: 1,
  149. x: -1,
  150. condition: ["isSafe"]
  151. },
  152. {
  153. y: -1,
  154. x: 0,
  155. condition: ["isSafe"]
  156. },
  157. {
  158. y: -1,
  159. x: 1,
  160. condition: ["isSafe"]
  161. },
  162. {
  163. y: -1,
  164. x: -1,
  165. condition: ["isSafe"]
  166. },
  167. {
  168. y: 0,
  169. x: 1,
  170. condition: ["isSafe"]
  171. },
  172. {
  173. y: 0,
  174. x: -1,
  175. condition: ["isSafe"]
  176. },
  177. // castling moves
  178. {
  179. y: 0,
  180. x: 2,
  181. condition: ["isSafe", "isFirstMove", "towerUntouched", "castling"]
  182. },
  183. {
  184. y: 0,
  185. x: -2,
  186. condition: ["isSafe", "isFirstMove", "towerUntouched", "castling"]
  187. }
  188. ]
  189. };
  190. const chessTypes = {
  191. p: "pawn",
  192. r: "rook",
  193. n: "knight",
  194. b: "bishop",
  195. q: "queen",
  196. k: "king"
  197. };
  198. const ALTERATION_FIRST = 10;
  199. const ALTERATION_LAST = 1;
  200. const Square = (square, metaData, startSquare = null) => {
  201. startSquare = startSquare ?? Number(square);
  202. let current = Number(square);
  203. let isOnPiece = false;
  204. let id = crypto.randomUUID();
  205. let isOnEnemyPiece = false;
  206. let isOnEndOfBoard = false;
  207. let isOutsideBoard = false;
  208. let isActivePiece = true;
  209. let canAttack = true;
  210. const validate = () => {
  211. const info = squareService.getCurrentLocationPieceInfo(
  212. current,
  213. startSquare
  214. );
  215. if (info) {
  216. isOnPiece = info.isOnPiece;
  217. isOnEnemyPiece = info.isOnEnemyPiece;
  218. } else {
  219. isOnPiece = false;
  220. isOnEnemyPiece = false;
  221. }
  222. if (squareService.isLocatedOnEndOfBoard(current)) {
  223. isOnEndOfBoard = true;
  224. }
  225. if (squareService.isOutsideOfBoard(current)) {
  226. isOutsideBoard = true;
  227. }
  228. };
  229. validate();
  230. const getFirst = () => Number(String(current).charAt(0));
  231. const getLast = () => Number(String(current).charAt(1));
  232. const moveRight = () => {
  233. current += ALTERATION_FIRST;
  234. validate();
  235. return Square(current, metaData, startSquare);
  236. };
  237. const moveLeft = () => {
  238. current -= ALTERATION_FIRST;
  239. validate();
  240. return Square(current, metaData, startSquare);
  241. };
  242. const moveUp = () => {
  243. current += ALTERATION_LAST;
  244. validate();
  245. return Square(current, metaData, startSquare);
  246. };
  247. const moveDown = () => {
  248. current -= ALTERATION_LAST;
  249. validate();
  250. return Square(current, metaData, startSquare);
  251. };
  252. const setActivePiece = (active) => {
  253. isActivePiece = active;
  254. };
  255. const setCanAttack = (attacking) => {
  256. canAttack = attacking;
  257. };
  258. return {
  259. getStartSquareNumber: () => startSquare,
  260. getStartSquare: () => Square(startSquare, metaData),
  261. getFirst,
  262. getLast,
  263. getCurrent: () => current,
  264. getMetaData: () => metaData,
  265. getId: () => id,
  266. moveRight,
  267. moveLeft,
  268. moveUp,
  269. moveDown,
  270. setActivePiece,
  271. setCanAttack,
  272. isActivePiece: () => isActivePiece,
  273. canAttack: () => canAttack,
  274. isOnPiece: () => isOnPiece,
  275. isOnEnemyPiece: () => isOnEnemyPiece,
  276. isOnEndOfBoard: () => isOnEndOfBoard,
  277. isOutsideBoard: () => isOutsideBoard,
  278. isOnRow: (row) => getLast() === row,
  279. getSquare: () => Square(current, metaData, startSquare)
  280. };
  281. };
  282. const handleRepeatedMoveUntilBreak = (square, moves2, callback) => {
  283. let tempSquare = square.getSquare();
  284. while (true) {
  285. tempSquare = callback(tempSquare);
  286. if ((tempSquare == null ? void 0 : tempSquare.isOutsideBoard()) || tempSquare === null) {
  287. break;
  288. }
  289. if (tempSquare.isOnPiece()) {
  290. if (tempSquare.isOnEnemyPiece()) {
  291. moves2.push(tempSquare.getSquare());
  292. } else {
  293. tempSquare.setActivePiece(false);
  294. moves2.push(tempSquare.getSquare());
  295. }
  296. break;
  297. }
  298. moves2.push(tempSquare.getSquare());
  299. }
  300. };
  301. const handleAxis = (axis, square, moveOnAxis) => {
  302. const isPositive = moveOnAxis > 0;
  303. const isNegative = moveOnAxis < 0;
  304. if (isPositive) {
  305. for (let i = 0; i < moveOnAxis; i++) {
  306. if (axis === "y")
  307. square.moveUp();
  308. if (axis === "x")
  309. square.moveRight();
  310. }
  311. }
  312. if (isNegative) {
  313. for (let i = 0; i > moveOnAxis; i--) {
  314. if (axis === "y")
  315. square.moveDown();
  316. if (axis === "x")
  317. square.moveLeft();
  318. }
  319. }
  320. };
  321. const prepareKingMove = (move, metaData) => {
  322. var _a;
  323. const x = move.x;
  324. const y = move.y;
  325. if (Number.isNaN(x) || Number.isNaN(y)) {
  326. console.log("Both need to be numbers");
  327. return null;
  328. }
  329. const square = Square(metaData.square, metaData);
  330. if ((_a = move.condition) == null ? void 0 : _a.includes("castling")) {
  331. return null;
  332. }
  333. handleAxis("x", square, x);
  334. handleAxis("y", square, y);
  335. return square;
  336. };
  337. const prepareKnightMove = (move, metaData) => {
  338. const x = move.x;
  339. const y = move.y;
  340. if (Number.isNaN(x) || Number.isNaN(y)) {
  341. console.log("Both need to be numbers");
  342. return null;
  343. }
  344. const square = Square(metaData.square, metaData);
  345. handleAxis("x", square, x);
  346. handleAxis("y", square, y);
  347. return square;
  348. };
  349. const prepareN1Moves = (move, metaData) => {
  350. let moves2 = [];
  351. if (move.x !== "n1" || move.y !== "n1") {
  352. console.log("Both need to be n1");
  353. return moves2;
  354. }
  355. const startSquare = Square(metaData.square, metaData);
  356. handleRepeatedMoveUntilBreak(startSquare, moves2, (square) => {
  357. square.moveUp();
  358. return square.moveRight();
  359. });
  360. handleRepeatedMoveUntilBreak(startSquare, moves2, (square) => {
  361. square.moveUp();
  362. return square.moveLeft();
  363. });
  364. handleRepeatedMoveUntilBreak(startSquare, moves2, (square) => {
  365. square.moveDown();
  366. return square.moveRight();
  367. });
  368. handleRepeatedMoveUntilBreak(startSquare, moves2, (square) => {
  369. square.moveDown();
  370. return square.moveLeft();
  371. });
  372. return moves2;
  373. };
  374. const prepareNMoves = (move, metaData) => {
  375. let moves2 = [];
  376. if (move.x === "n" && move.y === "n") {
  377. console.log("handle special case");
  378. return moves2;
  379. }
  380. if (move.x !== "n" && move.y !== "n") {
  381. console.log("Cannot have both x and y as n");
  382. return moves2;
  383. }
  384. const handleVertical = move.y === "n";
  385. const square = Square(metaData.square, metaData);
  386. if (handleVertical) {
  387. handleRepeatedMoveUntilBreak(
  388. square,
  389. moves2,
  390. (square2) => square2.moveUp()
  391. );
  392. handleRepeatedMoveUntilBreak(
  393. square,
  394. moves2,
  395. (square2) => square2.moveDown()
  396. );
  397. } else {
  398. handleRepeatedMoveUntilBreak(
  399. square,
  400. moves2,
  401. (square2) => square2.moveRight()
  402. );
  403. handleRepeatedMoveUntilBreak(
  404. square,
  405. moves2,
  406. (square2) => square2.moveLeft()
  407. );
  408. }
  409. return moves2;
  410. };
  411. const preparePawnMove = (move, metaData) => {
  412. var _a, _b, _c, _d, _e, _f, _g;
  413. let square = Square(metaData.square, metaData);
  414. const isWhitePiece = metaData.isWhite;
  415. const checkIfFirstMove = (square2) => {
  416. if (isWhitePiece) {
  417. return square2.getSquare().isOnRow(2);
  418. } else {
  419. return square2.getSquare().isOnRow(7);
  420. }
  421. };
  422. const isFirstMove = checkIfFirstMove(square);
  423. const handleAxis2 = (axis, move2, callbacks) => {
  424. const value = move2[axis];
  425. if (value !== 0 && Number.isInteger(value)) {
  426. let x = value;
  427. const isPositive = x > 0;
  428. if (isWhitePiece) {
  429. for (let i = 0; i < Math.abs(x); i++) {
  430. if (isPositive) {
  431. callbacks.whiteAndPositive(square);
  432. } else {
  433. callbacks.whiteAndNegative(square);
  434. }
  435. if (square.isOnPiece()) {
  436. break;
  437. }
  438. }
  439. } else {
  440. for (let i = 0; i < Math.abs(x); i++) {
  441. if (isPositive) {
  442. callbacks.blackAndPositive(square);
  443. } else {
  444. callbacks.blackAndNegative(square);
  445. }
  446. if (square.isOnPiece()) {
  447. break;
  448. }
  449. }
  450. }
  451. }
  452. };
  453. handleAxis2("y", move, {
  454. blackAndPositive: (square2) => square2.moveDown(),
  455. blackAndNegative: (square2) => square2.moveUp(),
  456. whiteAndPositive: (square2) => square2.moveUp(),
  457. whiteAndNegative: (square2) => square2.moveDown()
  458. });
  459. handleAxis2("x", move, {
  460. blackAndPositive: (square2) => square2.moveLeft(),
  461. blackAndNegative: (square2) => square2.moveRight(),
  462. whiteAndPositive: (square2) => square2.moveRight(),
  463. whiteAndNegative: (square2) => square2.moveLeft()
  464. });
  465. if (((_a = move == null ? void 0 : move.condition) == null ? void 0 : _a.includes("isFirstMove")) && !isFirstMove) {
  466. return null;
  467. }
  468. if (((_b = move == null ? void 0 : move.condition) == null ? void 0 : _b.includes("isFirstMove")) && isFirstMove && square.isOnPiece()) {
  469. square.setCanAttack(false);
  470. square.setActivePiece(false);
  471. return square;
  472. }
  473. if (((_c = move == null ? void 0 : move.condition) == null ? void 0 : _c.includes("isFirstMove")) && isFirstMove) {
  474. square.setCanAttack(false);
  475. return square;
  476. }
  477. if (((_d = move == null ? void 0 : move.condition) == null ? void 0 : _d.includes("canAttack")) && !square.isOnEnemyPiece()) {
  478. square.setActivePiece(false);
  479. return square;
  480. }
  481. if (((_e = move == null ? void 0 : move.condition) == null ? void 0 : _e.includes("canAttack")) && square.isOnEnemyPiece()) {
  482. square.setCanAttack(true);
  483. return square;
  484. }
  485. if (!((_f = move == null ? void 0 : move.condition) == null ? void 0 : _f.includes("canAttack")) && square.isOnPiece()) {
  486. square.setActivePiece(false);
  487. square.setCanAttack(false);
  488. return square;
  489. }
  490. if ((_g = move == null ? void 0 : move.condition) == null ? void 0 : _g.includes("base")) {
  491. square.setCanAttack(false);
  492. return square;
  493. }
  494. return square;
  495. };
  496. const moveService = {
  497. preparePawnMove,
  498. prepareKnightMove,
  499. prepareKingMove,
  500. prepareNMoves,
  501. prepareN1Moves
  502. };
  503. const clearSquare = (board) => {
  504. var _a, _b;
  505. const toRemove = board.querySelectorAll(".doRemove");
  506. for (const element of toRemove) {
  507. (_a = element == null ? void 0 : element.parentNode) == null ? void 0 : _a.removeChild(element);
  508. }
  509. const highlightsToRemove = board.querySelectorAll(".highlight");
  510. for (const element of highlightsToRemove) {
  511. (_b = element == null ? void 0 : element.classList) == null ? void 0 : _b.remove("highlight");
  512. }
  513. };
  514. const getCurrentLocationPieceInfo = (square, start) => {
  515. if (square === start)
  516. return null;
  517. const isOnPiece = (current2) => {
  518. var _a;
  519. return (_a = current2 == null ? void 0 : current2.className) == null ? void 0 : _a.includes("piece");
  520. };
  521. const startSquare = Array.from(
  522. document.querySelectorAll(`.square-${start}`)
  523. ).find((e) => isOnPiece(e));
  524. const current = Array.from(
  525. document.querySelectorAll(`.square-${square}`)
  526. ).find((e) => isOnPiece(e));
  527. const metaData = getMetaDataForSquare(startSquare);
  528. const isBlackPiecePlaying = !metaData.isWhite;
  529. const isStandingOnWhitePiece = (current2) => {
  530. const metaData2 = getMetaDataForSquare(current2);
  531. return (metaData2 == null ? void 0 : metaData2.isWhite) ?? false;
  532. };
  533. const isOnEnemy = isBlackPiecePlaying && isStandingOnWhitePiece(current) || !isBlackPiecePlaying && !isStandingOnWhitePiece(current);
  534. return {
  535. isOnPiece: isOnPiece(current),
  536. isOnEnemyPiece: isOnPiece(current) ? isOnEnemy : false
  537. };
  538. };
  539. const isLocatedOnEndOfBoard = (square) => {
  540. const first = Number(String(square).charAt(0));
  541. const last = Number(String(square).charAt(1));
  542. if (first === 8 || first === 1)
  543. return true;
  544. if (last === 8 || last === 1)
  545. return true;
  546. return false;
  547. };
  548. const isOutsideOfBoard = (square) => {
  549. const first = Number(String(square).charAt(0));
  550. const last = Number(String(square).charAt(1));
  551. if (!first || !last)
  552. return true;
  553. if (first > 8 || first < 1)
  554. return true;
  555. if (last > 8 || last < 1)
  556. return true;
  557. return false;
  558. };
  559. const getPossibleMoveSquares = (moves2, metaData) => {
  560. let totalMoves = [];
  561. for (const move of moves2) {
  562. let tempMoves = [];
  563. switch (metaData.type) {
  564. case "pawn":
  565. const pawnMove = moveService.preparePawnMove(move, metaData);
  566. if (pawnMove)
  567. tempMoves = [pawnMove];
  568. break;
  569. case "rook":
  570. tempMoves = moveService.prepareNMoves(move, metaData);
  571. break;
  572. case "bishop":
  573. tempMoves = moveService.prepareN1Moves(move, metaData);
  574. break;
  575. case "queen":
  576. const isNMove = move.x === "n" || move.y === "n";
  577. if (isNMove) {
  578. tempMoves = moveService.prepareNMoves(move, metaData);
  579. } else {
  580. tempMoves = moveService.prepareN1Moves(move, metaData);
  581. }
  582. break;
  583. case "knight":
  584. const knightMove = moveService.prepareKnightMove(
  585. move,
  586. metaData
  587. );
  588. if (knightMove)
  589. tempMoves = [knightMove];
  590. break;
  591. case "king":
  592. const kingMove = moveService.prepareKingMove(move, metaData);
  593. if (kingMove)
  594. tempMoves = [kingMove];
  595. break;
  596. default:
  597. console.log("Not implemented yet");
  598. }
  599. totalMoves = [...totalMoves, ...tempMoves];
  600. }
  601. return totalMoves;
  602. };
  603. const getMetaDataForSquare = (target) => {
  604. var _a;
  605. if (target instanceof SVGElement)
  606. return null;
  607. if (!((_a = target == null ? void 0 : target.className) == null ? void 0 : _a.includes("piece")))
  608. return null;
  609. const data = target.className.split(" ");
  610. let pieceInfo = data[1];
  611. let squareInfo = data[2];
  612. if (pieceInfo.includes("square")) {
  613. const temp = pieceInfo;
  614. pieceInfo = squareInfo;
  615. squareInfo = temp;
  616. }
  617. const square = squareInfo.split("-")[1];
  618. const pieceAbbreviation = pieceInfo[1];
  619. return {
  620. isWhite: pieceInfo.startsWith("b") ? false : true,
  621. type: chessTypes[pieceAbbreviation],
  622. square: Number(square),
  623. element: target
  624. };
  625. };
  626. const squareService = {
  627. clearSquare,
  628. isOutsideOfBoard,
  629. getCurrentLocationPieceInfo,
  630. isLocatedOnEndOfBoard,
  631. getPossibleMoveSquares,
  632. getMetaDataForSquare
  633. };
  634. const moves = [];
  635. const addMoves = (square) => {
  636. if (!square)
  637. return;
  638. const validate = (square2) => {
  639. if (squareService.isOutsideOfBoard(square2.getCurrent()))
  640. return;
  641. moves.push(square2);
  642. };
  643. if (Array.isArray(square)) {
  644. square.forEach(validate);
  645. return;
  646. }
  647. validate(square);
  648. };
  649. const getMoves = () => {
  650. return moves;
  651. };
  652. const clearMoves = () => {
  653. moves.length = 0;
  654. };
  655. const displayMoveService = { addMoves, getMoves, clearMoves };
  656. const getCurrentEnemyPieces = () => {
  657. const enemyPieces = Array.from(document.querySelectorAll(".piece")).filter(
  658. (element) => {
  659. const metaData = squareService.getMetaDataForSquare(element);
  660. return (metaData == null ? void 0 : metaData.isWhite) !== configService.playerIsWhite();
  661. }
  662. );
  663. return enemyPieces;
  664. };
  665. const getCurrentUserPieces = () => {
  666. const userPieces = Array.from(document.querySelectorAll(".piece")).filter(
  667. (element) => {
  668. const metaData = squareService.getMetaDataForSquare(element);
  669. return (metaData == null ? void 0 : metaData.isWhite) === configService.playerIsWhite();
  670. }
  671. );
  672. return userPieces;
  673. };
  674. const getPossibleEnemyMoves = () => {
  675. const enemies = getCurrentEnemyPieces().map(
  676. (element) => squareService.getMetaDataForSquare(element)
  677. );
  678. const possibleEnemyMoves = enemies.reduce(
  679. (accumulator, enemy) => {
  680. const moves2 = chessMoves[enemy.type];
  681. const possibleMoves = squareService.getPossibleMoveSquares(
  682. moves2,
  683. enemy
  684. );
  685. return [
  686. ...accumulator,
  687. ...possibleMoves.filter((s) => s.canAttack())
  688. ];
  689. },
  690. []
  691. );
  692. return possibleEnemyMoves;
  693. };
  694. const getPossibleUserMoves = () => {
  695. const userPieces = getCurrentUserPieces().map(
  696. (element) => squareService.getMetaDataForSquare(element)
  697. );
  698. const possibleUserMoves = userPieces.reduce(
  699. (accumulator, userPiece) => {
  700. const moves2 = chessMoves[userPiece.type];
  701. const possibleMoves = squareService.getPossibleMoveSquares(
  702. moves2,
  703. userPiece
  704. );
  705. return [
  706. ...accumulator,
  707. ...possibleMoves.filter((s) => s.canAttack())
  708. ];
  709. },
  710. []
  711. );
  712. return possibleUserMoves;
  713. };
  714. const pieceService = {
  715. getPossibleEnemyMoves,
  716. getPossibleUserMoves,
  717. getCurrentEnemyPieces,
  718. getCurrentUserPieces
  719. };
  720. const BACKGROUND_COLORS = {
  721. green: "lightgreen",
  722. gray: "lightgray",
  723. red: "red",
  724. orange: "orange"
  725. };
  726. const showPiecesInDanger = ({
  727. board,
  728. currentUserPieces,
  729. possibleEnemyMoves,
  730. allPossibleUserMoves
  731. }) => {
  732. currentUserPieces.forEach((piece) => {
  733. const squareMetaData = squareService.getMetaDataForSquare(piece);
  734. const isPieceInDanger = possibleEnemyMoves.some(
  735. (s) => s.getCurrent() === squareMetaData.square
  736. );
  737. const possibleMovesExludedCurrentPiece = allPossibleUserMoves.filter(
  738. (s) => {
  739. return piece.isEqualNode(s.getMetaData().element) === false;
  740. }
  741. );
  742. const pieceHasBackup = possibleMovesExludedCurrentPiece.some((s) => {
  743. return s.getCurrent() === squareMetaData.square;
  744. });
  745. const element = domService.createElement({
  746. type: "div",
  747. classes: [
  748. "capture-hint",
  749. `square-${squareMetaData.square}`,
  750. "doRemove"
  751. ]
  752. });
  753. if (isPieceInDanger && pieceHasBackup) {
  754. element.style.borderColor = BACKGROUND_COLORS.orange;
  755. } else if (isPieceInDanger) {
  756. element.style.borderColor = BACKGROUND_COLORS.red;
  757. }
  758. if (isPieceInDanger) {
  759. element.style.borderWidth = "8px";
  760. element.style.opacity = "0.5";
  761. board == null ? void 0 : board.appendChild(element);
  762. }
  763. });
  764. };
  765. const showPossibleMoves = ({
  766. board,
  767. activeMoves,
  768. possibleEnemyMoves
  769. }) => {
  770. activeMoves.forEach((square) => {
  771. if (square === null || square === void 0)
  772. return;
  773. if (square.getCurrent() === square.getStartSquareNumber())
  774. return;
  775. if (square.isOnPiece() && !square.isOnEnemyPiece())
  776. return;
  777. const classes = ["hint", `square-${square.getCurrent()}`, "doRemove"];
  778. if (square.isOnEnemyPiece())
  779. classes.push("enemy");
  780. const element = domService.createElement({
  781. type: "div",
  782. classes
  783. });
  784. const isPossibleEnemyMove = possibleEnemyMoves.some(
  785. (s) => s.getCurrent() === square.getCurrent()
  786. );
  787. const isUserPiece = configService.playerIsWhite() && square.getMetaData().isWhite || !configService.playerIsWhite() && !square.getMetaData().isWhite;
  788. const pieceCoveredByAmount = possibleEnemyMoves.filter(
  789. (s) => s.getCurrent() === square.getCurrent()
  790. ).length;
  791. let color = BACKGROUND_COLORS.gray;
  792. if (isUserPiece) {
  793. if (isPossibleEnemyMove && square.isOnEnemyPiece()) {
  794. color = BACKGROUND_COLORS.orange;
  795. } else if (isPossibleEnemyMove) {
  796. color = BACKGROUND_COLORS.orange;
  797. } else if (square.isOnEnemyPiece()) {
  798. color = BACKGROUND_COLORS.green;
  799. }
  800. if (pieceCoveredByAmount > 1) {
  801. element.textContent = pieceCoveredByAmount.toString();
  802. element.style.display = "grid";
  803. element.style.placeItems = "center";
  804. }
  805. }
  806. element.style.backgroundColor = color;
  807. element.style.opacity = "0.5";
  808. board == null ? void 0 : board.appendChild(element);
  809. });
  810. };
  811. const showPossibleFreeCaptures = ({
  812. board,
  813. allPossibleUserMoves,
  814. possibleEnemyMoves
  815. }) => {
  816. allPossibleUserMoves.forEach((square) => {
  817. if (square === null || square === void 0)
  818. return;
  819. if (square.getCurrent() === square.getStartSquareNumber())
  820. return;
  821. if (square.isOnPiece() && !square.isOnEnemyPiece())
  822. return;
  823. if (!square.isOnEnemyPiece())
  824. return;
  825. const isPossibleEnemyMove = possibleEnemyMoves.some(
  826. (s) => s.getCurrent() === square.getCurrent()
  827. );
  828. const isUserPiece = configService.playerIsWhite() && square.getMetaData().isWhite || !configService.playerIsWhite() && !square.getMetaData().isWhite;
  829. const classes = [
  830. "capture-hint",
  831. `square-${square.getCurrent()}`,
  832. "doRemove"
  833. ];
  834. const element = domService.createElement({
  835. type: "div",
  836. classes
  837. });
  838. if (isUserPiece && !isPossibleEnemyMove) {
  839. element.style.borderWidth = "8px";
  840. element.style.borderColor = BACKGROUND_COLORS.green;
  841. element.style.opacity = "0.5";
  842. board == null ? void 0 : board.appendChild(element);
  843. }
  844. });
  845. };
  846. const displayMoves = () => {
  847. const board = domService.getBoard();
  848. const possibleEnemyMoves = pieceService.getPossibleEnemyMoves();
  849. const moves2 = displayMoveService.getMoves();
  850. const activeMoves = moves2.filter((s) => s.isActivePiece());
  851. const currentUserPieces = pieceService.getCurrentUserPieces();
  852. const allPossibleUserMoves = pieceService.getPossibleUserMoves();
  853. showPiecesInDanger({
  854. board,
  855. currentUserPieces,
  856. possibleEnemyMoves,
  857. allPossibleUserMoves
  858. });
  859. showPossibleMoves({ board, activeMoves, possibleEnemyMoves });
  860. showPossibleFreeCaptures({
  861. board,
  862. allPossibleUserMoves,
  863. possibleEnemyMoves
  864. });
  865. };
  866. const displayService = { displayMoves };
  867. let firstRun = true;
  868. const addLeftClickEvent = () => {
  869. const board = domService.getBoard();
  870. if (board === null)
  871. return false;
  872. board.addEventListener("click", () => {
  873. squareService.clearSquare(board);
  874. displayMoveService.clearMoves();
  875. });
  876. return true;
  877. };
  878. const addRightClickEvent = () => {
  879. if (firstRun) {
  880. configService.init();
  881. firstRun = false;
  882. }
  883. const board = domService.getBoard();
  884. if (board === null)
  885. return false;
  886. board.addEventListener("contextmenu", (e) => {
  887. squareService.clearSquare(board);
  888. displayMoveService.clearMoves();
  889. const target = e.target;
  890. const metaData = squareService.getMetaDataForSquare(target);
  891. if (metaData === null)
  892. return;
  893. const moves2 = chessMoves[metaData.type];
  894. const possibleMoves = squareService.getPossibleMoveSquares(
  895. moves2,
  896. metaData
  897. );
  898. displayMoveService.addMoves(possibleMoves);
  899. displayService.displayMoves();
  900. });
  901. return true;
  902. };
  903. const eventService = { addLeftClickEvent, addRightClickEvent };
  904. const main = () => {
  905. try {
  906. const leftClickSuccess = eventService.addLeftClickEvent();
  907. const rightClickSuccess = eventService.addRightClickEvent();
  908. if (!leftClickSuccess || !rightClickSuccess)
  909. return false;
  910. return true;
  911. } catch (error) {
  912. console.error(error);
  913. return false;
  914. }
  915. };
  916. const IS_TM_SCRIPT = document.readyState === "interactive";
  917. const TIMEOUT_BEFORE_START = 2e3;
  918. const init = () => {
  919. let success = true;
  920. try {
  921. success = main();
  922. } catch (error) {
  923. console.error(error);
  924. success = false;
  925. }
  926. if (success) {
  927. console.log("%c Chess helper initialized!", "color: lightgreen");
  928. } else {
  929. console.error("%c Failed to initialize application", "color: lightred");
  930. }
  931. };
  932. const run = () => {
  933. console.log("%c Chess helper starting...", "color: lightblue");
  934. const boardExists = domService.getBoard();
  935. if (boardExists) {
  936. init();
  937. return;
  938. }
  939. console.log("%c Board not found, waiting...", "color: lightblue");
  940. const startup = setInterval(() => {
  941. const correctBoard = domService.getBoard();
  942. if (correctBoard) {
  943. clearInterval(startup);
  944. init();
  945. }
  946. }, TIMEOUT_BEFORE_START);
  947. };
  948. if (IS_TM_SCRIPT) {
  949. window.onload = () => {
  950. setTimeout(run, TIMEOUT_BEFORE_START);
  951. };
  952. } else {
  953. run();
  954. }
  955. })();