- // ==UserScript==
- // @name Chess.com Piece Numbers
- // @namespace https://theusaf.org
- // @version 0.0.5
- // @description Adds piece number data to pieces in the chess board
- // @author theusaf
- // @match https://www.chess.com/**
- // @icon https://www.google.com/s2/favicons?domain=chess.com
- // @grant none
- // @license MIT
- // ==/UserScript==
-
- let tries = 0;
-
- function init() {
- const board = document.querySelector("chess-board"),
- pieces = {
- black: {
- p: 2 // to fix promotion stuff
- },
- white: {
- p: 2
- }
- };
-
- if (board) {
- const observer = new MutationObserver((mutations, observer) => {
- const attributeMutations = new Set();
- for (const mutation of mutations) {
- if (mutation.type === "childList") {
- const {addedNodes, removedNodes} = mutation;
- for (const node of addedNodes) {
- if (node.nodeName !== "DIV") {continue;}
- if (Array.from(node.classList)?.includes("piece")) {
- addPiece(node);
- }
- }
- for (const node of removedNodes) {
- if (node.nodeName !== "DIV") {continue;}
- if (Array.from(node.classList)?.includes("piece")) {
- removePiece(node);
- }
- }
- } else {
- const filter = (mutation) => {
- return (/piece/.test(mutation.oldValue) ||
- /piece/.test(mutation.target.className)) &&
- (!/dragging/.test(mutation.target.className) &&
- !/dragging/.test(mutation.oldValue) &&
- mutation.oldValue !== null);
- };
- if (filter(mutation)) {
- attributeMutations.add(mutation);
- }
- }
- }
- const out = [],
- moveSquaresProcessed = new Set(),
- toSwap = new Set();
- for (const mutation of attributeMutations) {
- out.push(mutation);
- const piecePosition = getPieceSquare(mutation.target.className),
- [pieceTeam, pieceType] = getPieceType(mutation.target.className),
- [originalPieceTeam, originalPieceType] = getPieceType(mutation.oldValue);
- if (piecePosition in moveSquaresProcessed) {continue;}
- moveSquaresProcessed.add(piecePosition);
- let shouldContinue = false;
- // console.log(piecePosition, pieceTeam, pieceType, originalPieceTeam, originalPieceType)
- for (const swap of toSwap) {
- const {team, type, swapWith} = swap;
- if (pieceTeam === team && pieceType === type) {
- console.log("swapping");
- swapPieces(mutation.target, swapWith);
- toSwap.delete(swap);
- shouldContinue = true;
- break;
- }
- }
- if (shouldContinue) {continue;}
- if (pieceTeam === originalPieceTeam && pieceType === originalPieceType) {
- // no change required
- } else {
- // uh oh, need to swap!
- toSwap.add({
- team: originalPieceTeam,
- type: originalPieceType,
- swapWith: mutation.target
- });
- }
- }
- if (out.length) {
- /*console.log(out.map(mutation => {
- return [`${mutation.oldValue} --> ${mutation.target.className}`, mutation.target];
- }));*/
- // Check for any abnormalities and fix issues
- moveSquaresProcessed.clear();
- for (const mutation of attributeMutations) {
- const piecePosition = getPieceSquare(mutation.target.className),
- currentPiece = getPieceType(mutation.target.className).join(""),
- originalPiece = mutation.target.getAttribute("original-piece");
- if (piecePosition in moveSquaresProcessed) {continue;}
- moveSquaresProcessed.add(piecePosition);
- if (!currentPiece || !piecePosition) {continue;}
- if (currentPiece !== originalPiece) {
- const pieces = [...document.querySelectorAll(`[original-piece=${currentPiece}]`)];
- for (const piece of pieces) {
- const pieceOrignalPiece = piece.getAttribute("original-piece"),
- pieceCurrentPiece = getPieceType(piece.className).join("");
- if (pieceOrignalPiece !== pieceCurrentPiece) {
- console.log("Swapping #2", mutation.target, piece);
- swapPieces(piece, mutation.target);
- // swap original pieces also
- mutation.target.setAttribute("original-piece", pieceOrignalPiece);
- piece.setAttribute("original-piece", originalPiece);
- break;
- }
- }
- }
- }
- }
- });
- observer.observe(board, {
- childList: true,
- subtree: true,
- attributeFilter: ["class"],
- attributeOldValue: true
- });
- const existingPieces = document.querySelectorAll("chess-board .piece");
- for (const piece of existingPieces) {
- addPiece(piece);
- }
- } else {
- if (++tries > 10) {return;}
- setTimeout(init, 500);
- }
-
- function swapPieces(a, b) {
- const myNumber = a.getAttribute("piece-number"),
- myOriginalPiece = a.getAttribute("original-piece");
- a.setAttribute("piece-number", b.getAttribute("piece-number"));
- a.setAttribute("original-piece", b.getAttribute("original-piece"));
- b.setAttribute("piece-number", myNumber);
- b.setAttribute("original-piece", myOriginalPiece);
- }
- function getPieceSquare(name) {
- const piece = name.split(" ").find(word => /^square/.test(word));
- return piece?.split("-")[1];
- }
- function getPieceType(name) {
- const piece = name.split(" ").find(word => word.length === 2 && /^[wb]/.test(word));
- return piece?.split("") || [];
- }
- function addPiece(piece) {
- const colorPieces = piece.classList[1][0] === "w" ? pieces.white : pieces.black,
- actualPiece = piece.classList[1][1];
- if (typeof colorPieces[actualPiece] !== "number") {colorPieces[actualPiece] = 0;}
- colorPieces[actualPiece]++;
- piece.setAttribute("piece-number", colorPieces[actualPiece]);
- piece.setAttribute("original-piece", getPieceType(piece.className).join(""));
- }
- function removePiece(piece) {
- const colorPieces = piece.classList[1][0] === "w" ? pieces.white : pieces.black,
- actualPiece = piece.classList[1][1];
- if (typeof colorPieces[actualPiece] !== "number") {colorPieces[actualPiece] = 0;}
- colorPieces[actualPiece]--;
- }
- }
-
- init();