Skip to content

Commit 0b61428

Browse files
committed
improve aimulator
1 parent 37a53a0 commit 0b61428

File tree

3 files changed

+260
-2710
lines changed

3 files changed

+260
-2710
lines changed

aimulator.mjs

Lines changed: 216 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,41 @@
1-
#!/usr/bin/env node
2-
import * as GPT from './GPT.mjs';
3-
import * as Claude from './Claude.mjs';
41
import process from "process";
52
import fs from 'fs/promises';
63
import os from 'os';
74
import path from 'path';
5+
import { Anthropic } from '@anthropic-ai/sdk';
6+
7+
async function getAnthropicKey() {
8+
const keyPath = path.join(process.env.HOME, '.config', 'anthropic.token');
9+
return (await fs.readFile(keyPath, 'utf8')).trim();
10+
}
11+
12+
export async function ask({ system, messages, max_tokens, model = 'claude-3-opus-20240229', temperature = 1, debug = true }) {
13+
const anthropic = new Anthropic({ apiKey: await getAnthropicKey() });
14+
if (debug) {
15+
const stream = anthropic.messages.stream({
16+
model,
17+
messages,
18+
max_tokens: max_tokens || 4096,
19+
temperature,
20+
...(system && { system }),
21+
}).on('text', (text) => process.stdout.write(text));
22+
const message = await stream.finalMessage();
23+
console.log(); // Add a newline at the end
24+
return message.content[0].text;
25+
} else {
26+
const message = await anthropic.messages.create({
27+
model,
28+
messages,
29+
max_tokens: max_tokens || 4096,
30+
temperature,
31+
...(system && { system }),
32+
});
33+
return message.content[0].text;
34+
}
35+
}
836

937
const MODEL = "claude-3-opus-20240229";
38+
//const MODEL = "gpt-4-32k-0314";
1039

