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",
"bio": "You are playing minecraft and assisting other players in tasks.",
"memory": "",
"goals": [],
"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.coder = new Coder(this);
this.item_goal = new ItemGoal(this);
this.item_goal.setGoal('iron_pickaxe', 1);
console.log('Loading examples...');
this.history.load(profile);
this.item_goal.setGoals(this.history.goals);
await this.examples.load('./src/examples.json');
await this.coder.load();

View file

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

View file

@ -18,10 +18,11 @@ class ItemNode {
setRecipe(recipe) {
this.type = 'craft';
let size = 0;
this.recipe = [];
for (let [key, value] of Object.entries(recipe)) {
if (this.manager.nodes[key] === undefined)
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;
}
if (size > 4) {
@ -64,21 +65,16 @@ class ItemNode {
}
getChildren() {
let children = [];
for (let child of this.recipe) {
if (child[0] instanceof ItemWrapper && child[0].methods.length > 0) {
children.push(child);
}
}
if (this.prereq && this.prereq instanceof ItemWrapper && this.prereq.methods.length > 0) {
children.push([this.prereq, 1]);
let children = [...this.recipe];
if (this.prereq) {
children.push({node: this.prereq, quantity: 1});
}
return children;
}
isReady() {
for (let [child, quantity] of this.getChildren()) {
if (!child.isDone(quantity)) {
for (let child of this.getChildren()) {
if (!child.node.isDone(child.quantity)) {
return false;
}
}
@ -123,8 +119,8 @@ class ItemNode {
return 0;
}
let depth = 0;
for (let [child, quantity] of this.getChildren()) {
depth = Math.max(depth, child.getDepth(quantity));
for (let child of this.getChildren()) {
depth = Math.max(depth, child.node.getDepth(child.quantity));
}
return depth + 1;
}
@ -134,18 +130,19 @@ class ItemNode {
return 0;
}
let fails = 0;
for (let [child, quantity] of this.getChildren()) {
fails += child.getFails(quantity);
for (let child of this.getChildren()) {
fails += child.node.getFails(child.quantity);
}
return fails + this.fails;
}
getNext() {
if (this.isReady()) {
getNext(q=1) {
if (this.isDone(q))
return null;
if (this.isReady())
return this;
}
for (let [child, quantity] of this.getChildren()) {
let res = child.getNext();
for (let child of this.getChildren()) {
let res = child.node.getNext(child.quantity);
if (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() {
let recipes = mc.getItemCraftingRecipes(this.name);
if (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);
if (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);
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);
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;
}
getBestMethod() {
getBestMethod(q=1) {
let best_cost = -1;
let best_method = null;
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) {
best_cost = cost;
best_method = method;
@ -236,40 +242,28 @@ class ItemWrapper {
return best_method
}
getChildren() {
if (this.methods.length === 0)
return [];
return this.getBestMethod().getChildren();
}
isReady() {
isDone(q=1) {
if (this.methods.length === 0)
return false;
return this.getBestMethod().isReady();
}
isDone(quantity=1) {
if (this.methods.length === 0)
return true;
return this.getBestMethod().isDone(quantity);
return this.getBestMethod(q).isDone(q);
}
getDepth(q=1) {
if (this.methods.length === 0)
return 0;
return this.getBestMethod().getDepth(q);
return this.getBestMethod(q).getDepth(q);
}
getFails(q=1) {
if (this.methods.length === 0)
return 0;
return this.getBestMethod().getFails(q);
return this.getBestMethod(q).getFails(q);
}
getNext() {
getNext(q=1) {
if (this.methods.length === 0)
return null;
return this.getBestMethod().getNext();
return this.getBestMethod(q).getNext(q);
}
}
@ -278,20 +272,34 @@ export class ItemGoal {
constructor(agent, timeout=-1) {
this.agent = agent;
this.timeout = timeout;
this.goal = null;
this.quantity = 1;
this.goals = [];
this.nodes = {};
}
setGoal(goal, quantity=1) {
this.quantity = quantity;
if (this.nodes[goal] === undefined)
this.nodes[goal] = new ItemWrapper(this, null, goal);
this.goal = this.nodes[goal];
setGoals(goals) {
this.goals = []
for (let goal of goals) {
this.goals.push({name: goal, quantity: 1})
}
}
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
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
if (!this.agent.isIdle()) {
await new Promise((resolve) => setTimeout(resolve, 500));
if (!this.agent.isIdle())
return;
}
// Execute the next goal
let init_quantity = world.getInventoryCounts(this.agent.bot)[next.name] || 0;
this.agent.coder.interruptible = true;
await this.agent.coder.execute(async () => {
@ -315,10 +322,11 @@ export class ItemGoal {
this.agent.coder.interruptible = false;
let final_quantity = world.getInventoryCounts(this.agent.bot)[next.name] || 0;
// Log the result of the goal attempt
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 {
console.log(`Failed to obtain ${next.name} for goal ${this.goal.name}`);
console.log(`Failed to obtain ${next.name} for goal ${goal.name}`);
}
}
}