| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556 |
- import { yamlPrompt } from "@json-render/yaml";
- import { buildEditUserPrompt } from "@json-render/core";
- import type { Spec } from "@json-render/core";
- import { stringify } from "yaml";
- import { catalog } from "./catalog";
- const GAME_RULES = [
- "Use numeric values only (no Math.PI, use 3.14159)",
- "For GamePlane as ground: rotation [-1.5708, 0, 0], scale [size, size, 1]",
- "Use descriptive keys for new objects (e.g. 'obj-tree-1-trunk', 'obj-tree-1-canopy')",
- "Object element keys start with 'obj-'",
- "The root element 'scene' is a Group whose children lists all top-level element keys",
- "When adding an object: add the element AND append the key to the scene children",
- "COMPOSE objects into recognizable structures. TREE RECIPE: trunk = GameCylinder with radiusTop 0.12-0.2, radiusBottom 0.15-0.25, height 3-6, color '#8B4513' or '#5C3317', position Y = height/2. Canopy = GameSphere with radius 1.5-3, color '#228B22' or '#2E8B57', position Y = trunk height + canopy radius * 0.7. The trunk must be TALL and THIN (radius << height). HOUSE: GameBox walls (width 3, height 2.5, depth 3) + GameCone roof on top. LAMP: GameCylinder radiusTop 0.05, radiusBottom 0.05, height 3 + GameSphere radius 0.2 with emissive material at top. NEVER scatter disconnected primitives randomly.",
- "SPATIAL COHERENCE: related parts share the same X/Z base. Stack vertically with exact Y math: if trunk height=4, trunk Y=2 (half height). Canopy radius=2, canopy Y = 4 + 2*0.7 = 5.4. Objects that belong together must visually touch or overlap.",
- "Be AMBITIOUS and THOROUGH: when the user asks for something, go all-in — build 10-20+ composed structures with varied sizes, not just a handful of loose shapes",
- "REPEATING DETAILS: when placing repeating elements (road dashes, fence posts, windows, floor tiles, pillars, streetlights along a road), space them evenly and use ENOUGH to cover the full length/area. A 100-unit road needs 20+ dashes, not 5. A building face 10 units wide needs 4-5 windows per floor, not 1. Do NOT be lazy with repetition — density sells the scene.",
- "Always set castShadow on lights and objects, receiveShadow on ground/floors, and use materials with varied colors, metalness, roughness for visual richness",
- "When building environments, include atmosphere (Sky, Fog, ambient light), ground plane with receiveShadow, and decorative elements — make it feel like a complete, coherent scene",
- ];
- function serializeSpec(spec: Spec): string {
- return stringify(spec, { indent: 2, lineWidth: 0 });
- }
- export function generateSystemPrompt(): string {
- return yamlPrompt(catalog, {
- system:
- "You are an expert 3D level designer AI for a json-render game engine. You build rich, detailed, immersive scenes using YAML patch operations. When the user describes a scene or asks for changes, go big — create dense, visually interesting environments with many objects, proper lighting, shadows, physics, varied materials, and atmospheric effects. Think like a AAA game level designer, not a minimal prototype builder.",
- mode: "standalone",
- editModes: ["merge"],
- customRules: GAME_RULES,
- });
- }
- export function generateUserPrompt(
- userPrompt: string,
- currentSpec: Spec,
- previousPrompts: string[] = [],
- ): string {
- const prevContext =
- previousPrompts.length > 0
- ? `Previous instructions:\n${previousPrompts.join("\n")}\n\n`
- : "";
- return (
- prevContext +
- buildEditUserPrompt({
- prompt: userPrompt,
- currentSpec,
- config: { modes: ["merge"] },
- format: "yaml",
- serializer: serializeSpec,
- })
- );
- }
|