1140
const SYSTEM = `
1241
You're a game emulator. You can emulate ANY game, but text-based. Your goal is
@@ -15,87 +44,192 @@ original as possible, from start to end.
1544
1645
You'll be provided with:
1746
1. The chosen game.
18-
2. The current game log / history.
47+
2. The current message context.
1948
20-
You'll must answer with:
21-
1. A description of the current game screen.
22-
2. A text-based UI of the current game screen.
49+
Your responses must include:
50+
1. A short description of the current game screen or state.
51+
2. A textual 2D UI of the current game screen, using emojis and symbols.
2352
3. A labelled list of options that the player can take.
2453
25-
Note that the screen must emulate all game screen elements in a well-positioned,
26-
well-aligned 2D canvas. IT IS NOT ASCII ART. It is a textual UI. For example:
27-
28-
# Example 1: Pokémon Red Battle Screen
29-
30-
You're in a Pokémon battle.
31-
32-
Blastoise LV30 💦🐢💣
33-
HP: |||....... 🔫🐚🛡️
34-
35-
Charizard LV32 🔥🐉🦇
36-
HP: ||||||.... 🌋🦖😤
37-
38-
Options:
39-
A) [FIGHT] B) [PKMN]
40-
C) [ITEM] D) [RUN]
41-
42-
Notes:
43-
1. The screen was drawn as compactly as possible.
44-
2. Key in-game screen elements were positioned in 2D.
45-
3. HP bars were drawn visually, to make it appealing.
46-
4. Emojis (NOT ASCII art) were used to represent images.
47-
5. We expanded the FIGHT option for faster interactions.
54+
Always follow this template:
4855
49-
# Example 2: Zelda Majora's Mask - Odolwa Boss Fight Room
56+
<<description>>
57+
<<game_screen>>
58+
<<options>>
5059
51-
HP ❤️ ❤️ ❤️ 🤍🤍🤍🤍 :: [A] PutAway [B] 🗡
52-
MANA 🟩🟩🟩⬜⬜⬜⬜⬜⬜⬜ :: [<] 🪈 [V] 💣 [>] 🎣
60+
Guidelines for the game screen UI:
61+
- Draw it as compactly as possible while maintaining readability.
62+
- When handy, add a description / narration above the screen.
63+
- Use a 2D textual grid to position key game elements spatially.
64+
- Represent sprites, characters, items etc with 1-3 emojis each.
65+
- Draw HP/mana bars, item counts etc visually to form a nice UI.
66+
- Use ASCII diagrams very sparingly, mainly for progress bars.
67+
- Include menu options like Pause, Inventory etc for completeness.
68+
- Expand item/action options (e.g. Use X, Attack, Defend) for faster play.
5369
54-
Link Navi Door-A
55-
[🗡️🧝🛡️] [🧚] [🚪🔒]
56-
57-
Odolwa Jar Door-B Chest
58-
[🗡️🎭🗡️] [🏺] [🚪🔒] [🎁🔒]
70+
Here are some examples of how your game screen should look.
5971
60-
Grss Grss Grss
61-
[🌿] [🌿] [🌿]
72+
# Example: Pokémon Red - Battle Screen
6273
63-
💎 000 :: [_|7|_|_|_|_|_|_|_|_|_|_] ☀️ 1st
64-
65-
Options:
66-
A) Talk to Navi B) Use Item
67-
C) Attack Odolwa D) Attack Jar
68-
E) Open Door-A F) Open Door-B
69-
G) Move to Grass H) Press Start
70-
71-
Notes:
72-
1. The screen was drawn as compactly as possible.
73-
2. The room layout was positioned in a 2D grid.
74-
3. Key room elements like Link, Odolwa, doors, etc were positioned spatially.
75-
4. HP/Mana bars and Rupee count were drawn visually.
76-
5. Emojis represent Link's current weapon, characters, items, etc.
77-
6. ASCII diagrams used for Rupee count bar and day cycle.
78-
7. Start button menu option included for completeness.
79-
8. Expanded item usage controls for faster interactions.
80-
81-
IMPORTANT: You ARE the videogame. Stay in character. Answer ONLY with the
82-
game screen. Do NOT answer with assistant-like explanations.
83-
84-
IMPORTANT: Stay LOYAL to the original game, including its core mechanics, order
85-
of events and gameplay, from the initial menu all the way to the end screen.
86-
87-
At some points of the interaction, the player may add comments and hints after a
88-
hashtag ('#'). Use this feedback to adjust and improve the experience.`;
74+
You're in a Pokémon battle.
75+
,-----------------------------,
76+
Blastoise LV30 [💦🐢💣]
77+
HP: |||....... [🔫🐚🛡️]
78+
79+
Charizard LV32 [🔥🐉🦇]
80+
HP: ||||||.... [🌋🦖😤]
81+
'-----------------------------'
82+
A) FIGHT
83+
B) PKMN
84+
C) ITEM
85+
D) RUN
86+
87+
# Example: Zelda Majora's Mask - Odolwa Boss Room
88+
89+
You're in Odolwa's boss room in Woodfall Temple.
90+
Odolwa is dancing and swinging his swords menacingly.
91+
,--------------------------------------------------,
92+
HP ❤️ ❤️ ❤️ 🤍🤍🤍🤍
93+
MANA 🟩🟩🟩⬜⬜⬜⬜⬜⬜⬜
94+
95+
Link Navi Door0
96+
[🗡️🧝🛡️] [🧚] [🚪🔒]
97+
98+
Odolwa Jar Door1 Chest
99+
[🗡️🎭🗡️] [🏺] [🚪🔒] [🎁🔒]
100+
101+
Grs0 Grs1 Grs2
102+
[🌿] [🌿] [🌿]
103+
104+
💎 000 🕒 7 AM :: ☀️ 1st Day
105+
'--------------------------------------------------'
106+
A) Talk to Navi
107+
B) Enter Door0
108+
C) Attack Odolwa
109+
D) Break the Jar
110+
E) Enter Door1
111+
F) Check Grs0
112+
G) Check Grs1
113+
H) Check Grs2
114+
115+
# Example: Mario 64 - Inside Castle
116+
117+
You're in the main entrance hall of Princess Peach's castle.
118+
,---------------------------------.
119+
🍄x4 🌟x7
120+
121+
Door0 Door1 Door2
122+
[🚪🌟] [🚪🔒] [🚪0]
123+
124+
Door3 Door4 Door5 Door6
125+
[🚪0] [🚪3] [🚪7] [🚪1]
126+
127+
Exit Mario Coin0 Coin1
128+
[🚪] [🍄] [🟡] [🟡]
129+
'---------------------------------'
130+
A) Enter Door0
131+
B) Enter Door1
132+
C) Enter Door2
133+
D) Enter Door3
134+
E) Enter Door4
135+
F) Enter Door5
136+
G) Enter Door6
137+
H) Check Coin0
138+
I) Check Coin1
139+
J) Exit
140+
141+
# Example: Pokémon Red - Title Screen
142+
143+
,-------------------------------,
144+
Pokémon
145+
Red
146+
147+
[🔥🐉🦇]
148+
149+
©1996 Nintendo
150+
Creatures Inc.
151+
GAME FREAK inc.
152+
153+
Press Start Button
154+
'-------------------------------'
155+
A) New Game
156+
B) Continue
157+
C) Options
158+
159+
# Example: Pokémon Red - Introduction
160+
161+
,-------------------------------.
162+
163+
OAK
164+
Hello there! Welcome to the
165+
world of POKÉMON!
166+
167+
OAK
168+
My name is OAK!
169+
People call me the
170+
POKÉMON PROF!
171+
172+
NIDORAN♂
173+
[🐭💜🦏]
174+
'-------------------------------'
175+
A) Next
176+
177+
# Example: Pokémon Red - Pallet Town
178+
179+
You're in Pallet Town, your hometown.
180+
,--------------------------,
181+
🌳 [Route 1] 🌳
182+
183+
House0 House1
184+
[🏠] [🏠]
185+
186+
Grass Oak's Lab
187+
[🌿] [🏫]
188+
189+
Beach Sign 🌸
190+
[🌊] [🪧] 🌼
191+
'--------------------------'
192+
A) Enter House0
193+
B) Enter House1
194+
C) Enter Oak's Lab
195+
D) Check the Sign
196+
E) Walk in the Grass
197+
F) Exit to Route 1
198+
199+
# Example: Pokémon Red - Protagonist's House
200+
201+
You're inside your house in Pallet Town.
202+
,---------------------------.
203+
PC TV Stairs
204+
[💻] [📺] [┗┓]
205+
206+
Bed You
207+
[🛏️] [👦]
208+
'---------------------------'
209+
A) Check the PC
210+
B) Play SNES on TV
211+
C) Rest in Bed
212+
B) Go Downstairs
213+
214+
IMPORTANT:
215+
- You ARE the videogame. Stay in character.
216+
- Start from the game's initial menus and emulate each level in order.
217+
- Emulate the game loyally, following its original sequence of events.
218+
- Design a well-aligned UI for each screen. Position elements in 2D.
219+
- Respond with ONLY the next emulation step and its options.
220+
221+
If the player provides feedback after a '#', use it to improve the experience.
222+
`;
89223

90224
(async () => {
91225
console.clear();
92226

93227
const ASCII_ART = `
94-
\x1b[1m\x1b[36m█▀▀▀▀▀█ ▀ ▄▀▄ █▀▀▀▀▀█\x1b[0m
228+
\x1b[1m\x1b[36m█▀▀▀▀▀█ ▀ ▄▀▄ █▀▀▀▀▀█\x1b[0m
95229
\x1b[1m\x1b[36m█ ███ █ ▀ ▀█▀ █ ███ █\x1b[0m
96230
\x1b[1m\x1b[36m█ ▀▀▀ █ █ ▄█▄ █ ▀▀▀ █\x1b[0m
97231
\x1b[1m\x1b[36m▀▀▀▀▀▀▀ ▀ ▀▀▀ ▀▀▀▀▀▀▀\x1b[0m
98-
\x1b[2mA I E M U L A T O R\x1b[0m
232+
\x1b[2mA I E M U L A T O R\x1b[0m
99233
`.trim();
100234

101235
console.log(ASCII_ART);
@@ -104,31 +238,33 @@ hashtag ('#'). Use this feedback to adjust and improve the experience.`;
104238
console.log(`\x1b[32mUsing \x1b[1m${MODEL}\x1b[0m`);
105239
console.log("");
106240

107-
// TODO: get game input
108241
process.stdout.write("Game: ");
109242
const game = (await new Promise(resolve => process.stdin.once('data', data => resolve(data.toString())))).trim();
110243

111244
console.log(`Emulating ${game}...\n\n`);
112245

113-
let log = '';
246+
let messages = [
247+
{role: "user", content: `# GAME: ${game}`},
248+
];
114249

115250
while (true) {
116251
console.clear();
117252

118-
const response = await Claude.ask({
119-
system: SYSTEM,
120-
model: MODEL,
121-
prompt: `# GAME: ${game}\n# LOG:\n${log}\n\n# TASK: You must continue the game from here. Write your answer below, including the next screen's description, textual UI and player options:`,
122-
max_tokens: 4096,
123-
temperature: 0.9,
253+
const response = await ask({
254+
model: MODEL,
255+
messages,
256+
max_tokens: 2048,
257+
temperature: 0.5,
258+
system: SYSTEM,
124259
});
125260

126-
log += `# SCREEN:\n\n${response}\n\n`;
261+
messages.push({role: "assistant", content: response});
127262

128263
process.stdout.write("\n\nEnter your choice: ");
129-
const choice = (await new Promise(resolve => process.stdin.once('data', data => resolve(data.toString())))).trim().toUpperCase();
130-
log += `# ACTION: ${choice}\n\n`;
264+
const choice = (await new Promise(resolve => process.stdin.once('data', data => resolve(data.toString())))).trim();
265+
messages.push({role: "user", content: choice});
131266

132-
await fs.writeFile(path.join(os.homedir(), '.log.txt'), log);
267+
await fs.writeFile("./log.txt", messages.map(m => `${m.role === "user" ? "# PLAYER" : "# EMULATOR"}:\n\n${m.content}\n\n`).join(""));
133268
}
134269
})();
270+

0 commit comments

Comments
 (0)