mirror of
https://github.com/kolbytn/mindcraft.git
synced 2025-08-16 04:05:37 +02:00
Merge branch 'main' of https://github.com/icwhite/mindcraft
This commit is contained in:
commit
2027b71fe7
5 changed files with 67 additions and 21 deletions
|
@ -76,7 +76,7 @@ def analyze_json_file(file_path):
|
||||||
if 'turns' in data and isinstance(data['turns'], list):
|
if 'turns' in data and isinstance(data['turns'], list):
|
||||||
for turn in reversed(data['turns']): # Check turns from the end
|
for turn in reversed(data['turns']): # Check turns from the end
|
||||||
if turn.get('role') == 'system' and isinstance(turn.get('content'), str):
|
if turn.get('role') == 'system' and isinstance(turn.get('content'), str):
|
||||||
if "Task successful ended with code : 2" in turn['content'] or "Task ended in score: 1" in turn["content"]:
|
if "Task successful ended with code : 2" in turn['content'] or "Task ended with score : 1" in turn["content"] or "Task ended in score: 1" in turn["content"]:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
"name": "andy",
|
"name": "andy",
|
||||||
"model": "claude-3-5-haiku-latest",
|
"model": "claude-3-5-haiku-latest",
|
||||||
"modes": {
|
"modes": {
|
||||||
"hunting": false
|
"hunting": false,
|
||||||
|
"item_collecting": false
|
||||||
},
|
},
|
||||||
"conversing": "You are a task-focused Minecraft bot named $NAME. You have to collaborate with other agents in the world to complete the current task \nFeel free to ask other agents questions and make a plan to achieve the goal. You can request them to give them some of their inventory items if required to complete the goal. General Searching Tips:\n- The farm area is extensive - search thoroughly for needed resources\n There is a chest nearby with valuable items.\n- Divide tasks efficiently between agents for faster completion\n- Communicate your plan and progress clearly. You can see, move, mine, build, and interact with the world by using commands.\n$SELF_PROMPT Act human-like as if you were a typical Minecraft player, rather than an AI. Be very brief in your responses, don't apologize constantly, don't give instructions or make lists unless asked, and don't refuse requests. Don't pretend to act, use commands immediately when requested. Do NOT say this: 'Sure, I've stopped.', instead say this: 'Sure, I'll stop. !stop'. Do NOT say this: 'On my way! Give me a moment.', instead say this: 'On my way! !goToPlayer(\"playername\", 3)'. Respond only as $NAME, never output '(FROM OTHER BOT)' or pretend to be someone else. If you have nothing to say or do, respond with an just a tab '\t'. Share resources and information with other bots! This is extremely important to me, take a deep breath and have fun :) \nSummarized memory:'$MEMORY'\n$STATS\n$INVENTORY\n$COMMAND_DOCS\n$EXAMPLES\nConversation Begin:",
|
"conversing": "You are a task-focused Minecraft bot named $NAME. You have to collaborate with other agents in the world to complete the current task \nFeel free to ask other agents questions and make a plan to achieve the goal. You can request them to give them some of their inventory items if required to complete the goal. General Searching Tips:\n- You will be spawned in a farm with many crops and animals nearby. The farm area is extensive - search thoroughly for needed resources (with searchForBlocks parameters like 64,128,256)\n There is a chest nearby with valuable items. Along with the chest, a crafting table, fully fueled furnace and fully fueled smoker with coal are also available nearby which you can use to your advantage. On top of this plants like mushrooms, wheat, carrots, beetroots, pumpkins, potatoes are also present nearby.\nCollaboration tips - Divide tasks efficiently between agents for faster completion\n- Communicate your plan and progress clearly. You can see, move, mine, build, and interact with the world by using commands.\n$SELF_PROMPT Act human-like as if you were a typical Minecraft player, rather than an AI. Be very brief in your responses, don't apologize constantly, don't give instructions or make lists unless asked, and don't refuse requests. Don't pretend to act, use commands immediately when requested. Do NOT say this: 'Sure, I've stopped.', instead say this: 'Sure, I'll stop. !stop'. Do NOT say this: 'On my way! Give me a moment.', instead say this: 'On my way! !goToPlayer(\"playername\", 3)'. Respond only as $NAME, never output '(FROM OTHER BOT)' or pretend to be someone else. If you have nothing to say or do, respond with an just a tab '\t'. Share resources and information with other bots! This is extremely important to me, take a deep breath and have fun :) \nSummarized memory:'$MEMORY'\n$STATS\n$INVENTORY\n$COMMAND_DOCS\n$EXAMPLES\nConversation Begin:",
|
||||||
"saving_memory": "You are a minecraft bot named $NAME that has been talking and playing minecraft by using commands. Update your memory by summarizing the following conversation and your old memory in your next response. Prioritize preserving important facts, things you've learned, useful tips, and long term reminders. Do Not record stats, inventory, or docs! Only save transient information from your chat history. $SELF_PROMPT Make sure to include information relevant to the goal and inventory you have collected. You're limited to 500 characters, so be extremely brief and minimize words. Compress useful information. \nOld Memory: '$MEMORY'\nRecent conversation: \n$TO_SUMMARIZE\nSummarize your old memory and recent conversation into a new memory, and respond only with the unwrapped memory text: "
|
"saving_memory": "You are a minecraft bot named $NAME that has been talking and playing minecraft by using commands. Update your memory by summarizing the following conversation and your old memory in your next response. Prioritize preserving important facts, things you've learned, useful tips, and long term reminders. Do Not record stats, inventory, or docs! Only save transient information from your chat history. $SELF_PROMPT Make sure to include information relevant to the goal and inventory you have collected. You're limited to 500 characters, so be extremely brief and minimize words. Compress useful information. \nOld Memory: '$MEMORY'\nRecent conversation: \n$TO_SUMMARIZE\nSummarize your old memory and recent conversation into a new memory, and respond only with the unwrapped memory text: "
|
||||||
}
|
}
|
|
@ -460,7 +460,14 @@ export async function collectBlock(bot, blockType, num=1, exclude=null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await bot.collectBlock.collect(block);
|
if (mc.mustCollectManually(blockType)) {
|
||||||
|
await goToPosition(bot, block.position.x, block.position.y, block.position.z, 2);
|
||||||
|
await bot.dig(block);
|
||||||
|
await pickupNearbyItems(bot);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
await bot.collectBlock.collect(block);
|
||||||
|
}
|
||||||
collected++;
|
collected++;
|
||||||
await autoLight(bot);
|
await autoLight(bot);
|
||||||
}
|
}
|
||||||
|
@ -823,7 +830,7 @@ export async function putInChest(bot, itemName, num=-1) {
|
||||||
|
|
||||||
export async function takeFromChest(bot, itemName, num=-1) {
|
export async function takeFromChest(bot, itemName, num=-1) {
|
||||||
/**
|
/**
|
||||||
* Take the given item from the nearest chest.
|
* Take the given item from the nearest chest, potentially from multiple slots.
|
||||||
* @param {MinecraftBot} bot, reference to the minecraft bot.
|
* @param {MinecraftBot} bot, reference to the minecraft bot.
|
||||||
* @param {string} itemName, the item or block name to take from the chest.
|
* @param {string} itemName, the item or block name to take from the chest.
|
||||||
* @param {number} num, the number of items to take from the chest. Defaults to -1, which takes all items.
|
* @param {number} num, the number of items to take from the chest. Defaults to -1, which takes all items.
|
||||||
|
@ -838,17 +845,33 @@ export async function takeFromChest(bot, itemName, num=-1) {
|
||||||
}
|
}
|
||||||
await goToPosition(bot, chest.position.x, chest.position.y, chest.position.z, 2);
|
await goToPosition(bot, chest.position.x, chest.position.y, chest.position.z, 2);
|
||||||
const chestContainer = await bot.openContainer(chest);
|
const chestContainer = await bot.openContainer(chest);
|
||||||
let item = chestContainer.containerItems().find(item => item.name === itemName);
|
|
||||||
if (!item) {
|
// Find all matching items in the chest
|
||||||
|
let matchingItems = chestContainer.containerItems().filter(item => item.name === itemName);
|
||||||
|
if (matchingItems.length === 0) {
|
||||||
log(bot, `Could not find any ${itemName} in the chest.`);
|
log(bot, `Could not find any ${itemName} in the chest.`);
|
||||||
await chestContainer.close();
|
await chestContainer.close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let to_take = num === -1 ? item.count : Math.min(num, item.count);
|
|
||||||
await chestContainer.withdraw(item.type, null, to_take);
|
let totalAvailable = matchingItems.reduce((sum, item) => sum + item.count, 0);
|
||||||
|
let remaining = num === -1 ? totalAvailable : Math.min(num, totalAvailable);
|
||||||
|
let totalTaken = 0;
|
||||||
|
|
||||||
|
// Take items from each slot until we've taken enough or run out
|
||||||
|
for (const item of matchingItems) {
|
||||||
|
if (remaining <= 0) break;
|
||||||
|
|
||||||
|
let toTakeFromSlot = Math.min(remaining, item.count);
|
||||||
|
await chestContainer.withdraw(item.type, null, toTakeFromSlot);
|
||||||
|
|
||||||
|
totalTaken += toTakeFromSlot;
|
||||||
|
remaining -= toTakeFromSlot;
|
||||||
|
}
|
||||||
|
|
||||||
await chestContainer.close();
|
await chestContainer.close();
|
||||||
log(bot, `Successfully took ${to_take} ${itemName} from the chest.`);
|
log(bot, `Successfully took ${totalTaken} ${itemName} from the chest.`);
|
||||||
return true;
|
return totalTaken > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function viewChest(bot) {
|
export async function viewChest(bot) {
|
||||||
|
|
|
@ -126,16 +126,25 @@ class CookingCraftingTaskValidator {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.agent = agent;
|
this.agent = agent;
|
||||||
}
|
}
|
||||||
validate() {
|
validate(has_initiated) {
|
||||||
const result = checkItemPresence(this.data, this.agent);
|
if (has_initiated) {
|
||||||
let score = 0;
|
|
||||||
if (result.success) {
|
const result = checkItemPresence(this.data, this.agent);
|
||||||
score = 1;
|
let score = 0;
|
||||||
|
if (result.success) {
|
||||||
|
score = 1;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
"valid": result.success,
|
||||||
|
"score": score,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return {
|
||||||
|
"valid": false,
|
||||||
|
"score": 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return {
|
|
||||||
"valid": result.success,
|
|
||||||
"score": score,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,6 +197,7 @@ export class Task {
|
||||||
|
|
||||||
this.name = this.agent.name;
|
this.name = this.agent.name;
|
||||||
this.available_agents = settings.profiles.map((p) => JSON.parse(readFileSync(p, 'utf8')).name);
|
this.available_agents = settings.profiles.map((p) => JSON.parse(readFileSync(p, 'utf8')).name);
|
||||||
|
this.agent_initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
getAgentGoal() {
|
getAgentGoal() {
|
||||||
|
@ -239,7 +249,7 @@ export class Task {
|
||||||
isDone() {
|
isDone() {
|
||||||
let res = null;
|
let res = null;
|
||||||
if (this.validator)
|
if (this.validator)
|
||||||
res = this.validator.validate();
|
res = this.validator.validate(this.agent_initialized);
|
||||||
if (res && res.valid) {
|
if (res && res.valid) {
|
||||||
return {"message": 'Task successful', "score": res.score};
|
return {"message": 'Task successful', "score": res.score};
|
||||||
}
|
}
|
||||||
|
@ -311,6 +321,8 @@ export class Task {
|
||||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.agent_initialized = true;
|
||||||
|
|
||||||
if (this.initiator) {
|
if (this.initiator) {
|
||||||
await this.initiator.init();
|
await this.initiator.init();
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,16 @@ export function isHostile(mob) {
|
||||||
return (mob.type === 'mob' || mob.type === 'hostile') && mob.name !== 'iron_golem' && mob.name !== 'snow_golem';
|
return (mob.type === 'mob' || mob.type === 'hostile') && mob.name !== 'iron_golem' && mob.name !== 'snow_golem';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// blocks that don't work with collectBlock, need to be manually collected
|
||||||
|
export function mustCollectManually(blockName) {
|
||||||
|
// all crops (that aren't normal blocks), torches, buttons, levers, redstone,
|
||||||
|
const full_names = ['wheat', 'carrots', 'potatoes', 'beetroots', 'nether_wart', 'cocoa', 'sugar_cane', 'kelp', 'short_grass', 'fern', 'tall_grass', 'bamboo',
|
||||||
|
'poppy', 'dandelion', 'blue_orchid', 'allium', 'azure_bluet', 'oxeye_daisy', 'cornflower', 'lilac', 'wither_rose', 'lily_of_the_valley', 'wither_rose',
|
||||||
|
'lever', 'redstone_wire', 'lantern']
|
||||||
|
const partial_names = ['sapling', 'torch', 'button', 'carpet', 'pressure_plate', 'mushroom', 'tulip', 'bush', 'vines', 'fern']
|
||||||
|
return full_names.includes(blockName.toLowerCase()) || partial_names.some(partial => blockName.toLowerCase().includes(partial));
|
||||||
|
}
|
||||||
|
|
||||||
export function getItemId(itemName) {
|
export function getItemId(itemName) {
|
||||||
let item = mcdata.itemsByName[itemName];
|
let item = mcdata.itemsByName[itemName];
|
||||||
if (item) {
|
if (item) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue