Tweaking

just 4 smth

このスクリプトは単体で利用できません。右のようなメタデータを含むスクリプトから、ライブラリとして読み込まれます: // @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();
  }
})();