This commit is contained in:
Ayush Maniar 2025-04-07 20:33:54 -07:00
commit c43dc879d2
11 changed files with 13285 additions and 137 deletions

View file

@ -53,16 +53,19 @@ def analyze_json_file(file_path):
try: try:
with open(file_path, 'r') as f: with open(file_path, 'r') as f:
data = json.load(f) data = json.load(f)
if 'turns' in data and isinstance(data['turns'], list): if "turns" in data:
for turn in reversed(data['turns']): # Check turns from the end for turn in data["turns"]:
if turn.get('role') == 'system' and isinstance(turn.get('content'), str): if turn.get("role") == "system" and "content" in turn:
code = turn["content"].split(":")[-1].strip() if isinstance(turn["content"], str) and "Task ended with score : " in turn["content"]:
if code in ["2", "1"]: # Check for success codes score_found = True
return True if "Task ended with score : 1" in turn["content"]:
elif 0 < float(code) < 1: # Check for other success indicators return 1
return code elif "Task ended with score : 0" in turn["content"]:
else: return 0
return False else:
score = float(turn["content"].split(":")[-1].strip())
return score
return False return False
except FileNotFoundError: except FileNotFoundError:
print(f"Error: File not found: {file_path}") print(f"Error: File not found: {file_path}")
@ -82,12 +85,12 @@ def extract_result(folder_path):
if not json_files: if not json_files:
return None return None
else: else:
outcome = False score = None
for json_file in json_files: for json_file in json_files:
outcome = analyze_json_file(json_file) score = analyze_json_file(json_file)
if outcome: if score is not None:
return True return score
return False return 0
def aggregate_results(local_folders): def aggregate_results(local_folders):
""" """
@ -110,7 +113,7 @@ def aggregate_results(local_folders):
result = extract_result(folder_path) result = extract_result(folder_path)
if result is not None: if result is not None:
total += 1 total += 1
successful += float(result) successful += result
except Exception as e: except Exception as e:
print(f"Error processing {folder_name}: {e}") print(f"Error processing {folder_name}: {e}")
@ -161,28 +164,6 @@ def update_keys_json():
with open("keys.json", 'w', encoding='utf-8') as file: with open("keys.json", 'w', encoding='utf-8') as file:
json.dump(data, file, indent=4) json.dump(data, file, indent=4)
def check_task_completion(agents):
"""Check memory.json files of all agents to determine task success/failure."""
for agent in agents:
memory_path = f"bots/{agent}/memory.json"
try:
with open(memory_path, 'r') as f:
memory = json.load(f)
# Check the last system message in turns
for turn in reversed(memory['turns']):
if turn['role'] == 'system' and 'code' in turn['content']:
# Extract completion code
if 'code : 2' in turn['content']:
return True # Task successful
elif 'code : 4' in turn['content']:
return False # Task failed
except (FileNotFoundError, json.JSONDecodeError) as e:
print(f"Error reading memory for agent {agent}: {e}")
continue
return False # Default to failure if no conclusive result found
def set_environment_variable_tmux_session(session_name, key, value): def set_environment_variable_tmux_session(session_name, key, value):
"""Set an environment variable for the current process.""" """Set an environment variable for the current process."""
subprocess.run(["tmux", "send-keys", "-t", session_name, f"export {key}={value}", "C-m"]) subprocess.run(["tmux", "send-keys", "-t", session_name, f"export {key}={value}", "C-m"])
@ -202,7 +183,8 @@ def launch_parallel_experiments(task_path,
max_messages=15, max_messages=15,
num_examples=2, num_examples=2,
no_pruning=False, no_pruning=False,
block_conversation=False): block_conversation=False,
run_in_tmux=True):
with open(task_path, 'r', encoding='utf-8') as file: with open(task_path, 'r', encoding='utf-8') as file:
content = file.read() content = file.read()
@ -211,8 +193,6 @@ def launch_parallel_experiments(task_path,
task_ids = json_data.keys() task_ids = json_data.keys()
task_type = json_data[list(task_ids)[0]]["type"] task_type = json_data[list(task_ids)[0]]["type"]
# split the task_ids into num_parallel groups # split the task_ids into num_parallel groups
task_ids = list(task_ids) task_ids = list(task_ids)
task_ids_split = [task_ids[i::num_parallel] for i in range(num_parallel)] task_ids_split = [task_ids[i::num_parallel] for i in range(num_parallel)]
@ -224,7 +204,10 @@ def launch_parallel_experiments(task_path,
elif task_type == "construction": elif task_type == "construction":
world_name = "Superflat" world_name = "Superflat"
servers = create_server_files("./server_data/", num_parallel, world_name=world_name) if run_in_tmux:
servers = create_server_files("./server_data/", num_parallel, world_name=world_name)
else:
servers = [(f"./server_data_{i}/", 55916 + i) for i in range(num_parallel)]
date_time = datetime.now().strftime("%m-%d_%H-%M") date_time = datetime.now().strftime("%m-%d_%H-%M")
experiments_folder = f"experiments/{exp_name}_{date_time}" experiments_folder = f"experiments/{exp_name}_{date_time}"
exp_name = f"{exp_name}_{date_time}" exp_name = f"{exp_name}_{date_time}"
@ -259,7 +242,8 @@ def launch_parallel_experiments(task_path,
max_messages=max_messages, max_messages=max_messages,
num_examples=num_examples, num_examples=num_examples,
no_pruning=no_pruning, no_pruning=no_pruning,
block_conversation=block_conversation) block_conversation=block_conversation,
run_in_tmux=run_in_tmux)
time.sleep(5) time.sleep(5)
total_num_tasks = len(task_ids) total_num_tasks = len(task_ids)
@ -307,7 +291,8 @@ def launch_server_experiment(task_path,
max_messages=15, max_messages=15,
num_examples=2, num_examples=2,
no_pruning=False, no_pruning=False,
block_conversation=False): block_conversation=False,
run_in_tmux=True):
""" """
Launch a Minecraft server and run experiments on it. Launch a Minecraft server and run experiments on it.
@ -360,39 +345,107 @@ def launch_server_experiment(task_path,
agent_profiles_str += f'\"{agent}\", ' agent_profiles_str += f'\"{agent}\", '
agent_profiles_str += f"\"{agent_profiles[-1]}\"]'" agent_profiles_str += f"\"{agent_profiles[-1]}\"]'"
print(agent_profiles_str) print(agent_profiles_str)
launch_world(server_path, session_name="server_" + session_name, agent_names=agent_names, port=server_port) if run_in_tmux:
print("run in tmux is true")
subprocess.run(['tmux', 'new-session', '-d', '-s', session_name], check=True) 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 variables
set_environment_variable_tmux_session(session_name, "MINECRAFT_PORT", server_port) if run_in_tmux:
set_environment_variable_tmux_session(session_name, "MINDSERVER_PORT", mindserver_port) set_environment_variable_tmux_session(session_name, "MINECRAFT_PORT", server_port)
set_environment_variable_tmux_session(session_name, "PROFILES", agent_profiles_str) set_environment_variable_tmux_session(session_name, "MINDSERVER_PORT", mindserver_port)
set_environment_variable_tmux_session(session_name, "MAX_MESSAGES", str(max_messages)) set_environment_variable_tmux_session(session_name, "PROFILES", agent_profiles_str)
set_environment_variable_tmux_session(session_name, "NUM_EXAMPLES", str(num_examples)) set_environment_variable_tmux_session(session_name, "MAX_MESSAGES", str(max_messages))
set_environment_variable_tmux_session(session_name, "LOG_ALL", "true") set_environment_variable_tmux_session(session_name, "NUM_EXAMPLES", str(num_examples))
if insecure_coding: set_environment_variable_tmux_session(session_name, "LOG_ALL", "true")
set_environment_variable_tmux_session(session_name, "INSECURE_CODING", "true") if insecure_coding:
make_ops(agent_names, session_name) set_environment_variable_tmux_session(session_name, "INSECURE_CODING", "true")
make_ops(agent_names, session_name)
else:
agent_profiles_str = "["
for agent in agent_profiles[:-1]:
agent_profiles_str += f"\"{agent}\", "
agent_profiles_str += f"\"{agent_profiles[-1]}\"]"
# print(agent_profiles_str)
os.environ["PROFILES"] = agent_profiles_str
os.environ["MAX_MESSAGES"] = str(max_messages)
os.environ["NUM_EXAMPLES"] = str(num_examples)
os.environ["LOG_ALL"] = "true"
run_script(task_path,
task_ids,
num_exp,
experiments_folder,
agent_names,
server_path,
s3=s3,
s3_path=s3_path,
session_name=session_name,
run_in_tmux=run_in_tmux)
# add the bots as op # add the bots as op
# op_script_content = "sleep 5\n\op @p" * 20 # op_script_content = "sleep 5\n\op @p" * 20
# op_script_file = f"./tmp/op_script_{session_name}.sh" # op_script_file = f"./tmp/op_script_{session_name}.sh"
# make_script_file_and_run(op_script_content, "server_" + session_name, op_script_file) # make_script_file_and_run(op_script_content, "server_" + session_name, op_script_file)
blocked_actions = [] # blocked_actions = []
if not no_pruning: # if not no_pruning:
if task_type == "cooking": # if task_type == "cooking":
blocked_actions = BLOCKED_ACTIONS_COOKING # blocked_actions = BLOCKED_ACTIONS_COOKING
elif task_type == "techtree": # elif task_type == "techtree":
blocked_actions = BLOCKED_ACTIONS_CRAFTING # blocked_actions = BLOCKED_ACTIONS_CRAFTING
elif task_type == "construction": # elif task_type == "construction":
blocked_actions = BLOCKED_ACTIONS_CONSTRUCTION # blocked_actions = BLOCKED_ACTIONS_CONSTRUCTION
if block_conversation: # if block_conversation:
blocked_actions += ["!endConversation", "!startConversation"] # blocked_actions += ["!endConversation", "!startConversation"]
set_environment_variable_tmux_session(session_name, "BLOCKED_ACTIONS", blocked_actions) # set_environment_variable_tmux_session(session_name, "BLOCKED_ACTIONS", blocked_actions)
# script_content = ""
# for task_id in task_ids:
# # Create a separate folder for each task_id
# task_folder = os.path.join(experiments_folder, str(task_id))
# os.makedirs(task_folder, exist_ok=True)
# assert os.path.exists(task_folder), f"Directory {task_folder} was not created"
# print(f"Created directory: {task_folder}")
# cmd = f"node main.js --task_path \'{task_path}\' --task_id {task_id}"
# cp_cmd = f"cp {agent_names[0]}.json {server_path}bots/{agent_names[0]}/profile.json"
# for _ in range(num_exp):
# script_content += f"{cmd}\n"
# script_content += "sleep 2\n"
# for agent in agent_names:
# agent_file_path = os.path.join(task_folder, f"{agent}_{_}.json")
# script_content += f"echo 'Saving to {agent_file_path}'\n"
# cp_cmd = f"cp bots/{agent}/memory.json {agent_file_path}"
# script_content += f"echo '{cp_cmd}'\n"
# script_content += f"{cp_cmd}\n"
# script_content += "sleep 1\n"
# if s3:
# 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"
# script_content += "sleep 1\n"
# script_content += f"sleep 10\n"
# if s3:
# for agent in agent_names:
# 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, script_file, session_name=session_name, run_in_tmux=True)
def run_script(task_path,
task_ids,
num_exp,
experiments_folder,
agent_names,
server_path,
s3=False,
s3_path="mindcraft-experiments",
session_name="0",
run_in_tmux=True,):
script_content = "" script_content = ""
for task_id in task_ids: for task_id in task_ids:
# Create a separate folder for each task_id # Create a separate folder for each task_id
@ -426,7 +479,8 @@ def launch_server_experiment(task_path,
# Create a temporary shell script file # Create a temporary shell script file
script_file = f"./tmp/experiment_script_{session_name}.sh" script_file = f"./tmp/experiment_script_{session_name}.sh"
make_script_file_and_run(script_content, session_name, script_file) make_script_file_and_run(script_content, script_file, session_name=session_name, run_in_tmux=run_in_tmux)
def make_ops(agent_names, session_name): def make_ops(agent_names, session_name):
"""Make the agents operators in the Minecraft world.""" """Make the agents operators in the Minecraft world."""
@ -458,7 +512,10 @@ def check_agent_ops(agent_names, ops_file="ops.json"):
return False return False
return True return True
def make_script_file_and_run(script_content, session_name, file_name): def make_script_file_and_run(script_content,
file_name,
session_name="0",
run_in_tmux=True):
script_dir = os.path.dirname(file_name) script_dir = os.path.dirname(file_name)
os.makedirs(script_dir, exist_ok=True) os.makedirs(script_dir, exist_ok=True)
assert os.path.exists(script_dir), f"Script directory {script_dir} was not created" assert os.path.exists(script_dir), f"Script directory {script_dir} was not created"
@ -472,9 +529,10 @@ def make_script_file_and_run(script_content, session_name, file_name):
script_file_run = "bash " + file_name script_file_run = "bash " + file_name
# Execute the shell script using subprocess # Execute the shell script using subprocess
subprocess.run(["tmux", "send-keys", "-t", session_name, script_file_run, "C-m"]) if run_in_tmux:
subprocess.run(["tmux", "send-keys", "-t", session_name, script_file_run, "C-m"])
# subprocess.run(["tmux", "send-keys", "-t", session_name, f"/op {agent_names[0]}", "C-m"]) else:
subprocess.run(script_file_run.split())
def make_profiles(agent_names, models, apis, template_profile="profiles/collab_profile.json", url="http://127.0.0.1:8000/v1"): def make_profiles(agent_names, models, apis, template_profile="profiles/collab_profile.json", url="http://127.0.0.1:8000/v1"):
assert len(agent_names) == len(models) assert len(agent_names) == len(models)
@ -645,6 +703,7 @@ def main():
# edit_server_properties_file("../server_data/", 55917) # edit_server_properties_file("../server_data/", 55917)
parser = argparse.ArgumentParser(description='Run Minecraft AI agent experiments') parser = argparse.ArgumentParser(description='Run Minecraft AI agent experiments')
parser.add_argument('--no_launch_world', action='store_true', help='Do not launch the Minecraft world')
parser.add_argument('--task_path', default="multiagent_crafting_tasks.json", help='Path to the task file') parser.add_argument('--task_path', default="multiagent_crafting_tasks.json", help='Path to the task file')
parser.add_argument('--num_agents', default=2, type=int, help='Number of agents to run') parser.add_argument('--num_agents', default=2, type=int, help='Number of agents to run')
parser.add_argument('--num_exp', default=1, type=int, help='Number of experiments to run') parser.add_argument('--num_exp', default=1, type=int, help='Number of experiments to run')
@ -666,14 +725,15 @@ def main():
args = parser.parse_args() args = parser.parse_args()
print(args) print(args)
if not args.no_launch_world:
try: try:
subprocess.run(['tmux', 'kill-server'], check=True) subprocess.run(['tmux', 'kill-server'], check=True)
except: except:
print("No tmux session to kill") print("No tmux session to kill")
# delete all server files # delete all server files
clean_up_server_files(args.num_parallel) if not args.no_launch_world:
clean_up_server_files(args.num_parallel)
if args.add_keys: if args.add_keys:
update_keys_json() update_keys_json()
@ -692,7 +752,8 @@ def main():
max_messages=args.max_messages, max_messages=args.max_messages,
num_examples=args.num_examples, num_examples=args.num_examples,
no_pruning=args.no_pruning, no_pruning=args.no_pruning,
block_conversation=args.block_conversation) block_conversation=args.block_conversation,
run_in_tmux=not args.no_launch_world)
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View file

