Skip to main content
Glama
autonomous-creator.ts14.1 kB
import * as path from "path"; import { createNewProject } from "./game-creation-tools.js"; import { generateAndImplementScenario, type ScenarioGenerationRequest } from "./scenario-generation.js"; import { generateAndImplementBattleSystem, type BattleSystemConfig } from "./battle-system.js"; import { generateQuestSystem, type Quest } from "./quest-system.js"; import { generateAssetBatch, type AssetGenerationRequest } from "./asset-generation.js"; import { autoBalanceStats } from "./stat-balancer.js"; import { optimizeAssets, type OptimizationOptions, getProjectSize } from "./asset-optimizer.js"; export interface AutonomousCreationRequest { projectPath: string; concept: string; gameTitle?: string; length?: "short" | "medium" | "long"; difficulty?: "easy" | "normal" | "hard"; generateAssets?: boolean; assetCount?: { characters?: number; enemies?: number; tilesets?: number; }; optimize?: boolean; } export interface AutonomousCreationResult { success: boolean; projectPath?: string; steps?: { step: string; status: "success" | "failed" | "skipped"; details?: any; error?: string; }[]; error?: string; summary?: { totalMaps: number; totalActors: number; totalEnemies: number; totalEvents: number; totalQuests: number; assetsGenerated: number; projectSize?: string; estimatedPlaytime?: string; }; } export async function createGameAutonomously(request: AutonomousCreationRequest): Promise<AutonomousCreationResult> { const steps: AutonomousCreationResult["steps"] = []; const startTime = Date.now(); try { console.log(`🤖 Starting autonomous game creation: "${request.concept}"`); console.log(`📁 Project path: ${request.projectPath}`); // Step 1: Create Project console.log("\n📦 Step 1/8: Creating project..."); try { const gameTitle = request.gameTitle || extractTitleFromConcept(request.concept); await createNewProject(request.projectPath, gameTitle); steps.push({ step: "Project Creation", status: "success", details: { gameTitle, projectPath: request.projectPath } }); console.log(`✅ Project created: ${gameTitle}`); } catch (error) { steps.push({ step: "Project Creation", status: "failed", error: error instanceof Error ? error.message : String(error) }); throw error; } // Step 2: Analyze concept and determine game parameters console.log("\n🧠 Step 2/8: Analyzing concept and planning game..."); const gameParams = analyzeConceptAndPlan(request); steps.push({ step: "Concept Analysis", status: "success", details: gameParams }); console.log(`✅ Game parameters determined:`, gameParams); // Step 3: Generate scenario console.log("\n📖 Step 3/8: Generating scenario..."); try { const scenarioRequest: ScenarioGenerationRequest = { projectPath: request.projectPath, theme: request.concept, style: gameParams.style, length: request.length || "medium" }; const scenarioResult = await generateAndImplementScenario(scenarioRequest); const mapsCount = scenarioResult.scenario?.maps?.length || 0; const actorsCount = scenarioResult.scenario?.characters?.length || 0; steps.push({ step: "Scenario Generation", status: "success", details: { maps: mapsCount, actors: actorsCount, events: 0 } }); console.log(`✅ Scenario generated: ${mapsCount} maps, ${actorsCount} actors`); } catch (error) { steps.push({ step: "Scenario Generation", status: "failed", error: error instanceof Error ? error.message : String(error) }); console.log(`⚠️ Scenario generation failed: ${error instanceof Error ? error.message : String(error)}`); } // Step 4: Generate battle system console.log("\n⚔️ Step 4/8: Generating battle system..."); try { const battleRequest: BattleSystemConfig = { projectPath: request.projectPath, difficulty: request.difficulty || "normal", battleType: gameParams.battleType, enemyCount: gameParams.enemyCount }; const battleResult = await generateAndImplementBattleSystem(battleRequest); const enemiesCount = battleResult.battleSystem?.enemies?.length || 0; const troopsCount = battleResult.battleSystem?.troops?.length || 0; const skillsCount = battleResult.battleSystem?.skills?.length || 0; steps.push({ step: "Battle System Generation", status: "success", details: { enemies: enemiesCount, troops: troopsCount, skills: skillsCount } }); console.log(`✅ Battle system generated: ${enemiesCount} enemies, ${troopsCount} troops`); } catch (error) { steps.push({ step: "Battle System Generation", status: "failed", error: error instanceof Error ? error.message : String(error) }); console.log(`⚠️ Battle system generation failed: ${error instanceof Error ? error.message : String(error)}`); } // Step 5: Generate quest system console.log("\n🎯 Step 5/8: Generating quest system..."); try { const questResult = await generateQuestSystem( request.projectPath, gameParams.questCount, request.concept ); const questCount = questResult.quests?.length || 0; steps.push({ step: "Quest System Generation", status: "success", details: { quests: questCount } }); console.log(`✅ Quest system generated: ${questCount} quests`); } catch (error) { steps.push({ step: "Quest System Generation", status: "failed", error: error instanceof Error ? error.message : String(error) }); console.log(`⚠️ Quest system generation failed: ${error instanceof Error ? error.message : String(error)}`); } // Step 6: Generate assets if (request.generateAssets !== false) { console.log("\n🎨 Step 6/8: Generating game assets..."); try { const assetRequests = prepareAssetRequests(request); const assetResults = await generateAssetBatch(assetRequests); const successCount = assetResults.filter(r => r.success).length; steps.push({ step: "Asset Generation", status: "success", details: { assetsGenerated: successCount, totalRequested: assetRequests.length } }); console.log(`✅ Assets generated: ${successCount}/${assetRequests.length}`); } catch (error) { steps.push({ step: "Asset Generation", status: "failed", error: error instanceof Error ? error.message : String(error) }); console.log(`⚠️ Asset generation failed: ${error instanceof Error ? error.message : String(error)}`); } } else { steps.push({ step: "Asset Generation", status: "skipped", details: { reason: "Asset generation disabled" } }); console.log("⏭️ Asset generation skipped"); } // Step 7: Balance stats console.log("\n⚖️ Step 7/8: Balancing game stats..."); try { const balanceResult = await autoBalanceStats( request.projectPath, request.difficulty || "normal" ); steps.push({ step: "Stat Balancing", status: "success", details: balanceResult }); console.log(`✅ Stats balanced`); } catch (error) { steps.push({ step: "Stat Balancing", status: "failed", error: error instanceof Error ? error.message : String(error) }); console.log(`⚠️ Stat balancing failed: ${error instanceof Error ? error.message : String(error)}`); } // Step 8: Optimize if (request.optimize !== false) { console.log("\n🚀 Step 8/8: Optimizing project..."); try { const optimizeRequest: OptimizationOptions = { projectPath: request.projectPath, assetTypes: ["all"], quality: 85, removeUnused: true }; const optimizeResult = await optimizeAssets(optimizeRequest); steps.push({ step: "Project Optimization", status: "success", details: optimizeResult }); console.log(`✅ Project optimized`); } catch (error) { steps.push({ step: "Project Optimization", status: "failed", error: error instanceof Error ? error.message : String(error) }); console.log(`⚠️ Optimization failed: ${error instanceof Error ? error.message : String(error)}`); } } else { steps.push({ step: "Project Optimization", status: "skipped", details: { reason: "Optimization disabled" } }); console.log("⏭️ Optimization skipped"); } // Final Analysis console.log("\n📊 Analyzing final project..."); const projectSize = await getProjectSize(request.projectPath); const summary = { totalMaps: 0, // Would need to count from MapInfos.json totalActors: 0, totalEnemies: 0, totalEvents: 0, totalQuests: steps.find(s => s.step === "Quest System Generation")?.details?.quests || 0, assetsGenerated: steps.find(s => s.step === "Asset Generation")?.details?.assetsGenerated || 0, projectSize: formatBytes(projectSize.totalSize || 0), estimatedPlaytime: estimatePlaytime(request.length || "medium") }; const elapsedTime = ((Date.now() - startTime) / 1000).toFixed(1); console.log("\n🎉 ========================================"); console.log("🎉 GAME CREATION COMPLETE!"); console.log("🎉 ========================================"); console.log(`\n⏱️ Time taken: ${elapsedTime}s`); console.log(`\n📊 Summary:`); console.log(` 🗺️ Maps: ${summary.totalMaps}`); console.log(` 👤 Actors: ${summary.totalActors}`); console.log(` 👹 Enemies: ${summary.totalEnemies}`); console.log(` 📍 Events: ${summary.totalEvents}`); console.log(` 🎯 Quests: ${summary.totalQuests}`); console.log(` 🎨 Assets: ${summary.assetsGenerated}`); console.log(` 💾 Size: ${summary.projectSize}`); console.log(` ⏳ Playtime: ${summary.estimatedPlaytime}`); console.log(`\n📂 Project: ${request.projectPath}`); console.log(`\n✅ Open with RPG Maker MZ: ${path.join(request.projectPath, "Game.rpgproject")}`); return { success: true, projectPath: request.projectPath, steps, summary }; } catch (error) { console.log("\n❌ Game creation failed!"); return { success: false, error: error instanceof Error ? error.message : String(error), steps }; } } function extractTitleFromConcept(concept: string): string { // Simple title extraction from concept const words = concept.split(" ").slice(0, 3); return words.map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(" "); } function analyzeConceptAndPlan(request: AutonomousCreationRequest): any { const concept = request.concept.toLowerCase(); // Determine game style let style = "adventure"; if (concept.includes("epic") || concept.includes("grand") || concept.includes("legend")) { style = "epic"; } else if (concept.includes("dark") || concept.includes("horror") || concept.includes("mystery")) { style = "dark"; } else if (concept.includes("comedy") || concept.includes("funny") || concept.includes("humor")) { style = "comedy"; } else if (concept.includes("simple") || concept.includes("casual")) { style = "simple"; } // Determine battle type let battleType = "traditional"; if (concept.includes("tactical") || concept.includes("strategy")) { battleType = "tactical"; } else if (concept.includes("fast") || concept.includes("action")) { battleType = "fast-paced"; } // Determine content amounts based on length const length = request.length || "medium"; let enemyCount = 10; let questCount = 5; if (length === "short") { enemyCount = 5; questCount = 3; } else if (length === "long") { enemyCount = 20; questCount = 10; } return { style, battleType, enemyCount, questCount }; } function prepareAssetRequests(request: AutonomousCreationRequest): AssetGenerationRequest[] { const concept = request.concept; const assetCount = request.assetCount || {}; const requests: AssetGenerationRequest[] = []; // Characters const characterCount = assetCount.characters || 3; for (let i = 0; i < characterCount; i++) { requests.push({ projectPath: request.projectPath, assetType: "character", prompt: `${concept} character ${i + 1}, RPG sprite sheet`, filename: `Character${i + 1}.png` }); } // Enemies const enemyCount = assetCount.enemies || 5; for (let i = 0; i < enemyCount; i++) { requests.push({ projectPath: request.projectPath, assetType: "enemy", prompt: `${concept} enemy ${i + 1}, monster sprite`, filename: `Enemy${i + 1}.png` }); } // Tilesets const tilesetCount = assetCount.tilesets || 1; for (let i = 0; i < tilesetCount; i++) { requests.push({ projectPath: request.projectPath, assetType: "tileset", prompt: `${concept} themed tileset`, filename: `Tileset${i + 1}.png` }); } return requests; } function formatBytes(bytes: number): string { if (bytes === 0) return "0 Bytes"; const k = 1024; const sizes = ["Bytes", "KB", "MB", "GB"]; const i = Math.floor(Math.log(bytes) / Math.log(k)); return Math.round(bytes / Math.pow(k, i) * 100) / 100 + " " + sizes[i]; } function estimatePlaytime(length: string): string { switch (length) { case "short": return "1-2 hours"; case "medium": return "3-5 hours"; case "long": return "8-12 hours"; default: return "3-5 hours"; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ShunsukeHayashi/rpgmaker-mz-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server