// ==UserScript== // @name Connect 4 Board Evaluation for papergames // @namespace https://github.com/longkidkoolstar // @version 0.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("#connect4 > table"); const rows = boardContainer.querySelectorAll("tr"); let boardState = []; rows.forEach(row => { let rowState = []; row.querySelectorAll("td").forEach(cell => { if (cell.querySelector("circle.circle-dark")) { rowState.push("R"); } else if (cell.querySelector("circle.circle-light")) { rowState.push("Y"); } else { 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("#connect4 > table"); 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) { console.log(`Attempting to click on column ${column}`); const boardContainer = document.querySelector("#connect4 > table"); const rows = boardContainer.querySelectorAll("tr"); for (let i = rows.length - 2; i >= 0; i--) { // Start from the second last row (index 4) to avoid the evaluation row const cell = rows[i].querySelectorAll("td")[column]; if (cell && !cell.querySelector("circle.circle-dark") && !cell.querySelector("circle.circle-light")) { console.log(`Found empty cell at row ${i}, column ${column}`); // Reduced delay from 1000ms to 100ms console.log(`Dispatching click event on row ${i}, column ${column}`); var event = new MouseEvent('click', { bubbles: true, cancelable: true, }); cell.dispatchEvent(event); console.log(`Click event dispatched on row ${i}, column ${column}`); return; } } console.log(`No empty cell found in column ${column}`); } 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() { $('