// Script to automate Coin Craze game // To use: Copy and paste into browser console at https://testnet.succinct.xyz/coin
function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
async function solveCoinCraze() { // Function to simulate mouse events function simulateMouseEvent(element, x, y, type) { const rect = element.getBoundingClientRect(); const event = new MouseEvent(type, { bubbles: true, cancelable: true, view: window, clientX: rect.left + x, clientY: rect.top + y, screenX: rect.left + x, screenY: rect.top + y, buttons: type === 'mouseup' ? 0 : 1, button: 0, relatedTarget: null, }); element.dispatchEvent(event); }
// Function to get coin value function getCoinValue(coin) { return parseInt(coin.textContent); }
// Function to check if coins are in a straight line function areInStraightLine(coins, indices) { if (indices.length < 2) return true; const rects = indices.map(i => coins[i].getBoundingClientRect()); const centers = rects.map(rect => ({ x: rect.left + rect.width/2, y: rect.top + rect.height/2 }));
// Check if all coins are horizontally aligned (same y) const isHorizontal = centers.every(c => Math.abs(c.y - centers[0].y) < 15); if (isHorizontal) { // Sort by x coordinate const sortedIndices = [...indices].sort((a, b) => { const rectA = coins[a].getBoundingClientRect(); const rectB = coins[b].getBoundingClientRect(); return (rectA.left + rectA.width/2) - (rectB.left + rectB.width/2); }); // Check if coins are consecutive for (let i = 1; i < sortedIndices.length; i++) { const rect1 = coins[sortedIndices[i-1]].getBoundingClientRect(); const rect2 = coins[sortedIndices[i]].getBoundingClientRect(); const distance = (rect2.left + rect2.width/2) - (rect1.left + rect1.width/2); if (distance > rect1.width * 2) return false; } return true; }
// Check if all coins are vertically aligned (same x) const isVertical = centers.every(c => Math.abs(c.x - centers[0].x) < 15); if (isVertical) { // Sort by y coordinate const sortedIndices = [...indices].sort((a, b) => { const rectA = coins[a].getBoundingClientRect(); const rectB = coins[b].getBoundingClientRect(); return (rectA.top + rectA.height/2) - (rectB.top + rectB.height/2); }); // Check if coins are consecutive for (let i = 1; i < sortedIndices.length; i++) { const rect1 = coins[sortedIndices[i-1]].getBoundingClientRect(); const rect2 = coins[sortedIndices[i]].getBoundingClientRect(); const distance = (rect2.top + rect2.height/2) - (rect1.top + rect1.height/2); if (distance > rect1.height * 2) return false; } return true; }
return false; }
// Function to find sequence of adjacent coins that sum to 10 function findCoinCombination(coins) { const startTime = Date.now(); // Try all possible combinations for (let i = 0; i < coins.length; i++) { const value1 = getCoinValue(coins[i]); if (value1 > 10) continue;
// Get nearby coins for efficiency const rect1 = coins[i].getBoundingClientRect(); const nearby = []; for (let j = 0; j < coins.length; j++) { if (i === j) continue; const rect2 = coins[j].getBoundingClientRect(); const dx = (rect2.left + rect2.width/2) - (rect1.left + rect1.width/2); const dy = (rect2.top + rect2.height/2) - (rect1.top + rect1.height/2); const distance = Math.sqrt(dx * dx + dy * dy); if (distance < rect1.width * 2.5) { nearby.push(j); } }
// Try two-coin combinations with nearby coins for (const j of nearby) { const value2 = getCoinValue(coins[j]); const sequence = [i, j]; if (value1 + value2 === 10 && areInStraightLine(coins, sequence)) { return sequence; }
// Try three-coin combinations with another nearby coin if (value1 + value2 < 10) { for (const k of nearby) { if (k === i || k === j) continue; const value3 = getCoinValue(coins[k]); if (value1 + value2 + value3 === 10) { const sequence3 = [i, j, k]; if (areInStraightLine(coins, sequence3)) { return sequence3; } } } } }
// Check if we're taking too long if (Date.now() - startTime > 50) { return null; } } return null; }
// Function to handle game over sequence async function handleGameOver() { // Check for "Game Over!" text const gameOverText = document.evaluate( '/html/body/div[1]/main/div[1]/div/div/div[2]/div/div/div[2]/div/div/h2', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue;
if (gameOverText && gameOverText.textContent.includes('Game Over!')) { console.log('Game Over detected, handling end sequence...'); // Click "Confirm Score" const confirmScoreBtn = document.evaluate( '/html/body/div[1]/main/div[1]/div/div/div[2]/div/div/div[2]/div/div/div[2]/button[1]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; if (confirmScoreBtn) { confirmScoreBtn.click(); await sleep(1000); // Wait for confirmation dialog // Click "Confirm" const confirmBtn = document.evaluate( '/html/body/div[1]/main/div[1]/div/div/div[2]/div/div/div[3]/div/div/button[2]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; if (confirmBtn) { confirmBtn.click(); await sleep(1000); // Wait for play again button // Click "Play Again!" const playAgainBtn = document.evaluate( '/html/body/div[1]/main/div[1]/div/div/div[2]/div/div/div[2]/div/div/div[2]/button[1]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; if (playAgainBtn) { playAgainBtn.click(); await sleep(1000); // Wait for new game to start return true; } } } } return false; }
while (true) { try { // Check for game over first if (await handleGameOver()) { console.log('Starting new game...'); continue; }
// Get all coins using the specific selector const gameBoard = document.querySelector('body > div.fixed.inset-0.flex.flex-col.overflow-hidden.bg-cover.bg-center > main'); if (!gameBoard) { await sleep(100); continue; }
// Try different selectors for the coin container let container = gameBoard.querySelector('.game-board'); if (!container) { container = gameBoard.querySelector('[class*="aspect-square"]'); } if (!container) { container = gameBoard.querySelector('div[class*="relative"] > div > div'); } if (!container) { await sleep(100); continue; } // Get all button elements within the container const coins = Array.from(container.querySelectorAll('button')); if (coins.length === 0) { await sleep(100); continue; }
// Remove pointer-events-none class from parent elements let parent = container; while (parent) { if (parent.classList && parent.classList.contains('pointer-events-none')) { parent.classList.remove('pointer-events-none'); } parent = parent.parentElement; }
// Find combination that sums to 10 const combination = findCoinCombination(coins); if (!combination) { await sleep(100); continue; }
// Log the selected coins and their sum const values = combination.map(i => getCoinValue(coins[i])); const sum = values.reduce((a, b) => a + b, 0); console.log(`Selected ${values.length} coins:`, values.join(' + '), '=', sum);
// Select the coins const firstCoin = coins[combination[0]]; simulateMouseEvent(firstCoin, 20, 20, 'mousedown'); // Only move to the last coin directly const lastCoin = coins[combination[combination.length - 1]]; simulateMouseEvent(lastCoin, 20, 20, 'mousemove'); simulateMouseEvent(lastCoin, 20, 20, 'mouseup');
// Give the game a short break await sleep(100); } catch (error) { console.error('Error:', error); await sleep(100); } // Add a small break between iterations to prevent freezing await new Promise(resolve => setTimeout(resolve, 0)); } }
// Start the solver solveCoinCraze();
|