@ -12,14 +12,12 @@ export class ConstructionTaskValidator {
let valid = false; let valid = false;
let score = 0; let score = 0;
let result = this.blueprint.check(this.agent.bot); let result = this.blueprint.check(this.agent.bot);
if (result.mismatches.length === 0) { if (result.mismatches.y_amount === 0) {
valid = true; valid = true;
console.log('Task is complete'); console.log('Task is complete');
} }
let total_blocks = result.mismatches.length + result.matches.length; let total_blocks = result.mismatches.y_amount + result.matches.y_amount;
score = (result.matches.length / total_blocks) * 100; score = (result.matches.y_amount / total_blocks) * 100;
console.log(`Agent name is ${this.agent.name}`);
console.log(`Task is ${score}% complete \n\n`);
return { return {
"valid": valid, "valid": valid,
"score": score "score": score
@ -37,10 +35,10 @@ export class ConstructionTaskValidator {
export function resetConstructionWorld(bot, blueprint) { export function resetConstructionWorld(bot, blueprint) {
console.log('Resetting world...'); console.log('Resetting world...');
const starting_position = blueprint.levels[0].coordinates; const starting_position = blueprint.levels[0].coordinates;
const length = blueprint.levels[0].placement.length + 5; const y_amount = blueprint.levels[0].placement.y_amount + 5;
const height = blueprint.levels.length + 5; const height = blueprint.levels.y_amount + 5;
const width = blueprint.levels[0].placement[0].length + 5; const width = blueprint.levels[0].placement[0].y_amount + 5;
const command = `/fill ${starting_position[0]} ${starting_position[1]} ${starting_position[2]} ${starting_position[0] + width} ${starting_position[1] + height} ${starting_position[2] + length} air`; const command = `/fill ${starting_position[0]} ${starting_position[1]} ${starting_position[2]} ${starting_position[0] + width} ${starting_position[1] + height} ${starting_position[2] + y_amount} air`;
bot.chat(command); bot.chat(command);
console.log('World reset'); console.log('World reset');
} }
@ -50,7 +48,7 @@ export function checkLevelBlueprint(agent, levelNum) {
const bot = agent.bot; const bot = agent.bot;
try { try {
const result = blueprint.checkLevel(bot, levelNum); const result = blueprint.checkLevel(bot, levelNum);
if (result.mismatches.length === 0) { if (result.mismatches.y_amount === 0) {
return `Level ${levelNum} is correct`; return `Level ${levelNum} is correct`;
} else { } else {
let explanation = blueprint.explainLevelDifference(bot, levelNum); let explanation = blueprint.explainLevelDifference(bot, levelNum);
@ -69,7 +67,7 @@ export function checkBlueprint(agent) {
const blueprint = agent.task.blueprint; const blueprint = agent.task.blueprint;
const bot = agent.bot; const bot = agent.bot;
const result = blueprint.check(bot); const result = blueprint.check(bot);
if (result.mismatches.length === 0) { if (result.mismatches.y_amount === 0) {
return "Blueprint is correct"; return "Blueprint is correct";
} else { } else {
let explanation = blueprint.explainBlueprintDifference(bot); let explanation = blueprint.explainBlueprintDifference(bot);
@ -97,11 +95,11 @@ export class Blueprint {
var placement_string = "[\n"; var placement_string = "[\n";
for (let row of placement) { for (let row of placement) {
placement_string += "["; placement_string += "[";
for (let i = 0; i < row.length - 1; i++) { for (let i = 0; i < row.y_amount - 1; i++) {
let item = row[i]; let item = row[i];
placement_string += `${item}, `; placement_string += `${item}, `;
} }
let final_item = row[row.length - 1]; let final_item = row[row.y_amount - 1];
placement_string += `${final_item}],\n`; placement_string += `${final_item}],\n`;
} }
placement_string += "]"; placement_string += "]";
@ -118,7 +116,7 @@ export class Blueprint {
explainBlueprintDifference(bot) { explainBlueprintDifference(bot) {
var explanation = ""; var explanation = "";
const levels = this.data.levels; const levels = this.data.levels;
for (let i = 0; i < levels.length; i++) { for (let i = 0; i < levels.y_amount; i++) {
let level_explanation = this.explainLevelDifference(bot, i); let level_explanation = this.explainLevelDifference(bot, i);
explanation += level_explanation + "\n"; explanation += level_explanation + "\n";
} }
@ -129,7 +127,7 @@ export class Blueprint {
const mismatches = results.mismatches; const mismatches = results.mismatches;
const levelData = this.data.levels[levelNum]; const levelData = this.data.levels[levelNum];
if (mismatches.length === 0) { if (mismatches.y_amount === 0) {
return `Level ${levelData.level} is complete`; return `Level ${levelData.level} is complete`;
} }
var explanation = `Level ${levelData.level} `; var explanation = `Level ${levelData.level} `;
@ -153,7 +151,7 @@ export class Blueprint {
const levels = this.data.levels; const levels = this.data.levels;
const mismatches = []; const mismatches = [];
const matches = []; const matches = [];
for (let i = 0; i < levels.length; i++) { for (let i = 0; i < levels.y_amount; i++) {
const result = this.checkLevel(bot, i); const result = this.checkLevel(bot, i);
mismatches.push(...result.mismatches); mismatches.push(...result.mismatches);
matches.push(...result.matches); matches.push(...result.matches);
@ -173,9 +171,9 @@ export class Blueprint {
const mismatches = []; const mismatches = [];
const matches = []; const matches = [];
for (let zOffset = 0; zOffset < placement.length; zOffset++) { for (let zOffset = 0; zOffset < placement.y_amount; zOffset++) {
const row = placement[zOffset]; const row = placement[zOffset];
for (let xOffset = 0; xOffset < row.length; xOffset++) { for (let xOffset = 0; xOffset < row.y_amount; xOffset++) {
const blockName = row[xOffset]; const blockName = row[xOffset];
const x = startCoords[0] + xOffset; const x = startCoords[0] + xOffset;
@ -240,15 +238,15 @@ export class Blueprint {
// Update bounds // Update bounds
minX = Math.min(minX, baseX); minX = Math.min(minX, baseX);
maxX = Math.max(maxX, baseX + placement[0].length - 1); maxX = Math.max(maxX, baseX + placement[0].y_amount - 1);
minY = Math.min(minY, baseY); minY = Math.min(minY, baseY);
maxY = Math.max(maxY, baseY); maxY = Math.max(maxY, baseY);
minZ = Math.min(minZ, baseZ); minZ = Math.min(minZ, baseZ);
maxZ = Math.max(maxZ, baseZ + placement.length - 1); maxZ = Math.max(maxZ, baseZ + placement.y_amount - 1);
// Loop through the 2D placement array // Loop through the 2D placement array
for (let z = 0; z < placement.length; z++) { for (let z = 0; z < placement.y_amount; z++) {
for (let x = 0; x < placement[z].length; x++) { for (let x = 0; x < placement[z].y_amount; x++) {
const blockType = placement[z][x]; const blockType = placement[z][x];
if (blockType) { if (blockType) {
const setblockCommand = `/setblock ${baseX + x} ${baseY} ${baseZ + z} ${blockType}`; const setblockCommand = `/setblock ${baseX + x} ${baseY} ${baseZ + z} ${blockType}`;
@ -289,15 +287,15 @@ export class Blueprint {
// Update bounds // Update bounds
minX = Math.min(minX, baseX) - 30; minX = Math.min(minX, baseX) - 30;
maxX = Math.max(maxX, baseX + placement[0].length - 1) + 30; maxX = Math.max(maxX, baseX + placement[0].y_amount - 1) + 30;
minY = Math.min(minY, baseY); minY = Math.min(minY, baseY);
maxY = Math.max(maxY, baseY); maxY = Math.max(maxY, baseY);
minZ = Math.min(minZ, baseZ) - 30; minZ = Math.min(minZ, baseZ) - 30;
maxZ = Math.max(maxZ, baseZ + placement.length - 1) + 30; maxZ = Math.max(maxZ, baseZ + placement.y_amount - 1) + 30;
// Loop through the 2D placement array // Loop through the 2D placement array
for (let z = 0; z < placement.length; z++) { for (let z = 0; z < placement.y_amount; z++) {
for (let x = 0; x < placement[z].length; x++) { for (let x = 0; x < placement[z].y_amount; x++) {
const blockType = placement[z][x]; const blockType = placement[z][x];
if (blockType) { if (blockType) {
const setblockCommand = `/setblock ${baseX + x} ${baseY} ${baseZ + z} air`; const setblockCommand = `/setblock ${baseX + x} ${baseY} ${baseZ + z} air`;
@ -350,8 +348,8 @@ export function proceduralGeneration(m = 20,
complexity = 4, complexity = 4,
startCoord = [148,-60,-170]) { startCoord = [148,-60,-170]) {
// Build 3D space // Build 3D space
const matrix = Array.from({length: p}, () => const matrix = Array.from({y_amount: p}, () =>
Array.from({length: m}, () => Array.from({y_amount: m}, () =>
Array(n).fill('air') Array(n).fill('air')
) )
); );
@ -359,7 +357,7 @@ export function proceduralGeneration(m = 20,
// todo: extrapolate into another param? then have set materials be dynamic? // todo: extrapolate into another param? then have set materials be dynamic?
let roomMaterials = ["stone", "terracotta", "quartz_block", "copper_block", "purpur_block"] let roomMaterials = ["stone", "terracotta", "quartz_block", "copper_block", "purpur_block"]
if (complexity < roomMaterials.length) { if (complexity < roomMaterials.y_amount) {
roomMaterials = roomMaterials.slice(0, complexity + 1); roomMaterials = roomMaterials.slice(0, complexity + 1);
} }
@ -510,9 +508,9 @@ export function proceduralGeneration(m = 20,
// Takes in a room and randomly converts some faces to be windows // Takes in a room and randomly converts some faces to be windows
function addWindowsAsSquares(matrix, x, y, z, newLength, newWidth, newDepth, material) { function addWindowsAsSquares(matrix, x, y, z, newLength, newWidth, newDepth, material) {
// Matrix dimensions // Matrix dimensions
const matrixDepth = matrix.length; const matrixDepth = matrix.y_amount;
const matrixLength = matrix[0].length; const matrixLength = matrix[0].y_amount;
const matrixWidth = matrix[0][0].length; const matrixWidth = matrix[0][0].y_amount;
const windowX = Math.ceil(minRoomWidth / 2) const windowX = Math.ceil(minRoomWidth / 2)
const windowY = Math.ceil(minRoomLength / 2) const windowY = Math.ceil(minRoomLength / 2)
const windowZ = Math.ceil(minRoomDepth / 2) const windowZ = Math.ceil(minRoomDepth / 2)
@ -593,9 +591,9 @@ export function proceduralGeneration(m = 20,
function addWindowsAsPlane(matrix, x, y, z, newLength, newWidth, newDepth, material) { function addWindowsAsPlane(matrix, x, y, z, newLength, newWidth, newDepth, material) {
// Ensure the new dimensions are within bounds // Ensure the new dimensions are within bounds
const maxX = matrix[0].length; const maxX = matrix[0].y_amount;
const maxY = matrix[0][0].length; const maxY = matrix[0][0].y_amount;
const maxZ = matrix.length; const maxZ = matrix.y_amount;
// Each face has a 30% chance of becoming a window // Each face has a 30% chance of becoming a window
if (Math.random() < 0.8) { if (Math.random() < 0.8) {
@ -643,21 +641,21 @@ export function proceduralGeneration(m = 20,
//still a little buggy //still a little buggy
function addStairs(matrix, x, y, z, length, width, material) { function addStairs(matrix, x, y, z, y_amount, width, material) {
let currentZ = z; let currentZ = z;
let currentX = x + 1; let currentX = x + 1;
let currentY = y + 1; let currentY = y + 1;
let direction = 0; let direction = 0;
let stepCount = 0; let stepCount = 0;
const maxSteps = length * width; // Safety limit const maxSteps = y_amount * width; // Safety limit
while (currentZ >= 0 && currentX < x + length - 1 && currentY < y + width - 1 && stepCount < maxSteps) { while (currentZ >= 0 && currentX < x + y_amount - 1 && currentY < y + width - 1 && stepCount < maxSteps) {
// Place stair block // Place stair block
matrix[currentZ][currentX][currentY] = material || 'stone'; matrix[currentZ][currentX][currentY] = material || 'stone';
// Clear 3 blocks above for headroom // Clear 3 blocks above for headroom
for (let i = 1; i <= 3; i++) { for (let i = 1; i <= 3; i++) {
if (currentZ + i < matrix.length) { if (currentZ + i < matrix.y_amount) {
matrix[currentZ + i][currentX][currentY] = 'air'; matrix[currentZ + i][currentX][currentY] = 'air';
} }
} }
@ -665,8 +663,8 @@ export function proceduralGeneration(m = 20,
// Move to next position based on direction // Move to next position based on direction
if (direction === 0) { if (direction === 0) {
currentX++; currentX++;
if (currentX >= x + length - 1) { if (currentX >= x + y_amount - 1) {
currentX = x + length - 2; currentX = x + y_amount - 2;
direction = 1; direction = 1;
} else { } else {
currentZ--; currentZ--;
@ -700,7 +698,7 @@ export function proceduralGeneration(m = 20,
// Consider a random probability of adding a carpet // Consider a random probability of adding a carpet
if (Math.random() < probability) { if (Math.random() < probability) {
// Choose a random color for the carpet // Choose a random color for the carpet
let randomColor = colors[Math.floor(Math.random() * colors.length)]; let randomColor = colors[Math.floor(Math.random() * colors.y_amount)];
// Add carpet one z position above the floor with a random color // Add carpet one z position above the floor with a random color
matrix[z + 1][x][y] = `${randomColor}_carpet`; matrix[z + 1][x][y] = `${randomColor}_carpet`;
} }
@ -773,7 +771,7 @@ export function proceduralGeneration(m = 20,
for (let attempt = 0; attempt < 150; attempt++) { for (let attempt = 0; attempt < 150; attempt++) {
const material = roomMaterials[Math.floor(Math.random() * roomMaterials.length)]; const material = roomMaterials[Math.floor(Math.random() * roomMaterials.y_amount)];
// dimensions of room // dimensions of room
@ -790,7 +788,7 @@ export function proceduralGeneration(m = 20,
newZ = 0; // Ground floor newZ = 0; // Ground floor
if (validateAndBuildBorder(matrix, newX, newY, newZ, newLength, newWidth, newDepth, m, n, p, material)) { if (validateAndBuildBorder(matrix, newX, newY, newZ, newLength, newWidth, newDepth, m, n, p, material)) {
lastRoom = {x: newX, y: newY, z: newZ, length: newLength, width: newWidth, depth: newDepth}; lastRoom = {x: newX, y: newY, z: newZ, y_amount: newLength, width: newWidth, depth: newDepth};
roomPlaced = true; roomPlaced = true;
placedRooms++; placedRooms++;
@ -820,14 +818,14 @@ export function proceduralGeneration(m = 20,
embellishments(carpetStyle, windowStyle, matrix, newX, newY, newZ, newLength, newWidth, newDepth, material) embellishments(carpetStyle, windowStyle, matrix, newX, newY, newZ, newLength, newWidth, newDepth, material)
// addLadder(matrix, lastRoom.x + Math.floor(lastRoom.length / 2), // addLadder(matrix, lastRoom.x + Math.floor(lastRoom.y_amount / 2),
// lastRoom.y + Math.floor(lastRoom.width / 2), // lastRoom.y + Math.floor(lastRoom.width / 2),
// newZ); // Adding the ladder // newZ); // Adding the ladder
addStairs(matrix, newX, newY, newZ, newLength, newWidth, material) addStairs(matrix, newX, newY, newZ, newLength, newWidth, material)
lastRoom = {x: newX, y: newY, z: newZ, length: newLength, width: newWidth, depth: newDepth}; lastRoom = {x: newX, y: newY, z: newZ, y_amount: newLength, width: newWidth, depth: newDepth};
roomPlaced = true; roomPlaced = true;
placedRooms++; placedRooms++;
break; break;
@ -847,7 +845,7 @@ export function proceduralGeneration(m = 20,
addDoor(matrix, lastRoom.x, lastRoom.y + Math.floor(lastRoom.width / 2), lastRoom.z, material); addDoor(matrix, lastRoom.x, lastRoom.y + Math.floor(lastRoom.width / 2), lastRoom.z, material);
lastRoom = {x: newX, y: newY, z: newZ, length: newLength, width: newWidth, depth: newDepth}; lastRoom = {x: newX, y: newY, z: newZ, y_amount: newLength, width: newWidth, depth: newDepth};
roomPlaced = true; roomPlaced = true;
placedRooms++; placedRooms++;
break; break;
@ -855,7 +853,7 @@ export function proceduralGeneration(m = 20,
break; break;
case 'right': case 'right':
newX = lastRoom.x + lastRoom.length - 1; newX = lastRoom.x + lastRoom.y_amount - 1;
newY = lastRoom.y; newY = lastRoom.y;
newZ = lastRoom.z; newZ = lastRoom.z;
if (validateAndBuildBorder(matrix, newX, newY, newZ, newLength, newWidth, newDepth, m, n, p, material)) { if (validateAndBuildBorder(matrix, newX, newY, newZ, newLength, newWidth, newDepth, m, n, p, material)) {
@ -863,12 +861,12 @@ export function proceduralGeneration(m = 20,
embellishments(carpetStyle, windowStyle, matrix, newX, newY, newZ, newLength, newWidth, newDepth, material) embellishments(carpetStyle, windowStyle, matrix, newX, newY, newZ, newLength, newWidth, newDepth, material)
addDoor(matrix, lastRoom.x + lastRoom.length - 1, addDoor(matrix, lastRoom.x + lastRoom.y_amount - 1,
lastRoom.y + Math.floor(lastRoom.width / 2), lastRoom.y + Math.floor(lastRoom.width / 2),
lastRoom.z, material); lastRoom.z, material);
lastRoom = {x: newX, y: newY, z: newZ, length: newLength, width: newWidth, depth: newDepth}; lastRoom = {x: newX, y: newY, z: newZ, y_amount: newLength, width: newWidth, depth: newDepth};
roomPlaced = true; roomPlaced = true;
placedRooms++; placedRooms++;
break; break;
@ -884,12 +882,12 @@ export function proceduralGeneration(m = 20,
embellishments(carpetStyle, windowStyle, matrix, newX, newY, newZ, newLength, newWidth, newDepth, material) embellishments(carpetStyle, windowStyle, matrix, newX, newY, newZ, newLength, newWidth, newDepth, material)
addDoor(matrix, lastRoom.x + Math.floor(lastRoom.length / 2), addDoor(matrix, lastRoom.x + Math.floor(lastRoom.y_amount / 2),
lastRoom.y + lastRoom.width - 1, lastRoom.y + lastRoom.width - 1,
lastRoom.z, material); lastRoom.z, material);
lastRoom = {x: newX, y: newY, z: newZ, length: newLength, width: newWidth, depth: newDepth}; lastRoom = {x: newX, y: newY, z: newZ, y_amount: newLength, width: newWidth, depth: newDepth};
roomPlaced = true; roomPlaced = true;
placedRooms++; placedRooms++;
break; break;
@ -905,12 +903,12 @@ export function proceduralGeneration(m = 20,
embellishments(carpetStyle, windowStyle, matrix, newX, newY, newZ, newLength, newWidth, newDepth, material) embellishments(carpetStyle, windowStyle, matrix, newX, newY, newZ, newLength, newWidth, newDepth, material)
addDoor(matrix, lastRoom.x + Math.floor(lastRoom.length / 2), addDoor(matrix, lastRoom.x + Math.floor(lastRoom.y_amount / 2),
lastRoom.y, lastRoom.y,
lastRoom.z, material); lastRoom.z, material);
lastRoom = {x: newX, y: newY, z: newZ, length: newLength, width: newWidth, depth: newDepth}; lastRoom = {x: newX, y: newY, z: newZ, y_amount: newLength, width: newWidth, depth: newDepth};
roomPlaced = true; roomPlaced = true;
placedRooms++; placedRooms++;
break; break;
@ -978,7 +976,7 @@ function printMatrix(matrix) {
*/ */
function matrixToBlueprint(matrix, startCoord) { function matrixToBlueprint(matrix, startCoord) {
// Validate inputs // Validate inputs
if (!Array.isArray(matrix) || !Array.isArray(startCoord) || startCoord.length !== 3) { if (!Array.isArray(matrix) || !Array.isArray(startCoord) || startCoord.y_amount !== 3) {
console.log(matrix) console.log(matrix)
throw new Error('Invalid input format'); throw new Error('Invalid input format');
} }
@ -1003,6 +1001,85 @@ function matrixToBlueprint(matrix, startCoord) {
}; };
} }
async function getBlockName(bot, coordinate) {
const blockAtLocation = bot.blockAt(new Vec3(coordinate.x, coordinate.y, coordinate.z));
const blockName = blockAtLocation ? bot.registry.blocks[blockAtLocation.type].name : "air";
return blockName;
}
/**
* Converts a world location to a blueprint. takes some time to ensure that the chunks are loaded before conversion.
* @param startCoord - [x,y,z] that signifies the start of the blueprint
* @param y_amount - how many spaces you want to register from the start coordinate in the y dimension
* @param x_amount - how many spaces in the x direction on minecraft
* @param z_amount - how many spaces from the start coordinate in the z direction in minecraft
* @param bot - the mineflayer agent (ex. andy)
* @returns - a Blueprint object of the converted blueprint
*/
export async function worldToBlueprint(startCoord, y_amount, x_amount, z_amount, bot) {
await bot.waitForChunksToLoad();
const materials = {};
const levels = [];
for (let y = 0; y < y_amount; y++) {
const placement = [];
const coordinates = [startCoord.x, startCoord.y + y, startCoord.z];
for (let z = 0; z < z_amount; z++) {
const row = [];
for (let x = 0; x < x_amount; x++) {
const worldCoord = {
x: startCoord.x + x,
y: startCoord.y + y,
z: startCoord.z + z
};
await bot.waitForChunksToLoad(worldCoord);
const blockName = await getBlockName(bot, worldCoord);
row.push(blockName);
if (blockName !== 'air') {
materials[blockName] = (materials[blockName] || 0) + 1;
}
}
placement.push(row);
}
levels.push({
level: y,
coordinates: coordinates,
placement: placement
})
}
console.log(levels);
const blueprint_data = {
materials: materials,
levels: levels
}
return blueprint_data
}
export function blueprintToTask(blueprint_data, num_agents) {
let initialInventory = {}
for (let j = 0; j < num_agents; j++) {
initialInventory[JSON.stringify(j)] = {};
}
let give_agent = 0;
for (const key of Object.keys(blueprint_data.materials)) {
initialInventory[JSON.stringify(give_agent)][key] = blueprint_data.materials[key];
give_agent = (give_agent + 1) % num_agents;
}
const task = {
type: "construction",
goal: "Make a structure with the blueprint below",
conversation: "Let's share materials and make a structure with the blueprint",
agent_count: 2,
blueprint: blueprint_data,
initial_inventory: initialInventory,
};
return task;
}
// testing code // testing code

View file

@ -379,7 +379,7 @@ export class Prompter {
let prompt = this.profile.saving_memory; let prompt = this.profile.saving_memory;
prompt = await this.replaceStrings(prompt, null, null, to_summarize); prompt = await this.replaceStrings(prompt, null, null, to_summarize);
let resp = await this.chat_model.sendRequest([], prompt); let resp = await this.chat_model.sendRequest([], prompt);
await this._saveLog(prompt, null, resp, 'memSaving'); await this._saveLog(prompt, to_summarize, resp, 'memSaving');
if (resp?.includes('</think>')) { if (resp?.includes('</think>')) {
const [_, afterThink] = resp.split('</think>') const [_, afterThink] = resp.split('</think>')
resp = afterThink resp = afterThink

BIN
tasks/.DS_Store vendored

Binary file not shown.

View file

@ -0,0 +1,688 @@
{
"pyramid": {
"type": "construction",
"goal": "Make a structure with the blueprint below",
"conversation": "Let's share materials and make a structure with the blueprint",
"agent_count": 2,
"blueprint": {
"materials": {
"polished_granite": 1,
"gold_block": 27,
"stone_bricks": 41,
"polished_andesite": 34,
"quartz_block": 16,
"stone": 23,
"polished_diorite": 21,
"quartz_pillar": 2,
"glowstone": 3
},
"levels": [
{
"level": 0,
"coordinates": [
-60,
-60,
6
],
"placement": [
[
"polished_granite",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air"
],
[
"air",
"gold_block",
"stone_bricks",
"polished_andesite",
"gold_block",
"quartz_block",
"polished_andesite",
"gold_block",
"stone_bricks",
"gold_block"
],
[
"air",
"stone_bricks",
"polished_andesite",
"stone",
"polished_diorite",
"polished_andesite",
"stone",
"stone_bricks",
"polished_diorite",
"gold_block"
],
[
"air",
"polished_andesite",
"stone",
"polished_diorite",
"polished_andesite",
"stone",
"stone_bricks",
"polished_diorite",
"stone",
"stone_bricks"
],
[
"air",
"gold_block",
"polished_diorite",
"polished_andesite",
"stone",
"stone_bricks",
"polished_diorite",
"stone",
"stone_bricks",
"polished_andesite"
],
[
"air",
"quartz_block",
"polished_andesite",
"stone",
"stone_bricks",
"polished_diorite",
"stone",
"stone_bricks",
"polished_andesite",
"quartz_block"
],
[
"air",
"polished_andesite",
"stone",
"stone_bricks",
"polished_diorite",
"stone",
"stone_bricks",
"polished_andesite",
"polished_diorite",
"stone_bricks"
],
[
"air",
"gold_block",
"stone_bricks",
"polished_diorite",
"stone",
"stone_bricks",
"polished_andesite",
"polished_diorite",
"stone_bricks",
"polished_andesite"
],
[
"air",
"stone_bricks",
"polished_diorite",
"stone",
"stone_bricks",
"polished_andesite",
"polished_diorite",
"stone_bricks",
"polished_andesite",
"gold_block"
],
[
"air",
"gold_block",
"gold_block",
"stone_bricks",
"polished_andesite",
"quartz_block",
"stone_bricks",
"polished_andesite",
"gold_block",
"gold_block"
]
]
},
{
"level": 1,
"coordinates": [
-60,
-60,
6
],
"placement": [
[
"quartz_pillar",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air"
],
[
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air"
],
[
"air",
"air",
"gold_block",
"stone_bricks",
"polished_andesite",
"quartz_block",
"stone_bricks",
"polished_andesite",
"gold_block",
"air"
],
[
"air",
"air",
"stone_bricks",
"stone",
"polished_diorite",
"polished_andesite",
"stone",
"stone_bricks",
"stone_bricks",
"air"
],
[
"air",
"air",
"polished_andesite",
"polished_diorite",
"polished_andesite",
"stone",
"stone_bricks",
"polished_diorite",
"polished_andesite",
"air"
],
[
"air",
"air",
"quartz_block",
"polished_andesite",
"stone",
"glowstone",
"polished_diorite",
"stone",
"quartz_block",
"air"
],
[
"air",
"air",
"stone_bricks",
"stone",
"stone_bricks",
"polished_diorite",
"stone",
"stone_bricks",
"stone_bricks",
"air"
],
[
"air",
"air",
"polished_andesite",
"stone_bricks",
"polished_diorite",
"stone",
"stone_bricks",
"polished_andesite",
"polished_andesite",
"air"
],
[
"air",
"air",
"gold_block",
"stone_bricks",
"polished_andesite",
"quartz_block",
"stone_bricks",
"polished_andesite",
"gold_block",
"air"
],
[
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air"
]
]
},
{
"level": 2,
"coordinates": [
-60,
-60,
6
],
"placement": [
[
"quartz_pillar",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air"
],
[
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air"
],
[
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air"
],
[
"air",
"air",
"air",
"gold_block",
"stone_bricks",
"quartz_block",
"gold_block",
"gold_block",
"air",
"air"
],
[
"air",
"air",
"air",
"stone_bricks",
"polished_diorite",
"polished_andesite",
"stone",
"polished_andesite",
"air",
"air"
],
[
"air",
"air",
"air",
"quartz_block",
"polished_andesite",
"glowstone",
"stone_bricks",
"quartz_block",
"air",
"air"
],
[
"air",
"air",
"air",
"gold_block",
"stone",
"stone_bricks",
"polished_diorite",
"stone_bricks",
"air",
"air"
],
[
"air",
"air",
"air",
"gold_block",
"polished_andesite",
"quartz_block",
"stone_bricks",
"gold_block",
"air",
"air"
],
[
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air"
],
[
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air"
]
]
},
{
"level": 3,
"coordinates": [
-60,
-60,
6
],
"placement": [
[
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air"
],
[
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air"
],
[
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air"
],
[
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air"
],
[
"air",
"air",
"air",
"air",
"gold_block",
"quartz_block",
"gold_block",
"air",
"air",
"air"
],
[
"air",
"air",
"air",
"air",
"quartz_block",
"glowstone",
"quartz_block",
"air",
"air",
"air"
],
[
"air",
"air",
"air",
"air",
"gold_block",
"quartz_block",
"gold_block",
"air",
"air",
"air"
],
[
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air"
],
[
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air"
],
[
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air"
]
]
},
{
"level": 4,
"coordinates": [
-60,
-60,
6
],
"placement": [
[
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air"
],
[
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air"
],
[
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air"
],
[
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air"
],
[
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air"
],
[
"air",
"air",
"air",
"air",
"air",
"gold_block",
"air",
"air",
"air",
"air"
],
[
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air"
],
[
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air"
],
[
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air"
],
[
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air",
"air"
]
]
}
]
},
"initial_inventory": {
"0": {
"polished_granite": 1,
"stone_bricks": 41,
"quartz_block": 16,
"polished_diorite": 21,
"glowstone": 3
},
"1": {
"gold_block": 27,
"polished_andesite": 34,
"stone": 23,
"quartz_pillar": 2
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,54 @@
import mineflayer from 'mineflayer';
import { worldToBlueprint, blueprintToTask } from '../../src/agent/task_types/construction_tasks.js';
import fs from 'fs';
import { start } from 'repl';
const bot = mineflayer.createBot({
host: 'localhost', // Replace with your server IP or hostname
port: 55916, // Replace with your server port
username: 'andy', // Replace with your bot's username
// password: 'your_bot_password' // Only if the server has online-mode=true
});
bot.on('spawn', async () => {
console.log("Bot spawned. Starting blueprint check...");
// set this to be minX, minY, minZ
const startCoord = {
x: -60,
y: 1,
z: 6,
}
bot.chat(`/tp andy ${startCoord.x} ${startCoord.y} ${startCoord.z}`);
const yOffset = 5;
const xOffset = 10;
const zOffset = 10;
const taskFilePath = '/Users/isadorawhite/izzy_mindcraft/mindcraft/tasks/construction_tasks/custom/pyramid.json';
const task_name = "pyramid";
setTimeout(async () => {
let task_blueprint = await worldToBlueprint(startCoord, yOffset, xOffset, zOffset, bot);
for (const level of task_blueprint.levels) {
// Perform operations on each level
console.log("Level coordinates:", level.coordinates);
const new_coordinates = [level.coordinates[0], -60, level.coordinates[2]];
level.coordinates = new_coordinates;
console.log("New coordinates:", level.coordinates);
}
console.log("Blueprint generated:", task_blueprint.levels[0].coordinates);
const task = blueprintToTask(task_blueprint, 2);
const task_collection = {}
task_collection[task_name] = task;
fs.writeFileSync(taskFilePath, JSON.stringify(task_collection, null, 2), (err) => {
if (err) {
console.error('Error writing task to file:', err);
} else {
console.log('Task dumped to file successfully.');
}
});
}, 5000); // Delay of 5 seconds (5000 milliseconds)
});

Binary file not shown.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff