(async () => { // Helper for random delays const randomDelay = async (min, max) => { return new Promise(resolve => setTimeout(resolve, Math.floor(Math.random() * (max - min + 1) + min))); };
// Get grid state const getGrid = () => { try { const container = document.querySelector('#game-container > div > div.jsx-2883dceedf364fd2.absolute.left-0.top-0.h-full.w-full'); if (!container) { console.log('Container not found'); return null; }
const grid = Array(16).fill(0); const tiles = Array.from(container.children).filter(tile => tile.textContent && !tile.classList.contains('tile-new') );
tiles.forEach(tile => { const value = parseInt(tile.textContent); const style = window.getComputedStyle(tile); const topPercent = parseFloat(style.top.replace('px', '')); const leftPercent = parseFloat(style.left.replace('px', '')); const containerStyle = window.getComputedStyle(container); const containerHeight = parseFloat(containerStyle.height.replace('px', '')); const containerWidth = parseFloat(containerStyle.width.replace('px', '')); const row = Math.round((topPercent / containerHeight) * 4); const col = Math.round((leftPercent / containerWidth) * 4); if (row >= 0 && row < 4 && col >= 0 && col < 4) { const index = row * 4 + col; grid[index] = value; } });
// Debug print grid let gridStr = ''; for (let i = 0; i < 4; i++) { const row = grid.slice(i * 4, (i + 1) * 4).map(v => v.toString().padStart(4, ' ')); gridStr += row.join(' | ') + '\n'; if (i < 3) gridStr += '-'.repeat(29) + '\n'; } console.log(gridStr);
return grid; } catch (error) { console.error('Error reading grid:', error); return null; } };
// Get current score const getScore = () => { try { const scoreElement = document.querySelector('body > div.fixed.inset-0.flex.flex-col.overflow-hidden.bg-cover.bg-center > main > div.pointer-events-none.absolute.inset-0.flex.px-4.py-1 > div > div > div.relative.flex.w-full.flex-1.flex-col.items-start.justify-center > div > div > div > div.jsx-2883dceedf364fd2.mb-4.flex.items-center.justify-between > div.jsx-2883dceedf364fd2.flex.space-x-2 > div:nth-child(1) > div.jsx-2883dceedf364fd2.text-xl.font-bold.text-succinct-pink'); return scoreElement ? parseInt(scoreElement.textContent) : 0; } catch (error) { console.error('Error reading score:', error); return 0; } };
// Press key with proper delays const pressKey = async (direction) => { console.log(`Moving: ${direction}`); const event = new KeyboardEvent('keydown', { key: direction, code: direction, keyCode: { 'ArrowUp': 38, 'ArrowDown': 40, 'ArrowLeft': 37, 'ArrowRight': 39 }[direction], which: { 'ArrowUp': 38, 'ArrowDown': 40, 'ArrowLeft': 37, 'ArrowRight': 39 }[direction], bubbles: true, cancelable: true }); document.dispatchEvent(event); await randomDelay(150, 300); };
// Check for game over const isGameOver = () => { const gameOverElement = document.querySelector('#game-container > div.jsx-2883dceedf364fd2.duration-400.absolute.inset-0.z-10.flex.flex-col.items-center.justify-center.rounded.bg-white\\/90.backdrop-blur-sm.transition-all > div.jsx-2883dceedf364fd2.mb-1.text-4xl.font-extrabold.text-succinct-pink'); return gameOverElement && gameOverElement.textContent.includes('Game Over!'); };
// Handle game over actions const handleGameOver = async () => { const score = getScore(); console.log(`Game Over! Final score: ${score}`); await randomDelay(1000, 2000); // Wait for animation
try { if (score > 20000) { console.log('Score > 20000, clicking Confirm Score...'); const confirmButton = document.querySelector('#game-container > div.jsx-2883dceedf364fd2.duration-400.absolute.inset-0.z-10.flex.flex-col.items-center.justify-center.rounded.bg-white\\/90.backdrop-blur-sm.transition-all > div:nth-child(3) > button > div > span'); if (confirmButton) { confirmButton.click(); await randomDelay(500, 1000); } } else { console.log('Score <= 20000, clicking Try Again...'); const tryAgainButton = document.querySelector('#game-container > div.jsx-2883dceedf364fd2.duration-400.absolute.inset-0.z-10.flex.flex-col.items-center.justify-center.rounded.bg-white\\/90.backdrop-blur-sm.transition-all > div.jsx-2883dceedf364fd2.flex.flex-col.gap-3 > button.jsx-2883dceedf364fd2.rounded.bg-succinct-pink.px-6.py-2.font-bold.text-white.shadow-sm.transition-all.hover\\:bg-succinct-pink\\/80.active\\:scale-95'); if (tryAgainButton) { tryAgainButton.click(); await randomDelay(500, 1000); } } } catch (error) { console.error('Error handling game over:', error); } };
// Simple pattern-based strategy class GameStrategy { constructor() { this.patterns = [ ['ArrowRight', 'ArrowDown'], ['ArrowDown', 'ArrowRight'], ['ArrowRight', 'ArrowDown', 'ArrowRight'], ['ArrowDown', 'ArrowRight', 'ArrowDown'] ]; this.currentPattern = 0; this.patternIndex = 0; this.lastMoves = []; this.stuckCount = 0; }
async executeMove(grid) { // Check if we're stuck if (this.isStuck(grid)) { this.stuckCount++; if (this.stuckCount >= 2) { await this.performRecoverySequence(); return; } } else { this.stuckCount = 0; }
// Get next move from pattern const move = this.getNextMove(grid); await pressKey(move); this.lastMoves.push(move); if (this.lastMoves.length > 5) this.lastMoves.shift(); }
isStuck(grid) { if (this.lastMoves.length < 2) return false; return this.lastMoves.slice(-2).every(move => move === this.lastMoves[this.lastMoves.length - 1] ); }
async performRecoverySequence() { console.log('Performing recovery sequence...'); const recoveryMoves = ['ArrowLeft', 'ArrowUp', 'ArrowRight', 'ArrowDown']; for (const move of recoveryMoves) { await pressKey(move); await randomDelay(200, 400); } this.switchPattern(); this.stuckCount = 0; this.lastMoves = []; }
getNextMove(grid) { // Switch pattern if needed if (this.patternIndex >= this.patterns[this.currentPattern].length) { this.switchPattern(); }
// Get move from current pattern const move = this.patterns[this.currentPattern][this.patternIndex]; this.patternIndex++; return move; }
switchPattern() { this.currentPattern = (this.currentPattern + 1) % this.patterns.length; this.patternIndex = 0; } }
// Main game loop console.log('Starting 2048 game with pattern-based strategy...'); const strategy = new GameStrategy(); let moveCount = 0; let highestTile = 0; let lastGridState = null; let sameStateCount = 0; let consecutiveGames = 0;
while (true) { if (isGameOver()) { await handleGameOver(); consecutiveGames++; // Reset game state moveCount = 0; highestTile = 0; lastGridState = null; sameStateCount = 0; strategy.stuckCount = 0; strategy.lastMoves = []; // Wait before starting new game await randomDelay(1500, 2500); continue; }
const grid = getGrid(); if (!grid) { await randomDelay(500, 1000); continue; }
// Check for completely stuck state const currentGridStr = JSON.stringify(grid); if (currentGridStr === lastGridState) { sameStateCount++; if (sameStateCount >= 3) { console.log('Completely stuck, performing full reset...'); await pressKey('ArrowUp'); await randomDelay(200, 400); await pressKey('ArrowLeft'); await randomDelay(200, 400); sameStateCount = 0; continue; } } else { sameStateCount = 0; lastGridState = currentGridStr; }
// Track highest tile const currentHighest = Math.max(...grid); if (currentHighest > highestTile) { console.log(`New highest tile: ${currentHighest}`); highestTile = currentHighest; }
// Execute next move await strategy.executeMove(grid); moveCount++; // Longer delay between moves await randomDelay(200, 400); } })();
|