load goals, logic fixes

This commit is contained in:
Kolby Nottingham 2024-02-12 22:43:31 -08:00
parent 5a1e57bd42
commit 57783fb4ca
5 changed files with 89 additions and 58 deletions

View file

@ -2,5 +2,6 @@
"name": "andy", "name": "andy",
"bio": "You are playing minecraft and assisting other players in tasks.", "bio": "You are playing minecraft and assisting other players in tasks.",
"memory": "", "memory": "",
"goals": [],
"turns": [] "turns": []
} }

19
bots/andy/survive.json Normal file
View file

@ -0,0 +1,19 @@
{
"name": "andy",
"bio": "You are playing minecraft and assisting other players in tasks.",
"memory": "",
"goals": [
"wooden_pickaxe",
"torch",
"stone_pickaxe",
"stone_sword",
"leather_tunic",
"iron_pickaxe",
"iron_sword",
"iron_helmet",
"iron_boots",
"iron_leggings",
"iron_chestplate"
],
"turns": []
}

View file

@ -15,11 +15,11 @@ export class Agent {
this.history = new History(this); this.history = new History(this);
this.coder = new Coder(this); this.coder = new Coder(this);
this.item_goal = new ItemGoal(this); this.item_goal = new ItemGoal(this);
this.item_goal.setGoal('iron_pickaxe', 1);
console.log('Loading examples...'); console.log('Loading examples...');
this.history.load(profile); this.history.load(profile);
this.item_goal.setGoals(this.history.goals);
await this.examples.load('./src/examples.json'); await this.examples.load('./src/examples.json');
await this.coder.load(); await this.coder.load();

View file

@ -13,6 +13,7 @@ export class History {
// These define an agent's long term memory // These define an agent's long term memory
this.bio = ''; this.bio = '';
this.memory = ''; this.memory = '';
this.goals = [];
// Variables for controlling the agent's memory and knowledge // Variables for controlling the agent's memory and knowledge
this.max_messages = 20; this.max_messages = 20;
@ -88,6 +89,7 @@ export class History {
'name': this.name, 'name': this.name,
'bio': this.bio, 'bio': this.bio,
'memory': this.memory, 'memory': this.memory,
'goals': this.goals,
'turns': this.turns 'turns': this.turns
}; };
const json_data = JSON.stringify(data, null, 4); const json_data = JSON.stringify(data, null, 4);
@ -108,6 +110,7 @@ export class History {
this.bio = obj.bio; this.bio = obj.bio;
this.memory = obj.memory; this.memory = obj.memory;
this.turns = obj.turns; this.turns = obj.turns;
this.goals = obj.goals;
} catch (err) { } catch (err) {
console.error(`No file for profile '${load_path}' for agent ${this.name}.`); console.error(`No file for profile '${load_path}' for agent ${this.name}.`);
} }

View file

