mirror of
https://github.com/kolbytn/mindcraft.git
synced 2025-08-22 07:03:45 +02:00
load goals, logic fixes
This commit is contained in:
parent
5a1e57bd42
commit
57783fb4ca
5 changed files with 89 additions and 58 deletions
|
@ -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
19
bots/andy/survive.json
Normal 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": []
|
||||||
|
}
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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}.`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue