// ==UserScript== // @name Connect 4 Board Evaluation for papergames // @namespace https://github.com/longkidkoolstar // @version 0.2.2 // @description Visually shows you the best moves for both teams. Now works at the same time as the AI script I made. // @author longkidkoolstar // @license none // @match https://papergames.io/* // @icon https://i.imgur.com/IQi878N.png // @require https://code.jquery.com/jquery-3.6.0.min.js // @grant GM.xmlHttpRequest // @downloadURL none // ==/UserScript== (function() { 'use strict'; var username = localStorage.getItem('username'); var moveHistory = []; var lastBoardState = []; if (!username) { username = prompt('Please enter your Papergames username (case-sensitive):'); localStorage.setItem('username', username); } function getBoardState() { const boardContainer = document.querySelector(".grid.size6x7"); if (!boardContainer) { console.error("Board container not found"); return []; } let boardState = []; for (let row = 1; row <= 6; row++) { let rowState = []; for (let col = 1; col <= 7; col++) { const cellSelector = `.cell-${row}-${col}`; const cell = boardContainer.querySelector(cellSelector); if (cell) { if (cell.querySelector("circle.circle-dark")) { rowState.push("R"); } else if (cell.querySelector("circle.circle-light")) { rowState.push("Y"); } else { rowState.push("E"); } } else { console.error(`Cell not found: ${cellSelector}`); rowState.push("E"); } } boardState.push(rowState); } return boardState; } function detectNewMove() { const currentBoardState = getBoardState(); let newMove = false; for (let row = 0; row < 6; row++) { for (let col = 0; col < 7; col++) { if (lastBoardState[row] && lastBoardState[row][col] === 'E' && currentBoardState[row][col] !== 'E') { moveHistory.push(col + 1); newMove = true; } } } lastBoardState = currentBoardState; return newMove; } function getAPIEvaluation() { if (!detectNewMove()) return; let pos = moveHistory.join(""); const apiUrl = `https://connect4.gamesolver.org/solve?pos=${pos}`; GM.xmlHttpRequest({ method: "GET", url: apiUrl, onload: function(response) { const data = JSON.parse(response.responseText); displayEvaluations(data.score); }, onerror: function(error) { console.error("API request failed:", error); } }); } function displayEvaluations(scores) { const boardContainer = document.querySelector(".grid.size6x7"); let evalContainer = document.querySelector("#evaluation-container"); if (!evalContainer) { evalContainer = document.createElement("div"); evalContainer.id = "evaluation-container"; evalContainer.style.display = "flex"; evalContainer.style.justifyContent = "space-around"; evalContainer.style.marginTop = "10px"; boardContainer.parentNode.insertBefore(evalContainer, boardContainer.nextSibling); } // Clear existing evaluation cells evalContainer.innerHTML = ''; scores.forEach((score, index) => { const evalCell = document.createElement("div"); evalCell.textContent = score; evalCell.style.textAlign = 'center'; evalCell.style.fontWeight = 'bold'; evalCell.style.color = score > 0 ? 'green' : (score < 0 ? 'red' : 'black'); evalCell.style.cursor = 'pointer'; evalCell.style.flexGrow = '1'; evalCell.style.padding = '5px'; evalCell.onclick = function() { simulateCellClick(index); }; evalContainer.appendChild(evalCell); }); } function simulateCellClick(column, offset = 1) { console.log(`Attempting to click on column ${column} with an offset of ${offset}`); const boardContainer = document.querySelector(".grid.size6x7"); if (!boardContainer) { console.error("Board container not found"); return; } // Adjust column index with offset const adjustedColumn = column + offset; // Ensure the adjusted column is within valid bounds if (adjustedColumn < 1 || adjustedColumn > 7) { console.error(`Adjusted column index ${adjustedColumn} is out of bounds`); return; } // Iterate from row 6 to row 1 (1-based index) for (let row = 6; row >= 1; row--) { const cellSelector = `.cell-${row}-${adjustedColumn}`; const cell = boardContainer.querySelector(cellSelector); // Debugging output console.log(`Checking selector: ${cellSelector}`); if (cell) { console.log(`Found cell at row ${row}, column ${adjustedColumn}`); if (cell.classList.contains('selectable')) { console.log(`Cell at row ${row}, column ${adjustedColumn} is selectable`); var event = new MouseEvent('click', { bubbles: true, cancelable: true, }); cell.dispatchEvent(event); console.log(`Click event dispatched on row ${row}, column ${adjustedColumn}`); return; } else { console.log(`Cell at row ${row}, column ${adjustedColumn} is not selectable`); } } else { console.log(`No cell found at selector: ${cellSelector}`); } } console.log(`No selectable cell found in column ${adjustedColumn}`); } function resetVariables() { moveHistory = []; lastBoardState = []; console.log("Variables reset to default states"); } function checkForResetButtons() { var playOnlineButton = document.querySelector("button.btn-secondary.flex-grow-1"); var leaveRoomButton = document.querySelector("button.btn-light.ng-tns-c189-7"); if (playOnlineButton || leaveRoomButton) { resetVariables(); } } //Checking If the game is over so it can reset variables setInterval(function() { checkForResetButtons(); }, 500); setInterval(getAPIEvaluation, 10); console.log("Modified Connect 4 script loaded and running"); //---GUI // Check if username is stored in local storage var username = localStorage.getItem('username'); if (!username) { alert('Username is not stored in local storage.'); username = prompt('Please enter your Papergames username (case-sensitive):'); localStorage.setItem('username', username); } function logout() { localStorage.removeItem('username'); location.reload(); } function createLogoutButton() { $('