@ -18,10 +18,11 @@ class ItemNode {
setRecipe(recipe) { setRecipe(recipe) {
this.type = 'craft'; this.type = 'craft';
let size = 0; let size = 0;
this.recipe = [];
for (let [key, value] of Object.entries(recipe)) { for (let [key, value] of Object.entries(recipe)) {
if (this.manager.nodes[key] === undefined) if (this.manager.nodes[key] === undefined)
this.manager.nodes[key] = new ItemWrapper(this.manager, this.wrapper, key); this.manager.nodes[key] = new ItemWrapper(this.manager, this.wrapper, key);
this.recipe.push([this.manager.nodes[key], value]); this.recipe.push({node: this.manager.nodes[key], quantity: value});
size += value; size += value;
} }
if (size > 4) { if (size > 4) {
@ -64,21 +65,16 @@ class ItemNode {
} }
getChildren() { getChildren() {
let children = []; let children = [...this.recipe];
for (let child of this.recipe) { if (this.prereq) {
if (child[0] instanceof ItemWrapper && child[0].methods.length > 0) { children.push({node: this.prereq, quantity: 1});
children.push(child);
}
}
if (this.prereq && this.prereq instanceof ItemWrapper && this.prereq.methods.length > 0) {
children.push([this.prereq, 1]);
} }
return children; return children;
} }
isReady() { isReady() {
for (let [child, quantity] of this.getChildren()) { for (let child of this.getChildren()) {
if (!child.isDone(quantity)) { if (!child.node.isDone(child.quantity)) {
return false; return false;
} }
} }
@ -123,8 +119,8 @@ class ItemNode {
return 0; return 0;
} }
let depth = 0; let depth = 0;
for (let [child, quantity] of this.getChildren()) { for (let child of this.getChildren()) {
depth = Math.max(depth, child.getDepth(quantity)); depth = Math.max(depth, child.node.getDepth(child.quantity));
} }
return depth + 1; return depth + 1;
} }
@ -134,18 +130,19 @@ class ItemNode {
return 0; return 0;
} }
let fails = 0; let fails = 0;
for (let [child, quantity] of this.getChildren()) { for (let child of this.getChildren()) {
fails += child.getFails(quantity); fails += child.node.getFails(child.quantity);
} }
return fails + this.fails; return fails + this.fails;
} }
getNext() { getNext(q=1) {
if (this.isReady()) { if (this.isDone(q))
return null;
if (this.isReady())
return this; return this;
} for (let child of this.getChildren()) {
for (let [child, quantity] of this.getChildren()) { let res = child.node.getNext(child.quantity);
let res = child.getNext();
if (res) if (res)
return res; return res;
} }
@ -187,28 +184,37 @@ class ItemWrapper {
} }
} }
add_method(method) {
for (let child of method.getChildren()) {
if (child.node.methods.length === 0)
return;
}
this.methods.push(method);
}
createChildren() { createChildren() {
let recipes = mc.getItemCraftingRecipes(this.name); let recipes = mc.getItemCraftingRecipes(this.name);
if (recipes) { if (recipes) {
for (let recipe of recipes) { for (let recipe of recipes) {
this.methods.push(new ItemNode(this.manager, this, this.name).setRecipe(recipe)); this.add_method(new ItemNode(this.manager, this, this.name).setRecipe(recipe))
} }
} }
let block_source = mc.getItemBlockSource(this.name); let block_source = mc.getItemBlockSource(this.name);
if (block_source) { if (block_source) {
let tool = mc.getBlockTool(block_source); let tool = mc.getBlockTool(block_source);
this.methods.push(new ItemNode(this.manager, this, this.name).setCollectable(block_source, tool)); this.add_method(new ItemNode(this.manager, this, this.name).setCollectable(block_source, tool));
} }
let smeltingIngredient = mc.getItemSmeltingIngredient(this.name); let smeltingIngredient = mc.getItemSmeltingIngredient(this.name);
if (smeltingIngredient) { if (smeltingIngredient) {
this.methods.push(new ItemNode(this.manager, this, this.name).setSmeltable(smeltingIngredient)); this.add_method(new ItemNode(this.manager, this, this.name).setSmeltable(smeltingIngredient));
} }
let animal_source = mc.getItemAnimalSource(this.name); let animal_source = mc.getItemAnimalSource(this.name);
if (animal_source) { if (animal_source) {
this.methods.push(new ItemNode(this.manager, this, this.name).setHuntable(animal_source)); this.add_method(new ItemNode(this.manager, this, this.name).setHuntable(animal_source));
} }
} }
@ -223,11 +229,11 @@ class ItemWrapper {
return false; return false;
} }
getBestMethod() { getBestMethod(q=1) {
let best_cost = -1; let best_cost = -1;
let best_method = null; let best_method = null;
for (let method of this.methods) { for (let method of this.methods) {
let cost = method.getDepth() + method.getFails(); let cost = method.getDepth(q) + method.getFails(q);
if (best_cost == -1 || cost < best_cost) { if (best_cost == -1 || cost < best_cost) {
best_cost = cost; best_cost = cost;
best_method = method; best_method = method;
@ -236,40 +242,28 @@ class ItemWrapper {
return best_method return best_method
} }
getChildren() { isDone(q=1) {
if (this.methods.length === 0)
return [];
return this.getBestMethod().getChildren();
}
isReady() {
if (this.methods.length === 0) if (this.methods.length === 0)
return false; return false;
return this.getBestMethod().isReady(); return this.getBestMethod(q).isDone(q);
}
isDone(quantity=1) {
if (this.methods.length === 0)
return true;
return this.getBestMethod().isDone(quantity);
} }
getDepth(q=1) { getDepth(q=1) {
if (this.methods.length === 0) if (this.methods.length === 0)
return 0; return 0;
return this.getBestMethod().getDepth(q); return this.getBestMethod(q).getDepth(q);
} }
getFails(q=1) { getFails(q=1) {
if (this.methods.length === 0) if (this.methods.length === 0)
return 0; return 0;
return this.getBestMethod().getFails(q); return this.getBestMethod(q).getFails(q);
} }
getNext() { getNext(q=1) {
if (this.methods.length === 0) if (this.methods.length === 0)
return null; return null;
return this.getBestMethod().getNext(); return this.getBestMethod(q).getNext(q);
} }
} }
@ -278,20 +272,34 @@ export class ItemGoal {
constructor(agent, timeout=-1) { constructor(agent, timeout=-1) {
this.agent = agent; this.agent = agent;
this.timeout = timeout; this.timeout = timeout;
this.goal = null; this.goals = [];
this.quantity = 1;
this.nodes = {}; this.nodes = {};
} }
setGoal(goal, quantity=1) { setGoals(goals) {
this.quantity = quantity; this.goals = []
if (this.nodes[goal] === undefined) for (let goal of goals) {
this.nodes[goal] = new ItemWrapper(this, null, goal); this.goals.push({name: goal, quantity: 1})
this.goal = this.nodes[goal]; }
} }
async executeNext() { async executeNext() {
let next = this.goal.getNext(); // Get goal by priority
let goal = null;
let inventory = world.getInventoryCounts(this.agent.bot);
for (let g of this.goals) {
if (inventory[g.name] === undefined || inventory[g.name] < g.quantity) {
if (this.nodes[g.name] === undefined)
this.nodes[g.name] = new ItemWrapper(this, null, g.name);
goal = this.nodes[g.name];
break;
}
}
if (goal === null)
return;
// Get next goal to execute
let next = goal.getNext();
// Prevent unnecessary attempts to obtain blocks that are not nearby // Prevent unnecessary attempts to obtain blocks that are not nearby
if (next.type === 'block' && !world.getNearbyBlockTypes(this.agent.bot).includes(next.source)) { if (next.type === 'block' && !world.getNearbyBlockTypes(this.agent.bot).includes(next.source)) {
@ -302,11 +310,10 @@ export class ItemGoal {
} }
// Wait for the bot to be idle before attempting to execute the next goal // Wait for the bot to be idle before attempting to execute the next goal
if (!this.agent.isIdle()) { if (!this.agent.isIdle())
await new Promise((resolve) => setTimeout(resolve, 500));
return; return;
}
// Execute the next goal
let init_quantity = world.getInventoryCounts(this.agent.bot)[next.name] || 0; let init_quantity = world.getInventoryCounts(this.agent.bot)[next.name] || 0;
this.agent.coder.interruptible = true; this.agent.coder.interruptible = true;
await this.agent.coder.execute(async () => { await this.agent.coder.execute(async () => {
@ -315,10 +322,11 @@ export class ItemGoal {
this.agent.coder.interruptible = false; this.agent.coder.interruptible = false;
let final_quantity = world.getInventoryCounts(this.agent.bot)[next.name] || 0; let final_quantity = world.getInventoryCounts(this.agent.bot)[next.name] || 0;
// Log the result of the goal attempt
if (final_quantity > init_quantity) { if (final_quantity > init_quantity) {
console.log(`Successfully obtained ${next.name} for goal ${this.goal.name}`); console.log(`Successfully obtained ${next.name} for goal ${goal.name}`);
} else { } else {
console.log(`Failed to obtain ${next.name} for goal ${this.goal.name}`); console.log(`Failed to obtain ${next.name} for goal ${goal.name}`);
} }
} }
} }