Last active
August 22, 2025 17:22
-
-
Save michelefenu/f7d8577de1aa97af9d40bb3a7951bf0c to your computer and use it in GitHub Desktop.
AI Dino
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * MODEL: Gemini 2.5 Pro | |
| * PROMPT: Create a JavaScript script that automates playing the Chrome T-Rex game by detecting upcoming obstacles and triggering an automatic jump to avoid them. | |
| * WORKING: Partially | |
| * | |
| * Chrome T-Rex Game Automation Script | |
| * | |
| */ | |
| function automateTrexGame() { | |
| // Check if the game's Runner instance is available | |
| if (typeof Runner === 'undefined' || !Runner.instance_) { | |
| console.log("T-Rex game not found. Make sure you are on the 'chrome://dino' page and the game has started."); | |
| return; | |
| } | |
| const runner = Runner.instance_; | |
| const originalGameOver = runner.gameOver; | |
| let automationInterval; | |
| // Function to simulate a jump | |
| function jump() { | |
| // We only jump if the T-Rex is not already in the air | |
| if (!runner.tRex.jumping) { | |
| // Trigger the keydown event for the 'ArrowUp' key | |
| const event = new KeyboardEvent('keydown', { | |
| keyCode: 38, | |
| which: 38, | |
| code: 'ArrowUp', | |
| bubbles: true, | |
| }); | |
| document.dispatchEvent(event); | |
| console.log('Jump!'); | |
| } | |
| } | |
| // The main loop for the automation logic | |
| function gameLoop() { | |
| // If the game is over, we stop the automation | |
| if (runner.crashed) { | |
| console.log('Game Over. Stopping automation.'); | |
| clearInterval(automationInterval); | |
| return; | |
| } | |
| const obstacles = runner.horizon.obstacles; | |
| const tRex = runner.tRex; | |
| const currentSpeed = runner.currentSpeed; | |
| // Check if there are any obstacles on the screen | |
| if (obstacles.length > 0) { | |
| const nextObstacle = obstacles[0]; | |
| // Define the distance at which the T-Rex should jump. | |
| // This distance increases as the game speed increases. | |
| const jumpThreshold = 30 + currentSpeed * 15; | |
| // Check the distance to the next obstacle | |
| if (nextObstacle.xPos <= jumpThreshold) { | |
| // Check the vertical position of the obstacle to handle birds (pterodactyls) | |
| // The yPos for high-flying birds is typically 75 | |
| if (nextObstacle.yPos <= 100) { // Standard cactus or low-flying bird | |
| jump(); | |
| } | |
| // If it's a high-flying bird, we don't need to jump. | |
| // The T-Rex can run underneath it. | |
| } | |
| } | |
| } | |
| // Overwrite the game's gameOver function to stop our script | |
| runner.gameOver = function() { | |
| console.log('Game Over detected. Cleaning up.'); | |
| clearInterval(automationInterval); | |
| // Call the original gameOver function to display the game over screen | |
| originalGameOver.call(this); | |
| }; | |
| // Start the automation loop | |
| // The interval is set to a low value for quick reactions | |
| automationInterval = setInterval(gameLoop, 10); | |
| console.log('T-Rex game automation started!'); | |
| } | |
| // Start the automation | |
| automateTrexGame(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * MODEL: GPT 5 | |
| * PROMPT: Develop a JavaScript script that automates gameplay of the Chrome T-Rex game by automatically detecting approaching obstacles using in-game element analysis or visual cues, and programmatically triggering jump actions when obstacles are within a specified proximity to prevent collisions. | |
| Ensure the script continuously monitors obstacle positions, calculates the optimal timing for jumps, and interfaces with the game's event system to simulate game actions seamlessly. Include logic to adapt to varying obstacle speeds and game levels for reliable performance during an active game session. | |
| Keep the code minimal. | |
| * WORKING: NO | |
| * | |
| */ | |
| (() => { | |
| const wait = (f)=>new Promise(r=>{const t=setInterval(()=>{const R=window.Runner&&Runner.instance_; if(R&&R.horizon&&R.tRex){clearInterval(t);r(R)}},80)}); | |
| wait().then(R=>{ | |
| let last=0, minGap=200; // ms between jumps to avoid spam | |
| const pressUp = () => { | |
| if (typeof R.onKeyDown==='function') { R.onKeyDown({keyCode:38, preventDefault(){} }); return; } | |
| if (R.tRex && typeof R.tRex.startJump==='function') { R.tRex.startJump(R.currentSpeed||0); return; } | |
| const e={keyCode:38,which:38,code:'ArrowUp',bubbles:true}; | |
| document.dispatchEvent(new KeyboardEvent('keydown',e)); | |
| setTimeout(()=>document.dispatchEvent(new KeyboardEvent('keyup',e)),80); | |
| }; | |
| const jump = () => { | |
| if (!R.tRex || R.tRex.jumping || R.tRex.ducking) return; | |
| if (performance.now()-last<minGap) return; | |
| last=performance.now(); pressUp(); | |
| }; | |
| const nearestObstacle = () => { | |
| const a=R.horizon.obstacles; if(!a||!a.length) return null; | |
| const me=R.tRex.xPos||50; let n=null,d=1e9; | |
| for(const o of a){const dd=o.xPos-me; if(dd>=0 && dd<d){d=dd;n=o}} | |
| return n?{d, w:n.width||0, y:n.yPos||0}:null; | |
| }; | |
| const loop = () => { | |
| if (R.crashed) { try{ R.restart(); }catch{} } | |
| if (!(R.paused||R.crashed||R.playingIntro)) { | |
| const o=nearestObstacle(); | |
| if (o) { | |
| const speed=R.currentSpeed||0; | |
| // Adaptive trigger: earlier at higher speeds and for wider obstacles | |
| let trigger = 35 + speed*10 + o.w*0.75; | |
| // High pterodactyls (small y) usually pass overheadβskip | |
| if (o.y<70) trigger = Infinity; | |
| if (o.d <= trigger) jump(); | |
| } | |
| } | |
| requestAnimationFrame(loop); | |
| }; | |
| loop(); | |
| console.log('Dino bot running. Refresh page to stop.'); | |
| }); | |
| })(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * MODEL: GPT-5 | |
| * PROMPT: Create a JavaScript script that automates playing the Chrome T-Rex game by detecting upcoming obstacles and triggering an automatic jump to avoid them. | |
| * WORKING: NO | |
| * | |
| * Chrome T-Rex Game Automation Script | |
| */ | |
| (() => { | |
| const r = window.Runner && Runner.instance_; | |
| if (!r) { console.warn('Runner.instance_ not found. Open chrome://dino and start the game.'); return; } | |
| // Toggle: re-run to disable | |
| if (window._autoDino) { window._autoDino.stop(); delete window._autoDino; console.log('Auto Dino disabled'); return; } | |
| const state = { on: true, lastAction: 0 }; | |
| const cfg = { | |
| jumpLeadBase: 40, // base lead distance (px) | |
| jumpLeadPerSpeed: 25, // extra lead per unit speed (px) | |
| widthFactor: 0.5, // consider obstacle width | |
| minIntervalMs: 300, // min time between actions (ms) | |
| duckHoldMs: 300, // how long to hold duck (ms) | |
| autoRestart: true // auto-restart after crash | |
| }; | |
| const now = () => performance.now(); | |
| const keyDown = (code) => document.dispatchEvent(new KeyboardEvent('keydown', { keyCode: code, which: code, bubbles: true })); | |
| const keyUp = (code) => document.dispatchEvent(new KeyboardEvent('keyup', { keyCode: code, which: code, bubbles: true })); | |
| function jump() { | |
| if (r.tRex.jumping || r.tRex.ducking) return; | |
| const t = now(); | |
| if (t - state.lastAction < cfg.minIntervalMs) return; | |
| if (typeof r.tRex.startJump === 'function') { | |
| r.tRex.startJump(r.currentSpeed); | |
| } else { | |
| keyUp(40); // make sure not ducking | |
| keyDown(32); keyUp(32); // Space | |
| } | |
| state.lastAction = t; | |
| } | |
| let duckTimeout; | |
| function duckShort() { | |
| if (r.tRex.jumping) return; | |
| const t = now(); | |
| if (t - state.lastAction < 120) return; | |
| keyDown(40); // ArrowDown | |
| clearTimeout(duckTimeout); | |
| duckTimeout = setTimeout(() => keyUp(40), cfg.duckHoldMs); | |
| state.lastAction = t; | |
| } | |
| const nearestObstacle = () => { | |
| const obs = r.horizon && r.horizon.obstacles; | |
| if (!obs || !obs.length) return null; | |
| return obs[0]; // closest is first | |
| }; | |
| function tick() { | |
| if (!state.on) return; | |
| // Handle crash and restart | |
| if (r.crashed) { | |
| if (cfg.autoRestart) { | |
| try { r.restart(); } catch {} | |
| } | |
| requestAnimationFrame(tick); | |
| return; | |
| } | |
| // If game not active yet, keep polling | |
| if (r.activated === false) { | |
| requestAnimationFrame(tick); | |
| return; | |
| } | |
| const obs = nearestObstacle(); | |
| if (obs) { | |
| const speed = r.currentSpeed || 0; | |
| const trexFront = r.tRex.xPos + r.tRex.config.WIDTH; | |
| const distance = obs.xPos - trexFront; | |
| const threshold = cfg.jumpLeadBase + cfg.jumpLeadPerSpeed * speed + cfg.widthFactor * (obs.width || 0); | |
| const isBird = obs.typeConfig && obs.typeConfig.type === 'PTERODACTYL'; | |
| if (isBird) { | |
| // Pterodactyl flies at different heights. Low/mid => jump. High => duck. | |
| const birdIsLowOrMid = obs.yPos >= 75; // heuristic: >=75 is low/mid altitude | |
| if (distance < threshold) { | |
| if (birdIsLowOrMid) jump(); | |
| else duckShort(); | |
| } | |
| } else { | |
| // Cacti and ground obstacles => jump | |
| if (distance < threshold) jump(); | |
| } | |
| } | |
| requestAnimationFrame(tick); | |
| } | |
| requestAnimationFrame(tick); | |
| window._autoDino = { | |
| stop() { state.on = false; keyUp(40); console.log('Auto Dino stopped'); }, | |
| start() { if (!state.on) { state.on = true; requestAnimationFrame(tick); console.log('Auto Dino started'); } }, | |
| config: cfg | |
| }; | |
| console.log('Auto Dino enabled. Use _autoDino.stop() to stop, _autoDino.start() to resume, and _autoDino.config to tweak.'); | |
| })(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * MODEL: Claude 4 Sonnet (Thinking) | |
| * PROMPT: Create a JavaScript script that automates playing the Chrome T-Rex game by detecting upcoming obstacles and triggering an automatic jump to avoid them. | |
| * WORKING: NO | |
| * | |
| * Chrome T-Rex Game Automation Script | |
| * | |
| * USAGE INSTRUCTIONS: | |
| * 1. Open Chrome and go to chrome://dino/ (or disconnect internet and try to browse) | |
| * 2. Press F12 to open Developer Console | |
| * 3. Paste this entire script into the console and press Enter | |
| * 4. Type: const bot = new TRexBot(); bot.start(); and press Enter | |
| * 5. Click on the game to focus it, then press Space to start | |
| * 6. To stop the bot: bot.stop(); | |
| */ | |
| class TRexBot { | |
| constructor() { | |
| this.runner = null; | |
| this.tRex = null; | |
| this.canvas = null; | |
| this.canvasCtx = null; | |
| this.isRunning = false; | |
| this.gameSpeed = 6; | |
| this.lastObstacleX = 0; | |
| this.frameId = null; | |
| this.jumpThreshold = 150; | |
| this.duckThreshold = 120; | |
| this.minJumpGap = 300; | |
| this.lastJumpTime = 0; | |
| this.isDucking = false; | |
| this.duckDuration = 500; | |
| this.duckStartTime = 0; | |
| this.frameSkip = 0; | |
| this.maxFrameSkip = 2; | |
| this.maxRetries = 5; | |
| this.retryCount = 0; | |
| this.initialize(); | |
| } | |
| initialize() { | |
| try { | |
| this.detectGameElements(); | |
| this.setupEventListeners(); | |
| console.log('π¦ T-Rex Bot initialized successfully!'); | |
| console.log('π Commands: bot.start() | bot.stop() | bot.getStats()'); | |
| } catch (error) { | |
| console.error('β Failed to initialize T-Rex Bot:', error); | |
| this.handleInitializationError(); | |
| } | |
| } | |
| detectGameElements() { | |
| this.runner = window.Runner || | |
| (window.runner && window.runner.instance_) || | |
| this.findRunnerInstance(); | |
| if (!this.runner) throw new Error('T-Rex game not found. Make sure you\'re on chrome://dino/'); | |
| this.canvas = document.querySelector('canvas.runner-canvas') || | |
| document.querySelector('canvas'); | |
| if (!this.canvas) throw new Error('Game canvas not found'); | |
| this.canvasCtx = this.canvas.getContext('2d'); | |
| this.tRex = this.runner.tRex; | |
| if (!this.tRex) throw new Error('T-Rex object not found'); | |
| this.validateGameMethods(); | |
| } | |
| findRunnerInstance() { | |
| const possibleNames = ['Runner', 'runner', 'game', 'trexGame']; | |
| for (const name of possibleNames) { | |
| if (window[name] && typeof window[name] === 'object') { | |
| return window[name].instance_ || window[name]; | |
| } | |
| } | |
| const scripts = document.querySelectorAll('script'); | |
| for (const script of scripts) { | |
| if (script.textContent && script.textContent.includes('Runner')) { | |
| document.body.click(); | |
| setTimeout(() => this.detectGameElements(), 100); | |
| return null; | |
| } | |
| } | |
| return null; | |
| } | |
| validateGameMethods() { | |
| const requiredMethods = ['startJump', 'endJump']; | |
| const tRexMethods = Object.getOwnPropertyNames(Object.getPrototypeOf(this.tRex)); | |
| for (const method of requiredMethods) { | |
| if (!tRexMethods.includes(method) && typeof this.tRex[method] !== 'function') { | |
| console.warn(`β οΈ Method ${method} not found on T-Rex object`); | |
| } | |
| } | |
| } | |
| setupEventListeners() { | |
| const originalGameOver = this.runner.gameOver; | |
| this.runner.gameOver = () => { | |
| console.log('π Game Over! Final Score:', this.getScore()); | |
| this.stop(); | |
| originalGameOver.call(this.runner); | |
| }; | |
| this.monitorSpeedChanges(); | |
| } | |
| monitorSpeedChanges() { | |
| const checkSpeed = () => { | |
| if (this.runner && this.runner.currentSpeed) { | |
| const newSpeed = this.runner.currentSpeed; | |
| if (newSpeed !== this.gameSpeed) { | |
| this.gameSpeed = newSpeed; | |
| this.adjustTimingForSpeed(); | |
| console.log(`π Speed changed to: ${this.gameSpeed}`); | |
| } | |
| } | |
| }; | |
| setInterval(checkSpeed, 1000); | |
| } | |
| adjustTimingForSpeed() { | |
| this.jumpThreshold = Math.max(100, 150 - (this.gameSpeed - 6) * 3); | |
| this.duckThreshold = Math.max(80, 120 - (this.gameSpeed - 6) * 2); | |
| if (this.gameSpeed > 12) { | |
| this.maxFrameSkip = 1; | |
| } else if (this.gameSpeed > 8) { | |
| this.maxFrameSkip = 2; | |
| } else { | |
| this.maxFrameSkip = 0; | |
| } | |
| } | |
| start() { | |
| if (this.isRunning) { | |
| console.log('π€ Bot is already running!'); | |
| return; | |
| } | |
| try { | |
| this.isRunning = true; | |
| this.gameLoop(); | |
| console.log('π T-Rex Bot started! The bot will begin when the game starts.'); | |
| } catch (error) { | |
| console.error('β Failed to start bot:', error); | |
| this.stop(); | |
| } | |
| } | |
| stop() { | |
| this.isRunning = false; | |
| if (this.frameId) { | |
| cancelAnimationFrame(this.frameId); | |
| this.frameId = null; | |
| } | |
| if (this.isDucking) this.stopDucking(); | |
| console.log('π T-Rex Bot stopped.'); | |
| } | |
| gameLoop() { | |
| if (!this.isRunning) return; | |
| try { | |
| this.frameSkip++; | |
| if (this.frameSkip <= this.maxFrameSkip) { | |
| this.frameId = requestAnimationFrame(() => this.gameLoop()); | |
| return; | |
| } | |
| this.frameSkip = 0; | |
| if (!this.isGameRunning()) { | |
| this.frameId = requestAnimationFrame(() => this.gameLoop()); | |
| return; | |
| } | |
| if (this.isDucking && Date.now() - this.duckStartTime > this.duckDuration) { | |
| this.stopDucking(); | |
| } | |
| const obstacles = this.detectObstacles(); | |
| this.reactToObstacles(obstacles); | |
| } catch (error) { | |
| console.error('β Error in game loop:', error); | |
| this.handleGameLoopError(); | |
| } | |
| this.frameId = requestAnimationFrame(() => this.gameLoop()); | |
| } | |
| isGameRunning() { | |
| return this.runner && | |
| this.runner.playing && | |
| !this.runner.crashed && | |
| this.runner.activated; | |
| } | |
| detectObstacles() { | |
| if (!this.runner.horizon || !this.runner.horizon.obstacles) return []; | |
| const obstacles = []; | |
| const tRexX = this.tRex.xPos; | |
| this.runner.horizon.obstacles.forEach(obstacle => { | |
| if (obstacle.xPos > tRexX) { | |
| const distance = obstacle.xPos - tRexX; | |
| obstacles.push({ | |
| type: this.getObstacleType(obstacle), | |
| distance: distance, | |
| xPos: obstacle.xPos, | |
| yPos: obstacle.yPos, | |
| width: obstacle.typeConfig?.width || obstacle.width || 17, | |
| height: obstacle.typeConfig?.height || obstacle.height || 35, | |
| obstacle: obstacle | |
| }); | |
| } | |
| }); | |
| return obstacles.sort((a, b) => a.distance - b.distance); | |
| } | |
| getObstacleType(obstacle) { | |
| if (obstacle.typeConfig) { | |
| return obstacle.typeConfig.type === 'PTERODACTYL' ? 'pterodactyl' : 'cactus'; | |
| } | |
| if (obstacle.yPos < 75) return 'pterodactyl'; | |
| return 'cactus'; | |
| } | |
| reactToObstacles(obstacles) { | |
| if (obstacles.length === 0) return; | |
| const nearestObstacle = obstacles[0]; | |
| const currentTime = Date.now(); | |
| let actionThreshold; | |
| if (nearestObstacle.type === 'pterodactyl') { | |
| if (nearestObstacle.yPos > 50) { | |
| actionThreshold = this.duckThreshold; | |
| if (nearestObstacle.distance <= actionThreshold && !this.isDucking) { | |
| this.startDucking(); | |
| } | |
| return; | |
| } else { | |
| actionThreshold = this.jumpThreshold; | |
| } | |
| } else { | |
| actionThreshold = this.jumpThreshold; | |
| } | |
| const speedMultiplier = 1 + (this.gameSpeed - 6) * 0.1; | |
| actionThreshold *= speedMultiplier; | |
| if (nearestObstacle.distance <= actionThreshold) { | |
| if (nearestObstacle.type === 'cactus' || | |
| (nearestObstacle.type === 'pterodactyl' && nearestObstacle.yPos <= 50)) { | |
| if (currentTime - this.lastJumpTime > this.minJumpGap) { | |
| this.jump(); | |
| this.lastJumpTime = currentTime; | |
| } | |
| } | |
| } | |
| } | |
| jump() { | |
| try { | |
| if (this.tRex.jumping || this.tRex.ducking) return; | |
| if (this.isDucking) this.stopDucking(); | |
| if (typeof this.tRex.startJump === 'function') { | |
| this.tRex.startJump(this.runner.currentSpeed); | |
| } else { | |
| this.simulateKeyPress(32); | |
| } | |
| } catch (error) { | |
| console.error('β Error jumping:', error); | |
| } | |
| } | |
| startDucking() { | |
| try { | |
| if (this.tRex.jumping || this.isDucking) return; | |
| this.isDucking = true; | |
| this.duckStartTime = Date.now(); | |
| if (typeof this.tRex.setDuck === 'function') { | |
| this.tRex.setDuck(true); | |
| } else { | |
| this.simulateKeyPress(40); | |
| } | |
| } catch (error) { | |
| console.error('β Error ducking:', error); | |
| } | |
| } | |
| stopDucking() { | |
| try { | |
| if (!this.isDucking) return; | |
| this.isDucking = false; | |
| if (typeof this.tRex.setDuck === 'function') { | |
| this.tRex.setDuck(false); | |
| } else { | |
| this.simulateKeyRelease(40); | |
| } | |
| } catch (error) { | |
| console.error('β Error stopping duck:', error); | |
| } | |
| } | |
| simulateKeyPress(keyCode) { | |
| const event = new KeyboardEvent('keydown', { | |
| keyCode: keyCode, | |
| which: keyCode, | |
| bubbles: true | |
| }); | |
| document.dispatchEvent(event); | |
| } | |
| simulateKeyRelease(keyCode) { | |
| const event = new KeyboardEvent('keyup', { | |
| keyCode: keyCode, | |
| which: keyCode, | |
| bubbles: true | |
| }); | |
| document.dispatchEvent(event); | |
| } | |
| handleInitializationError() { | |
| this.retryCount++; | |
| if (this.retryCount < this.maxRetries) { | |
| console.log(`π Retrying initialization (${this.retryCount}/${this.maxRetries})...`); | |
| setTimeout(() => this.initialize(), 1000); | |
| } else { | |
| console.error('β Failed to initialize after maximum retries'); | |
| console.log('π‘ Try refreshing the page and starting the T-Rex game first'); | |
| } | |
| } | |
| handleGameLoopError() { | |
| this.retryCount++; | |
| if (this.retryCount < this.maxRetries) { | |
| console.log(`π Recovering from error (${this.retryCount}/${this.maxRetries})...`); | |
| setTimeout(() => this.gameLoop(), 100); | |
| } else { | |
| console.error('β Too many errors, stopping bot'); | |
| this.stop(); | |
| } | |
| } | |
| getScore() { | |
| try { | |
| return this.runner.distanceRan ? Math.floor(this.runner.distanceRan * 0.01) : 0; | |
| } catch (error) { | |
| return 0; | |
| } | |
| } | |
| getStats() { | |
| const stats = { | |
| isRunning: this.isRunning, | |
| gameSpeed: this.gameSpeed, | |
| currentScore: this.getScore(), | |
| jumpThreshold: this.jumpThreshold, | |
| duckThreshold: this.duckThreshold, | |
| isDucking: this.isDucking, | |
| isGameRunning: this.isGameRunning() | |
| }; | |
| console.table(stats); | |
| return stats; | |
| } | |
| debug() { | |
| const obstacles = this.detectObstacles(); | |
| console.log('π Debug Info:', { | |
| gameRunning: this.isGameRunning(), | |
| tRexPos: this.tRex ? this.tRex.xPos : 'N/A', | |
| obstacles: obstacles.map(obs => ({ | |
| type: obs.type, | |
| distance: Math.round(obs.distance), | |
| position: `${obs.xPos}, ${obs.yPos}` | |
| })), | |
| gameSpeed: this.gameSpeed, | |
| botStatus: this.isRunning ? 'Running' : 'Stopped' | |
| }); | |
| } | |
| } | |
| window.TRexBot = TRexBot; | |
| console.log('π¦ T-Rex Bot loaded! Use: const bot = new TRexBot(); bot.start()'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment