|
| 1 | +import { Stagehand } from "../lib"; |
| 2 | +import { z } from "zod"; |
| 3 | +async function example() { |
| 4 | + console.log("🎮 Starting 2048 bot..."); |
| 5 | + const stagehand = new Stagehand({ |
| 6 | + env: "LOCAL", |
| 7 | + verbose: 1, |
| 8 | + debugDom: true, |
| 9 | + domSettleTimeoutMs: 100, |
| 10 | + }); |
| 11 | + try { |
| 12 | + console.log("🌟 Initializing Stagehand..."); |
| 13 | + await stagehand.init(); |
| 14 | + console.log("🌐 Navigating to 2048..."); |
| 15 | + await stagehand.page.goto("https://ovolve.github.io/2048-AI/"); |
| 16 | + console.log("⌛ Waiting for game to initialize..."); |
| 17 | + await stagehand.page.waitForSelector(".grid-container", { timeout: 10000 }); |
| 18 | + // Main game loop |
| 19 | + while (true) { |
| 20 | + console.log("🔄 Game loop iteration..."); |
| 21 | + // Add a small delay for UI updates |
| 22 | + await new Promise((resolve) => setTimeout(resolve, 300)); |
| 23 | + // Get current game state |
| 24 | + const gameState = await stagehand.extract({ |
| 25 | + instruction: `Extract the current game state: |
| 26 | + 1. Score from the score counter |
| 27 | + 2. All tile values in the 4x4 grid (empty spaces as 0) |
| 28 | + 3. Highest tile value present`, |
| 29 | + schema: z.object({ |
| 30 | + score: z.number(), |
| 31 | + highestTile: z.number(), |
| 32 | + grid: z.array(z.array(z.number())), |
| 33 | + }), |
| 34 | + }); |
| 35 | + const transposedGrid = gameState.grid[0].map((_, colIndex) => |
| 36 | + gameState.grid.map((row) => row[colIndex]), |
| 37 | + ); |
| 38 | + const grid = transposedGrid.map((row, rowIndex) => ({ |
| 39 | + [`row${rowIndex + 1}`]: row, |
| 40 | + })); |
| 41 | + console.log("Game State:", { |
| 42 | + score: gameState.score, |
| 43 | + highestTile: gameState.highestTile, |
| 44 | + grid: grid, |
| 45 | + }); |
| 46 | + // Analyze board and decide next move |
| 47 | + const analysis = await stagehand.extract({ |
| 48 | + instruction: `Based on the current game state: |
| 49 | + - Score: ${gameState.score} |
| 50 | + - Highest tile: ${gameState.highestTile} |
| 51 | + - Grid: This is a 4x4 matrix ordered by row (top to bottom) and column (left to right). The rows are stacked vertically, and tiles can move vertically between rows or horizontally between columns:\n${grid |
| 52 | + .map((row) => { |
| 53 | + const rowName = Object.keys(row)[0]; |
| 54 | + return ` ${rowName}: ${row[rowName].join(", ")}`; |
| 55 | + }) |
| 56 | + .join("\n")} |
| 57 | + What is the best move (up/down/left/right)? Consider: |
| 58 | + 1. Keeping high value tiles in corners (bottom left, bottom right, top left, top right) |
| 59 | + 2. Maintaining a clear path to merge tiles |
| 60 | + 3. Avoiding moves that could block merges |
| 61 | + 4. Only adjacent tiles of the same value can merge |
| 62 | + 5. Making a move will move all tiles in that direction until they hit a tile of a different value or the edge of the board |
| 63 | + 6. Tiles cannot move past the edge of the board |
| 64 | + 7. Each move must move at least one tile`, |
| 65 | + schema: z.object({ |
| 66 | + move: z.enum(["up", "down", "left", "right"]), |
| 67 | + confidence: z.number(), |
| 68 | + reasoning: z.string(), |
| 69 | + }), |
| 70 | + }); |
| 71 | + console.log("Move Analysis:", analysis); |
| 72 | + const moveKey = { |
| 73 | + up: "ArrowUp", |
| 74 | + down: "ArrowDown", |
| 75 | + left: "ArrowLeft", |
| 76 | + right: "ArrowRight", |
| 77 | + }[analysis.move]; |
| 78 | + await stagehand.page.keyboard.press(moveKey); |
| 79 | + console.log("🎯 Executed move:", analysis.move); |
| 80 | + } |
| 81 | + } catch (error) { |
| 82 | + console.error("❌ Error in game loop:", error); |
| 83 | + const isGameOver = await stagehand.page.evaluate(() => { |
| 84 | + return document.querySelector(".game-over") !== null; |
| 85 | + }); |
| 86 | + if (isGameOver) { |
| 87 | + console.log("🏁 Game Over!"); |
| 88 | + return; |
| 89 | + } |
| 90 | + throw error; // Re-throw non-game-over errors |
| 91 | + } |
| 92 | +} |
| 93 | +(async () => { |
| 94 | + await example(); |
| 95 | +})(); |
0 commit comments