cleanup everything lol
This commit is contained in:
@@ -62,15 +62,15 @@ async function callOllama(prompt, model = "gemma3n:e4b", retries = 5, stepName =
|
||||
|
||||
function parseList(raw) {
|
||||
return raw
|
||||
.split(/\n|(?=\d+[).]\s)/g)
|
||||
.map(line => cleanText(line.replace(/^\d+[).\s-]*/, "")))
|
||||
.split(/\n?\d+[).]\s+/)
|
||||
.map(line => cleanText(line))
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
function parseObjects(raw, type = "rooms") {
|
||||
return raw
|
||||
.split("\n")
|
||||
.map(line => cleanText(line.replace(/^\d+[).\s-]*/, "")))
|
||||
.split(/\n?\d+[).]\s+/)
|
||||
.map(entry => cleanText(entry))
|
||||
.filter(Boolean)
|
||||
.map(entry => {
|
||||
const [name, ...descParts] = entry.split(/[-–—:]/);
|
||||
@@ -97,7 +97,7 @@ Each title should come from a different style or theme. Make the set varied and
|
||||
- Weird fantasy: uncanny, surreal, unsettling
|
||||
- Whimsical: fun, quirky, playful
|
||||
|
||||
Avoid repeating materials or adjectives. Do not include explanations, markdown, or preambles. Only the 10 numbered titles.`,
|
||||
Avoid repeating materials or adjectives. Avoid the words "obsidian" and "clockwork". Do not include explanations, markdown, or preambles. Only the 10 numbered titles.`,
|
||||
undefined, 5, "Step 1: Titles"
|
||||
);
|
||||
const titles10 = parseList(titles10Raw, 30);
|
||||
@@ -108,7 +108,7 @@ Avoid repeating materials or adjectives. Do not include explanations, markdown,
|
||||
`Here are 10 dungeon titles:
|
||||
${titles10.join("\n")}
|
||||
|
||||
Select the 3 most interesting titles from the above list and create 2 additional unique titles.
|
||||
Randomly select 3 of the titles from the above list and create 2 additional unique titles. Avoid the words "obsidian" and "clockwork".
|
||||
Output exactly 5 titles as a numbered list, plain text only. No explanations.`,
|
||||
undefined, 5, "Step 2: Narrow Titles"
|
||||
);
|
||||
@@ -117,7 +117,7 @@ Output exactly 5 titles as a numbered list, plain text only. No explanations.`,
|
||||
|
||||
// --- Step 3: Final title ---
|
||||
const bestTitleRaw = await callOllama(
|
||||
`From the following 5 dungeon titles, select the one that sounds the most fun to play.
|
||||
`From the following 5 dungeon titles, randomly select only one of them.
|
||||
Output only the title, no explanation, no numbering, no extra text:
|
||||
|
||||
${titles5.join("\n")}`,
|
||||
@@ -129,7 +129,7 @@ ${titles5.join("\n")}`,
|
||||
// --- Step 4: Flavor text ---
|
||||
const flavorRaw = await callOllama(
|
||||
`Write a single evocative paragraph describing the dungeon titled "${title}".
|
||||
Do not include hooks, NPCs, treasure, or instructions. Output plain text only, one paragraph.`,
|
||||
Do not include hooks, NPCs, treasure, or instructions. Output plain text only, one paragraph. Maximum 4 sentences.`,
|
||||
undefined, 5, "Step 4: Flavor"
|
||||
);
|
||||
const flavor = flavorRaw;
|
||||
@@ -141,40 +141,23 @@ Do not include hooks, NPCs, treasure, or instructions. Output plain text only, o
|
||||
|
||||
${flavor}
|
||||
|
||||
Generate 3 adventure hooks (one sentence each) and 3 rumors (one sentence each).
|
||||
Output numbered lists only, plain text. Maximum 120 characters per item. No explanations or extra text.
|
||||
Format as:
|
||||
|
||||
Hooks:
|
||||
1. ...
|
||||
2. ...
|
||||
3. ...
|
||||
|
||||
Rumors:
|
||||
1. ...
|
||||
2. ...
|
||||
3. ...`
|
||||
,
|
||||
Generate 3 short adventure hooks or rumors (mix them naturally).
|
||||
Output as a single numbered list, plain text only.
|
||||
Maximum 2 sentences per item. No explanations or extra text.`,
|
||||
undefined, 5, "Step 5: Hooks & Rumors"
|
||||
);
|
||||
const [hooksSection, rumorsSection] = hooksRumorsRaw.split(/Rumors[:\n]/i);
|
||||
const hooks = parseList(hooksSection.replace(/Hooks[:\n]*/i, ""), 120);
|
||||
const rumors = parseList(rumorsSection || "", 120);
|
||||
console.log("🔹 Hooks:", hooks);
|
||||
console.log("🔹 Rumors:", rumors);
|
||||
const hooksRumors = parseList(hooksRumorsRaw, 120);
|
||||
console.log("🔹 Hooks & Rumors:", hooksRumors);
|
||||
|
||||
// --- Step 6: Rooms & Encounters ---
|
||||
const roomsEncountersRaw = await callOllama(
|
||||
`Using the flavor, hooks, and rumors:
|
||||
`Using the flavor and these hooks/rumors:
|
||||
|
||||
Flavor:
|
||||
${flavor}
|
||||
|
||||
Hooks:
|
||||
${hooks.join("\n")}
|
||||
|
||||
Rumors:
|
||||
${rumors.join("\n")}
|
||||
Hooks & Rumors:
|
||||
${hooksRumors.join("\n")}
|
||||
|
||||
Generate 5 rooms (name + short description) and 3 encounters (name + details).
|
||||
Output two numbered lists, labeled "Rooms:" and "Encounters:". Plain text only. No extra explanation.`,
|
||||
@@ -197,11 +180,33 @@ Output numbered lists labeled "Treasure:" and "NPCs:". Plain text only, no extra
|
||||
undefined, 5, "Step 7: Treasure & NPCs"
|
||||
);
|
||||
const [treasureSection, npcsSection] = treasureNpcsRaw.split(/NPCs[:\n]/i);
|
||||
const treasure = parseList(treasureSection.replace(/Treasure[:\n]*/i, ""), 120);
|
||||
const treasure = parseList(treasureSection.replace(/Treasures?[:\n]*/i, ""), 120);
|
||||
const npcs = parseObjects(npcsSection || "", "npcs", 120);
|
||||
console.log("🔹 Treasure:", treasure);
|
||||
console.log("🔹 NPCs:", npcs);
|
||||
|
||||
// --- Step 8: Plot Resolutions ---
|
||||
const plotResolutionsRaw = await callOllama(
|
||||
`Based on the following dungeon flavor and story hooks:
|
||||
|
||||
Flavor:
|
||||
${flavor}
|
||||
|
||||
Hooks & Rumors:
|
||||
${hooksRumors.join("\n")}
|
||||
|
||||
Major NPCs / Encounters:
|
||||
${[...npcs.map(n => n.name), ...encounters.map(e => e.name)].join(", ")}
|
||||
|
||||
Suggest 3 possible, non-conflicting story climaxes or plot resolutions for adventurers exploring this dungeon.
|
||||
These are prompts and ideas for brainstorming the dungeon's ending, not fixed outcomes.
|
||||
Start each item with phrases like "The adventurers could..." or "The PCs might..." to emphasize their hypothetical nature.
|
||||
Keep each item short (max 2 sentences). Output as a numbered list, plain text only.`,
|
||||
undefined, 5, "Step 8: Plot Resolutions"
|
||||
);
|
||||
const plotResolutions = parseList(plotResolutionsRaw, 180);
|
||||
console.log("🔹 Plot Resolutions:", plotResolutions);
|
||||
|
||||
console.log("\n🎉 Dungeon generation complete!");
|
||||
return { title, flavor, map: "map.png", hooks, rumors, rooms, encounters, treasure, npcs };
|
||||
return { title, flavor, map: "map.png", hooksRumors, rooms, encounters, treasure, npcs, plotResolutions };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user