diff --git a/dominic/canemine.lua b/dominic/canemine.lua index 01e8738..96da3f8 100644 --- a/dominic/canemine.lua +++ b/dominic/canemine.lua @@ -1,4 +1,11 @@ args = {...} +turtlestatus = { + name = os.getComputerLabel(), + id = os.getComputerID(), + fuel = "", + state = "init", + job = nil +} function noop() end @@ -143,7 +150,7 @@ function digShaft() end function digTo(x, z) - print("Digging to rel. coord ("..tostring(x)..", "..tostring(z)..")") + --print("Digging to rel. coord ("..tostring(x)..", "..tostring(z)..")") while z > 0 do moveSafe(turtle.forward, turtle.inspect, turtle.dig) z = z - 1 @@ -304,7 +311,7 @@ function goToJob() end function waitForJob() - print("Waiting for job...") + --print("Waiting for job...") while true do status, block = turtle.inspectDown() if status and block["name"] == "computercraft:wired_modem_full" then @@ -320,12 +327,13 @@ function waitForJob() sender, message, proto = rednet.receive("newjob", 2) if message then job = tonumber(message) - print("Received job "..tostring(job)) + --print("Received job "..tostring(job)) return job else if not retrying then retrying = true - print("No job received. I will keep retrying.") + --print("No job received. I will keep retrying.") + turtlestatus["state"] = "Waiting for job... (retrying)" end end end @@ -340,22 +348,64 @@ function emptyToBarrel() end end +function drawStatus() + print("Turtle ("..tostring(turtlestatus["id"])..")") + print() + print(" \""..turtlestatus["name"].."\"") + print() + print() + if turtlestatus["job"] then + print("Current job: "..tostring(turtlestatus["job"])) + else + print("Current job: ") + end + print() + if turtlestatus["job"] then + print("Recent fuel usage: "..tostring(turtlestatus["fuel"])) + else + print("Recent fuel usage: ") + end + print() + print("Status:") + print(" "..turtlestatus["state"]) + print() +end + while true do + turtlestatus["state"] = "Waiting for job..." + drawStatus() thejob = waitForJob() + turtlestatus["job"] = thejob + turtlestatus["state"] = "Refueling..." + drawStatus() doRefuel() fuel = turtle.getFuelLevel() + turtlestatus["state"] = "Headed to the jobsite..." + drawStatus() goToJob() x, z = ithSpot(thejob) digTo(x,z) + turtlestatus["state"] = "Digging the Shaft..." + drawStatus() digShaft() + turtlestatus["state"] = "Returning to the station..." + drawStatus() goToSpawn(x, z) path = math.floor(math.random() + 0.5) + turtlestatus["state"] = "Unloading Inventory..." + drawStatus() goToBarrel(path) emptyToBarrel() leaveBarrel(path) fuelconsumed = fuel - turtle.getFuelLevel() - print("I consumed "..tostring(fuelconsumed).." fuel") - print("Reporting Duty") + --print("I consumed "..tostring(fuelconsumed).." fuel") + --print("Reporting Duty") + turtlestatus["fuel"] = fuelconsumed + turtlestatus["state"] = "Reporting duty..." + drawStatus() reportDuty(thejob, fuelconsumed) + turtlestatus["job"] = nil + turtlestatus["state"] = "Going back in line..." + drawStatus() enqueueTurtle() end diff --git a/mine/client.lua b/mine/client.lua new file mode 100644 index 0000000..83afcfc --- /dev/null +++ b/mine/client.lua @@ -0,0 +1,588 @@ +args = {...} +x, z, direction = 0, 0, 0 +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 = math.floor(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 + +function digSafe(inspectAction, digAction) + while true do + local status, block = inspectAction() + if status then + if block["name"]:lower():find("turtle") then + -- turtle in front of me. its free space + return true + else + digAction() + -- gravel may take time to fall. + sleep(1) + end + else + -- No block in front of me. good + return true + end + 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 + +function updateState(update) + for k,v in pairs(update) do + turtlestate[k] = v + end + drawStatus() +end + +function enqueueForJob2() + updateState({ state = "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 + turtle.turnLeft() + 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) + return job + else + if not retrying then + retrying = true + --print("No job received. I will keep retrying.") + --turtlestate["state"] = "Waiting for job... (retrying)" + updateState({ state = "Waiting for job... (retrying)" }) + end + end + end +end + +function faceDir(dir) + if ((direction - dir) % 4 == 2) then + turtle.turnRight() + turtle.turnRight() + direction = (direction + 2) % 4 + elseif ((direction - dir) % 4 == 1) then + turtle.turnLeft() + direction = (direction -1) % 4 + elseif ((direction - dir) % 4 == 3) then + turtle.turnRight() + direction = (direction + 1) % 4 + end +end +-- directions: 0, 1, 2, 3 -> x, z, -x, -z +function goToCoordXZ(targetX, targetZ, extraaction) + if targetX > x then + faceDir(0) + while (targetX > x) do + moveSafe(turtle.forward, turtle.inspect, turtle.dig) + x = x + 1 + extraaction() + end + end + if targetX < x then + faceDir(2) + while (targetX < x) do + moveSafe(turtle.forward, turtle.inspect, turtle.dig) + x = x - 1 + extraaction() + end + end + if targetZ > z then + faceDir(1) + while (targetZ > z) do + moveSafe(turtle.forward, turtle.inspect, turtle.dig) + z = z + 1 + extraaction() + end + end + if targetZ < z then + faceDir(3) + while (targetZ < z) do + moveSafe(turtle.forward, turtle.inspect, turtle.dig) + z = z - 1 + extraaction() + end + end +end + +function goToJob(job) + jobX, jobZ = iTo2Dcoords(job) -- this does all the magic + updateState({ state = "Going on the job...", morestate = " Jobsite is at ("..tostring(jobX)..", "..tostring(jobZ)..")" }) + -- move to hole + 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) + moveSafe(turtle.forward, turtle.inspect, noop) + -- reset coords, descend + x, z = 0, 0 + moveSafe(turtle.down, turtle.inspectDown, noop) + moveSafe(turtle.down, turtle.inspectDown, noop) + -- go to job + function extraaction() + repeat sleep(0.6) until (not digSafe(turtle.inspectUp, turtle.digUp())) + end + goToCoord(jobX, jobZ, extraaction) +end + +function turtleAI2() + while true do + local job = enqueueForJob2() + goToJob(job) + -- returnToQueue() + break + end +end + +function extraaction() + repeat sleep(0.6) until (not digSafe(turtle.inspectUp, turtle.digUp())) +end +-- turtleAI() +faceDir(3) +goToCoordXZ(4, 2, extraaction) +goToCoordXZ(0, 0, extraaction) +goToCoordXZ(4, 2, extraaction) 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