diff --git a/bots/andy/assist.json b/bots/andy/assist.json index eb47577..680b4be 100644 --- a/bots/andy/assist.json +++ b/bots/andy/assist.json @@ -2,6 +2,5 @@ "name": "andy", "bio": "You are playing minecraft and assisting other players in tasks.", "memory": "", - "goals": [], "turns": [] } \ No newline at end of file diff --git a/bots/andy/survive.json b/bots/andy/survive.json deleted file mode 100644 index 4f34cc1..0000000 --- a/bots/andy/survive.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "andy", - "bio": "You are playing minecraft and assisting other players in tasks.", - "memory": "", - "goals": [ - "wooden_pickaxe", - "torch", - "stone_pickaxe", - "stone_sword", - "leather_chestplate", - "iron_pickaxe", - "iron_sword", - "iron_helmet", - "iron_boots", - "iron_leggings", - "iron_chestplate" - ], - "turns": [] -} \ No newline at end of file diff --git a/src/agent/agent.js b/src/agent/agent.js index 37d81e8..680bf93 100644 --- a/src/agent/agent.js +++ b/src/agent/agent.js @@ -4,7 +4,7 @@ import { Prompter } from './prompter.js'; import { initModes } from './modes.js'; import { initBot } from '../utils/mcdata.js'; import { containsCommand, commandExists, executeCommand, truncCommandMessage } from './commands/index.js'; -import { ItemGoal } from './item_goal.js'; +import { NPCContoller } from './npc/controller.js'; export class Agent { @@ -13,13 +13,12 @@ export class Agent { this.name = this.prompter.getName(); this.history = new History(this); this.coder = new Coder(this); - this.item_goal = new ItemGoal(this); + this.npc = new NPCContoller(this); await this.prompter.initExamples(); if (load_mem) this.history.load(); - this.item_goal.setGoals(this.history.goals); console.log('Logging in...'); this.bot = initBot(this.name); @@ -178,20 +177,13 @@ export class Agent { }); this.bot.on('idle', async () => { - // Resume all paused modes this.bot.modes.unPauseAll(); - - // Wait a while for inputs before acting independently - await new Promise((resolve) => setTimeout(resolve, 2000)); - if (!this.isIdle()) return; - - // Resume behavior or persue goal - if (this.coder.resume_func != null) - this.coder.executeResume(); - else - this.item_goal.executeNext(); + this.coder.executeResume(); }); + // Init NPC controller + this.npc.init(); + // This update loop ensures that each update() is called one at a time, even if it takes longer than the interval const INTERVAL = 300; setTimeout(async () => { diff --git a/src/agent/history.js b/src/agent/history.js index a55a0db..09479a5 100644 --- a/src/agent/history.js +++ b/src/agent/history.js @@ -1,4 +1,5 @@ -import { writeFileSync, readFileSync, mkdirSync } from 'fs'; +import { writeFileSync, readFileSync } from 'fs'; +import { NPCData } from './npc/data.js'; export class History { @@ -10,7 +11,6 @@ export class History { // These define an agent's long term memory this.memory = ''; - this.goals = []; // Variables for controlling the agent's memory and knowledge this.max_messages = 20; @@ -51,9 +51,10 @@ export class History { let data = { 'name': this.name, 'memory': this.memory, - 'goals': this.goals, 'turns': this.turns }; + if (this.agent.npc.data !== null) + data.npc = this.agent.npc.data.toObject(); const json_data = JSON.stringify(data, null, 4); writeFileSync(this.memory_fp, json_data, (err) => { if (err) { @@ -69,8 +70,8 @@ export class History { const data = readFileSync(this.memory_fp, 'utf8'); const obj = JSON.parse(data); this.memory = obj.memory; + this.agent.npc.data = NPCData.fromObject(obj.npc); this.turns = obj.turns; - this.goals = obj.goals; } catch (err) { console.error(`No memory file '${this.memory_fp}' for agent ${this.name}.`); } diff --git a/src/agent/npc/controller.js b/src/agent/npc/controller.js new file mode 100644 index 0000000..c8649ff --- /dev/null +++ b/src/agent/npc/controller.js @@ -0,0 +1,26 @@ +import { NPCData } from './data.js'; +import { ItemGoal } from './item_goal.js'; + + +export class NPCContoller { + constructor(agent) { + this.agent = agent; + this.data = NPCData.fromObject(agent.prompter.prompts.npc); + this.item_goal = new ItemGoal(agent); + } + + init() { + if (this.data === null) return; + this.item_goal.setGoals(this.data.goals); + + this.agent.bot.on('idle', async () => { + // Wait a while for inputs before acting independently + await new Promise((resolve) => setTimeout(resolve, 2000)); + if (!this.agent.isIdle()) return; + + // Persue goal + if (this.agent.coder.resume_func === null) + this.item_goal.executeNext(); + }); + } +} \ No newline at end of file diff --git a/src/agent/npc/data.js b/src/agent/npc/data.js new file mode 100644 index 0000000..b0425de --- /dev/null +++ b/src/agent/npc/data.js @@ -0,0 +1,18 @@ +export class NPCData { + constructor() { + this.goals = []; + } + + toObject() { + return { + goals: this.goals + } + } + + static fromObject(obj) { + if (!obj) return null; + let npc = new NPCData(); + npc.goals = obj.goals; + return npc; + } +} \ No newline at end of file diff --git a/src/agent/item_goal.js b/src/agent/npc/item_goal.js similarity index 98% rename from src/agent/item_goal.js rename to src/agent/npc/item_goal.js index 3c15ccf..9b03964 100644 --- a/src/agent/item_goal.js +++ b/src/agent/npc/item_goal.js @@ -1,6 +1,6 @@ -import * as skills from './library/skills.js'; -import * as world from './library/world.js'; -import * as mc from '../utils/mcdata.js'; +import * as skills from '../library/skills.js'; +import * as world from '../library/world.js'; +import * as mc from '../../utils/mcdata.js'; const blacklist = [