Skip to content

Commit 3b66c8b

Browse files
alexdphanpkiv
andauthored
2048 example (#136)
* 2048 example * remove pnpm lock --------- Co-authored-by: Paul Klein <paulleoklein@gmail.com>
1 parent 1e65d64 commit 3b66c8b

File tree

2 files changed

+96
-0
lines changed

2 files changed

+96
-0
lines changed

examples/2048.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
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+
})();

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"scripts": {
88
"example": "npm run build-dom-scripts && tsx examples/example.ts",
99
"debug-url": "npm run build-dom-scripts && tsx examples/debugUrl.ts",
10+
"2048": "npm run build-dom-scripts && tsx examples/2048.ts",
1011
"format": "prettier --write .",
1112
"cache:clear": "rm -rf .cache",
1213
"evals": "npm run build-dom-scripts && npx braintrust eval evals/index.eval.ts",

0 commit comments

Comments
 (0)