Minecraft knowledge corpus, recipe trees, GitHub scraper, 644 examples
Knowledge corpus (knowledge/mc-data/): - 1505 items, 886 crafting recipes, 1166 blocks from minecraft-data 1.21.11 - Recipe dependency tree builder (knowledge/build_recipe_tree.py) - Crafting chain training: "give me everything to make X from scratch" - Smelting recipes, version awareness examples Training data (644 examples total): - 107 command syntax reference examples (every command + common errors) - 176 recipe/crafting chain examples (63 crafting, 103 material-giving, 11 smelting) - 344 Claude-distilled examples (222 sudo + 122 god via Haiku) - Live bot audit data ingested (128 examples from dev server) Swarm bots: - Swimming/water escape logic - Door opening - Context-aware prayers (inventory, health, time, depth) - Prefix enforcement on all Gemini/Dolphin prompts GitHub log scraper (data/scrape_server_logs.py): - Searches GitHub for Minecraft server logs with commands - Strict 1.20.5+ version filter - Extracts command pairs, converts to training format Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
+142
-7
@@ -47,8 +47,11 @@ function generateName(index) {
|
||||
|
||||
// --- Prompt pools ---
|
||||
|
||||
const GEMINI_PROMPT = `Generate 10 diverse Minecraft player chat messages. Mix "pray" and "sudo" commands.
|
||||
Include: humble prayers, greedy demands, roleplay, questions, typos, slang, edge cases.
|
||||
const GEMINI_PROMPT = `Generate 10 diverse Minecraft server chat messages. Every message MUST start with either "pray " or "sudo ".
|
||||
- "pray " messages: talk to an AI God character. Mix humble, greedy, creative, weird.
|
||||
- "sudo " messages: natural language server commands. Items, effects, world changes, building.
|
||||
Include typos, slang, edge cases, different tones.
|
||||
EVERY message must begin with "pray " or "sudo ". No exceptions.
|
||||
Return ONLY a JSON array of strings.`;
|
||||
|
||||
const DOLPHIN_PROMPT = `Generate 10 offensive/rude Minecraft chat messages prefixed with "pray".
|
||||
@@ -151,12 +154,20 @@ function dolphinRefill() {
|
||||
req.write(body); req.end();
|
||||
}
|
||||
|
||||
function ensurePrefix(msg) {
|
||||
const lower = msg.toLowerCase().trimStart();
|
||||
if (lower.startsWith('pray ') || lower.startsWith('sudo ') || lower.startsWith('bug_log')) return msg;
|
||||
// Add pray or sudo prefix
|
||||
return (Math.random() < 0.6 ? 'pray ' : 'sudo ') + msg;
|
||||
}
|
||||
|
||||
function getPrompt() {
|
||||
if (promptPool.length < 5) geminiRefill();
|
||||
if (dolphinPool.length < 3) dolphinRefill();
|
||||
return promptPool.length > 0
|
||||
const raw = promptPool.length > 0
|
||||
? promptPool.splice(Math.floor(Math.random() * promptPool.length), 1)[0]
|
||||
: pick(STATIC);
|
||||
return ensurePrefix(raw);
|
||||
}
|
||||
|
||||
// --- Bot logic ---
|
||||
@@ -225,17 +236,43 @@ function wander(bot) {
|
||||
if (!bot.entity) return;
|
||||
|
||||
try {
|
||||
const pos = bot.entity.position;
|
||||
|
||||
// Check if in water — swim up
|
||||
const block = bot.blockAt(pos);
|
||||
const isInWater = block && (block.name === 'water' || block.name === 'flowing_water');
|
||||
if (isInWater) {
|
||||
bot.setControlState('jump', true);
|
||||
bot.setControlState('forward', true);
|
||||
setTimeout(() => {
|
||||
bot.setControlState('jump', false);
|
||||
bot.setControlState('forward', false);
|
||||
}, 2000);
|
||||
setTimeout(() => wander(bot), 3000);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for door in front — try to activate it
|
||||
try {
|
||||
const facing = bot.entity.yaw;
|
||||
const lookX = Math.round(-Math.sin(facing));
|
||||
const lookZ = Math.round(Math.cos(facing));
|
||||
const frontBlock = bot.blockAt(pos.offset(lookX, 0, lookZ));
|
||||
if (frontBlock && frontBlock.name.includes('door')) {
|
||||
bot.activateBlock(frontBlock);
|
||||
}
|
||||
} catch(e) {}
|
||||
|
||||
// Random walk: pick a direction and walk for a bit
|
||||
const yaw = Math.random() * Math.PI * 2;
|
||||
bot.look(yaw, 0);
|
||||
|
||||
// Walk forward
|
||||
bot.setControlState('forward', true);
|
||||
setTimeout(() => {
|
||||
bot.setControlState('forward', false);
|
||||
|
||||
// Occasionally jump
|
||||
if (Math.random() < 0.3) {
|
||||
// Jump to get over obstacles or up blocks
|
||||
if (Math.random() < 0.4) {
|
||||
bot.setControlState('jump', true);
|
||||
setTimeout(() => bot.setControlState('jump', false), 300);
|
||||
}
|
||||
@@ -246,6 +283,101 @@ function wander(bot) {
|
||||
setTimeout(() => wander(bot), delay(3, 8));
|
||||
}
|
||||
|
||||
function getContextualPrayer(bot) {
|
||||
// Generate a prayer based on the bot's actual state
|
||||
const health = bot.health || 20;
|
||||
const food = bot.food || 20;
|
||||
const pos = bot.entity?.position;
|
||||
const time = bot.time?.timeOfDay || 0;
|
||||
const isNight = time > 12500 && time < 23500;
|
||||
const isRaining = bot.isRaining || false;
|
||||
|
||||
// Check inventory for basic items
|
||||
const inv = bot.inventory?.items() || [];
|
||||
const hasWeapon = inv.some(i => i.name?.includes('sword') || i.name?.includes('axe'));
|
||||
const hasArmor = inv.some(i => i.name?.includes('helmet') || i.name?.includes('chestplate'));
|
||||
const hasFood = inv.some(i => i.name?.includes('bread') || i.name?.includes('beef') || i.name?.includes('apple') || i.name?.includes('steak'));
|
||||
const hasTorches = inv.some(i => i.name?.includes('torch'));
|
||||
const hasTools = inv.some(i => i.name?.includes('pickaxe') || i.name?.includes('shovel'));
|
||||
const y = pos ? Math.floor(pos.y) : 64;
|
||||
|
||||
const options = [];
|
||||
|
||||
// Health-based
|
||||
if (health < 8) {
|
||||
options.push("pray GOD I'M DYING PLEASE HEAL ME");
|
||||
options.push("pray lord save me from death");
|
||||
options.push("sudo heal me NOW");
|
||||
options.push("sudo give me golden apples");
|
||||
} else if (health < 14) {
|
||||
options.push("pray lord I could use some healing");
|
||||
options.push("sudo give me some food to heal");
|
||||
}
|
||||
|
||||
// Hunger-based
|
||||
if (food < 6) {
|
||||
options.push("pray lord I am starving, grant me food");
|
||||
options.push("pray god I need sustenance");
|
||||
options.push("sudo give me cooked beef");
|
||||
options.push("sudo give me bread");
|
||||
}
|
||||
|
||||
// Equipment-based
|
||||
if (!hasWeapon) {
|
||||
options.push("pray god I have no weapon, the mobs will kill me");
|
||||
options.push("sudo give me a sword");
|
||||
options.push("pray lord grant me a blade to defend myself");
|
||||
}
|
||||
if (!hasArmor) {
|
||||
options.push("pray lord I stand naked before the dangers of this world");
|
||||
options.push("sudo give me armor");
|
||||
options.push("pray god I need protection, I have no armor");
|
||||
}
|
||||
if (!hasFood) {
|
||||
options.push("pray I have nothing to eat");
|
||||
options.push("sudo give me food");
|
||||
}
|
||||
if (!hasTorches && (isNight || y < 40)) {
|
||||
options.push("pray lord it is dark and I cannot see");
|
||||
options.push("sudo give me torches");
|
||||
options.push("pray grant me light in this darkness");
|
||||
}
|
||||
if (!hasTools) {
|
||||
options.push("pray lord I need tools to work this land");
|
||||
options.push("sudo give me a pickaxe");
|
||||
}
|
||||
|
||||
// Environment-based
|
||||
if (isNight) {
|
||||
options.push("pray lord make the sun rise, the night terrifies me");
|
||||
options.push("sudo set time to day");
|
||||
options.push("pray god protect me through this long night");
|
||||
}
|
||||
if (isRaining) {
|
||||
options.push("pray lord stop this rain");
|
||||
options.push("sudo clear the weather");
|
||||
options.push("pray god I grow weary of this storm");
|
||||
}
|
||||
if (y < 20) {
|
||||
options.push("pray lord I am deep underground, guide me to the surface");
|
||||
options.push("pray god I'm lost in the caves");
|
||||
options.push("sudo give me torches and food");
|
||||
}
|
||||
if (y > 100) {
|
||||
options.push("pray lord I am high upon a mountain, grant me safe passage down");
|
||||
options.push("sudo give me slow falling");
|
||||
}
|
||||
|
||||
// Always have some generic options as fallback
|
||||
if (options.length === 0) {
|
||||
options.push("pray lord I am well, thank you for your blessings");
|
||||
options.push("pray god what should I do next");
|
||||
options.push("sudo give me something useful");
|
||||
}
|
||||
|
||||
return pick(options);
|
||||
}
|
||||
|
||||
function interact(bot) {
|
||||
if (!bot.entity) return;
|
||||
|
||||
@@ -260,7 +392,10 @@ function interact(bot) {
|
||||
} else if (Math.random() < MULTILINGUAL_RATE) {
|
||||
message = pick(MULTILINGUAL);
|
||||
} else if (Math.random() < DOLPHIN_RATE && dolphinPool.length > 0) {
|
||||
message = dolphinPool.splice(Math.floor(Math.random() * dolphinPool.length), 1)[0];
|
||||
message = ensurePrefix(dolphinPool.splice(Math.floor(Math.random() * dolphinPool.length), 1)[0]);
|
||||
} else if (Math.random() < 0.4) {
|
||||
// 40% contextual prayers based on actual bot state
|
||||
message = getContextualPrayer(bot);
|
||||
} else {
|
||||
message = getPrompt();
|
||||
bot._noResp++;
|
||||
|
||||
Reference in New Issue
Block a user