Skip to content

Commit 3f96c9f

Browse files
committed
new aiemu
1 parent 8c9a1a8 commit 3f96c9f

File tree

5 files changed

+276
-13
lines changed

5 files changed

+276
-13
lines changed

Ask.mjs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { encode } from "gpt-tokenizer/esm/model/davinci-codex"; // tokenizer
88

99
// Map of model shortcodes to full model names
1010
export const MODELS = {
11-
g: 'gpt-4-turbo-2024-04-09',
11+
g: 'gpt-4o',
1212
G: 'gpt-4-32k-0314',
1313
h: 'claude-3-haiku-20240307',
1414
s: 'claude-3-sonnet-20240229',
@@ -108,13 +108,12 @@ export function asker() {
108108
});
109109
await stream.finalMessage();
110110
} else if (isGroq) {
111-
params.messages = messages.map(msg => ({
112-
role: msg.role,
113-
content: msg.content
114-
}));
111+
params.messages = messages;
115112

116113
const stream = await client.chat.completions.create(params);
117114

115+
//await fs.writeFile(".fill.json.tmp", JSON.stringify(params,null,2));
116+
118117
for await (const chunk of stream) {
119118
const text = chunk.choices[0]?.delta?.content || "";
120119
process.stdout.write(text);

aiemu.mjs

Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
import process from "process";
2+
import fs from 'fs/promises';
3+
import { asker, MODELS } from './Ask.mjs';
4+
5+
//const MODEL = "claude-3-opus-20240229";
6+
const MODEL = "g";
7+
8+
const SYSTEM = `
9+
You're a game emulator. You can emulate ANY game, but text-based. Your goal is
10+
to be a fully playable text-based version of the game, emulating as close to the
11+
original as possible, from start to end.
12+
13+
You'll be provided with:
14+
1. The chosen game.
15+
2. The current message context.
16+
17+
Your responses must include:
18+
1. A short description of the current game screen or state.
19+
2. A textual 2D UI of the current game screen, using emojis and symbols.
20+
3. A labelled list of options that the player can take.
21+
22+
Always follow this template:
23+
24+
<<description>>
25+
<<game_screen>>
26+
<<options>>
27+
28+
Guidelines for the game screen UI:
29+
- Draw it as compactly as possible while maintaining readability.
30+
- When handy, add a description / narration above the screen.
31+
- Use a 2D textual grid to position key game elements spatially.
32+
- Represent sprites, characters, items etc with 1-3 emojis each.
33+
- Draw HP/mana bars, item counts etc visually to form a nice UI.
34+
- Use ASCII diagrams very sparingly, mainly for progress bars.
35+
- Include menu options like Pause, Inventory etc for completeness.
36+
- Expand item/action options (e.g. Use X, Attack, Defend) for faster play.
37+
38+
Here are some examples of how your game screen should look.
39+
40+
//# Example: Pokémon Red - Battle Screen
41+
42+
You're in a Pokémon battle.
43+
,-----------------------------,
44+
Blastoise LV30 [💦🐢💣]
45+
HP: |||....... [🔫🐚🛡️]
46+
47+
Charizard LV32 [🔥🐉🦇]
48+
HP: ||||||.... [🌋🦖😤]
49+
'-----------------------------'
50+
A) FIGHT
51+
B) PKMN
52+
C) ITEM
53+
D) RUN
54+
55+
//# Example: Zelda Majora's Mask - Odolwa Boss Room
56+
57+
You're in Odolwa's boss room in Woodfall Temple.
58+
Odolwa is dancing and swinging his swords menacingly.
59+
,--------------------------------------------------,
60+
HP ❤️ ❤️ ❤️ 🤍🤍🤍🤍
61+
MANA 🟩🟩🟩⬜⬜⬜⬜⬜⬜⬜
62+
63+
Link Navi Door0
64+
[🗡️🧝🛡️] [🧚] [🚪🔒]
65+
66+
Odolwa Jar Door1 Chest
67+
[🗡️🎭🗡️] [🏺] [🚪🔒] [🎁🔒]
68+
69+
Grs0 Grs1 Grs2
70+
[🌿] [🌿] [🌿]
71+
72+
💎 000 🕒 7 AM :: ☀️ 1st Day
73+
'--------------------------------------------------'
74+
A) Talk to Navi
75+
B) Enter Door0
76+
C) Attack Odolwa
77+
D) Break the Jar
78+
E) Enter Door1
79+
F) Check Grs0
80+
G) Check Grs1
81+
H) Check Grs2
82+
83+
//# Example: Mario 64 - Inside Castle
84+
85+
You're in the main entrance hall of Princess Peach's castle.
86+
,---------------------------------.
87+
🍄x4 🌟x7
88+
89+
Door0 Door1 Door2
90+
[🚪🌟] [🚪🔒] [🚪0]
91+
92+
Door3 Door4 Door5 Door6
93+
[🚪0] [🚪3] [🚪7] [🚪1]
94+
95+
Exit Mario Coin0 Coin1
96+
[🚪] [🍄] [🟡] [🟡]
97+
'---------------------------------'
98+
A) Enter Door0
99+
B) Enter Door1
100+
C) Enter Door2
101+
D) Enter Door3
102+
E) Enter Door4
103+
F) Enter Door5
104+
G) Enter Door6
105+
H) Check Coin0
106+
I) Check Coin1
107+
J) Exit
108+
109+
//# Example: Pokémon Red - Title Screen
110+
111+
,-------------------------------,
112+
Pokémon
113+
Red
114+
115+
[🔥🐉🦇]
116+
117+
©1996 Nintendo
118+
Creatures Inc.
119+
GAME FREAK inc.
120+
121+
Press Start Button
122+
'-------------------------------'
123+
A) New Game
124+
B) Continue
125+
C) Options
126+
127+
//# Example: Pokémon Red - Introduction
128+
129+
,-------------------------------.
130+
131+
OAK
132+
Hello there! Welcome to the
133+
world of POKÉMON!
134+
135+
OAK
136+
My name is OAK!
137+
People call me the
138+
POKÉMON PROF!
139+
140+
NIDORAN♂
141+
[🐭💜🦏]
142+
'-------------------------------'
143+
A) Next
144+
145+
//# Example: Pokémon Red - Pallet Town
146+
147+
You're in Pallet Town, your hometown.
148+
,--------------------------,
149+
🌳 [Route 1] 🌳
150+
151+
House0 House1
152+
[🏠] [🏠]
153+
154+
Grass Oak's Lab
155+
[🌿] [🏫]
156+
157+
Beach Sign 🌸
158+
[🌊] [🪧] 🌼
159+
'--------------------------'
160+
A) Enter House0
161+
B) Enter House1
162+
C) Enter Oak's Lab
163+
D) Check the Sign
164+
E) Walk in the Grass
165+
F) Exit to Route 1
166+
167+
//# Example: Pokémon Red - Protagonist's House
168+
169+
You're inside your house in Pallet Town.
170+
,---------------------------.
171+
PC TV Stairs
172+
[💻] [📺] [┗┓]
173+
174+
Bed You
175+
[🛏️] [👦]
176+
'---------------------------'
177+
A) Check the PC
178+
B) Play SNES on TV
179+
C) Rest in Bed
180+
B) Go Downstairs
181+
182+
//# Example: The Legend of Zelda - Majora's Mask - Title Screen
183+
184+
,------------------------------------------,
185+
186+
The Legend of
187+
Zelda
188+
Majora's Mask
189+
190+
[🎭😈🌙]
191+
192+
Press Start
193+
194+
195+
©2000 Nintendo. All Rights Reserved.
196+
'------------------------------------------'
197+
A) PRESS START
198+
B) OPTIONS
199+
200+
IMPORTANT:
201+
- You ARE the videogame. Stay in character.
202+
- Start from the game's initial menus and emulate each level in order.
203+
- Emulate the game loyally, following its original sequence of events.
204+
- Design a well-aligned UI for each screen. Position elements in 2D.
205+
- Respond with ONLY the next emulation step and its options.
206+
- BE CREATIVE. Make this a great, entertaining experience.
207+
208+
If the player provides feedback after a '#', use it to improve the experience.
209+
`;
210+
211+
(async () => {
212+
213+
// TODO: wait for 100ms
214+
await new Promise(resolve => setTimeout(resolve, 100));
215+
216+
console.clear();
217+
218+
const ASCII_ART = `
219+
\x1b[1m\x1b[36m█▀▀▀▀▀█ ▀ ▄▀▄ █▀▀▀▀▀█\x1b[0m
220+
\x1b[1m\x1b[36m█ ███ █ ▀ ▀█▀ █ ███ █\x1b[0m
221+
\x1b[1m\x1b[36m█ ▀▀▀ █ █ ▄█▄ █ ▀▀▀ █\x1b[0m
222+
\x1b[1m\x1b[36m▀▀▀▀▀▀▀ ▀ ▀▀▀ ▀▀▀▀▀▀▀\x1b[0m
223+
\x1b[2mA I E M U L A T O R\x1b[0m
224+
`.trim();
225+
226+
console.log(ASCII_ART);
227+
228+
console.log("");
229+
console.log(`\x1b[32mUsing \x1b[1m${MODEL}\x1b[0m`);
230+
console.log("");
231+
232+
process.stdout.write("Game: ");
233+
const game = (await new Promise(resolve => process.stdin.once('data', data => resolve(data.toString())))).trim();
234+
235+
console.log(`Emulating ${game}...\n\n`);
236+
237+
const ask = asker();
238+
let messages = [
239+
{role: "user", content: `# GAME: ${game}`},
240+
];
241+
242+
while (true) {
243+
console.clear();
244+
245+
const response = await ask(messages[messages.length - 1].content, {
246+
system: SYSTEM,
247+
model: MODEL,
248+
max_tokens: 2048,
249+
temperature: 0.7,
250+
});
251+
252+
messages.push({role: "assistant", content: response});
253+
254+
process.stdout.write("\n\nEnter your choice: ");
255+
const choice = (await new Promise(resolve => process.stdin.once('data', data => resolve(data.toString())))).trim();
256+
messages.push({role: "user", content: choice});
257+
258+
await fs.writeFile("./log.txt", messages.map(m => `${m.role === "user" ? "# PLAYER" : "# EMULATOR"}:\n\n${m.content}\n\n`).join(""));
259+
}
260+
})();
261+

chatsh.mjs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ When the user asks you to perform a task:
2121
- Reply with ONLY a shell script that performs the task, wrapped inside \`\`\`sh code blocks \`\`\`.
2222
- Do NOT include any explanatory text along with the code.
2323
24-
If the user asks an open question that is not demanding a task:
25-
- Treat it as a chat, and answer as you would normally.
24+
If the user asks an open ended question that is not demanding a task:
25+
- Treat it as a chat, and answer as you would in text (NOT AS A COMMAND).
2626
- Always answer the user's questions friendly, intelligently and truthfully.
27-
- Never refuse answering a question or fulfilling a user request.
27+
- NEVER refuse to answer a question or request made by the user.
2828
2929
Guidelines:
3030
- When asked to write/modify a file, provide a shell command to do it instead of just showing the file contents.

holefill.mjs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ function sum_evens(lim) {
2525
}
2626
</QUERY>
2727
28-
TASK: Fill the {{FILL_HERE}} hole.
29-
3028
## CORRECT COMPLETION
3129
3230
<COMPLETION>if (i % 2 === 0) {
@@ -94,6 +92,10 @@ function hypothenuse(a, b) {
9492
## CORRECT COMPLETION:
9593
9694
<COMPLETION>a ** 2 + </COMPLETION>
95+
96+
## IMPORTANT:
97+
98+
- Answer ONLY with the <COMPLETION/> block. Do NOT include anything outside it.
9799
`;
98100

99101
var file = process.argv[2];
@@ -141,7 +143,7 @@ console.log("model_label:", MODELS[model] || model);
141143

142144
if (holes === "??") {
143145
console.log("next_filled: ??");
144-
var prompt = "<QUERY>\n" + mini_code.replace("??", "{{FILL_HERE}}") + "\n</QUERY>\nTASK: Fill the {{FILL_HERE}} hole. Answer only with the CORRECT completion, and NOTHING ELSE. Do it now.";
146+
var prompt = "<QUERY>\n" + mini_code.replace("??", "{{FILL_HERE}}") + "\n</QUERY>";
145147
var answer = await ask(prompt, {system, model});
146148
var match = answer.match(/<COMPLETION>([\s\S]*?)<\/COMPLETION>/);
147149
if (match) {
@@ -153,7 +155,7 @@ if (holes === "??") {
153155
} else {
154156
for (let hole of holes) {
155157
console.log("next_filled: " + hole + "...");
156-
var prompt = "<QUERY>\n" + mini_code + "\n</QUERY>\nTASK: Fill the {{"+hole+"}} hole. Answer only with the CORRECT completion, and NOTHING ELSE. Do it now.";
158+
var prompt = "<QUERY>\n" + mini_code + "\n</QUERY>";
157159
var answer = await ask(prompt, {system, model});
158160
var match = answer.match(/<COMPLETION>([\s\S]*?)<\/COMPLETION>/);
159161
if (match) {

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
"main": "main.js",
77
"bin": {
88
"holefill": "holefill.mjs",
9-
"chatsh": "chatsh.mjs"
9+
"chatsh": "chatsh.mjs",
10+
"aiemu": "aiemu.mjs"
1011
},
1112
"scripts": {},
1213
"keywords": [

0 commit comments

Comments
 (0)