mirror of
https://github.com/kolbytn/mindcraft.git
synced 2025-08-11 09:45:33 +02:00
Merge pull request #8 from icwhite/constructionTaskRevision
Construction task revision
This commit is contained in:
commit
c9b52ffa5b
9 changed files with 170 additions and 4598470 deletions
7
.gitignore
vendored
7
.gitignore
vendored
|
@ -19,5 +19,10 @@ experiments/
|
||||||
andy_*.json
|
andy_*.json
|
||||||
jill_*.json
|
jill_*.json
|
||||||
src/models/logs/*
|
src/models/logs/*
|
||||||
server_data*
|
server_data/*
|
||||||
results/*
|
results/*
|
||||||
|
tasks/construction_tasks/test_multiagent_construction_tasks.json
|
||||||
|
tasks/construction_tasks/train_multiagent_construction_tasks.json
|
||||||
|
tasks/construction_tasks/test/**
|
||||||
|
tasks/construction_tasks/train/**
|
||||||
|
server_data*
|
||||||
|
|
|
@ -34,7 +34,9 @@ export default
|
||||||
"language": "en", // translate to/from this language. Supports these language names: https://cloud.google.com/translate/docs/languages
|
"language": "en", // translate to/from this language. Supports these language names: https://cloud.google.com/translate/docs/languages
|
||||||
"show_bot_views": false, // show bot's view in browser at localhost:3000, 3001...
|
"show_bot_views": false, // show bot's view in browser at localhost:3000, 3001...
|
||||||
|
|
||||||
|
|
||||||
"allow_insecure_coding": process.env.INSECURE_CODING || false, // allows newAction command and model can write/run code on your computer. enable at own risk
|
"allow_insecure_coding": process.env.INSECURE_CODING || false, // allows newAction command and model can write/run code on your computer. enable at own risk
|
||||||
|
"blocked_actions" : process.env.BLOCKED_ACTIONS || [] , // commands to disable and remove from docs. Ex: ["!setMode"]
|
||||||
"blocked_actions" : process.env.BLOCKED_ACTIONS || ["!checkBlueprint", "!checkBlueprintLevel", "!getBlueprint", "!getBlueprintLevel"] , // commands to disable and remove from docs. Ex: ["!setMode"]
|
"blocked_actions" : process.env.BLOCKED_ACTIONS || ["!checkBlueprint", "!checkBlueprintLevel", "!getBlueprint", "!getBlueprintLevel"] , // commands to disable and remove from docs. Ex: ["!setMode"]
|
||||||
"code_timeout_mins": -1, // minutes code is allowed to run. -1 for no timeout
|
"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.
|
"relevant_docs_count": 5, // Parameter: -1 = all, 0 = no references, 5 = five references. If exceeding the maximum, all reference documents are returned.
|
||||||
|
|
|
@ -18,7 +18,7 @@ export class ConstructionTaskValidator {
|
||||||
}
|
}
|
||||||
let total_blocks = result.mismatches.length + result.matches.length;
|
let total_blocks = result.mismatches.length + result.matches.length;
|
||||||
score = (result.matches.length / total_blocks) * 100;
|
score = (result.matches.length / total_blocks) * 100;
|
||||||
// console.log(`Task is ${score}% complete`);
|
console.log(`Task is ${score}% complete`);
|
||||||
return {
|
return {
|
||||||
"valid": valid,
|
"valid": valid,
|
||||||
"score": score
|
"score": score
|
||||||
|
@ -346,7 +346,7 @@ export function proceduralGeneration(m = 20,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// set materials
|
// 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.length) {
|
||||||
|
@ -441,7 +441,7 @@ export function proceduralGeneration(m = 20,
|
||||||
newZ >= 0 && newZ + newDepth <= p &&
|
newZ >= 0 && newZ + newDepth <= p &&
|
||||||
isSpaceValid(newX, newY, newZ, newLength, newWidth, newDepth)
|
isSpaceValid(newX, newY, newZ, newLength, newWidth, newDepth)
|
||||||
) {
|
) {
|
||||||
console.log(`Placing room at (${newX}, ${newY}, ${newZ}) with dimensions (${newLength}x${newWidth}x${newDepth})`);
|
// console.log(`Placing room at (${newX}, ${newY}, ${newZ}) with dimensions (${newLength}x${newWidth}x${newDepth})`);
|
||||||
for (let di = 0; di < newDepth; di++) {
|
for (let di = 0; di < newDepth; di++) {
|
||||||
for (let dj = 0; dj < newLength; dj++) {
|
for (let dj = 0; dj < newLength; dj++) {
|
||||||
for (let dk = 0; dk < newWidth; dk++) {
|
for (let dk = 0; dk < newWidth; dk++) {
|
||||||
|
@ -485,10 +485,15 @@ export function proceduralGeneration(m = 20,
|
||||||
matrix[z][x][y] = material;
|
matrix[z][x][y] = material;
|
||||||
|
|
||||||
// Place the lower half of the door
|
// Place the lower half of the door
|
||||||
matrix[z + 1][x][y] = 'dark_oak_door[half=lower, hinge=left]';
|
// matrix[z + 1][x][y] = 'dark_oak_door[half=lower, hinge=left]';
|
||||||
|
|
||||||
|
matrix[z + 1][x][y] = 'dark_oak_door';
|
||||||
|
|
||||||
|
|
||||||
// Place the upper half of the door
|
// Place the upper half of the door
|
||||||
matrix[z + 2][x][y] = 'dark_oak_door[half=upper, hinge=left]';
|
// matrix[z + 2][x][y] = 'dark_oak_door[half=upper, hinge=left]';
|
||||||
|
matrix[z + 2][x][y] = 'dark_oak_door';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -627,51 +632,46 @@ export function proceduralGeneration(m = 20,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// out of commission
|
//still a little buggy
|
||||||
function addStairs(matrix, x, y, z, direction) {
|
function addStairs(matrix, x, y, z, length, width, material) {
|
||||||
let dz = 0; // Change in Z direction
|
let currentZ = z;
|
||||||
let dx = 0; // Change in X direction
|
let currentX = x + 1;
|
||||||
let facing = '';
|
let currentY = y + 1;
|
||||||
|
let direction = 0;
|
||||||
|
let stepCount = 0;
|
||||||
|
const maxSteps = length * width; // Safety limit
|
||||||
|
|
||||||
// Determine direction and facing
|
while (currentZ >= 0 && currentX < x + length - 1 && currentY < y + width - 1 && stepCount < maxSteps) {
|
||||||
switch (direction) {
|
// Place stair block
|
||||||
case 'north':
|
matrix[currentZ][currentX][currentY] = material || 'stone';
|
||||||
dz = -1;
|
|
||||||
facing = 'oak_stairs[facing=north]';
|
// Clear 3 blocks above for headroom
|
||||||
break;
|
for (let i = 1; i <= 3; i++) {
|
||||||
case 'south':
|
if (currentZ + i < matrix.length) {
|
||||||
dz = 1;
|
matrix[currentZ + i][currentX][currentY] = 'air';
|
||||||
facing = 'oak_stairs[facing=south]';
|
}
|
||||||
break;
|
|
||||||
case 'east':
|
|
||||||
dx = 1;
|
|
||||||
facing = 'oak_stairs[facing=east]';
|
|
||||||
break;
|
|
||||||
case 'west':
|
|
||||||
dx = -1;
|
|
||||||
facing = 'oak_stairs[facing=west]';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
console.error('Invalid stair direction');
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bore stair pattern downwards until we hit a floor or the matrix edge
|
// Move to next position based on direction
|
||||||
let currentZ = z;
|
if (direction === 0) {
|
||||||
while (currentZ > 0 && matrix[currentZ - 1][x][y] === 'air') {
|
currentX++;
|
||||||
// Place stone as foundation
|
if (currentX >= x + length - 1) {
|
||||||
matrix[currentZ - 1][x][y] = 'stone';
|
currentX = x + length - 2;
|
||||||
|
direction = 1;
|
||||||
// Place stair above the stone
|
} else {
|
||||||
matrix[currentZ][x][y] = facing;
|
|
||||||
|
|
||||||
// Move down diagonally
|
|
||||||
x += dx;
|
|
||||||
y += dz;
|
|
||||||
currentZ--;
|
currentZ--;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
currentY++;
|
||||||
|
if (currentY >= y + width - 1) {
|
||||||
|
currentY = y + width - 2;
|
||||||
|
direction = 0;
|
||||||
|
} else {
|
||||||
|
currentZ--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check if we've hit the edge
|
stepCount++;
|
||||||
if (x < 0 || x >= matrix[0].length || y < 0 || y >= matrix[0][0].length) break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -707,19 +707,23 @@ export function proceduralGeneration(m = 20,
|
||||||
|
|
||||||
// Build the first 3 ladder segments from floor level downwards
|
// Build the first 3 ladder segments from floor level downwards
|
||||||
for (let i = 0; i < 3; i++) {
|
for (let i = 0; i < 3; i++) {
|
||||||
|
// Place stone block behind ladder
|
||||||
|
matrix[currentZ][x - 1][y] = 'stone';
|
||||||
|
// Place ladder
|
||||||
matrix[currentZ][x][y] = 'ladder[facing=north]';
|
matrix[currentZ][x][y] = 'ladder[facing=north]';
|
||||||
currentZ -= 1
|
currentZ -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Continue building ladder downwards until a floor is hit or we reach the bottom
|
// Continue building ladder downwards until a floor is hit or we reach the bottom
|
||||||
while (currentZ >= 0 && matrix[currentZ][x][y] === 'air') {
|
while (currentZ >= 0 && matrix[currentZ][x][y] === 'air') {
|
||||||
|
// Place stone block behind ladder
|
||||||
|
matrix[currentZ][x - 1][y] = 'stone';
|
||||||
// Place ladder
|
// Place ladder
|
||||||
matrix[currentZ][x][y] = 'ladder[facing=north]';
|
matrix[currentZ][x][y] = 'ladder[facing=north]';
|
||||||
|
|
||||||
// Move down
|
// Move down
|
||||||
currentZ--;
|
currentZ--;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -806,9 +810,11 @@ 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.length / 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)
|
||||||
|
|
||||||
|
|
||||||
lastRoom = {x: newX, y: newY, z: newZ, length: newLength, width: newWidth, depth: newDepth};
|
lastRoom = {x: newX, y: newY, z: newZ, length: newLength, width: newWidth, depth: newDepth};
|
||||||
|
@ -987,3 +993,24 @@ function matrixToBlueprint(matrix, startCoord) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// testing code
|
||||||
|
|
||||||
|
// let blueprint = proceduralGeneration(10,10,20)
|
||||||
|
// const b = new Blueprint(blueprint)
|
||||||
|
// const result = b.autoBuild();
|
||||||
|
// const commands = result.commands;
|
||||||
|
// const nearbyPosition = result.nearbyPosition;
|
||||||
|
//
|
||||||
|
// import {initBot} from "../../utils/mcdata.js";
|
||||||
|
// let bot = initBot("andy");
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// bot.on('spawn', async () => {
|
||||||
|
// console.log("nearby position", nearbyPosition);
|
||||||
|
// bot.chat(`/tp @andy ${nearbyPosition.x} ${nearbyPosition.y} ${nearbyPosition.z}`);
|
||||||
|
// for (const command of commands) {
|
||||||
|
// bot.chat(command);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
|
@ -413,7 +413,6 @@ export class Task {
|
||||||
//Ensures construction is cleaned out first. -> relies on cheats which are turned off?
|
//Ensures construction is cleaned out first. -> relies on cheats which are turned off?
|
||||||
if (this.blueprint){
|
if (this.blueprint){
|
||||||
const result = this.blueprint.autoDelete();
|
const result = this.blueprint.autoDelete();
|
||||||
// const result = clearHouse(blueprint)
|
|
||||||
const commands = result.commands;
|
const commands = result.commands;
|
||||||
const nearbyPosition = result.nearbyPosition;
|
const nearbyPosition = result.nearbyPosition;
|
||||||
console.log("nearby position", nearbyPosition);
|
console.log("nearby position", nearbyPosition);
|
||||||
|
|
BIN
tasks/.DS_Store
vendored
Normal file
BIN
tasks/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
tasks/construction_tasks/.DS_Store
vendored
Normal file
BIN
tasks/construction_tasks/.DS_Store
vendored
Normal file
Binary file not shown.
|
@ -1,32 +1,24 @@
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
import {proceduralGeneration} from "../../src/agent/task_types/construction_tasks.js";
|
import {proceduralGeneration} from "../../src/agent/task_types/construction_tasks.js";
|
||||||
|
|
||||||
|
//note 'main' (script to run generation of tasks) is at bottom of page
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to initalize agent inventories
|
* Helper function to initalize agent inventories
|
||||||
* @param blueprint
|
* @param blueprint
|
||||||
* @param agents
|
* @param agents
|
||||||
|
* @param evenlySplit - When true, splits materials evenly across inventories
|
||||||
* @returns {{}}
|
* @returns {{}}
|
||||||
*/
|
*/
|
||||||
function createInitialInventory(blueprint, agents) {
|
function createInitialInventory(blueprint, agents, evenlySplit = true) {
|
||||||
/*
|
|
||||||
params:
|
|
||||||
- blueprint object
|
|
||||||
- number of agents (for inventory initialization)
|
|
||||||
|
|
||||||
logic of the function:
|
|
||||||
- loop matrix
|
|
||||||
- every time a new material is hit, put it in a different agents inventory
|
|
||||||
-
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
const inventories = {};
|
const inventories = {};
|
||||||
const materialCounts = {};
|
const materialCounts = {};
|
||||||
let currentAgent = 0;
|
let currentAgent = 0;
|
||||||
|
|
||||||
// Initialize inventories
|
// Initialize inventories
|
||||||
for (let i = 0; i < agents; i++) {
|
for (let i = 0; i < agents; i++) {
|
||||||
inventories[i] = {'diamond_pickaxe':1};
|
inventories[i] = {'diamond_pickaxe': 1};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count materials in blueprint and replace ladder variants with "ladder"
|
// Count materials in blueprint and replace ladder variants with "ladder"
|
||||||
|
@ -53,13 +45,29 @@ function createInitialInventory(blueprint, agents) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (evenlySplit) {
|
||||||
|
// Distribute materials evenly among agents
|
||||||
|
for (const [material, count] of Object.entries(materialCounts)) {
|
||||||
|
const baseAmount = Math.floor(count / agents);
|
||||||
|
const remainder = count % agents;
|
||||||
|
|
||||||
// Distribute materials among agents
|
// Give each agent the base amount
|
||||||
|
for (let i = 0; i < agents; i++) {
|
||||||
|
inventories[i][material] = baseAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Distribute remainder one by one to agents
|
||||||
|
for (let i = 0; i < remainder; i++) {
|
||||||
|
inventories[i][material]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Original distribution - one material type to one agent
|
||||||
for (const [material, count] of Object.entries(materialCounts)) {
|
for (const [material, count] of Object.entries(materialCounts)) {
|
||||||
inventories[currentAgent][material] = count;
|
inventories[currentAgent][material] = count;
|
||||||
currentAgent = (currentAgent + 1) % agents;
|
currentAgent = (currentAgent + 1) % agents;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return inventories;
|
return inventories;
|
||||||
}
|
}
|
||||||
|
@ -78,17 +86,16 @@ function calculateSpaceNeeded(rooms) {
|
||||||
/**
|
/**
|
||||||
* MAIN GENERATION FUNCTION
|
* MAIN GENERATION FUNCTION
|
||||||
*
|
*
|
||||||
* Varies materials, room count, windows and carpets to create different complexities of construction tasks.
|
* Varies agents, materials, room count, windows and carpets to create different complexities of construction tasks.
|
||||||
* @param variants is the number of variants within each complexity level you want.
|
* @param variants is the number of variants within each complexity level you want.
|
||||||
* @returns The tasks as nested JSON {{}}
|
* @returns The tasks as nested JSON {{}}
|
||||||
*/
|
*/
|
||||||
function generateConstructionTasks(variants) {
|
function generateConstructionTasks(variants, agents) {
|
||||||
const materialLevels = 5;
|
const materialLevels = 5;
|
||||||
const agentCount = 2
|
|
||||||
const roomCounts = [4, 6, 8];
|
const roomCounts = [4, 6, 8];
|
||||||
const windowStyles = [0, 1, 2];
|
const windowStyles = [0, 1, 2];
|
||||||
const carpetStyles = [0, 1, 2];
|
const carpetStyles = [0, 1, 2];
|
||||||
const timeout = 600 // 10 min base
|
const timeout = 600; // 10 min base
|
||||||
|
|
||||||
const tasks = {};
|
const tasks = {};
|
||||||
|
|
||||||
|
@ -97,6 +104,7 @@ function generateConstructionTasks(variants) {
|
||||||
for (let w = 0; w < windowStyles.length; w++) {
|
for (let w = 0; w < windowStyles.length; w++) {
|
||||||
for (let c = 0; c < carpetStyles.length; c++) {
|
for (let c = 0; c < carpetStyles.length; c++) {
|
||||||
for (let variant = 0; variant < variants; variant++) {
|
for (let variant = 0; variant < variants; variant++) {
|
||||||
|
|
||||||
const rooms = roomCounts[r];
|
const rooms = roomCounts[r];
|
||||||
const spaceSize = calculateSpaceNeeded(rooms);
|
const spaceSize = calculateSpaceNeeded(rooms);
|
||||||
|
|
||||||
|
@ -105,8 +113,8 @@ function generateConstructionTasks(variants) {
|
||||||
spaceSize,
|
spaceSize,
|
||||||
spaceSize,
|
spaceSize,
|
||||||
rooms,
|
rooms,
|
||||||
4,
|
5,
|
||||||
4,
|
5,
|
||||||
4,
|
4,
|
||||||
5,
|
5,
|
||||||
"air",
|
"air",
|
||||||
|
@ -121,13 +129,14 @@ function generateConstructionTasks(variants) {
|
||||||
type: "construction",
|
type: "construction",
|
||||||
goal: "Make a house with the blueprint",
|
goal: "Make a house with the blueprint",
|
||||||
conversation: "Let's share materials and make a house with the blueprint",
|
conversation: "Let's share materials and make a house with the blueprint",
|
||||||
agent_count: agentCount,
|
agent_count: agents,
|
||||||
initial_inventory: createInitialInventory(blueprint, agentCount),
|
initial_inventory: createInitialInventory(blueprint, agents),
|
||||||
timeout: timeout+(300*r), // 5 minute per additional level of complexity
|
timeout: timeout + (300 * r), // 5 minute per additional level of complexity
|
||||||
blueprint: blueprint,
|
blueprint: blueprint,
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,15 +146,29 @@ function generateConstructionTasks(variants) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// const fs = require('fs');
|
||||||
|
// const path = require('path');
|
||||||
|
|
||||||
//Main: writes the generated tasks to a file.
|
// Function to create directories and generate tasks
|
||||||
const tasks = generateConstructionTasks(5);
|
function setupTaskFiles(baseDirs, agentCounts, variants) {
|
||||||
// Clear existing file content
|
baseDirs.forEach(base => {
|
||||||
fs.writeFileSync('./train_multiagent_construction_tasks.json', '');
|
if (!fs.existsSync(base)) {
|
||||||
// re-add
|
fs.mkdirSync(base, { recursive: true });
|
||||||
fs.writeFileSync(
|
}
|
||||||
'./train_multiagent_construction_tasks.json',
|
|
||||||
JSON.stringify(tasks, null, 2)
|
agentCounts.forEach(count => {
|
||||||
);
|
const tasks = generateConstructionTasks(variants, count);
|
||||||
|
const filePath = path.join(base, `${count}agents.json`);
|
||||||
|
|
||||||
|
fs.writeFileSync(filePath, JSON.stringify(tasks, null, 2));
|
||||||
|
console.log(`Generated tasks saved to ${filePath}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const baseDirs = ['./train', './test'];
|
||||||
|
const agentCounts = [2, 3, 4, 5];
|
||||||
|
const variants = 5;
|
||||||
|
|
||||||
|
setupTaskFiles(baseDirs, agentCounts, variants);
|
||||||
|
|
||||||
console.log("Generated tasks saved to test_multiagent_construction_tasks.json");
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue