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:
2026-03-18 20:33:09 -04:00
parent 65ee146043
commit 0473eb0b50
14 changed files with 103586 additions and 7 deletions
+142 -7
View File
@@ -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++;