Merge branch 'main' into cleanup

This commit is contained in:
MaxRobinsonTheGreat 2025-03-19 13:29:37 -05:00
commit 96250b3ce5
37 changed files with 82713 additions and 51 deletions

View file

@ -76,7 +76,7 @@ def analyze_json_file(file_path):
if 'turns' in data and isinstance(data['turns'], list):
for turn in reversed(data['turns']): # Check turns from the end
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 False
except FileNotFoundError:

View file

@ -0,0 +1,39 @@
import boto3
import os
import json
import re
from botocore.exceptions import ClientError
import json
import argparse
from tqdm import tqdm
import glob
def analyze_json_file(file_path):
"""
Analyzes a single JSON file to extract the task outcome.
Args:
file_path (str): Path to the JSON file.
Returns:
str or None: The task outcome string if found, otherwise None.
"""
try:
with open(file_path, 'r') as f:
data = json.load(f)
if 'turns' in data and isinstance(data['turns'], list):
for turn in reversed(data['turns']): # Check turns from the end
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"]:
return True
return False
except FileNotFoundError:
print(f"Error: File not found: {file_path}")
return None
except json.JSONDecodeError:
print(f"Error: Invalid JSON format in: {file_path}")
return None
except Exception as e:
print(f"An unexpected error occurred while processing {file_path}: {e}")
return None

222
analyze_cooking_tasks.py Normal file
View file

@ -0,0 +1,222 @@
import os
import json
import re
from collections import defaultdict
def extract_cooking_items(exp_dir):
"""Extract cooking items from experiment directory name."""
# Remove prefix and blocked access part
clean_name = re.sub(r'^multiagent_cooking_', '', exp_dir)
clean_name = re.sub(r'_blocked_access_[0-9_]+$', '', clean_name)
# Extract individual items
items = []
for item_match in re.finditer(r'([0-9]+)_([a-zA-Z_]+)', clean_name):
count = int(item_match.group(1))
item = item_match.group(2)
# Remove trailing underscores to fix the item name issue
item = item.rstrip('_')
items.append(item)
return items
def analyze_experiments(root_dir):
# Store results by number of blocked agents
blocked_access_results = defaultdict(lambda: {
"success": 0,
"total": 0,
"cake_success": 0,
"cake_total": 0,
"non_cake_success": 0,
"non_cake_total": 0
})
# Store results by cooking item
cooking_item_results = defaultdict(lambda: {
"success": 0,
"total": 0
})
# Keep track of all unique cooking items
all_cooking_items = set()
# Get a list of all experiment directories
experiment_dirs = [d for d in os.listdir(root_dir) if os.path.isdir(os.path.join(root_dir, d))
and d.startswith("multiagent_cooking_")]
for exp_dir in experiment_dirs:
# Extract cooking items
cooking_items = extract_cooking_items(exp_dir)
# Add to unique items set
all_cooking_items.update(cooking_items)
# Check if experiment involves cake
has_cake = any(item == "cake" for item in cooking_items)
# Extract blocked access information from directory name
blocked_access_match = re.search(r'blocked_access_([0-9_]+)$', exp_dir)
if blocked_access_match:
blocked_access_str = blocked_access_match.group(1)
# Count how many agents have blocked access
num_blocked_agents = len(blocked_access_str.split('_'))
blocked_key = f"{num_blocked_agents} agent(s)"
else:
# No agents blocked
blocked_key = "0 agent(s)"
# Check if the task was successful
is_successful = False
full_exp_path = os.path.join(root_dir, exp_dir)
# Get all JSON files in the experiment directory
agent_files = [f for f in os.listdir(full_exp_path) if f.endswith(".json")]
# Check each agent file for success information
for agent_file in agent_files:
agent_file_path = os.path.join(full_exp_path, agent_file)
try:
with open(agent_file_path, 'r') as f:
agent_data = json.load(f)
# Check for success in the turns data
if "turns" in agent_data:
for turn in agent_data["turns"]:
if turn.get("role") == "system" and "content" in turn:
if isinstance(turn["content"], str) and "Task ended with score : 1" in turn["content"]:
is_successful = True
break
# If we found success, no need to check other files
if is_successful:
break
except (json.JSONDecodeError, IOError) as e:
print(f"Error reading {agent_file_path}: {e}")
# Continue to check other agent files instead of failing
continue
# Update cooking item results
for item in cooking_items:
cooking_item_results[item]["total"] += 1
if is_successful:
cooking_item_results[item]["success"] += 1
# Update the appropriate blocked access counters
# First update the category-specific counters
if has_cake:
blocked_access_results[blocked_key]["cake_total"] += 1
if is_successful:
blocked_access_results[blocked_key]["cake_success"] += 1
else:
blocked_access_results[blocked_key]["non_cake_total"] += 1
if is_successful:
blocked_access_results[blocked_key]["non_cake_success"] += 1
# Only count non-cake experiments in the main totals
blocked_access_results[blocked_key]["total"] += 1
if is_successful:
blocked_access_results[blocked_key]["success"] += 1
return blocked_access_results, cooking_item_results, all_cooking_items
def print_blocked_results(results):
print("\nExperiment Results by Number of Agents with Blocked Access (Excluding Cake Experiments):")
print("=" * 80)
print(f"{'Blocked Agents':<15} | {'Success Rate':<15} | {'Success/Total':<15} | {'Cake Tasks':<15} | {'Non-Cake Tasks':<15}")
print("-" * 80)
# Calculate totals
total_success = 0
total_experiments = 0
total_cake = 0
total_non_cake = 0
# Sort by number of blocked agents
for key in sorted(results.keys(), key=lambda x: int(x.split()[0])):
success = results[key]["success"]
total = results[key]["total"]
cake_total = results[key]["cake_total"]
non_cake_total = results[key]["non_cake_total"]
# Verify that non_cake_total matches total
if non_cake_total != total:
print(f"Warning: Non-cake total ({non_cake_total}) doesn't match the total ({total}) for {key}")
total_success += success
total_experiments += total
total_cake += cake_total
total_non_cake += non_cake_total
success_rate = (success / total * 100) if total > 0 else 0
print(f"{key:<15} | {success_rate:>6.2f}% | {success}/{total:<13} | {cake_total:<15} | {non_cake_total:<15}")
# Calculate overall success rate (excluding cake experiments)
overall_success_rate = (total_success / total_experiments * 100) if total_experiments > 0 else 0
print("-" * 80)
print(f"{'Overall':<15} | {overall_success_rate:>6.2f}% | {total_success}/{total_experiments:<13} | {total_cake:<15} | {total_non_cake:<15}")
# Print cake experiment details
print("\nCake Experiment Details:")
print("=" * 60)
print(f"{'Blocked Agents':<15} | {'Success Rate':<15} | {'Success/Total':<15}")
print("-" * 60)
cake_total_success = 0
cake_total_experiments = 0
for key in sorted(results.keys(), key=lambda x: int(x.split()[0])):
cake_success = results[key]["cake_success"]
cake_total = results[key]["cake_total"]
cake_total_success += cake_success
cake_total_experiments += cake_total
cake_success_rate = (cake_success / cake_total * 100) if cake_total > 0 else 0
print(f"{key:<15} | {cake_success_rate:>6.2f}% | {cake_success}/{cake_total}")
cake_overall_success_rate = (cake_total_success / cake_total_experiments * 100) if cake_total_experiments > 0 else 0
print("-" * 60)
print(f"{'Overall':<15} | {cake_overall_success_rate:>6.2f}% | {cake_total_success}/{cake_total_experiments}")
def print_cooking_items(cooking_items):
print("\nUnique Cooking Items Found:")
print("=" * 60)
print(", ".join(sorted(cooking_items)))
print(f"Total unique items: {len(cooking_items)}")
def print_item_results(item_results):
print("\nExperiment Results by Cooking Item:")
print("=" * 60)
print(f"{'Cooking Item':<20} | {'Success Rate':<15} | {'Success/Total':<15}")
print("-" * 60)
# Sort by item name
for item in sorted(item_results.keys()):
success = item_results[item]["success"]
total = item_results[item]["total"]
success_rate = (success / total * 100) if total > 0 else 0
print(f"{item:<20} | {success_rate:>6.2f}% | {success}/{total}")
print("-" * 60)
def main():
# Update this path to your experiments directory
experiments_root = "../results/llama_70b_hells_kitchen_cooking_tasks"
print(f"Analyzing experiments in: {os.path.abspath(experiments_root)}")
blocked_results, item_results, unique_items = analyze_experiments(experiments_root)
print_blocked_results(blocked_results)
print_cooking_items(unique_items)
print_item_results(item_results)
if __name__ == "__main__":
main()

