From e26f22514e632f22d4bb80c345428187f00c6714 Mon Sep 17 00:00:00 2001 From: Dominic Zimmer Date: Mon, 6 Jul 2020 14:46:46 +0200 Subject: [PATCH] Migrate turtle client and server to /mine --- mine/client.lua | 445 ++++++++++++++++++++++++++++++++++++++++++++++++ mine/server.lua | 46 +++++ 2 files changed, 491 insertions(+) create mode 100644 mine/client.lua create mode 100644 mine/server.lua diff --git a/mine/client.lua b/mine/client.lua new file mode 100644 index 0000000..8453cf2 --- /dev/null +++ b/mine/client.lua @@ -0,0 +1,445 @@ +args = {...} +turtlestate = { + name = os.getComputerLabel(), + id = os.getComputerID(), + fuel = "", + state = "init", + job = nil +} + +function noop() end + +function pair(x, y) + return math.floor((x + y) * (x + y + 1)/2 + y) +end + +function unpairX(z) + local j = math.floor(math.sqrt(0.25 + 2*z) - 0.5) + return j - (z - j*(j+1)/2) +end + + +function unpairZ(z) + local j = math.floor(math.sqrt(0.25 + 2*z) - 0.5) + return z - j * (j+1)/2; +end + +lookup = {4, 1, 3, 0, 2} +local function isDiggingSpot(x, y) + local val = lookup[(y % 5) + 1] + return (x % 5) == val +end + +offset = 10 +function ithSpot(i) + j = offset + while true do + x, z = unpairX(j), unpairZ(j) + if isDiggingSpot(x, z) then + if i <= 1 then + return x, z + else + i = i - 1 + end + end + j = j + 1 + end +end + +function adjustToQuadrant(i, x, z) + if i % 4 == 0 then + return x, z + elseif i % 4 == 1 then + return -z-1, x + elseif i % 4 == 2 then + return z, -x-1 + elseif i % 4 == 3 then + return -z-1, -x-1 + end +end + +function iTo2Dcoords(j) + i = j // 4 + quadrantI = j % 4 -- 0-3 quadrant + counter = 0 -- number of digging spots found + j = 0 -- enumerate 2D plane + while true do + x, z = unpairX(j), unpairZ(j) -- coords in first quadrant + x, z = adjustToQuadrant(quadrantI, x, z) -- map coords correctly into other quadrants + if isDiggingSpot(x, z) then + if counter == i then + return x, z + end + counter = counter + 1 + end + j = j + 1 + end +end + +-- move safely into the direction, not hurting other turtles, but freeing the path if needed. +function moveSafe(moveAction, inspectAction, digAction) + while true do + local status, block = inspectAction() + if status then + if block["name"]:lower():find("turtle") then + -- turtle in front of me. lets wait for it to move + sleep(0.6) + else + digAction() + end + else + -- nothing in the way, try to move + if moveAction() then + break + end + end + end +end + +-- If the block in front of the turtle is desired, take it. +function grabOres() + local status, block = turtle.inspect() + if status and block["name"]:lower():find("ore") then + turtle.dig() + end +end + +-- dig all the way down to bedrock, collect ores +-- Parameters: +-- * moveAction: the **vertical** move action, eg turtle.down +-- * digAction: the **vertical** dig action, eg turtle.digDown +-- * inpectAction: the **vertical** inspect action, eg turtle.inspectDown +-- * limit: if >= 0 * the number of blocks to dig +-- * dig until bedrock is hit +-- +-- +-- Returns: the depth dug +function digDeep(moveAction, digAction, inspectAction, limit) + local depth = 0 + grabOres() + while true do + -- termination condition: + -- * if limit != -1: limit > 0 + -- * otherwise : bedrock beneath + if limit < 0 then + local status, nextblock = inspectAction() + if status and nextblock["name"] == "minecraft:bedrock" then + return depth + end + else + if limit == 0 then + return depth + end + end + -- Limit not reached: keep digging + depth = depth + 1 + limit = limit - 1 + digAction() + moveAction() + grabOres() -- inspect block in front of turtle, take if neccessary + end +end + +function selectCobble() + for i = 1,16 do + turtle.select(i) + item = turtle.getItemDetail() + if item and item["name"] == "minecraft:cobblestone" then + break + end + end +end + +function selectFuel() + for i = 1,16 do + turtle.select(i) + item = turtle.getItemDetail() + if item and (item["name"] == "minecraft:coal" or item["name"] == "minecraft:charcoal") then + break + end + end +end + +function digShaft() + turtle.digDown() + selectCobble() + turtle.placeUp() + turtle.down() + depth = digDeep(turtle.down, turtle.digDown, turtle.inspectDown, -1) + turtle.turnLeft() + digDeep(turtle.up, noop, noop, depth) + turtle.turnLeft() + digDeep(turtle.down, noop, noop, depth) + turtle.turnLeft() + digDeep(turtle.up, noop, noop, depth) + selectCobble() + turtle.placeDown() + turtle.up() + turtle.digUp() + turtle.up() +end + +function digTo(x, z) + --print("Digging to rel. coord ("..tostring(x)..", "..tostring(z)..")") + while z > 0 do + moveSafe(turtle.forward, turtle.inspect, turtle.dig) + z = z - 1 + repeat sleep(0.6) + until (not turtle.digUp()) + end + turtle.turnRight() + while x > 0 do + moveSafe(turtle.forward, turtle.inspect, turtle.dig) + x = x - 1 + repeat sleep(0.6) + until (not turtle.digUp()) + end +end + +function goToSpawn(x, z) + moveSafe(turtle.up, turtle.inspectUp, turtle.digUp) + while z > 0 do + moveSafe(turtle.forward, turtle.inspect, turtle.dig) + z = z - 1 + end + turtle.turnRight() + while x > 0 do + moveSafe(turtle.forward, turtle.inspect, turtle.dig) + x = x - 1 + end +end + +function moveSafeForward() + moveSafe(turtle.forward, turtle.inspect, noop) +end + +function goToBarrel(path) + if path == 0 then + turtle.turnLeft() + moveSafe(turtle.forward, turtle.inspect, noop) + turtle.turnRight() + moveSafe(turtle.forward, turtle.inspect, noop) + moveSafe(turtle.forward, turtle.inspect, noop) + moveSafe(turtle.forward, turtle.inspect, noop) + moveSafe(turtle.forward, turtle.inspect, noop) + moveSafe(turtle.forward, turtle.inspect, noop) + turtle.turnRight() + moveSafe(turtle.forward, turtle.inspect, noop) + moveSafe(turtle.forward, turtle.inspect, noop) + moveSafe(turtle.down, turtle.inspectDown, noop) + else + moveSafe(turtle.forward, turtle.inspect, noop) + turtle.turnRight() + moveSafe(turtle.forward, turtle.inspect, noop) + turtle.turnLeft() + moveSafe(turtle.forward, turtle.inspect, noop) + moveSafe(turtle.forward, turtle.inspect, noop) + moveSafe(turtle.forward, turtle.inspect, noop) + moveSafe(turtle.down, turtle.inspectDown, noop) + turtle.turnRight() + end +end + +function leaveBarrel(path) + if path == 0 then + moveSafe(turtle.forward, turtle.inspect, noop) + moveSafe(turtle.forward, turtle.inspect, noop) + moveSafe(turtle.forward, turtle.inspect, noop) + turtle.turnRight() + moveSafe(turtle.forward, turtle.inspect, noop) + moveSafe(turtle.forward, turtle.inspect, noop) + turtle.turnRight() + else + moveSafe(turtle.forward, turtle.inspect, noop) + moveSafe(turtle.forward, turtle.inspect, noop) + moveSafe(turtle.forward, turtle.inspect, noop) + turtle.turnRight() + moveSafe(turtle.forward, turtle.inspect, noop) + turtle.turnRight() + end +end + +function reportDuty(id, fuelconsumed) + moveSafe(turtle.down, turtle.inspectDown, noop) + moveSafe(turtle.down, turtle.inspectDown, noop) + moveSafe(turtle.down, turtle.inspectDown, noop) + moveSafeForward() + moveSafeForward() + moveSafeForward() + moveSafeForward() + moveSafeForward() + moveSafeForward() + moveSafeForward() + moveSafeForward() + rednet.open("bottom") + --print("Proto: Sending completed Job id") + rednet.broadcast(tostring(id), "jobs") + sleep(0.6) + --print("Proto: Sending fuel status") + rednet.broadcast(tostring(fuelconsumed), "fuel") + while true do + --print("Proto: Awaiting thanks") + sender, message, proto = rednet.receive("jobcomplete") + if message == "thanks" then + break + else + sleep(1) + end + end + --print("Proto: Received thanks") +end + +function enqueueTurtle() + moveSafe(turtle.up, turtle.inspectUp, noop) + moveSafe(turtle.up, turtle.inspectUp, noop) + moveSafe(turtle.up, turtle.inspectUp, noop) + turtle.turnLeft() + moveSafeForward() + moveSafeForward() + moveSafeForward() + turtle.turnRight() + while true do + local status, block = turtle.inspectDown() + if not status then + if turtle.down() then + break -- we moved in line + end + else + if turtle.forward() then + -- pass, thats ok + else + local status, block = turtle.inspect() + if status and not block["name"]:lower():find("turtle") then + turtle.dig() + turtle.forward() + turtle.digUp() + turtle.digDown() + end + end + end + end + -- we moved into line + turtle.turnLeft() + turtle.turnLeft() +end + +function doRefuel() + moveSafeForward() + turtle.turnRight() + while turtle.getFuelLevel() < 1500 do + turtle.suck(4) + selectFuel() + turtle.refuel() + end + turtle.turnLeft() +end + +function goToJob() + moveSafeForward() + moveSafeForward() + moveSafeForward() +end + +function waitForJob() + --print("Waiting for job...") + while true do + status, block = turtle.inspectDown() + if status and block["name"] == "computercraft:wired_modem_full" then + break + else + moveSafeForward() + end + end + rednet.open("bottom") + local retrying = false + while true do + rednet.broadcast("gibjob", "jobs") + sender, message, proto = rednet.receive("newjob", 2) + if message then + job = tonumber(message) + --print("Received job "..tostring(job)) + return job + else + if not retrying then + retrying = true + --print("No job received. I will keep retrying.") + turtlestate["state"] = "Waiting for job... (retrying)" + end + end + end +end + +function emptyToBarrel() + sleep(0.4) + for i = 1,16 do + turtle.select(i) + sleep(0.1) + turtle.dropDown() + end +end + +function drawStatus() + print("Turtle ("..tostring(turtlestate["id"])..")") + print() + print(" \""..turtlestate["name"].."\"") + print() + print() + if turtlestate["job"] then + print("Current job: "..tostring(turtlestate["job"])) + else + print("Current job: ") + end + print() + if turtlestate["job"] then + print("Recent fuel usage: "..tostring(turtlestate["fuel"])) + else + print("Recent fuel usage: ") + end + print() + print("Status:") + print(" "..turtlestate["state"]) + print() +end + +function turtleAI() + while true do + turtlestate["state"] = "Waiting for job..." + drawStatus() + thejob = waitForJob() + turtlestate["job"] = thejob + turtlestate["state"] = "Refueling..." + drawStatus() + doRefuel() + fuel = turtle.getFuelLevel() + turtlestate["state"] = "Headed to the jobsite..." + drawStatus() + goToJob() + x, z = ithSpot(thejob) + digTo(x,z) + turtlestate["state"] = "Digging the Shaft..." + drawStatus() + digShaft() + turtlestate["state"] = "Returning to the station..." + drawStatus() + goToSpawn(x, z) + path = math.floor(math.random() + 0.5) + turtlestate["state"] = "Unloading Inventory..." + drawStatus() + goToBarrel(path) + emptyToBarrel() + leaveBarrel(path) + fuelconsumed = fuel - turtle.getFuelLevel() + --print("I consumed "..tostring(fuelconsumed).." fuel") + --print("Reporting Duty") + turtlestate["fuel"] = fuelconsumed + turtlestate["state"] = "Reporting duty..." + drawStatus() + reportDuty(thejob, fuelconsumed) + turtlestate["job"] = nil + turtlestate["state"] = "Going back in line..." + drawStatus() + enqueueTurtle() + end +end + +turtleAI() diff --git a/mine/server.lua b/mine/server.lua new file mode 100644 index 0000000..76ed962 --- /dev/null +++ b/mine/server.lua @@ -0,0 +1,46 @@ +rednet.open("back") + +curjob = 69 +while true do + print("From what index do you want to resume jobs?") + x = read() + if tonumber(x) then + curjob = tonumber(x) + break + end + print("That's not a number.") +end + +function getNextJob() + curjob = curjob + 1 + return curjob - 1 +end + +while true do + sender, message, proto = rednet.receive("jobs") + if not message then + sleep(0.6) + else + --print("> raw: "..message) + if message == "gibjob" then + if rs.getInput("right") then + job = getNextJob() + rednet.broadcast(tostring(job), "newjob") + print("Found job request. Offering "..tostring(job)) + end + else + -- numberic job is complete + completejob = tonumber(message) + fuelused = "??" + fuelsender, fuelmessage, fuelproto = rednet.receive("fuel") + if fuelmessage then + fuelused = fuelmessage + end + print("Job "..tostring(completejob).." was completed, "..fuelused.." fuel was used") + rednet.broadcast("thanks", "jobcomplete") + log = io.open("jobs.log","a") + log:write(tostring(completejob),"\n") + log:close() + end + end +end