Greasy Fork is available in English.

Tweaking

just 4 smth

Dit script moet niet direct worden geïnstalleerd - het is een bibliotheek voor andere scripts om op te nemen met de meta-richtlijn // @require https://update.greasyfork.org/scripts/471295/1222885/Tweaking.js

// ==UserScript==
// @name       chess-helper
// @namespace  chess-helper
// @version    0.0.1
// @author     monkey
// @icon       https://images.chesscomfiles.com/uploads/v1/images_users/tiny_mce/SamCopeland/phpmeXx6V.png
// @match      https://www.chess.com/*
// @run-at     document-end
// ==/UserScript==

(function() {
  "use strict";
  let playerIsWhiteCache = false;
  const playerIsWhite = () => {
    if (playerIsWhiteCache)
      return playerIsWhiteCache;
    const firstCoordinateIsEight = document.querySelector(".coordinates").childNodes[0].textContent === "8";
    playerIsWhiteCache = firstCoordinateIsEight;
    return firstCoordinateIsEight;
  };
  const init$1 = () => {
    playerIsWhite();
  };
  const configService = { playerIsWhite, init: init$1 };
  const createElement = ({
    type,
    classes
  }) => {
    const element = document.createElement(type);
    classes.forEach((c) => element.classList.add(c));
    return element;
  };
  const getBoard = () => {
    const board = document.querySelector("chess-board");
    if (!board)
      return null;
    return board;
  };
  const domService = { createElement, getBoard };
  const chessMoves = {
    pawn: [
      {
        x: 0,
        y: 1,
        condition: ["base"]
      },
      {
        x: 0,
        y: 2,
        condition: ["isFirstMove"]
      },
      {
        y: 1,
        x: 1,
        condition: ["canAttack"]
      },
      {
        y: 1,
        x: -1,
        condition: ["canAttack"]
      }
    ],
    rook: [
      {
        y: "n",
        x: 0
      },
      {
        y: 0,
        x: "n"
      }
    ],
    bishop: [
      {
        y: "n1",
        x: "n1"
      }
    ],
    queen: [
      {
        y: "n1",
        x: "n1"
      },
      {
        y: "n",
        x: 0
      },
      {
        y: 0,
        x: "n"
      }
    ],
    knight: [
      {
        y: 2,
        x: 1,
        condition: ["always"]
      },
      {
        y: 2,
        x: -1,
        condition: ["always"]
      },
      {
        y: -2,
        x: 1,
        condition: ["always"]
      },
      {
        y: -2,
        x: -1,
        condition: ["always"]
      },
      {
        y: 1,
        x: 2,
        condition: ["always"]
      },
      {
        y: 1,
        x: -2,
        condition: ["always"]
      },
      {
        y: -1,
        x: 2,
        condition: ["always"]
      },
      {
        y: -1,
        x: -2,
        condition: ["always"]
      }
    ],
    king: [
      {
        y: 1,
        x: 0,
        condition: ["isSafe"]
      },
      {
        y: 1,
        x: 1,
        condition: ["isSafe"]
      },
      {
        y: 1,
        x: -1,
        condition: ["isSafe"]
      },
      {
        y: -1,
        x: 0,
        condition: ["isSafe"]
      },
      {
        y: -1,
        x: 1,
        condition: ["isSafe"]
      },
      {
        y: -1,
        x: -1,
        condition: ["isSafe"]
      },
      {
        y: 0,
        x: 1,
        condition: ["isSafe"]
      },
      {
        y: 0,
        x: -1,
        condition: ["isSafe"]
      },
      // castling moves
      {
        y: 0,
        x: 2,
        condition: ["isSafe", "isFirstMove", "towerUntouched", "castling"]
      },
      {
        y: 0,
        x: -2,
        condition: ["isSafe", "isFirstMove", "towerUntouched", "castling"]
      }
    ]
  };
  const chessTypes = {
    p: "pawn",
    r: "rook",
    n: "knight",
    b: "bishop",
    q: "queen",
    k: "king"
  };
  const ALTERATION_FIRST = 10;
  const ALTERATION_LAST = 1;
  const Square = (square, metaData, startSquare = null) => {
    startSquare = startSquare ?? Number(square);
    let current = Number(square);
    let isOnPiece = false;
    let id = crypto.randomUUID();
    let isOnEnemyPiece = false;
    let isOnEndOfBoard = false;
    let isOutsideBoard = false;
    let isActivePiece = true;
    let canAttack = true;
    const validate = () => {
      const info = squareService.getCurrentLocationPieceInfo(
        current,
        startSquare
      );
      if (info) {
        isOnPiece = info.isOnPiece;
        isOnEnemyPiece = info.isOnEnemyPiece;
      } else {
        isOnPiece = false;
        isOnEnemyPiece = false;
      }
      if (squareService.isLocatedOnEndOfBoard(current)) {
        isOnEndOfBoard = true;
      }
      if (squareService.isOutsideOfBoard(current)) {
        isOutsideBoard = true;
      }
    };
    validate();
    const getFirst = () => Number(String(current).charAt(0));
    const getLast = () => Number(String(current).charAt(1));
    const moveRight = () => {
      current += ALTERATION_FIRST;
      validate();
      return Square(current, metaData, startSquare);
    };
    const moveLeft = () => {
      current -= ALTERATION_FIRST;
      validate();
      return Square(current, metaData, startSquare);
    };
    const moveUp = () => {
      current += ALTERATION_LAST;
      validate();
      return Square(current, metaData, startSquare);
    };
    const moveDown = () => {
      current -= ALTERATION_LAST;
      validate();
      return Square(current, metaData, startSquare);
    };
    const setActivePiece = (active) => {
      isActivePiece = active;
    };
    const setCanAttack = (attacking) => {
      canAttack = attacking;
    };
    return {
      getStartSquareNumber: () => startSquare,
      getStartSquare: () => Square(startSquare, metaData),
      getFirst,
      getLast,
      getCurrent: () => current,
      getMetaData: () => metaData,
      getId: () => id,
      moveRight,
      moveLeft,
      moveUp,
      moveDown,
      setActivePiece,
      setCanAttack,
      isActivePiece: () => isActivePiece,
      canAttack: () => canAttack,
      isOnPiece: () => isOnPiece,
      isOnEnemyPiece: () => isOnEnemyPiece,
      isOnEndOfBoard: () => isOnEndOfBoard,
      isOutsideBoard: () => isOutsideBoard,
      isOnRow: (row) => getLast() === row,
      getSquare: () => Square(current, metaData, startSquare)
    };
  };
  const handleRepeatedMoveUntilBreak = (square, moves2, callback) => {
    let tempSquare = square.getSquare();
    while (true) {
      tempSquare = callback(tempSquare);
      if ((tempSquare == null ? void 0 : tempSquare.isOutsideBoard()) || tempSquare === null) {
        break;
      }
      if (tempSquare.isOnPiece()) {
        if (tempSquare.isOnEnemyPiece()) {
          moves2.push(tempSquare.getSquare());
        } else {
          tempSquare.setActivePiece(false);
          moves2.push(tempSquare.getSquare());
        }
        break;
      }
      moves2.push(tempSquare.getSquare());
    }
  };
  const handleAxis = (axis, square, moveOnAxis) => {
    const isPositive = moveOnAxis > 0;
    const isNegative = moveOnAxis < 0;
    if (isPositive) {
      for (let i = 0; i < moveOnAxis; i++) {
        if (axis === "y")
          square.moveUp();
        if (axis === "x")
          square.moveRight();
      }
    }
    if (isNegative) {
      for (let i = 0; i > moveOnAxis; i--) {
        if (axis === "y")
          square.moveDown();
        if (axis === "x")
          square.moveLeft();
      }
    }
  };
  const prepareKingMove = (move, metaData) => {
    var _a;
    const x = move.x;
    const y = move.y;
    if (Number.isNaN(x) || Number.isNaN(y)) {
      console.log("Both need to be numbers");
      return null;
    }
    const square = Square(metaData.square, metaData);
    if ((_a = move.condition) == null ? void 0 : _a.includes("castling")) {
      return null;
    }
    handleAxis("x", square, x);
    handleAxis("y", square, y);
    return square;
  };
  const prepareKnightMove = (move, metaData) => {
    const x = move.x;
    const y = move.y;
    if (Number.isNaN(x) || Number.isNaN(y)) {
      console.log("Both need to be numbers");
      return null;
    }
    const square = Square(metaData.square, metaData);
    handleAxis("x", square, x);
    handleAxis("y", square, y);
    return square;
  };
  const prepareN1Moves = (move, metaData) => {
    let moves2 = [];
    if (move.x !== "n1" || move.y !== "n1") {
      console.log("Both need to be n1");
      return moves2;
    }
    const startSquare = Square(metaData.square, metaData);
    handleRepeatedMoveUntilBreak(startSquare, moves2, (square) => {
      square.moveUp();
      return square.moveRight();
    });
    handleRepeatedMoveUntilBreak(startSquare, moves2, (square) => {
      square.moveUp();
      return square.moveLeft();
    });
    handleRepeatedMoveUntilBreak(startSquare, moves2, (square) => {
      square.moveDown();
      return square.moveRight();
    });
    handleRepeatedMoveUntilBreak(startSquare, moves2, (square) => {
      square.moveDown();
      return square.moveLeft();
    });
    return moves2;
  };
  const prepareNMoves = (move, metaData) => {
    let moves2 = [];
    if (move.x === "n" && move.y === "n") {
      console.log("handle special case");
      return moves2;
    }
    if (move.x !== "n" && move.y !== "n") {
      console.log("Cannot have both x and y as n");
      return moves2;
    }
    const handleVertical = move.y === "n";
    const square = Square(metaData.square, metaData);
    if (handleVertical) {
      handleRepeatedMoveUntilBreak(
        square,
        moves2,
        (square2) => square2.moveUp()
      );
      handleRepeatedMoveUntilBreak(
        square,
        moves2,
        (square2) => square2.moveDown()
      );
    } else {
      handleRepeatedMoveUntilBreak(
        square,
        moves2,
        (square2) => square2.moveRight()
      );
      handleRepeatedMoveUntilBreak(
        square,
        moves2,
        (square2) => square2.moveLeft()
      );
    }
    return moves2;
  };
  const preparePawnMove = (move, metaData) => {
    var _a, _b, _c, _d, _e, _f, _g;
    let square = Square(metaData.square, metaData);
    const isWhitePiece = metaData.isWhite;
    const checkIfFirstMove = (square2) => {
      if (isWhitePiece) {
        return square2.getSquare().isOnRow(2);
      } else {
        return square2.getSquare().isOnRow(7);
      }
    };
    const isFirstMove = checkIfFirstMove(square);
    const handleAxis2 = (axis, move2, callbacks) => {
      const value = move2[axis];
      if (value !== 0 && Number.isInteger(value)) {
        let x = value;
        const isPositive = x > 0;
        if (isWhitePiece) {
          for (let i = 0; i < Math.abs(x); i++) {
            if (isPositive) {
              callbacks.whiteAndPositive(square);
            } else {
              callbacks.whiteAndNegative(square);
            }
            if (square.isOnPiece()) {
              break;
            }
          }
        } else {
          for (let i = 0; i < Math.abs(x); i++) {
            if (isPositive) {
              callbacks.blackAndPositive(square);
            } else {
              callbacks.blackAndNegative(square);
            }
            if (square.isOnPiece()) {
              break;
            }
          }
        }
      }
    };
    handleAxis2("y", move, {
      blackAndPositive: (square2) => square2.moveDown(),
      blackAndNegative: (square2) => square2.moveUp(),
      whiteAndPositive: (square2) => square2.moveUp(),
      whiteAndNegative: (square2) => square2.moveDown()
    });
    handleAxis2("x", move, {
      blackAndPositive: (square2) => square2.moveLeft(),
      blackAndNegative: (square2) => square2.moveRight(),
      whiteAndPositive: (square2) => square2.moveRight(),
      whiteAndNegative: (square2) => square2.moveLeft()
    });
    if (((_a = move == null ? void 0 : move.condition) == null ? void 0 : _a.includes("isFirstMove")) && !isFirstMove) {
      return null;
    }
    if (((_b = move == null ? void 0 : move.condition) == null ? void 0 : _b.includes("isFirstMove")) && isFirstMove && square.isOnPiece()) {
      square.setCanAttack(false);
      square.setActivePiece(false);
      return square;
    }
    if (((_c = move == null ? void 0 : move.condition) == null ? void 0 : _c.includes("isFirstMove")) && isFirstMove) {
      square.setCanAttack(false);
      return square;
    }
    if (((_d = move == null ? void 0 : move.condition) == null ? void 0 : _d.includes("canAttack")) && !square.isOnEnemyPiece()) {
      square.setActivePiece(false);
      return square;
    }
    if (((_e = move == null ? void 0 : move.condition) == null ? void 0 : _e.includes("canAttack")) && square.isOnEnemyPiece()) {
      square.setCanAttack(true);
      return square;
    }
    if (!((_f = move == null ? void 0 : move.condition) == null ? void 0 : _f.includes("canAttack")) && square.isOnPiece()) {
      square.setActivePiece(false);
      square.setCanAttack(false);
      return square;
    }
    if ((_g = move == null ? void 0 : move.condition) == null ? void 0 : _g.includes("base")) {
      square.setCanAttack(false);
      return square;
    }
    return square;
  };
  const moveService = {
    preparePawnMove,
    prepareKnightMove,
    prepareKingMove,
    prepareNMoves,
    prepareN1Moves
  };
  const clearSquare = (board) => {
    var _a, _b;
    const toRemove = board.querySelectorAll(".doRemove");
    for (const element of toRemove) {
      (_a = element == null ? void 0 : element.parentNode) == null ? void 0 : _a.removeChild(element);
    }
    const highlightsToRemove = board.querySelectorAll(".highlight");
    for (const element of highlightsToRemove) {
      (_b = element == null ? void 0 : element.classList) == null ? void 0 : _b.remove("highlight");
    }
  };
  const getCurrentLocationPieceInfo = (square, start) => {
    if (square === start)
      return null;
    const isOnPiece = (current2) => {
      var _a;
      return (_a = current2 == null ? void 0 : current2.className) == null ? void 0 : _a.includes("piece");
    };
    const startSquare = Array.from(
      document.querySelectorAll(`.square-${start}`)
    ).find((e) => isOnPiece(e));
    const current = Array.from(
      document.querySelectorAll(`.square-${square}`)
    ).find((e) => isOnPiece(e));
    const metaData = getMetaDataForSquare(startSquare);
    const isBlackPiecePlaying = !metaData.isWhite;
    const isStandingOnWhitePiece = (current2) => {
      const metaData2 = getMetaDataForSquare(current2);
      return (metaData2 == null ? void 0 : metaData2.isWhite) ?? false;
    };
    const isOnEnemy = isBlackPiecePlaying && isStandingOnWhitePiece(current) || !isBlackPiecePlaying && !isStandingOnWhitePiece(current);
    return {
      isOnPiece: isOnPiece(current),
      isOnEnemyPiece: isOnPiece(current) ? isOnEnemy : false
    };
  };
  const isLocatedOnEndOfBoard = (square) => {
    const first = Number(String(square).charAt(0));
    const last = Number(String(square).charAt(1));
    if (first === 8 || first === 1)
      return true;
    if (last === 8 || last === 1)
      return true;
    return false;
  };
  const isOutsideOfBoard = (square) => {
    const first = Number(String(square).charAt(0));
    const last = Number(String(square).charAt(1));
    if (!first || !last)
      return true;
    if (first > 8 || first < 1)
      return true;
    if (last > 8 || last < 1)
      return true;
    return false;
  };
  const getPossibleMoveSquares = (moves2, metaData) => {
    let totalMoves = [];
    for (const move of moves2) {
      let tempMoves = [];
      switch (metaData.type) {
        case "pawn":
          const pawnMove = moveService.preparePawnMove(move, metaData);
          if (pawnMove)
            tempMoves = [pawnMove];
          break;
        case "rook":
          tempMoves = moveService.prepareNMoves(move, metaData);
          break;
        case "bishop":
          tempMoves = moveService.prepareN1Moves(move, metaData);
          break;
        case "queen":
          const isNMove = move.x === "n" || move.y === "n";
          if (isNMove) {
            tempMoves = moveService.prepareNMoves(move, metaData);
          } else {
            tempMoves = moveService.prepareN1Moves(move, metaData);
          }
          break;
        case "knight":
          const knightMove = moveService.prepareKnightMove(
            move,
            metaData
          );
          if (knightMove)
            tempMoves = [knightMove];
          break;
        case "king":
          const kingMove = moveService.prepareKingMove(move, metaData);
          if (kingMove)
            tempMoves = [kingMove];
          break;
        default:
          console.log("Not implemented yet");
      }
      totalMoves = [...totalMoves, ...tempMoves];
    }
    return totalMoves;
  };
  const getMetaDataForSquare = (target) => {
    var _a;
    if (target instanceof SVGElement)
      return null;
    if (!((_a = target == null ? void 0 : target.className) == null ? void 0 : _a.includes("piece")))
      return null;
    const data = target.className.split(" ");
    let pieceInfo = data[1];
    let squareInfo = data[2];
    if (pieceInfo.includes("square")) {
      const temp = pieceInfo;
      pieceInfo = squareInfo;
      squareInfo = temp;
    }
    const square = squareInfo.split("-")[1];
    const pieceAbbreviation = pieceInfo[1];
    return {
      isWhite: pieceInfo.startsWith("b") ? false : true,
      type: chessTypes[pieceAbbreviation],
      square: Number(square),
      element: target
    };
  };
  const squareService = {
    clearSquare,
    isOutsideOfBoard,
    getCurrentLocationPieceInfo,
    isLocatedOnEndOfBoard,
    getPossibleMoveSquares,
    getMetaDataForSquare
  };
  const moves = [];
  const addMoves = (square) => {
    if (!square)
      return;
    const validate = (square2) => {
      if (squareService.isOutsideOfBoard(square2.getCurrent()))
        return;
      moves.push(square2);
    };
    if (Array.isArray(square)) {
      square.forEach(validate);
      return;
    }
    validate(square);
  };
  const getMoves = () => {
    return moves;
  };
  const clearMoves = () => {
    moves.length = 0;
  };
  const displayMoveService = { addMoves, getMoves, clearMoves };
  const getCurrentEnemyPieces = () => {
    const enemyPieces = Array.from(document.querySelectorAll(".piece")).filter(
      (element) => {
        const metaData = squareService.getMetaDataForSquare(element);
        return (metaData == null ? void 0 : metaData.isWhite) !== configService.playerIsWhite();
      }
    );
    return enemyPieces;
  };
  const getCurrentUserPieces = () => {
    const userPieces = Array.from(document.querySelectorAll(".piece")).filter(
      (element) => {
        const metaData = squareService.getMetaDataForSquare(element);
        return (metaData == null ? void 0 : metaData.isWhite) === configService.playerIsWhite();
      }
    );
    return userPieces;
  };
  const getPossibleEnemyMoves = () => {
    const enemies = getCurrentEnemyPieces().map(
      (element) => squareService.getMetaDataForSquare(element)
    );
    const possibleEnemyMoves = enemies.reduce(
      (accumulator, enemy) => {
        const moves2 = chessMoves[enemy.type];
        const possibleMoves = squareService.getPossibleMoveSquares(
          moves2,
          enemy
        );
        return [
          ...accumulator,
          ...possibleMoves.filter((s) => s.canAttack())
        ];
      },
      []
    );
    return possibleEnemyMoves;
  };
  const getPossibleUserMoves = () => {
    const userPieces = getCurrentUserPieces().map(
      (element) => squareService.getMetaDataForSquare(element)
    );
    const possibleUserMoves = userPieces.reduce(
      (accumulator, userPiece) => {
        const moves2 = chessMoves[userPiece.type];
        const possibleMoves = squareService.getPossibleMoveSquares(
          moves2,
          userPiece
        );
        return [
          ...accumulator,
          ...possibleMoves.filter((s) => s.canAttack())
        ];
      },
      []
    );
    return possibleUserMoves;
  };
  const pieceService = {
    getPossibleEnemyMoves,
    getPossibleUserMoves,
    getCurrentEnemyPieces,
    getCurrentUserPieces
  };
  const BACKGROUND_COLORS = {
    green: "lightgreen",
    gray: "lightgray",
    red: "red",
    orange: "orange"
  };
  const showPiecesInDanger = ({
    board,
    currentUserPieces,
    possibleEnemyMoves,
    allPossibleUserMoves
  }) => {
    currentUserPieces.forEach((piece) => {
      const squareMetaData = squareService.getMetaDataForSquare(piece);
      const isPieceInDanger = possibleEnemyMoves.some(
        (s) => s.getCurrent() === squareMetaData.square
      );
      const possibleMovesExludedCurrentPiece = allPossibleUserMoves.filter(
        (s) => {
          return piece.isEqualNode(s.getMetaData().element) === false;
        }
      );
      const pieceHasBackup = possibleMovesExludedCurrentPiece.some((s) => {
        return s.getCurrent() === squareMetaData.square;
      });
      const element = domService.createElement({
        type: "div",
        classes: [
          "capture-hint",
          `square-${squareMetaData.square}`,
          "doRemove"
        ]
      });
      if (isPieceInDanger && pieceHasBackup) {
        element.style.borderColor = BACKGROUND_COLORS.orange;
      } else if (isPieceInDanger) {
        element.style.borderColor = BACKGROUND_COLORS.red;
      }
      if (isPieceInDanger) {
        element.style.borderWidth = "8px";
        element.style.opacity = "0.5";
        board == null ? void 0 : board.appendChild(element);
      }
    });
  };
  const showPossibleMoves = ({
    board,
    activeMoves,
    possibleEnemyMoves
  }) => {
    activeMoves.forEach((square) => {
      if (square === null || square === void 0)
        return;
      if (square.getCurrent() === square.getStartSquareNumber())
        return;
      if (square.isOnPiece() && !square.isOnEnemyPiece())
        return;
      const classes = ["hint", `square-${square.getCurrent()}`, "doRemove"];
      if (square.isOnEnemyPiece())
        classes.push("enemy");
      const element = domService.createElement({
        type: "div",
        classes
      });
      const isPossibleEnemyMove = possibleEnemyMoves.some(
        (s) => s.getCurrent() === square.getCurrent()
      );
      const isUserPiece = configService.playerIsWhite() && square.getMetaData().isWhite || !configService.playerIsWhite() && !square.getMetaData().isWhite;
      const pieceCoveredByAmount = possibleEnemyMoves.filter(
        (s) => s.getCurrent() === square.getCurrent()
      ).length;
      let color = BACKGROUND_COLORS.gray;
      if (isUserPiece) {
        if (isPossibleEnemyMove && square.isOnEnemyPiece()) {
          color = BACKGROUND_COLORS.orange;
        } else if (isPossibleEnemyMove) {
          color = BACKGROUND_COLORS.orange;
        } else if (square.isOnEnemyPiece()) {
          color = BACKGROUND_COLORS.green;
        }
        if (pieceCoveredByAmount > 1) {
          element.textContent = pieceCoveredByAmount.toString();
          element.style.display = "grid";
          element.style.placeItems = "center";
        }
      }
      element.style.backgroundColor = color;
      element.style.opacity = "0.5";
      board == null ? void 0 : board.appendChild(element);
    });
  };
  const showPossibleFreeCaptures = ({
    board,
    allPossibleUserMoves,
    possibleEnemyMoves
  }) => {
    allPossibleUserMoves.forEach((square) => {
      if (square === null || square === void 0)
        return;
      if (square.getCurrent() === square.getStartSquareNumber())
        return;
      if (square.isOnPiece() && !square.isOnEnemyPiece())
        return;
      if (!square.isOnEnemyPiece())
        return;
      const isPossibleEnemyMove = possibleEnemyMoves.some(
        (s) => s.getCurrent() === square.getCurrent()
      );
      const isUserPiece = configService.playerIsWhite() && square.getMetaData().isWhite || !configService.playerIsWhite() && !square.getMetaData().isWhite;
      const classes = [
        "capture-hint",
        `square-${square.getCurrent()}`,
        "doRemove"
      ];
      const element = domService.createElement({
        type: "div",
        classes
      });
      if (isUserPiece && !isPossibleEnemyMove) {
        element.style.borderWidth = "8px";
        element.style.borderColor = BACKGROUND_COLORS.green;
        element.style.opacity = "0.5";
        board == null ? void 0 : board.appendChild(element);
      }
    });
  };
  const displayMoves = () => {
    const board = domService.getBoard();
    const possibleEnemyMoves = pieceService.getPossibleEnemyMoves();
    const moves2 = displayMoveService.getMoves();
    const activeMoves = moves2.filter((s) => s.isActivePiece());
    const currentUserPieces = pieceService.getCurrentUserPieces();
    const allPossibleUserMoves = pieceService.getPossibleUserMoves();
    showPiecesInDanger({
      board,
      currentUserPieces,
      possibleEnemyMoves,
      allPossibleUserMoves
    });
    showPossibleMoves({ board, activeMoves, possibleEnemyMoves });
    showPossibleFreeCaptures({
      board,
      allPossibleUserMoves,
      possibleEnemyMoves
    });
  };
  const displayService = { displayMoves };
  let firstRun = true;
  const addLeftClickEvent = () => {
    const board = domService.getBoard();
    if (board === null)
      return false;
    board.addEventListener("click", () => {
      squareService.clearSquare(board);
      displayMoveService.clearMoves();
    });
    return true;
  };
  const addRightClickEvent = () => {
    if (firstRun) {
      configService.init();
      firstRun = false;
    }
    const board = domService.getBoard();
    if (board === null)
      return false;
    board.addEventListener("contextmenu", (e) => {
      squareService.clearSquare(board);
      displayMoveService.clearMoves();
      const target = e.target;
      const metaData = squareService.getMetaDataForSquare(target);
      if (metaData === null)
        return;
      const moves2 = chessMoves[metaData.type];
      const possibleMoves = squareService.getPossibleMoveSquares(
        moves2,
        metaData
      );
      displayMoveService.addMoves(possibleMoves);
      displayService.displayMoves();
    });
    return true;
  };
  const eventService = { addLeftClickEvent, addRightClickEvent };
  const main = () => {
    try {
      const leftClickSuccess = eventService.addLeftClickEvent();
      const rightClickSuccess = eventService.addRightClickEvent();
      if (!leftClickSuccess || !rightClickSuccess)
        return false;
      return true;
    } catch (error) {
      console.error(error);
      return false;
    }
  };
  const IS_TM_SCRIPT = document.readyState === "interactive";
  const TIMEOUT_BEFORE_START = 2e3;
  const init = () => {
    let success = true;
    try {
      success = main();
    } catch (error) {
      console.error(error);
      success = false;
    }
    if (success) {
      console.log("%c Chess helper initialized!", "color: lightgreen");
    } else {
      console.error("%c Failed to initialize application", "color: lightred");
    }
  };
  const run = () => {
    console.log("%c Chess helper starting...", "color: lightblue");
    const boardExists = domService.getBoard();
    if (boardExists) {
      init();
      return;
    }
    console.log("%c Board not found, waiting...", "color: lightblue");
    const startup = setInterval(() => {
      const correctBoard = domService.getBoard();
      if (correctBoard) {
        clearInterval(startup);
        init();
      }
    }, TIMEOUT_BEFORE_START);
  };
  if (IS_TM_SCRIPT) {
    window.onload = () => {
      setTimeout(run, TIMEOUT_BEFORE_START);
    };
  } else {
    run();
  }
})();