View file

@ -8,6 +8,13 @@ import re
import sys
import os
import time
import filecmp
import json
import glob
import socket
from tqdm import tqdm
import boto3
BLOCKED_ACTIONS_COOKING = [
'!activate', '!attackPlayer', '!checkBlueprint', '!checkBlueprintLevel',
@ -33,6 +40,81 @@ BLOCKED_ACTIONS_CONSTRUCTION = [
'!stop', '!takeFromChest', '!viewChest'
]
def analyze_json_file(file_path):
"""
Analyzes a single JSON file to extract the task outcome.
Args:
file_path (str): Path to the JSON file.
Returns:
str or None: The task outcome string if found, otherwise None.
"""
try:
with open(file_path, 'r') as f:
data = json.load(f)
if 'turns' in data and isinstance(data['turns'], list):
for turn in reversed(data['turns']): # Check turns from the end
if turn.get('role') == 'system' and isinstance(turn.get('content'), str):
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 False
except FileNotFoundError:
print(f"Error: File not found: {file_path}")
return None
except json.JSONDecodeError:
print(f"Error: Invalid JSON format in: {file_path}")
return None
except Exception as e:
print(f"An unexpected error occurred while processing {file_path}: {e}")
return None
def extract_result(folder_path):
folder_name = os.path.basename(folder_path)
json_files = glob.glob(os.path.join(folder_path, "*.json"))
# assert len(json_files) == 2, f"Expected 2 json files in {folder_name}, found {len(json_files)}"
if not json_files:
print(f"No JSON files found in {folder_name}")
return None
else:
outcome = False
for json_file in json_files:
outcome = analyze_json_file(json_file)
if outcome:
return True
return False
def aggregate_results(local_folders):
"""
Aggregates the analysis results for each folder.
Args:
local_folders (list): List of local folder paths containing the JSON files.
Returns:
dict: A dictionary where keys are folder names and values are the aggregated outcomes.
"""
aggregated_data = {}
total = 0
successful = 0
for folder_path in tqdm(local_folders):
folder_name = os.path.basename(folder_path)
try:
result = extract_result(folder_path)
if result is not None:
total += 1
successful += int(result)
except Exception as e:
print(f"Error processing {folder_name}: {e}")
return {
"total": total,
"successful": successful,
}
def read_settings(file_path):
"""Read and parse the settings.js file to get agent profiles."""
with open(file_path, 'r', encoding='utf-8') as file:
@ -133,6 +215,14 @@ def launch_parallel_experiments(task_path,
experiments_folder = f"experiments/{exp_name}_{date_time}"
exp_name = f"{exp_name}_{date_time}"
split_task_path = task_path.split("/")
if len(split_task_path) > 1:
task_path_name = split_task_path[-2]
else:
task_path_name = "tasks"
s3_path = f"{bucket_name}/{task_type}/{model}/{task_path_name}/{exp_name}/"
# start wandb
os.makedirs(experiments_folder, exist_ok=True)
for i, server in enumerate(servers):
@ -150,14 +240,25 @@ def launch_parallel_experiments(task_path,
insecure_coding=insecure_coding,
num_agents=num_agents,
url=url,
task_type=task_type)
task_type=task_type,
s3_path=s3_path)
time.sleep(5)
for i in range(20):
for i in range(len(servers)):
session_name = str(servers[i][1] - 55916)
subprocess.run(["tmux", "send-keys", "-t", "server_" + session_name, f"/op @a", "C-m"])
time.sleep(10)
total_num_tasks = len(task_ids)
total_num_experiments = total_num_tasks * num_exp
total_run = 0
while total_run < total_num_experiments:
results = aggregate_results([f"{experiments_folder}/{task_id}" for task_id in task_ids])
total_run = results["total"]
print(f"Total tasks run: {total_run}/{total_num_experiments}")
print(results)
with open(f"{experiments_folder}/results.txt", "w") as file:
file.write(str(results))
if s3:
s3 = boto3.client('s3')
s3.upload_file(f"{experiments_folder}/results.txt", bucket_name, s3_path)
time.sleep(15)
def launch_server_experiment(task_path,
task_ids,
@ -173,7 +274,8 @@ def launch_server_experiment(task_path,
template_profile="profiles/tasks/collab_profile.json",
insecure_coding=False,
url="http://127.0.0.1:8000/v1",
task_type="techtree"):
task_type="techtree",
s3_path=""):
"""
Launch a Minecraft server and run experiments on it.
@param task_path: Path to the task file
@ -221,10 +323,12 @@ def launch_server_experiment(task_path,
agent_profiles_str += f'\"{agent}\", '
agent_profiles_str += f"\"{agent_profiles[-1]}\"]'"
print(agent_profiles_str)
launch_world(server_path, session_name="server_" + session_name, agent_names=agent_names)
launch_world(server_path, session_name="server_" + session_name, agent_names=agent_names, port=server_port)
subprocess.run(['tmux', 'new-session', '-d', '-s', session_name], check=True)
# set environment variables
set_environment_variable_tmux_session(session_name, "MINECRAFT_PORT", server_port)
set_environment_variable_tmux_session(session_name, "MINDSERVER_PORT", mindserver_port)
@ -233,13 +337,14 @@ def launch_server_experiment(task_path,
set_environment_variable_tmux_session(session_name, "INSECURE_CODING", "true")
# you need to add the bots to the world first before you can add them as op
cmd = f"node main.js --task_path example_tasks.json --task_id debug_{num_agents}_agent_timeout"
# cmd = f"node main.js --task_path example_tasks.json --task_id debug_{num_agents}_agent_timeout"
subprocess.run(["tmux", "send-keys", "-t", session_name, cmd, "C-m"])
# subprocess.run(["tmux", "send-keys", "-t", session_name, cmd, "C-m"])
time.sleep(40)
# time.sleep(40)
subprocess.run(["tmux", "send-keys", "-t", "server_" + session_name, f"/op {agent_names[0]}", "C-m"])
# subprocess.run(["tmux", "send-keys", "-t", "server_" + session_name, f"/op @a", "C-m"])
make_ops(agent_names, session_name)
# add the bots as op
# op_script_content = "sleep 5\n\op @p" * 20
@ -252,6 +357,8 @@ def launch_server_experiment(task_path,
elif task_type == "construction":
set_environment_variable_tmux_session(session_name, "BLOCKED_ACTIONS", BLOCKED_ACTIONS_CONSTRUCTION)
script_content = ""
for task_id in task_ids:
@ -274,8 +381,7 @@ def launch_server_experiment(task_path,
script_content += f"{cp_cmd}\n"
script_content += "sleep 1\n"
if s3:
s3_cmd = f"aws s3 cp {agent_file_path} s3://{bucket_name}/{exp_name}/{task_id}/{agent}_{_}.json"
s3_upload_experiment = f"aws s3 cp {agent_file_path} s3://{bucket_name}/{exp_name}/{task_id}/{agent}_{_}.json"
s3_cmd = f"aws s3 cp {agent_file_path} s3://{s3_path}/{task_id}/{agent}_{_}.json"
script_content += f"echo 'Uploading {agent_file_path} to S3'\n"
script_content += f"echo '{s3_cmd}'\n"
script_content += f"{s3_cmd}\n"
@ -283,12 +389,42 @@ def launch_server_experiment(task_path,
script_content += f"sleep 10\n"
if s3:
for agent in agent_names:
script_content += f"aws s3 cp bots/{agent} s3://{bucket_name}/{exp_name}/bots/{agent} --recursive\n"
script_content += f"aws s3 cp bots/{agent} s3://{s3_path}/bots/{agent} --recursive\n"
# Create a temporary shell script file
script_file = f"./tmp/experiment_script_{session_name}.sh"
make_script_file_and_run(script_content, session_name, script_file)
def make_ops(agent_names, session_name):
"""Make the agents operators in the Minecraft world."""
print('Making agents operators...')
cmd = f"node main.js --task_path example_tasks.json --task_id debug_{len(agent_names)}_agent_timeout"
subprocess.run(["tmux", "send-keys", "-t", session_name, cmd, "C-m"])
time.sleep(30)
subprocess.run(["tmux", "send-keys", "-t", "server_" + session_name, f"/op @a", "C-m"])
agents_op = check_agent_ops(agent_names, ops_file=f"./server_data_{session_name}/ops.json")
if agents_op:
print("Agents are operators! You are good to go :D")
else:
print("Agents are not operators! Something went wrong :(")
make_ops(agent_names, session_name)
def check_agent_ops(agent_names, ops_file="ops.json"):
with open(ops_file, "r") as f:
ops_data = json.load(f)
ops_names = [op["name"] for op in ops_data]
for agent in agent_names:
if agent not in ops_names:
return False
return True
def make_script_file_and_run(script_content, session_name, file_name):
script_dir = os.path.dirname(file_name)
os.makedirs(script_dir, exist_ok=True)
@ -323,6 +459,12 @@ def make_profiles(agent_names, models, apis, template_profile="profiles/collab_p
"model": models[index],
"url": url
}
elif apis[index] == "ollama":
profile["model"] = {
"api": "ollama",
"model": models[index],
"embedding": "ollama"
}
else:
profile["model"] = models[index]
@ -372,6 +514,23 @@ def copy_server_files(source_path, dest_path):
print(f"Server files copied to {dest_path}")
except Exception as e:
print(f"Error copying server files: {e}")
time.sleep(10)
same_files = check_same_files(source_path, dest_path)
if not same_files:
copy_server_files(source_path, dest_path)
print("The destination path does not contain all the same files as the source path.")
else:
print("The destination path contains all the same files as the source path.")
def check_same_files(d1, d2):
items1 = set(os.listdir(d1))
items2 = set(os.listdir(d2))
if items1 != items2:
return False
return True
def delete_server_files(dest_path):
"""Delete server files from the specified location."""
@ -380,17 +539,37 @@ def delete_server_files(dest_path):
print(f"Server files deleted from {dest_path}")
except Exception as e:
print(f"Error deleting server files: {e}")
if not os.path.exists(dest_path):
print("Server files deleted successfully.")
else:
print("Error deleting server files.")
delete_server_files(dest_path)
def launch_world(server_path="./server_data/", agent_names=["andy", "jill"], session_name="server"):
def launch_world(server_path="./server_data/", agent_names=["andy", "jill"], session_name="server", port=55916):
"""Launch the Minecraft world."""
print(server_path)
print(f"Launching Minecraft world with port {port}...")
cmd = f"cd {server_path} && java -jar server.jar"
subprocess.run(['tmux', 'new-session', '-d', '-s', session_name], check=True)
subprocess.run(["tmux", "send-keys", "-t", session_name, cmd, "C-m"])
# for agent in agent_names:
# print(f"\n\n/op {agent}\n\n")
# subprocess.run(["tmux", "send-keys", "-t", session_name, f"/op {agent}", "C-m"])
time.sleep(5)
time.sleep(10)
if not test_server_running(port):
print("Server failed to start. Retrying...")
launch_world(server_path, agent_names, session_name, port)
def test_server_running(port=55916):
host = 'localhost'
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
try:
s.connect((host, port))
print("Server is running on port 55916")
return True
except ConnectionRefusedError:
print("Server is not running on port 55916")
return False
def kill_world(session_name="server"):
"""Kill the Minecraft world."""

View file

@ -2,8 +2,9 @@
"name": "andy",
"model": "claude-3-5-haiku-latest",
"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: "
}

View file

@ -39,7 +39,7 @@ export default
"code_timeout_mins": -1, // minutes code is allowed to run. -1 for no timeout
"relevant_docs_count": 5, // Parameter: -1 = all, 0 = no references, 5 = five references. If exceeding the maximum, all reference documents are returned.
"max_messages": 150, // max number of messages to keep in context
"max_messages": process.env.MAX_MESSAGES || 15, // max number of messages to keep in context
"num_examples": 2, // number of examples to give to the model
"max_commands": -1, // max number of commands that can be used in consecutive responses. -1 for no limit
"verbose_commands": true, // show full command syntax

View file

@ -24,6 +24,8 @@ export class Agent {
}
console.log('Starting agent initialization with profile:', profile_fp);
// Initialize components with more detailed error handling
console.log('Initializing action manager...');
@ -45,7 +47,21 @@ export class Agent {
console.log('Initializing examples...');
await this.prompter.initExamples();
console.log('Initializing task...');
this.task = new Task(this, task_path, task_id);
// load mem first before doing task
let save_data = null;
if (load_mem) {
save_data = this.history.load();
}
console.log(save_data);
let taskStart = null;
if (save_data) {
taskStart = save_data.taskStart;
} else {
taskStart = Date.now();
}
// incorporate new restart time into task
this.task = new Task(this, task_path, task_id, taskStart);
this.blocked_actions = settings.blocked_actions.concat(this.task.blocked_actions || []);
blacklistCommands(this.blocked_actions);
@ -56,10 +72,7 @@ export class Agent {
initModes(this);
let save_data = null;
if (load_mem) {
save_data = this.history.load();
}
this.bot.on('login', () => {
console.log(this.name, 'logged in!');

View file

@ -86,6 +86,7 @@ export class History {
turns: this.turns,
self_prompting_state: this.agent.self_prompter.state,
self_prompt: this.agent.self_prompter.isStopped() ? null : this.agent.self_prompter.prompt,
taskStart: this.agent.task.taskStartTime,
last_sender: this.agent.last_sender
};
writeFileSync(this.memory_fp, JSON.stringify(data, null, 2));

View file

@ -460,7 +460,14 @@ export async function collectBlock(bot, blockType, num=1, exclude=null) {
return false;
}
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++;
await autoLight(bot);
}
@ -823,7 +830,7 @@ export async function putInChest(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 {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.
@ -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);
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.`);
await chestContainer.close();
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();
log(bot, `Successfully took ${to_take} ${itemName} from the chest.`);
return true;
log(bot, `Successfully took ${totalTaken} ${itemName} from the chest.`);
return totalTaken > 0;
}
export async function viewChest(bot) {

View file

@ -126,25 +126,39 @@ class CookingCraftingTaskValidator {
this.data = data;
this.agent = agent;
}
validate() {
const result = checkItemPresence(this.data, this.agent);
let score = 0;
if (result.success) {
score = 1;
validate(has_initiated) {
if (has_initiated) {
const result = checkItemPresence(this.data, this.agent);
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,
};
}
}
export class Task {
constructor(agent, task_path, task_id) {
constructor(agent, task_path, task_id, taskStartTime = null) {
this.agent = agent;
this.data = null;
this.taskTimeout = 300;
this.taskStartTime = Date.now();
console.log("task start time", taskStartTime);
if (taskStartTime !== null)
this.taskStartTime = taskStartTime;
else
this.taskStartTime = Date.now();
console.log(this.taskStartTime);
this.validator = null;
this.reset_function = null;
this.blocked_actions = [];
@ -188,6 +202,7 @@ export class Task {
this.name = this.agent.name;
this.available_agents = settings.profiles.map((p) => JSON.parse(readFileSync(p, 'utf8')).name);
this.agent_initialized = false;
}
getAgentGoal() {
@ -239,7 +254,7 @@ export class Task {
isDone() {
let res = null;
if (this.validator)
res = this.validator.validate();
res = this.validator.validate(this.agent_initialized);
if (res && res.valid) {
return {"message": 'Task successful', "score": res.score};
}
@ -311,6 +326,8 @@ export class Task {
await new Promise((resolve) => setTimeout(resolve, 500));
}
this.agent_initialized = true;
if (this.initiator) {
await this.initiator.init();
}

View file

@ -86,6 +86,16 @@ export function isHostile(mob) {
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) {
let item = mcdata.itemsByName[itemName];
if (item) {

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,16 @@
{
"num_tasks": 199,
"avg_depth": 2.2525252525252526,
"std_depth": 0.9248907589704736,
"num_tasks_based_depth": {
"0": 98,
"1": 72,
"2": 20,
"3": 8
},
"num_missing_resources": {
"0": 116,
"1": 76,
"2": 6
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,16 @@
{
"num_tasks": 184,
"avg_depth": 2.4754098360655736,
"std_depth": 0.9684626549338964,
"num_tasks_based_depth": {
"0": 72,
"1": 78,
"2": 21,
"3": 12
},
"num_missing_resources": {
"0": 108,
"1": 66,
"2": 9
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,15 @@
{
"num_tasks": 129,
"avg_depth": 2.5625,
"std_depth": 1.0879309490955758,
"num_tasks_based_depth": {
"0": 56,
"1": 52,
"2": 12,
"3": 8
},
"num_missing_resources": {
"0": 100,
"1": 28
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,15 @@
{
"num_tasks": 131,
"avg_depth": 2.8461538461538463,
"std_depth": 0.9880948137434719,
"num_tasks_based_depth": {
"0": 45,
"1": 60,
"2": 15,
"3": 10
},
"num_missing_resources": {
"0": 95,
"1": 35
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,14 @@
{
"num_tasks": 205,
"avg_depth": 2.1176470588235294,
"std_depth": 0.7578881603955948,
"num_tasks_based_depth": {
"0": 100,
"1": 76,
"2": 28
},
"num_missing_resources": {
"0": 145,
"1": 59
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,14 @@
{
"num_tasks": 172,
"avg_depth": 2.280701754385965,
"std_depth": 0.6947013990604671,
"num_tasks_based_depth": {
"0": 63,
"1": 81,
"2": 27
},
"num_missing_resources": {
"0": 135,
"1": 36
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,14 @@
{
"num_tasks": 153,
"avg_depth": 2.1578947368421053,
"std_depth": 0.7443229275647865,
"num_tasks_based_depth": {
"0": 72,
"1": 60,
"2": 20
},
"num_missing_resources": {
"0": 128,
"1": 24
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,14 @@
{
"num_tasks": 136,
"avg_depth": 2.259259259259259,
"std_depth": 0.6436350813697311,
"num_tasks_based_depth": {
"0": 50,
"1": 65,
"2": 20
},
"num_missing_resources": {
"0": 110,
"1": 25
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,16 @@
{
"num_tasks": 276,
"avg_depth": 2.260869565217391,
"std_depth": 0.7642780796194337,
"num_tasks_based_depth": {
"0": 100,
"1": 100,
"2": 76
},
"num_missing_resources": {
"0": 148,
"1": 91,
"2": 35,
"3": 2
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,15 @@
{
"num_tasks": 281,
"avg_depth": 2.2562277580071175,
"std_depth": 0.7487869226953681,
"num_tasks_based_depth": {
"0": 100,
"1": 100,
"2": 81
},
"num_missing_resources": {
"0": 171,
"1": 79,
"2": 31
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,16 @@
{
"num_tasks": 248,
"avg_depth": 2.0766129032258065,
"std_depth": 0.8020748166140171,
"num_tasks_based_depth": {
"0": 100,
"1": 100,
"2": 48
},
"num_missing_resources": {
"0": 155,
"1": 66,
"2": 25,
"3": 2
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,15 @@
{
"num_tasks": 240,
"avg_depth": 2.0166666666666666,
"std_depth": 0.7525881269917101,
"num_tasks_based_depth": {
"0": 100,
"1": 100,
"2": 40
},
"num_missing_resources": {
"0": 173,
"1": 64,
"2": 3
}
}

View file

@ -0,0 +1,703 @@
{
"multiagent_crafting_pink_wool_full_plan__depth_0": {
"goal": "Collaborate with other agents to craft an pink_wool",
"conversation": "Let's work together to craft an pink_wool.",
"initial_inventory": {
"0": {
"pink_dye": 1
},
"1": {
"black_wool": 1
}
},
"agent_count": 2,
"target": "pink_wool",
"number_of_target": 1,
"type": "techtree",
"max_depth": 1,
"depth": 0,
"timeout": 300,
"blocked_actions": {
"0": [],
"1": []
},
"missing_items": [],
"requires_ctable": false
},
"multiagent_crafting_lime_wool_partial_plan__depth_0": {
"goal": "Collaborate with other agents to craft an lime_wool",
"conversation": "Let's work together to craft an lime_wool.",
"initial_inventory": {
"0": {
"lime_dye": 1
},
"1": {
"black_wool": 1
}
},
"agent_count": 2,
"target": "lime_wool",
"number_of_target": 1,
"type": "techtree",
"max_depth": 2,
"depth": 0,
"timeout": 300,
"blocked_actions": {
"0": [
],
"1": ["!getCraftingPlan"]
},
"missing_items": [
],
"requires_ctable": false
},
"multiagent_crafting_purple_banner_full_plan_requires_ctable__depth_0": {
"goal": "Collaborate with other agents to craft an purple_banner",
"conversation": "Let's work together to craft an purple_banner.",
"initial_inventory": {
"0": {
"purple_wool": 4,
"stick": 1
},
"1": {
"purple_wool": 3,
"crafting_table": 1
}
},
"agent_count": 2,
"target": "purple_banner",
"number_of_target": 1,
"type": "techtree",
"max_depth": 3,
"depth": 0,
"timeout": 300,
"blocked_actions": {
"0": [],
"1": []
},
"missing_items": [],
"requires_ctable": true
},
"multiagent_crafting_soul_campfire_partial_plan_requires_ctable__depth_0": {
"goal": "Collaborate with other agents to craft an soul_campfire",
"conversation": "Let's work together to craft an soul_campfire.",
"initial_inventory": {
"0": {
"oak_planks": 2,
"soul_sand": 1,
"dark_oak_log": 2
},
"1": {
"oak_planks": 1,
"dark_oak_log": 1,
"crafting_table": 1
}
},
"agent_count": 2,
"target": "soul_campfire",
"number_of_target": 1,
"type": "techtree",
"max_depth": 2,
"depth": 0,
"timeout": 300,
"blocked_actions": {
"0": [
"!getCraftingPlan"
],
"1": []
},
"missing_items": [],
"requires_ctable": true
},
"multiagent_crafting_bookshelf_full_plan_requires_ctable__depth_0": {
"goal": "Collaborate with other agents to craft a bookshelf",
"conversation": "Let's work together to craft a bookshelf.",
"initial_inventory": {
"0": {
"oak_planks": 4,
"book": 2
},
"1": {
"oak_planks": 2,
"book": 1,
"crafting_table": 1
}
},
"agent_count": 2,
"target": "bookshelf",
"number_of_target": 1,
"type": "techtree",
"max_depth": 1,
"depth": 0,
"timeout": 300,
"blocked_actions": {
"0": [],
"1": []
},
"missing_items": [],
"requires_ctable": true
},
"multiagent_crafting_compass_partial_plan_requires_ctable__depth_0": {
"goal": "Collaborate with other agents to craft a compass",
"conversation": "Let's work together to craft a compass.",
"initial_inventory": {
"0": {
"iron_ingot": 2
},
"1": {
"iron_ingot": 2,
"redstone": 1,
"crafting_table": 1
}
},
"agent_count": 2,
"target": "compass",
"number_of_target": 1,
"type": "techtree",
"max_depth": 2,
"depth": 0,
"timeout": 300,
"blocked_actions": {
"0": [
"!getCraftingPlan"
],
"1": []
},
"missing_items": [],
"requires_ctable": true
},
"multiagent_crafting_fishing_rod_full_plan_requires_ctable__depth_1": {
"goal": "Collaborate with other agents to craft a fishing_rod",
"conversation": "Let's work together to craft a fishing_rod.",
"initial_inventory": {
"0": {
"string": 1,
"oak_planks": 2
},
"1": {
"string": 1,
"crafting_table": 1
}
},
"agent_count": 2,
"target": "fishing_rod",
"number_of_target": 1,
"type": "techtree",
"max_depth": 3,
"depth": 1,
"timeout": 300,
"blocked_actions": {
"0": [],
"1": []
},
"missing_items": [
],
"requires_ctable": true
},
"multiagent_crafting_cake_partial_plan_requires_ctable__depth_0": {
"goal": "Collaborate with other agents to craft a cake",
"conversation": "Let's work together to craft a cake.",
"initial_inventory": {
"0": {
"wheat": 2,
"sugar": 1,
"egg": 1
},
"1": {
"wheat": 1,
"milk_bucket": 2,
"crafting_table": 1
}
},
"agent_count": 2,
"target": "cake",
"number_of_target": 1,
"type": "techtree",
"max_depth": 3,
"depth": 0,
"timeout": 300,
"blocked_actions": {
"0": [
"!getCraftingPlan"
],
"1": []
},
"missing_items": [],
"requires_ctable": true
},
"multiagent_crafting_golden_carrot_full_plan_requires_ctable__depth_0": {
"goal": "Collaborate with other agents to craft a golden_carrot",
"conversation": "Let's work together to craft a golden_carrot.",
"initial_inventory": {
"0": {
"gold_nugget": 5,
"carrot": 1
},
"1": {
"gold_nugget": 3,
"crafting_table": 1
}
},
"agent_count": 2,
"target": "golden_carrot",
"number_of_target": 1,
"type": "techtree",
"max_depth": 2,
"depth": 0,
"timeout": 300,
"blocked_actions": {
"0": [],
"1": []
},
"missing_items": [],
"requires_ctable": true
},
"multiagent_crafting_map_partial_plan_requires_ctable__depth_0": {
"goal": "Collaborate with other agents to craft a map",
"conversation": "Let's work together to craft a map.",
"initial_inventory": {
"0": {
"paper": 5
},
"1": {
"paper": 3,
"compass": 1,
"crafting_table": 1
}
},
"agent_count": 2,
"target": "map",
"number_of_target": 1,
"type": "techtree",
"max_depth": 1,
"depth": 0,
"timeout": 300,
"blocked_actions": {
"0": [
"!getCraftingPlan"
],
"1": []
},
"missing_items": [],
"requires_ctable": true
},
"multiagent_crafting_blue_wool_full_plan__depth_0": {
"goal": "Collaborate with other agents to craft blue_wool",
"conversation": "Let's work together to craft blue_wool.",
"initial_inventory": {
"0": {
"blue_dye": 1
},
"1": {
"white_wool": 1
}
},
"agent_count": 2,
"target": "blue_wool",
"number_of_target": 1,
"type": "techtree",
"max_depth": 1,
"depth": 0,
"timeout": 300,
"blocked_actions": {
"0": [],
"1": []
},
"missing_items": [],
"requires_ctable": false
},
"multiagent_crafting_lime_wool_partial_plan__depth_2": {
"goal": "Collaborate with other agents to craft lime_wool",
"conversation": "Let's work together to craft lime_wool.",
"initial_inventory": {
"0": {
"green_dye": 1
},
"1": {
"white_wool": 1,
"bone_meal": 1
}
},
"agent_count": 2,
"target": "lime_wool",
"number_of_target": 1,
"type": "techtree",
"max_depth": 2,
"depth": 1,
"timeout": 300,
"blocked_actions": {
"0": [
"!getCraftingPlan"
],
"1": []
},
"missing_items": [
],
"requires_ctable": false
},
"multiagent_crafting_magenta_wool_full_plan__depth_2": {
"goal": "Collaborate with other agents to craft magenta_wool",
"conversation": "Let's work together to craft magenta_wool.",
"initial_inventory": {
"0": {
"rose_red": 1,
"lapis_lazuli": 1
},
"1": {
"white_wool": 1,
"bone_meal": 1
}
},
"agent_count": 2,
"target": "magenta_wool",
"number_of_target": 1,
"type": "techtree",
"max_depth": 3,
"depth": 2,
"timeout": 300,
"blocked_actions": {
"0": [],
"1": []
},
"missing_items": [
],
"requires_ctable": false
},
"multiagent_crafting_chest_full_plan_requires_ctable__depth_1": {
"goal": "Collaborate with other agents to craft a chest",
"conversation": "Let's work together to craft a chest.",
"initial_inventory": {
"0": {
"oak_log": 1
},
"1": {
"oak_planks": 4,
"crafting_table": 1
}
},
"agent_count": 2,
"target": "chest",
"number_of_target": 1,
"type": "techtree",
"max_depth": 1,
"depth": 1,
"timeout": 300,
"blocked_actions": {
"0": [],
"1": []
},
"missing_items": [],
"requires_ctable": true
},
"multiagent_crafting_barrel_partial_plan_requires_ctable__depth_1": {
"goal": "Collaborate with other agents to craft a barrel",
"conversation": "Let's work together to craft a barrel.",
"initial_inventory": {
"0": {
"spruce_planks": 3,
"crafting_table": 1
},
"1": {
"spruce_planks": 3,
"wooden_slab": 1
}
},
"agent_count": 2,
"target": "barrel",
"number_of_target": 1,
"type": "techtree",
"max_depth": 2,
"depth": 1,
"timeout": 300,
"blocked_actions": {
"0": [
"!getCraftingPlan"
],
"1": []
},
"missing_items": [
],
"requires_ctable": true
},
"multiagent_crafting_lectern_full_plan_requires_ctable__depth_2": {
"goal": "Collaborate with other agents to craft a lectern",
"conversation": "Let's work together to craft a lectern.",
"initial_inventory": {
"0": {
"birch_slab": 5,
"crafting_table": 1
},
"1": {
"birch_log": 2,
"book": 3
}
},
"agent_count": 2,
"target": "lectern",
"number_of_target": 1,
"type": "techtree",
"max_depth": 2,
"depth": 2,
"timeout": 300,
"blocked_actions": {
"0": [],
"1": []
},
"missing_items": [
],
"requires_ctable": true
},
"multiagent_crafting_clock_partial_plan_requires_ctable__depth_0": {
"goal": "Collaborate with other agents to craft a clock",
"conversation": "Let's work together to craft a clock.",
"initial_inventory": {
"0": {
"gold_ingot": 2
},
"1": {
"gold_ingot": 2,
"redstone": 1,
"crafting_table": 1
}
},
"agent_count": 2,
"target": "clock",
"number_of_target": 1,
"type": "techtree",
"max_depth": 2,
"depth": 0,
"timeout": 300,
"blocked_actions": {
"0": [
"!getCraftingPlan"
],
"1": []
},
"missing_items": [],
"requires_ctable": true
},
"multiagent_crafting_firework_rocket_partial_plan__depth_0": {
"goal": "Collaborate with other agents to craft firework_rocket",
"conversation": "Let's work together to craft firework_rocket.",
"initial_inventory": {
"0": {
"paper": 1
},
"1": {
"gunpowder": 3
}
},
"agent_count": 2,
"target": "firework_rocket",
"number_of_target": 1,
"type": "techtree",
"max_depth": 2,
"depth": 0,
"timeout": 300,
"blocked_actions": {
"0": [
"!getCraftingPlan"
],
"1": []
},
"missing_items": [],
"requires_ctable": false
},
"multiagent_crafting_enchanting_table_partial_plan_requires_ctable__depth_0": {
"goal": "Collaborate with other agents to craft an enchanting_table",
"conversation": "Let's work together to craft an enchanting_table.",
"initial_inventory": {
"0": {
"diamond": 2,
"obsidian": 2,
"crafting_table": 1
},
"1": {
"obsidian": 2,
"book": 1
}
},
"agent_count": 2,
"target": "enchanting_table",
"number_of_target": 1,
"type": "techtree",
"max_depth": 0,
"depth": 0,
"timeout": 300,
"blocked_actions": {
"0": [
"!getCraftingPlan"
],
"1": []
},
"missing_items": [],
"requires_ctable": true
},
"multiagent_crafting_jukebox_full_plan_requires_ctable__depth_1": {
"goal": "Collaborate with other agents to craft a jukebox",
"conversation": "Let's work together to craft a jukebox.",
"initial_inventory": {
"0": {
"diamond": 1
},
"1": {
"oak_log": 2,
"crafting_table": 1
}
},
"agent_count": 2,
"target": "jukebox",
"number_of_target": 1,
"type": "techtree",
"max_depth": 1,
"depth": 1,
"timeout": 300,
"blocked_actions": {
"0": [],
"1": []
},
"missing_items": [],
"requires_ctable": true
},
"multiagent_crafting_light_gray_wool_full_plan__depth_1": {
"goal": "Collaborate with other agents to craft light_gray_wool",
"conversation": "Let's work together to craft light_gray_wool.",
"initial_inventory": {
"0": {
"black_dye": 1
},
"1": {
"white_wool": 1,
"white_dye": 2
}
},
"agent_count": 2,
"target": "light_gray_wool",
"number_of_target": 1,
"type": "techtree",
"max_depth": 2,
"depth": 1,
"timeout": 300,
"blocked_actions": {
"0": [],
"1": []
},
"missing_items": [
],
"requires_ctable": false
},
"multiagent_crafting_blast_furnace_full_plan_requires_ctable__depth_1": {
"goal": "Collaborate with other agents to craft a blast_furnace",
"conversation": "Let's work together to craft a blast_furnace.",
"initial_inventory": {
"0": {
"iron_ingot": 5,
"smooth_stone": 3
},
"1": {
"cobblestone": 8,
"crafting_table": 1
}
},
"agent_count": 2,
"target": "blast_furnace",
"number_of_target": 1,
"type": "techtree",
"max_depth": 2,
"depth": 1,
"timeout": 300,
"blocked_actions": {
"0": [],
"1": []
},
"missing_items": [
],
"requires_ctable": true
},
"multiagent_crafting_activator_rail_full_plan_requires_ctable__depth_2": {
"goal": "Collaborate with other agents to craft activator_rail",
"conversation": "Let's work together to craft activator_rail.",
"initial_inventory": {
"0": {
"iron_ingot": 3,
"oak_planks": 6
},
"1": {
"redstone": 1,
"iron_ingot": 3,
"crafting_table": 1
}
},
"agent_count": 2,
"target": "activator_rail",
"number_of_target": 1,
"type": "techtree",
"max_depth": 3,
"depth": 2,
"timeout": 300,
"blocked_actions": {
"0": [],
"1": []
},
"missing_items": [
],
"requires_ctable": true
},
"multiagent_crafting_campfire_partial_plan_requires_ctable__depth_2": {
"goal": "Collaborate with other agents to craft campfire",
"conversation": "Let's work together to craft campfire.",
"initial_inventory": {
"0": {
"oak_log": 8
},
"1": {
"coal": 1,
"crafting_table": 1
}
},
"agent_count": 2,
"target": "campfire",
"number_of_target": 1,
"type": "techtree",
"max_depth": 3,
"depth": 2,
"timeout": 300,
"blocked_actions": {
"0": [
"!getCraftingPlan"
],
"1": []
},
"missing_items": [
],
"requires_ctable": true
},
"multiagent_crafting_crossbow_full_plan_requires_ctable__depth_2": {
"goal": "Collaborate with other agents to craft a crossbow",
"conversation": "Let's work together to craft a crossbow.",
"initial_inventory": {
"0": {
"oak_planks": 8,
"iron_ingot": 2
},
"1": {
"string": 2,
"crafting_table": 1
}
},
"agent_count": 2,
"target": "crossbow",
"number_of_target": 1,
"type": "techtree",
"max_depth": 3,
"depth": 2,
"timeout": 300,
"blocked_actions": {
"0": [],
"1": []
},
"missing_items": [
],
"requires_ctable": true
}
}

View file

@ -0,0 +1,291 @@
{
"crafting_iron_pickaxe": {
"goal": "Craft an iron pickaxe.",
"initial_inventory": {
"stone_pickaxe": 1
},
"agent_count": 1,
"target": "iron_pickaxe",
"number_of_target": 1,
"type": "techtree",
"timeout": 500
},
"crafting_stick": {
"goal": "Craft sticks.",
"initial_inventory": {},
"agent_count": 1,
"target": "stick",
"number_of_target": 4,
"type": "techtree",
"timeout": 300
},
"crafting_oak_log": {
"goal": "Get oak logs.",
"initial_inventory": {},
"agent_count": 1,
"target": "oak_log",
"number_of_target": 1,
"type": "techtree",
"timeout": 300
},
"crafting_wooden_pickaxe": {
"goal": "Craft a wooden pickaxe.",
"initial_inventory": {},
"agent_count": 1,
"target": "wooden_pickaxe",
"number_of_target": 1,
"type": "techtree",
"timeout": 300
},
"crafting_stone_pickaxe": {
"goal": "Craft a stone pickaxe.",
"initial_inventory": {},
"agent_count": 1,
"target": "stone_pickaxe",
"number_of_target": 1,
"type": "techtree",
"timeout": 300
},
"crafting_shears": {
"goal": "Craft shears.",
"initial_inventory": {
"iron_pickaxe": 1
},
"agent_count": 1,
"target": "shears",
"number_of_target": 1,
"type": "techtree",
"timeout": 500
},
"crafting_redstone": {
"goal": "Get redstone.",
"initial_inventory": {
"iron_pickaxe": 1
},
"agent_count": 1,
"target": "redstone",
"number_of_target": 1,
"type": "techtree",
"timeout": 300
},
"crafting_gold_ingot": {
"goal": "Get gold ingot.",
"initial_inventory": {
"iron_pickaxe": 1
},
"agent_count": 1,
"target": "gold_ingot",
"number_of_target": 1,
"type": "techtree",
"timeout": 500
},
"crafting_copper_ingot": {
"goal": "Get copper ingot.",
"initial_inventory": {
"iron_pickaxe": 1
},
"agent_count": 1,
"target": "copper_ingot",
"number_of_target": 1,
"type": "techtree",
"timeout": 500
},
"crafting_diamond": {
"goal": "Get diamond.",
"initial_inventory": {
"iron_pickaxe": 1
},
"agent_count": 1,
"target": "diamond",
"number_of_target": 1,
"type": "techtree",
"timeout": 500
},
"crafting_pink_wool_missing_wool": {
"goal": "Craft a pink wool.",
"initial_inventory": {
"pink_dye": 1,
"shears": 1
},
"agent_count": 1,
"target": "pink_wool",
"number_of_target": 1,
"type": "techtree",
"timeout": 500
},
"crafting_light_gray_banner": {
"goal": "Craft a light gray banner.",
"initial_inventory": {
"shears": 1,
"light_gray_dye": 7,
"oak_planks": 1,
"wool": 5
},
"agent_count": 1,
"target": "light_gray_banner",
"number_of_target": 1,
"type": "techtree",
"timeout": 500
},
"crafting_brush_missing_copper_ingot_": {
"goal": "Craft a brush.",
"initial_inventory": {
"feather": 1,
"diamond_pickaxe": 1
},
"agent_count": 1,
"target": "brush",
"number_of_target": 1,
"type": "techtree",
"timeout": 500
},
"crafting_shield_missing_planks": {
"goal": "Craft a shield.",
"initial_inventory": {
"iron_ingot": 6
},
"agent_count": 1,
"target": "shield",
"number_of_target": 1,
"type": "techtree",
"timeout": 300
},
"crafting_shield_missing_iron_ingot": {
"goal": "Craft a shield.",
"initial_inventory": {
"oak_planks": 7
},
"agent_count": 1,
"target": "shield",
"number_of_target": 1,
"type": "techtree",
"timeout": 500
},
"crafting_chest_minecart": {
"goal": "Craft a chest minecart.",
"agent_count": 1,
"initial_inventory":{
"chest": 1,
"minecart": 1
},
"target": "chest_minecart",
"number_of_target": 1,
"type": "techtree",
"timeout": 300
},
"crafting_stone_hoe": {
"goal": "Craft a stone hoe.",
"initial_inventory": {
"wooden_pickaxe": 1
},
"agent_count": 1,
"target": "stone_hoe",
"number_of_target": 1,
"type": "techtree",
"timeout": 300
},
"crafting_wooden_axe": {
"goal": "Craft a wooden axe.",
"initial_inventory": {},
"agent_count": 1,
"target": "wooden_axe",
"number_of_target": 1,
"type": "techtree",
"timeout": 300
},
"crafting_wooden_shovel": {
"goal": "Craft a wooden shovel.",
"initial_inventory": {},
"agent_count": 1,
"target": "wooden_shovel",
"number_of_target": 1,
"type": "techtree",
"timeout": 300
},
"crafting_crafting_table": {
"goal": "Craft a crafting table.",
"initial_inventory": {},
"agent_count": 1,
"target": "crafting_table",
"number_of_target": 1,
"type": "techtree",
"timeout": 300
},
"crafting_furnace": {
"goal": "Craft a furnace.",
"initial_inventory": {
"wooden_pickaxe": 1
},
"agent_count": 1,
"target": "furnace",
"number_of_target": 1,
"type": "techtree",
"timeout": 300
},
"crafting_torch": {
"goal": "Craft torches.",
"initial_inventory": {
"wooden_pickaxe": 1
},
"agent_count": 1,
"target": "torch",
"number_of_target": 4,
"type": "techtree",
"timeout": 300
},
"crafting_iron_ingot": {
"goal": "Get iron ingot.",
"initial_inventory": {
"stone_pickaxe": 1
},
"agent_count": 1,
"target": "iron_ingot",
"number_of_target": 1,
"type": "techtree",
"timeout": 500
},
"crafting_diamond_from_stone_pickaxe": {
"goal": "Get a diamond using only a stone pickaxe.",
"initial_inventory": {
"stone_pickaxe": 1
},
"agent_count": 1,
"target": "diamond",
"number_of_target": 1,
"type": "techtree",
"timeout": 500
},
"crafting_diamond_pickaxe": {
"goal": "Craft a diamond pickaxe.",
"initial_inventory": {
"iron_pickaxe": 1
},
"agent_count": 1,
"target": "diamond_pickaxe",
"number_of_target": 1,
"type": "techtree",
"timeout": 500
},
"crafting_compass": {
"goal": "Craft a compass.",
"initial_inventory": {
"stone_pickaxe": 1
},
"agent_count": 1,
"target": "compass",
"number_of_target": 1,
"type": "techtree",
"timeout": 500
},
"mining_lapis_lazuli": {
"goal": "Mine lapis lazuli.",
"initial_inventory": {
"iron_pickaxe": 1
},
"agent_count": 1,
"target": "lapis_lazuli",
"number_of_target": 1,
"type": "techtree",
"timeout": 300
}
}